svn commit: r285422 - in head: share/man/man4 sys/conf sys/dev/random sys/net sys/netgraph

Mark Murray markm at FreeBSD.org
Sun Jul 12 18:14:44 UTC 2015


Author: markm
Date: Sun Jul 12 18:14:38 2015
New Revision: 285422
URL: https://svnweb.freebsd.org/changeset/base/285422

Log:
  * Address review (and add a bit myself).
   - Tweek man page.
   - Remove all mention of RANDOM_FORTUNA. If the system owner wants YARROW or DUMMY, they ask for it, otherwise they get FORTUNA.
   - Tidy up headers a bit.
   - Tidy up declarations a bit.
   - Make static in a couple of places where needed.
   - Move Yarrow/Fortuna SYSINIT/SYSUNINIT to randomdev.c, moving us towards a single file where the algorithm context is used.
   - Get rid of random_*_process_buffer() functions. They were only used in one place each, and are better subsumed into those places.
   - Remove *_post_read() functions as they are stubs everywhere.
   - Assert against buffer size illegalities.
   - Clean up some silly code in the randomdev_read() routine.
   - Make the harvesting more consistent.
   - Make some requested argument name changes.
   - Tidy up and clarify a few comments.
   - Make some requested comment changes.
   - Make some requested macro changes.
  
  * NOTE: the thing calling itself a 'unit test' is not yet a proper
    unit test, but it helps me ensure things work. It may be a proper
    unit test at some time in the future, but for now please don't make
    any assumptions or hold any expectations.
  
  Differential Revision:	https://reviews.freebsd.org/D2025
  Approved by:	so (/dev/random blanket)

Modified:
  head/share/man/man4/random.4
  head/sys/conf/NOTES
  head/sys/dev/random/build.sh
  head/sys/dev/random/fortuna.c
  head/sys/dev/random/hash.h
  head/sys/dev/random/random_harvestq.c
  head/sys/dev/random/randomdev.c
  head/sys/dev/random/randomdev.h
  head/sys/dev/random/unit_test.c
  head/sys/dev/random/unit_test.h
  head/sys/dev/random/yarrow.c
  head/sys/net/if_tun.c
  head/sys/netgraph/ng_iface.c

Modified: head/share/man/man4/random.4
==============================================================================
--- head/share/man/man4/random.4	Sun Jul 12 17:28:31 2015	(r285421)
+++ head/share/man/man4/random.4	Sun Jul 12 18:14:38 2015	(r285422)
@@ -62,7 +62,7 @@ This sysctl will not return
 random bytes unless
 the
 .Xr random 4
-is seeded.
+device is seeded.
 .Pp
 This initial seeding
 of random number generators

Modified: head/sys/conf/NOTES
==============================================================================
--- head/sys/conf/NOTES	Sun Jul 12 17:28:31 2015	(r285421)
+++ head/sys/conf/NOTES	Sun Jul 12 18:14:38 2015	(r285422)
@@ -2978,8 +2978,8 @@ options 	MAXFILES=999
 
 # Random number generator
 # Only ONE of the below two may be used; they are mutually exclusive.
+# If neither is present, then the Fortuna algorithm is used.
 options 	RANDOM_YARROW	# Yarrow CSPRNG (Default)
-#options 	RANDOM_FORTUNA	# Fortuna CSPRNG
 options 	RANDOM_DEBUG	# Debugging messages
 
 # Module to enable execution of application via emulators like QEMU

Modified: head/sys/dev/random/build.sh
==============================================================================
--- head/sys/dev/random/build.sh	Sun Jul 12 17:28:31 2015	(r285421)
+++ head/sys/dev/random/build.sh	Sun Jul 12 18:14:38 2015	(r285422)
@@ -28,7 +28,14 @@
 #
 # Basic script to build crude unit tests.
 #
-cc -g -O0 -pthread -DRANDOM_DEBUG -DRANDOM_YARROW \
+# Diff-reduction checking between Yarrow and fortuna is done like so:
+#
+# $ diff -u -B <(sed -e 's/yarrow/wombat/g' \
+#                    -e 's/YARROW/WOMBAT/g' yarrow.c) \
+#              <(sed -e 's/fortuna/wombat/g' \
+#                    -e 's/FORTUNA/WOMBAT/g' fortuna.c) | less
+#
+cc -g -O0 -pthread -DRANDOM_DEBUG \
 	-I../.. -lstdthreads -Wall \
 	unit_test.c \
 	yarrow.c \
@@ -39,7 +46,7 @@ cc -g -O0 -pthread -DRANDOM_DEBUG -DRAND
 	../../crypto/sha2/sha256c.c \
 	-lz \
 	-o yunit_test
-cc -g -O0 -pthread -DRANDOM_DEBUG -DRANDOM_FORTUNA \
+cc -g -O0 -pthread -DRANDOM_DEBUG \
 	-I../.. -lstdthreads -Wall \
 	unit_test.c \
 	fortuna.c \

Modified: head/sys/dev/random/fortuna.c
==============================================================================
--- head/sys/dev/random/fortuna.c	Sun Jul 12 17:28:31 2015	(r285421)
+++ head/sys/dev/random/fortuna.c	Sun Jul 12 18:14:38 2015	(r285422)
@@ -39,10 +39,8 @@ __FBSDID("$FreeBSD$");
 #ifdef _KERNEL
 #include <sys/param.h>
 #include <sys/kernel.h>
-#include <sys/conf.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
-#include <sys/module.h>
 #include <sys/mutex.h>
 #include <sys/random.h>
 #include <sys/sysctl.h>
@@ -71,6 +69,7 @@ __FBSDID("$FreeBSD$");
 #include <crypto/sha2/sha2.h>
 
 #include <dev/random/hash.h>
+#include <dev/random/randomdev.h>
 #include <dev/random/uint128.h>
 #include <dev/random/fortuna.h>
 #endif /* _KERNEL */
@@ -125,26 +124,28 @@ static uint8_t zero_region[RANDOM_ZERO_B
 
 static void random_fortuna_pre_read(void);
 static void random_fortuna_read(uint8_t *, u_int);
-static void random_fortuna_post_read(void);
 static void random_fortuna_write(uint8_t *, u_int);
 static void random_fortuna_reseed(void);
 static int random_fortuna_seeded(void);
 static void random_fortuna_process_event(struct harvest_event *);
+static void random_fortuna_init_alg(void *);
+static void random_fortuna_deinit_alg(void *);
+
+static void random_fortuna_reseed_internal(uint32_t *entropy_data, u_int blockcount);
 
-#ifdef _KERNEL
 /* Interface to Adaptors system */
 struct random_algorithm random_alg_context = {
 	.ra_ident = "Fortuna",
+	.ra_init_alg = random_fortuna_init_alg,
+	.ra_deinit_alg = random_fortuna_deinit_alg,
 	.ra_pre_read = random_fortuna_pre_read,
 	.ra_read = random_fortuna_read,
-	.ra_post_read = random_fortuna_post_read,
 	.ra_write = random_fortuna_write,
 	.ra_reseed = random_fortuna_reseed,
 	.ra_seeded = random_fortuna_seeded,
 	.ra_event_processor = random_fortuna_process_event,
 	.ra_poolcount = RANDOM_FORTUNA_NPOOLS,
 };
-#endif
 
 /* ARGSUSED */
 static void
@@ -194,9 +195,6 @@ random_fortuna_init_alg(void *unused __u
 	fortuna_state.fs_counter = UINT128_ZERO;
 	explicit_bzero(&fortuna_state.fs_key, sizeof(fortuna_state.fs_key));
 }
-#ifdef _KERNEL
-SYSINIT(random_fortuna, SI_SUB_RANDOM, SI_ORDER_THIRD, random_fortuna_init_alg, NULL);
-#endif
 
 /* ARGSUSED */
 static void
@@ -209,15 +207,12 @@ random_fortuna_deinit_alg(void *unused _
 	sysctl_ctx_free(&random_clist);
 #endif
 }
-#ifdef _KERNEL
-SYSUNINIT(random_fortuna, SI_SUB_RANDOM, SI_ORDER_THIRD, random_fortuna_deinit_alg, NULL);
-#endif
 
 /*-
  * FS&K - AddRandomEvent()
  * Process a single stochastic event off the harvest queue
  */
-void
+static void
 random_fortuna_process_event(struct harvest_event *event)
 {
 	u_int pl;
@@ -251,29 +246,6 @@ random_fortuna_process_event(struct harv
 }
 
 /*-
- * Process a block of data suspected to be slightly stochastic.
- * Do this by breaking it up and inserting the pieces as if
- * they were separate events.
- */
-static void
-random_fortuna_process_buffer(uint32_t *buf, u_int wordcount)
-{
-	static struct harvest_event event;
-	static u_int destination = 0;
-	int i;
-
-	for (i = 0; i < wordcount; i += sizeof(event.he_entropy)/sizeof(event.he_entropy[0])) {
-		event.he_somecounter = (uint32_t)get_cyclecount();
-		event.he_size = sizeof(event.he_entropy);
-		event.he_bits = event.he_size/8;
-		event.he_source = RANDOM_CACHED;
-		event.he_destination = destination++; /* Harmless cheating */
-		memcpy(event.he_entropy, buf + i, sizeof(event.he_entropy));
-		random_fortuna_process_event(&event);
-	}
-}
-
-/*-
  * FS&K - Reseed()
  * This introduces new key material into the output generator.
  * Additionaly it increments the output generator's counter
@@ -358,13 +330,10 @@ random_fortuna_genrandom(uint8_t *buf, u
 }
 
 /*-
- * FS&K - RandomData()
- * Used to return processed entropy from the PRNG.
- * There is a pre_read and a post_read required to be present
- * (but they can be null functions) in order to allow specific
- * actions at the begin or the end of a read. Fortuna does its
- * reseeding in the _pre_read() part, and _post_read() is not
- * used.
+ * FS&K - RandomData() (Part 1)
+ * Used to return processed entropy from the PRNG. There is a pre_read
+ * required to be present (but it can be a stub) in order to allow
+ * specific actions at the begin of the read.
  */
 void
 random_fortuna_pre_read(void)
@@ -435,8 +404,10 @@ random_fortuna_pre_read(void)
 }
 
 /*-
- * Main read from Fortuna.
- * The supplied buf MUST be a multiple (>=0) of RANDOM_BLOCKSIZE in size.
+ * FS&K - RandomData() (Part 2)
+ * Main read from Fortuna, continued. May be called multiple times after
+ * the random_fortuna_pre_read() above.
+ * The supplied buf MUST be a multiple of RANDOM_BLOCKSIZE in size.
  * Lots of code presumes this for efficiency, both here and in other
  * routines. You are NOT allowed to break this!
  */
@@ -444,24 +415,21 @@ void
 random_fortuna_read(uint8_t *buf, u_int bytecount)
 {
 
+	KASSERT((bytecount % RANDOM_BLOCKSIZE) == 0, ("%s(): bytecount (= %d) must be a multiple of %d", __func__, bytecount, RANDOM_BLOCKSIZE ));
 	RANDOM_RESEED_LOCK();
 	random_fortuna_genrandom(buf, bytecount);
 	RANDOM_RESEED_UNLOCK();
 }
 
-void
-random_fortuna_post_read(void)
-{
-
-	/* CWOT */
-}
-
 /* Internal function to hand external entropy to the PRNG. */
 void
 random_fortuna_write(uint8_t *buf, u_int count)
 {
+	static u_int destination = 0;
+	struct harvest_event event;
 	struct randomdev_hash hash;
 	uint32_t entropy_data[RANDOM_KEYSIZE_WORDS], timestamp;
+	int i;
 
 	/* Extra timing here is helpful to scrape scheduler timing entropy */
 	randomdev_hash_init(&hash);
@@ -472,15 +440,21 @@ random_fortuna_write(uint8_t *buf, u_int
 	randomdev_hash_iterate(&hash, &timestamp, sizeof(timestamp));
 	randomdev_hash_finish(&hash, entropy_data);
 	explicit_bzero(&hash, sizeof(hash));
-	random_fortuna_process_buffer(entropy_data, sizeof(entropy_data)/sizeof(entropy_data[0]));
+	for (i = 0; i < RANDOM_KEYSIZE_WORDS; i += sizeof(event.he_entropy)/sizeof(event.he_entropy[0])) {
+		event.he_somecounter = (uint32_t)get_cyclecount();
+		event.he_size = sizeof(event.he_entropy);
+		event.he_bits = event.he_size/8;
+		event.he_source = RANDOM_CACHED;
+		event.he_destination = destination++; /* Harmless cheating */
+		memcpy(event.he_entropy, entropy_data + i, sizeof(event.he_entropy));
+		random_fortuna_process_event(&event);
+	}
 	explicit_bzero(entropy_data, sizeof(entropy_data));
 }
 
 void
 random_fortuna_reseed(void)
 {
-
-	/* CWOT */
 }
 
 int

Modified: head/sys/dev/random/hash.h
==============================================================================
--- head/sys/dev/random/hash.h	Sun Jul 12 17:28:31 2015	(r285421)
+++ head/sys/dev/random/hash.h	Sun Jul 12 18:14:38 2015	(r285422)
@@ -29,18 +29,21 @@
 #ifndef SYS_DEV_RANDOM_HASH_H_INCLUDED
 #define	SYS_DEV_RANDOM_HASH_H_INCLUDED
 
+/* Keys are formed from cipher blocks */
 #define	RANDOM_KEYSIZE		32	/* (in bytes) == 256 bits */
 #define	RANDOM_KEYSIZE_WORDS	(RANDOM_KEYSIZE/sizeof(uint32_t))
 #define	RANDOM_BLOCKSIZE	16	/* (in bytes) == 128 bits */
 #define	RANDOM_BLOCKSIZE_WORDS	(RANDOM_BLOCKSIZE/sizeof(uint32_t))
 #define	RANDOM_KEYS_PER_BLOCK	(RANDOM_KEYSIZE/RANDOM_BLOCKSIZE)
+
+/* The size of the zero block portion used to form H_d(m) */
 #define	RANDOM_ZERO_BLOCKSIZE	64	/* (in bytes) == 512 zero bits */
 
-struct randomdev_hash {		/* Big! Make static! */
+struct randomdev_hash {
 	SHA256_CTX	sha;
 };
 
-struct randomdev_key {		/* Big! Make static! */
+struct randomdev_key {
 	keyInstance key;	/* Key schedule */
 	cipherInstance cipher;	/* Rijndael internal */
 };

Modified: head/sys/dev/random/random_harvestq.c
==============================================================================
--- head/sys/dev/random/random_harvestq.c	Sun Jul 12 17:28:31 2015	(r285421)
+++ head/sys/dev/random/random_harvestq.c	Sun Jul 12 18:14:38 2015	(r285422)
@@ -74,8 +74,8 @@ volatile int random_kthread_control;
  * this make is a bit easier to lock and protect.
  */
 static struct harvest_context {
-	/* The harvest mutex protects the consistency of the entropy Fifos and
-	 * empty fifo and other associated structures.
+	/* The harvest mutex protects all of harvest_context and
+	 * the related data.
 	 */
 	struct mtx hc_mtx;
 	/* Round-robin destination cache. */
@@ -95,6 +95,9 @@ static struct harvest_context {
 	 * If (ring.in + 1) == ring.out (mod RANDOM_RING_MAX),
 	 *     the buffer is full.
 	 *
+	 * NOTE: ring.in points to the last added element,
+	 * and ring.out points to the last consumed element.
+	 *
 	 * The ring.in variable needs locking as there are multiple
 	 * sources to the ring. Only the sources may change ring.in,
 	 * but the consumer may examine it.
@@ -110,7 +113,7 @@ static struct harvest_context {
 	} hc_entropy_ring;
 	struct fast_entropy_accumulator {
 		volatile u_int pos;
-		uint32_t buf[8];
+		uint32_t buf[RANDOM_ACCUM_MAX];
 	} hc_entropy_fast_accumulator;
 } harvest_context;
 
@@ -150,7 +153,7 @@ random_kthread(void)
 				break;
 		}
 		random_sources_feed();
-		/* XXX: FIX!! This This seems a little slow; 8 items every 0.1s from UMA? */
+		/* XXX: FIX!! Increase the high-performance data rate? Need some measurements first. */
 		for (i = 0; i < RANDOM_ACCUM_MAX; i++) {
 			if (harvest_context.hc_entropy_fast_accumulator.buf[i]) {
 				random_harvest_direct(harvest_context.hc_entropy_fast_accumulator.buf + i, sizeof(harvest_context.hc_entropy_fast_accumulator.buf[0]), 4, RANDOM_FAST);
@@ -238,8 +241,6 @@ random_harvestq_init(void *unused __unus
 {
 	struct sysctl_oid *random_sys_o;
 
-	if (bootverbose)
-		printf("random: %s\n", __func__);
 	random_sys_o = SYSCTL_ADD_NODE(&random_clist,
 	    SYSCTL_STATIC_CHILDREN(_kern_random),
 	    OID_AUTO, "harvest", CTLFLAG_RW, 0,
@@ -285,6 +286,8 @@ random_harvestq_prime(void *unused __unu
 	if (keyfile != NULL) {
 		data = preload_fetch_addr(keyfile);
 		size = preload_fetch_size(keyfile);
+		/* Trim the size. If the admin has a file with a funny size, we lose some. Tough. */
+		size -= (size % sizeof(event.he_entropy));
 		if (data != NULL && size != 0) {
 			for (i = 0; i < size; i += sizeof(event.he_entropy)) {
 				count = sizeof(event.he_entropy);
@@ -314,7 +317,7 @@ random_harvestq_deinit(void *unused __un
 
 	/* Command the hash/reseed thread to end and wait for it to finish */
 	random_kthread_control = 0;
-	tsleep(&harvest_context.hc_kthread_proc, 0, "term", 0);
+	tsleep(&harvest_context.hc_kthread_proc, 0, "harvqterm", 0);
 	sysctl_ctx_free(&random_clist);
 }
 SYSUNINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_SECOND, random_harvestq_deinit, NULL);
@@ -334,7 +337,7 @@ SYSUNINIT(random_device_h_init, SI_SUB_R
  * read which can be quite expensive.
  */
 void
-random_harvest_queue(const void *entropy, u_int count, u_int bits, enum random_entropy_source origin)
+random_harvest_queue(const void *entropy, u_int size, u_int bits, enum random_entropy_source origin)
 {
 	struct harvest_event *event;
 	u_int ring_in;
@@ -351,14 +354,14 @@ random_harvest_queue(const void *entropy
 		event->he_source = origin;
 		event->he_destination = harvest_context.hc_destination[origin]++;
 		event->he_bits = bits;
-		if (count <= sizeof(event->he_entropy)) {
-			event->he_size = count;
-			memcpy(event->he_entropy, entropy, count);
+		if (size <= sizeof(event->he_entropy)) {
+			event->he_size = size;
+			memcpy(event->he_entropy, entropy, size);
 		}
 		else {
 			/* Big event, so squash it */
 			event->he_size = sizeof(event->he_entropy[0]);
-			event->he_entropy[0] = jenkins_hash(entropy, count, (uint32_t)(uintptr_t)event);
+			event->he_entropy[0] = jenkins_hash(entropy, size, (uint32_t)(uintptr_t)event);
 		}
 		harvest_context.hc_entropy_ring.in = ring_in;
 	}
@@ -372,7 +375,7 @@ random_harvest_queue(const void *entropy
  * This is the right place for high-rate harvested data.
  */
 void
-random_harvest_fast(const void *entropy, u_int count, u_int bits, enum random_entropy_source origin)
+random_harvest_fast(const void *entropy, u_int size, u_int bits, enum random_entropy_source origin)
 {
 	u_int pos;
 
@@ -381,7 +384,7 @@ random_harvest_fast(const void *entropy,
 	if (!(harvest_context.hc_source_mask & (1 << origin)))
 		return;
 	pos = harvest_context.hc_entropy_fast_accumulator.pos;
-	harvest_context.hc_entropy_fast_accumulator.buf[pos] ^= jenkins_hash(entropy, count, (uint32_t)get_cyclecount());
+	harvest_context.hc_entropy_fast_accumulator.buf[pos] ^= jenkins_hash(entropy, size, (uint32_t)get_cyclecount());
 	harvest_context.hc_entropy_fast_accumulator.pos = (pos + 1)%RANDOM_ACCUM_MAX;
 }
 
@@ -392,20 +395,20 @@ random_harvest_fast(const void *entropy,
  * (e.g.) booting when initial entropy is being gathered.
  */
 void
-random_harvest_direct(const void *entropy, u_int count, u_int bits, enum random_entropy_source origin)
+random_harvest_direct(const void *entropy, u_int size, u_int bits, enum random_entropy_source origin)
 {
 	struct harvest_event event;
 
 	KASSERT(origin >= RANDOM_START && origin < ENTROPYSOURCE, ("%s: origin %d invalid\n", __func__, origin));
 	if (!(harvest_context.hc_source_mask & (1 << origin)))
 		return;
-	count = MIN(count, sizeof(event.he_entropy));
+	size = MIN(size, sizeof(event.he_entropy));
 	event.he_somecounter = (uint32_t)get_cyclecount();
-	event.he_size = count;
+	event.he_size = size;
 	event.he_bits = bits;
 	event.he_source = origin;
 	event.he_destination = harvest_context.hc_destination[origin]++;
-	memcpy(event.he_entropy, entropy, count);
+	memcpy(event.he_entropy, entropy, size);
 	random_harvestq_fast_process_event(&event);
 	explicit_bzero(&event, sizeof(event));
 }

Modified: head/sys/dev/random/randomdev.c
==============================================================================
--- head/sys/dev/random/randomdev.c	Sun Jul 12 17:28:31 2015	(r285421)
+++ head/sys/dev/random/randomdev.c	Sun Jul 12 18:14:38 2015	(r285422)
@@ -62,7 +62,7 @@ __FBSDID("$FreeBSD$");
 #error "Cannot define both RANDOM_DUMMY and RANDOM_YARROW"
 #endif
 
-#define	RANDOM_MINOR	0
+#define	RANDOM_UNIT	0
 
 static d_read_t randomdev_read;
 static d_write_t randomdev_write;
@@ -107,12 +107,13 @@ dummy_random(void)
 
 struct random_algorithm random_alg_context = {
 	.ra_ident = "Dummy",
-	.ra_reseed = dummy_random,
-	.ra_seeded = (random_alg_seeded_t *)dummy_random_zero,
+	.ra_init_alg = NULL,
+	.ra_deinit_alg = NULL,
 	.ra_pre_read = dummy_random,
 	.ra_read = (random_alg_read_t *)dummy_random_zero,
-	.ra_post_read = dummy_random,
 	.ra_write = (random_alg_write_t *)dummy_random_zero,
+	.ra_reseed = dummy_random,
+	.ra_seeded = (random_alg_seeded_t *)dummy_random_zero,
 	.ra_event_processor = NULL,
 	.ra_poolcount = 0,
 };
@@ -123,6 +124,23 @@ LIST_HEAD(sources_head, random_sources);
 static struct sources_head source_list = LIST_HEAD_INITIALIZER(source_list);
 static u_int read_rate;
 
+static void
+random_alg_context_ra_init_alg(void *data)
+{
+
+	random_alg_context.ra_init_alg(data);
+}
+
+static void
+random_alg_context_ra_deinit_alg(void *data)
+{
+
+	random_alg_context.ra_deinit_alg(data);
+}
+
+SYSINIT(random_device, SI_SUB_RANDOM, SI_ORDER_THIRD, random_alg_context_ra_init_alg, NULL);
+SYSUNINIT(random_device, SI_SUB_RANDOM, SI_ORDER_THIRD, random_alg_context_ra_deinit_alg, NULL);
+
 #endif /* defined(RANDOM_DUMMY) */
 
 static struct selinfo rsel;
@@ -142,15 +160,15 @@ randomdev_read(struct cdev *dev __unused
 	random_alg_context.ra_pre_read();
 	/* (Un)Blocking logic */
 	error = 0;
-	while (!random_alg_context.ra_seeded() && error == 0) {
+	while (!random_alg_context.ra_seeded()) {
 		if (flags & O_NONBLOCK)	{
 			error = EWOULDBLOCK;
 			break;
 		}
-		tsleep(&random_alg_context, 0, "randrd", hz/10);
+		tsleep(&random_alg_context, 0, "randseed", hz/10);
 		/* keep tapping away at the pre-read until we seed/unblock. */
 		random_alg_context.ra_pre_read();
-		printf("random: %s unblock (error = %d)\n", __func__, error);
+		printf("random: %s unblock wait\n", __func__);
 	}
 	if (error == 0) {
 #if !defined(RANDOM_DUMMY)
@@ -160,10 +178,10 @@ randomdev_read(struct cdev *dev __unused
 		nbytes = uio->uio_resid;
 		while (uio->uio_resid && !error) {
 			c = MIN(uio->uio_resid, PAGE_SIZE);
+			/* See the random_buf size requirements in the Yarrow/Fortuna code */
 			random_alg_context.ra_read(random_buf, c);
 			error = uiomove(random_buf, c, uio);
 		}
-		random_alg_context.ra_post_read();
 		if (nbytes != uio->uio_resid && (error == ERESTART || error == EINTR) )
 			/* Return partial read, not error. */
 			error = 0;
@@ -204,7 +222,6 @@ read_random(void *random_buf, u_int len)
 		memcpy(random_buf, local_buf, len);
 	} else
 		len = 0;
-	random_alg_context.ra_post_read();
 	return (len);
 }
 
@@ -382,7 +399,7 @@ randomdev_modevent(module_t mod __unused
 	case MOD_LOAD:
 		printf("random: entropy device external interface\n");
 		random_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &random_cdevsw,
-		    RANDOM_MINOR, NULL, UID_ROOT, GID_WHEEL, 0644, "random");
+		    RANDOM_UNIT, NULL, UID_ROOT, GID_WHEEL, 0644, "random");
 		make_dev_alias(random_dev, "urandom"); /* compatibility */
 		break;
 	case MOD_UNLOAD:

Modified: head/sys/dev/random/randomdev.h
==============================================================================
--- head/sys/dev/random/randomdev.h	Sun Jul 12 17:28:31 2015	(r285421)
+++ head/sys/dev/random/randomdev.h	Sun Jul 12 18:14:38 2015	(r285422)
@@ -29,6 +29,8 @@
 #ifndef SYS_DEV_RANDOM_RANDOMDEV_H_INCLUDED
 #define	SYS_DEV_RANDOM_RANDOMDEV_H_INCLUDED
 
+#ifdef _KERNEL
+
 /* This header contains only those definitions that are global
  * and non algorithm-specific for the entropy processor
  */
@@ -55,11 +57,12 @@ MALLOC_DECLARE(M_ENTROPY);
 
 #define	RANDOM_ALG_READ_RATE_MINIMUM	32
 
+#endif /* _KERNEL */
+
 struct harvest_event;
 
 typedef void random_alg_pre_read_t(void);
 typedef void random_alg_read_t(uint8_t *, u_int);
-typedef void random_alg_post_read_t(void);
 typedef void random_alg_write_t(uint8_t *, u_int);
 typedef int random_alg_seeded_t(void);
 typedef void random_alg_reseed_t(void);
@@ -74,9 +77,10 @@ typedef u_int random_source_read_t(void 
 struct random_algorithm {
 	const char			*ra_ident;
 	u_int				 ra_poolcount;
+	void				(*ra_init_alg)(void *);
+	void				(*ra_deinit_alg)(void *);
 	random_alg_pre_read_t		*ra_pre_read;
 	random_alg_read_t		*ra_read;
-	random_alg_post_read_t		*ra_post_read;
 	random_alg_write_t		*ra_write;
 	random_alg_reseed_t		*ra_reseed;
 	random_alg_seeded_t		*ra_seeded;
@@ -85,6 +89,8 @@ struct random_algorithm {
 
 extern struct random_algorithm random_alg_context;
 
+#ifdef _KERNEL
+
 /*
  * Random Source is a source of entropy that can provide
  * specified or approximate amount of entropy immediately
@@ -108,6 +114,8 @@ void random_source_deregister(struct ran
 
 void random_sources_feed(void);
 
+#endif /* _KERNEL */
+
 void randomdev_unblock(void);
 
 #endif /* SYS_DEV_RANDOM_RANDOMDEV_H_INCLUDED */

Modified: head/sys/dev/random/unit_test.c
==============================================================================
--- head/sys/dev/random/unit_test.c	Sun Jul 12 17:28:31 2015	(r285421)
+++ head/sys/dev/random/unit_test.c	Sun Jul 12 18:14:38 2015	(r285422)
@@ -52,15 +52,9 @@ Where <alg> is YARROW or FORTUNA.
 #include <unistd.h>
 #include <zlib.h>
 
+#include "randomdev.h"
 #include "unit_test.h"
 
-#ifdef RANDOM_YARROW
-#include "dev/random/yarrow.h"
-#endif
-#ifdef RANDOM_FORTUNA
-#include "dev/random/fortuna.h"
-#endif
-
 #define	NUM_THREADS	  3
 #define	DEBUG
 
@@ -112,7 +106,7 @@ block_deflate(uint8_t *uncompr, uint8_t 
 	while (c_stream.total_in != len && c_stream.total_out < (len*2u + 512u)) {
 		err = deflate(&c_stream, Z_NO_FLUSH);
 #ifdef DEBUG
-		printf("deflate: len = %zd  total_in = %lu  total_out = %lu\n", len, c_stream.total_in, c_stream.total_out);
+		printf("deflate progress: len = %zd  total_in = %lu  total_out = %lu\n", len, c_stream.total_in, c_stream.total_out);
 #endif
 		check_err(err, "deflate(..., Z_NO_FLUSH)");
 	}
@@ -120,7 +114,7 @@ block_deflate(uint8_t *uncompr, uint8_t 
 	for (;;) {
 		err = deflate(&c_stream, Z_FINISH);
 #ifdef DEBUG
-		printf("deflate: len = %zd  total_in = %lu  total_out = %lu\n", len, c_stream.total_in, c_stream.total_out);
+		printf("deflate    final: len = %zd  total_in = %lu  total_out = %lu\n", len, c_stream.total_in, c_stream.total_out);
 #endif
 		if (err == Z_STREAM_END) break;
 		check_err(err, "deflate(..., Z_STREAM_END)");
@@ -133,7 +127,7 @@ block_deflate(uint8_t *uncompr, uint8_t 
 }
 
 void
-random_adaptor_unblock(void)
+randomdev_unblock(void)
 {
 
 #if 0
@@ -166,12 +160,7 @@ RunHarvester(void *arg __unused)
 		e.he_destination = i;
 		e.he_source = (i + 3)%7;
 		e.he_next = NULL;
-#ifdef RANDOM_YARROW
-		random_yarrow_process_event(&e);
-#endif
-#ifdef RANDOM_FORTUNA
-		random_fortuna_process_event(&e);
-#endif
+		random_alg_context.ra_event_processor(&e);
 		usleep(r);
 	}
 
@@ -198,12 +187,7 @@ WriteCSPRNG(void *threadid)
 			printf("Thread write 1 - %d\n", i);
 		if (buf != NULL) {
 			printf("Thread 1 writing.\n");
-#ifdef RANDOM_YARROW
-			random_yarrow_write(buf, i);
-#endif
-#ifdef RANDOM_FORTUNA
-			random_fortuna_write(buf, i);
-#endif
+			random_alg_context.ra_write(buf, i);
 			free(buf);
 		}
 		usleep(1000000);
@@ -220,6 +204,7 @@ static int
 ReadCSPRNG(void *threadid)
 {
 	size_t tid, zsize;
+	u_int buffersize;
 	uint8_t *buf, *zbuf;
 	int i;
 #ifdef DEBUG
@@ -229,40 +214,22 @@ ReadCSPRNG(void *threadid)
 	tid = (size_t)threadid;
 	printf("Thread #%zd starts\n", tid);
 
-#ifdef RANDOM_YARROW
-	while (!random_yarrow_seeded())
-#endif
-#ifdef RANDOM_FORTUNA
-	while (!random_fortuna_seeded())
-#endif
+	while (!random_alg_context.ra_seeded())
 	{
-#ifdef RANDOM_YARROW
-		random_yarrow_pre_read();
-		random_yarrow_post_read();
-#endif
-#ifdef RANDOM_FORTUNA
-		random_fortuna_pre_read();
-		random_fortuna_post_read();
-#endif
+		random_alg_context.ra_pre_read();
 		usleep(100);
 	}
 
 	for (i = 0; i < 100000; i++) {
-		buf = malloc(i);
+		buffersize = i + RANDOM_BLOCKSIZE;
+		buffersize -= buffersize%RANDOM_BLOCKSIZE;
+		buf = malloc(buffersize);
 		zbuf = malloc(2*i + 1024);
 		if (i % 1000 == 0)
 			printf("Thread read %zd - %d\n", tid, i);
 		if (buf != NULL && zbuf != NULL) {
-#ifdef RANDOM_YARROW
-			random_yarrow_pre_read();
-			random_yarrow_read(buf, i);
-			random_yarrow_post_read();
-#endif
-#ifdef RANDOM_FORTUNA
-			random_fortuna_pre_read();
-			random_fortuna_read(buf, i);
-			random_fortuna_post_read();
-#endif
+			random_alg_context.ra_pre_read();
+			random_alg_context.ra_read(buf, buffersize);
 			zsize = block_deflate(buf, zbuf, i);
 			if (zsize < i)
 				printf("ERROR!! Compressible RNG output!\n");
@@ -300,12 +267,7 @@ main(int argc, char *argv[])
 	int rc;
 	long t;
 
-#ifdef RANDOM_YARROW
-	random_yarrow_init_alg();
-#endif
-#ifdef RANDOM_FORTUNA
-	random_fortuna_init_alg();
-#endif
+	random_alg_context.ra_init_alg(NULL);
 
 	for (t = 0; t < NUM_THREADS; t++) {
 		printf("In main: creating thread %ld\n", t);
@@ -324,12 +286,7 @@ main(int argc, char *argv[])
 	thrd_join(threads[1], &rc);
 	thrd_join(threads[0], &rc);
 
-#ifdef RANDOM_YARROW
-	random_yarrow_deinit_alg();
-#endif
-#ifdef RANDOM_FORTUNA
-	random_fortuna_deinit_alg();
-#endif
+	random_alg_context.ra_deinit_alg(NULL);
 
 	/* Last thing that main() should do */
 	thrd_exit(0);

Modified: head/sys/dev/random/unit_test.h
==============================================================================
--- head/sys/dev/random/unit_test.h	Sun Jul 12 17:28:31 2015	(r285421)
+++ head/sys/dev/random/unit_test.h	Sun Jul 12 18:14:38 2015	(r285422)
@@ -34,7 +34,9 @@
 #error "Random unit tests cannot be compiled into the kernel."
 #endif
 
-void random_adaptor_unblock(void);
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdint.h>
 
 #if defined(clang) && __has_builtin(__builtin_readcyclecounter)
 #define	rdtsc __builtin_readcyclecounter
@@ -61,6 +63,7 @@ get_cyclecount(void)
 }
 
 #define	HARVESTSIZE	2
+#define RANDOM_BLOCKSIZE	16
 
 enum random_entropy_source {
 	RANDOM_START = 0,

Modified: head/sys/dev/random/yarrow.c
==============================================================================
--- head/sys/dev/random/yarrow.c	Sun Jul 12 17:28:31 2015	(r285421)
+++ head/sys/dev/random/yarrow.c	Sun Jul 12 18:14:38 2015	(r285422)
@@ -30,11 +30,8 @@ __FBSDID("$FreeBSD$");
 
 #ifdef _KERNEL
 #include <sys/param.h>
-#include <sys/kernel.h>
-#include <sys/conf.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
-#include <sys/module.h>
 #include <sys/mutex.h>
 #include <sys/random.h>
 #include <sys/sysctl.h>
@@ -54,6 +51,7 @@ __FBSDID("$FreeBSD$");
 #include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <string.h>
 #include <threads.h>
 
@@ -63,6 +61,7 @@ __FBSDID("$FreeBSD$");
 #include <crypto/sha2/sha2.h>
 
 #include <dev/random/hash.h>
+#include <dev/random/randomdev.h>
 #include <dev/random/uint128.h>
 #include <dev/random/yarrow.h>
 #endif /* _KERNEL */
@@ -109,27 +108,28 @@ RANDOM_CHECK_UINT(slowoverthresh, 1, 5);
 
 static void random_yarrow_pre_read(void);
 static void random_yarrow_read(uint8_t *, u_int);
-static void random_yarrow_post_read(void);
 static void random_yarrow_write(uint8_t *, u_int);
 static void random_yarrow_reseed(void);
 static int random_yarrow_seeded(void);
-static void random_yarrow_reseed_internal(u_int);
 static void random_yarrow_process_event(struct harvest_event *);
+static void random_yarrow_init_alg(void *);
+static void random_yarrow_deinit_alg(void *);
+
+static void random_yarrow_reseed_internal(u_int);
 
-#ifdef _KERNEL
 /* Interface to Adaptors system */
 struct random_algorithm random_alg_context = {
 	.ra_ident = "Yarrow",
+	.ra_init_alg = random_yarrow_init_alg,
+	.ra_deinit_alg = random_yarrow_deinit_alg,
 	.ra_pre_read = random_yarrow_pre_read,
 	.ra_read = random_yarrow_read,
-	.ra_post_read = random_yarrow_post_read,
 	.ra_write = random_yarrow_write,
 	.ra_reseed = random_yarrow_reseed,
 	.ra_seeded = random_yarrow_seeded,
 	.ra_event_processor = random_yarrow_process_event,
 	.ra_poolcount = RANDOM_YARROW_NPOOLS,
 };
-#endif
 
 /* ARGSUSED */
 static void
@@ -199,9 +199,6 @@ random_yarrow_init_alg(void *unused __un
 	/* Clear the counter */
 	yarrow_state.ys_counter = UINT128_ZERO;
 }
-#ifdef _KERNEL
-SYSINIT(random_yarrow, SI_SUB_RANDOM, SI_ORDER_THIRD, random_yarrow_init_alg, NULL);
-#endif
 
 /* ARGSUSED */
 static void
@@ -214,9 +211,6 @@ random_yarrow_deinit_alg(void *unused __
 	sysctl_ctx_free(&random_clist);
 #endif
 }
-#ifdef _KERNEL
-SYSUNINIT(random_yarrow, SI_SUB_RANDOM, SI_ORDER_THIRD, random_yarrow_deinit_alg, NULL);
-#endif
 
 /* Process a single stochastic event off the harvest queue */
 static void
@@ -255,25 +249,6 @@ random_yarrow_process_event(struct harve
 	RANDOM_RESEED_UNLOCK();
 }
 
-/* Process a block of data suspected to be slightly stochastic. */
-static void
-random_yarrow_process_buffer(uint32_t *buf, u_int wordcount)
-{
-	static struct harvest_event event;
-	static u_int destination = 0;
-	int i;
-
-	for (i = 0; i < wordcount; i += sizeof(event.he_entropy)/sizeof(event.he_entropy[0])) {
-		event.he_somecounter = (uint32_t)get_cyclecount();
-		event.he_size = sizeof(event.he_entropy);
-		event.he_bits = event.he_size/8;
-		event.he_source = RANDOM_CACHED;
-		event.he_destination = destination++; /* Harmless cheating */
-		memcpy(event.he_entropy, buf + i, sizeof(event.he_entropy));
-		random_yarrow_process_event(&event);
-	}
-}
-
 static void
 random_yarrow_reseed_internal(u_int fastslow)
 {
@@ -384,12 +359,11 @@ random_yarrow_generator_gate(void)
 }
 
 /*-
- * Used to return processed entropy from the PRNG.
- * There is a pre_read and a post_read required to be present
- * (but they can be null functions) in order to allow specific
- * actions at the begin or the end of a read. Yarrow does its
- * reseeding in its own thread. The _pre_read() and _post_read()
- * are not used here, and must be kept for completeness.
+ * Used to return processed entropy from the PRNG. There is a pre_read
+ * required to be present (but it can be a stub) in order to allow
+ * specific actions at the begin of the read.
+ * Yarrow does its reseeding in its own thread; _pre_read() is not used
+ * by Yarrow but must be kept for completeness.
  */
 void
 random_yarrow_pre_read(void)
@@ -407,6 +381,7 @@ random_yarrow_read(uint8_t *buf, u_int b
 {
 	u_int blockcount, i;
 
+	KASSERT((bytecount % RANDOM_BLOCKSIZE) == 0, ("%s(): bytecount (= %d) must be a multiple of %d", __func__, bytecount, RANDOM_BLOCKSIZE ));
 	RANDOM_RESEED_LOCK();
 	blockcount = (bytecount + RANDOM_BLOCKSIZE - 1)/RANDOM_BLOCKSIZE;
 	for (i = 0; i < blockcount; i++) {
@@ -421,19 +396,15 @@ random_yarrow_read(uint8_t *buf, u_int b
 	RANDOM_RESEED_UNLOCK();
 }
 
-void
-random_yarrow_post_read(void)
-{
-
-	/* CWOT */
-}
-
 /* Internal function to hand external entropy to the PRNG. */
 void
 random_yarrow_write(uint8_t *buf, u_int count)
 {
+	static u_int destination = 0;
+	static struct harvest_event event;
 	struct randomdev_hash hash;
 	uint32_t entropy_data[RANDOM_KEYSIZE_WORDS], timestamp;
+	int i;
 
 	/* Extra timing here is helpful to scrape scheduler timing entropy */
 	randomdev_hash_init(&hash);
@@ -444,7 +415,15 @@ random_yarrow_write(uint8_t *buf, u_int 
 	randomdev_hash_iterate(&hash, &timestamp, sizeof(timestamp));
 	randomdev_hash_finish(&hash, entropy_data);
 	explicit_bzero(&hash, sizeof(hash));
-	random_yarrow_process_buffer(entropy_data, sizeof(entropy_data)/sizeof(entropy_data[0]));
+	for (i = 0; i < RANDOM_KEYSIZE_WORDS; i += sizeof(event.he_entropy)/sizeof(event.he_entropy[0])) {
+		event.he_somecounter = (uint32_t)get_cyclecount();
+		event.he_size = sizeof(event.he_entropy);
+		event.he_bits = event.he_size/8;
+		event.he_source = RANDOM_CACHED;
+		event.he_destination = destination++; /* Harmless cheating */
+		memcpy(event.he_entropy, entropy_data + i, sizeof(event.he_entropy));
+		random_yarrow_process_event(&event);
+	}
 	explicit_bzero(entropy_data, sizeof(entropy_data));
 }
 

Modified: head/sys/net/if_tun.c
==============================================================================
--- head/sys/net/if_tun.c	Sun Jul 12 17:28:31 2015	(r285421)
+++ head/sys/net/if_tun.c	Sun Jul 12 18:14:38 2015	(r285422)
@@ -906,7 +906,7 @@ tunwrite(struct cdev *dev, struct uio *u
 		m_freem(m);
 		return (EAFNOSUPPORT);
 	}
-	random_harvest_queue(&(m->m_data), 12, 2, RANDOM_NET_TUN);
+	random_harvest_queue(m, sizeof(*m), 2, RANDOM_NET_TUN);
 	if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len);
 	if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
 	CURVNET_SET(ifp->if_vnet);

Modified: head/sys/netgraph/ng_iface.c
==============================================================================
--- head/sys/netgraph/ng_iface.c	Sun Jul 12 17:28:31 2015	(r285421)
+++ head/sys/netgraph/ng_iface.c	Sun Jul 12 18:14:38 2015	(r285422)
@@ -705,7 +705,7 @@ ng_iface_rcvdata(hook_p hook, item_p ite
 		m_freem(m);
 		return (EAFNOSUPPORT);
 	}
-	random_harvest_queue(&(m->m_data), 12, 2, RANDOM_NET_NG);
+	random_harvest_queue(m, sizeof(*m), 2, RANDOM_NET_NG);
 	M_SETFIB(m, ifp->if_fib);
 	netisr_dispatch(isr, m);
 	return (0);


More information about the svn-src-all mailing list