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/...

Mark Murray markm at FreeBSD.org
Fri Oct 4 06:55:09 UTC 2013


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 at 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 at 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 at 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 at 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 ***


More information about the svn-src-projects mailing list