diff options
Diffstat (limited to 'sys/dev/rnd.c')
-rw-r--r-- | sys/dev/rnd.c | 95 |
1 files changed, 59 insertions, 36 deletions
diff --git a/sys/dev/rnd.c b/sys/dev/rnd.c index 7ed32c52708..40999f7cb82 100644 --- a/sys/dev/rnd.c +++ b/sys/dev/rnd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rnd.c,v 1.33 1999/09/28 01:24:46 deraadt Exp $ */ +/* $OpenBSD: rnd.c,v 1.34 2000/03/19 17:38:03 mickey Exp $ */ /* * random.c -- A strong random number generator @@ -225,28 +225,23 @@ * Eastlake, Steve Crocker, and Jeff Schiller. */ +#undef RNDEBUG + #include <sys/param.h> -#include <sys/types.h> #include <sys/systm.h> -#include <sys/kernel.h> #include <sys/conf.h> -#include <sys/device.h> #include <sys/disk.h> #include <sys/ioctl.h> #include <sys/malloc.h> -#include <sys/proc.h> -#include <sys/user.h> #include <sys/fcntl.h> #include <sys/vnode.h> #include <sys/md5k.h> #include <sys/sysctl.h> -#include <net/netisr.h> - #include <dev/rndvar.h> #include <dev/rndioctl.h> -#ifdef DEBUG +#ifdef RNDEBUG int rnd_debug = 0x0000; #define RD_INPUT 0x000f /* input data */ #define RD_OUTPUT 0x00f0 /* output data */ @@ -278,7 +273,7 @@ int rnd_debug = 0x0000; /* p60/256kL2 reported to have some drops w/ these numbers */ #define QEVLEN 40 #define QEVSLOW 32 /* yet another 0.75 for 60-minutes hour /-; */ -#define QEVSBITS 4 +#define QEVSBITS 6 /* There is actually only one of these, globally. */ struct random_bucket { @@ -299,7 +294,7 @@ struct arc4_stream { u_int8_t i; u_int8_t j; u_int8_t s[256]; - int cnt; + u_int cnt; }; struct rand_event { @@ -336,7 +331,7 @@ static struct rand_event *event_free; static __inline void add_entropy_word __P((const u_int32_t)); static void enqueue_randomness __P((register struct timer_rand_state*, u_int)); void dequeue_randomness __P((void *)); -static __inline int extract_entropy __P((register u_int8_t *, int)); +static __inline void extract_entropy __P((register u_int8_t *, int)); void arc4_init __P((u_int8_t *, int)); static __inline void arc4_stir __P((void)); static __inline u_int8_t arc4_getbyte __P((void)); @@ -405,8 +400,15 @@ arc4maybeinit (void) } } +int +arc4random_8(void) +{ + arc4maybeinit(); + return arc4_getbyte(); +} + u_int32_t -arc4random (void) +arc4random(void) { arc4maybeinit (); return ((arc4_getbyte () << 24) | (arc4_getbyte () << 16) @@ -422,6 +424,7 @@ arc4_stir (void) get_random_bytes (buf + sizeof (struct timeval), sizeof (buf) - sizeof (struct timeval)); arc4_init (buf, sizeof (buf)); + rndstats.arc4_stirs++; } void @@ -432,7 +435,7 @@ randomattach(void) struct rand_event *rep; if (rnd_attached) { -#ifdef DEBUG +#ifdef RNDEBUG printf("random: second attach\n"); #endif return; @@ -539,16 +542,17 @@ enqueue_randomness(state, val) register struct timer_rand_state *state; u_int val; { - u_int nbits = 0; struct timeval tv; register struct rand_event *rep; int s; - u_int time; + u_int time, nbits; rndstats.rnd_enqs++; microtime(&tv); time = tv.tv_usec ^ tv.tv_sec; + nbits = 0; + /* * Calculate number of bits of randomness we probably * added. We take into account the first and second order @@ -561,16 +565,39 @@ enqueue_randomness(state, val) if (delta < 0) delta = -delta; if (delta2 < 0) delta2 = -delta2; - delta = MIN(delta, delta2) >> 1; - for (nbits = 0; delta; nbits++) + delta2 = delta = MIN(delta, delta2) >> 1; + + if (delta & 0xffff0000) { + nbits = 16; + delta >>= 16; + } + if (delta & 0xff00) { + nbits += 8; + delta >>= 8; + } + if (delta & 0xf0) { + nbits += 4; + delta >>= 4; + } + if (delta & 0xc) { + nbits += 2; + delta >>= 2; + } + if (delta & 2) { + nbits += 1; delta >>= 1; + } + if (delta & 1) + nbits++; - if (rndstats.rnd_queued > QEVSLOW && nbits < QEVSBITS) { + rndstats.rnd_ed[nbits]++; + + if (rndstats.rnd_queued > QEVSLOW && nbits > QEVSBITS) { rndstats.rnd_drople++; return; } state->last_time = time; - state->last_delta = delta; + state->last_delta = delta2; } s = splhigh(); @@ -594,7 +621,7 @@ enqueue_randomness(state, val) rndstats.rnd_queued++; if (rep == NULL) - timeout(dequeue_randomness, (void *)0xdeadd00d, 1); + timeout(dequeue_randomness, NULL, 1); } @@ -640,7 +667,7 @@ dequeue_randomness(v) rndstats.rnd_queued--; if (random_state.entropy_count > 8 && rndstats.rnd_asleep != 0) { -#ifdef DEBUG +#ifdef RNDEBUG if (rnd_debug & RD_WAIT) printf("rnd: wakeup[%d]{%u}\n", rndstats.rnd_asleep, @@ -719,12 +746,12 @@ add_tty_randomness(c) * bits of entropy are left in the pool, but it does not restrict the * number of bytes that are actually obtained. */ -static __inline int +static __inline void extract_entropy(buf, nbytes) register u_int8_t *buf; int nbytes; { - int ret, i; + int i; MD5_CTX tmp; enqueue_randomness(&extract_timer_state, nbytes); @@ -733,7 +760,6 @@ extract_entropy(buf, nbytes) if (random_state.entropy_count > POOLBITS) random_state.entropy_count = POOLBITS; - ret = nbytes; if (random_state.entropy_count / 8 >= nbytes) random_state.entropy_count -= nbytes*8; else @@ -778,8 +804,6 @@ extract_entropy(buf, nbytes) /* Wipe data from memory */ bzero(&tmp, sizeof(tmp)); - - return ret; } /* @@ -823,7 +847,7 @@ randomread(dev, uio, ioflag) ret = EWOULDBLOCK; break; } -#ifdef DEBUG +#ifdef RNDEBUG if (rnd_debug & RD_WAIT) printf("rnd: sleep[%d]\n", rndstats.rnd_asleep); @@ -832,7 +856,7 @@ randomread(dev, uio, ioflag) rndstats.rnd_waits++; ret = tsleep(&rndstats.rnd_asleep, PWAIT | PCATCH, "rndrd", 0); -#ifdef DEBUG +#ifdef RNDEBUG if (rnd_debug & RD_WAIT) printf("rnd: awakened(%d)\n", ret); #endif @@ -841,13 +865,13 @@ randomread(dev, uio, ioflag) } n = min(n, random_state.entropy_count / 8); rndstats.rnd_reads++; -#ifdef DEBUG +#ifdef RNDEBUG if (rnd_debug & RD_OUTPUT) printf("rnd: %u possible output\n", n); #endif case RND_URND: - n = extract_entropy((char *)buf, n); -#ifdef DEBUG + get_random_bytes((char *)buf, n); +#ifdef RNDEBUG if (rnd_debug & RD_OUTPUT) printf("rnd: %u bytes for output\n", n); #endif @@ -861,9 +885,8 @@ randomread(dev, uio, ioflag) { u_int8_t *cp = (u_int8_t *) buf; u_int8_t *end = cp + n; - arc4maybeinit (); while (cp < end) - *cp++ = arc4_getbyte (); + *cp++ = arc4random_8(); break; } } @@ -919,7 +942,7 @@ randomwrite(dev, uio, flags) } if (minor(dev) == RND_ARND && !ret) - arc4_stir (); + arc4random_uninitialized = 2; return ret; } @@ -960,7 +983,7 @@ randomioctl(dev, cmd, data, flag, p) return EPERM; if (random_state.entropy_count < 64) return EAGAIN; - arc4_stir (); + arc4random_uninitialized = 2; ret = 0; break; default: |