summaryrefslogtreecommitdiffstats
path: root/sys/dev/random
diff options
context:
space:
mode:
authormarkm <markm@FreeBSD.org>2001-03-10 12:51:55 +0000
committermarkm <markm@FreeBSD.org>2001-03-10 12:51:55 +0000
commitad4dd3b5a22959becd824aa989ac27a7b27e037e (patch)
tree46e10e74c3796f985f882d072fc9ecd912b67560 /sys/dev/random
parenta9b8e8be5d560774accffee6d14de8dfce8c81ba (diff)
downloadFreeBSD-src-ad4dd3b5a22959becd824aa989ac27a7b27e037e.zip
FreeBSD-src-ad4dd3b5a22959becd824aa989ac27a7b27e037e.tar.gz
Very large makeover of the /dev/random driver.
o Separate the kernel stuff from the Yarrow algorithm. Yarrow is now well contained in one source file and one header. o Replace the Blowfish-based crypto routines with Rijndael-based ones. (Rijndael is the new AES algorithm). The huge improvement in Rijndael's key-agility over Blowfish means that this is an extremely dramatic improvement in speed, and makes a heck of a difference in its (lack of) CPU load. o Clean up the sysctl's. At BDE's prompting, I have gone back to static sysctls. o Bug fixes. The streamlining of the crypto stuff enabled me to find and fix some bugs. DES also found a bug in the reseed routine which is fixed. o Change the way reseeds clear "used" entropy. Previously, only the source(s) that caused a reseed were cleared. Now all sources in the relevant pool(s) are cleared. o Code tidy-up. Mostly to make it (nearly) 80-column compliant.
Diffstat (limited to 'sys/dev/random')
-rw-r--r--sys/dev/random/harvest.c5
-rw-r--r--sys/dev/random/hash.c106
-rw-r--r--sys/dev/random/hash.h18
-rw-r--r--sys/dev/random/randomdev.c335
-rw-r--r--sys/dev/random/randomdev.h83
-rw-r--r--sys/dev/random/yarrow.c381
-rw-r--r--sys/dev/random/yarrow.h36
7 files changed, 505 insertions, 459 deletions
diff --git a/sys/dev/random/harvest.c b/sys/dev/random/harvest.c
index 59495d7..c0c9a02 100644
--- a/sys/dev/random/harvest.c
+++ b/sys/dev/random/harvest.c
@@ -38,10 +38,7 @@
#include <machine/cpu.h>
-#include <crypto/blowfish/blowfish.h>
-
-#include <dev/random/hash.h>
-#include <dev/random/yarrow.h>
+#include <dev/random/randomdev.h>
static u_int read_random_phony(void *, u_int);
diff --git a/sys/dev/random/hash.c b/sys/dev/random/hash.c
index 21c89e0..ed796f1 100644
--- a/sys/dev/random/hash.c
+++ b/sys/dev/random/hash.c
@@ -33,19 +33,17 @@
#include <sys/random.h>
#include <sys/types.h>
-#include <crypto/blowfish/blowfish.h>
+#include <crypto/rijndael/rijndael.h>
#include <dev/random/hash.h>
-/* initialise the hash by copying in some supplied data */
+/* initialise the hash by zeroing it */
void
-yarrow_hash_init(struct yarrowhash *context, void *data, size_t size)
+yarrow_hash_init(struct yarrowhash *context)
{
- size_t count;
-
- count = size > KEYSIZE ? KEYSIZE : size;
- memset(context->hash, 0xff, KEYSIZE);
- memcpy(context->hash, data, count);
+ rijndael_cipherInit(&context->cipher, MODE_CBC, NULL);
+ bzero(context->hash, KEYSIZE);
+ context->partial = 0;
}
/* Do a Davies-Meyer hash using a block cipher.
@@ -55,65 +53,65 @@ yarrow_hash_init(struct yarrowhash *context, void *data, size_t size)
void
yarrow_hash_iterate(struct yarrowhash *context, void *data, size_t size)
{
- u_char keybuffer[KEYSIZE], temp[KEYSIZE];
- size_t count;
- int iteration, last, i;
+ u_char temp[KEYSIZE];
+ u_int i, j;
- iteration = 0;
- last = 0;
- for (;;) {
- if (size <= KEYSIZE)
- last = 1;
- count = size > KEYSIZE ? KEYSIZE : size;
- memcpy(keybuffer, &((u_char *)data)[iteration], count);
- memset(&keybuffer[KEYSIZE - count], 0xff, count);
- BF_set_key(&context->hashkey, count,
- &((u_char *)data)[iteration]);
- BF_cbc_encrypt(context->hash, temp, KEYSIZE, &context->hashkey,
- context->ivec, BF_ENCRYPT);
- for (i = 0; i < KEYSIZE; i++)
- context->hash[i] ^= temp[i];
- if (last)
- break;
- iteration += KEYSIZE;
- size -= KEYSIZE;
+ for (i = 0; i < size; i++) {
+ context->accum[context->partial++] = ((u_char *)(data))[i];
+ if (context->partial == (KEYSIZE - 1)) {
+ rijndael_makeKey(&context->hashkey, DIR_ENCRYPT,
+ KEYSIZE*8, context->accum);
+ rijndael_blockEncrypt(&context->cipher,
+ &context->hashkey, context->hash,
+ KEYSIZE*8, temp);
+ for (j = 0; j < KEYSIZE; j++)
+ context->hash[j] ^= temp[j];
+ bzero(context->accum, KEYSIZE);
+ context->partial = 0;
+ }
}
}
-/* Conclude by returning a pointer to the data */
+/* Conclude by returning the hash in the supplied /buf/ which must be
+ * KEYSIZE bytes long. Trailing data (less than KEYSIZE bytes) are
+ * not forgotten.
+ */
void
yarrow_hash_finish(struct yarrowhash *context, void *buf)
{
- memcpy(buf, context->hash, sizeof(context->hash));
+ u_char temp[KEYSIZE];
+ int i;
+
+ if (context->partial) {
+ rijndael_makeKey(&context->hashkey, DIR_ENCRYPT,
+ KEYSIZE*8, context->accum);
+ rijndael_blockEncrypt(&context->cipher,
+ &context->hashkey, context->hash,
+ KEYSIZE*8, temp);
+ for (i = 0; i < KEYSIZE; i++)
+ context->hash[i] ^= temp[i];
+ }
+ memcpy(buf, context->hash, KEYSIZE);
+ bzero(context->hash, KEYSIZE);
}
-/* Initialise the encryption routine by setting up the key schedule */
+/* Initialise the encryption routine by setting up the key schedule
+ * from the supplied /key/ which must be KEYSIZE bytes of binary
+ * data.
+ */
void
-yarrow_encrypt_init(struct yarrowkey *context, void *data, size_t size)
+yarrow_encrypt_init(struct yarrowkey *context, void *data)
{
- size_t count;
-
- count = size > KEYSIZE ? KEYSIZE : size;
- BF_set_key(&context->key, count, data);
+ rijndael_cipherInit(&context->cipher, MODE_CBC, NULL);
+ rijndael_makeKey(&context->key, DIR_ENCRYPT, KEYSIZE*8, data);
}
-/* Encrypt the supplied data using the key schedule preset in the context */
+/* Encrypt the supplied data using the key schedule preset in the context.
+ * KEYSIZE bytes are encrypted from /d_in/ to /d_out/.
+ */
void
-yarrow_encrypt(struct yarrowkey *context, void *d_in, void *d_out, size_t size)
+yarrow_encrypt(struct yarrowkey *context, void *d_in, void *d_out)
{
- size_t count;
- int iteration, last;
-
- last = 0;
- for (iteration = 0;; iteration += KEYSIZE) {
- if (size <= KEYSIZE)
- last = 1;
- count = size > KEYSIZE ? KEYSIZE : size;
- BF_cbc_encrypt(&((u_char *)d_in)[iteration],
- &((u_char *)d_out)[iteration], count, &context->key,
- context->ivec, BF_ENCRYPT);
- if (last)
- break;
- size -= KEYSIZE;
- }
+ rijndael_blockEncrypt(&context->cipher, &context->key, d_in,
+ KEYSIZE*8, d_out);
}
diff --git a/sys/dev/random/hash.h b/sys/dev/random/hash.h
index f210f13..99f0b48 100644
--- a/sys/dev/random/hash.h
+++ b/sys/dev/random/hash.h
@@ -26,21 +26,23 @@
* $FreeBSD$
*/
-#define KEYSIZE 32 /* 32 bytes == 256 bits */
+#define KEYSIZE 32 /* in bytes - 32 bytes == 256 bits */
struct yarrowhash { /* Big! Make static! */
- BF_KEY hashkey; /* Data cycles through here */
- u_char ivec[8]; /* Blowfish Internal */
+ keyInstance hashkey; /* Data cycles through here */
+ cipherInstance cipher; /* Rijndael internal */
u_char hash[KEYSIZE]; /* Repeatedly encrypted */
+ u_char accum[KEYSIZE]; /* Accumulate partial chunks */
+ u_int partial; /* Keep track of < KEYSIZE chunks */
};
struct yarrowkey { /* Big! Make static! */
- BF_KEY key; /* Key schedule */
- u_char ivec[8]; /* Blowfish Internal */
+ keyInstance key; /* Key schedule */
+ cipherInstance cipher; /* Rijndael internal */
};
-void yarrow_hash_init(struct yarrowhash *, void *, size_t);
+void yarrow_hash_init(struct yarrowhash *);
void yarrow_hash_iterate(struct yarrowhash *, void *, size_t);
void yarrow_hash_finish(struct yarrowhash *, void *);
-void yarrow_encrypt_init(struct yarrowkey *, void *, size_t);
-void yarrow_encrypt(struct yarrowkey *context, void *, void *, size_t);
+void yarrow_encrypt_init(struct yarrowkey *, void *);
+void yarrow_encrypt(struct yarrowkey *context, void *, void *);
diff --git a/sys/dev/random/randomdev.c b/sys/dev/random/randomdev.c
index 8358877..e30e9ae 100644
--- a/sys/dev/random/randomdev.c
+++ b/sys/dev/random/randomdev.c
@@ -33,6 +33,7 @@
#include <sys/fcntl.h>
#include <sys/uio.h>
#include <sys/kernel.h>
+#include <sys/kthread.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/bus.h>
@@ -41,23 +42,23 @@
#include <sys/random.h>
#include <sys/sysctl.h>
#include <sys/vnode.h>
+#include <sys/unistd.h>
+
#include <machine/bus.h>
+#include <machine/cpu.h>
#include <machine/resource.h>
-#include <crypto/blowfish/blowfish.h>
-#include <dev/random/hash.h>
-#include <dev/random/yarrow.h>
+#include <dev/random/randomdev.h>
-static d_open_t random_open;
-static d_close_t random_close;
-static d_read_t random_read;
-static d_write_t random_write;
-static d_ioctl_t random_ioctl;
-static d_poll_t random_poll;
+static d_open_t random_open;
+static d_close_t random_close;
+static d_read_t random_read;
+static d_write_t random_write;
+static d_ioctl_t random_ioctl;
+static d_poll_t random_poll;
#define CDEV_MAJOR 2
#define RANDOM_MINOR 3
-#define URANDOM_MINOR 4
static struct cdevsw random_cdevsw = {
/* open */ random_open,
@@ -76,13 +77,63 @@ static struct cdevsw random_cdevsw = {
/* bmaj */ -1
};
+static void random_kthread(void *);
+static void random_harvest_internal(u_int64_t, void *, u_int, u_int, u_int, enum esource);
+static void random_write_internal(void *, u_int);
+
+/* Ring buffer holding harvested entropy */
+static struct harvestring {
+ volatile u_int head;
+ volatile u_int tail;
+ struct harvest data[HARVEST_RING_SIZE];
+} harvestring;
+
+static struct random_systat {
+ u_int seeded; /* 0 causes blocking 1 allows normal output */
+ u_int burst; /* number of events to do before sleeping */
+ struct selinfo rsel; /* For poll(2) */
+} random_systat;
+
+/* <0 to end the kthread, 0 to let it run */
+static int random_kthread_control = 0;
+
+static struct proc *random_kthread_proc;
+
/* For use with make_dev(9)/destroy_dev(9). */
-static dev_t random_dev;
-static dev_t urandom_dev; /* XXX Temporary */
+static dev_t random_dev;
+static dev_t urandom_dev;
+
+static int
+random_check_boolean(SYSCTL_HANDLER_ARGS)
+{
+ if (oidp->oid_arg1 != NULL && *(u_int *)(oidp->oid_arg1) != 0)
+ *(u_int *)(oidp->oid_arg1) = 1;
+ return sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
+}
-/* To stash the sysctl's until they are removed */
-static struct sysctl_oid *random_sysctl[12]; /* magic # is sysctl count */
-static int sysctlcount = 0;
+RANDOM_CHECK_UINT(burst, 0, 20);
+
+SYSCTL_NODE(_kern, OID_AUTO, random, CTLFLAG_RW,
+ 0, "Random Number Generator");
+SYSCTL_NODE(_kern_random, OID_AUTO, sys, CTLFLAG_RW,
+ 0, "Entropy Device Parameters");
+SYSCTL_PROC(_kern_random_sys, OID_AUTO, seeded,
+ CTLTYPE_INT|CTLFLAG_RW, &random_systat.seeded, 1,
+ random_check_boolean, "I", "Seeded State");
+SYSCTL_PROC(_kern_random_sys, OID_AUTO, burst,
+ CTLTYPE_INT|CTLFLAG_RW, &random_systat.burst, 20,
+ random_check_uint_burst, "I", "Harvest Burst Size");
+SYSCTL_NODE(_kern_random_sys, OID_AUTO, harvest, CTLFLAG_RW,
+ 0, "Entropy Sources");
+SYSCTL_PROC(_kern_random_sys_harvest, OID_AUTO, ethernet,
+ CTLTYPE_INT|CTLFLAG_RW, &harvest.ethernet, 0,
+ random_check_boolean, "I", "Harvest NIC entropy");
+SYSCTL_PROC(_kern_random_sys_harvest, OID_AUTO, point_to_point,
+ CTLTYPE_INT|CTLFLAG_RW, &harvest.point_to_point, 0,
+ random_check_boolean, "I", "Harvest serial net entropy");
+SYSCTL_PROC(_kern_random_sys_harvest, OID_AUTO, interrupt,
+ CTLTYPE_INT|CTLFLAG_RW, &harvest.interrupt, 0,
+ random_check_boolean, "I", "Harvest IRQ entropy");
static int
random_open(dev_t dev, int flags, int fmt, struct proc *p)
@@ -104,15 +155,16 @@ random_close(dev_t dev, int flags, int fmt, struct proc *p)
static int
random_read(dev_t dev, struct uio *uio, int flag)
{
- u_int c, ret;
- int error = 0;
- void *random_buf;
+ u_int c, ret;
+ int error = 0;
+ void *random_buf;
- while (!random_state.seeded) {
+ while (!random_systat.seeded) {
if (flag & IO_NDELAY)
error = EWOULDBLOCK;
else
- error = tsleep(&random_state, PUSER|PCATCH, "rndblk", 0);
+ error = tsleep(&random_systat, PUSER|PCATCH,
+ "block", 0);
if (error != 0)
return error;
}
@@ -129,17 +181,18 @@ random_read(dev_t dev, struct uio *uio, int flag)
static int
random_write(dev_t dev, struct uio *uio, int flag)
{
- u_int c;
- int error = 0;
- void *random_buf;
+ u_int c;
+ int error;
+ void *random_buf;
+ error = 0;
random_buf = (void *)malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
while (uio->uio_resid > 0) {
c = min(uio->uio_resid, PAGE_SIZE);
error = uiomove(random_buf, c, uio);
if (error)
break;
- write_random(random_buf, c);
+ random_write_internal(random_buf, c);
}
free(random_buf, M_TEMP);
return error;
@@ -154,14 +207,14 @@ random_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
static int
random_poll(dev_t dev, int events, struct proc *p)
{
- int revents;
+ int revents;
revents = 0;
if (events & (POLLIN | POLLRDNORM)) {
- if (random_state.seeded)
+ if (random_systat.seeded)
revents = events & (POLLIN | POLLRDNORM);
else
- selrecord(p, &random_state.rsel);
+ selrecord(p, &random_systat.rsel);
}
return revents;
}
@@ -169,84 +222,58 @@ random_poll(dev_t dev, int events, struct proc *p)
static int
random_modevent(module_t mod, int type, void *data)
{
- struct sysctl_oid *node_base, *node1, *node2;
- int error, i;
+ int error;
switch(type) {
case MOD_LOAD:
- error = random_init();
- if (error != 0)
- return error;
+ random_init();
+
+ /* This can be turned off by the very paranoid
+ * a reseed will turn it back on.
+ */
+ random_systat.seeded = 1;
- random_sysctl[sysctlcount++] = node_base =
- SYSCTL_ADD_NODE(NULL, SYSCTL_STATIC_CHILDREN(_kern),
- OID_AUTO, "random", CTLFLAG_RW, 0,
- "Random Number Generator");
- random_sysctl[sysctlcount++] = node1 =
- SYSCTL_ADD_NODE(NULL, SYSCTL_CHILDREN(node_base),
- OID_AUTO, "sys", CTLFLAG_RW, 0,
- "Entropy Device Parameters");
- random_sysctl[sysctlcount++] =
- SYSCTL_ADD_INT(NULL, SYSCTL_CHILDREN(node1),
- OID_AUTO, "seeded", CTLFLAG_RW,
- &random_state.seeded, 0, "Seeded State");
- random_sysctl[sysctlcount++] =
- SYSCTL_ADD_INT(NULL, SYSCTL_CHILDREN(node1),
- OID_AUTO, "harvest_ethernet", CTLFLAG_RW,
- &harvest.ethernet, 0, "Harvest NIC entropy");
- random_sysctl[sysctlcount++] =
- SYSCTL_ADD_INT(NULL, SYSCTL_CHILDREN(node1),
- OID_AUTO, "harvest_point_to_point", CTLFLAG_RW,
- &harvest.point_to_point, 0, "Harvest serial net entropy");
- random_sysctl[sysctlcount++] =
- SYSCTL_ADD_INT(NULL, SYSCTL_CHILDREN(node1),
- OID_AUTO, "harvest_interrupt", CTLFLAG_RW,
- &harvest.interrupt, 0, "Harvest IRQ entropy");
- random_sysctl[sysctlcount++] = node2 =
- SYSCTL_ADD_NODE(NULL, SYSCTL_CHILDREN(node_base),
- OID_AUTO, "yarrow", CTLFLAG_RW, 0,
- "Yarrow Parameters");
- random_sysctl[sysctlcount++] =
- SYSCTL_ADD_INT(NULL, SYSCTL_CHILDREN(node2),
- OID_AUTO, "gengateinterval", CTLFLAG_RW,
- &random_state.gengateinterval, 0,
- "Generator Gate Interval");
- random_sysctl[sysctlcount++] =
- SYSCTL_ADD_INT(NULL, SYSCTL_CHILDREN(node2),
- OID_AUTO, "bins", CTLFLAG_RW,
- &random_state.bins, 0,
- "Execution time tuner");
- random_sysctl[sysctlcount++] =
- SYSCTL_ADD_INT(NULL, SYSCTL_CHILDREN(node2),
- OID_AUTO, "fastthresh", CTLFLAG_RW,
- &random_state.pool[0].thresh, 0,
- "Fast pool reseed threshhold");
- random_sysctl[sysctlcount++] =
- SYSCTL_ADD_INT(NULL, SYSCTL_CHILDREN(node2),
- OID_AUTO, "slowthresh", CTLFLAG_RW,
- &random_state.pool[1].thresh, 0,
- "Slow pool reseed threshhold");
- random_sysctl[sysctlcount++] =
- SYSCTL_ADD_INT(NULL, SYSCTL_CHILDREN(node2),
- OID_AUTO, "slowoverthresh", CTLFLAG_RW,
- &random_state.slowoverthresh, 0,
- "Slow pool over-threshhold reseed");
+ /* Number of envents to process off the harvest
+ * queue before giving it a break and sleeping
+ */
+ random_systat.burst = 20;
+
+ /* Initialise the harvest ringbuffer */
+ harvestring.head = 0;
+ harvestring.tail = 0;
if (bootverbose)
printf("random: <entropy source>\n");
random_dev = make_dev(&random_cdevsw, RANDOM_MINOR, UID_ROOT,
GID_WHEEL, 0666, "random");
- urandom_dev = make_dev(&random_cdevsw, URANDOM_MINOR, UID_ROOT,
- GID_WHEEL, 0666, "urandom"); /* XXX Temporary */
+ urandom_dev = make_dev_alias(random_dev, "urandom");
+
+ /* Start the hash/reseed thread */
+ 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,
+ read_random_real);
+
return 0;
case MOD_UNLOAD:
+ /* Deregister the randomness harvesting routine */
+ random_deinit_harvester();
+
+ /* Command the hash/reseed thread to end and
+ * wait for it to finish
+ */
+ random_kthread_control = -1;
+ tsleep((void *)&random_kthread_control, PUSER, "term", 0);
+
random_deinit();
+
destroy_dev(random_dev);
- destroy_dev(urandom_dev); /* XXX Temporary */
- for (i = sysctlcount - 1; i >= 0; i--)
- if (sysctl_remove_oid(random_sysctl[i], 1, 0) == EINVAL)
- panic("random: removing sysctl");
+ destroy_dev(urandom_dev);
return 0;
case MOD_SHUTDOWN:
@@ -258,3 +285,129 @@ random_modevent(module_t mod, int type, void *data)
}
DEV_MODULE(random, random_modevent, NULL);
+
+static void
+random_kthread(void *arg /* NOTUSED */)
+{
+ struct harvest *event;
+ int newtail, burst;
+
+ /* Drain the harvest queue (in 'burst' size chunks,
+ * if 'burst' > 0. If 'burst' == 0, then completely
+ * drain the queue.
+ */
+ for (burst = 0; ; burst++) {
+
+ if ((harvestring.tail == harvestring.head) ||
+ (random_systat.burst && burst == random_systat.burst)) {
+ tsleep(&harvestring, PUSER, "sleep", hz/10);
+ burst = 0;
+
+ }
+ else {
+
+ /* Suck a harvested entropy event out of the queue and
+ * hand it to the event processor
+ */
+
+ newtail = (harvestring.tail + 1) & HARVEST_RING_MASK;
+ event = &harvestring.data[harvestring.tail];
+
+ /* Bump the ring counter. This action is assumed
+ * to be atomic.
+ */
+ harvestring.tail = newtail;
+
+ random_process_event(event);
+
+ }
+
+ /* Is the thread scheduled for a shutdown? */
+ if (random_kthread_control != 0) {
+#ifdef DEBUG
+ mtx_lock(&Giant);
+ printf("Random kthread setting terminate\n");
+ mtx_unlock(&Giant);
+#endif
+ random_set_wakeup_exit(&random_kthread_control);
+ /* NOTREACHED */
+ break;
+ }
+
+ }
+
+}
+
+/* Entropy harvesting routine. This is supposed to be fast; do
+ * not do anything slow in here!
+ */
+static void
+random_harvest_internal(u_int64_t somecounter, void *entropy, u_int count,
+ u_int bits, u_int frac, enum esource origin)
+{
+ struct harvest *harvest;
+ int newhead;
+
+ newhead = (harvestring.head + 1) & HARVEST_RING_MASK;
+
+ if (newhead != harvestring.tail) {
+
+ /* Add the harvested data to the ring buffer */
+
+ harvest = &harvestring.data[harvestring.head];
+
+ /* Stuff the harvested data into the ring */
+ harvest->somecounter = somecounter;
+ count = count > HARVESTSIZE ? HARVESTSIZE : count;
+ memcpy(harvest->entropy, entropy, count);
+ harvest->size = count;
+ harvest->bits = bits;
+ harvest->frac = frac;
+ harvest->source = origin < ENTROPYSOURCE ? origin : 0;
+
+ /* Bump the ring counter. This action is assumed
+ * to be atomic.
+ */
+ harvestring.head = newhead;
+
+ }
+
+}
+
+static void
+random_write_internal(void *buf, u_int count)
+{
+ u_int i;
+
+ /* Break the input up into HARVESTSIZE chunks.
+ * The writer has too much control here, so "estimate" the
+ * the entropy as zero.
+ */
+ for (i = 0; i < count; i += HARVESTSIZE) {
+ random_harvest_internal(get_cyclecount(), (char *)buf + i,
+ HARVESTSIZE, 0, 0, RANDOM_WRITE);
+ }
+
+ /* Maybe the loop iterated at least once */
+ if (i > count)
+ i -= HARVESTSIZE;
+
+ /* Get the last bytes even if the input length is not
+ * a multiple of HARVESTSIZE.
+ */
+ count %= HARVESTSIZE;
+ if (count) {
+ random_harvest_internal(get_cyclecount(), (char *)buf + i,
+ count, 0, 0, RANDOM_WRITE);
+ }
+}
+
+void
+random_unblock(void)
+{
+ if (!random_systat.seeded) {
+ random_systat.seeded = 1;
+ selwakeup(&random_systat.rsel);
+ wakeup(&random_systat);
+ }
+}
diff --git a/sys/dev/random/randomdev.h b/sys/dev/random/randomdev.h
new file mode 100644
index 0000000..dc6a673
--- /dev/null
+++ b/sys/dev/random/randomdev.h
@@ -0,0 +1,83 @@
+/*-
+ * Copyright (c) 2001 Mark R V Murray
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/* This header contains only those definitions that are global
+ * and non algorithm-specific for the entropy processor
+ */
+
+/* #define ENTROPYSOURCE nn entropy sources (actually classes)
+ * This is properly defined in
+ * an enum in sys/random.h
+ */
+
+/* Cryptographic block size in bits */
+#define BLOCKSIZE 256
+
+/* The ring size _MUST_ be a power of 2 */
+#define HARVEST_RING_SIZE 1024 /* harvest ring buffer size */
+#define HARVEST_RING_MASK (HARVEST_RING_SIZE - 1)
+
+#define HARVESTSIZE 16 /* max size of each harvested entropy unit */
+
+SYSCTL_DECL(_kern_random);
+
+/* These are used to queue harvested packets of entropy. The entropy
+ * buffer size is pretty arbitrary.
+ */
+struct harvest {
+ u_int64_t somecounter; /* fast counter for clock jitter */
+ u_char entropy[HARVESTSIZE]; /* the harvested entropy */
+ u_int size, bits, frac; /* stats about the entropy */
+ enum esource source; /* stats about the entropy */
+};
+
+void random_init(void);
+void random_deinit(void);
+void random_init_harvester(void (*)(u_int64_t, void *, u_int, u_int, u_int, enum esource), u_int (*)(void *, u_int));
+void random_deinit_harvester(void);
+void random_set_wakeup_exit(void *);
+void random_process_event(struct harvest *event);
+void random_reseed(void);
+void random_unblock(void);
+
+u_int read_random_real(void *, u_int);
+
+/* If this was c++, this would be a template */
+#define RANDOM_CHECK_UINT(name, min, max) \
+static int \
+random_check_uint_##name##(SYSCTL_HANDLER_ARGS) \
+{ \
+ if (oidp->oid_arg1 != NULL) { \
+ if (*(u_int *)(oidp->oid_arg1) < min) \
+ *(u_int *)(oidp->oid_arg1) = min; \
+ else if (*(u_int *)(oidp->oid_arg1) > max) \
+ *(u_int *)(oidp->oid_arg1) = max; \
+ } \
+ return sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, \
+ req); \
+}
diff --git a/sys/dev/random/yarrow.c b/sys/dev/random/yarrow.c
index 6313587..542bece 100644
--- a/sys/dev/random/yarrow.c
+++ b/sys/dev/random/yarrow.c
@@ -29,229 +29,128 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
-#include <sys/kthread.h>
#include <sys/libkern.h>
#include <sys/mutex.h>
#include <sys/selinfo.h>
#include <sys/random.h>
+#include <sys/sysctl.h>
#include <sys/types.h>
-#include <sys/unistd.h>
-#include <machine/atomic.h>
-#include <machine/cpu.h>
-
-#include <crypto/blowfish/blowfish.h>
+#include <crypto/rijndael/rijndael.h>
#include <dev/random/hash.h>
+#include <dev/random/randomdev.h>
#include <dev/random/yarrow.h>
/* #define DEBUG */
-static void generator_gate(void);
-static void reseed(int);
-static void random_harvest_internal(u_int64_t, void *, u_int, u_int, u_int, enum esource);
+RANDOM_CHECK_UINT(gengateinterval, 4, 64);
+RANDOM_CHECK_UINT(bins, 2, 16);
+RANDOM_CHECK_UINT(fastthresh, BLOCKSIZE/4, BLOCKSIZE);
+RANDOM_CHECK_UINT(slowthresh, BLOCKSIZE/4, BLOCKSIZE);
+RANDOM_CHECK_UINT(slowoverthresh, 1, 5);
+
+SYSCTL_NODE(_kern_random, OID_AUTO, yarrow, CTLFLAG_RW, 0, "Yarrow Parameters");
+SYSCTL_PROC(_kern_random_yarrow, OID_AUTO, gengateinterval,
+ CTLTYPE_INT|CTLFLAG_RW, &random_state.gengateinterval, 10,
+ random_check_uint_gengateinterval, "I", "Generator Gate Interval");
+SYSCTL_PROC(_kern_random_yarrow, OID_AUTO, bins,
+ CTLTYPE_INT|CTLFLAG_RW, &random_state.bins, 10,
+ random_check_uint_bins, "I", "Execution time tuner");
+SYSCTL_PROC(_kern_random_yarrow, OID_AUTO, fastthresh,
+ CTLTYPE_INT|CTLFLAG_RW, &random_state.pool[0].thresh, (3*BLOCKSIZE)/4,
+ random_check_uint_fastthresh, "I", "Fast reseed threshold");
+SYSCTL_PROC(_kern_random_yarrow, OID_AUTO, slowthresh,
+ CTLTYPE_INT|CTLFLAG_RW, &random_state.pool[1].thresh, BLOCKSIZE,
+ random_check_uint_slowthresh, "I", "Slow reseed threshold");
+SYSCTL_PROC(_kern_random_yarrow, OID_AUTO, slowoverthresh,
+ CTLTYPE_INT|CTLFLAG_RW, &random_state.slowoverthresh, 2,
+ random_check_uint_slowoverthresh, "I", "Slow over-threshold reseed");
-static void random_kthread(void *);
+static void generator_gate(void);
+static void reseed(u_int);
/* Structure holding the entropy state */
struct random_state random_state;
-/* These are used to queue harvested packets of entropy. The entropy
- * buffer size is pretty arbitrary.
- */
-struct harvest {
- u_int64_t somecounter; /* fast counter for clock jitter */
- u_char entropy[HARVESTSIZE]; /* the harvested entropy */
- u_int size, bits, frac; /* stats about the entropy */
- enum esource source; /* stats about the entropy */
-};
-
-/* Ring buffer holding harvested entropy */
-static struct harvestring {
- volatile int head;
- volatile int tail;
- struct harvest data[HARVEST_RING_SIZE];
-} harvestring;
-
/* The reseed thread mutex */
static struct mtx random_reseed_mtx;
-/* <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 *arg /* NOTUSED */)
+/* Process a single stochastic event off the harvest queue */
+void
+random_process_event(struct harvest *event)
{
- int pl, src, overthreshhold[2], newtail;
- struct harvest *event;
+ u_int pl, src, overthreshhold[2];
struct source *source;
-#ifdef DEBUG
- mtx_lock(&Giant);
- printf("OWNERSHIP Giant == %d sched_lock == %d\n",
- mtx_owned(&Giant), mtx_owned(&sched_lock));
- mtx_unlock(&Giant);
-#endif
-
- for (pl = 0; pl < 2; pl++)
- yarrow_hash_init(&random_state.pool[pl].hash, NULL, 0);
-
- for (;;) {
-
- if (harvestring.tail == harvestring.head)
- tsleep(&harvestring, PUSER, "rndslp", hz/10);
-
- else {
-
- /* Suck the harvested entropy out of the queue and hash
- * it into the appropriate pool.
- */
-
- newtail = (harvestring.tail + 1) & HARVEST_RING_MASK;
- event = &harvestring.data[harvestring.tail];
-
- /* Bump the ring counter. This action is assumed
- * to be atomic.
- */
- harvestring.tail = newtail;
-
- pl = random_state.which = !random_state.which;
-
- source = &random_state.pool[pl].source[event->source];
- yarrow_hash_iterate(&random_state.pool[pl].hash,
- event->entropy, sizeof(event->entropy));
- yarrow_hash_iterate(&random_state.pool[pl].hash,
- &event->somecounter, sizeof(event->somecounter));
- source->frac += event->frac;
- source->bits += event->bits + source->frac/1024;
- source->frac %= 1024;
-
- /* Count the over-threshold sources in each pool */
- for (pl = 0; pl < 2; pl++) {
- overthreshhold[pl] = 0;
- for (src = 0; src < ENTROPYSOURCE; src++) {
- if (random_state.pool[pl].source[src].bits
- > random_state.pool[pl].thresh)
- overthreshhold[pl]++;
- }
- }
-
- /* if any fast source over threshhold, reseed */
- if (overthreshhold[FAST])
- reseed(FAST);
-
- /* if enough slow sources are over threshhold, reseed */
- if (overthreshhold[SLOW] >= random_state.slowoverthresh)
- reseed(SLOW);
-
+ /* Unpack the event into the appropriate source accumulator */
+ pl = random_state.which;
+ source = &random_state.pool[pl].source[event->source];
+ yarrow_hash_iterate(&random_state.pool[pl].hash, event->entropy,
+ sizeof(event->entropy));
+ yarrow_hash_iterate(&random_state.pool[pl].hash, &event->somecounter,
+ sizeof(event->somecounter));
+ source->frac += event->frac;
+ source->bits += event->bits + source->frac/1024;
+ source->frac %= 1024;
+
+ /* Count the over-threshold sources in each pool */
+ for (pl = 0; pl < 2; pl++) {
+ overthreshhold[pl] = 0;
+ for (src = 0; src < ENTROPYSOURCE; src++) {
+ if (random_state.pool[pl].source[src].bits
+ > random_state.pool[pl].thresh)
+ overthreshhold[pl]++;
}
+ }
- /* Is the thread scheduled for a shutdown? */
- if (random_kthread_control != 0) {
-#ifdef DEBUG
- mtx_lock(&Giant);
- printf("Random kthread setting terminate\n");
- mtx_unlock(&Giant);
-#endif
- random_set_wakeup_exit(&random_kthread_control);
- /* NOTREACHED */
- break;
- }
+ /* if any fast source over threshhold, reseed */
+ if (overthreshhold[FAST])
+ reseed(FAST);
- }
+ /* if enough slow sources are over threshhold, reseed */
+ if (overthreshhold[SLOW] >= random_state.slowoverthresh)
+ reseed(SLOW);
+ /* Invert the fast/slow pool selector bit */
+ random_state.which = !random_state.which;
}
-int
+void
random_init(void)
{
- int error;
-
-#ifdef DEBUG
- mtx_lock(&Giant);
- printf("Random initialise\n");
- mtx_unlock(&Giant);
-#endif
-
- /* This can be turned off by the very paranoid
- * a reseed will turn it back on.
- */
- random_state.seeded = 1;
+ int i;
/* Yarrow parameters. Do not adjust these unless you have
* have a very good clue about what they do!
*/
random_state.gengateinterval = 10;
random_state.bins = 10;
- random_state.pool[0].thresh = 100;
- random_state.pool[1].thresh = 160;
+ random_state.pool[0].thresh = (3*BLOCKSIZE)/4;
+ random_state.pool[1].thresh = BLOCKSIZE;
random_state.slowoverthresh = 2;
random_state.which = FAST;
- mtx_init(&random_reseed_mtx, "random reseed", MTX_DEF);
-
- harvestring.head = 0;
- harvestring.tail = 0;
-
- /* Start the hash/reseed thread */
- error = kthread_create(random_kthread, NULL,
- &random_kthread_proc, RFHIGHPID, "random");
- if (error != 0)
- return error;
+ /* Initialise the fast and slow entropy pools */
+ for (i = 0; i < 2; i++)
+ yarrow_hash_init(&random_state.pool[i].hash);
- /* Register the randomness harvesting routine */
- random_init_harvester(random_harvest_internal, read_random_real);
+ /* Clear the counter */
+ for (i = 0; i < 4; i++)
+ random_state.counter[i] = 0;
-#ifdef DEBUG
- mtx_lock(&Giant);
- printf("Random initialise finish\n");
- mtx_unlock(&Giant);
-#endif
-
- return 0;
+ /* Set up a lock for the reseed process */
+ mtx_init(&random_reseed_mtx, "random reseed", MTX_DEF);
}
void
random_deinit(void)
{
-#ifdef DEBUG
- mtx_lock(&Giant);
- printf("Random deinitialise\n");
- mtx_unlock(&Giant);
-#endif
-
- /* Deregister the randomness harvesting routine */
- random_deinit_harvester();
-
-#ifdef DEBUG
- mtx_lock(&Giant);
- printf("Random deinitialise waiting for thread to terminate\n");
- mtx_unlock(&Giant);
-#endif
-
- /* Command the hash/reseed thread to end and wait for it to finish */
- random_kthread_control = -1;
- tsleep((void *)&random_kthread_control, PUSER, "rndend", 0);
-
-#ifdef DEBUG
- mtx_lock(&Giant);
- printf("Random deinitialise removing mutexes\n");
- mtx_unlock(&Giant);
-#endif
-
mtx_destroy(&random_reseed_mtx);
-
-#ifdef DEBUG
- mtx_lock(&Giant);
- printf("Random deinitialise finish\n");
- mtx_unlock(&Giant);
-#endif
}
static void
-reseed(int fastslow)
+reseed(u_int fastslow)
{
/* Interrupt-context stack is a limited resource; make large
* structures static.
@@ -260,7 +159,7 @@ reseed(int fastslow)
static struct yarrowhash context;
u_char hash[KEYSIZE]; /* h' */
u_char temp[KEYSIZE];
- int i, j;
+ u_int i, j;
#ifdef DEBUG
mtx_lock(&Giant);
@@ -273,14 +172,15 @@ reseed(int fastslow)
/* 1. Hash the accumulated entropy into v[0] */
- yarrow_hash_init(&context, NULL, 0);
+ yarrow_hash_init(&context);
/* Feed the slow pool hash in if slow */
if (fastslow == SLOW)
yarrow_hash_iterate(&context,
- &random_state.pool[SLOW].hash, sizeof(struct yarrowhash));
-
+ &random_state.pool[SLOW].hash,
+ sizeof(struct yarrowhash));
yarrow_hash_iterate(&context,
&random_state.pool[FAST].hash, sizeof(struct yarrowhash));
+ yarrow_hash_finish(&context, v[0]);
/* 2. Compute hash values for all v. _Supposed_ to be computationally
* intensive.
@@ -289,13 +189,13 @@ reseed(int fastslow)
if (random_state.bins > TIMEBIN)
random_state.bins = TIMEBIN;
for (i = 1; i < random_state.bins; i++) {
- yarrow_hash_init(&context, NULL, 0);
- /* v[i] #= h(v[i-1]) */
+ yarrow_hash_init(&context);
+ /* v[i] #= h(v[i - 1]) */
yarrow_hash_iterate(&context, v[i - 1], KEYSIZE);
/* v[i] #= h(v[0]) */
yarrow_hash_iterate(&context, v[0], KEYSIZE);
/* v[i] #= h(i) */
- yarrow_hash_iterate(&context, &i, sizeof(int));
+ yarrow_hash_iterate(&context, &i, sizeof(u_int));
/* Return the hashval */
yarrow_hash_finish(&context, v[i]);
}
@@ -304,29 +204,26 @@ reseed(int fastslow)
* it is not being ignored!
*/
- yarrow_hash_init(&context, NULL, 0);
+ yarrow_hash_init(&context);
yarrow_hash_iterate(&context, &random_state.key, KEYSIZE);
for (i = 1; i < random_state.bins; i++)
yarrow_hash_iterate(&context, &v[i], KEYSIZE);
yarrow_hash_finish(&context, temp);
- yarrow_encrypt_init(&random_state.key, temp, KEYSIZE);
+ yarrow_encrypt_init(&random_state.key, temp);
/* 4. Recompute the counter */
- random_state.counter = 0;
- yarrow_encrypt(&random_state.key, &random_state.counter, temp,
- sizeof(random_state.counter));
- memcpy(&random_state.counter, temp, random_state.counter);
+ for (i = 0; i < 4; i++)
+ random_state.counter[i] = 0;
+ yarrow_encrypt(&random_state.key, random_state.counter, temp);
+ memcpy(random_state.counter, temp, sizeof(random_state.counter));
/* 5. Reset entropy estimate accumulators to zero */
for (i = 0; i <= fastslow; i++) {
for (j = 0; j < ENTROPYSOURCE; j++) {
- if (random_state.pool[i].source[j].bits >
- random_state.pool[i].thresh) {
- random_state.pool[i].source[j].bits = 0;
- random_state.pool[i].source[j].frac = 0;
- }
+ random_state.pool[i].source[j].bits = 0;
+ random_state.pool[i].source[j].frac = 0;
}
}
@@ -348,14 +245,13 @@ reseed(int fastslow)
mtx_unlock(&Giant);
#endif
- if (!random_state.seeded) {
- random_state.seeded = 1;
- selwakeup(&random_state.rsel);
- wakeup(&random_state);
- }
-
+ /* Unblock the device if it was blocked due to being unseeded */
+ random_unblock();
}
+/* Internal function to do return processed entropy from the
+ * Yarrow PRNG
+ */
u_int
read_random_real(void *buf, u_int count)
{
@@ -376,12 +272,13 @@ read_random_real(void *buf, u_int count)
if (count >= sizeof(random_state.counter)) {
retval = 0;
for (i = 0; i < count; i += sizeof(random_state.counter)) {
- random_state.counter++;
- yarrow_encrypt(&random_state.key, &random_state.counter,
- &genval, sizeof(random_state.counter));
+ random_state.counter[0]++;
+ yarrow_encrypt(&random_state.key, random_state.counter,
+ &genval);
memcpy((char *)buf + i, &genval,
sizeof(random_state.counter));
- if (++random_state.outputblocks >= random_state.gengateinterval) {
+ if (++random_state.outputblocks >=
+ random_state.gengateinterval) {
generator_gate();
random_state.outputblocks = 0;
}
@@ -390,12 +287,13 @@ read_random_real(void *buf, u_int count)
}
else {
if (!cur) {
- random_state.counter++;
- yarrow_encrypt(&random_state.key, &random_state.counter,
- &genval, sizeof(random_state.counter));
+ random_state.counter[0]++;
+ yarrow_encrypt(&random_state.key, random_state.counter,
+ &genval);
memcpy(buf, &genval, count);
cur = sizeof(random_state.counter) - count;
- if (++random_state.outputblocks >= random_state.gengateinterval) {
+ if (++random_state.outputblocks >=
+ random_state.gengateinterval) {
generator_gate();
random_state.outputblocks = 0;
}
@@ -414,38 +312,10 @@ read_random_real(void *buf, u_int count)
return retval;
}
-void
-write_random(void *buf, u_int count)
-{
- u_int i;
-
- /* Break the input up into HARVESTSIZE chunks.
- * The writer has too much control here, so "estimate" the
- * the entropy as zero.
- */
- for (i = 0; i < count; i += HARVESTSIZE) {
- random_harvest_internal(get_cyclecount(), (char *)buf + i,
- HARVESTSIZE, 0, 0, RANDOM_WRITE);
- }
-
- /* Maybe the loop iterated at least once */
- if (i > count)
- i -= HARVESTSIZE;
-
- /* Get the last bytes even if the input length is not
- * a multiple of HARVESTSIZE.
- */
- count %= HARVESTSIZE;
- if (count) {
- random_harvest_internal(get_cyclecount(), (char *)buf + i,
- count, 0, 0, RANDOM_WRITE);
- }
-}
-
static void
generator_gate(void)
{
- int i;
+ u_int i;
u_char temp[KEYSIZE];
#ifdef DEBUG
@@ -455,12 +325,12 @@ generator_gate(void)
#endif
for (i = 0; i < KEYSIZE; i += sizeof(random_state.counter)) {
- random_state.counter++;
- yarrow_encrypt(&random_state.key, &random_state.counter,
- &(temp[i]), sizeof(random_state.counter));
+ random_state.counter[0]++;
+ yarrow_encrypt(&random_state.key, random_state.counter,
+ &(temp[i]));
}
- yarrow_encrypt_init(&random_state.key, temp, KEYSIZE);
+ yarrow_encrypt_init(&random_state.key, temp);
memset((void *)temp, 0, KEYSIZE);
#ifdef DEBUG
@@ -470,43 +340,6 @@ generator_gate(void)
#endif
}
-/* Entropy harvesting routine. This is supposed to be fast; do
- * not do anything slow in here!
- */
-
-static void
-random_harvest_internal(u_int64_t somecounter, void *entropy, u_int count,
- u_int bits, u_int frac, enum esource origin)
-{
- struct harvest *harvest;
- int newhead;
-
- newhead = (harvestring.head + 1) & HARVEST_RING_MASK;
-
- if (newhead != harvestring.tail) {
-
- /* Add the harvested data to the ring buffer */
-
- harvest = &harvestring.data[harvestring.head];
-
- /* Stuff the harvested data into the ring */
- harvest->somecounter = somecounter;
- count = count > HARVESTSIZE ? HARVESTSIZE : count;
- memcpy(harvest->entropy, entropy, count);
- harvest->size = count;
- harvest->bits = bits;
- harvest->frac = frac;
- harvest->source = origin < ENTROPYSOURCE ? origin : 0;
-
- /* Bump the ring counter. This action is assumed
- * to be atomic.
- */
- harvestring.head = newhead;
-
- }
-
-}
-
/* Helper routine to perform explicit reseeds */
void
random_reseed(void)
diff --git a/sys/dev/random/yarrow.h b/sys/dev/random/yarrow.h
index d605356..7c603c7 100644
--- a/sys/dev/random/yarrow.h
+++ b/sys/dev/random/yarrow.h
@@ -26,42 +26,25 @@
* $FreeBSD$
*/
-/* #define ENTROPYSOURCE nn entropy sources (actually classes)
- * This is properly defined in
- * an enum in sys/random.h
+/* This contains Yarrow-specific declarations.
+ * See http://www.counterpane.com/yarrow.html
*/
-/* The ring size _MUST_ be a power of 2 */
-#define HARVEST_RING_SIZE 1024 /* harvest ring buffer size */
-#define HARVEST_RING_MASK (HARVEST_RING_SIZE - 1)
-
#define TIMEBIN 16 /* max value for Pt/t */
-#define HARVESTSIZE 16 /* max size of each harvested entropy unit */
-
#define FAST 0
#define SLOW 1
-int random_init(void);
-void random_deinit(void);
-void random_init_harvester(void (*)(u_int64_t, void *, u_int, u_int, u_int, enum esource), u_int (*)(void *, u_int));
-void random_deinit_harvester(void);
-void random_set_wakeup_exit(void *);
-
-void random_reseed(void);
-
-u_int read_random_real(void *, 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.
+ * Exactly one will be instantiated.
*/
struct random_state {
- u_int64_t counter; /* C */
+ u_int64_t counter[4]; /* C - 256 bits */
struct yarrowkey key; /* K */
- int gengateinterval; /* Pg */
- int bins; /* Pt/t */
- int outputblocks; /* count output blocks for gates */
+ u_int gengateinterval; /* Pg */
+ u_int bins; /* Pt/t */
+ u_int outputblocks; /* count output blocks for gates */
u_int slowoverthresh; /* slow pool overthreshhold reseed count */
struct pool {
struct source {
@@ -72,10 +55,7 @@ struct random_state {
u_int thresh; /* pool reseed threshhold */
struct yarrowhash hash; /* accumulated entropy */
} pool[2]; /* pool[0] is fast, pool[1] is slow */
- int which; /* toggle - shows the current insertion pool */
- int seeded; /* 0 causes blocking 1 allows normal output */
- struct selinfo rsel; /* For poll(2) */
- u_char raw[HARVESTSIZE];/* Raw buffer for checking */
+ u_int which; /* toggle - sets the current insertion pool */
};
extern struct random_state random_state;
OpenPOWER on IntegriCloud