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")
This commit is contained in:
parent
f94bf02fdb
commit
7aa4389a6c
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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,10 +84,19 @@ 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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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,10 +84,19 @@ 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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -2956,9 +2956,8 @@ scgetc(sc_softc_t *sc, u_int flags)
|
||||
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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user