svn commit: r254927 - projects/random_number_generator/sys/dev/random

Mark Murray markm at FreeBSD.org
Mon Aug 26 18:29:53 UTC 2013


Author: markm
Date: Mon Aug 26 18:29:51 2013
New Revision: 254927
URL: http://svnweb.freebsd.org/changeset/base/254927

Log:
  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.

Modified:
  projects/random_number_generator/sys/dev/random/harvest.c
  projects/random_number_generator/sys/dev/random/hash.c
  projects/random_number_generator/sys/dev/random/hash.h
  projects/random_number_generator/sys/dev/random/randomdev_soft.c
  projects/random_number_generator/sys/dev/random/randomdev_soft.h
  projects/random_number_generator/sys/dev/random/yarrow.c
  projects/random_number_generator/sys/dev/random/yarrow.h

Modified: projects/random_number_generator/sys/dev/random/harvest.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/harvest.c	Mon Aug 26 18:21:04 2013	(r254926)
+++ projects/random_number_generator/sys/dev/random/harvest.c	Mon Aug 26 18:29:51 2013	(r254927)
@@ -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) = r
 
 /* 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 (*reap
 
 /* Deinitialise the harvester at unload time */
 void
-random_yarrow_deinit_harvester(void)
+randomdev_deinit_harvester(void)
 {
 	reap_func = NULL;
 	read_func = read_random_phony;

Modified: projects/random_number_generator/sys/dev/random/hash.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/hash.c	Mon Aug 26 18:21:04 2013	(r254926)
+++ projects/random_number_generator/sys/dev/random/hash.c	Mon Aug 26 18:29:51 2013	(r254927)
@@ -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);
 }

Modified: projects/random_number_generator/sys/dev/random/hash.h
==============================================================================
--- projects/random_number_generator/sys/dev/random/hash.h	Mon Aug 26 18:21:04 2013	(r254926)
+++ projects/random_number_generator/sys/dev/random/hash.h	Mon Aug 26 18:29:51 2013	(r254927)
@@ -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);

Modified: projects/random_number_generator/sys/dev/random/randomdev_soft.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/randomdev_soft.c	Mon Aug 26 18:21:04 2013	(r254926)
+++ projects/random_number_generator/sys/dev/random/randomdev_soft.c	Mon Aug 26 18:29:51 2013	(r254927)
@@ -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 someco
 {
 	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 someco
 	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 someco
 			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 someco
 }
 
 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, 
 		 * (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);

Modified: projects/random_number_generator/sys/dev/random/randomdev_soft.h
==============================================================================
--- projects/random_number_generator/sys/dev/random/randomdev_soft.h	Mon Aug 26 18:21:04 2013	(r254926)
+++ projects/random_number_generator/sys/dev/random/randomdev_soft.h	Mon Aug 26 18:29:51 2013	(r254927)
@@ -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)				\

Modified: projects/random_number_generator/sys/dev/random/yarrow.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/yarrow.c	Mon Aug 26 18:21:04 2013	(r254926)
+++ projects/random_number_generator/sys/dev/random/yarrow.c	Mon Aug 26 18:29:51 2013	(r254927)
@@ -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 *eve
 	/* 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
 	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
 
 	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 */

Modified: projects/random_number_generator/sys/dev/random/yarrow.h
==============================================================================
--- projects/random_number_generator/sys/dev/random/yarrow.h	Mon Aug 26 18:21:04 2013	(r254926)
+++ projects/random_number_generator/sys/dev/random/yarrow.h	Mon Aug 26 18:29:51 2013	(r254927)
@@ -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);


More information about the svn-src-projects mailing list