Date: Fri, 4 Oct 2013 06:55:06 +0000 (UTC) From: Mark Murray <markm@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r256042 - in projects/random_number_generator: share/examples/kld/random_adaptor sys/conf sys/dev/glxsb sys/dev/hifn sys/dev/random sys/dev/rndtest sys/dev/safe sys/dev/syscons sys/dev/... Message-ID: <201310040655.r946t6ZR038091@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: markm Date: Fri Oct 4 06:55:06 2013 New Revision: 256042 URL: http://svnweb.freebsd.org/changeset/base/256042 Log: Snapshot. This passes the build test, but has not yet been finished or debugged. Contains: * Refactor the hardware RNG CPU instruction sources to feed into the software mixer. This is unfinished. The actual harvesting needs to be sorted out. Modified by me (see below). * Remove 'frac' parameter from random_harvest(). This was never used and adds extra code for no good reason. * Remove device write entropy harvesting. This provided a weak attack vector, was not very good at bootstrapping the device. To follow will be a replacement explicit reseed knob. * Separate out all the RANDOM_PURE sources into separate harvest entities. This adds some secuity in the case where more than one is present. * Review all the code and fix anything obviously messy or inconsistent. Address som review concerns while I'm here, like rename the pseudo-rng to 'dummy'. Submitted by: Arthur Mesh <arthurmesh@gmail.com> (the first item) Added: projects/random_number_generator/sys/dev/random/dummy_rng.c - copied, changed from r256023, projects/random_number_generator/sys/dev/random/pseudo_rng.c projects/random_number_generator/sys/dev/random/live_entropy_sources.c (contents, props changed) projects/random_number_generator/sys/dev/random/live_entropy_sources.h (contents, props changed) Deleted: projects/random_number_generator/sys/dev/random/pseudo_rng.c Modified: projects/random_number_generator/share/examples/kld/random_adaptor/random_adaptor_example.c projects/random_number_generator/sys/conf/files projects/random_number_generator/sys/conf/files.amd64 projects/random_number_generator/sys/conf/files.i386 projects/random_number_generator/sys/dev/glxsb/glxsb.c projects/random_number_generator/sys/dev/hifn/hifn7751.c projects/random_number_generator/sys/dev/random/harvest.c projects/random_number_generator/sys/dev/random/ivy.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_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/randomdev_soft.h projects/random_number_generator/sys/dev/random/yarrow.c projects/random_number_generator/sys/dev/rndtest/rndtest.c projects/random_number_generator/sys/dev/safe/safe.c projects/random_number_generator/sys/dev/syscons/scmouse.c projects/random_number_generator/sys/dev/syscons/syscons.c projects/random_number_generator/sys/dev/ubsec/ubsec.c projects/random_number_generator/sys/kern/kern_intr.c projects/random_number_generator/sys/mips/cavium/octeon_rnd.c projects/random_number_generator/sys/net/if_ethersubr.c projects/random_number_generator/sys/net/if_tun.c projects/random_number_generator/sys/netgraph/ng_iface.c projects/random_number_generator/sys/sys/random.h Modified: projects/random_number_generator/share/examples/kld/random_adaptor/random_adaptor_example.c ============================================================================== --- projects/random_number_generator/share/examples/kld/random_adaptor/random_adaptor_example.c Fri Oct 4 05:11:00 2013 (r256041) +++ projects/random_number_generator/share/examples/kld/random_adaptor/random_adaptor_example.c Fri Oct 4 06:55:06 2013 (r256042) @@ -30,32 +30,29 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/kernel.h> +#include <sys/lock.h> #include <sys/module.h> -#include <sys/selinfo.h> +#include <sys/random.h> #include <sys/systm.h> +#include <dev/random/live_entropy_sources.h> #include <dev/random/random_adaptors.h> #include <dev/random/randomdev.h> -#define RNG_NAME "example" - static int random_example_read(void *, int); struct random_adaptor random_example = { .ident = "Example RNG", - .init = (random_init_func_t *)random_null_func, - .deinit = (random_deinit_func_t *)random_null_func, + .source = RANDOM_PURE_BOGUS, /* Make sure this is in + * sys/random.h and is unique */ .read = random_example_read, - .write = (random_write_func_t *)random_null_func, - .reseed = (random_reseed_func_t *)random_null_func, - .seeded = 1, }; /* * Used under the license provided @ http://xkcd.com/221/ * http://creativecommons.org/licenses/by-nc/2.5/ */ -static u_char +static uint8_t getRandomNumber(void) { return 4; /* chosen by fair dice roll, guaranteed to be random */ @@ -64,14 +61,13 @@ getRandomNumber(void) static int random_example_read(void *buf, int c) { - u_char *b; + uint8_t *b; int count; b = buf; - for (count = 0; count < c; count++) { + for (count = 0; count < c; count++) b[count] = getRandomNumber(); - } printf("returning %d bytes of pure randomness\n", c); return (c); @@ -80,15 +76,26 @@ random_example_read(void *buf, int c) static int random_example_modevent(module_t mod, int type, void *unused) { + int error = 0; switch (type) { case MOD_LOAD: - random_adaptor_register(RNG_NAME, &random_example); - EVENTHANDLER_INVOKE(random_adaptor_attach, &random_example); - return (0); + live_entropy_source_register(&random_example); + break; + + case MOD_UNLOAD: + live_entropy_source_deregister(&random_example); + break; + + case MOD_SHUTDOWN: + break; + + default: + error = EOPNOTSUPP; + break; } - return (EINVAL); + return (error); } -RANDOM_ADAPTOR_MODULE(random_example, random_example_modevent, 1); +LIVE_ENTROPY_SRC_MODULE(live_entropy_source_example, random_example_modevent, 1); Modified: projects/random_number_generator/sys/conf/files ============================================================================== --- projects/random_number_generator/sys/conf/files Fri Oct 4 05:11:00 2013 (r256041) +++ projects/random_number_generator/sys/conf/files Fri Oct 4 06:55:06 2013 (r256042) @@ -2043,13 +2043,14 @@ rt2860.fw optional rt2860fw | ralfw \ no-obj no-implicit-rule \ clean "rt2860.fw" dev/random/harvest.c standard -dev/random/hash.c optional random -dev/random/pseudo_rng.c standard +dev/random/dummy_rng.c standard dev/random/random_adaptors.c standard -dev/random/random_harvestq.c standard +dev/random/live_entropy_sources.c optional random +dev/random/random_harvestq.c optional random dev/random/randomdev.c optional random dev/random/randomdev_soft.c optional random dev/random/yarrow.c optional random +dev/random/hash.c optional random dev/rc/rc.c optional rc dev/re/if_re.c optional re dev/rndtest/rndtest.c optional rndtest Modified: projects/random_number_generator/sys/conf/files.amd64 ============================================================================== --- projects/random_number_generator/sys/conf/files.amd64 Fri Oct 4 05:11:00 2013 (r256041) +++ projects/random_number_generator/sys/conf/files.amd64 Fri Oct 4 06:55:06 2013 (r256042) @@ -259,8 +259,6 @@ dev/nvme/nvme_sysctl.c optional nvme dev/nvme/nvme_test.c optional nvme dev/nvme/nvme_util.c optional nvme dev/nvram/nvram.c optional nvram isa -dev/random/ivy.c optional random rdrand_rng -dev/random/nehemiah.c optional random padlock_rng dev/qlxge/qls_dbg.c optional qlxge pci dev/qlxge/qls_dump.c optional qlxge pci dev/qlxge/qls_hw.c optional qlxge pci Modified: projects/random_number_generator/sys/conf/files.i386 ============================================================================== --- projects/random_number_generator/sys/conf/files.i386 Fri Oct 4 05:11:00 2013 (r256041) +++ projects/random_number_generator/sys/conf/files.i386 Fri Oct 4 06:55:06 2013 (r256042) @@ -257,8 +257,6 @@ dev/nvme/nvme_test.c optional nvme dev/nvme/nvme_util.c optional nvme dev/nvram/nvram.c optional nvram isa dev/pcf/pcf_isa.c optional pcf -dev/random/ivy.c optional random rdrand_rng -dev/random/nehemiah.c optional random padlock_rng dev/sbni/if_sbni.c optional sbni dev/sbni/if_sbni_isa.c optional sbni isa dev/sbni/if_sbni_pci.c optional sbni pci Modified: projects/random_number_generator/sys/dev/glxsb/glxsb.c ============================================================================== --- projects/random_number_generator/sys/dev/glxsb/glxsb.c Fri Oct 4 05:11:00 2013 (r256041) +++ projects/random_number_generator/sys/dev/glxsb/glxsb.c Fri Oct 4 06:55:06 2013 (r256042) @@ -476,7 +476,7 @@ glxsb_rnd(void *v) if (status & SB_RNS_TRNG_VALID) { value = bus_read_4(sc->sc_sr, SB_RANDOM_NUM); /* feed with one uint32 */ - random_harvest(&value, 4, 32/2, 0, RANDOM_PURE); + random_harvest(&value, 4, 32/2, RANDOM_PURE_GLXSB); } callout_reset(&sc->sc_rngco, sc->sc_rnghz, glxsb_rnd, sc); Modified: projects/random_number_generator/sys/dev/hifn/hifn7751.c ============================================================================== --- projects/random_number_generator/sys/dev/hifn/hifn7751.c Fri Oct 4 05:11:00 2013 (r256041) +++ projects/random_number_generator/sys/dev/hifn/hifn7751.c Fri Oct 4 06:55:06 2013 (r256042) @@ -258,7 +258,7 @@ hifn_partname(struct hifn_softc *sc) static void default_harvest(struct rndtest_state *rsp, void *buf, u_int count) { - random_harvest(buf, count, count*NBBY/2, 0, RANDOM_PURE); + random_harvest(buf, count, count*NBBY/2, RANDOM_PURE_HIFN); } static u_int Copied and modified: projects/random_number_generator/sys/dev/random/dummy_rng.c (from r256023, projects/random_number_generator/sys/dev/random/pseudo_rng.c) ============================================================================== --- projects/random_number_generator/sys/dev/random/pseudo_rng.c Thu Oct 3 17:30:55 2013 (r256023, copy source) +++ projects/random_number_generator/sys/dev/random/dummy_rng.c Fri Oct 4 06:55:06 2013 (r256042) @@ -28,87 +28,90 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> -#include <sys/time.h> +#include <sys/fcntl.h> #include <sys/kernel.h> #include <sys/module.h> +#include <sys/random.h> #include <sys/selinfo.h> #include <sys/systm.h> +#include <sys/time.h> #include <dev/random/random_adaptors.h> #include <dev/random/randomdev.h> -static struct mtx pseudo_random_block_mtx; +static struct mtx dummy_random_mtx; -static int -pseudo_random_block_read(void *buf __unused, int c __unused) +/* Used to fake out unused random calls in random_adaptor */ +static void +random_null_func(void) { +} - mtx_lock(&pseudo_random_block_mtx); - - printf("random(4) device is blocking.\n"); - msleep(pseudo_random_block_read, &pseudo_random_block_mtx, 0, - "block", 0); - - mtx_unlock(&pseudo_random_block_mtx); +static int +dummy_random_poll(int events __unused, struct thread *td __unused) +{ return (0); } -static void -pseudo_random_block_init(void) +static int +dummy_random_block(int flag) { + int error = 0; - mtx_init(&pseudo_random_block_mtx, "sleep mtx for random_block", - NULL, MTX_DEF); + mtx_lock(&dummy_random_mtx); + + /* Blocking logic */ + while (!error) { + if (flag & O_NONBLOCK) + error = EWOULDBLOCK; + else { + printf("random: dummy device blocking on read.\n"); + error = msleep(&dummy_random_block, + &dummy_random_mtx, + PUSER | PCATCH, "block", 0); + } + } + mtx_unlock(&dummy_random_mtx); + + return (error); } static void -pseudo_random_block_deinit(void) +dummy_random_init(void) { - mtx_destroy(&pseudo_random_block_mtx); + mtx_init(&dummy_random_mtx, "sleep mtx for dummy_random", + NULL, MTX_DEF); } -struct random_adaptor pseudo_random_block = { - .ident = "pseudo-RNG that always blocks", - .init = pseudo_random_block_init, - .deinit = pseudo_random_block_deinit, - .read = pseudo_random_block_read, - .write = (random_write_func_t *)random_null_func, - .reseed = (random_reseed_func_t *)random_null_func, - .seeded = 1, -}; - -static int -pseudo_random_panic_read(void *buf, int c) +static void +dummy_random_deinit(void) { - panic("Insert a witty panic msg in here."); - - return (0); + mtx_destroy(&dummy_random_mtx); } -struct random_adaptor pseudo_random_panic = { - .ident = "pseudo-RNG that always panics on first read(2)", - .init = (random_init_func_t *)random_null_func, - .deinit = (random_deinit_func_t *)random_null_func, - .read = pseudo_random_panic_read, - .write = (random_write_func_t *)random_null_func, +struct random_adaptor dummy_random = { + .ident = "Dummy entropy device that always blocks", + .init = dummy_random_init, + .deinit = dummy_random_deinit, + .block = dummy_random_block, + .poll = dummy_random_poll, + .read = (random_read_func_t *)random_null_func, .reseed = (random_reseed_func_t *)random_null_func, - .seeded = 1, + .seeded = 0, /* This device can never be seeded */ }; static int -pseudo_random_modevent(module_t mod, int type, void *unused) +dummy_random_modevent(module_t mod __unused, int type, void *unused __unused) { switch (type) { case MOD_LOAD: - random_adaptor_register("block", &pseudo_random_block); + random_adaptor_register("dummy", &dummy_random); EVENTHANDLER_INVOKE(random_adaptor_attach, - &pseudo_random_block); - - random_adaptor_register("panic", &pseudo_random_panic); + &dummy_random); return (0); } @@ -116,4 +119,4 @@ pseudo_random_modevent(module_t mod, int return (EINVAL); } -RANDOM_ADAPTOR_MODULE(pseudo, pseudo_random_modevent, 1); +RANDOM_ADAPTOR_MODULE(dummy, dummy_random_modevent, 1); Modified: projects/random_number_generator/sys/dev/random/harvest.c ============================================================================== --- projects/random_number_generator/sys/dev/random/harvest.c Fri Oct 4 05:11:00 2013 (r256041) +++ projects/random_number_generator/sys/dev/random/harvest.c Fri Oct 4 06:55:06 2013 (r256042) @@ -48,20 +48,20 @@ __FBSDID("$FreeBSD$"); static int read_random_phony(void *, int); /* Structure holding the desired entropy sources */ -struct harvest_select harvest = { 1, 1, 1, 0 }; +struct harvest_select harvest = { 1, 1, 1, 1 }; static int warned = 0; /* hold the address of the routine which is actually called if * the randomdev is loaded */ -static void (*reap_func)(u_int64_t, const void *, u_int, u_int, u_int, +static void (*reap_func)(u_int64_t, const void *, u_int, u_int, enum esource) = NULL; static int (*read_func)(void *, int) = read_random_phony; /* Initialise the harvester at load time */ void randomdev_init_harvester(void (*reaper)(u_int64_t, const void *, u_int, - u_int, u_int, enum esource), int (*reader)(void *, int)) + u_int, enum esource), int (*reader)(void *, int)) { reap_func = reaper; read_func = reader; @@ -86,12 +86,10 @@ randomdev_deinit_harvester(void) * read which can be quite expensive. */ void -random_harvest(void *entropy, u_int count, u_int bits, u_int frac, - enum esource origin) +random_harvest(void *entropy, u_int count, u_int bits, enum esource origin) { if (reap_func) - (*reap_func)(get_cyclecount(), entropy, count, bits, frac, - origin); + (*reap_func)(get_cyclecount(), entropy, count, bits, origin); } /* Userland-visible version of read_random */ Modified: projects/random_number_generator/sys/dev/random/ivy.c ============================================================================== --- projects/random_number_generator/sys/dev/random/ivy.c Fri Oct 4 05:11:00 2013 (r256041) +++ projects/random_number_generator/sys/dev/random/ivy.c Fri Oct 4 06:55:06 2013 (r256042) @@ -30,50 +30,44 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> -#include <sys/time.h> #include <sys/kernel.h> #include <sys/lock.h> #include <sys/module.h> -#include <sys/mutex.h> +#include <sys/random.h> #include <sys/selinfo.h> #include <sys/systm.h> #include <machine/md_var.h> #include <machine/specialreg.h> +#include <dev/random/live_entropy_sources.h> #include <dev/random/random_adaptors.h> #include <dev/random/randomdev.h> #define RETRY_COUNT 10 -static void random_ivy_init(void); -static void random_ivy_deinit(void); static int random_ivy_read(void *, int); -struct random_adaptor random_ivy = { +struct random_hardware_source random_ivy = { .ident = "Hardware, Intel IvyBridge+ RNG", - .init = random_ivy_init, - .deinit = random_ivy_deinit, - .read = random_ivy_read, - .write = (random_write_func_t *)random_null_func, - .reseed = (random_reseed_func_t *)random_null_func, - .seeded = 1, + .source = RANDOM_PURE_RDRAND, + .read = random_ivy_read }; static inline int -ivy_rng_store(long *tmp) +ivy_rng_store(uint64_t *tmp) { #ifdef __GNUCLIKE_ASM uint32_t count; __asm __volatile( #ifdef __amd64__ - ".byte\t0x48,0x0f,0xc7,0xf0\n\t" /* rdrand %rax */ + "rdrand\t%%rax\n\t" "jnc\t1f\n\t" "movq\t%%rax,%1\n\t" "movl\t$8,%%eax\n" #else /* i386 */ - ".byte\t0x0f,0xc7,0xf0\n\t" /* rdrand %eax */ + "rdrand\t%%eax\n\t" "jnc\t1f\n\t" "movl\t%%eax,%1\n\t" "movl\t$4,%%eax\n" @@ -86,34 +80,26 @@ ivy_rng_store(long *tmp) #endif } -static void -random_ivy_init(void) -{ -} - -void -random_ivy_deinit(void) -{ -} - static int random_ivy_read(void *buf, int c) { - char *b; - long tmp; - int count, res, retry; + uint8_t *b; + int count, ret, retry; + uint64_t tmp; - for (count = c, b = buf; count > 0; count -= res, b += res) { + b = buf; + for (count = c; count > 0; count -= ret) { for (retry = 0; retry < RETRY_COUNT; retry++) { - res = ivy_rng_store(&tmp); - if (res != 0) + ret = ivy_rng_store(&tmp); + if (ret != 0) break; } - if (res == 0) + if (ret == 0) break; - if (res > count) - res = count; - memcpy(b, &tmp, res); + if (ret > count) + ret = count; + memcpy(b, &tmp, ret); + b += ret; } return (c - count); } @@ -121,25 +107,35 @@ random_ivy_read(void *buf, int c) static int rdrand_modevent(module_t mod, int type, void *unused) { + int error = 0; switch (type) { case MOD_LOAD: - if (cpu_feature2 & CPUID2_RDRAND) { - random_adaptor_register("rdrand", &random_ivy); - EVENTHANDLER_INVOKE(random_adaptor_attach, &random_ivy); - return (0); - } else { + if (cpu_feature2 & CPUID2_RDRAND) + live_entropy_source_register(&random_ivy); + else #ifndef KLD_MODULE if (bootverbose) #endif - printf( - "%s: RDRAND feature is not present on this CPU\n", + printf("%s: RDRAND is not present\n", random_ivy.ident); - return (0); - } + break; + + case MOD_UNLOAD: + if (cpu_feature2 & CPUID2_RDRAND) + live_entropy_source_deregister(&random_ivy); + break; + + case MOD_SHUTDOWN: + break; + + default: + error = EOPNOTSUPP; + break; + } - return (EINVAL); + return (error); } -RANDOM_ADAPTOR_MODULE(random_rdrand, rdrand_modevent, 1); +LIVE_ENTROPY_SRC_MODULE(random_rdrand, rdrand_modevent, 1); Added: projects/random_number_generator/sys/dev/random/live_entropy_sources.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/random_number_generator/sys/dev/random/live_entropy_sources.c Fri Oct 4 06:55:06 2013 (r256042) @@ -0,0 +1,185 @@ +/*- + * Copyright (c) 2013 Arthur Mesh <arthurmesh@gmail.com> + * Copyright (c) 2013 Mark R V Murray + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +__FBSDID("$FreeBSD$"); + +#include <sys/kernel.h> +#include <sys/libkern.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/queue.h> +#include <sys/random.h> +#include <sys/selinfo.h> +#include <sys/sx.h> +#include <sys/sysctl.h> +#include <sys/systm.h> +#include <sys/unistd.h> + +#include <dev/random/randomdev.h> +#include <dev/random/randomdev_soft.h> +#include <dev/random/random_adaptors.h> + +#include "live_entropy_sources.h" + +LIST_HEAD(les_head, live_entropy_sources); +static struct les_head sources = LIST_HEAD_INITIALIZER(sources); +static struct sx les_lock; /* need a sleepable lock */ + +#define LES_THRESHOLD 10 + +MALLOC_DEFINE(M_LIVE_ENTROPY_SRCS, "live_entropy_sources", + "Live Entropy Sources"); + +void +live_entropy_source_register(struct random_hardware_source *rsource) +{ + struct live_entropy_sources *les; + + KASSERT(rsource != NULL, ("invalid input to %s", __func__)); + + les = malloc(sizeof(struct live_entropy_sources), M_LIVE_ENTROPY_SRCS, + M_WAITOK); + les->rsource = rsource; + + sx_xlock(&les_lock); + LIST_INSERT_HEAD(&sources, les, entries); + sx_xunlock(&les_lock); +} + +void +live_entropy_source_deregister(struct random_hardware_source *rsource) +{ + struct live_entropy_sources *les; + + KASSERT(rsource != NULL, ("invalid input to %s", __func__)); + + sx_xlock(&les_lock); + LIST_FOREACH(les, &sources, entries) { + if (les->rsource == rsource) { + LIST_REMOVE(les, entries); + free(les, M_LIVE_ENTROPY_SRCS); + break; + } + } + sx_xunlock(&les_lock); +} + +static int +live_entropy_source_handler(SYSCTL_HANDLER_ARGS) +{ + struct live_entropy_sources *les; + int error, count; + + count = error = 0; + + sx_slock(&les_lock); + + if (LIST_EMPTY(&sources)) + error = SYSCTL_OUT(req, "", 0); + else { + LIST_FOREACH(les, &sources, entries) { + + error = SYSCTL_OUT(req, ",", count++ ? 1 : 0); + if (error) + break; + + error = SYSCTL_OUT(req, les->rsource->ident, strlen(les->rsource->ident)); + if (error) + break; + } + } + + sx_sunlock(&les_lock); + + return (error); +} + +static void +live_entropy_sources_init(void *unused) +{ + + SYSCTL_PROC(_kern_random, OID_AUTO, live_entropy_sources, + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, + NULL, 0, live_entropy_source_handler, "", + "List of Active Live Entropy Sources"); + + sx_init(&les_lock, "live_entropy_sources"); +} + +/* + * Run through all "live" sources reading entropy for the given + * number of rounds, which should be a multiple of the number + * of entropy accumulation pools in use; 2 for Yarrow and 32 + * for Fortuna. + */ +void +live_entropy_sources_feed(int rounds) +{ + struct live_entropy_sources *les; + uint8_t buf[HARVESTSIZE]; + int i, n; + + sx_slock(&les_lock); + + /* + * Walk over all of live entropy sources, and feed their output + * to the system-wide RNG. + */ + LIST_FOREACH(les, &sources, entries) { + + for (i = 0; i < rounds; i++) { + /* + * This should be quick, since it's a live entropy + * source. + */ + n = les->rsource->read(buf, sizeof(buf)); + /* FIXME: Whine loudly if this didn't work. */ + + /* + * FIXME: Cannot harvest this stuff into the queue; + * the poor thing will choke to death! + */ + random_harvest(buf, n, 0, les->rsource->source); + } + + } + + sx_sunlock(&les_lock); +} + +static void +live_entropy_sources_deinit(void *unused) +{ + + sx_destroy(&les_lock); +} + +SYSINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST, + live_entropy_sources_init, NULL); +SYSUNINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST, + live_entropy_sources_deinit, NULL); Added: projects/random_number_generator/sys/dev/random/live_entropy_sources.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/random_number_generator/sys/dev/random/live_entropy_sources.h Fri Oct 4 06:55:06 2013 (r256042) @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2013 Arthur Mesh <arthurmesh@gmail.com> + * Copyright (c) 2013 Mark R V Murray + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __LIVE_ENTROPY_SOURCES__ +#define __LIVE_ENTROPY_SOURCES__ + +/* + * Live entropy source is a source of entropy that can provide + * specified or approximate amount of entropy immediately upon request or within + * an acceptable amount of time. + */ +struct live_entropy_sources { + LIST_ENTRY(live_entropy_sources) entries; /* list of providers */ + struct random_hardware_source *rsource; /* associated random adaptor */ +}; + +void live_entropy_source_register(struct random_hardware_source *); +void live_entropy_source_deregister(struct random_hardware_source *); +void live_entropy_sources_feed(int); + +#define LIVE_ENTROPY_SRC_MODULE(name, modevent, ver) \ + static moduledata_t name##_mod = { \ + #name, \ + modevent, \ + 0 \ + }; \ + DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, \ + SI_ORDER_SECOND); \ + MODULE_VERSION(name, ver); \ + MODULE_DEPEND(name, random, 1, 1, 1); + +#endif /* __LIVE_ENTROPY_SOURCES__ */ Modified: projects/random_number_generator/sys/dev/random/nehemiah.c ============================================================================== --- projects/random_number_generator/sys/dev/random/nehemiah.c Fri Oct 4 05:11:00 2013 (r256041) +++ projects/random_number_generator/sys/dev/random/nehemiah.c Fri Oct 4 06:55:06 2013 (r256042) @@ -1,6 +1,5 @@ /*- - * Copyright (c) 2013 David E. O'Brien <obrien@NUXI.org> - * Copyright (c) 2004 Mark R V Murray + * Copyright (c) 2013 Mark R V Murray * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,209 +29,126 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> -#include <sys/time.h> +#include <sys/kernel.h> #include <sys/lock.h> -#include <sys/mutex.h> #include <sys/module.h> +#include <sys/random.h> #include <sys/selinfo.h> #include <sys/systm.h> -#include <sys/kernel.h> #include <machine/pcb.h> #include <machine/md_var.h> #include <machine/specialreg.h> +#include <dev/random/live_entropy_sources.h> #include <dev/random/random_adaptors.h> #include <dev/random/randomdev.h> -#define RANDOM_BLOCK_SIZE 256 -#define CIPHER_BLOCK_SIZE 16 - static void random_nehemiah_init(void); static void random_nehemiah_deinit(void); static int random_nehemiah_read(void *, int); -struct random_adaptor random_nehemiah = { - .ident = "Hardware, VIA Nehemiah", - .init = random_nehemiah_init, - .deinit = random_nehemiah_deinit, - .read = random_nehemiah_read, - .write = (random_write_func_t *)random_null_func, - .reseed = (random_reseed_func_t *)random_null_func, - .seeded = 1, +struct random_hardware_source random_nehemiah = { + .ident = "Hardware, VIA Nehemiah Padlock RNG", + .source = RANDOM_PURE_NEHEMIAH, + .read = random_nehemiah_read }; -union VIA_ACE_CW { - uint64_t raw; - struct { - u_int round_count : 4; - u_int algorithm_type : 3; - u_int key_generation_type : 1; - u_int intermediate : 1; - u_int decrypt : 1; - u_int key_size : 2; - u_int filler0 : 20; - u_int filler1 : 32; - u_int filler2 : 32; - u_int filler3 : 32; - } field; -}; - -/* The extra 7 is to allow an 8-byte write on the last byte of the - * arrays. The ACE wants the AES data 16-byte/128-bit aligned, and - * it _always_ writes n*64 bits. The RNG does not care about alignment, - * and it always writes n*32 bits or n*64 bits. - */ -static uint8_t key[CIPHER_BLOCK_SIZE+7] __aligned(16); -static uint8_t iv[CIPHER_BLOCK_SIZE+7] __aligned(16); -static uint8_t in[RANDOM_BLOCK_SIZE+7] __aligned(16); -static uint8_t out[RANDOM_BLOCK_SIZE+7] __aligned(16); - -static union VIA_ACE_CW acw __aligned(16); +/* This H/W RNG never stores more than 8 bytes in one go */ static struct fpu_kern_ctx *fpu_ctx_save; -static struct mtx random_nehemiah_mtx; - /* ARGSUSED */ static __inline size_t VIA_RNG_store(void *buf) { -#ifdef __GNUCLIKE_ASM uint32_t retval = 0; uint32_t rate = 0; - /* The .byte line is really VIA C3 "xstore" instruction */ +#ifdef __GNUCLIKE_ASM __asm __volatile( - "movl $0,%%edx \n\t" - ".byte 0x0f, 0xa7, 0xc0" + "movl $0,%%edx\n\t" + "xstore" : "=a" (retval), "+d" (rate), "+D" (buf) : : "memory" ); +#endif if (rate == 0) return (retval&0x1f); -#endif return (0); } -/* ARGSUSED */ -static __inline void -VIA_ACE_cbc(void *in, void *out, size_t count, void *key, union VIA_ACE_CW *cw, void *iv) -{ -#ifdef __GNUCLIKE_ASM - /* The .byte line is really VIA C3 "xcrypt-cbc" instruction */ - __asm __volatile( - "pushf \n\t" - "popf \n\t" - "rep \n\t" - ".byte 0x0f, 0xa7, 0xc8" - : "+a" (iv), "+c" (count), "+D" (out), "+S" (in) - : "b" (key), "d" (cw) - : "cc", "memory" - ); -#endif -} - static void random_nehemiah_init(void) { - acw.raw = 0ULL; - acw.field.round_count = 12; - mtx_init(&random_nehemiah_mtx, "random nehemiah", NULL, MTX_DEF); fpu_ctx_save = fpu_kern_alloc_ctx(FPU_KERN_NORMAL); } -void +static void random_nehemiah_deinit(void) { fpu_kern_free_ctx(fpu_ctx_save); - mtx_destroy(&random_nehemiah_mtx); } static int random_nehemiah_read(void *buf, int c) { - int i, error; + uint8_t *b; size_t count, ret; - uint8_t *p; + uint64_t tmp; - mtx_lock(&random_nehemiah_mtx); - error = fpu_kern_enter(curthread, fpu_ctx_save, FPU_KERN_NORMAL); - if (error != 0) { - mtx_unlock(&random_nehemiah_mtx); - return (0); + if ((fpu_kern_enter(curthread, fpu_ctx_save, FPU_KERN_NORMAL) == 0)) { + b = buf; + for (count = c; count > 0; count -= ret) { + ret = MIN(VIA_RNG_store(&tmp), count); + memcpy(b, &tmp, ret); + b += ret; + } + fpu_kern_leave(curthread, fpu_ctx_save); } + else + c = 0; - /* Get a random AES key */ - count = 0; - p = key; - do { - ret = VIA_RNG_store(p); - p += ret; - count += ret; - } while (count < CIPHER_BLOCK_SIZE); - - /* Get a random AES IV */ - count = 0; - p = iv; - do { - ret = VIA_RNG_store(p); - p += ret; - count += ret; - } while (count < CIPHER_BLOCK_SIZE); - - /* Get a block of random bytes */ - count = 0; - p = in; - do { - ret = VIA_RNG_store(p); - p += ret; - count += ret; - } while (count < RANDOM_BLOCK_SIZE); - - /* This is a Davies-Meyer hash of the most paranoid variety; the - * key, IV and the data are all read directly from the hardware RNG. - * All of these are used precisely once. - */ - VIA_ACE_cbc(in, out, RANDOM_BLOCK_SIZE/CIPHER_BLOCK_SIZE, - key, &acw, iv); - for (i = 0; i < RANDOM_BLOCK_SIZE; i++) - out[i] ^= in[i]; - - c = MIN(RANDOM_BLOCK_SIZE, c); - memcpy(buf, out, (size_t)c); - - fpu_kern_leave(curthread, fpu_ctx_save); - mtx_unlock(&random_nehemiah_mtx); return (c); } static int nehemiah_modevent(module_t mod, int type, void *unused) { + int error = 0; switch (type) { case MOD_LOAD: if (via_feature_rng & VIA_HAS_RNG) { - random_adaptor_register("nehemiah", &random_nehemiah); - EVENTHANDLER_INVOKE(random_adaptor_attach, - &random_nehemiah); - return (0); - } else { + live_entropy_source_register(&random_nehemiah); + random_nehemiah_init(); + } else #ifndef KLD_MODULE if (bootverbose) #endif - printf( - "%s: VIA RNG feature is not present on this CPU\n", + printf("%s: VIA Padlock RNG not present\n", random_nehemiah.ident); - return (0); - } + break; + + case MOD_UNLOAD: + if (via_feature_rng & VIA_HAS_RNG) + random_nehemiah_deinit(); + live_entropy_source_deregister(&random_nehemiah); + break; + + case MOD_SHUTDOWN: + break; + + default: + error = EOPNOTSUPP; + break; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201310040655.r946t6ZR038091>