summaryrefslogtreecommitdiffstats
path: root/sys/dev/random
diff options
context:
space:
mode:
authormarkm <markm@FreeBSD.org>2000-07-25 21:18:47 +0000
committermarkm <markm@FreeBSD.org>2000-07-25 21:18:47 +0000
commit12a237a692a81328f3f14927af016b53de12eabd (patch)
treed58170d695bea67ad11d489d9a5a743980675bfc /sys/dev/random
parent218edb7befe15334d4053ab8e1621558da5eccb0 (diff)
downloadFreeBSD-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/dev/random')
-rw-r--r--sys/dev/random/harvest.c8
-rw-r--r--sys/dev/random/randomdev.c14
-rw-r--r--sys/dev/random/yarrow.c43
-rw-r--r--sys/dev/random/yarrow.h4
4 files changed, 48 insertions, 21 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.
OpenPOWER on IntegriCloud