Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 13 Nov 2013 22:48:35 +0000 (UTC)
From:      Mark Murray <markm@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r258109 - projects/random_number_generator/sys/dev/random
Message-ID:  <201311132248.rADMmZOV028943@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: markm
Date: Wed Nov 13 22:48:35 2013
New Revision: 258109
URL: http://svnweb.freebsd.org/changeset/base/258109

Log:
  More code examination and fixes. This pass was to mainly to attack "XXX: FIX!!" instances.
  
  * Biggest bit of work was to add rate-adaptive live entropy support to the high-rate "live" sources. The current code is there to exercise to process, and will be frobbed later. (Damn. I forgot to put in a "XXX: " Comment).
  
  * Clean up comments where issues are noticed.
  
  * Move code around a bit to be in more logical places (dummy random_read(9) is now in dummy_rng.c).

Modified:
  projects/random_number_generator/sys/dev/random/dummy_rng.c
  projects/random_number_generator/sys/dev/random/live_entropy_sources.c
  projects/random_number_generator/sys/dev/random/nehemiah.c
  projects/random_number_generator/sys/dev/random/random_adaptors.c
  projects/random_number_generator/sys/dev/random/random_adaptors.h
  projects/random_number_generator/sys/dev/random/random_harvestq.c
  projects/random_number_generator/sys/dev/random/random_harvestq.h
  projects/random_number_generator/sys/dev/random/randomdev.c
  projects/random_number_generator/sys/dev/random/randomdev.h
  projects/random_number_generator/sys/dev/random/randomdev_soft.c
  projects/random_number_generator/sys/dev/random/yarrow.c

Modified: projects/random_number_generator/sys/dev/random/dummy_rng.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/dummy_rng.c	Wed Nov 13 22:35:18 2013	(r258108)
+++ projects/random_number_generator/sys/dev/random/dummy_rng.c	Wed Nov 13 22:48:35 2013	(r258109)
@@ -35,13 +35,17 @@ __FBSDID("$FreeBSD$");
 #include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/random.h>
+#include <sys/syslog.h>
 #include <sys/systm.h>
 #include <sys/time.h>
 
 #include <dev/random/randomdev.h>
 #include <dev/random/random_adaptors.h>
 
-static struct mtx	dummy_random_mtx;
+static struct mtx dummy_random_mtx;
+
+/* If no entropy device is loaded, don't spam the console with warnings */
+static int warned = 0;
 
 /* Used to fake out unused random calls in random_adaptor */
 static void
@@ -94,6 +98,39 @@ dummy_random_deinit(void)
 	mtx_destroy(&dummy_random_mtx);
 }
 
+/* This is used only by the internal read_random(9) call, and then only
+ * if no entropy processor is loaded.
+ *
+ * DO NOT, REPEAT, DO NOT add this to the "struct random_adaptor" below!
+ *
+ * Make a token effort to provide _some_ kind of output. No warranty of
+ * the quality of this output is made, mainly because its lousy.
+ *
+ * Caveat Emptor.
+ */
+int
+dummy_random_read_phony(void *buf, int count)
+{
+	u_long randval;
+	int size, i;
+
+	if (!warned) {
+		log(LOG_WARNING, "random device not loaded; using insecure pseudo-random number generator\n");
+		warned = 1;
+	}
+
+	/* srandom() is called in kern/init_main.c:proc0_post() */
+
+	/* Fill buf[] with random(9) output */
+	for (i = 0; i < count; i+= (int)sizeof(u_long)) {
+		randval = random();
+		size = MIN(count - i, sizeof(u_long));
+		memcpy(&((char *)buf)[i], &randval, (size_t)size);
+	}
+
+	return (count);
+}
+
 struct random_adaptor randomdev_dummy = {
 	.ra_ident = "Dummy entropy device",
 	.ra_init = dummy_random_init,

Modified: projects/random_number_generator/sys/dev/random/live_entropy_sources.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/live_entropy_sources.c	Wed Nov 13 22:35:18 2013	(r258108)
+++ projects/random_number_generator/sys/dev/random/live_entropy_sources.c	Wed Nov 13 22:48:35 2013	(r258109)
@@ -133,11 +133,9 @@ live_entropy_source_handler(SYSCTL_HANDL
 void
 live_entropy_sources_feed(void)
 {
-	/* XXX: This wastes a few words of space */
-	static u_int destination[ENTROPYSOURCE];
 	static struct harvest_event event;
 	struct live_entropy_sources *lles;
-	int i, n;
+	int i, n, read_rate;
 
 	sx_slock(&les_lock);
 
@@ -145,21 +143,20 @@ live_entropy_sources_feed(void)
 	 * Walk over all of live entropy sources, and feed their output
 	 * to the system-wide RNG.
 	 */
+	read_rate = random_adaptor_read_rate();
 	LIST_FOREACH(lles, &les_sources, lles_entries) {
 
-		/* XXX: FIX!! "2" is the number of pools in Yarrow */
-		for (i = 0; i < 2; i++) {
-			/*
-			 * This should be quick, since it's a live entropy
-			 * source.
-			 */
-			/* XXX: FIX!! Whine loudly if this didn't work. */
-			n = lles->lles_rsource->les_read(event.he_entropy, HARVESTSIZE);
+		for (i = 0; i < harvest_pool_count*read_rate; i++) {
 			event.he_somecounter = get_cyclecount();
 			event.he_size = n;
 			event.he_bits = (n*8)/2;
 			event.he_source = lles->lles_rsource->les_source;
-			event.he_destination = destination[event.he_source]++;
+			event.he_destination = harvest_destination[event.he_source]++;
+
+			/* This *must* be quick, since it's a live entropy source. */
+			n = lles->lles_rsource->les_read(event.he_entropy, HARVESTSIZE);
+			KASSERT((n > 0 && n <= HARVESTSIZE), ("very bad return from les_read (= %d) in %s", n, __func__));
+			memset(event.he_entropy + n, 0, HARVESTSIZE - (u_int)n);
 
 			/* Do the actual entropy insertion */
 			harvest_process_event(&event);

Modified: projects/random_number_generator/sys/dev/random/nehemiah.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/nehemiah.c	Wed Nov 13 22:35:18 2013	(r258108)
+++ projects/random_number_generator/sys/dev/random/nehemiah.c	Wed Nov 13 22:48:35 2013	(r258109)
@@ -58,7 +58,7 @@ static struct live_entropy_source random
 	.les_read = random_nehemiah_read
 };
 
-/* XXX: FIX? TODO? now that the Davies-Meyer hash is gone and we only use
+/* XXX: FIX? Now that the Davies-Meyer hash is gone and we only use
  * the 'xstore' instruction, do we still need to preserve the
  * FPU state with fpu_kern_(enter|leave)() ?
  */

Modified: projects/random_number_generator/sys/dev/random/random_adaptors.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/random_adaptors.c	Wed Nov 13 22:35:18 2013	(r258108)
+++ projects/random_number_generator/sys/dev/random/random_adaptors.c	Wed Nov 13 22:48:35 2013	(r258109)
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/libkern.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
+#include <sys/mutex.h>
 #include <sys/poll.h>
 #include <sys/queue.h>
 #include <sys/random.h>
@@ -55,8 +56,12 @@ static struct sx random_adaptors_lock; /
 LIST_HEAD(adaptors_head, random_adaptors);
 static struct adaptors_head random_adaptors_list = LIST_HEAD_INITIALIZER(random_adaptors_list);
 static struct random_adaptor *random_adaptor = NULL; /* Currently active adaptor */
+/* End of data items requiring adaptor lock protection */
 
-/* End of data items requiring lock protection */
+/* The rate mutex protects the consistency of the read-rate logic. */
+struct mtx rate_mtx;
+int random_adaptor_read_rate_cache;
+/* End of data items requiring rate mutex protection */
 
 MALLOC_DEFINE(M_ENTROPY, "entropy", "Entropy harvesting buffers and data structures");
 
@@ -136,6 +141,13 @@ random_adaptor_read(struct uio *uio, int
 
 	KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
 
+	/* The read-rate stuff is a *VERY* crude measure of the instantaneous read rate, designed
+	 * to increase the use of 'live' entropy sources when lots of reads are done.
+	 */
+	mtx_lock(&rate_mtx);
+	random_adaptor_read_rate_cache += (int)((uio->uio_resid + PAGE_SIZE + 1)/PAGE_SIZE);
+	mtx_unlock(&rate_mtx);
+
 	sx_slock(&random_adaptors_lock);
 
 	/* Blocking logic */
@@ -166,6 +178,18 @@ random_adaptor_read(struct uio *uio, int
 }
 
 int
+random_adaptor_read_rate(void)
+{
+	int ret;
+
+	mtx_lock(&rate_mtx);
+	ret = random_adaptor_read_rate_cache = random_adaptor_read_rate_cache ? random_adaptor_read_rate_cache%32 + 1 : 1;
+	mtx_unlock(&rate_mtx);
+
+	return (ret);
+}
+
+int
 random_adaptor_poll(int events, struct thread *td)
 {
 	int revents = 0;
@@ -320,6 +344,7 @@ random_adaptors_init(void *unused __unus
 	    "Active Random Number Generator Adaptor");
 
 	sx_init(&random_adaptors_lock, "random_adaptors");
+	mtx_init(&rate_mtx, "read rate mutex", NULL, MTX_DEF);
 
 	/* This dummy "thing" is not a module by itself, but part of the
 	 * randomdev module.
@@ -334,26 +359,29 @@ random_adaptors_deinit(void *unused __un
 	/* Don't do this! Panic will follow. */
 	/* random_adaptor_deregister("dummy"); */
 
+	mtx_destroy(&rate_mtx);
 	sx_destroy(&random_adaptors_lock);
 }
 
-/* XXX: FIX!! Move this to where its not so well hidden, like randomdev[_soft].c, maybe. */
 /*
  * First seed.
  *
+ * NB! NB! NB!
+ *
+ * NB! NB! NB!
+ *
  * It turns out this is bloody dangerous. I was fiddling with code elsewhere
  * and managed to get conditions where a safe (i.e. seeded) entropy device should
- * not have been possible. This managed to hide that by seeding the device anyway.
+ * not have been possible. This managed to hide that by unblocking the device anyway.
  * As crap randomness is not directly distinguishable from good randomness, this
  * could have gone unnoticed for quite a while.
  *
  * Very luckily, the probe-time entropy is very nearly good enough to cause a
- * first seed all of the time, and the default settings for interrupt- and SWI
- * entropy harvesting causes a proper, safe, first (re)seed in short order
- * after that.
+ * first seed all of the time, and the default settings for other entropy
+ * harvesting causes a proper, safe, first seed (unblock) in short order after that.
  *
  * That said, the below would be useful where folks are more concerned with
- * a quick start than with extra paranoia.
+ * a quick start than with extra paranoia in a low-entropy environment.
  *
  * markm - October 2013.
  */

Modified: projects/random_number_generator/sys/dev/random/random_adaptors.h
==============================================================================
--- projects/random_number_generator/sys/dev/random/random_adaptors.h	Wed Nov 13 22:35:18 2013	(r258108)
+++ projects/random_number_generator/sys/dev/random/random_adaptors.h	Wed Nov 13 22:48:35 2013	(r258109)
@@ -68,4 +68,6 @@ int random_adaptor_block(int);
 int random_adaptor_read(struct uio *, int);
 int random_adaptor_poll(int, struct thread *);
 
+int random_adaptor_read_rate(void);
+
 #endif /* SYS_DEV_RANDOM_RANDOM_ADAPTORS_H_INCLUDED */

Modified: projects/random_number_generator/sys/dev/random/random_harvestq.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/random_harvestq.c	Wed Nov 13 22:35:18 2013	(r258108)
+++ projects/random_number_generator/sys/dev/random/random_harvestq.c	Wed Nov 13 22:48:35 2013	(r258109)
@@ -77,9 +77,19 @@ static struct entropyfifo emptyfifo;
 /* Harvested entropy */
 static struct entropyfifo harvestfifo;
 
+/* Round-robin destination cache. */
+u_int harvest_destination[ENTROPYSOURCE];
+
 /* Function called to process one harvested stochastic event */
 void (*harvest_process_event)(struct harvest_event *);
 
+/* Pool count is used by anything needing to know how many entropy
+ * pools are currently being maintained.
+ * This is of use to (e.g.) the live source feed where we need to give
+ * all the pools a top-up.
+ */
+int harvest_pool_count;
+
 /* <0 to end the kthread, 0 to let it run, 1 to flush the harvest queues */
 int random_kthread_control = 0;
 
@@ -143,7 +153,7 @@ random_kthread(void *arg __unused)
 }
 
 void
-random_harvestq_init(void (*event_processor)(struct harvest_event *))
+random_harvestq_init(void (*event_processor)(struct harvest_event *), int poolcount)
 {
 	uint8_t *keyfile, *data;
 	int error, i;
@@ -165,6 +175,9 @@ random_harvestq_init(void (*event_proces
 	/* Point to the correct event_processing function */
 	harvest_process_event = event_processor;
 
+	/* Store the pool count (used by live source feed) */
+	harvest_pool_count = poolcount;
+
 	mtx_init(&harvest_mtx, "entropy harvest mutex", NULL, MTX_SPIN);
 
 	/* Start the hash/reseed thread */
@@ -231,9 +244,8 @@ void
 random_harvestq_internal(const void *entropy, u_int count, u_int bits,
     enum random_entropy_source origin)
 {
-	/* XXX: This wastes a few words of space */
-	static u_int destination[ENTROPYSOURCE];
 	struct harvest_event *event;
+	size_t c;
 
 	KASSERT(origin >= RANDOM_START && origin < ENTROPYSOURCE,
 	    ("random_harvest_internal: origin %d invalid\n", origin));
@@ -252,9 +264,10 @@ random_harvestq_internal(const void *ent
 		event->he_size = count;
 		event->he_bits = bits;
 		event->he_source = origin;
-		event->he_destination = destination[origin]++;
-		memcpy(event->he_entropy, entropy,
-		    MIN(count, HARVESTSIZE));
+		event->he_destination = harvest_destination[origin]++;
+		c = MIN(count, HARVESTSIZE);
+		memcpy(event->he_entropy, entropy, c);
+		memset(event->he_entropy + c, 0, HARVESTSIZE - c);
 
 		STAILQ_INSERT_TAIL(&harvestfifo.head,
 		    event, he_next);

Modified: projects/random_number_generator/sys/dev/random/random_harvestq.h
==============================================================================
--- projects/random_number_generator/sys/dev/random/random_harvestq.h	Wed Nov 13 22:35:18 2013	(r258108)
+++ projects/random_number_generator/sys/dev/random/random_harvestq.h	Wed Nov 13 22:48:35 2013	(r258109)
@@ -45,13 +45,24 @@ struct harvest_event {
 	STAILQ_ENTRY(harvest_event)	he_next;		/* next item on the list */
 };
 
-void random_harvestq_init(void (*)(struct harvest_event *));
+void random_harvestq_init(void (*)(struct harvest_event *), int);
 void random_harvestq_deinit(void);
 void random_harvestq_internal(const void *, u_int, u_int, enum random_entropy_source);
 
+/* Pool count is used by anything needing to know how many entropy
+ * pools are currently being maintained.
+ * This is of use to (e.g.) the live source feed where we need to give
+ * all the pools a top-up.
+ */
+extern int harvest_pool_count;
+
 /* This is in randomdev.c as it needs to be permanently in the kernel */
 void randomdev_set_wakeup_exit(void *);
 
+/* Round-robin destination cache. */
+extern u_int harvest_destination[ENTROPYSOURCE];
+
+/* Function called to process one harvested stochastic event */
 extern void (*harvest_process_event)(struct harvest_event *);
 
 extern int random_kthread_control;

Modified: projects/random_number_generator/sys/dev/random/randomdev.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/randomdev.c	Wed Nov 13 22:35:18 2013	(r258108)
+++ projects/random_number_generator/sys/dev/random/randomdev.c	Wed Nov 13 22:48:35 2013	(r258109)
@@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$");
 #include <sys/proc.h>
 #include <sys/random.h>
 #include <sys/sysctl.h>
-#include <sys/syslog.h>
 #include <sys/systm.h>
 #include <sys/uio.h>
 #include <sys/unistd.h>
@@ -175,18 +174,14 @@ randomdev_modevent(module_t mod __unused
 DEV_MODULE(randomdev, randomdev_modevent, NULL);
 MODULE_VERSION(randomdev, 1);
 
-/* Internal stub/fake routines for when no entropy device is loaded */
+/* Internal stub/fake routine for when no entropy processor is loaded */
 static void random_harvest_phony(const void *, u_int, u_int, enum random_entropy_source);
-static int random_read_phony(void *, int);
 
 /* hold the addresses of the routines which are actually called if
  * the random device is loaded.
  */
 static void (*reap_func)(const void *, u_int, u_int, enum random_entropy_source) = random_harvest_phony;
-static int (*read_func)(void *, int) = random_read_phony;
-
-/* If no entropy device is loaded, don't spam the console with warnings */
-static int warned = 0;
+static int (*read_func)(void *, int) = dummy_random_read_phony;
 
 /* Initialise the harvester when/if it is loaded */
 void
@@ -195,7 +190,6 @@ randomdev_init_harvester(void (*reaper)(
 {
 	reap_func = reaper;
 	read_func = reader;
-	warned = 1;
 }
 
 /* Deinitialise the harvester when/if it is unloaded */
@@ -203,8 +197,7 @@ void
 randomdev_deinit_harvester(void)
 {
 	reap_func = random_harvest_phony;
-	read_func = random_read_phony;
-	warned = 0;
+	read_func = dummy_random_read_phony;
 }
 
 /* Entropy harvesting routine. This is supposed to be fast; do
@@ -239,34 +232,6 @@ read_random(void *buf, int count)
 	return ((*read_func)(buf, count));
 }
 
-/* If the entropy device is not loaded, make a token effort to
- * provide _some_ kind of output. No warranty of the quality of
- * this output is made, mainly because its lousy. Caveat Emptor.
- */
-/* XXX: FIX!! Move this to dummy_rng.c ? */
-static int
-random_read_phony(void *buf, int count)
-{
-	u_long randval;
-	int size, i;
-
-	if (!warned) {
-		log(LOG_WARNING, "random device not loaded; using insecure pseudo-random number generator\n");
-		warned = 1;
-	}
-
-	/* srandom() is called in kern/init_main.c:proc0_post() */
-
-	/* Fill buf[] with random(9) output */
-	for (i = 0; i < count; i+= (int)sizeof(u_long)) {
-		randval = random();
-		size = MIN(count - i, sizeof(u_long));
-		memcpy(&((char *)buf)[i], &randval, (size_t)size);
-	}
-
-	return (count);
-}
-
 /* Helper routine to enable kproc_exit() to work while the module is
  * being (or has been) unloaded.
  * This routine is in this file because it is always linked into the kernel,

Modified: projects/random_number_generator/sys/dev/random/randomdev.h
==============================================================================
--- projects/random_number_generator/sys/dev/random/randomdev.h	Wed Nov 13 22:35:18 2013	(r258108)
+++ projects/random_number_generator/sys/dev/random/randomdev.h	Wed Nov 13 22:48:35 2013	(r258109)
@@ -46,6 +46,9 @@ void randomdev_init_harvester(void (*)(c
     int (*)(void *, int));
 void randomdev_deinit_harvester(void);
 
+/* Stub/fake routines for when no entropy processor is loaded */
+extern int dummy_random_read_phony(void *, int);
+
 extern u_int randomdev_harvest_source_mask;
 
 /* kern.random sysctls */

Modified: projects/random_number_generator/sys/dev/random/randomdev_soft.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/randomdev_soft.c	Wed Nov 13 22:35:18 2013	(r258108)
+++ projects/random_number_generator/sys/dev/random/randomdev_soft.c	Wed Nov 13 22:48:35 2013	(r258109)
@@ -192,10 +192,10 @@ randomdev_init(void)
 
 	/* Register the randomness processing routine */
 #if defined(RANDOM_YARROW)
-	random_harvestq_init(random_yarrow_process_event);
+	random_harvestq_init(random_yarrow_process_event, 2);
 #endif
 #if defined(RANDOM_FORTUNA)
-	random_harvestq_init(random_fortuna_process_event);
+	random_harvestq_init(random_fortuna_process_event, 32);
 #endif
 
 	/* Register the randomness harvesting routine */

Modified: projects/random_number_generator/sys/dev/random/yarrow.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/yarrow.c	Wed Nov 13 22:35:18 2013	(r258108)
+++ projects/random_number_generator/sys/dev/random/yarrow.c	Wed Nov 13 22:48:35 2013	(r258109)
@@ -292,7 +292,8 @@ reseed(u_int fastslow)
 	memset((void *)hash, 0, sizeof(hash));
 
 	/* 7. Dump to seed file */
-#ifdef RANDOM_RWFILE_WRITE_OK /* XXX: Not defined so writes ain't gonna happen */
+#ifdef RANDOM_RWFILE_WRITE_IS_OK /* Not defined so writes ain't gonna happen */
+	/* This pseudo-code is documentation. Please leave it alone. */
 	seed_file = "<some file>";
 	error = randomdev_write_file(seed_file, <generated entropy>, PAGE_SIZE);
 	if (error == 0)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201311132248.rADMmZOV028943>