diff options
author | Michael Shalayeff <mickey@cvs.openbsd.org> | 1997-06-10 18:55:31 +0000 |
---|---|---|
committer | Michael Shalayeff <mickey@cvs.openbsd.org> | 1997-06-10 18:55:31 +0000 |
commit | 4aca8c105a9fc533f16592ff4a765615621c1f9e (patch) | |
tree | 228c84af2bbe8bf9e0328e8af5e67a98d6c317ff /sys/dev/rnd.c | |
parent | 43a0df915d441d36ff0047f2037dc7c168585bdd (diff) |
do the job out of the calling function's spl
Diffstat (limited to 'sys/dev/rnd.c')
-rw-r--r-- | sys/dev/rnd.c | 193 |
1 files changed, 115 insertions, 78 deletions
diff --git a/sys/dev/rnd.c b/sys/dev/rnd.c index 4c80d717740..39b8aece144 100644 --- a/sys/dev/rnd.c +++ b/sys/dev/rnd.c @@ -1,9 +1,9 @@ -/* $OpenBSD: rnd.c,v 1.18 1997/03/30 22:05:11 mickey Exp $ */ +/* $OpenBSD: rnd.c,v 1.19 1997/06/10 18:55:30 mickey Exp $ */ /* * random.c -- A strong random number generator * - * Copyright (c) 1996 Michael Shalayeff. + * Copyright (c) 1996, 1997 Michael Shalayeff. * * Version 1.00, last modified 26-May-96 * @@ -239,6 +239,7 @@ #include <sys/fcntl.h> #include <sys/vnode.h> #include <sys/md5k.h> +#include <sys/queue.h> #include <net/netisr.h> @@ -246,10 +247,11 @@ #include <dev/rndioctl.h> #ifdef DEBUG -int rnd_debug = 0x0000; +int rnd_debug = 0x0100; #define RD_INPUT 0x000f /* input data */ #define RD_OUTPUT 0x00f0 /* output data */ #define RD_WAIT 0x0100 /* sleep/wakeup for good data */ +#define RD_QUEUE 0x0200 /* event queuing */ #endif /* @@ -278,15 +280,15 @@ int rnd_debug = 0x0000; struct random_bucket { u_int add_ptr; u_int entropy_count; - int input_rotate; + u_char input_rotate; u_int32_t *pool; }; /* There is one of these per entropy source */ struct timer_rand_state { u_long last_time; - int last_delta; - int dont_count_entropy:1; + u_int last_delta; + u_char dont_count_entropy:1; }; struct arc4_stream { @@ -295,6 +297,12 @@ struct arc4_stream { u_char s[256]; }; +struct rand_event { + struct timer_rand_state *re_state; + struct timeval re_tv; + u_int re_val; +}; + /* tags for different random sources */ #define ENT_NET 0x100 #define ENT_DISK 0x200 @@ -315,14 +323,14 @@ static int rnd_sleep = 0; #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #endif -static __inline void add_entropy_word __P((struct random_bucket *, - const u_int32_t)); -void add_timer_randomness __P((struct random_bucket *, - struct timer_rand_state *, u_int)); -static __inline int extract_entropy __P((struct random_bucket *, char *, int)); +static __inline void add_entropy_word __P((const u_int32_t)); +static __inline int extract_entropy __P((register char *, int)); void arc4_init __P((struct arc4_stream *, u_char *, int)); -static __inline void arc4_stir (struct arc4_stream *); -static __inline u_char arc4_getbyte __P((struct arc4_stream *)); +static __inline void arc4_stir __P((void)); +static __inline u_char arc4_getbyte __P((register struct arc4_stream *)); +static void __inline queue_randomness + __P((register struct timer_rand_state *, u_int)); +void unqueue_randomness __P((void *)); /* Arcfour random stream generator. This code is derived from section * 17.1 of Applied Cryptography, second edition, which describes a @@ -359,9 +367,9 @@ arc4_init (struct arc4_stream *as, u_char *data, int len) } static __inline u_char -arc4_getbyte (struct arc4_stream *as) +arc4_getbyte (register struct arc4_stream *as) { - u_char si, sj; + register u_char si, sj; as->i = (as->i + 1) & 0xff; si = as->s[as->i]; @@ -372,16 +380,14 @@ arc4_getbyte (struct arc4_stream *as) return (as->s[(si + sj) & 0xff]); } -static inline void +static __inline void arc4maybeinit (void) { - if (arc4random_uninitialized) { - if (arc4random_uninitialized > 1 - || random_state.entropy_count >= 128) { - arc4random_uninitialized--; - arc4_stir (&arc4random_state); - } - } + if (arc4random_uninitialized && (arc4random_uninitialized > 1 || + random_state.entropy_count >= 128)) { + arc4random_uninitialized--; + arc4_stir (); + } } u_int32_t @@ -446,34 +452,34 @@ randomclose(dev, flag, mode, p) * get affected. --- TYT, 10/11/95 */ static __inline void -add_entropy_word(r, input) - struct random_bucket *r; +add_entropy_word(input) const u_int32_t input; { - u_int i; - u_int32_t w; + register u_int i; + register u_int32_t w; - w = (input << r->input_rotate) | (input >> (32 - r->input_rotate)); - i = r->add_ptr = (r->add_ptr - 1) & (POOLWORDS-1); + w = (input << random_state.input_rotate) | + (input >> (32 - random_state.input_rotate)); + i = random_state.add_ptr = (random_state.add_ptr - 1) & (POOLWORDS-1); if (i) - r->input_rotate = (r->input_rotate + 7) & 31; + random_state.input_rotate = (random_state.input_rotate + 7) & 31; else /* * At the beginning of the pool, add an extra 7 bits * rotation, so that successive passes spread the * input bits across the pool evenly. */ - r->input_rotate = (r->input_rotate + 14) & 31; + random_state.input_rotate = (random_state.input_rotate + 14) & 31; /* XOR in the various taps */ - w ^= r->pool[(i+TAP1)&(POOLWORDS-1)]; - w ^= r->pool[(i+TAP2)&(POOLWORDS-1)]; - w ^= r->pool[(i+TAP3)&(POOLWORDS-1)]; - w ^= r->pool[(i+TAP4)&(POOLWORDS-1)]; - w ^= r->pool[(i+TAP5)&(POOLWORDS-1)]; - w ^= r->pool[i]; + w ^= random_state.pool[(i+TAP1)&(POOLWORDS-1)]; + w ^= random_state.pool[(i+TAP2)&(POOLWORDS-1)]; + w ^= random_state.pool[(i+TAP3)&(POOLWORDS-1)]; + w ^= random_state.pool[(i+TAP4)&(POOLWORDS-1)]; + w ^= random_state.pool[(i+TAP5)&(POOLWORDS-1)]; + w ^= random_state.pool[i]; /* Rotate w left 1 bit (stolen from SHA) and store */ - r->pool[i] = (w << 1) | (w >> 31); + random_state.pool[i] = (w << 1) | (w >> 31); } /* @@ -489,21 +495,23 @@ add_entropy_word(r, input) * */ void -add_timer_randomness(r, state, num) - struct random_bucket *r; - struct timer_rand_state *state; - u_int num; +unqueue_randomness(ptr) + void *ptr; { - int delta, delta2; + struct rand_event *re = (struct rand_event *)ptr; + struct timer_rand_state *state = re->re_state; + u_long time = re->re_tv.tv_usec ^ re->re_tv.tv_sec; + u_int delta, delta2; u_int nbits; - u_long time; - struct timeval tv; - microtime(&tv); - time = tv.tv_usec ^ tv.tv_sec; + add_entropy_word((u_int32_t)re->re_val); + add_entropy_word((u_int32_t)time); - add_entropy_word(r, (u_int32_t)num); - add_entropy_word(r, time); +#ifdef DEBUG + if (rnd_debug & RD_QUEUE) + printf("rnd: dequeuing %p\n", re); +#endif + FREE(re, M_TEMP); /* * Calculate number of bits of randomness we probably @@ -523,36 +531,66 @@ add_timer_randomness(r, state, num) for (nbits = 0; delta; nbits++) delta >>= 1; - r->entropy_count += nbits; - + random_state.entropy_count += nbits; + /* Prevent overflow */ - if (r->entropy_count > POOLBITS) - r->entropy_count = POOLBITS; + if (random_state.entropy_count > POOLBITS) + random_state.entropy_count = POOLBITS; } - if (r->entropy_count > 8 && rnd_sleep != 0) { + if (random_state.entropy_count > 8 && rnd_sleep != 0) { rnd_sleep--; #ifdef DEBUG if (rnd_debug & RD_WAIT) printf("rnd: wakeup[%d]{%u}\n", - rnd_sleep, r->entropy_count); + rnd_sleep, random_state.entropy_count); #endif wakeup(&rnd_sleep); } } +/* + * Queue event for future processing by unqueue_randomness + * + */ +static __inline void +queue_randomness(state, val) + register struct timer_rand_state *state; + u_int val; +{ + register struct rand_event *re; + MALLOC(re, struct rand_event *, sizeof(*re), M_TEMP, M_WAITOK); + + microtime(&re->re_tv); + re->re_state = state; + re->re_val = val; +#ifdef DEBUG + if (rnd_debug & RD_QUEUE) + printf("rnd: queuing %p\n", re); +#endif + timeout(unqueue_randomness, re, 1); +} + void add_mouse_randomness(mouse_data) u_int32_t mouse_data; { - add_timer_randomness(&random_state, &mouse_timer_state, mouse_data); + /* Has randomattach run yet? */ + if (random_state.pool == NULL) + return; + + queue_randomness(&mouse_timer_state, mouse_data); } void add_net_randomness(isr) int isr; { - add_timer_randomness(&random_state, &net_timer_state, ENT_NET + isr); + /* Has randomattach run yet? */ + if (random_state.pool == NULL) + return; + + queue_randomness(&net_timer_state, ENT_NET + isr); } void @@ -572,7 +610,7 @@ add_disk_randomness(n) c ^= n & 0xff; n >>= 8; c ^= n & 0xff; - add_timer_randomness(&random_state, &disk_timer_state, ENT_DISK + c); + queue_randomness(&disk_timer_state, ENT_DISK + c); } void @@ -583,7 +621,7 @@ add_tty_randomness(c) if (random_state.pool == NULL) return; - add_timer_randomness(&random_state, &tty_timer_state, ENT_TTY + c); + queue_randomness(&tty_timer_state, ENT_TTY + c); } #if POOLWORDS % 16 @@ -596,42 +634,41 @@ add_tty_randomness(c) * number of bytes that are actually obtained. */ static __inline int -extract_entropy(r, buf, nbytes) - struct random_bucket *r; - char *buf; +extract_entropy(buf, nbytes) + register char *buf; int nbytes; { int ret, i; MD5_CTX tmp; - add_timer_randomness(r, &extract_timer_state, nbytes); + queue_randomness(&extract_timer_state, nbytes); /* Redundant, but just in case... */ - if (r->entropy_count > POOLBITS) - r->entropy_count = POOLBITS; + if (random_state.entropy_count > POOLBITS) + random_state.entropy_count = POOLBITS; ret = nbytes; - if (r->entropy_count / 8 >= nbytes) - r->entropy_count -= nbytes*8; + if (random_state.entropy_count / 8 >= nbytes) + random_state.entropy_count -= nbytes*8; else - r->entropy_count = 0; + random_state.entropy_count = 0; while (nbytes) { /* Hash the pool to get the output */ MD5Init(&tmp); for (i = 0; i < POOLWORDS; i += 16) - MD5Update(&tmp, (u_int8_t*)r->pool+i, 16); + MD5Update(&tmp, (u_int8_t*)random_state.pool+i, 16); /* Modify pool so next hash will produce different results */ for (i = 0; i < sizeof(tmp.buffer)/sizeof(tmp.buffer[0]); i++) - add_entropy_word(r, tmp.buffer[i]); + add_entropy_word(tmp.buffer[i]); /* * Run the MD5 Transform one more time, since we want * to add at least minimal obscuring of the inputs to * add_entropy_word(). --- TYT */ - MD5Update(&tmp, (u_int8_t*)r->pool, 16); + MD5Update(&tmp, (u_int8_t*)random_state.pool, 16); /* * In case the hash function has some recognizable @@ -650,7 +687,7 @@ extract_entropy(r, buf, nbytes) bcopy((caddr_t)&tmp.buffer, buf, i); nbytes -= i; buf += i; - add_timer_randomness(r, &extract_timer_state, nbytes); + queue_randomness(&extract_timer_state, nbytes); } /* Wipe data from memory */ @@ -669,7 +706,7 @@ get_random_bytes(buf, nbytes) void *buf; size_t nbytes; { - extract_entropy(&random_state, (char *) buf, nbytes); + extract_entropy((char *) buf, nbytes); } int @@ -720,7 +757,7 @@ randomread(dev, uio, ioflag) printf("rnd: %u possible output\n", n); #endif case RND_URND: - n = extract_entropy(&random_state, (char *)buf, n); + n = extract_entropy((char *)buf, n); #ifdef DEBUG if (rnd_debug & RD_OUTPUT) printf("rnd: %u bytes for output\n", n); @@ -764,7 +801,7 @@ randomselect(dev, rw, p) } static __inline void -arc4_stir (struct arc4_stream *as) +arc4_stir () { u_char buf[256]; @@ -799,12 +836,12 @@ randomwrite(dev, uio, flags) ((u_char *) buf)[n++] = 0; n >>= 2; for (i = 0; i < n; i++) - add_entropy_word(&random_state, buf[i]); + add_entropy_word(buf[i]); } } if (minor(dev) == RND_ARND && !ret) - arc4_stir (&arc4random_state); + arc4_stir (); return ret; } @@ -845,7 +882,7 @@ randomioctl(dev, cmd, data, flag, p) return EPERM; if (random_state.entropy_count < 64) return EAGAIN; - arc4_stir (&arc4random_state); + arc4_stir (); ret = 0; break; default: |