svn commit: r257918 - in projects/random_number_generator/sys: conf dev/random modules modules/padlock_rng modules/random modules/rdrand_rng sys
Mark Murray
markm at FreeBSD.org
Sun Nov 10 16:33:17 UTC 2013
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 at 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 at 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 ***
More information about the svn-src-projects
mailing list