From owner-svn-src-head@freebsd.org Sun Jul 12 18:14:44 2015 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 6EDC299950D; Sun, 12 Jul 2015 18:14:44 +0000 (UTC) (envelope-from markm@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 5CE761621; Sun, 12 Jul 2015 18:14:44 +0000 (UTC) (envelope-from markm@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.70]) by repo.freebsd.org (8.14.9/8.14.9) with ESMTP id t6CIEiv5045549; Sun, 12 Jul 2015 18:14:44 GMT (envelope-from markm@FreeBSD.org) Received: (from markm@localhost) by repo.freebsd.org (8.14.9/8.14.9/Submit) id t6CIEdkN045519; Sun, 12 Jul 2015 18:14:39 GMT (envelope-from markm@FreeBSD.org) Message-Id: <201507121814.t6CIEdkN045519@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: markm set sender to markm@FreeBSD.org using -f From: Mark Murray Date: Sun, 12 Jul 2015 18:14:39 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r285422 - in head: share/man/man4 sys/conf sys/dev/random sys/net sys/netgraph X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 12 Jul 2015 18:14:44 -0000 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 #include -#include #include #include -#include #include #include #include @@ -71,6 +69,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #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, ×tamp, 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 is YARROW or FORTUNA. #include #include +#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 +#include +#include #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 -#include -#include #include #include -#include #include #include #include @@ -54,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -63,6 +61,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #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, ×tamp, 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);