svn commit: r258109 - projects/random_number_generator/sys/dev/random
Mark Murray
markm at FreeBSD.org
Wed Nov 13 22:48:38 UTC 2013
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)
More information about the svn-src-projects
mailing list