summaryrefslogtreecommitdiffstats
path: root/sys/dev/random
diff options
context:
space:
mode:
authormarkm <markm@FreeBSD.org>2013-08-26 18:29:51 +0000
committermarkm <markm@FreeBSD.org>2013-08-26 18:29:51 +0000
commite007bbae78703d83fd29b3ba2507dfcac7e45b44 (patch)
treec6b9fa1a072b3a044fc794152e9ae4ec68733c7d /sys/dev/random
parentbd5fc148c56b178ea549ad2e722738a8d6d81503 (diff)
downloadFreeBSD-src-e007bbae78703d83fd29b3ba2507dfcac7e45b44.zip
FreeBSD-src-e007bbae78703d83fd29b3ba2507dfcac7e45b44.tar.gz
Snapshot of current work;
1) Clean up namespace; only use "Yarrow" where it is Yarrow-specific or close enough to the Yarrow algorithm. For the rest use a neutral name. 2) Tidy up headers; put private stuff in private places. More could be done here. 3) Streamline the hashing/encryption; no need for a 256-bit counter; 128 bits will last for long enough. There are bits of debug code lying around; these will be removed at a later stage.
Diffstat (limited to 'sys/dev/random')
-rw-r--r--sys/dev/random/harvest.c6
-rw-r--r--sys/dev/random/hash.c28
-rw-r--r--sys/dev/random/hash.h19
-rw-r--r--sys/dev/random/randomdev_soft.c156
-rw-r--r--sys/dev/random/randomdev_soft.h27
-rw-r--r--sys/dev/random/yarrow.c173
-rw-r--r--sys/dev/random/yarrow.h37
7 files changed, 253 insertions, 193 deletions
diff --git a/sys/dev/random/harvest.c b/sys/dev/random/harvest.c
index a1ff8dd..473e429 100644
--- a/sys/dev/random/harvest.c
+++ b/sys/dev/random/harvest.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000-2004 Mark R V Murray
+ * Copyright (c) 2000-2013 Mark R V Murray
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -60,7 +60,7 @@ static int (*read_func)(void *, int) = read_random_phony;
/* Initialise the harvester at load time */
void
-random_yarrow_init_harvester(void (*reaper)(u_int64_t, const void *, u_int,
+randomdev_init_harvester(void (*reaper)(u_int64_t, const void *, u_int,
u_int, u_int, enum esource), int (*reader)(void *, int))
{
reap_func = reaper;
@@ -69,7 +69,7 @@ random_yarrow_init_harvester(void (*reaper)(u_int64_t, const void *, u_int,
/* Deinitialise the harvester at unload time */
void
-random_yarrow_deinit_harvester(void)
+randomdev_deinit_harvester(void)
{
reap_func = NULL;
read_func = read_random_phony;
diff --git a/sys/dev/random/hash.c b/sys/dev/random/hash.c
index 611f866..cf0feaa 100644
--- a/sys/dev/random/hash.c
+++ b/sys/dev/random/hash.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000-2004 Mark R V Murray
+ * Copyright (c) 2000-2013 Mark R V Murray
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,46 +36,46 @@ __FBSDID("$FreeBSD$");
#include <dev/random/hash.h>
-/* initialise the hash */
+/* Initialise the hash */
void
-yarrow_hash_init(struct yarrowhash *context)
+randomdev_hash_init(struct randomdev_hash *context)
{
SHA256_Init(&context->sha);
}
-/* iterate the hash */
+/* Iterate the hash */
void
-yarrow_hash_iterate(struct yarrowhash *context, void *data, size_t size)
+randomdev_hash_iterate(struct randomdev_hash *context, void *data, size_t size)
{
SHA256_Update(&context->sha, data, size);
}
-/* Conclude by returning the hash in the supplied /buf/ which must be
+/* Conclude by returning the hash in the supplied <*buf> which must be
* KEYSIZE bytes long.
*/
void
-yarrow_hash_finish(struct yarrowhash *context, void *buf)
+randomdev_hash_finish(struct randomdev_hash *context, void *buf)
{
SHA256_Final(buf, &context->sha);
}
/* Initialise the encryption routine by setting up the key schedule
- * from the supplied /data/ which must be KEYSIZE bytes of binary
- * data.
+ * from the supplied <*data> which must be KEYSIZE bytes of binary
+ * data. Use CBC mode for better avalanche.
*/
void
-yarrow_encrypt_init(struct yarrowkey *context, void *data)
+randomdev_encrypt_init(struct randomdev_key *context, void *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.
- * KEYSIZE bytes are encrypted from /d_in/ to /d_out/.
+ * <length> bytes are encrypted from <*d_in> to <*d_out>. <length> must be
+ * a multiple of BLOCKSIZE.
*/
void
-yarrow_encrypt(struct yarrowkey *context, void *d_in, void *d_out)
+randomdev_encrypt(struct randomdev_key *context, void *d_in, void *d_out, unsigned length)
{
- rijndael_blockEncrypt(&context->cipher, &context->key, d_in,
- KEYSIZE*8, d_out);
+ rijndael_blockEncrypt(&context->cipher, &context->key, d_in, length*8, d_out);
}
diff --git a/sys/dev/random/hash.h b/sys/dev/random/hash.h
index 8580d14..62f116d 100644
--- a/sys/dev/random/hash.h
+++ b/sys/dev/random/hash.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000-2004 Mark R V Murray
+ * Copyright (c) 2000-2013 Mark R V Murray
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,19 +26,20 @@
* $FreeBSD$
*/
-#define KEYSIZE 32 /* (in bytes) 32 bytes == 256 bits */
+#define KEYSIZE 32 /* (in bytes) == 256 bits */
+#define BLOCKSIZE 16 /* (in bytes) == 128 bits */
-struct yarrowhash { /* Big! Make static! */
+struct randomdev_hash { /* Big! Make static! */
SHA256_CTX sha;
};
-struct yarrowkey { /* Big! Make static! */
+struct randomdev_key { /* Big! Make static! */
keyInstance key; /* Key schedule */
cipherInstance cipher; /* Rijndael internal */
};
-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 *);
-void yarrow_encrypt(struct yarrowkey *context, void *, void *);
+void randomdev_hash_init(struct randomdev_hash *);
+void randomdev_hash_iterate(struct randomdev_hash *, void *, size_t);
+void randomdev_hash_finish(struct randomdev_hash *, void *);
+void randomdev_encrypt_init(struct randomdev_key *, void *);
+void randomdev_encrypt(struct randomdev_key *context, void *, void *, unsigned);
diff --git a/sys/dev/random/randomdev_soft.c b/sys/dev/random/randomdev_soft.c
index 7e537fe..9e5a5fd 100644
--- a/sys/dev/random/randomdev_soft.c
+++ b/sys/dev/random/randomdev_soft.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000-2009 Mark R V Murray
+ * Copyright (c) 2000-2013 Mark R V Murray
* Copyright (c) 2004 Robert N. M. Watson
* All rights reserved.
*
@@ -26,6 +26,12 @@
*
*/
+#if !defined(YARROW_RNG) && !defined(FORTUNA_RNG)
+#define YARROW_RNG
+#elif defined(YARROW_RNG) && defined(FORTUNA_RNG)
+#error "Must define either YARROW_RNG or FORTUNA_RNG"
+#endif
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -54,30 +60,56 @@ __FBSDID("$FreeBSD$");
#include <dev/random/random_adaptors.h>
#include <dev/random/randomdev.h>
#include <dev/random/randomdev_soft.h>
+#if defined(YARROW_RNG)
+#include <dev/random/yarrow.h>
+#endif
+#if defined(FORTUNA_RNG)
+#include <dev/random/fortuna.h>
+#endif
#define RANDOM_FIFO_MAX 256 /* How many events to queue up */
static void random_kthread(void *);
-static void
-random_harvest_internal(u_int64_t, const void *, u_int,
+static void random_harvest_internal(u_int64_t, const void *, u_int,
u_int, u_int, enum esource);
-static int random_yarrow_poll(int event,struct thread *td);
-static int random_yarrow_block(int flag);
-static void random_yarrow_flush_reseed(void);
+static int randomdev_poll(int event, struct thread *td);
+static int randomdev_block(int flag);
+static void randomdev_flush_reseed(void);
-struct random_adaptor random_yarrow = {
+#if defined(YARROW_RNG)
+static struct random_adaptor random_context = {
.ident = "Software, Yarrow",
- .init = random_yarrow_init,
- .deinit = random_yarrow_deinit,
- .block = random_yarrow_block,
+ .init = randomdev_init,
+ .deinit = randomdev_deinit,
+ .block = randomdev_block,
.read = random_yarrow_read,
- .write = random_yarrow_write,
- .poll = random_yarrow_poll,
- .reseed = random_yarrow_flush_reseed,
- .seeded = 1,
+ .write = randomdev_write,
+ .poll = randomdev_poll,
+ .reseed = randomdev_flush_reseed,
+ .seeded = 0,
+};
+#define RANDOM_MODULE_NAME yarrow
+#define RANDOM_CSPRNG_NAME "yarrow"
+#endif
+
+#if defined(FORTUNA_RNG)
+static struct random_adaptor random_context = {
+ .ident = "Software, Fortuna",
+ .init = randomdev_init,
+ .deinit = randomdev_deinit,
+ .block = randomdev_block,
+ .read = random_fortuna_read,
+ .write = randomdev_write,
+ .poll = randomdev_poll,
+ .reseed = randomdev_flush_reseed,
+ .seeded = 0,
};
+#define RANDOM_MODULE_NAME fortuna
+#define RANDOM_CSPRNG_NAME "fortuna"
-MALLOC_DEFINE(M_ENTROPY, "entropy", "Entropy harvesting buffers");
+#endif
+
+MALLOC_DEFINE(M_ENTROPY, "entropy", "Entropy harvesting buffers for " RANDOM_CSPRNG_NAME);
/*
* The harvest mutex protects the consistency of the entropy fifos and
@@ -116,16 +148,20 @@ random_check_boolean(SYSCTL_HANDLER_ARGS)
return sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
}
-/* ARGSUSED */
void
-random_yarrow_init(void)
+randomdev_init(void)
{
int error, i;
struct harvest *np;
struct sysctl_oid *random_sys_o, *random_sys_harvest_o;
enum esource e;
+#if defined(YARROW_RNG)
random_yarrow_init_alg(&random_clist);
+#endif
+#if defined(FORTUNA_RNG)
+ random_fortuna_init_alg(&random_clist);
+#endif
random_sys_o = SYSCTL_ADD_NODE(&random_clist,
SYSCTL_STATIC_CHILDREN(_kern_random),
@@ -135,7 +171,7 @@ random_yarrow_init(void)
SYSCTL_ADD_PROC(&random_clist,
SYSCTL_CHILDREN(random_sys_o),
OID_AUTO, "seeded", CTLTYPE_INT | CTLFLAG_RW,
- &random_yarrow.seeded, 1, random_check_boolean, "I",
+ &random_context.seeded, 1, random_check_boolean, "I",
"Seeded State");
random_sys_harvest_o = SYSCTL_ADD_NODE(&random_clist,
@@ -156,13 +192,18 @@ random_yarrow_init(void)
SYSCTL_ADD_PROC(&random_clist,
SYSCTL_CHILDREN(random_sys_harvest_o),
OID_AUTO, "interrupt", CTLTYPE_INT | CTLFLAG_RW,
- &harvest.interrupt, 1, random_check_boolean, "I",
+ &harvest.interrupt, 0, random_check_boolean, "I",
"Harvest IRQ entropy");
SYSCTL_ADD_PROC(&random_clist,
SYSCTL_CHILDREN(random_sys_harvest_o),
OID_AUTO, "swi", CTLTYPE_INT | CTLFLAG_RW,
&harvest.swi, 0, random_check_boolean, "I",
"Harvest SWI entropy");
+ SYSCTL_ADD_PROC(&random_clist,
+ SYSCTL_CHILDREN(random_sys_harvest_o),
+ OID_AUTO, "namei", CTLTYPE_INT | CTLFLAG_RW,
+ &harvest.namei, 0, random_check_boolean, "I",
+ "Harvest namei cache entropy");
/* Initialise the harvest fifos */
STAILQ_INIT(&emptyfifo.head);
@@ -180,24 +221,23 @@ random_yarrow_init(void)
/* Start the hash/reseed thread */
error = kproc_create(random_kthread, NULL,
- &random_kthread_proc, RFHIGHPID, 0, "yarrow");
+ &random_kthread_proc, RFHIGHPID, 0, RANDOM_CSPRNG_NAME);
if (error != 0)
panic("Cannot create entropy maintenance thread.");
/* Register the randomness harvesting routine */
- random_yarrow_init_harvester(random_harvest_internal,
- random_yarrow_read);
+ randomdev_init_harvester(random_harvest_internal,
+ random_context.read);
}
-/* ARGSUSED */
void
-random_yarrow_deinit(void)
+randomdev_deinit(void)
{
struct harvest *np;
enum esource e;
/* Deregister the randomness harvesting routine */
- random_yarrow_deinit_harvester();
+ randomdev_deinit_harvester();
/*
* Command the hash/reseed thread to end and wait for it to finish
@@ -219,7 +259,12 @@ random_yarrow_deinit(void)
}
}
+#if defined(YARROW_RNG)
random_yarrow_deinit_alg();
+#endif
+#if defined(FORTUNA_RNG)
+ random_fortuna_deinit_alg();
+#endif
mtx_destroy(&harvest_mtx);
@@ -298,10 +343,7 @@ random_harvest_internal(u_int64_t somecounter, const void *entropy,
{
struct harvest *event;
- KASSERT(origin == RANDOM_START || origin == RANDOM_WRITE ||
- origin == RANDOM_KEYBOARD || origin == RANDOM_MOUSE ||
- origin == RANDOM_NET || origin == RANDOM_INTERRUPT ||
- origin == RANDOM_PURE,
+ KASSERT(origin >= RANDOM_START && origin <= RANDOM_PURE,
("random_harvest_internal: origin %d invalid\n", origin));
/* Lockless read to avoid lock operations if fifo is full. */
@@ -311,12 +353,13 @@ random_harvest_internal(u_int64_t somecounter, const void *entropy,
mtx_lock_spin(&harvest_mtx);
/*
- * Don't make the harvest queues too big - help to prevent low-grade
+ * Don't make the harvest queues too big - help to thwart low-grade
* entropy swamping
*/
if (harvestfifo[origin].count < RANDOM_FIFO_MAX) {
event = STAILQ_FIRST(&emptyfifo.head);
if (event != NULL) {
+ count = MIN(count, HARVESTSIZE);
/* Add the harvested data to the fifo */
STAILQ_REMOVE_HEAD(&emptyfifo.head, next);
harvestfifo[origin].count++;
@@ -326,10 +369,20 @@ random_harvest_internal(u_int64_t somecounter, const void *entropy,
event->frac = frac;
event->source = origin;
- /* XXXX Come back and make this dynamic! */
- count = MIN(count, HARVESTSIZE);
memcpy(event->entropy, entropy, count);
+#if 1
+ {
+ int i;
+ printf("Harvest:%16jX ", event->somecounter);
+ for (i = 0; i < event->size; i++)
+ printf("%02X", event->entropy[i]);
+ for (; i < 16; i++)
+ printf(" ");
+ printf(" %2d 0x%2X.%03X %02X\n", event->size, event->bits, event->frac, event->source);
+ }
+#endif
+
STAILQ_INSERT_TAIL(&harvestfifo[origin].head,
event, next);
}
@@ -338,7 +391,7 @@ random_harvest_internal(u_int64_t somecounter, const void *entropy,
}
void
-random_yarrow_write(void *buf, int count)
+randomdev_write(void *buf, int count)
{
int i;
u_int chunk;
@@ -357,46 +410,46 @@ random_yarrow_write(void *buf, int count)
}
void
-random_yarrow_unblock(void)
+randomdev_unblock(void)
{
- if (!random_yarrow.seeded) {
- random_yarrow.seeded = 1;
- selwakeuppri(&random_yarrow.rsel, PUSER);
- wakeup(&random_yarrow);
+ if (!random_context.seeded) {
+ random_context.seeded = 1;
+ selwakeuppri(&random_context.rsel, PUSER);
+ wakeup(&random_context);
}
(void)atomic_cmpset_int(&arc4rand_iniseed_state, ARC4_ENTR_NONE,
ARC4_ENTR_HAVE);
}
static int
-random_yarrow_poll(int events, struct thread *td)
+randomdev_poll(int events, struct thread *td)
{
int revents = 0;
mtx_lock(&random_reseed_mtx);
- if (random_yarrow.seeded)
+ if (random_context.seeded)
revents = events & (POLLIN | POLLRDNORM);
else
- selrecord(td, &random_yarrow.rsel);
+ selrecord(td, &random_context.rsel);
mtx_unlock(&random_reseed_mtx);
return revents;
}
static int
-random_yarrow_block(int flag)
+randomdev_block(int flag)
{
int error = 0;
mtx_lock(&random_reseed_mtx);
/* Blocking logic */
- while (!random_yarrow.seeded && !error) {
+ while (!random_context.seeded && !error) {
if (flag & O_NONBLOCK)
error = EWOULDBLOCK;
else {
printf("Entropy device is blocking.\n");
- error = msleep(&random_yarrow,
+ error = msleep(&random_context,
&random_reseed_mtx,
PUSER | PCATCH, "block", 0);
}
@@ -408,23 +461,28 @@ random_yarrow_block(int flag)
/* Helper routine to perform explicit reseeds */
static void
-random_yarrow_flush_reseed(void)
+randomdev_flush_reseed(void)
{
/* Command a entropy queue flush and wait for it to finish */
random_kthread_control = 1;
while (random_kthread_control)
pause("-", hz / 10);
+#if defined(YARROW_RNG)
random_yarrow_reseed();
+#endif
+#if defined(FORTUNA_RNG)
+ random_fortuna_reseed();
+#endif
}
static int
-yarrow_modevent(module_t mod, int type, void *unused)
+randomdev_modevent(module_t mod, int type, void *unused)
{
switch (type) {
case MOD_LOAD:
- random_adaptor_register("yarrow", &random_yarrow);
+ random_adaptor_register(RANDOM_CSPRNG_NAME, &random_context);
/*
* For statically built kernels that contain both device
* random and options PADLOCK_RNG/RDRAND_RNG/etc..,
@@ -437,11 +495,11 @@ yarrow_modevent(module_t mod, int type, void *unused)
* (by dependency). This event handler is there to delay
* creation of /dev/{u,}random and attachment of this *_rng.ko.
*/
- EVENTHANDLER_INVOKE(random_adaptor_attach, &random_yarrow);
+ EVENTHANDLER_INVOKE(random_adaptor_attach, &random_context);
return (0);
}
return (EINVAL);
}
-RANDOM_ADAPTOR_MODULE(yarrow, yarrow_modevent, 1);
+RANDOM_ADAPTOR_MODULE(RANDOM_MODULE_NAME, randomdev_modevent, 1);
diff --git a/sys/dev/random/randomdev_soft.h b/sys/dev/random/randomdev_soft.h
index 2007694..c92a5a8 100644
--- a/sys/dev/random/randomdev_soft.h
+++ b/sys/dev/random/randomdev_soft.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000-2004 Mark R V Murray
+ * Copyright (c) 2000-2013 Mark R V Murray
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,9 +35,6 @@
* 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)
@@ -51,34 +48,28 @@ MALLOC_DECLARE(M_ENTROPY);
*/
struct harvest {
uintmax_t somecounter; /* fast counter for clock jitter */
- u_char entropy[HARVESTSIZE]; /* the harvested entropy */
+ uint8_t entropy[HARVESTSIZE]; /* the harvested entropy */
u_int size, bits, frac; /* stats about the entropy */
enum esource source; /* stats about the entropy */
STAILQ_ENTRY(harvest) next; /* next item on the list */
};
-void random_yarrow_init(void);
-void random_yarrow_deinit(void);
+void randomdev_init(void);
+void randomdev_deinit(void);
-int random_yarrow_read(void *, int);
-void random_yarrow_write(void *, int);
+void randomdev_write(void *, int);
-void random_yarrow_init_harvester(void (*)(u_int64_t, const void *, u_int,
+void randomdev_init_harvester(void (*)(u_int64_t, const void *, u_int,
u_int, u_int, enum esource), int (*)(void *, int));
-void random_yarrow_deinit_harvester(void);
+void randomdev_deinit_harvester(void);
void random_set_wakeup_exit(void *);
void random_process_event(struct harvest *event);
-void random_yarrow_reseed(void);
-void random_yarrow_unblock(void);
-
-void random_yarrow_init_alg(struct sysctl_ctx_list *);
-void random_yarrow_deinit_alg(void);
+void randomdev_unblock(void);
-extern struct random_adaptor random_yarrow;
extern struct mtx random_reseed_mtx;
-/* If this was c++, this would be a template */
+/* If this was C++, the macro below would be a template */
#define RANDOM_CHECK_UINT(name, min, max) \
static int \
random_check_uint_##name(SYSCTL_HANDLER_ARGS) \
diff --git a/sys/dev/random/yarrow.c b/sys/dev/random/yarrow.c
index 09f079a..21913f9 100644
--- a/sys/dev/random/yarrow.c
+++ b/sys/dev/random/yarrow.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000-2004 Mark R V Murray
+ * Copyright (c) 2000-2013 Mark R V Murray
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -45,21 +45,68 @@ __FBSDID("$FreeBSD$");
#include <dev/random/randomdev_soft.h>
#include <dev/random/yarrow.h>
+#define TIMEBIN 16 /* max value for Pt/t */
+
+#define FAST 0
+#define SLOW 1
+
+/* This is the beastie that needs protecting. It contains all of the
+ * state that we are excited about.
+ * Exactly one is instantiated.
+ */
+static struct random_state {
+ union {
+ uint8_t byte[BLOCKSIZE];
+ uint64_t qword[BLOCKSIZE/sizeof(uint64_t)];
+ } counter; /* C */
+ struct randomdev_key key; /* K */
+ 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 {
+ u_int bits; /* estimated bits of entropy */
+ u_int frac; /* fractional bits of entropy
+ (given as 1024/n) */
+ } source[ENTROPYSOURCE];
+ u_int thresh; /* pool reseed threshhold */
+ struct randomdev_hash hash; /* accumulated entropy */
+ } pool[2]; /* pool[0] is fast, pool[1] is slow */
+ u_int which; /* toggle - sets the current insertion pool */
+} random_state;
+
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(fastthresh, (BLOCKSIZE*8)/4, (BLOCKSIZE*8)); /* Bit counts */
+RANDOM_CHECK_UINT(slowthresh, (BLOCKSIZE*8)/4, (BLOCKSIZE*8)); /* Bit counts */
RANDOM_CHECK_UINT(slowoverthresh, 1, 5);
-/* Structure holding the entropy state */
-static struct random_state random_state;
-
static void generator_gate(void);
static void reseed(u_int);
/* The reseed thread mutex */
struct mtx random_reseed_mtx;
+/* 128-bit C = 0 */
+/* Nothing to see here, folks, just an ugly mess. */
+static void
+clear_counter(void)
+{
+ random_state.counter.qword[0] = 0UL;
+ random_state.counter.qword[1] = 0UL;
+}
+
+/* 128-bit C = C + 1 */
+/* Nothing to see here, folks, just an ugly mess. */
+static void
+increment_counter(void)
+{
+ random_state.counter.qword[0]++;
+ if (!random_state.counter.qword[0])
+ random_state.counter.qword[1]++;
+}
+
/* Process a single stochastic event off the harvest queue */
void
random_process_event(struct harvest *event)
@@ -71,13 +118,13 @@ random_process_event(struct harvest *event)
/* 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,
+ randomdev_hash_iterate(&random_state.pool[pl].hash, event->entropy,
sizeof(event->entropy));
- yarrow_hash_iterate(&random_state.pool[pl].hash, &event->somecounter,
+ randomdev_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;
+ source->bits += event->bits + (source->frac >> 12); /* bits + frac/0x1000 */
+ source->frac &= 0xFFF; /* Keep the fractional bits */
/* Count the over-threshold sources in each pool */
for (pl = 0; pl < 2; pl++) {
@@ -132,14 +179,14 @@ random_yarrow_init_alg(struct sysctl_ctx_list *clist)
SYSCTL_ADD_PROC(clist,
SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO,
"fastthresh", CTLTYPE_INT|CTLFLAG_RW,
- &random_state.pool[0].thresh, (3*BLOCKSIZE)/4,
+ &random_state.pool[0].thresh, (3*(BLOCKSIZE*8))/4,
random_check_uint_fastthresh, "I",
"Fast reseed threshold");
SYSCTL_ADD_PROC(clist,
SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO,
"slowthresh", CTLTYPE_INT|CTLFLAG_RW,
- &random_state.pool[1].thresh, BLOCKSIZE,
+ &random_state.pool[1].thresh, (BLOCKSIZE*8),
random_check_uint_slowthresh, "I",
"Slow reseed threshold");
@@ -152,21 +199,20 @@ random_yarrow_init_alg(struct sysctl_ctx_list *clist)
random_state.gengateinterval = 10;
random_state.bins = 10;
- random_state.pool[0].thresh = (3*BLOCKSIZE)/4;
- random_state.pool[1].thresh = BLOCKSIZE;
+ random_state.pool[0].thresh = (3*(BLOCKSIZE*8))/4;
+ random_state.pool[1].thresh = (BLOCKSIZE*8);
random_state.slowoverthresh = 2;
random_state.which = FAST;
/* Initialise the fast and slow entropy pools */
for (i = 0; i < 2; i++)
- yarrow_hash_init(&random_state.pool[i].hash);
+ randomdev_hash_init(&random_state.pool[i].hash);
/* Clear the counter */
- for (i = 0; i < 4; i++)
- random_state.counter[i] = 0;
+ clear_counter();
/* Set up a lock for the reseed process */
- mtx_init(&random_reseed_mtx, "random reseed", NULL, MTX_DEF);
+ mtx_init(&random_reseed_mtx, "Yarrow reseed", NULL, MTX_DEF);
}
void
@@ -181,10 +227,10 @@ reseed(u_int fastslow)
/* Interrupt-context stack is a limited resource; make large
* structures static.
*/
- static u_char v[TIMEBIN][KEYSIZE]; /* v[i] */
- static struct yarrowhash context;
- u_char hash[KEYSIZE]; /* h' */
- u_char temp[KEYSIZE];
+ static uint8_t v[TIMEBIN][KEYSIZE]; /* v[i] */
+ static struct randomdev_hash context;
+ uint8_t hash[KEYSIZE]; /* h' */
+ uint8_t temp[KEYSIZE];
u_int i;
enum esource j;
@@ -193,15 +239,15 @@ reseed(u_int fastslow)
/* 1. Hash the accumulated entropy into v[0] */
- yarrow_hash_init(&context);
+ randomdev_hash_init(&context);
/* Feed the slow pool hash in if slow */
if (fastslow == SLOW)
- yarrow_hash_iterate(&context,
+ randomdev_hash_iterate(&context,
&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]);
+ sizeof(struct randomdev_hash));
+ randomdev_hash_iterate(&context,
+ &random_state.pool[FAST].hash, sizeof(struct randomdev_hash));
+ randomdev_hash_finish(&context, v[0]);
/* 2. Compute hash values for all v. _Supposed_ to be computationally
* intensive.
@@ -210,34 +256,33 @@ reseed(u_int fastslow)
if (random_state.bins > TIMEBIN)
random_state.bins = TIMEBIN;
for (i = 1; i < random_state.bins; i++) {
- yarrow_hash_init(&context);
+ randomdev_hash_init(&context);
/* v[i] #= h(v[i - 1]) */
- yarrow_hash_iterate(&context, v[i - 1], KEYSIZE);
+ randomdev_hash_iterate(&context, v[i - 1], KEYSIZE);
/* v[i] #= h(v[0]) */
- yarrow_hash_iterate(&context, v[0], KEYSIZE);
+ randomdev_hash_iterate(&context, v[0], KEYSIZE);
/* v[i] #= h(i) */
- yarrow_hash_iterate(&context, &i, sizeof(u_int));
+ randomdev_hash_iterate(&context, &i, sizeof(u_int));
/* Return the hashval */
- yarrow_hash_finish(&context, v[i]);
+ randomdev_hash_finish(&context, v[i]);
}
/* 3. Compute a new key; h' is the identity function here;
* it is not being ignored!
*/
- yarrow_hash_init(&context);
- yarrow_hash_iterate(&context, &random_state.key, KEYSIZE);
+ randomdev_hash_init(&context);
+ randomdev_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);
+ randomdev_hash_iterate(&context, &v[i], KEYSIZE);
+ randomdev_hash_finish(&context, temp);
+ randomdev_encrypt_init(&random_state.key, temp);
/* 4. Recompute the 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));
+ clear_counter();
+ randomdev_encrypt(&random_state.key, random_state.counter.byte, temp, BLOCKSIZE);
+ memcpy(random_state.counter.byte, temp, BLOCKSIZE);
/* 5. Reset entropy estimate accumulators to zero */
@@ -258,7 +303,7 @@ reseed(u_int fastslow)
/* XXX Not done here yet */
/* Unblock the device if it was blocked due to being unseeded */
- random_yarrow_unblock();
+ randomdev_unblock();
/* Release the reseed mutex */
mtx_unlock(&random_reseed_mtx);
@@ -270,7 +315,7 @@ random_yarrow_read(void *buf, int count)
{
static int cur = 0;
static int gate = 1;
- static u_char genval[KEYSIZE];
+ static uint8_t genval[KEYSIZE];
size_t tomove;
int i;
int retval;
@@ -283,16 +328,14 @@ random_yarrow_read(void *buf, int count)
random_state.outputblocks = 0;
gate = 0;
}
- if (count > 0 && (size_t)count >= sizeof(random_state.counter)) {
+ if (count > 0 && (size_t)count >= BLOCKSIZE) {
retval = 0;
- for (i = 0; i < count; i += (int)sizeof(random_state.counter)) {
- random_state.counter[0]++;
- yarrow_encrypt(&random_state.key, random_state.counter,
- genval);
- tomove = min(count - i, sizeof(random_state.counter));
+ for (i = 0; i < count; i += BLOCKSIZE) {
+ increment_counter();
+ randomdev_encrypt(&random_state.key, random_state.counter.byte, genval, BLOCKSIZE);
+ tomove = MIN(count - i, BLOCKSIZE);
memcpy((char *)buf + i, genval, tomove);
- if (++random_state.outputblocks >=
- random_state.gengateinterval) {
+ if (++random_state.outputblocks >= random_state.gengateinterval) {
generator_gate();
random_state.outputblocks = 0;
}
@@ -302,13 +345,11 @@ random_yarrow_read(void *buf, int count)
}
else {
if (!cur) {
- random_state.counter[0]++;
- yarrow_encrypt(&random_state.key, random_state.counter,
- genval);
+ increment_counter();
+ randomdev_encrypt(&random_state.key, random_state.counter.byte, genval, BLOCKSIZE);
memcpy(buf, genval, (size_t)count);
- cur = (int)sizeof(random_state.counter) - count;
- if (++random_state.outputblocks >=
- random_state.gengateinterval) {
+ cur = BLOCKSIZE - count;
+ if (++random_state.outputblocks >= random_state.gengateinterval) {
generator_gate();
random_state.outputblocks = 0;
}
@@ -316,9 +357,7 @@ random_yarrow_read(void *buf, int count)
}
else {
retval = MIN(cur, count);
- memcpy(buf,
- &genval[(int)sizeof(random_state.counter) - cur],
- (size_t)retval);
+ memcpy(buf, &genval[BLOCKSIZE - cur], (size_t)retval);
cur -= retval;
}
}
@@ -330,17 +369,15 @@ static void
generator_gate(void)
{
u_int i;
- u_char temp[KEYSIZE];
+ uint8_t temp[KEYSIZE];
- for (i = 0; i < KEYSIZE; i += sizeof(random_state.counter)) {
- random_state.counter[0]++;
- yarrow_encrypt(&random_state.key, random_state.counter,
- &(temp[i]));
+ for (i = 0; i < KEYSIZE; i += BLOCKSIZE) {
+ increment_counter();
+ randomdev_encrypt(&random_state.key, random_state.counter.byte, temp + i, BLOCKSIZE);
}
- yarrow_encrypt_init(&random_state.key, temp);
+ randomdev_encrypt_init(&random_state.key, temp);
memset((void *)temp, 0, KEYSIZE);
-
}
/* Helper routine to perform explicit reseeds */
diff --git a/sys/dev/random/yarrow.h b/sys/dev/random/yarrow.h
index 558354d..0bde5b5 100644
--- a/sys/dev/random/yarrow.h
+++ b/sys/dev/random/yarrow.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000-2004 Mark R V Murray
+ * Copyright (c) 2000-2013 Mark R V Murray
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,34 +26,7 @@
* $FreeBSD$
*/
-/* This contains Yarrow-specific declarations.
- * See http://www.counterpane.com/yarrow.html
- */
-
-#define TIMEBIN 16 /* max value for Pt/t */
-
-#define FAST 0
-#define SLOW 1
-
-/* 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[4]; /* C - 256 bits */
- struct yarrowkey key; /* K */
- 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 {
- u_int bits; /* estimated bits of entropy */
- u_int frac; /* fractional bits of entropy
- (given as 1024/n) */
- } source[ENTROPYSOURCE];
- u_int thresh; /* pool reseed threshhold */
- struct yarrowhash hash; /* accumulated entropy */
- } pool[2]; /* pool[0] is fast, pool[1] is slow */
- u_int which; /* toggle - sets the current insertion pool */
-};
+void random_yarrow_init_alg(struct sysctl_ctx_list *);
+void random_yarrow_deinit_alg(void);
+int random_yarrow_read(void *, int);
+void random_yarrow_reseed(void);
OpenPOWER on IntegriCloud