*/
#include <sys/types.h>
+#include <sys/systm.h>
#include <sys/random.h>
#include <sys/libkern.h>
#include <sys/time.h>
+#include <vm/vm_extern.h>
+
#define ARC4_MAXRUNS 16384
#define ARC4_RESEED_SECONDS 300
#define ARC4_KEYBYTES 32 /* 256 bit key */
-static uint8_t arc4_i, arc4_j;
-static int arc4_initialized = 0;
-static int arc4_numruns = 0;
-static uint8_t arc4_sbox[256];
-static struct timeval arc4_tv_nextreseed;
+struct arc4_data {
+ uint8_t arc4_i;
+ uint8_t arc4_j;
+ int arc4_numruns;
+ time_t arc4_nextreseed;
+ uint8_t arc4_sbox[256];
+};
+
+static struct arc4_data *arc4_data_pcpu[MAXCPU];
-static uint8_t arc4_randbyte(void);
+static uint8_t arc4_randbyte(struct arc4_data *);
static __inline void
arc4_swap(uint8_t *a, uint8_t *b)
* Stir our S-box.
*/
static void
-arc4_randomstir (void)
+arc4_randomstir(struct arc4_data *d)
{
uint8_t key[256];
int r, n;
*/
r = read_random_unlimited(key, ARC4_KEYBYTES);
/* If r == 0 || -1, just use what was on the stack. */
- if (r > 0)
- {
+ if (r > 0) {
for (n = r; n < sizeof(key); n++)
key[n] = key[n % r];
}
for (n = 0; n < 256; n++) {
- arc4_j = (arc4_j + arc4_sbox[n] + key[n]) % 256;
- arc4_swap(&arc4_sbox[n], &arc4_sbox[arc4_j]);
+ d->arc4_j = (d->arc4_j + d->arc4_sbox[n] + key[n]) % 256;
+ arc4_swap(&d->arc4_sbox[n], &d->arc4_sbox[d->arc4_j]);
}
/*
* Discard early keystream, as per recommendations in:
* "(Not So) Random Shuffles of RC4" by Ilya Mironov.
*/
- for (n = 0; n < 768*4; n++)
- arc4_randbyte();
+ for (n = 0; n < 768 * 4; n++)
+ arc4_randbyte(d);
/* Reset for next reseed cycle. */
- getmicrotime(&arc4_tv_nextreseed);
- arc4_tv_nextreseed.tv_sec += ARC4_RESEED_SECONDS;
- arc4_numruns = 0;
-}
-
-/*
- * Initialize our S-box to its beginning defaults.
- */
-static void
-arc4_init(void)
-{
- int n;
-
- arc4_i = arc4_j = 0;
- for (n = 0; n < 256; n++)
- arc4_sbox[n] = (uint8_t)n;
-
- arc4_randomstir();
- arc4_initialized = 1;
-
- /*
- * Discard early keystream, as per recommendations in:
- * "(Not So) Random Shuffles of RC4" by Ilya Mironov.
- */
- for (n = 0; n < 768 * 4; n++)
- arc4_randbyte();
+ d->arc4_nextreseed = time_uptime + ARC4_RESEED_SECONDS;
+ d->arc4_numruns = 0;
}
/*
* Generate a random byte.
*/
static uint8_t
-arc4_randbyte(void)
+arc4_randbyte(struct arc4_data *d)
{
uint8_t arc4_t;
- arc4_i = (arc4_i + 1) % 256;
- arc4_j = (arc4_j + arc4_sbox[arc4_i]) % 256;
+ d->arc4_i = (d->arc4_i + 1) % 256;
+ d->arc4_j = (d->arc4_j + d->arc4_sbox[d->arc4_i]) % 256;
- arc4_swap(&arc4_sbox[arc4_i], &arc4_sbox[arc4_j]);
+ arc4_swap(&d->arc4_sbox[d->arc4_i], &d->arc4_sbox[d->arc4_j]);
- arc4_t = (arc4_sbox[arc4_i] + arc4_sbox[arc4_j]) % 256;
- return arc4_sbox[arc4_t];
+ arc4_t = (d->arc4_sbox[d->arc4_i] + d->arc4_sbox[d->arc4_j]) % 256;
+ return d->arc4_sbox[arc4_t];
}
uint32_t
karc4random(void)
{
+ struct arc4_data *d = arc4_data_pcpu[mycpuid];
uint32_t ret;
- struct timeval tv_now;
- /* Initialize array if needed. */
- if (!arc4_initialized)
- arc4_init();
+#if 0
+ /* No one call this function in ISR/ithread. */
+ crit_enter();
+#endif
- getmicrotime(&tv_now);
- if ((++arc4_numruns > ARC4_MAXRUNS) ||
- (tv_now.tv_sec > arc4_tv_nextreseed.tv_sec))
- {
- arc4_randomstir();
- }
+ if (++(d->arc4_numruns) > ARC4_MAXRUNS ||
+ time_uptime > d->arc4_nextreseed)
+ arc4_randomstir(d);
- ret = arc4_randbyte();
- ret |= arc4_randbyte() << 8;
- ret |= arc4_randbyte() << 16;
- ret |= arc4_randbyte() << 24;
+ ret = arc4_randbyte(d);
+ ret |= arc4_randbyte(d) << 8;
+ ret |= arc4_randbyte(d) << 16;
+ ret |= arc4_randbyte(d) << 24;
+
+#if 0
+ crit_exit();
+#endif
return ret;
}
void
karc4rand(void *ptr, size_t len)
{
- uint8_t *p;
- struct timeval tv_now;
+ struct arc4_data *d = arc4_data_pcpu[mycpuid];
+ uint8_t *p = ptr;
- p = ptr;
+#if 0
+ /* No one call this function in ISR/ithread. */
+ crit_enter();
+#endif
- /* Initialize array if needed. */
- if (!arc4_initialized)
- arc4_init();
-
- getmicrotime(&tv_now);
- if ((++arc4_numruns > ARC4_MAXRUNS) ||
- (tv_now.tv_sec > arc4_tv_nextreseed.tv_sec))
- {
- arc4_randomstir();
- }
+ if (++(d->arc4_numruns) > ARC4_MAXRUNS ||
+ time_uptime > d->arc4_nextreseed)
+ arc4_randomstir(d);
while (len--)
- *p++ = arc4_randbyte();
+ *p++ = arc4_randbyte(d);
+
+#if 0
+ crit_exit();
+#endif
+}
+
+/*
+ * Initialize our S-box to its beginning defaults.
+ */
+void
+arc4_init_pcpu(int cpuid)
+{
+ struct arc4_data *d;
+ int n;
+
+ KASSERT(arc4_data_pcpu[cpuid] == NULL,
+ ("arc4 was initialized on cpu%d", cpuid));
+
+ d = (void *)kmem_alloc3(&kernel_map, sizeof(*d), VM_SUBSYS_GD,
+ KM_CPU(cpuid));
+ memset(d, 0, sizeof(*d));
+
+ for (n = 0; n < 256; n++)
+ d->arc4_sbox[n] = (uint8_t)n;
+
+ arc4_randomstir(d);
+
+ /*
+ * Discard early keystream, as per recommendations in:
+ * "(Not So) Random Shuffles of RC4" by Ilya Mironov.
+ */
+ for (n = 0; n < 768 * 4; n++)
+ arc4_randbyte(d);
+
+ arc4_data_pcpu[cpuid] = d;
}