Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 10 Nov 2013 16:33:15 +0000 (UTC)
From:      Mark Murray <markm@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r257918 - in projects/random_number_generator/sys: conf dev/random modules modules/padlock_rng modules/random modules/rdrand_rng sys
Message-ID:  <201311101633.rAAGXFKp045009@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: markm
Date: Sun Nov 10 16:33:14 2013
New Revision: 257918
URL: http://svnweb.freebsd.org/changeset/base/257918

Log:
  This counts as a pretty heavy code review, much overdue.
  
  * Simplify the code where possible; remove unneeded variables, excess macro wrapping and useless code. Tidy comments etc.
  
  * Combine common code into files; the harvest.c file was particularly confusing.
  
  * The dummy fallback is an inherent part of the device; don't pretend it is a separate module.
  
  * Attempt to make the modularisation complete. This is unfinished, in that unloading random.ko may cause panics.
  
  * Reduce excess header inclusion where this was found.
  
  * Don't unconditionally (re)seed the Yarrow device on boot; there is adequate entropy for it to start by itself with default settings. This was nasty; I managews to get an auto-seed in an unsafe state by fiddling. This is too bad of a foot-shooter to mess with.
  
  I'm now much happier with this from a security perspective.

Added:
  projects/random_number_generator/sys/modules/padlock_rng/
  projects/random_number_generator/sys/modules/padlock_rng/Makefile   (contents, props changed)
  projects/random_number_generator/sys/modules/rdrand_rng/
  projects/random_number_generator/sys/modules/rdrand_rng/Makefile   (contents, props changed)
Deleted:
  projects/random_number_generator/sys/dev/random/harvest.c
Modified:
  projects/random_number_generator/sys/conf/files
  projects/random_number_generator/sys/dev/random/dummy_rng.c
  projects/random_number_generator/sys/dev/random/hash.c
  projects/random_number_generator/sys/dev/random/hash.h
  projects/random_number_generator/sys/dev/random/ivy.c
  projects/random_number_generator/sys/dev/random/live_entropy_sources.c
  projects/random_number_generator/sys/dev/random/live_entropy_sources.h
  projects/random_number_generator/sys/dev/random/nehemiah.c
  projects/random_number_generator/sys/dev/random/random_adaptors.c
  projects/random_number_generator/sys/dev/random/random_adaptors.h
  projects/random_number_generator/sys/dev/random/random_harvestq.c
  projects/random_number_generator/sys/dev/random/random_harvestq.h
  projects/random_number_generator/sys/dev/random/randomdev.c
  projects/random_number_generator/sys/dev/random/randomdev.h
  projects/random_number_generator/sys/dev/random/randomdev_soft.c
  projects/random_number_generator/sys/dev/random/randomdev_soft.h
  projects/random_number_generator/sys/dev/random/rwfile.c
  projects/random_number_generator/sys/dev/random/rwfile.h
  projects/random_number_generator/sys/dev/random/yarrow.c
  projects/random_number_generator/sys/dev/random/yarrow.h
  projects/random_number_generator/sys/modules/Makefile
  projects/random_number_generator/sys/modules/random/Makefile
  projects/random_number_generator/sys/sys/random.h

Modified: projects/random_number_generator/sys/conf/files
==============================================================================
--- projects/random_number_generator/sys/conf/files	Sun Nov 10 14:18:05 2013	(r257917)
+++ projects/random_number_generator/sys/conf/files	Sun Nov 10 16:33:14 2013	(r257918)
@@ -2040,12 +2040,11 @@ rt2860.fw			optional rt2860fw | ralfw		\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"rt2860.fw"
-dev/random/harvest.c		standard
-dev/random/dummy_rng.c		standard
+dev/random/randomdev.c		standard
 dev/random/random_adaptors.c	standard
+dev/random/dummy_rng.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

Modified: projects/random_number_generator/sys/dev/random/dummy_rng.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/dummy_rng.c	Sun Nov 10 14:18:05 2013	(r257917)
+++ projects/random_number_generator/sys/dev/random/dummy_rng.c	Sun Nov 10 16:33:14 2013	(r257918)
@@ -1,5 +1,6 @@
 /*-
  * 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
@@ -30,15 +31,16 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/fcntl.h>
 #include <sys/kernel.h>
+#include <sys/lock.h>
 #include <sys/malloc.h>
-#include <sys/module.h>
+#include <sys/mutex.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>
+#include <dev/random/random_adaptors.h>
 
 static struct mtx	dummy_random_mtx;
 
@@ -94,7 +96,7 @@ dummy_random_deinit(void)
 }
 
 struct random_adaptor dummy_random = {
-	.ident = "Dummy entropy device that always blocks",
+	.ident = "Dummy entropy device",
 	.init = dummy_random_init,
 	.deinit = dummy_random_deinit,
 	.block = dummy_random_block,
@@ -104,21 +106,3 @@ struct random_adaptor dummy_random = {
 	.seeded = 0, /* This device can never be seeded */
 	.priority = 1, /* Bottom priority, so goes to last position */
 };
-
-static int
-dummy_random_modevent(module_t mod __unused, int type, void *unused __unused)
-{
-
-	switch (type) {
-	case MOD_LOAD:
-		random_adaptor_register("dummy", &dummy_random);
-		EVENTHANDLER_INVOKE(random_adaptor_attach,
-		    &dummy_random);
-
-		return (0);
-	}
-
-	return (EINVAL);
-}
-
-RANDOM_ADAPTOR_MODULE(dummy, dummy_random_modevent, 1);

Modified: projects/random_number_generator/sys/dev/random/hash.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/hash.c	Sun Nov 10 14:18:05 2013	(r257917)
+++ projects/random_number_generator/sys/dev/random/hash.c	Sun Nov 10 16:33:14 2013	(r257918)
@@ -75,7 +75,7 @@ randomdev_encrypt_init(struct randomdev_
  * a multiple of BLOCKSIZE.
  */
 void
-randomdev_encrypt(struct randomdev_key *context, void *d_in, void *d_out, unsigned length)
+randomdev_encrypt(struct randomdev_key *context, void *d_in, void *d_out, u_int length)
 {
 	rijndael_blockEncrypt(&context->cipher, &context->key, d_in, length*8, d_out);
 }

Modified: projects/random_number_generator/sys/dev/random/hash.h
==============================================================================
--- projects/random_number_generator/sys/dev/random/hash.h	Sun Nov 10 14:18:05 2013	(r257917)
+++ projects/random_number_generator/sys/dev/random/hash.h	Sun Nov 10 16:33:14 2013	(r257918)
@@ -45,6 +45,6 @@ void randomdev_hash_init(struct randomde
 void randomdev_hash_iterate(struct randomdev_hash *, void *, size_t);
 void randomdev_hash_finish(struct randomdev_hash *, void *);
 void randomdev_encrypt_init(struct randomdev_key *, void *);
-void randomdev_encrypt(struct randomdev_key *context, void *, void *, unsigned);
+void randomdev_encrypt(struct randomdev_key *context, void *, void *, u_int);
 
 #endif

Modified: projects/random_number_generator/sys/dev/random/ivy.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/ivy.c	Sun Nov 10 14:18:05 2013	(r257917)
+++ projects/random_number_generator/sys/dev/random/ivy.c	Sun Nov 10 16:33:14 2013	(r257918)
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
+#include <sys/conf.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/module.h>
@@ -55,7 +56,7 @@ __FBSDID("$FreeBSD$");
 
 static int random_ivy_read(void *, int);
 
-static struct random_hardware_source random_ivy = {
+static struct live_entropy_source random_ivy = {
 	.ident = "Hardware, Intel IvyBridge+ RNG",
 	.source = RANDOM_PURE_RDRAND,
 	.read = random_ivy_read
@@ -130,4 +131,6 @@ rdrand_modevent(module_t mod, int type, 
 	return (error);
 }
 
-LIVE_ENTROPY_SRC_MODULE(random_rdrand, rdrand_modevent, 1);
+DEV_MODULE(rdrand, rdrand_modevent, NULL);
+MODULE_VERSION(rdrand, 1);
+MODULE_DEPEND(rdrand, randomdev, 1, 1, 1);

Modified: projects/random_number_generator/sys/dev/random/live_entropy_sources.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/live_entropy_sources.c	Sun Nov 10 14:18:05 2013	(r257917)
+++ projects/random_number_generator/sys/dev/random/live_entropy_sources.c	Sun Nov 10 16:33:14 2013	(r257918)
@@ -58,7 +58,7 @@ static struct les_head sources = LIST_HE
 static struct sx les_lock; /* need a sleepable lock */
 
 void
-live_entropy_source_register(struct random_hardware_source *rsource)
+live_entropy_source_register(struct live_entropy_source *rsource)
 {
 	struct live_entropy_sources *les;
 
@@ -73,7 +73,7 @@ live_entropy_source_register(struct rand
 }
 
 void
-live_entropy_source_deregister(struct random_hardware_source *rsource)
+live_entropy_source_deregister(struct live_entropy_source *rsource)
 {
 	struct live_entropy_sources *les = NULL;
 
@@ -93,43 +93,23 @@ live_entropy_source_deregister(struct ra
 static int
 live_entropy_source_handler(SYSCTL_HANDLER_ARGS)
 {
+	/* XXX: FIX!! Fixed array size */
+	char buf[128];
 	struct live_entropy_sources *les;
-	int error, count;
-
-	count = error = 0;
+	int count;
 
 	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;
-		}
+	buf[0] = '\0';
+	count = 0;
+	LIST_FOREACH(les, &sources, entries) {
+		strcat(buf, (count++ ? "," : ""));
+		strcat(buf, les->rsource->ident);
 	}
 
 	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");
+	return (SYSCTL_OUT(req, buf, strlen(buf)));
 }
 
 /*
@@ -142,11 +122,15 @@ live_entropy_sources_init(void *unused)
  * This function runs inside the RNG thread! Don't do anything silly!
  * Remember that we are NOT holding harvest_mtx on entry!
  */
+/* XXXRW: get_cyclecount() is cheap on most modern hardware, where cycle
+ * counters are built in, but on older hardware it will do a real time clock
+ * read which can be quite expensive.
+ */
 void
-live_entropy_sources_feed(int rounds, event_proc_f entropy_processor)
+live_entropy_sources_feed(void)
 {
 	static struct harvest event;
-	static uint8_t buf[HARVESTSIZE];
+	static u_int dest = 0;
 	struct live_entropy_sources *les;
 	int i, n;
 
@@ -158,23 +142,22 @@ live_entropy_sources_feed(int rounds, ev
 	 */
 	LIST_FOREACH(les, &sources, entries) {
 
-		for (i = 0; i < rounds; i++) {
+		/* XXX: FIX!! "2" is the number of pools in Yarrow */
+		for (i = 0; i < 2; i++) {
 			/*
 			 * This should be quick, since it's a live entropy
 			 * source.
 			 */
-			/* FIXME: Whine loudly if this didn't work. */
-			n = les->rsource->read(buf, sizeof(buf));
-			n = MIN(n, HARVESTSIZE);
-
+			/* XXX: FIX!! Whine loudly if this didn't work. */
+			n = les->rsource->read(event.entropy, HARVESTSIZE);
 			event.somecounter = get_cyclecount();
 			event.size = n;
 			event.bits = (n*8)/2;
 			event.source = les->rsource->source;
-			memcpy(event.entropy, buf, n);
+			event.destination = dest++;
 
 			/* Do the actual entropy insertion */
-			entropy_processor(&event);
+			harvest_process_event(&event);
 		}
 
 	}
@@ -183,6 +166,18 @@ live_entropy_sources_feed(int rounds, ev
 }
 
 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");
+}
+
+static void
 live_entropy_sources_deinit(void *unused)
 {
 

Modified: projects/random_number_generator/sys/dev/random/live_entropy_sources.h
==============================================================================
--- projects/random_number_generator/sys/dev/random/live_entropy_sources.h	Sun Nov 10 14:18:05 2013	(r257917)
+++ projects/random_number_generator/sys/dev/random/live_entropy_sources.h	Sun Nov 10 16:33:14 2013	(r257918)
@@ -35,26 +35,21 @@
  * specified or approximate amount of entropy immediately upon request or within
  * an acceptable amount of time.
  */
+struct live_entropy_source {
+	const char		*ident;
+	enum esource		source;
+	random_read_func_t	*read;
+};
+
 struct live_entropy_sources {
 	LIST_ENTRY(live_entropy_sources) entries;	/* list of providers */
-	struct random_hardware_source	*rsource;	/* associated random adaptor */
+	struct live_entropy_source	*rsource;	/* associated random adaptor */
 };
 
 extern struct mtx live_mtx;
 
-void live_entropy_source_register(struct random_hardware_source *);
-void live_entropy_source_deregister(struct random_hardware_source *);
-void live_entropy_sources_feed(int, event_proc_f);
-
-#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);
+void live_entropy_source_register(struct live_entropy_source *);
+void live_entropy_source_deregister(struct live_entropy_source *);
+void live_entropy_sources_feed(void);
 
 #endif /* SYS_DEV_RANDOM_LIVE_ENTROPY_SOURCES_H_INCLUDED */

Modified: projects/random_number_generator/sys/dev/random/nehemiah.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/nehemiah.c	Sun Nov 10 14:18:05 2013	(r257917)
+++ projects/random_number_generator/sys/dev/random/nehemiah.c	Sun Nov 10 16:33:14 2013	(r257918)
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2013 Mark R V Murray
+ * Copyright (c) 2013 David E. O'Brien <obrien@NUXI.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -30,6 +31,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
+#include <sys/conf.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/module.h>
@@ -52,13 +54,13 @@ static void random_nehemiah_init(void);
 static void random_nehemiah_deinit(void);
 static int random_nehemiah_read(void *, int);
 
-static struct random_hardware_source random_nehemiah = {
+static struct live_entropy_source random_nehemiah = {
 	.ident = "Hardware, VIA Nehemiah Padlock RNG",
 	.source = RANDOM_PURE_NEHEMIAH,
 	.read = random_nehemiah_read
 };
 
-/* TODO: now that the Davies-Meyer hash is gone and we only use
+/* XXX: FIX? TODO? now that the Davies-Meyer hash is gone and we only use
  * the 'xstore' instruction, do we still need to preserve the
  * FPU state with fpu_kern_(enter|leave)() ?
  */
@@ -75,7 +77,7 @@ VIA_RNG_store(void *buf)
 #ifdef __GNUCLIKE_ASM
 	__asm __volatile(
 		"movl	$0,%%edx\n\t"
-		".byte	0x0f, 0xa7, 0xc0" /* xstore */
+		"xstore"
 			: "=a" (retval), "+d" (rate), "+D" (buf)
 			:
 			: "memory"
@@ -154,4 +156,6 @@ nehemiah_modevent(module_t mod, int type
 	return (error);
 }
 
-LIVE_ENTROPY_SRC_MODULE(nehemiah, nehemiah_modevent, 1);
+DEV_MODULE(nehemiah, nehemiah_modevent, NULL);
+MODULE_VERSION(nehemiah, 1);
+MODULE_DEPEND(nehemiah, randomdev, 1, 1, 1);

Modified: projects/random_number_generator/sys/dev/random/random_adaptors.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/random_adaptors.c	Sun Nov 10 14:18:05 2013	(r257917)
+++ projects/random_number_generator/sys/dev/random/random_adaptors.c	Sun Nov 10 16:33:14 2013	(r257918)
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
 #include <sys/unistd.h>
 
 #include <dev/random/randomdev.h>
-#include <dev/random/randomdev_soft.h>
 #include <dev/random/random_adaptors.h>
 
 LIST_HEAD(adaptors_head, random_adaptors);
@@ -53,11 +52,11 @@ static struct sx adaptors_lock; /* need 
 /* List for the dynamic sysctls */
 static struct sysctl_ctx_list random_clist;
 
-struct random_adaptor *random_adaptor;
+struct random_adaptor *random_adaptor = NULL;
 
 MALLOC_DEFINE(M_ENTROPY, "entropy", "Entropy harvesting buffers and data structures");
 
-int
+void
 random_adaptor_register(const char *name, struct random_adaptor *rsp)
 {
 	struct random_adaptors *rpp;
@@ -72,10 +71,30 @@ random_adaptor_register(const char *name
 	LIST_INSERT_HEAD(&adaptors, rpp, entries);
 	sx_xunlock(&adaptors_lock);
 
-	return (0);
+	random_adaptor_choose();
+}
+
+void
+random_adaptor_deregister(const char *name)
+{
+	struct random_adaptors *rpp;
+
+	KASSERT(name != NULL, ("invalid input to %s", __func__));
+
+	sx_xlock(&adaptors_lock);
+	LIST_FOREACH(rpp, &adaptors, entries)
+		if (strcmp(rpp->name, name) == 0) {
+			LIST_REMOVE(rpp, entries);
+			break;
+		}
+	sx_xunlock(&adaptors_lock);
+	if (rpp != NULL)
+		free(rpp, M_ENTROPY);
+
+	random_adaptor_choose();
 }
 
-struct random_adaptor *
+static struct random_adaptor *
 random_adaptor_get(const char *name)
 {
 	struct random_adaptors	*rpp;
@@ -95,91 +114,90 @@ random_adaptor_get(const char *name)
 }
 
 /*
- * Walk a list of registered random(4) adaptors and pick the last non-selected
- * one.
- *
- * If none are selected, use yarrow if available.
+ * Walk a list of registered random(4) adaptors and pick either a requested
+ * one or the highest priority one, whichever comes first. Panic on failure
+ * as the fallback must be the "dummy" adaptor.
  */
 void
-random_adaptor_choose(struct random_adaptor **adaptor)
+random_adaptor_choose(void)
 {
 	char			 rngs[128], *token, *cp;
 	struct random_adaptors	*rppi;
-	unsigned		 primax;
+	struct random_adaptor	*random_adaptor_previous;
+	u_int			 primax;
 
-	KASSERT(adaptor != NULL, ("pre-conditions failed"));
+	random_adaptor_previous = random_adaptor;
 
-	*adaptor = NULL;
+	random_adaptor = NULL;
 	if (TUNABLE_STR_FETCH("kern.random.active_adaptor", rngs, sizeof(rngs))) {
 		cp = rngs;
 
 		while ((token = strsep(&cp, ",")) != NULL)
-			if ((*adaptor = random_adaptor_get(token)) != NULL)
+			if ((random_adaptor = random_adaptor_get(token)) != NULL) {
+				printf("random: selecting requested adaptor <%s>\n",
+				    random_adaptor->ident);
 				break;
-			else if (bootverbose)
-				printf("%s random adaptor is not available,"
-				    " skipping\n", token);
+			}
+			else
+				printf("random: requested adaptor <%s> not available\n",
+				    token);
 	}
 
-	if (*adaptor == NULL) {
+	primax = 0U;
+	if (random_adaptor == NULL) {
 		/*
 		 * Fall back to the highest priority item on the available
 		 * RNG list.
 		 */
 		sx_slock(&adaptors_lock);
-
-		primax = 0U;
 		LIST_FOREACH(rppi, &adaptors, entries) {
 			if (rppi->rsp->priority >= primax) {
+				random_adaptor = rppi->rsp;
 				primax = rppi->rsp->priority;
-				*adaptor = rppi->rsp;
 			}
 		}
-
 		sx_sunlock(&adaptors_lock);
-
-		if (bootverbose && *adaptor)
-			printf("Falling back to <%s> random adaptor\n",
-			    (*adaptor)->ident);
+		if (random_adaptor != NULL)
+			printf("random: selecting highest priority adaptor <%s>\n",
+			    random_adaptor->ident);
 	}
-}
 
-static void
-random_adaptors_deinit(void *unused)
-{
+	KASSERT(random_adaptor != NULL, ("adaptor not found"));
 
-	sx_destroy(&adaptors_lock);
-	sysctl_ctx_free(&random_clist);
+	/* If we are changing adaptors, deinit the old and init the new. */
+	if (random_adaptor != random_adaptor_previous) {
+		if (random_adaptor_previous != NULL)
+			(random_adaptor_previous->deinit)();
+		(random_adaptor->init)();
+	}
 }
 
 static int
 random_sysctl_adaptors_handler(SYSCTL_HANDLER_ARGS)
 {
-	struct random_adaptors	*rpp;
-	int error, count;
-
-	count = error = 0;
+	/* XXX: FIX!! Fixed array size, but see below, this may be OK */
+	char buf[128], *pbuf;
+	struct random_adaptors *rpp;
+	int count, snp;
+	size_t lbuf;
 
 	sx_slock(&adaptors_lock);
 
-	if (LIST_EMPTY(&adaptors))
-		error = SYSCTL_OUT(req, "", 0);
-	else {
-		LIST_FOREACH(rpp, &adaptors, entries) {
-
-			error = SYSCTL_OUT(req, ",", count++ ? 1 : 0);
-			if (error)
-				break;
-
-			error = SYSCTL_OUT(req, rpp->name, strlen(rpp->name));
-			if (error)
-				break;
-		}
+	buf[0] = '\0';
+	pbuf = buf;
+	lbuf = 256;
+	count = 0;
+	LIST_FOREACH(rpp, &adaptors, entries) {
+		snp = snprintf(pbuf, lbuf, "%s%s(%d)",
+		    (count++ ? "," : ""), rpp->name, rpp->rsp->priority);
+		KASSERT(snp > 0, ("buffer overflow"));
+		lbuf -= (size_t)snp;
+		pbuf += snp;
 	}
 
 	sx_sunlock(&adaptors_lock);
 
-	return (error);
+	return (SYSCTL_OUT(req, buf, strlen(buf)));
 }
 
 static int
@@ -211,8 +229,9 @@ random_sysctl_active_adaptor_handler(SYS
 	return (error);
 }
 
+/* ARGSUSED */
 static void
-random_adaptors_init(void *unused)
+random_adaptors_init(void *unused __unused)
 {
 
 	SYSCTL_PROC(_kern_random, OID_AUTO, adaptors,
@@ -226,23 +245,59 @@ random_adaptors_init(void *unused)
 	    "Active Random Number Generator Adaptor");
 
 	sx_init(&adaptors_lock, "random_adaptors");
+
+	/* This dummy "thing" is not a module by itself, but part of the
+	 * randomdev module.
+	 */
+	random_adaptor_register("dummy", &dummy_random);
 }
 
-SYSCTL_NODE(_kern, OID_AUTO, random, CTLFLAG_RW, 0, "Random Number Generator");
+/* ARGSUSED */
+static void
+random_adaptors_deinit(void *unused __unused)
+{
+	/* Don't do this! Panic will follow. */
+	/* random_adaptor_deregister("dummy"); */
 
-SYSINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST, random_adaptors_init,
-    NULL);
-SYSUNINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST,
-    random_adaptors_deinit, NULL);
+	sx_destroy(&adaptors_lock);
+	sysctl_ctx_free(&random_clist);
+}
 
+/* XXX: FIX!! Move this to where its not so well hidden, like randomdev[_soft].c, maybe. */
+/*
+ * First seed.
+ *
+ * It turns out this is bloody dangerous. I was fiddling with code elsewhere
+ * and managed to get conditions where a safe (i.e. seeded) entropy device should
+ * not have been possible. This managed to hide that by seeding the device anyway.
+ * As crap randomness is not directly distinguishable from good randomness, this
+ * could have gone unnoticed for quite a while.
+ *
+ * Very luckily, the probe-time entropy is very nearly good enough to cause a
+ * first seed all of the time, and the default settings for interrupt- and SWI
+ * entropy harvesting causes a proper, safe, first (re)seed in short order
+ * after that.
+ *
+ * That said, the below would be useful where folks are more concerned with
+ * a quick start than with extra paranoia.
+ *
+ * markm - October 2013.
+ */
+#ifdef RANDOM_AUTOSEED
+/* ARGSUSED */
 static void
-random_adaptors_reseed(void *unused)
+random_adaptors_seed(void *unused __unused)
 {
-
-	(void)unused;
+ 
 	if (random_adaptor != NULL)
 		(*random_adaptor->reseed)();
 	arc4rand(NULL, 0, 1);
 }
-SYSINIT(random_reseed, SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST,
+SYSINIT(random_seed, SI_SUB_INTRINSIC_POST, SI_ORDER_LAST,
     random_adaptors_reseed, NULL);
+#endif /*  RANDOM_AUTOSEED */
+
+SYSINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_SECOND,
+    random_adaptors_init, NULL);
+SYSUNINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_SECOND,
+    random_adaptors_deinit, NULL);

Modified: projects/random_number_generator/sys/dev/random/random_adaptors.h
==============================================================================
--- projects/random_number_generator/sys/dev/random/random_adaptors.h	Sun Nov 10 14:18:05 2013	(r257917)
+++ projects/random_number_generator/sys/dev/random/random_adaptors.h	Sun Nov 10 16:33:14 2013	(r257918)
@@ -29,43 +29,31 @@
 #ifndef SYS_DEV_RANDOM_RANDOM_ADAPTORS_H_INCLUDED
 #define SYS_DEV_RANDOM_RANDOM_ADAPTORS_H_INCLUDED
 
-#include <sys/eventhandler.h>
-
 MALLOC_DECLARE(M_ENTROPY);
 
+struct random_adaptor {
+	struct selinfo		rsel;
+	const char		*ident;
+	int			seeded;
+	u_int			priority;
+	random_init_func_t	*init;
+	random_deinit_func_t	*deinit;
+	random_block_func_t	*block;
+	random_read_func_t	*read;
+	random_poll_func_t	*poll;
+	random_reseed_func_t	*reseed;
+};
+
 struct random_adaptors {
 	LIST_ENTRY(random_adaptors) entries;	/* list of providers */
 	const char		*name;		/* name of random adaptor */
 	struct random_adaptor	*rsp;
 };
 
-struct random_adaptor *random_adaptor_get(const char *);
-int random_adaptor_register(const char *, struct random_adaptor *);
-void random_adaptor_choose(struct random_adaptor **);
+void random_adaptor_register(const char *, struct random_adaptor *);
+void random_adaptor_deregister(const char *);
+void random_adaptor_choose(void);
 
 extern struct random_adaptor *random_adaptor;
 
-/*
- * random_adaptor's should be registered prior to
- * random module (SI_SUB_DRIVERS/SI_ORDER_MIDDLE)
- */
-#define RANDOM_ADAPTOR_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);
-
-typedef void (*random_adaptor_attach_hook)(void *, struct random_adaptor *);
-EVENTHANDLER_DECLARE(random_adaptor_attach, random_adaptor_attach_hook);
-
-/* kern.random sysctls */
-#ifdef SYSCTL_DECL	/* from sysctl.h */
-SYSCTL_DECL(_kern_random);
-#endif /* SYSCTL_DECL */
-
 #endif /* SYS_DEV_RANDOM_RANDOM_ADAPTORS_H_INCLUDED */

Modified: projects/random_number_generator/sys/dev/random/random_harvestq.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/random_harvestq.c	Sun Nov 10 14:18:05 2013	(r257917)
+++ projects/random_number_generator/sys/dev/random/random_harvestq.c	Sun Nov 10 16:33:14 2013	(r257918)
@@ -47,16 +47,20 @@ __FBSDID("$FreeBSD$");
 #include <sys/unistd.h>
 
 #include <machine/cpu.h>
-#include <machine/vmparam.h>
 
 #include <dev/random/randomdev.h>
-#include <dev/random/randomdev_soft.h>
 #include <dev/random/random_adaptors.h>
 #include <dev/random/random_harvestq.h>
 #include <dev/random/live_entropy_sources.h>
 #include <dev/random/rwfile.h>
 
-#define RANDOM_FIFO_MAX	1024	/* How many events to queue up */
+/*
+ * How many events to queue up. We create this many items in
+ * an 'empty' queue, then transfer them to the 'harvest' queue with
+ * supplied junk. When used, they are transferred back to the
+ * 'empty' queue.
+ */
+#define RANDOM_FIFO_MAX	1024
 
 /*
  * The harvest mutex protects the consistency of the entropy fifos and
@@ -66,7 +70,6 @@ struct mtx	harvest_mtx;
 
 /* Lockable FIFO queue holding entropy buffers */
 struct entropyfifo {
-	int count;
 	STAILQ_HEAD(harvestlist, harvest) head;
 };
 
@@ -76,6 +79,9 @@ static struct entropyfifo emptyfifo;
 /* Harvested entropy */
 static struct entropyfifo harvestfifo;
 
+/* Function called to process one harvested stochastic event */
+void (*harvest_process_event)(struct harvest *);
+
 /* <0 to end the kthread, 0 to let it run, 1 to flush the harvest queues */
 int random_kthread_control = 0;
 
@@ -87,6 +93,7 @@ static struct entropy_cache {
 	int already_read;
 } entropy_files[] = {
 	{ "/entropy", 0 },
+	{ "/var/db/entropy-file", 0 },
 	{ "/var/db/entropy/saved-entropy.1", 0 },
 	{ "/var/db/entropy/saved-entropy.2", 0 },
 	{ "/var/db/entropy/saved-entropy.3", 0 },
@@ -97,53 +104,32 @@ static struct entropy_cache {
 	{ "/var/db/entropy/saved-entropy.8", 0 },
 	{ NULL, 0 }
 };
-#endif
 
 /* Deal with entropy cached externally if this is present.
  * Lots of policy may eventually arrive in this function.
- * Called after / is mounted.
+ * Called after any volume is mounted; this way we can keep
+ * looking for files in (say) /var/db/entropy/...
+ * 
+ * We keep a cache of files read so we don't keep re-reading them.
+ *
+ * Optionally (a compile-time option) overwrite these files.
  */
 static void
 random_harvestq_cache(void *arg1 __unused, struct mount *arg2 __unused,
     struct vnode *arg3 __unused, struct thread *arg4 __unused)
 {
-	static int boot_cache_read = 0;
-	uint8_t *keyfile, *data;
-	size_t size, i;
-#ifdef RANDOM_RWFILE
 	static int caches_read = 0;
 	struct entropy_cache *entropy_file;
-	uint8_t *zbuf;
 	int error;
-#endif
+	size_t i;
+	uint8_t *data;
 
-	/* Get stuff that may have been preloaded by loader(8) */
-	if (!boot_cache_read) {
-		boot_cache_read = 1;
-		keyfile = preload_search_by_type("/boot/entropy");
-		if (keyfile != NULL) {
-			data = preload_fetch_addr(keyfile);
-			size = preload_fetch_size(keyfile);
-			if (data != NULL && size != 0) {
-				for (i = 0; i < size; i += 16)
-					random_harvestq_internal(get_cyclecount(), data + i, 16, 16, RANDOM_CACHED);
-				printf("random: read %zu bytes from preloaded cache\n", size);
-				bzero(data, size);
-			}
-			else
-				if (bootverbose)
-					printf("random: no preloaded entropy cache\n");
-		}
-	}
-
-#ifdef RANDOM_RWFILE
 	/* Read and attempt to overwrite the entropy cache files.
 	 * If the file exists, can be read and then overwritten,
 	 * then use it. Ignore it otherwise, but print out what is
 	 * going on.
 	 */
 	data = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK);
-	zbuf = __DECONST(void *, zero_region);
 	for (entropy_file = entropy_files; entropy_file->filename; entropy_file++) {
 		if (entropy_file->already_read)
 			break;
@@ -151,12 +137,12 @@ random_harvestq_cache(void *arg1 __unuse
 		if (error == 0) {
 			printf("random: entropy cache '%s' provides %ld bytes\n", entropy_file->filename, (long)PAGE_SIZE);
 #ifdef RANDOM_RWFILE_WRITE_OK /* Not defined so writes disabled for now */
-			error = randomdev_write_file(entropy_file->filename, zbuf, PAGE_SIZE);
+			error = randomdev_write_file(entropy_file->filename, zero_region, PAGE_SIZE);
 			if (error == 0) {
-				printf("random: entropy cache '%s' contents used and successfully overwritten\n", entropy_file->filename);
+				printf("random: entropy cache '%s' successfully overwritten\n", entropy_file->filename);
 #endif
 				for (i = 0; i < PAGE_SIZE; i += 16)
-					random_harvestq_internal(get_cyclecount(), data + i, 16, 16, RANDOM_CACHED);
+					random_harvestq_internal(data + i, 16, 16, RANDOM_CACHED);
 				entropy_file->already_read = 1;
 				caches_read++;
 #ifdef RANDOM_RWFILE_WRITE_OK /* Not defined so writes disabled for now */
@@ -173,21 +159,19 @@ random_harvestq_cache(void *arg1 __unuse
 	free(data, M_ENTROPY);
 
 	if (bootverbose)
-		printf("random: total entropy cache files read = %d\n", caches_read);
-#endif
+		printf("random: total entropy cache files read so far = %d\n", caches_read);
 }
+/* Invoke the above every time a FS is mounted; this way we can keep going after cached entropy */
 EVENTHANDLER_DEFINE(vfs_mounted, random_harvestq_cache, NULL, 0);
+#endif /* RANDOM_RWFILE */
 
 static void
-random_kthread(void *arg)
+random_kthread(void *arg __unused)
 {
 	STAILQ_HEAD(, harvest) local_queue;
 	struct harvest *event = NULL;
-	int local_count;
-	event_proc_f entropy_processor = arg;
 
 	STAILQ_INIT(&local_queue);
-	local_count = 0;
 
 	/* Process until told to stop */
 	mtx_lock_spin(&harvest_mtx);
@@ -199,8 +183,6 @@ random_kthread(void *arg)
 		 * queue for processing while not holding the mutex.
 		 */
 		STAILQ_CONCAT(&local_queue, &harvestfifo.head);
-		local_count += harvestfifo.count;
-		harvestfifo.count = 0;
 
 		/*
 		 * Deal with events, if any.
@@ -209,22 +191,16 @@ random_kthread(void *arg)
 		if (!STAILQ_EMPTY(&local_queue)) {
 			mtx_unlock_spin(&harvest_mtx);
 			STAILQ_FOREACH(event, &local_queue, next)
-				entropy_processor(event);
+				harvest_process_event(event);
 			mtx_lock_spin(&harvest_mtx);
 			STAILQ_CONCAT(&emptyfifo.head, &local_queue);
-			emptyfifo.count += local_count;
-			local_count = 0;
 		}
 
-		KASSERT(local_count == 0, ("random_kthread: local_count %d",
-		    local_count));
-
 		/*
-		 * Do only one round of the hardware sources for now.
-		 * Later we'll need to make it rate-adaptive.
+		 * Give the fast hardware sources a go
 		 */
 		mtx_unlock_spin(&harvest_mtx);
-		live_entropy_sources_feed(1, entropy_processor);
+		live_entropy_sources_feed();
 		mtx_lock_spin(&harvest_mtx);
 
 		/*
@@ -242,14 +218,16 @@ random_kthread(void *arg)
 	}
 	mtx_unlock_spin(&harvest_mtx);
 
-	random_set_wakeup_exit(&random_kthread_control);
+	randomdev_set_wakeup_exit(&random_kthread_control);
 	/* NOTREACHED */
 }
 
 void
-random_harvestq_init(event_proc_f cb)
+random_harvestq_init(void (*event_processor)(struct harvest *))
 {
+	uint8_t *keyfile, *data;
 	int error, i;
+	size_t size, j;
 	struct harvest *np;
 
 	/* Initialise the harvest fifos */
@@ -260,20 +238,39 @@ random_harvestq_init(event_proc_f cb)
 		np = malloc(sizeof(struct harvest), M_ENTROPY, M_WAITOK);
 		STAILQ_INSERT_TAIL(&emptyfifo.head, np, next);
 	}
-	emptyfifo.count = RANDOM_FIFO_MAX;
 
 	/* Will contain the queued-up events. */
 	STAILQ_INIT(&harvestfifo.head);
-	harvestfifo.count = 0;
+
+	/* Point to the correct event_processing function */
+	harvest_process_event = event_processor;
 
 	mtx_init(&harvest_mtx, "entropy harvest mutex", NULL, MTX_SPIN);
 
 	/* Start the hash/reseed thread */
-	error = kproc_create(random_kthread, cb,
+	error = kproc_create(random_kthread, NULL,
 	    &random_kthread_proc, RFHIGHPID, 0, "rand_harvestq"); /* RANDOM_CSPRNG_NAME */
 
 	if (error != 0)
 		panic("Cannot create entropy maintenance thread.");
+
+	/* Get entropy that may have been preloaded by loader(8)
+	 * and use it to pre-charge the entropy harvest queue.
+	 */
+	keyfile = preload_search_by_type("/boot/entropy");
+	if (keyfile != NULL) {
+		data = preload_fetch_addr(keyfile);
+		size = preload_fetch_size(keyfile);
+		if (data != NULL && size != 0) {
+			for (j = 0; j < size; j += 16)
+				random_harvestq_internal(data + j, 16, 16, RANDOM_CACHED);
+			printf("random: read %zu bytes from preloaded cache\n", size);
+			bzero(data, size);
+		}
+		else
+			printf("random: no preloaded entropy cache\n");
+	}
+
 }
 
 void
@@ -287,13 +284,11 @@ random_harvestq_deinit(void)
 		STAILQ_REMOVE_HEAD(&emptyfifo.head, next);
 		free(np, M_ENTROPY);
 	}
-	emptyfifo.count = 0;
 	while (!STAILQ_EMPTY(&harvestfifo.head)) {
 		np = STAILQ_FIRST(&harvestfifo.head);
 		STAILQ_REMOVE_HEAD(&harvestfifo.head, next);
 		free(np, M_ENTROPY);
 	}
-	harvestfifo.count = 0;
 
 	mtx_destroy(&harvest_mtx);
 }
@@ -308,44 +303,40 @@ random_harvestq_deinit(void)
  * check a few lines below. This includes the "always-on" sources
  * like the Intel "rdrand" or the VIA Nehamiah "xstore" sources.
  */
+/* XXXRW: get_cyclecount() is cheap on most modern hardware, where cycle
+ * counters are built in, but on older hardware it will do a real time clock
+ * read which can be quite expensive.
+ */
 void
-random_harvestq_internal(u_int64_t somecounter, const void *entropy,
-    u_int count, u_int bits, enum esource origin)
+random_harvestq_internal(const void *entropy, u_int count, u_int bits,
+    enum esource origin)
 {
+	static u_int destination[ENTROPYSOURCE];
 	struct harvest *event;
 
 	KASSERT(origin >= RANDOM_START && origin < ENTROPYSOURCE,
 	    ("random_harvest_internal: origin %d invalid\n", origin));
 
-	/* Lockless read to avoid lock operations if fifo is full. */
-	if (harvestfifo.count >= RANDOM_FIFO_MAX)
+	/* Lockless check to avoid lock operations if queue is empty. */
+	if (STAILQ_EMPTY(&emptyfifo.head))
 		return;
 
 	mtx_lock_spin(&harvest_mtx);
 
-	/*
-	 * On't overfill the harvest queue; this could steal all
-	 * our memory.
-	 */
-	if (harvestfifo.count < RANDOM_FIFO_MAX) {
-		event = STAILQ_FIRST(&emptyfifo.head);
-		if (event != NULL) {
-			/* Add the harvested data to the fifo */
-			STAILQ_REMOVE_HEAD(&emptyfifo.head, next);
-			emptyfifo.count--;
-			event->somecounter = somecounter;
-			event->size = count;
-			event->bits = bits;
-			event->source = origin;
-
-			/* XXXX Come back and make this dynamic! */
-			count = MIN(count, HARVESTSIZE);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201311101633.rAAGXFKp045009>