diff options
author | markm <markm@FreeBSD.org> | 2000-07-25 21:18:47 +0000 |
---|---|---|
committer | markm <markm@FreeBSD.org> | 2000-07-25 21:18:47 +0000 |
commit | 12a237a692a81328f3f14927af016b53de12eabd (patch) | |
tree | d58170d695bea67ad11d489d9a5a743980675bfc /sys | |
parent | 218edb7befe15334d4053ab8e1621558da5eccb0 (diff) | |
download | FreeBSD-src-12a237a692a81328f3f14927af016b53de12eabd.zip FreeBSD-src-12a237a692a81328f3f14927af016b53de12eabd.tar.gz |
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")
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/random/harvest.c | 8 | ||||
-rw-r--r-- | sys/dev/random/randomdev.c | 14 | ||||
-rw-r--r-- | sys/dev/random/yarrow.c | 43 | ||||
-rw-r--r-- | sys/dev/random/yarrow.h | 4 | ||||
-rw-r--r-- | sys/dev/randomdev/harvest.c | 8 | ||||
-rw-r--r-- | sys/dev/randomdev/randomdev.c | 14 | ||||
-rw-r--r-- | sys/dev/randomdev/yarrow.c | 43 | ||||
-rw-r--r-- | sys/dev/randomdev/yarrow.h | 4 | ||||
-rw-r--r-- | sys/dev/syscons/syscons.c | 3 | ||||
-rw-r--r-- | sys/dev/syscons/sysmouse.c | 5 | ||||
-rw-r--r-- | sys/sys/random.h | 9 |
11 files changed, 103 insertions, 52 deletions
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 <dev/randomdev/yarrow.h> +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. diff --git a/sys/dev/randomdev/harvest.c b/sys/dev/randomdev/harvest.c index 3e16059..92de318 100644 --- a/sys/dev/randomdev/harvest.c +++ b/sys/dev/randomdev/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/randomdev/randomdev.c b/sys/dev/randomdev/randomdev.c index c84f4bd..645cfb0 100644 --- a/sys/dev/randomdev/randomdev.c +++ b/sys/dev/randomdev/randomdev.c @@ -46,6 +46,7 @@ #include <dev/randomdev/yarrow.h> +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/randomdev/yarrow.c b/sys/dev/randomdev/yarrow.c index bc85575..9611436 100644 --- a/sys/dev/randomdev/yarrow.c +++ b/sys/dev/randomdev/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/randomdev/yarrow.h b/sys/dev/randomdev/yarrow.h index e64a1bc..a11dbae 100644 --- a/sys/dev/randomdev/yarrow.h +++ b/sys/dev/randomdev/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. diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index cbcace8..2a447f7 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -2956,9 +2956,8 @@ next_code: if (!(c & RELKEY)) sc_touch_scrn_saver(); - /* do the /dev/random device a favour */ if (!(flags & SCGETC_CN)) - random_harvest((u_int64_t)c, 1, 0, RANDOM_KEYBOARD); + random_harvest(&c, sizeof(c), 1, 0, RANDOM_KEYBOARD); if (scp->kbd_mode != K_XLATE) return KEYCHAR(c); diff --git a/sys/dev/syscons/sysmouse.c b/sys/dev/syscons/sysmouse.c index 5c92b23..3f13de2 100644 --- a/sys/dev/syscons/sysmouse.c +++ b/sys/dev/syscons/sysmouse.c @@ -334,10 +334,7 @@ sysmouse_event(mouse_info_t *info) sysmouse_tty); } - /* do the /dev/random device a favour */ - /* The nasty-looking cast is to force treatment of 8 u_chars */ - /* in buf as a u_int64_t */ - random_harvest(*((u_int64_t *)buf), 2, 0, RANDOM_MOUSE); + random_harvest(buf, sizeof(buf), 2, 0, RANDOM_MOUSE); return mouse_status.flags; } diff --git a/sys/sys/random.h b/sys/sys/random.h index 25bc9b3..9fadb54 100644 --- a/sys/sys/random.h +++ b/sys/sys/random.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2000 Mark Murray + * Copyright (c) 2000 Mark R. V. Murray * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,10 +31,11 @@ #ifdef _KERNEL -u_int read_random(char *, u_int); +u_int read_random(void *, u_int); -enum esource { RANDOM_WRITE, RANDOM_KEYBOARD, RANDOM_MOUSE, ENTROPYSOURCE }; -void random_harvest(u_int64_t, u_int, u_int, enum esource); +enum esource { RANDOM_WRITE, RANDOM_KEYBOARD, RANDOM_MOUSE, RANDOM_NET, \ + ENTROPYSOURCE }; +void random_harvest(void *, u_int, u_int, u_int, enum esource); #endif |