From owner-svn-src-projects@FreeBSD.ORG Wed Nov 13 22:48:38 2013 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id DAA88BBE; Wed, 13 Nov 2013 22:48:37 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id BB17C26C2; Wed, 13 Nov 2013 22:48:37 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id rADMmb5f028955; Wed, 13 Nov 2013 22:48:37 GMT (envelope-from markm@svn.freebsd.org) Received: (from markm@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id rADMmZOV028943; Wed, 13 Nov 2013 22:48:35 GMT (envelope-from markm@svn.freebsd.org) Message-Id: <201311132248.rADMmZOV028943@svn.freebsd.org> From: Mark Murray Date: Wed, 13 Nov 2013 22:48:35 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r258109 - projects/random_number_generator/sys/dev/random X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 13 Nov 2013 22:48:38 -0000 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 #include #include +#include #include #include #include #include -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 #include #include +#include #include #include #include @@ -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 #include #include -#include #include #include #include @@ -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 = ""; error = randomdev_write_file(seed_file, , PAGE_SIZE); if (error == 0)