summaryrefslogtreecommitdiff
path: root/sys/dev/rnd.c
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>1997-06-10 18:55:31 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>1997-06-10 18:55:31 +0000
commit4aca8c105a9fc533f16592ff4a765615621c1f9e (patch)
tree228c84af2bbe8bf9e0328e8af5e67a98d6c317ff /sys/dev/rnd.c
parent43a0df915d441d36ff0047f2037dc7c168585bdd (diff)
do the job out of the calling function's spl
Diffstat (limited to 'sys/dev/rnd.c')
-rw-r--r--sys/dev/rnd.c193
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: