svn commit: r258288 - projects/random_number_generator/sys/dev/random
Mark Murray
markm at FreeBSD.org
Sun Nov 17 23:43:52 UTC 2013
Author: markm
Date: Sun Nov 17 23:43:50 2013
New Revision: 258288
URL: http://svnweb.freebsd.org/changeset/base/258288
Log:
Snapshot of WIP.
Big refactor of the random_adaptors code to remove unnecessary layering.
Also Yet Another Big Sweep Of Old code, essentially a rewrite of anything dodgy looking with my mind on efficiency. Some excess code is removed, and block copies are eliminated where possible.
Locking is broken. This will be fixed in a follow-up.
Modified:
projects/random_number_generator/sys/dev/random/dummy_rng.c
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/yarrow.c
projects/random_number_generator/sys/dev/random/yarrow.h
Modified: projects/random_number_generator/sys/dev/random/dummy_rng.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/dummy_rng.c Sun Nov 17 23:28:10 2013 (r258287)
+++ projects/random_number_generator/sys/dev/random/dummy_rng.c Sun Nov 17 23:43:50 2013 (r258288)
@@ -28,94 +28,66 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_random.h"
+
#include <sys/param.h>
+#include <sys/conf.h>
#include <sys/fcntl.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
-#include <sys/mutex.h>
#include <sys/random.h>
#include <sys/syslog.h>
#include <sys/systm.h>
-#include <sys/time.h>
#include <dev/random/randomdev.h>
#include <dev/random/random_adaptors.h>
-static struct mtx dummy_random_mtx;
-
-/* If no entropy device is loaded, don't spam the console with warnings */
-static int warned = 0;
-
-/* Used to fake out unused random calls in random_adaptor */
-static void
-random_null_func(void)
-{
-}
-
static int
-dummy_random_poll(int events __unused, struct thread *td __unused)
+dummy_random_zero(void)
{
return (0);
}
-static int
-dummy_random_block(int flag)
-{
- int error = 0;
-
- 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
-dummy_random_init(void)
+dummy_random(void)
{
-
- mtx_init(&dummy_random_mtx, "sleep mtx for dummy_random",
- NULL, MTX_DEF);
}
+/* ARGSUSED */
static void
-dummy_random_deinit(void)
+dummy_random_init(struct mtx *mtx __unused)
{
- mtx_destroy(&dummy_random_mtx);
+ randomdev_init_reader(dummy_random_read_phony);
}
/* This is used only by the internal read_random(9) call, and then only
* if no entropy processor is loaded.
*
- * DO NOT, REPEAT, DO NOT add this to the "struct random_adaptor" below!
- *
* Make a token effort to provide _some_ kind of output. No warranty of
* the quality of this output is made, mainly because its lousy.
*
+ * This is only used by the internal read_random(9) call when no other
+ * adaptor is active.
+ *
+ * It has external scope due to the way things work in
+ * randomdev_[de]init_reader() that the rest of the world doesn't need to
+ * know about.
+ *
* Caveat Emptor.
*/
-int
-dummy_random_read_phony(void *buf, int count)
+u_int
+dummy_random_read_phony(void *buf, u_int count)
{
+ /* If no entropy device is loaded, don't spam the console with warnings */
+ static int warned = 0;
u_long randval;
int size, i;
if (!warned) {
- log(LOG_WARNING, "random device not loaded; using insecure pseudo-random number generator\n");
+ log(LOG_WARNING, "random device not loaded/active; using insecure pseudo-random number generator\n");
warned = 1;
}
@@ -132,13 +104,12 @@ dummy_random_read_phony(void *buf, int c
}
struct random_adaptor randomdev_dummy = {
- .ra_ident = "Dummy entropy device",
- .ra_init = dummy_random_init,
- .ra_deinit = dummy_random_deinit,
- .ra_block = dummy_random_block,
- .ra_poll = dummy_random_poll,
- .ra_read = (random_adaptor_read_func_t *)random_null_func,
- .ra_reseed = (random_adaptor_reseed_func_t *)random_null_func,
- .ra_seeded = 0, /* This device can never be seeded */
+ .ra_ident = "Dummy",
.ra_priority = 1, /* Bottom priority, so goes to last position */
+ .ra_reseed = dummy_random,
+ .ra_seeded = (random_adaptor_seeded_func_t *)dummy_random_zero,
+ .ra_read = (random_adaptor_read_func_t *)dummy_random_zero,
+ .ra_write = (random_adaptor_write_func_t *)dummy_random_zero,
+ .ra_init = dummy_random_init,
+ .ra_deinit = dummy_random,
};
Modified: projects/random_number_generator/sys/dev/random/ivy.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/ivy.c Sun Nov 17 23:28:10 2013 (r258287)
+++ projects/random_number_generator/sys/dev/random/ivy.c Sun Nov 17 23:43:50 2013 (r258288)
@@ -52,10 +52,10 @@ __FBSDID("$FreeBSD$");
#define RETRY_COUNT 10
-static int random_ivy_read(void *, int);
+static u_int random_ivy_read(void *, u_int);
static struct live_entropy_source random_ivy = {
- .les_ident = "Hardware, Intel IvyBridge+ RNG",
+ .les_ident = "Intel IvyBridge+ RNG",
.les_source = RANDOM_PURE_RDRAND,
.les_read = random_ivy_read
};
@@ -85,15 +85,17 @@ ivy_rng_store(long *buf)
#endif
}
-static int
-random_ivy_read(void *buf, int c)
+/* It is specifically allowed that buf is a multiple of sizeof(long) */
+static u_int
+random_ivy_read(void *buf, u_int c)
{
long *b;
- int count;
+ u_int count;
KASSERT(c % sizeof(long) == 0, ("partial read %d", c));
- for (b = buf, count = c; count > 0; count -= sizeof(long), b++) {
- if (ivy_rng_store(b) == 0)
+ b = buf;
+ for (count = c; count > 0; count -= sizeof(long)) {
+ if (ivy_rng_store(b++) == 0)
break;
}
return (c - count);
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 17 23:28:10 2013 (r258287)
+++ projects/random_number_generator/sys/dev/random/live_entropy_sources.c Sun Nov 17 23:43:50 2013 (r258288)
@@ -28,6 +28,8 @@
#include <sys/param.h>
__FBSDID("$FreeBSD$");
+#include "opt_random.h"
+
#include <sys/kernel.h>
#include <sys/libkern.h>
#include <sys/lock.h>
@@ -52,7 +54,7 @@ __FBSDID("$FreeBSD$");
/*
* The les_lock protects the consistency of the "struct les_head les_sources"
*/
-static struct sx les_lock; /* need a sleepable lock */
+static struct sx les_lock; /* Need a sleepable lock for the sbuf/sysctl stuff. */
LIST_HEAD(les_head, live_entropy_sources);
static struct les_head les_sources = LIST_HEAD_INITIALIZER(les_sources);
@@ -124,7 +126,6 @@ live_entropy_source_handler(SYSCTL_HANDL
*
* BEWARE!!!
* 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
@@ -135,7 +136,8 @@ live_entropy_sources_feed(void)
{
static struct harvest_event event;
struct live_entropy_sources *lles;
- int i, n, read_rate;
+ int i, read_rate;
+ u_int n;
sx_slock(&les_lock);
@@ -156,7 +158,7 @@ live_entropy_sources_feed(void)
/* This *must* be quick, since it's a live entropy source. */
n = lles->lles_rsource->les_read(event.he_entropy, HARVESTSIZE);
KASSERT((n > 0 && n <= HARVESTSIZE), ("very bad return from les_read (= %d) in %s", n, __func__));
- memset(event.he_entropy + n, 0, HARVESTSIZE - (u_int)n);
+ memset(event.he_entropy + n, 0, HARVESTSIZE - n);
/* Do the actual entropy insertion */
harvest_process_event(&event);
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 17 23:28:10 2013 (r258287)
+++ projects/random_number_generator/sys/dev/random/live_entropy_sources.h Sun Nov 17 23:43:50 2013 (r258288)
@@ -30,6 +30,8 @@
#ifndef SYS_DEV_RANDOM_LIVE_ENTROPY_SOURCES_H_INCLUDED
#define SYS_DEV_RANDOM_LIVE_ENTROPY_SOURCES_H_INCLUDED
+typedef u_int random_live_read_func_t(void *, u_int);
+
/*
* Live entropy source is a source of entropy that can provide
* specified or approximate amount of entropy immediately upon request or within
@@ -38,7 +40,7 @@
struct live_entropy_source {
const char *les_ident;
enum random_entropy_source les_source;
- random_adaptor_read_func_t *les_read;
+ random_live_read_func_t *les_read;
};
struct live_entropy_sources {
Modified: projects/random_number_generator/sys/dev/random/nehemiah.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/nehemiah.c Sun Nov 17 23:28:10 2013 (r258287)
+++ projects/random_number_generator/sys/dev/random/nehemiah.c Sun Nov 17 23:43:50 2013 (r258288)
@@ -50,10 +50,10 @@ __FBSDID("$FreeBSD$");
static void random_nehemiah_init(void);
static void random_nehemiah_deinit(void);
-static int random_nehemiah_read(void *, int);
+static u_int random_nehemiah_read(void *, u_int);
static struct live_entropy_source random_nehemiah = {
- .les_ident = "Hardware, VIA Nehemiah Padlock RNG",
+ .les_ident = "VIA Nehemiah Padlock RNG",
.les_source = RANDOM_PURE_NEHEMIAH,
.les_read = random_nehemiah_read
};
@@ -100,8 +100,9 @@ random_nehemiah_deinit(void)
fpu_kern_free_ctx(fpu_ctx_save);
}
-static int
-random_nehemiah_read(void *buf, int c)
+/* It is specifically allowed that buf is a multiple of sizeof(long) */
+static u_int
+random_nehemiah_read(void *buf, u_int c)
{
uint8_t *b;
size_t count, ret;
Modified: projects/random_number_generator/sys/dev/random/random_adaptors.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/random_adaptors.c Sun Nov 17 23:28:10 2013 (r258287)
+++ projects/random_number_generator/sys/dev/random/random_adaptors.c Sun Nov 17 23:43:50 2013 (r258288)
@@ -29,7 +29,11 @@
#include <sys/param.h>
__FBSDID("$FreeBSD$");
+#include "opt_random.h"
+
#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
#include <sys/libkern.h>
@@ -40,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/queue.h>
#include <sys/random.h>
#include <sys/sbuf.h>
+#include <sys/selinfo.h>
#include <sys/sx.h>
#include <sys/sysctl.h>
#include <sys/uio.h>
@@ -48,25 +53,105 @@ __FBSDID("$FreeBSD$");
#include <dev/random/randomdev.h>
#include <dev/random/random_adaptors.h>
-/* These are the data structures and associated items that need to be locked against
- * "under-the-feet" changes.
+/* The random_adaptors_lock protects random_adaptors_list and friends and random_adaptor.
+ * We need a sleepable lock for uiomove/block/poll/sbuf/sysctl.
*/
-static struct sx random_adaptors_lock; /* need a sleepable lock */
-
+static struct sx random_adaptors_lock;
LIST_HEAD(adaptors_head, random_adaptors);
static struct adaptors_head random_adaptors_list = LIST_HEAD_INITIALIZER(random_adaptors_list);
static struct random_adaptor *random_adaptor = NULL; /* Currently active adaptor */
-/* End of data items requiring adaptor lock protection */
+/* End of data items requiring random_adaptors_lock protection */
-/* The rate mutex protects the consistency of the read-rate logic. */
-struct mtx rate_mtx;
+/* The random_rate_mtx mutex protects the consistency of the read-rate logic. */
+struct mtx random_rate_mtx;
int random_adaptor_read_rate_cache;
-/* End of data items requiring rate mutex protection */
+/* End of data items requiring random_rate_mtx mutex protection */
+
+/* The random_reseed_mtx mutex protects seeding and polling/blocking.
+ * This is passed into the software entropy hasher/processor.
+ */
+struct mtx random_reseed_mtx;
+/* End of data items requiring random_reseed_mtx mutex protection */
-MALLOC_DEFINE(M_ENTROPY, "entropy", "Entropy harvesting buffers and data structures");
+static struct selinfo rsel;
+
+/* Utility routine to change active adaptor when the random_adaptors_list
+ * gets modified.
+ *
+ * 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 always be the "dummy" adaptor.
+ */
+static void
+random_adaptor_choose(void)
+{
+ char rngs[128], *token, *cp;
+ struct random_adaptors *rra, *rrai;
+ struct random_adaptor *random_adaptor_previous;
+ int primax;
+
+ /* We are going to be messing with random_adaptor.
+ * Exclusive lock is mandatory.
+ */
+ sx_assert(&random_adaptors_lock, SA_XLOCKED);
+
+ random_adaptor_previous = random_adaptor;
+
+ random_adaptor = NULL;
+ if (TUNABLE_STR_FETCH("kern.random.active_adaptor", rngs, sizeof(rngs))) {
+ cp = rngs;
-static void random_adaptor_choose(void);
+ while ((token = strsep(&cp, ",")) != NULL) {
+ LIST_FOREACH(rra, &random_adaptors_list, rra_entries)
+ if (strcmp(rra->rra_name, token) == 0) {
+ random_adaptor = rra->rra_ra;
+ break;
+ }
+ if (random_adaptor != NULL) {
+ printf("random: selecting requested adaptor <%s>\n",
+ random_adaptor->ra_ident);
+ break;
+ }
+ else
+ printf("random: requested adaptor <%s> not available\n",
+ token);
+ }
+ }
+ primax = 0;
+ if (random_adaptor == NULL) {
+ /*
+ * Fall back to the highest priority item on the available
+ * RNG list.
+ */
+ LIST_FOREACH(rrai, &random_adaptors_list, rra_entries) {
+ if (rrai->rra_ra->ra_priority >= primax) {
+ random_adaptor = rrai->rra_ra;
+ primax = rrai->rra_ra->ra_priority;
+ }
+ }
+ if (random_adaptor != NULL)
+ printf("random: selecting highest priority adaptor <%s>\n",
+ random_adaptor->ra_ident);
+ }
+
+ KASSERT(random_adaptor != NULL, ("adaptor not found"));
+
+ /* If we are changing adaptors, deinit the old and init the new. */
+ if (random_adaptor != random_adaptor_previous) {
+#ifdef RANDOM_DEBUG
+ printf("random: %s - changing from %s to %s\n", __func__,
+ (random_adaptor_previous == NULL ? "NULL" : random_adaptor_previous->ra_ident),
+ random_adaptor->ra_ident);
+#endif
+ if (random_adaptor_previous != NULL)
+ (random_adaptor_previous->ra_deinit)();
+ (random_adaptor->ra_init)(&random_reseed_mtx);
+ }
+}
+
+
+/* XXX: FIX!! Make sure we are not inserting a duplicate */
void
random_adaptor_register(const char *name, struct random_adaptor *ra)
{
@@ -79,12 +164,8 @@ random_adaptor_register(const char *name
rra->rra_ra = ra;
sx_xlock(&random_adaptors_lock);
-
- /* XXX: FIX!! Make sure we are not inserting a duplicate */
LIST_INSERT_HEAD(&random_adaptors_list, rra, rra_entries);
-
random_adaptor_choose();
-
sx_xunlock(&random_adaptors_lock);
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
@@ -99,80 +180,133 @@ random_adaptor_deregister(const char *na
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
sx_xlock(&random_adaptors_lock);
-
LIST_FOREACH(rra, &random_adaptors_list, rra_entries)
if (strcmp(rra->rra_name, name) == 0) {
LIST_REMOVE(rra, rra_entries);
break;
}
-
random_adaptor_choose();
- /* It is conceivable that there is no active random adaptor here,
- * e.g. at shutdown.
- */
-
sx_xunlock(&random_adaptors_lock);
- if (rra != NULL)
- free(rra, M_ENTROPY);
+ free(rra, M_ENTROPY);
}
+/*
+ * Per-instance structure.
+ *
+ * List of locks
+ * XXX: FIX!!
+ */
+struct random_adaptor_softc {
+ int oink;
+ int tweet;
+};
+
+static void
+random_adaptor_dtor(void *data)
+{
+ struct random_adaptor_softc *ras = data;
+
+ free(ras, M_ENTROPY);
+}
+
+/* ARGSUSED */
int
-random_adaptor_block(int flag)
+random_adaptor_open(struct cdev *dev __unused, int flags, int mode __unused, struct thread *td __unused)
{
- int ret;
+ struct random_adaptor_softc *ras;
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
- sx_slock(&random_adaptors_lock);
+ ras = malloc(sizeof(struct random_adaptor_softc), M_ENTROPY, M_WAITOK|M_ZERO);
+ /* XXX: FIX!! Set up softc here */
- ret = random_adaptor->ra_block(flag);
+ devfs_set_cdevpriv(ras, random_adaptor_dtor);
- sx_sunlock(&random_adaptors_lock);
+ /* Give the source a chance to do some pre-read/write startup */
+ if (flags & FREAD) {
+ sx_slock(&random_adaptors_lock);
+ (random_adaptor->ra_read)(NULL, 0);
+ sx_sunlock(&random_adaptors_lock);
+ } else if (flags & FWRITE) {
+ sx_slock(&random_adaptors_lock);
+ (random_adaptor->ra_write)(NULL, 0);
+ sx_sunlock(&random_adaptors_lock);
+ }
+
+ return (0);
+}
- return ret;
+/* ARGSUSED */
+int
+random_adaptor_close(struct cdev *dev __unused, int flags, int fmt __unused, struct thread *td __unused)
+{
+
+ KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
+
+ /* Give the source a chance to do some post-read/write shutdown */
+ if (flags & FREAD) {
+ sx_slock(&random_adaptors_lock);
+ (random_adaptor->ra_read)(NULL, 1);
+ sx_sunlock(&random_adaptors_lock);
+ } else if (flags & FWRITE) {
+ sx_slock(&random_adaptors_lock);
+ (random_adaptor->ra_write)(NULL, 1);
+ sx_sunlock(&random_adaptors_lock);
+ }
+
+ return (0);
}
+/* ARGSUSED */
int
-random_adaptor_read(struct uio *uio, int flag)
+random_adaptor_read(struct cdev *dev __unused, struct uio *uio, int flags __unused)
{
- int c, error = 0;
void *random_buf;
+ int c, error;
+ u_int npages;
+ struct random_adaptor_softc *ras;
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
- /* The read-rate stuff is a *VERY* crude measure of the instantaneous read rate, designed
- * to increase the use of 'live' entropy sources when lots of reads are done.
- */
- mtx_lock(&rate_mtx);
- random_adaptor_read_rate_cache += (int)((uio->uio_resid + PAGE_SIZE + 1)/PAGE_SIZE);
- mtx_unlock(&rate_mtx);
+ error = devfs_get_cdevpriv((void **)&ras);
+ if (error == 0) {
- sx_slock(&random_adaptors_lock);
+ sx_slock(&random_adaptors_lock);
- /* Blocking logic */
- if (random_adaptor->ra_seeded)
- error = (random_adaptor->ra_block)(flag);
-
- /* The actual read */
- if (!error) {
-
- random_buf = (void *)malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK);
-
- while (uio->uio_resid > 0 && !error) {
- c = MIN(uio->uio_resid, PAGE_SIZE);
- c = (random_adaptor->ra_read)(random_buf, c);
- error = uiomove(random_buf, c, uio);
+ /* Blocking logic */
+ mtx_lock(&random_reseed_mtx);
+ while (!random_adaptor->ra_seeded() && !error) {
+ if (flags & O_NONBLOCK)
+ error = EWOULDBLOCK;
+ else
+ error = msleep(&random_adaptor, &random_reseed_mtx, PUSER | PCATCH, "block", 0);
}
- /* Finished reading; let the source know so it can do some
- * optional housekeeping */
- (random_adaptor->ra_read)(NULL, 0);
+ mtx_unlock(&random_reseed_mtx);
- free(random_buf, M_ENTROPY);
+ /* The actual read */
+ if (!error) {
+ /* The read-rate stuff is a *VERY* crude indication of the instantaneous read rate,
+ * designed to increase the use of 'live' entropy sources when lots of reads are done.
+ */
+ mtx_lock(&random_rate_mtx);
+ npages = (uio->uio_resid + PAGE_SIZE - 1)/PAGE_SIZE;
+ random_adaptor_read_rate_cache += npages;
+ random_adaptor_read_rate_cache = MIN(random_adaptor_read_rate_cache, 32);
+ mtx_unlock(&random_rate_mtx);
+
+ random_buf = (void *)malloc(npages*PAGE_SIZE, M_ENTROPY, M_WAITOK);
+ while (uio->uio_resid > 0 && !error) {
+ c = MIN(uio->uio_resid, npages*PAGE_SIZE);
+ (random_adaptor->ra_read)(random_buf, c);
+ error = uiomove(random_buf, c, uio);
+ }
+ free(random_buf, M_ENTROPY);
+ }
- }
+ sx_sunlock(&random_adaptors_lock);
- sx_sunlock(&random_adaptors_lock);
+ }
return (error);
}
@@ -182,98 +316,83 @@ random_adaptor_read_rate(void)
{
int ret;
- mtx_lock(&rate_mtx);
- ret = random_adaptor_read_rate_cache = random_adaptor_read_rate_cache ? random_adaptor_read_rate_cache%32 + 1 : 1;
- mtx_unlock(&rate_mtx);
+ KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
+
+ mtx_lock(&random_rate_mtx);
+ ret = random_adaptor_read_rate_cache;
+ mtx_unlock(&random_rate_mtx);
return (ret);
}
+/* ARGSUSED */
int
-random_adaptor_poll(int events, struct thread *td)
+random_adaptor_write(struct cdev *dev __unused, struct uio *uio, int flags __unused)
{
- int revents = 0;
+ int error;
+ struct random_adaptor_softc *ras;
- sx_slock(&random_adaptors_lock);
+ KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
- if (events & (POLLIN | POLLRDNORM)) {
- if (random_adaptor->ra_seeded)
- revents = events & (POLLIN | POLLRDNORM);
- else
- revents = (random_adaptor->ra_poll)(events, td);
+ sx_slock(&random_adaptors_lock);
+ error = devfs_get_cdevpriv((void **)&ras);
+ if (error == 0) {
+ /* We used to allow this to insert userland entropy.
+ * We don't any more because (1) this so-called entropy
+ * is usually lousy and (b) its vaguely possible to
+ * mess with entropy harvesting by overdoing a write.
+ * Now we just ignore input like /dev/null does.
+ */
+ /* XXX: FIX!! Now that RWFILE is gone, we need to get this back.
+ * ALSO: See devfs_get_cdevpriv(9) and friends for ways to build per-session nodes.
+ */
+ uio->uio_resid = 0;
+ /* c = (random_adaptor->ra_write)(random_buf, c); */
}
-
sx_sunlock(&random_adaptors_lock);
- return (revents);
+ return (error);
}
-/*
- * 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.
- */
-static void
-random_adaptor_choose(void)
+/* ARGSUSED */
+int
+random_adaptor_poll(struct cdev *dev __unused, int events, struct thread *td __unused)
{
- char rngs[128], *token, *cp;
- struct random_adaptors *rra, *rrai;
- struct random_adaptor *random_adaptor_previous;
- int primax;
-
- /* We are going to be messing with random_adaptor.
- * Exclusive lock is mandatory.
- */
- sx_assert(&random_adaptors_lock, SA_XLOCKED);
+ struct random_adaptor_softc *ras;
- random_adaptor_previous = random_adaptor;
+ KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
- random_adaptor = NULL;
- if (TUNABLE_STR_FETCH("kern.random.active_adaptor", rngs, sizeof(rngs))) {
- cp = rngs;
+ if (devfs_get_cdevpriv((void **)&ras) != 0)
+ return (events &
+ (POLLHUP|POLLIN|POLLRDNORM|POLLOUT|POLLWRNORM));
- while ((token = strsep(&cp, ",")) != NULL) {
- LIST_FOREACH(rra, &random_adaptors_list, rra_entries)
- if (strcmp(rra->rra_name, token) == 0) {
- random_adaptor = rra->rra_ra;
- break;
- }
- if (random_adaptor != NULL) {
- printf("random: selecting requested adaptor <%s>\n",
- random_adaptor->ra_ident);
- break;
- }
- else
- printf("random: requested adaptor <%s> not available\n",
- token);
- }
+ sx_slock(&random_adaptors_lock);
+ mtx_lock(&random_reseed_mtx);
+ if (events & (POLLIN | POLLRDNORM)) {
+ if (random_adaptor->ra_seeded())
+ events &= (POLLIN | POLLRDNORM);
+ else
+ selrecord(td, &rsel);
}
+ mtx_unlock(&random_reseed_mtx);
+ sx_sunlock(&random_adaptors_lock);
- primax = 0;
- if (random_adaptor == NULL) {
- /*
- * Fall back to the highest priority item on the available
- * RNG list.
- */
- LIST_FOREACH(rrai, &random_adaptors_list, rra_entries) {
- if (rrai->rra_ra->ra_priority >= primax) {
- random_adaptor = rrai->rra_ra;
- primax = rrai->rra_ra->ra_priority;
- }
- }
- if (random_adaptor != NULL)
- printf("random: selecting highest priority adaptor <%s>\n",
- random_adaptor->ra_ident);
- }
+ return (events);
+}
- KASSERT(random_adaptor != NULL, ("adaptor not found"));
+/* This will be called by the entropy processor when it seeds itself and becomes secure */
+void
+random_adaptor_unblock(void)
+{
- /* 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->ra_deinit)();
- (random_adaptor->ra_init)();
- }
+ mtx_assert(&random_reseed_mtx, MA_OWNED);
+
+ selwakeuppri(&rsel, PUSER);
+ wakeup(&random_adaptor);
+ printf("random: unblocking device.\n");
+
+ /* Do arc4random(9) a favour while we are about it. */
+ (void)atomic_cmpset_int(&arc4rand_iniseed_state, ARC4_ENTR_NONE, ARC4_ENTR_HAVE);
}
static int
@@ -284,9 +403,7 @@ random_sysctl_adaptors_handler(SYSCTL_HA
int error, count;
sx_slock(&random_adaptors_lock);
-
sbuf_new_for_sysctl(&sbuf, NULL, 64, req);
-
count = 0;
LIST_FOREACH(rra, &random_adaptors_list, rra_entries)
sbuf_printf(&sbuf, "%s%s(%d)",
@@ -294,7 +411,6 @@ random_sysctl_adaptors_handler(SYSCTL_HA
error = sbuf_finish(&sbuf);
sbuf_delete(&sbuf);
-
sx_sunlock(&random_adaptors_lock);
return (error);
@@ -310,19 +426,14 @@ random_sysctl_active_adaptor_handler(SYS
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
sx_slock(&random_adaptors_lock);
-
sbuf_new_for_sysctl(&sbuf, NULL, 16, req);
-
LIST_FOREACH(rra, &random_adaptors_list, rra_entries)
if (rra->rra_ra == random_adaptor) {
sbuf_cat(&sbuf, rra->rra_name);
break;
}
-
-
error = sbuf_finish(&sbuf);
sbuf_delete(&sbuf);
-
sx_sunlock(&random_adaptors_lock);
return (error);
@@ -344,30 +455,37 @@ random_adaptors_init(void *unused __unus
"Active Random Number Generator Adaptor");
sx_init(&random_adaptors_lock, "random_adaptors");
- mtx_init(&rate_mtx, "read rate mutex", NULL, MTX_DEF);
- /* This dummy "thing" is not a module by itself, but part of the
+ mtx_init(&random_rate_mtx, "read rate mutex", NULL, MTX_DEF);
+ mtx_init(&random_reseed_mtx, "read rate mutex", NULL, MTX_DEF);
+
+ /* The dummy adaptor is not a module by itself, but part of the
* randomdev module.
*/
random_adaptor_register("dummy", &randomdev_dummy);
}
+SYSINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST,
+ random_adaptors_init, NULL);
/* ARGSUSED */
static void
random_adaptors_deinit(void *unused __unused)
{
- /* Don't do this! Panic will follow. */
+ /* Don't do this! Panic will surely follow! */
/* random_adaptor_deregister("dummy"); */
- mtx_destroy(&rate_mtx);
+ mtx_destroy(&random_reseed_mtx);
+ mtx_destroy(&random_rate_mtx);
+
sx_destroy(&random_adaptors_lock);
}
+SYSUNINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST,
+ random_adaptors_deinit, NULL);
/*
* First seed.
*
* NB! NB! NB!
- *
* NB! NB! NB!
*
* It turns out this is bloody dangerous. I was fiddling with code elsewhere
@@ -376,6 +494,9 @@ random_adaptors_deinit(void *unused __un
* As crap randomness is not directly distinguishable from good randomness, this
* could have gone unnoticed for quite a while.
*
+ * NB! NB! NB!
+ * NB! NB! NB!
+ *
* 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 other entropy
* harvesting causes a proper, safe, first seed (unblock) in short order after that.
@@ -394,9 +515,7 @@ random_adaptors_seed(void *unused __unus
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
sx_slock(&random_adaptors_lock);
-
random_adaptor->ra_reseed();
-
sx_sunlock(&random_adaptors_lock);
arc4rand(NULL, 0, 1);
@@ -404,8 +523,3 @@ random_adaptors_seed(void *unused __unus
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 17 23:28:10 2013 (r258287)
+++ projects/random_number_generator/sys/dev/random/random_adaptors.h Sun Nov 17 23:43:50 2013 (r258288)
@@ -31,25 +31,22 @@
MALLOC_DECLARE(M_ENTROPY);
-typedef void random_adaptor_init_func_t(void);
+typedef void random_adaptor_init_func_t(struct mtx *);
typedef void random_adaptor_deinit_func_t(void);
-
-typedef int random_adaptor_block_func_t(int);
-typedef int random_adaptor_read_func_t(void *, int);
-typedef int random_adaptor_poll_func_t(int, struct thread *);
-
+typedef void random_adaptor_read_func_t(uint8_t *, u_int);
+typedef void random_adaptor_write_func_t(uint8_t *, u_int);
+typedef int random_adaptor_seeded_func_t(void);
typedef void random_adaptor_reseed_func_t(void);
struct random_adaptor {
const char *ra_ident;
- int ra_seeded;
- int ra_priority;
+ int ra_priority;
random_adaptor_init_func_t *ra_init;
random_adaptor_deinit_func_t *ra_deinit;
- random_adaptor_block_func_t *ra_block;
random_adaptor_read_func_t *ra_read;
- random_adaptor_poll_func_t *ra_poll;
+ random_adaptor_write_func_t *ra_write;
random_adaptor_reseed_func_t *ra_reseed;
+ random_adaptor_seeded_func_t *ra_seeded;
};
struct random_adaptors {
@@ -64,10 +61,13 @@ extern struct random_adaptor randomdev_d
void random_adaptor_register(const char *, struct random_adaptor *);
void random_adaptor_deregister(const char *);
-int random_adaptor_block(int);
-int random_adaptor_read(struct uio *, int);
-int random_adaptor_poll(int, struct thread *);
+int random_adaptor_open(struct cdev *, int, int, struct thread *);
+int random_adaptor_read(struct cdev *, struct uio *, int);
+int random_adaptor_write(struct cdev *, struct uio *, int);
+int random_adaptor_close(struct cdev *, int, int, struct thread *);
+int random_adaptor_poll(struct cdev *, int, struct thread *);
int random_adaptor_read_rate(void);
+void random_adaptor_unblock(void);
#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 17 23:28:10 2013 (r258287)
+++ projects/random_number_generator/sys/dev/random/random_harvestq.c Sun Nov 17 23:43:50 2013 (r258288)
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/random.h>
+#include <sys/sbuf.h>
#include <sys/sysctl.h>
#include <sys/unistd.h>
@@ -52,6 +53,9 @@ __FBSDID("$FreeBSD$");
#include <dev/random/random_harvestq.h>
#include <dev/random/live_entropy_sources.h>
+/* List for the dynamic sysctls */
+static struct sysctl_ctx_list random_clist;
+
/*
* How many events to queue up. We create this many items in
* an 'empty' queue, then transfer them to the 'harvest' queue with
@@ -64,7 +68,7 @@ __FBSDID("$FreeBSD$");
* The harvest mutex protects the consistency of the entropy Fifos and
* empty fifo and other associated structures.
*/
-struct mtx harvest_mtx;
+static struct mtx harvest_mtx;
/* Lockable FIFO queue holding entropy buffers */
struct entropyfifo {
@@ -83,6 +87,11 @@ u_int harvest_destination[ENTROPYSOURCE]
/* Function called to process one harvested stochastic event */
void (*harvest_process_event)(struct harvest_event *);
+/* Allow the sysadmin to select the broad category of
+ * entropy types to harvest.
+ */
+static u_int harvest_source_mask = ((1<<RANDOM_ENVIRONMENTAL_END) - 1);
+
/* Pool count is used by anything needing to know how many entropy
* pools are currently being maintained.
* This is of use to (e.g.) the live source feed where we need to give
@@ -91,7 +100,7 @@ void (*harvest_process_event)(struct har
int harvest_pool_count;
/* <0 to end the kthread, 0 to let it run, 1 to flush the harvest queues */
-int random_kthread_control = 0;
+static int random_kthread_control = 0;
static struct proc *random_kthread_proc;
@@ -153,12 +162,75 @@ random_kthread(void *arg __unused)
}
void
+random_harvestq_flush(void)
+{
+
+ /* Command a entropy queue flush and wait for it to finish */
+ random_kthread_control = 1;
+ while (random_kthread_control)
+ pause("-", hz/10);
+
+#if 0
+#if defined(RANDOM_YARROW)
+ random_yarrow_reseed();
+#endif
+#if defined(RANDOM_FORTUNA)
+ random_fortuna_reseed();
+#endif
+#endif
+}
+
+/* ARGSUSED */
+RANDOM_CHECK_UINT(harvestmask, 0, ((1<<RANDOM_ENVIRONMENTAL_END) - 1));
+
+/* ARGSUSED */
+static int
+random_print_harvestmask(SYSCTL_HANDLER_ARGS)
+{
+ struct sbuf sbuf;
+ int error, i;
+
+ error = sysctl_wire_old_buffer(req, 0);
+ if (error == 0) {
+ sbuf_new_for_sysctl(&sbuf, NULL, 128, req);
+ for (i = 31; i >= 0; i--)
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-projects
mailing list