diff options
author | markm <markm@FreeBSD.org> | 2000-10-14 10:59:56 +0000 |
---|---|---|
committer | markm <markm@FreeBSD.org> | 2000-10-14 10:59:56 +0000 |
commit | a8d2363750f62cf99c9e91b3edb208a5862543e9 (patch) | |
tree | 9b8a3e92ad99aac2e9f68f5d325968f510b05f7e /sys/dev/random/yarrow.c | |
parent | 4dcc092204f26668eab762bae3b04da3bc9007b5 (diff) | |
download | FreeBSD-src-a8d2363750f62cf99c9e91b3edb208a5862543e9.zip FreeBSD-src-a8d2363750f62cf99c9e91b3edb208a5862543e9.tar.gz |
After some complaints about the dir names, the random device is
now in dirs called sys/*/random/ instead of sys/*/randomdev/*.
Introduce blocking, but only at startup; the random device will
block until the first reseed happens to prevent clients from
using untrustworthy output.
Provide a read_random() call for the rest of the kernel so that
the entropy device does not need to be present. This means that
things like IPX no longer need to have "device random" hardcoded
into thir kernel config. The downside is that read_random() will
provide very poor output until the entropy device is loaded and
reseeded. It is recommended that developers do NOT use the
read_random() call; instead, they should use arc4random() which
internally uses read_random().
Clean up the mutex and locking code a bit; this makes it possible
to unload the module again.
Diffstat (limited to 'sys/dev/random/yarrow.c')
-rw-r--r-- | sys/dev/random/yarrow.c | 65 |
1 files changed, 34 insertions, 31 deletions
diff --git a/sys/dev/random/yarrow.c b/sys/dev/random/yarrow.c index 1360d8e..fe4d160 100644 --- a/sys/dev/random/yarrow.c +++ b/sys/dev/random/yarrow.c @@ -38,6 +38,7 @@ #include <sys/libkern.h> #include <sys/malloc.h> #include <sys/proc.h> +#include <sys/select.h> #include <sys/random.h> #include <sys/time.h> #include <sys/types.h> @@ -45,8 +46,8 @@ #include <machine/mutex.h> #include <crypto/blowfish/blowfish.h> -#include <dev/randomdev/hash.h> -#include <dev/randomdev/yarrow.h> +#include <dev/random/hash.h> +#include <dev/random/yarrow.h> /* #define DEBUG */ /* #define DEBUG1 */ /* Very noisy - prints plenty harvesting stats */ @@ -65,11 +66,11 @@ TAILQ_HEAD(harvestqueue, harvest) harvestqueue, initqueue = TAILQ_HEAD_INITIALIZER(harvestqueue); /* These are used to queue harvested packets of entropy. The entropy - * buffer size of 16 is pretty arbitrary. + * buffer size is pretty arbitrary. */ struct harvest { struct timespec time; /* nanotime for clock jitter */ - u_char entropy[16]; /* the harvested entropy */ + u_char entropy[HARVESTSIZE]; /* the harvested entropy */ u_int size, bits, frac; /* stats about the entropy */ enum esource source; /* stats about the entropy */ u_int pool; /* which pool this goes into */ @@ -79,19 +80,18 @@ struct harvest { /* The reseed thread mutex */ static struct mtx random_reseed_mtx; -/* The entropy harvest mutex */ +/* The entropy harvest mutex, as well as the mutex associated + * with the msleep() call during deinit + */ static struct mtx random_harvest_mtx; -/* <0 until the kthread starts, 0 for running */ -static int random_kthread_status = -1; - /* <0 to end the kthread, 0 to let it run */ static int random_kthread_control = 0; static struct proc *random_kthread_proc; static void -random_kthread(void *status) +random_kthread(void *arg /* NOTUSED */) { int pl, src, overthreshhold[2]; struct harvest *event; @@ -101,10 +101,8 @@ random_kthread(void *status) #endif #ifdef DEBUG - printf("At %s, line %d: mtx_owned(&Giant) == %d\n", __FILE__, __LINE__, mtx_owned(&Giant)); - printf("At %s, line %d: mtx_owned(&sched_lock) == %d\n", __FILE__, __LINE__, mtx_owned(&sched_lock)); + printf("At %s, line %d: mtx_owned(&Giant) == %d, mtx_owned(&sched_lock) == %d\n", __FILE__, __LINE__, mtx_owned(&Giant), mtx_owned(&sched_lock)); #endif - random_set_wakeup((int *)status, 0); for (pl = 0; pl < 2; pl++) yarrow_hash_init(&random_state.pool[pl].hash, NULL, 0); @@ -148,9 +146,6 @@ random_kthread(void *status) source->frac %= 1024; free(event, M_TEMP); - /* XXX abuse tsleep() to get at mi_switch() */ - /* tsleep(&harvestqueue, PUSER, "rndprc", 1); */ - } #ifdef DEBUG1 printf("Harvested %d events\n", queuecount); @@ -177,7 +172,7 @@ random_kthread(void *status) } /* Is the thread scheduled for a shutdown? */ - if (random_kthread_control < 0) { + if (random_kthread_control != 0) { if (!TAILQ_EMPTY(&harvestqueue)) { #ifdef DEBUG printf("Random cleaning extraneous events\n"); @@ -192,7 +187,8 @@ random_kthread(void *status) #ifdef DEBUG printf("Random kthread setting terminate\n"); #endif - random_set_wakeup_exit((int *)status, -1, 0); + random_set_wakeup_exit(&random_kthread_control); + /* NOTREACHED */ break; } @@ -223,13 +219,13 @@ random_init(void) mtx_init(&random_harvest_mtx, "random harvest", MTX_DEF); /* Start the hash/reseed thread */ - error = kthread_create(random_kthread, &random_kthread_status, + error = kthread_create(random_kthread, NULL, &random_kthread_proc, RFHIGHPID, "random"); if (error != 0) return error; /* Register the randomness harvesting routine */ - random_init_harvester(random_harvest_internal); + random_init_harvester(random_harvest_internal, read_random_real); #ifdef DEBUG printf("Random initalise finish\n"); @@ -253,9 +249,11 @@ random_deinit(void) #endif /* Command the hash/reseed thread to end and wait for it to finish */ + mtx_enter(&random_harvest_mtx, MTX_DEF); random_kthread_control = -1; - while (random_kthread_status != -1) - tsleep(&random_kthread_status, PUSER, "rndend", hz); + msleep((void *)&random_kthread_control, &random_harvest_mtx, PUSER, + "rndend", 0); + mtx_exit(&random_harvest_mtx, MTX_DEF); #ifdef DEBUG printf("Random deinitalise removing mutexes\n"); @@ -364,10 +362,16 @@ reseed(int fastslow) printf("Reseed finish\n"); #endif + if (!random_state.seeded) { + random_state.seeded = 1; + selwakeup(&random_state.rsel); + wakeup(&random_state); + } + } u_int -read_random(void *buf, u_int count) +read_random_real(void *buf, u_int count) { static u_int64_t genval; static int cur = 0; @@ -430,19 +434,19 @@ write_random(void *buf, u_int count) u_int i; struct timespec timebuf; - /* arbitrarily break the input up into 8-byte chunks */ - for (i = 0; i < count; i += 8) { + /* arbitrarily break the input up into HARVESTSIZE chunks */ + for (i = 0; i < count; i += HARVESTSIZE) { nanotime(&timebuf); - random_harvest_internal(&timebuf, (char *)buf + i, 8, 0, 0, + random_harvest_internal(&timebuf, (char *)buf + i, HARVESTSIZE, 0, 0, RANDOM_WRITE); } /* Maybe the loop iterated at least once */ if (i > count) - i -= 8; + i -= HARVESTSIZE; - /* Get the last bytes even if the input length is not a multiple of 8 */ - count %= 8; + /* Get the last bytes even if the input length is not a multiple of HARVESTSIZE */ + count %= HARVESTSIZE; if (count) { nanotime(&timebuf); random_harvest_internal(&timebuf, (char *)buf + i, count, 0, 0, @@ -486,7 +490,6 @@ random_harvest_internal(struct timespec *timep, void *entropy, u_int count, u_int bits, u_int frac, enum esource origin) { struct harvest *event; - u_int64_t entropy_buf; #if 0 #ifdef DEBUG @@ -501,8 +504,8 @@ random_harvest_internal(struct timespec *timep, void *entropy, u_int count, event->time = *timep; /* the harvested entropy */ - count = count > sizeof(entropy_buf) - ? sizeof(entropy_buf) + count = count > sizeof(event->entropy) + ? sizeof(event->entropy) : count; memcpy(event->entropy, entropy, count); |