From 12a237a692a81328f3f14927af016b53de12eabd Mon Sep 17 00:00:00 2001 From: markm Date: Tue, 25 Jul 2000 21:18:47 +0000 Subject: o Fix a horrible bug where small reads (< 8 bytes) would return the wrong bytes. o Improve the public interface; use void* instead of char* or u_int64_t to pass arbitrary data around. Submitted by: kris ("horrible bug") --- sys/dev/random/harvest.c | 8 ++++---- sys/dev/random/randomdev.c | 14 ++++++++++++-- sys/dev/random/yarrow.c | 43 ++++++++++++++++++++++++++++++------------- sys/dev/random/yarrow.h | 4 ++-- 4 files changed, 48 insertions(+), 21 deletions(-) (limited to 'sys/dev/random') diff --git a/sys/dev/random/harvest.c b/sys/dev/random/harvest.c index 3e16059..92de318 100644 --- a/sys/dev/random/harvest.c +++ b/sys/dev/random/harvest.c @@ -42,11 +42,11 @@ /* hold the address of the routine which is actually called if * the ramdomdev is loaded */ -static void (*reap)(struct timespec *, u_int64_t, u_int, u_int, u_int) = NULL; +static void (*reap)(struct timespec *, void *, u_int, u_int, u_int, u_int) = NULL; /* Initialise the harvester at load time */ void -random_init_harvester(void (*reaper)(struct timespec *, u_int64_t, u_int, u_int, u_int)) +random_init_harvester(void (*reaper)(struct timespec *, void *, u_int, u_int, u_int, u_int)) { reap = reaper; } @@ -64,12 +64,12 @@ random_deinit_harvester(void) * the entropy device. */ void -random_harvest(u_int64_t entropy, u_int bits, u_int frac, u_int origin) +random_harvest(void *entropy, u_int count, u_int bits, u_int frac, u_int origin) { struct timespec timebuf; if (reap) { nanotime(&timebuf); - (*reap)(&timebuf, entropy, bits, frac, origin); + (*reap)(&timebuf, entropy, count, bits, frac, origin); } } diff --git a/sys/dev/random/randomdev.c b/sys/dev/random/randomdev.c index c84f4bd..645cfb0 100644 --- a/sys/dev/random/randomdev.c +++ b/sys/dev/random/randomdev.c @@ -46,6 +46,7 @@ #include +static d_open_t random_open; static d_read_t random_read; static d_write_t random_write; @@ -54,7 +55,7 @@ static d_write_t random_write; #define URANDOM_MINOR 4 static struct cdevsw random_cdevsw = { - /* open */ (d_open_t *)nullop, + /* open */ random_open, /* close */ (d_close_t *)nullop, /* read */ random_read, /* write */ random_write, @@ -83,11 +84,20 @@ SYSCTL_INT(_kern_random_yarrow, OID_AUTO, bins, CTLFLAG_RW, SYSCTL_INT(_kern_random_yarrow, OID_AUTO, fastthresh, CTLFLAG_RW, &random_state.pool[0].thresh, 100, "Fast pool reseed threshhold"); SYSCTL_INT(_kern_random_yarrow, OID_AUTO, slowthresh, CTLFLAG_RW, - &random_state.pool[1].thresh, 100, "Slow pool reseed threshhold"); + &random_state.pool[1].thresh, 160, "Slow pool reseed threshhold"); SYSCTL_INT(_kern_random_yarrow, OID_AUTO, slowoverthresh, CTLFLAG_RW, &random_state.slowoverthresh, 2, "Slow pool over-threshhold reseed"); static int +random_open(dev_t dev, int flags, int fmt, struct proc *p) +{ + if ((flags & FWRITE) && (securelevel > 0 || suser(p))) + return EPERM; + else + return 0; +} + +static int random_read(dev_t dev, struct uio *uio, int flag) { u_int c, ret; diff --git a/sys/dev/random/yarrow.c b/sys/dev/random/yarrow.c index bc85575..9611436 100644 --- a/sys/dev/random/yarrow.c +++ b/sys/dev/random/yarrow.c @@ -48,7 +48,7 @@ static void generator_gate(void); static void reseed(int); -static void random_harvest_internal(struct timespec *, u_int64_t, u_int, u_int, enum esource); +static void random_harvest_internal(struct timespec *, void *, u_int, u_int, u_int, enum esource); /* Structure holding the entropy state */ struct random_state random_state; @@ -216,13 +216,13 @@ reseed(int fastslow) } u_int -read_random(char *buf, u_int count) +read_random(void *buf, u_int count) { + static u_int64_t genval; static int cur = 0; static int gate = 1; u_int i; u_int retval; - u_int64_t genval; intrmask_t mask; /* The reseed task must not be jumped on */ @@ -241,7 +241,8 @@ read_random(char *buf, u_int count) (unsigned char *)&genval, sizeof(random_state.counter), &random_state.key, random_state.ivec, BF_ENCRYPT); - memcpy(&buf[i], &genval, sizeof(random_state.counter)); + memcpy((char *)buf + i, &genval, + sizeof(random_state.counter)); if (++random_state.outputblocks >= random_state.gengateinterval) { generator_gate(); random_state.outputblocks = 0; @@ -268,8 +269,8 @@ read_random(char *buf, u_int count) else { retval = cur < count ? cur : count; memcpy(buf, - (char *)&random_state.counter + - (sizeof(random_state.counter) - retval), + (char *)&genval + + (sizeof(random_state.counter) - cur), retval); cur -= retval; } @@ -279,7 +280,7 @@ read_random(char *buf, u_int count) } void -write_random(char *buf, u_int count) +write_random(void *buf, u_int count) { u_int i; intrmask_t mask; @@ -287,11 +288,21 @@ write_random(char *buf, u_int count) /* The reseed task must not be jumped on */ mask = splsofttq(); - for (i = 0; i < count/sizeof(u_int64_t); i++) { + /* arbitrarily break the input up into 8-byte chunks */ + for (i = 0; i < count; i += 8) { nanotime(&timebuf); - random_harvest_internal(&timebuf, - *(u_int64_t *)&buf[i*sizeof(u_int64_t)], - 0, 0, RANDOM_WRITE); + random_harvest_internal(&timebuf, (char *)buf + i, 8, 0, 0, + RANDOM_WRITE); + } + /* Maybe the loop iterated at least once */ + if (i > count) + i -= 8; + /* Get the last bytes even if the input length is not a multiple of 8 */ + count %= 8; + if (count) { + nanotime(&timebuf); + random_harvest_internal(&timebuf, (char *)buf + i, count, 0, 0, + RANDOM_WRITE); } reseed(FAST); splx(mask); @@ -329,7 +340,7 @@ generator_gate(void) */ static void -random_harvest_internal(struct timespec *timep, u_int64_t entropy, +random_harvest_internal(struct timespec *timep, void *entropy, u_int count, u_int bits, u_int frac, enum esource origin) { u_int insert; @@ -338,6 +349,7 @@ random_harvest_internal(struct timespec *timep, u_int64_t entropy, struct source *source; struct pool *pool; intrmask_t mask; + u_int64_t entropy_buf; #ifdef DEBUG printf("Random harvest\n"); @@ -363,7 +375,12 @@ random_harvest_internal(struct timespec *timep, u_int64_t entropy, bucket->nanotime = *timep; /* the harvested entropy */ - bucket->data = entropy; + count = count > sizeof(entropy_buf) + ? sizeof(entropy_buf) + : count; + memcpy(&entropy_buf, entropy, count); + /* XOR it in to really foul up the works */ + bucket->data ^= entropy_buf; /* update the estimates - including "fractional bits" */ source->bits += bits; diff --git a/sys/dev/random/yarrow.h b/sys/dev/random/yarrow.h index e64a1bc..a11dbae 100644 --- a/sys/dev/random/yarrow.h +++ b/sys/dev/random/yarrow.h @@ -42,10 +42,10 @@ void random_init(void); void random_deinit(void); -void random_init_harvester(void (*)(struct timespec *, u_int64_t, u_int, u_int, enum esource)); +void random_init_harvester(void (*)(struct timespec *, void *, u_int, u_int, u_int, enum esource)); void random_deinit_harvester(void); -void write_random(char *, u_int); +void write_random(void *, u_int); /* This is the beastie that needs protecting. It contains all of the * state that we are excited about. -- cgit v1.1