diff --git a/bsd/sys/dev/random/dummy_rng.c b/bsd/sys/dev/random/dummy_rng.c
new file mode 100644
index 0000000000000000000000000000000000000000..810a784a3b1fdce5aae2416ae82a1a29bae4ad40
--- /dev/null
+++ b/bsd/sys/dev/random/dummy_rng.c
@@ -0,0 +1,124 @@
+/*-
+ * Copyright (c) 2013 Arthur Mesh <arthurmesh@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/fcntl.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/random.h>
+#include <sys/selinfo.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+
+#include <dev/random/random_adaptors.h>
+#include <dev/random/randomdev.h>
+
+static struct mtx	dummy_random_mtx;
+
+/* 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)
+{
+
+	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)
+{
+
+	mtx_init(&dummy_random_mtx, "sleep mtx for dummy_random",
+	    NULL, MTX_DEF);
+}
+
+static void
+dummy_random_deinit(void)
+{
+
+	mtx_destroy(&dummy_random_mtx);
+}
+
+struct random_adaptor dummy_random = {
+	.ident = "Dummy entropy device that always blocks",
+	.init = dummy_random_init,
+	.deinit = dummy_random_deinit,
+	.block = dummy_random_block,
+	.poll = dummy_random_poll,
+	.read = (random_read_func_t *)random_null_func,
+	.reseed = (random_reseed_func_t *)random_null_func,
+	.seeded = 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);
diff --git a/bsd/sys/dev/random/harvest.c b/bsd/sys/dev/random/harvest.c
new file mode 100644
index 0000000000000000000000000000000000000000..9dbae8449b35fa8e174268a5947b6afd5e92bd0e
--- /dev/null
+++ b/bsd/sys/dev/random/harvest.c
@@ -0,0 +1,141 @@
+/*-
+ * Copyright (c) 2000-2013 Mark R V Murray
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/poll.h>
+#include <sys/queue.h>
+#include <sys/random.h>
+#include <sys/selinfo.h>
+#include <sys/syslog.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+
+#include <machine/cpu.h>
+
+#include <dev/random/randomdev_soft.h>
+
+static int read_random_phony(void *, int);
+
+/* Structure holding the desired entropy sources */
+struct harvest_select harvest = { 1, 1, 1, 1 };
+static int warned = 0;
+
+/* hold the address of the routine which is actually called if
+ * the randomdev is loaded
+ */
+static void (*reap_func)(u_int64_t, const void *, u_int, u_int,
+    enum esource) = NULL;
+static int (*read_func)(void *, int) = read_random_phony;
+
+/* Initialise the harvester at load time */
+void
+randomdev_init_harvester(void (*reaper)(u_int64_t, const void *, u_int,
+    u_int, enum esource), int (*reader)(void *, int))
+{
+	reap_func = reaper;
+	read_func = reader;
+}
+
+/* Deinitialise the harvester at unload time */
+void
+randomdev_deinit_harvester(void)
+{
+	reap_func = NULL;
+	read_func = read_random_phony;
+	warned = 0;
+}
+
+/* Entropy harvesting routine. This is supposed to be fast; do
+ * not do anything slow in here!
+ * Implemented as in indirect call to allow non-inclusion of
+ * the entropy device.
+ *
+ * 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_harvest(const void *entropy, u_int count, u_int bits, enum esource origin)
+{
+	if (reap_func)
+		(*reap_func)(get_cyclecount(), entropy, count, bits, origin);
+}
+
+/* Userland-visible version of read_random */
+int
+read_random(void *buf, int count)
+{
+	return ((*read_func)(buf, count));
+}
+
+/* If the entropy device is not loaded, make a token effort to
+ * provide _some_ kind of randomness. This should only be used
+ * inside other RNG's, like arc4random(9).
+ */
+static int
+read_random_phony(void *buf, int count)
+{
+	u_long randval;
+	int size, i;
+
+	if (!warned) {
+		log(LOG_WARNING, "random device not loaded; using insecure entropy\n");
+		warned = 1;
+	}
+
+	/* srandom() is called in kern/init_main.c:proc0_post() */
+
+	/* Fill buf[] with random(9) output */
+	for (i = 0; i < count; i+= (int)sizeof(u_long)) {
+		randval = random();
+		size = MIN(count - i, sizeof(u_long));
+		memcpy(&((char *)buf)[i], &randval, (size_t)size);
+	}
+
+	return (count);
+}
+
+/* Helper routine to enable kproc_exit() to work while the module is
+ * being (or has been) unloaded.
+ * This routine is in this file because it is always linked into the kernel,
+ * and will thus never be unloaded. This is critical for unloadable modules
+ * that have threads.
+ */
+void
+random_set_wakeup_exit(void *control)
+{
+	wakeup(control);
+	kproc_exit(0);
+	/* NOTREACHED */
+}
diff --git a/bsd/sys/dev/random/hash.c b/bsd/sys/dev/random/hash.c
new file mode 100644
index 0000000000000000000000000000000000000000..cf0feaa66ef9ebe6cd4a0c8a93957ae5f3705bd5
--- /dev/null
+++ b/bsd/sys/dev/random/hash.c
@@ -0,0 +1,81 @@
+/*-
+ * Copyright (c) 2000-2013 Mark R V Murray
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <crypto/rijndael/rijndael-api-fst.h>
+#include <crypto/sha2/sha2.h>
+
+#include <dev/random/hash.h>
+
+/* Initialise the hash */
+void
+randomdev_hash_init(struct randomdev_hash *context)
+{
+	SHA256_Init(&context->sha);
+}
+
+/* Iterate the hash */
+void
+randomdev_hash_iterate(struct randomdev_hash *context, void *data, size_t size)
+{
+	SHA256_Update(&context->sha, data, size);
+}
+
+/* Conclude by returning the hash in the supplied <*buf> which must be
+ * KEYSIZE bytes long.
+ */
+void
+randomdev_hash_finish(struct randomdev_hash *context, void *buf)
+{
+	SHA256_Final(buf, &context->sha);
+}
+
+/* Initialise the encryption routine by setting up the key schedule
+ * from the supplied <*data> which must be KEYSIZE bytes of binary
+ * data. Use CBC mode for better avalanche.
+ */
+void
+randomdev_encrypt_init(struct randomdev_key *context, void *data)
+{
+	rijndael_cipherInit(&context->cipher, MODE_CBC, NULL);
+	rijndael_makeKey(&context->key, DIR_ENCRYPT, KEYSIZE*8, data);
+}
+
+/* Encrypt the supplied data using the key schedule preset in the context.
+ * <length> bytes are encrypted from <*d_in> to <*d_out>. <length> must be
+ * a multiple of BLOCKSIZE.
+ */
+void
+randomdev_encrypt(struct randomdev_key *context, void *d_in, void *d_out, unsigned length)
+{
+	rijndael_blockEncrypt(&context->cipher, &context->key, d_in, length*8, d_out);
+}
diff --git a/bsd/sys/dev/random/hash.h b/bsd/sys/dev/random/hash.h
new file mode 100644
index 0000000000000000000000000000000000000000..4e6a4a0db831c4a7f9cf5728701839a77a398a9f
--- /dev/null
+++ b/bsd/sys/dev/random/hash.h
@@ -0,0 +1,50 @@
+/*-
+ * Copyright (c) 2000-2013 Mark R V Murray
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef SYS_DEV_RANDOM_HASH_H_INCLUDED
+#define SYS_DEV_RANDOM_HASH_H_INCLUDED
+
+#define	KEYSIZE		32	/* (in bytes) == 256 bits */
+#define	BLOCKSIZE	16	/* (in bytes) == 128 bits */
+
+struct randomdev_hash {		/* Big! Make static! */
+	SHA256_CTX	sha;
+};
+
+struct randomdev_key {		/* Big! Make static! */
+	keyInstance key;	/* Key schedule */
+	cipherInstance cipher;	/* Rijndael internal */
+};
+
+void randomdev_hash_init(struct randomdev_hash *);
+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);
+
+#endif
diff --git a/bsd/sys/dev/random/ivy.c b/bsd/sys/dev/random/ivy.c
new file mode 100644
index 0000000000000000000000000000000000000000..9b4001692adaaa4c663afeff2311518d0a4e0f1e
--- /dev/null
+++ b/bsd/sys/dev/random/ivy.c
@@ -0,0 +1,137 @@
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ * Copyright (c) 2013 David E. O'Brien <obrien@NUXI.org>
+ * Copyright (c) 2012 Konstantin Belousov <kib@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by Konstantin Belousov
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/random.h>
+#include <sys/selinfo.h>
+#include <sys/systm.h>
+
+#include <machine/md_var.h>
+#include <machine/specialreg.h>
+
+#include <dev/random/randomdev.h>
+#include <dev/random/randomdev_soft.h>
+#include <dev/random/random_harvestq.h>
+#include <dev/random/live_entropy_sources.h>
+#include <dev/random/random_adaptors.h>
+
+#define	RETRY_COUNT	10
+
+static int random_ivy_read(void *, int);
+
+static struct random_hardware_source random_ivy = {
+	.ident = "Hardware, Intel IvyBridge+ RNG",
+	.source = RANDOM_PURE_RDRAND,
+	.read = random_ivy_read
+};
+
+static inline int
+ivy_rng_store(long *buf)
+{
+#ifdef __GNUCLIKE_ASM
+	long tmp;
+	int retry;
+
+	retry = RETRY_COUNT;
+	__asm __volatile(
+	    "1:\n\t"
+	    "rdrand	%2\n\t"	/* read randomness into tmp */
+	    "jb		2f\n\t" /* CF is set on success, exit retry loop */
+	    "dec	%0\n\t" /* otherwise, retry-- */
+	    "jne	1b\n\t" /* and loop if retries are not exhausted */
+	    "jmp	3f\n"	/* failure, retry is 0, used as return value */
+	    "2:\n\t"
+	    "mov	%2,%1\n\t" /* *buf = tmp */
+	    "3:"
+	    : "+q" (retry), "=m" (*buf), "=q" (tmp) : : "cc");
+	return (retry);
+#else /* __GNUCLIKE_ASM */
+	return (0);
+#endif
+}
+
+static int
+random_ivy_read(void *buf, int c)
+{
+	long *b;
+	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)
+			break;
+	}
+	return (c - count);
+}
+
+static int
+rdrand_modevent(module_t mod, int type, void *unused)
+{
+	int error = 0;
+
+	switch (type) {
+	case MOD_LOAD:
+		if (cpu_feature2 & CPUID2_RDRAND)
+			live_entropy_source_register(&random_ivy);
+		else
+#ifndef KLD_MODULE
+			if (bootverbose)
+#endif
+				printf("%s: RDRAND is not present\n",
+				    random_ivy.ident);
+		break;
+
+	case MOD_UNLOAD:
+		if (cpu_feature2 & CPUID2_RDRAND)
+			live_entropy_source_deregister(&random_ivy);
+		break;
+
+	case MOD_SHUTDOWN:
+		break;
+
+	default:
+		error = EOPNOTSUPP;
+		break;
+
+	}
+
+	return (error);
+}
+
+LIVE_ENTROPY_SRC_MODULE(random_rdrand, rdrand_modevent, 1);
diff --git a/bsd/sys/dev/random/live_entropy_sources.c b/bsd/sys/dev/random/live_entropy_sources.c
new file mode 100644
index 0000000000000000000000000000000000000000..d406ebd20861bf3da0178391db70928a4bea6b6b
--- /dev/null
+++ b/bsd/sys/dev/random/live_entropy_sources.c
@@ -0,0 +1,195 @@
+/*-
+ * Copyright (c) 2013 Arthur Mesh <arthurmesh@gmail.com>
+ * Copyright (c) 2013 Mark R V Murray
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/kernel.h>
+#include <sys/libkern.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/random.h>
+#include <sys/selinfo.h>
+#include <sys/sx.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/unistd.h>
+
+#include <machine/cpu.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 "live_entropy_sources.h"
+
+LIST_HEAD(les_head, live_entropy_sources);
+static struct les_head sources = LIST_HEAD_INITIALIZER(sources);
+
+/*
+ * The live_lock protects the consistency of the "struct les_head sources"
+ */
+static struct sx les_lock; /* need a sleepable lock */
+
+void
+live_entropy_source_register(struct random_hardware_source *rsource)
+{
+	struct live_entropy_sources *les;
+
+	KASSERT(rsource != NULL, ("invalid input to %s", __func__));
+
+	les = malloc(sizeof(struct live_entropy_sources), M_ENTROPY, M_WAITOK);
+	les->rsource = rsource;
+
+	sx_xlock(&les_lock);
+	LIST_INSERT_HEAD(&sources, les, entries);
+	sx_xunlock(&les_lock);
+}
+
+void
+live_entropy_source_deregister(struct random_hardware_source *rsource)
+{
+	struct live_entropy_sources *les = NULL;
+
+	KASSERT(rsource != NULL, ("invalid input to %s", __func__));
+
+	sx_xlock(&les_lock);
+	LIST_FOREACH(les, &sources, entries)
+		if (les->rsource == rsource) {
+			LIST_REMOVE(les, entries);
+			break;
+		}
+	sx_xunlock(&les_lock);
+	if (les != NULL)
+		free(les, M_ENTROPY);
+}
+
+static int
+live_entropy_source_handler(SYSCTL_HANDLER_ARGS)
+{
+	struct live_entropy_sources *les;
+	int error, count;
+
+	count = error = 0;
+
+	sx_slock(&les_lock);
+
+	if (LIST_EMPTY(&sources))
+		error = SYSCTL_OUT(req, "", 0);
+	else {
+		LIST_FOREACH(les, &sources, entries) {
+
+			error = SYSCTL_OUT(req, ",", count++ ? 1 : 0);
+			if (error)
+				break;
+
+			error = SYSCTL_OUT(req, les->rsource->ident, strlen(les->rsource->ident));
+			if (error)
+				break;
+		}
+	}
+
+	sx_sunlock(&les_lock);
+
+	return (error);
+}
+
+static void
+live_entropy_sources_init(void *unused)
+{
+
+	SYSCTL_PROC(_kern_random, OID_AUTO, live_entropy_sources,
+	    CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
+	    NULL, 0, live_entropy_source_handler, "",
+	    "List of Active Live Entropy Sources");
+
+	sx_init(&les_lock, "live_entropy_sources");
+}
+
+/*
+ * Run through all "live" sources reading entropy for the given
+ * number of rounds, which should be a multiple of the number
+ * of entropy accumulation pools in use; 2 for Yarrow and 32
+ * for Fortuna.
+ *
+ * BEWARE!!!
+ * This function runs inside the RNG thread! Don't do anything silly!
+ * Remember that we are NOT holding harvest_mtx on entry!
+ */
+void
+live_entropy_sources_feed(int rounds, event_proc_f entropy_processor)
+{
+	static struct harvest event;
+	static uint8_t buf[HARVESTSIZE];
+	struct live_entropy_sources *les;
+	int i, n;
+
+	sx_slock(&les_lock);
+
+	/*
+	 * Walk over all of live entropy sources, and feed their output
+	 * to the system-wide RNG.
+	 */
+	LIST_FOREACH(les, &sources, entries) {
+
+		for (i = 0; i < rounds; i++) {
+			/*
+			 * This should be quick, since it's a live entropy
+			 * source.
+			 */
+			/* FIXME: Whine loudly if this didn't work. */
+			n = les->rsource->read(buf, sizeof(buf));
+			n = MIN(n, HARVESTSIZE);
+
+			event.somecounter = get_cyclecount();
+			event.size = n;
+			event.bits = (n*8)/2;
+			event.source = les->rsource->source;
+			memcpy(event.entropy, buf, n);
+
+			/* Do the actual entropy insertion */
+			entropy_processor(&event);
+		}
+
+	}
+
+	sx_sunlock(&les_lock);
+}
+
+static void
+live_entropy_sources_deinit(void *unused)
+{
+
+	sx_destroy(&les_lock);
+}
+
+SYSINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST,
+    live_entropy_sources_init, NULL);
+SYSUNINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST,
+    live_entropy_sources_deinit, NULL);
diff --git a/bsd/sys/dev/random/live_entropy_sources.h b/bsd/sys/dev/random/live_entropy_sources.h
new file mode 100644
index 0000000000000000000000000000000000000000..9a23070fa6379240f4bd002548cd04902165dfbe
--- /dev/null
+++ b/bsd/sys/dev/random/live_entropy_sources.h
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 2013 Arthur Mesh <arthurmesh@gmail.com>
+ * Copyright (c) 2013 Mark R V Murray
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef SYS_DEV_RANDOM_LIVE_ENTROPY_SOURCES_H_INCLUDED
+#define SYS_DEV_RANDOM_LIVE_ENTROPY_SOURCES_H_INCLUDED
+
+/*
+ * Live entropy source is a source of entropy that can provide
+ * specified or approximate amount of entropy immediately upon request or within
+ * an acceptable amount of time.
+ */
+struct live_entropy_sources {
+	LIST_ENTRY(live_entropy_sources) entries;	/* list of providers */
+	struct random_hardware_source	*rsource;	/* associated random adaptor */
+};
+
+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);
+
+#endif /* SYS_DEV_RANDOM_LIVE_ENTROPY_SOURCES_H_INCLUDED */
diff --git a/bsd/sys/dev/random/nehemiah.c b/bsd/sys/dev/random/nehemiah.c
new file mode 100644
index 0000000000000000000000000000000000000000..b60689e2bc64c782a4415d73b09c4b38b536e40a
--- /dev/null
+++ b/bsd/sys/dev/random/nehemiah.c
@@ -0,0 +1,161 @@
+/*-
+ * Copyright (c) 2013 Mark R V Murray
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/random.h>
+#include <sys/selinfo.h>
+#include <sys/systm.h>
+
+#include <machine/segments.h>
+#include <machine/pcb.h>
+#include <machine/md_var.h>
+#include <machine/specialreg.h>
+
+#include <dev/random/randomdev.h>
+#include <dev/random/randomdev_soft.h>
+#include <dev/random/random_harvestq.h>
+#include <dev/random/live_entropy_sources.h>
+#include <dev/random/random_adaptors.h>
+
+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 = {
+	.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
+ * the 'xstore' instruction, do we still need to preserve the
+ * FPU state with fpu_kern_(enter|leave)() ?
+ */
+static struct fpu_kern_ctx *fpu_ctx_save;
+
+/* This H/W source never stores more than 8 bytes in one go */
+/* ARGSUSED */
+static __inline size_t
+VIA_RNG_store(void *buf)
+{
+	uint32_t retval = 0;
+	uint32_t rate = 0;
+
+#ifdef __GNUCLIKE_ASM
+	__asm __volatile(
+		"movl	$0,%%edx\n\t"
+		".byte	0x0f, 0xa7, 0xc0" /* xstore */
+			: "=a" (retval), "+d" (rate), "+D" (buf)
+			:
+			: "memory"
+	);
+#endif
+	if (rate == 0)
+		return (retval&0x1f);
+	return (0);
+}
+
+static void
+random_nehemiah_init(void)
+{
+
+	fpu_ctx_save = fpu_kern_alloc_ctx(FPU_KERN_NORMAL);
+}
+
+static void
+random_nehemiah_deinit(void)
+{
+
+	fpu_kern_free_ctx(fpu_ctx_save);
+}
+
+static int
+random_nehemiah_read(void *buf, int c)
+{
+	uint8_t *b;
+	size_t count, ret;
+	uint64_t tmp;
+
+	if ((fpu_kern_enter(curthread, fpu_ctx_save, FPU_KERN_NORMAL) == 0)) {
+		b = buf;
+		for (count = c; count > 0; count -= ret) {
+			ret = MIN(VIA_RNG_store(&tmp), count);
+			memcpy(b, &tmp, ret);
+			b += ret;
+		}
+		fpu_kern_leave(curthread, fpu_ctx_save);
+	}
+	else
+		c = 0;
+
+	return (c);
+}
+
+static int
+nehemiah_modevent(module_t mod, int type, void *unused)
+{
+	int error = 0;
+
+	switch (type) {
+	case MOD_LOAD:
+		if (via_feature_rng & VIA_HAS_RNG) {
+			live_entropy_source_register(&random_nehemiah);
+			random_nehemiah_init();
+		} else
+#ifndef KLD_MODULE
+			if (bootverbose)
+#endif
+				printf("%s: VIA Padlock RNG not present\n",
+				    random_nehemiah.ident);
+		break;
+
+	case MOD_UNLOAD:
+		if (via_feature_rng & VIA_HAS_RNG)
+			random_nehemiah_deinit();
+			live_entropy_source_deregister(&random_nehemiah);
+		break;
+
+	case MOD_SHUTDOWN:
+		break;
+
+	default:
+		error = EOPNOTSUPP;
+		break;
+
+	}
+
+	return (error);
+}
+
+LIVE_ENTROPY_SRC_MODULE(nehemiah, nehemiah_modevent, 1);
diff --git a/bsd/sys/dev/random/random_adaptors.c b/bsd/sys/dev/random/random_adaptors.c
new file mode 100644
index 0000000000000000000000000000000000000000..4f5ad2c1ebe166011aa85d81a073698827d2b572
--- /dev/null
+++ b/bsd/sys/dev/random/random_adaptors.c
@@ -0,0 +1,251 @@
+/*-
+ * Copyright (c) 2013 Arthur Mesh <arthurmesh@gmail.com>
+ * Copyright (c) 2013 David E. O'Brien <obrien@NUXI.org>
+ * Copyright (c) 2013 Mark R V Murray
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/libkern.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/random.h>
+#include <sys/selinfo.h>
+#include <sys/sx.h>
+#include <sys/sysctl.h>
+#include <sys/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);
+static struct adaptors_head adaptors = LIST_HEAD_INITIALIZER(adaptors);
+static struct sx adaptors_lock; /* need a sleepable lock */
+
+/* List for the dynamic sysctls */
+static struct sysctl_ctx_list random_clist;
+
+struct random_adaptor *random_adaptor;
+
+MALLOC_DEFINE(M_ENTROPY, "entropy", "Entropy harvesting buffers and data structures");
+
+int
+random_adaptor_register(const char *name, struct random_adaptor *rsp)
+{
+	struct random_adaptors *rpp;
+
+	KASSERT(name != NULL && rsp != NULL, ("invalid input to %s", __func__));
+
+	rpp = malloc(sizeof(struct random_adaptors), M_ENTROPY, M_WAITOK);
+	rpp->name = name;
+	rpp->rsp = rsp;
+
+	sx_xlock(&adaptors_lock);
+	LIST_INSERT_HEAD(&adaptors, rpp, entries);
+	sx_xunlock(&adaptors_lock);
+
+	return (0);
+}
+
+struct random_adaptor *
+random_adaptor_get(const char *name)
+{
+	struct random_adaptors	*rpp;
+	struct random_adaptor	*rsp;
+
+	rsp = NULL;
+
+	sx_slock(&adaptors_lock);
+
+	LIST_FOREACH(rpp, &adaptors, entries)
+		if (strcmp(rpp->name, name) == 0)
+			rsp = rpp->rsp;
+
+	sx_sunlock(&adaptors_lock);
+
+	return (rsp);
+}
+
+/*
+ * Walk a list of registered random(4) adaptors and pick the last non-selected
+ * one.
+ *
+ * If none are selected, use yarrow if available.
+ */
+void
+random_adaptor_choose(struct random_adaptor **adaptor)
+{
+	char			 rngs[128], *token, *cp;
+	struct random_adaptors	*rppi, *ramax;
+	unsigned		 primax;
+
+	KASSERT(adaptor != NULL, ("pre-conditions failed"));
+
+	*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)
+				break;
+			else if (bootverbose)
+				printf("%s random adaptor is not available,"
+				    " skipping\n", token);
+	}
+
+	primax = 0U;
+	if (*adaptor == NULL) {
+		/*
+		 * Fall back to the highest priority item on the available
+		 * RNG list.
+		 */
+		sx_slock(&adaptors_lock);
+
+		ramax = NULL;
+		LIST_FOREACH(rppi, &adaptors, entries) {
+			if (rppi->rsp->priority >= primax) {
+				ramax = rppi;
+				primax = rppi->rsp->priority;
+			}
+		}
+		if (ramax != NULL)
+			*adaptor = ramax->rsp;
+
+		sx_sunlock(&adaptors_lock);
+
+		if (bootverbose && *adaptor)
+			printf("Falling back to <%s> random adaptor\n",
+			    (*adaptor)->ident);
+	}
+}
+
+static void
+random_adaptors_deinit(void *unused)
+{
+
+	sx_destroy(&adaptors_lock);
+	sysctl_ctx_free(&random_clist);
+}
+
+static int
+random_sysctl_adaptors_handler(SYSCTL_HANDLER_ARGS)
+{
+	struct random_adaptors	*rpp;
+	int error, count;
+
+	count = error = 0;
+
+	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;
+		}
+	}
+
+	sx_sunlock(&adaptors_lock);
+
+	return (error);
+}
+
+static int
+random_sysctl_active_adaptor_handler(SYSCTL_HANDLER_ARGS)
+{
+	struct random_adaptor	*rsp;
+	struct random_adaptors	*rpp;
+	const char		*name;
+	int error;
+
+	name = NULL;
+	rsp = random_adaptor;
+
+	if (rsp != NULL) {
+		sx_slock(&adaptors_lock);
+
+		LIST_FOREACH(rpp, &adaptors, entries)
+			if (rpp->rsp == rsp)
+				name = rpp->name;
+
+		sx_sunlock(&adaptors_lock);
+	}
+
+	if (rsp == NULL || name == NULL)
+		error = SYSCTL_OUT(req, "", 0);
+	else
+		error = SYSCTL_OUT(req, name, strlen(name));
+
+	return (error);
+}
+
+static void
+random_adaptors_init(void *unused)
+{
+
+	SYSCTL_PROC(_kern_random, OID_AUTO, adaptors,
+	    CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
+	    NULL, 0, random_sysctl_adaptors_handler, "",
+	    "Random Number Generator adaptors");
+
+	SYSCTL_PROC(_kern_random, OID_AUTO, active_adaptor,
+	    CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
+	    NULL, 0, random_sysctl_active_adaptor_handler, "",
+	    "Active Random Number Generator Adaptor");
+
+	sx_init(&adaptors_lock, "random_adaptors");
+}
+
+SYSCTL_NODE(_kern, OID_AUTO, random, CTLFLAG_RW, 0, "Random Number Generator");
+
+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);
+
+static void
+random_adaptors_reseed(void *unused)
+{
+
+	(void)unused;
+	if (random_adaptor != NULL)
+		(*random_adaptor->reseed)();
+	arc4rand(NULL, 0, 1);
+}
+SYSINIT(random_reseed, SI_SUB_INTRINSIC_POST, SI_ORDER_SECOND,
+    random_adaptors_reseed, NULL);
diff --git a/bsd/sys/dev/random/random_adaptors.h b/bsd/sys/dev/random/random_adaptors.h
new file mode 100644
index 0000000000000000000000000000000000000000..4765694a4526a7dce1007f4671bd70d62d7988be
--- /dev/null
+++ b/bsd/sys/dev/random/random_adaptors.h
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 2013 Arthur Mesh <arthurmesh@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef 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_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 **);
+
+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 */
diff --git a/bsd/sys/dev/random/random_harvestq.c b/bsd/sys/dev/random/random_harvestq.c
new file mode 100644
index 0000000000000000000000000000000000000000..b7b8381c8eb528ffae0a50332fa0c4ac8871f6f4
--- /dev/null
+++ b/bsd/sys/dev/random/random_harvestq.c
@@ -0,0 +1,322 @@
+/*-
+ * Copyright (c) 2000-2013 Mark R V Murray
+ * Copyright (c) 2013 Arthur Mesh
+ * Copyright (c) 2004 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_random.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/eventhandler.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/linker.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/random.h>
+#include <sys/selinfo.h>
+#include <sys/sysctl.h>
+#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 */
+
+/*
+ * The harvest mutex protects the consistency of the entropy fifos and
+ * empty fifo and other associated structures.
+ */
+struct mtx	harvest_mtx;
+
+/* Lockable FIFO queue holding entropy buffers */
+struct entropyfifo {
+	int count;
+	STAILQ_HEAD(harvestlist, harvest) head;
+};
+
+/* Empty entropy buffers */
+static struct entropyfifo emptyfifo;
+
+/* Harvested entropy */
+static struct entropyfifo harvestfifo;
+
+/* <0 to end the kthread, 0 to let it run, 1 to flush the harvest queues */
+int random_kthread_control = 0;
+
+static struct proc *random_kthread_proc;
+
+#ifdef RANDOM_RWFILE
+static const char *entropy_files[] = {
+	"/entropy",
+	NULL
+};
+#endif
+
+/* Deal with entropy cached externally if this is present.
+ * Lots of policy may eventually arrive in this function.
+ * Called after / is mounted.
+ */
+static void
+random_harvestq_cache(void *arg __unused)
+{
+	uint8_t *keyfile, *data;
+	size_t size, i;
+#ifdef RANDOM_RWFILE
+	const char **entropy_file;
+	uint8_t *zbuf;
+	int error;
+#endif
+
+	/* Get stuff that may have been preloaded by loader(8) */
+	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
+			printf("random: no preloaded entropy cache available\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; entropy_file++) {
+		error = randomdev_read_file(*entropy_file, data, PAGE_SIZE);
+		if (error == 0) {
+			printf("random: entropy cache '%s' provides %ld bytes\n", *entropy_file, (long)PAGE_SIZE);
+			error = randomdev_write_file(*entropy_file, zbuf, PAGE_SIZE);
+			if (error == 0) {
+				printf("random: entropy cache '%s' contents used and successfully overwritten\n", *entropy_file);
+				for (i = 0; i < PAGE_SIZE; i += 16)
+					random_harvestq_internal(get_cyclecount(), data + i, 16, 16, RANDOM_CACHED);
+			}
+			else
+				printf("random: entropy cache '%s' not overwritten and therefore not used; error = %d\n", *entropy_file, error);
+		}
+		else
+			printf("random: entropy cache '%s' not present or unreadable; error = %d\n", *entropy_file, error);
+	}
+	bzero(data, PAGE_SIZE);
+	free(data, M_ENTROPY);
+#endif
+}
+EVENTHANDLER_DEFINE(mountroot, random_harvestq_cache, NULL, 0);
+
+static void
+random_kthread(void *arg)
+{
+	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);
+	for (; random_kthread_control >= 0;) {
+
+		/*
+		 * Grab all the entropy events.
+		 * Drain entropy source records into a thread-local
+		 * 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.
+		 * Then transfer the used events back into the empty fifo.
+		 */
+		if (!STAILQ_EMPTY(&local_queue)) {
+			mtx_unlock_spin(&harvest_mtx);
+			STAILQ_FOREACH(event, &local_queue, next)
+				entropy_processor(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.
+		 */
+		mtx_unlock_spin(&harvest_mtx);
+		live_entropy_sources_feed(1, entropy_processor);
+		mtx_lock_spin(&harvest_mtx);
+
+		/*
+		 * If a queue flush was commanded, it has now happened,
+		 * and we can mark this by resetting the command.
+		 */
+
+		if (random_kthread_control == 1)
+			random_kthread_control = 0;
+
+		/* Work done, so don't belabour the issue */
+		msleep_spin_sbt(&random_kthread_control, &harvest_mtx,
+		    "-", SBT_1S/10, 0, C_PREL(1));
+
+	}
+	mtx_unlock_spin(&harvest_mtx);
+
+	random_set_wakeup_exit(&random_kthread_control);
+	/* NOTREACHED */
+}
+
+void
+random_harvestq_init(event_proc_f cb)
+{
+	int error, i;
+	struct harvest *np;
+
+	/* Initialise the harvest fifos */
+
+	/* Contains the currently unused event structs. */
+	STAILQ_INIT(&emptyfifo.head);
+	for (i = 0; i < RANDOM_FIFO_MAX; i++) {
+		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;
+
+	mtx_init(&harvest_mtx, "entropy harvest mutex", NULL, MTX_SPIN);
+
+	/* Start the hash/reseed thread */
+	error = kproc_create(random_kthread, cb,
+	    &random_kthread_proc, RFHIGHPID, 0, "rand_harvestq"); /* RANDOM_CSPRNG_NAME */
+
+	if (error != 0)
+		panic("Cannot create entropy maintenance thread.");
+}
+
+void
+random_harvestq_deinit(void)
+{
+	struct harvest *np;
+
+	/* Destroy the harvest fifos */
+	while (!STAILQ_EMPTY(&emptyfifo.head)) {
+		np = STAILQ_FIRST(&emptyfifo.head);
+		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);
+}
+
+/*
+ * Entropy harvesting routine.
+ * This is supposed to be fast; do not do anything slow in here!
+ *
+ * It is also illegal (and morally reprehensible) to insert any
+ * high-rate data here. "High-rate" is define as a data source
+ * that will usually cause lots of failures of the "Lockless read"
+ * check a few lines below. This includes the "always-on" sources
+ * like the Intel "rdrand" or the VIA Nehamiah "xstore" sources.
+ */
+void
+random_harvestq_internal(u_int64_t somecounter, const void *entropy,
+    u_int count, u_int bits, enum esource origin)
+{
+	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)
+		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);
+			memcpy(event->entropy, entropy, count);
+
+			STAILQ_INSERT_TAIL(&harvestfifo.head,
+			    event, next);
+			harvestfifo.count++;
+		}
+	}
+
+	mtx_unlock_spin(&harvest_mtx);
+}
diff --git a/bsd/sys/dev/random/random_harvestq.h b/bsd/sys/dev/random/random_harvestq.h
new file mode 100644
index 0000000000000000000000000000000000000000..a2ac3d1f91bc4bed753ba88e97e8275fd5052a58
--- /dev/null
+++ b/bsd/sys/dev/random/random_harvestq.h
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 2013 Arthur Mesh <arthurmesh@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef SYS_DEV_RANDOM_RANDOM_HARVESTQ_H_INCLUDED
+#define SYS_DEV_RANDOM_RANDOM_HARVESTQ_H_INCLUDED
+
+typedef void (*event_proc_f)(struct harvest *event);
+
+void random_harvestq_init(event_proc_f);
+void random_harvestq_deinit(void);
+void random_harvestq_internal(u_int64_t, const void *,
+    u_int, u_int, enum esource);
+
+extern int random_kthread_control;
+extern struct mtx harvest_mtx;
+
+#endif /* SYS_DEV_RANDOM_RANDOM_HARVESTQ_H_INCLUDED */
diff --git a/bsd/sys/dev/random/randomdev.c b/bsd/sys/dev/random/randomdev.c
new file mode 100644
index 0000000000000000000000000000000000000000..b76cb839a02cf171249142c4f369bf74bf821855
--- /dev/null
+++ b/bsd/sys/dev/random/randomdev.c
@@ -0,0 +1,233 @@
+/*-
+ * Copyright (c) 2000-2013 Mark R V Murray
+ * Copyright (c) 2013 Arthur Mesh <arthurmesh@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
+#include <sys/filio.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/poll.h>
+#include <sys/priv.h>
+#include <sys/proc.h>
+#include <sys/random.h>
+#include <sys/selinfo.h>
+#include <sys/uio.h>
+#include <sys/unistd.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.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>
+
+#define RANDOM_MINOR	0
+
+static d_read_t random_read;
+static d_write_t random_write;
+static d_ioctl_t random_ioctl;
+static d_poll_t random_poll;
+
+static struct cdevsw random_cdevsw = {
+	.d_version = D_VERSION,
+	.d_read = random_read,
+	.d_write = random_write,
+	.d_ioctl = random_ioctl,
+	.d_poll = random_poll,
+	.d_name = "random",
+};
+
+/* For use with make_dev(9)/destroy_dev(9). */
+static struct cdev *random_dev;
+
+/* ARGSUSED */
+static int
+random_read(struct cdev *dev __unused, struct uio *uio, int flag)
+{
+	int c, error = 0;
+	void *random_buf;
+
+	/* Blocking logic */
+	if (!random_adaptor->seeded)
+		error = (*random_adaptor->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->read)(random_buf, c);
+			error = uiomove(random_buf, c, uio);
+		}
+		/* Finished reading; let the source know so it can do some
+		 * optional housekeeping */
+		(*random_adaptor->read)(NULL, 0);
+
+		free(random_buf, M_ENTROPY);
+
+	}
+
+	return (error);
+}
+
+/* ARGSUSED */
+static int
+random_write(struct cdev *dev __unused, struct uio *uio, int flag __unused)
+{
+
+	/* 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.
+	 */
+	uio->uio_resid = 0;
+
+	return (0);
+}
+
+/* ARGSUSED */
+static int
+random_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t addr __unused,
+    int flags __unused, struct thread *td __unused)
+{
+	int error = 0;
+
+	switch (cmd) {
+		/* Really handled in upper layer */
+	case FIOASYNC:
+	case FIONBIO:
+		break;
+	default:
+		error = ENOTTY;
+	}
+	return (error);
+}
+
+/* ARGSUSED */
+static int
+random_poll(struct cdev *dev __unused, int events, struct thread *td)
+{
+	int revents = 0;
+
+	if (events & (POLLIN | POLLRDNORM)) {
+		if (random_adaptor->seeded)
+			revents = events & (POLLIN | POLLRDNORM);
+		else
+			revents = (*random_adaptor->poll)(events, td);
+	}
+	return (revents);
+}
+
+static void
+random_initialize(void *p, struct random_adaptor *s)
+{
+	static int random_inited = 0;
+
+	if (random_inited) {
+		printf("random: <%s> already initialized\n",
+		    random_adaptor->ident);
+		return;
+	}
+
+	random_adaptor = s;
+
+	(s->init)();
+
+	printf("random: <%s> initialized\n", s->ident);
+
+	/* Use an appropriately evil mode for those who are concerned
+	 * with daemons */
+	random_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &random_cdevsw,
+	    RANDOM_MINOR, NULL, UID_ROOT, GID_WHEEL, 0666, "random");
+	make_dev_alias(random_dev, "urandom"); /* compatibility */
+
+	/* mark random(4) as initialized, to avoid being called again */
+	random_inited = 1;
+}
+
+/* ARGSUSED */
+static int
+random_modevent(module_t mod __unused, int type, void *data __unused)
+{
+	static eventhandler_tag attach_tag = NULL;
+	int error = 0;
+
+	switch (type) {
+	case MOD_LOAD:
+		random_adaptor_choose(&random_adaptor);
+
+		if (random_adaptor == NULL) {
+			printf("random: No random adaptor attached, "
+			    "postponing initialization\n");
+			attach_tag = EVENTHANDLER_REGISTER(random_adaptor_attach,
+			    random_initialize, NULL, EVENTHANDLER_PRI_ANY);
+		} else
+			random_initialize(NULL, random_adaptor);
+
+		break;
+
+	case MOD_UNLOAD:
+		if (random_adaptor != NULL) {
+			(*random_adaptor->deinit)();
+			destroy_dev(random_dev);
+		}
+		/* Unregister the event handler */
+		if (attach_tag != NULL)
+			EVENTHANDLER_DEREGISTER(random_adaptor_attach,
+			    attach_tag);
+
+		break;
+
+	case MOD_SHUTDOWN:
+		break;
+
+	default:
+		error = EOPNOTSUPP;
+		break;
+
+	}
+	return (error);
+}
+
+DEV_MODULE(random, random_modevent, NULL);
+MODULE_VERSION(random, 1);
diff --git a/bsd/sys/dev/random/randomdev.h b/bsd/sys/dev/random/randomdev.h
new file mode 100644
index 0000000000000000000000000000000000000000..b87789f0834fb9c0b215a8421213924f88b39969
--- /dev/null
+++ b/bsd/sys/dev/random/randomdev.h
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 2000-2013 Mark R V Murray
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef SYS_DEV_RANDOM_RANDOMDEV_H_INCLUDED
+#define SYS_DEV_RANDOM_RANDOMDEV_H_INCLUDED
+
+/* This header contains only those definitions that are global
+ * and non algorithm-specific for the entropy processor
+ */
+
+typedef void random_init_func_t(void);
+typedef void random_deinit_func_t(void);
+typedef int random_block_func_t(int);
+typedef int random_read_func_t(void *, int);
+typedef int random_poll_func_t(int, struct thread *);
+typedef void random_reseed_func_t(void);
+
+struct random_adaptor {
+	struct selinfo		rsel;
+	const char		*ident;
+	int			seeded;
+	unsigned		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_hardware_source {
+	const char		*ident;
+	enum esource		source;
+	random_read_func_t	*read;
+};
+
+#endif
diff --git a/bsd/sys/dev/random/randomdev_soft.c b/bsd/sys/dev/random/randomdev_soft.c
new file mode 100644
index 0000000000000000000000000000000000000000..0929704da896b2b5b154d8cf55a93f4152e82fe2
--- /dev/null
+++ b/bsd/sys/dev/random/randomdev_soft.c
@@ -0,0 +1,299 @@
+/*-
+ * Copyright (c) 2000-2013 Mark R V Murray
+ * Copyright (c) 2004 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "opt_random.h"
+
+#if !defined(RANDOM_YARROW) && !defined(RANDOM_FORTUNA)
+#define RANDOM_YARROW
+#elif defined(RANDOM_YARROW) && defined(RANDOM_FORTUNA)
+#error "Must define either RANDOM_YARROW or RANDOM_FORTUNA"
+#endif
+#if defined(RANDOM_FORTUNA)
+#error "Fortuna is not yet implemented"
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.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/poll.h>
+#include <sys/random.h>
+#include <sys/selinfo.h>
+#include <sys/sysctl.h>
+#include <sys/uio.h>
+#include <sys/unistd.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+
+#include <dev/random/randomdev.h>
+#include <dev/random/randomdev_soft.h>
+#include <dev/random/random_harvestq.h>
+#include <dev/random/random_adaptors.h>
+#if defined(RANDOM_YARROW)
+#include <dev/random/yarrow.h>
+#endif
+#if defined(RANDOM_FORTUNA)
+#include <dev/random/fortuna.h>
+#endif
+
+
+static int randomdev_poll(int event, struct thread *td);
+static int randomdev_block(int flag);
+static void randomdev_flush_reseed(void);
+
+#if defined(RANDOM_YARROW)
+static struct random_adaptor random_context = {
+	.ident = "Software, Yarrow",
+	.init = randomdev_init,
+	.deinit = randomdev_deinit,
+	.block = randomdev_block,
+	.read = random_yarrow_read,
+	.poll = randomdev_poll,
+	.reseed = randomdev_flush_reseed,
+	.seeded = 0, /* This will be seeded during entropy processing */
+	.priority = 90, /* High priority, so top of the list. Fortuna may still win. */
+};
+#define RANDOM_MODULE_NAME	yarrow
+#define RANDOM_CSPRNG_NAME	"yarrow"
+#endif
+
+#if defined(RANDOM_FORTUNA)
+static struct random_adaptor random_context = {
+	.ident = "Software, Fortuna",
+	.init = randomdev_init,
+	.deinit = randomdev_deinit,
+	.block = randomdev_block,
+	.read = random_fortuna_read,
+	.poll = randomdev_poll,
+	.reseed = randomdev_flush_reseed,
+	.seeded = 0, /* This will be excplicitly seeded at startup when secured */
+	.priority = 100, /* High priority, so top of the list. Beat Yarrow. */
+};
+#define RANDOM_MODULE_NAME	fortuna
+#define RANDOM_CSPRNG_NAME	"fortuna"
+#endif
+
+TUNABLE_INT("kern.random.sys.seeded", &random_context.seeded);
+
+/* List for the dynamic sysctls */
+static struct sysctl_ctx_list random_clist;
+
+/* ARGSUSED */
+static int
+random_check_boolean(SYSCTL_HANDLER_ARGS)
+{
+	if (oidp->oid_arg1 != NULL && *(u_int *)(oidp->oid_arg1) != 0)
+		*(u_int *)(oidp->oid_arg1) = 1;
+	return (sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req));
+}
+
+void
+randomdev_init(void)
+{
+	struct sysctl_oid *random_sys_o, *random_sys_harvest_o;
+
+#if defined(RANDOM_YARROW)
+	random_yarrow_init_alg(&random_clist);
+#endif
+#if defined(RANDOM_FORTUNA)
+	random_fortuna_init_alg(&random_clist);
+#endif
+
+	random_sys_o = SYSCTL_ADD_NODE(&random_clist,
+	    SYSCTL_STATIC_CHILDREN(_kern_random),
+	    OID_AUTO, "sys", CTLFLAG_RW, 0,
+	    "Entropy Device Parameters");
+
+	SYSCTL_ADD_PROC(&random_clist,
+	    SYSCTL_CHILDREN(random_sys_o),
+	    OID_AUTO, "seeded", CTLTYPE_INT | CTLFLAG_RW,
+	    &random_context.seeded, 0, random_check_boolean, "I",
+	    "Seeded State");
+
+	random_sys_harvest_o = SYSCTL_ADD_NODE(&random_clist,
+	    SYSCTL_CHILDREN(random_sys_o),
+	    OID_AUTO, "harvest", CTLFLAG_RW, 0,
+	    "Entropy Sources");
+
+	SYSCTL_ADD_PROC(&random_clist,
+	    SYSCTL_CHILDREN(random_sys_harvest_o),
+	    OID_AUTO, "ethernet", CTLTYPE_INT | CTLFLAG_RW,
+	    &harvest.ethernet, 1, random_check_boolean, "I",
+	    "Harvest NIC entropy");
+	SYSCTL_ADD_PROC(&random_clist,
+	    SYSCTL_CHILDREN(random_sys_harvest_o),
+	    OID_AUTO, "point_to_point", CTLTYPE_INT | CTLFLAG_RW,
+	    &harvest.point_to_point, 1, random_check_boolean, "I",
+	    "Harvest serial net entropy");
+	SYSCTL_ADD_PROC(&random_clist,
+	    SYSCTL_CHILDREN(random_sys_harvest_o),
+	    OID_AUTO, "interrupt", CTLTYPE_INT | CTLFLAG_RW,
+	    &harvest.interrupt, 1, random_check_boolean, "I",
+	    "Harvest IRQ entropy");
+	SYSCTL_ADD_PROC(&random_clist,
+	    SYSCTL_CHILDREN(random_sys_harvest_o),
+	    OID_AUTO, "swi", CTLTYPE_INT | CTLFLAG_RW,
+	    &harvest.swi, 1, random_check_boolean, "I",
+	    "Harvest SWI entropy");
+
+	random_harvestq_init(random_process_event);
+
+	/* Register the randomness harvesting routine */
+	randomdev_init_harvester(random_harvestq_internal,
+	    random_context.read);
+}
+
+void
+randomdev_deinit(void)
+{
+	/* Deregister the randomness harvesting routine */
+	randomdev_deinit_harvester();
+
+	/*
+	 * Command the hash/reseed thread to end and wait for it to finish
+	 */
+	random_kthread_control = -1;
+	tsleep((void *)&random_kthread_control, 0, "term", 0);
+
+#if defined(RANDOM_YARROW)
+	random_yarrow_deinit_alg();
+#endif
+#if defined(RANDOM_FORTUNA)
+	random_fortuna_deinit_alg();
+#endif
+
+	sysctl_ctx_free(&random_clist);
+}
+
+void
+randomdev_unblock(void)
+{
+	if (!random_context.seeded) {
+		selwakeuppri(&random_context.rsel, PUSER);
+		wakeup(&random_context);
+                printf("random: unblocking device.\n");
+		random_context.seeded = 1;
+	}
+	/* 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
+randomdev_poll(int events, struct thread *td)
+{
+	int revents = 0;
+
+	mtx_lock(&random_reseed_mtx);
+
+	if (random_context.seeded)
+		revents = events & (POLLIN | POLLRDNORM);
+	else
+		selrecord(td, &random_context.rsel);
+
+	mtx_unlock(&random_reseed_mtx);
+	return (revents);
+}
+
+static int
+randomdev_block(int flag)
+{
+	int error = 0;
+
+	mtx_lock(&random_reseed_mtx);
+
+	/* Blocking logic */
+	while (!random_context.seeded && !error) {
+		if (flag & O_NONBLOCK)
+			error = EWOULDBLOCK;
+		else {
+			printf("random: blocking on read.\n");
+			error = msleep(&random_context,
+			    &random_reseed_mtx,
+			    PUSER | PCATCH, "block", 0);
+		}
+	}
+	mtx_unlock(&random_reseed_mtx);
+
+	return (error);
+}
+
+/* Helper routine to perform explicit reseeds */
+static void
+randomdev_flush_reseed(void)
+{
+	/* Command a entropy queue flush and wait for it to finish */
+	random_kthread_control = 1;
+	while (random_kthread_control)
+		pause("-", hz / 10);
+
+#if defined(RANDOM_YARROW)
+	/* This ultimately calls randomdev_unblock() */
+	random_yarrow_reseed();
+#endif
+#if defined(RANDOM_FORTUNA)
+	/* This ultimately calls randomdev_unblock() */
+	random_fortuna_reseed();
+#endif
+}
+
+static int
+randomdev_modevent(module_t mod __unused, int type, void *unused __unused)
+{
+
+	switch (type) {
+	case MOD_LOAD:
+		random_adaptor_register(RANDOM_CSPRNG_NAME, &random_context);
+		/*
+		 * For statically built kernels that contain both device
+		 * random and options PADLOCK_RNG/RDRAND_RNG/etc..,
+		 * this event handler will do nothing, since the random
+		 * driver-specific handlers are loaded after these HW
+		 * consumers, and hence hasn't yet registered for this event.
+		 *
+		 * In case where both the random driver and RNG's are built
+		 * as seperate modules, random.ko is loaded prior to *_rng.ko's
+		 * (by dependency). This event handler is there to delay
+		 * creation of /dev/{u,}random and attachment of this *_rng.ko.
+		 */
+		EVENTHANDLER_INVOKE(random_adaptor_attach, &random_context);
+		return (0);
+	}
+
+	return (EINVAL);
+}
+
+RANDOM_ADAPTOR_MODULE(RANDOM_MODULE_NAME, randomdev_modevent, 1);
diff --git a/bsd/sys/dev/random/randomdev_soft.h b/bsd/sys/dev/random/randomdev_soft.h
new file mode 100644
index 0000000000000000000000000000000000000000..cbee779a7d05c92f0a6ba21593f266d4cad47d30
--- /dev/null
+++ b/bsd/sys/dev/random/randomdev_soft.h
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (c) 2000-2013 Mark R V Murray
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef SYS_DEV_RANDOM_RANDOMDEV_SOFT_H_INCLUDED
+#define SYS_DEV_RANDOM_RANDOMDEV_SOFT_H_INCLUDED
+
+/* This header contains only those definitions that are global
+ * and harvester-specific for the entropy processor
+ */
+
+/* #define ENTROPYSOURCE nn	   entropy sources (actually classes)
+ *					This is properly defined in
+ *					an enum in sys/random.h
+ */
+
+/* The ring size _MUST_ be a power of 2 */
+#define HARVEST_RING_SIZE	1024	/* harvest ring buffer size */
+#define HARVEST_RING_MASK	(HARVEST_RING_SIZE - 1)
+
+#define HARVESTSIZE	16	/* max size of each harvested entropy unit */
+
+/* These are used to queue harvested packets of entropy. The entropy
+ * buffer size is pretty arbitrary.
+ */
+struct harvest {
+	uintmax_t somecounter;		/* fast counter for clock jitter */
+	uint8_t entropy[HARVESTSIZE];	/* the harvested entropy */
+	u_int size, bits;		/* stats about the entropy */
+	enum esource source;		/* origin of the entropy */
+	STAILQ_ENTRY(harvest) next;	/* next item on the list */
+};
+
+void randomdev_init(void);
+void randomdev_deinit(void);
+
+void randomdev_init_harvester(void (*)(u_int64_t, const void *, u_int,
+	u_int, enum esource), int (*)(void *, int));
+void randomdev_deinit_harvester(void);
+
+void random_set_wakeup_exit(void *);
+void random_process_event(struct harvest *event);
+void randomdev_unblock(void);
+
+extern struct mtx random_reseed_mtx;
+
+/* If this was C++, the macro below would be a template */
+#define RANDOM_CHECK_UINT(name, min, max)				\
+static int								\
+random_check_uint_##name(SYSCTL_HANDLER_ARGS)				\
+{									\
+	if (oidp->oid_arg1 != NULL) {					\
+		 if (*(u_int *)(oidp->oid_arg1) <= (min))		\
+			*(u_int *)(oidp->oid_arg1) = (min);		\
+		 else if (*(u_int *)(oidp->oid_arg1) > (max))		\
+			*(u_int *)(oidp->oid_arg1) = (max);		\
+	}								\
+        return (sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2,	\
+		req));							\
+}
+
+#endif
diff --git a/bsd/sys/dev/random/rwfile.c b/bsd/sys/dev/random/rwfile.c
new file mode 100644
index 0000000000000000000000000000000000000000..9b3895791690f56f4655ec37e773b16049820b52
--- /dev/null
+++ b/bsd/sys/dev/random/rwfile.c
@@ -0,0 +1,96 @@
+/*-
+ * Copyright (c) 2013 Mark R V Murray
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_random.h"
+
+#ifdef RANDOM_RWFILE
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/namei.h>
+#include <sys/fcntl.h>
+#include <sys/vnode.h>
+
+#include <dev/random/rwfile.h>
+
+int
+randomdev_read_file(const char *filename, void *buf, size_t length)
+{
+	struct nameidata nd;
+	struct thread* td = curthread;
+	int error;
+	ssize_t resid;
+	int flags;
+
+	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, td);
+	flags = FREAD;
+	error = vn_open(&nd, &flags, 0, NULL);
+	if (error == 0) {
+		NDFREE(&nd, NDF_ONLY_PNBUF);
+		if (nd.ni_vp->v_type != VREG)
+			error = ENOEXEC;
+		else
+			error = vn_rdwr(UIO_READ, nd.ni_vp, buf, length, 0, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid, td);
+		VOP_UNLOCK(nd.ni_vp, 0);
+		vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
+	}
+
+	return (error);
+}
+
+int
+randomdev_write_file(const char *filename, void *buf, size_t length)
+{
+	struct nameidata nd;
+	struct thread* td = curthread;
+	int error;
+	ssize_t resid;
+	int flags;
+
+	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, td);
+	flags = FWRITE | O_CREAT | O_TRUNC;
+	error = vn_open(&nd, &flags, 0, NULL);
+	if (error == 0) {
+		NDFREE(&nd, NDF_ONLY_PNBUF);
+		if (nd.ni_vp->v_type != VREG)
+			error = ENOEXEC;
+		else
+			error = vn_rdwr(UIO_WRITE, nd.ni_vp, buf, length, 0, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid, td);
+
+		VOP_UNLOCK(nd.ni_vp, 0);
+		vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
+	}
+
+	return (error);
+}
+
+#endif
diff --git a/bsd/sys/dev/random/rwfile.h b/bsd/sys/dev/random/rwfile.h
new file mode 100644
index 0000000000000000000000000000000000000000..f14fd7b7e9636c1bd1c1b98b928ecaea4f396b0f
--- /dev/null
+++ b/bsd/sys/dev/random/rwfile.h
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 2013 Mark R V Murray
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef SYS_DEV_RANDOM_RWFILE_H_INCLUDED
+#define SYS_DEV_RANDOM_RWFILE_H_INCLUDED
+
+#ifdef RANDOM_RWFILE
+
+int randomdev_read_file(const char *filename, void *buf, size_t);
+int randomdev_write_file(const char *filename, void *buf, size_t);
+
+#endif
+
+#endif
diff --git a/bsd/sys/dev/random/yarrow.c b/bsd/sys/dev/random/yarrow.c
new file mode 100644
index 0000000000000000000000000000000000000000..1cfa37372ed8d1ca2b0a460f4d7d7616b770af55
--- /dev/null
+++ b/bsd/sys/dev/random/yarrow.c
@@ -0,0 +1,416 @@
+/*-
+ * Copyright (c) 2000-2013 Mark R V Murray
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_random.h"
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/random.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+
+#include <crypto/rijndael/rijndael-api-fst.h>
+#include <crypto/sha2/sha2.h>
+
+#include <dev/random/hash.h>
+#include <dev/random/random_adaptors.h>
+#include <dev/random/randomdev_soft.h>
+#include <dev/random/yarrow.h>
+
+#define TIMEBIN		16	/* max value for Pt/t */
+
+#define FAST		0
+#define SLOW		1
+
+/* This is the beastie that needs protecting. It contains all of the
+ * state that we are excited about.
+ * Exactly one is instantiated.
+ */
+static struct random_state {
+	union {
+		uint8_t byte[BLOCKSIZE];
+		uint64_t qword[BLOCKSIZE/sizeof(uint64_t)];
+	} counter;		/* C */
+	struct randomdev_key key; /* K */
+	u_int gengateinterval;	/* Pg */
+	u_int bins;		/* Pt/t */
+	u_int outputblocks;	/* count output blocks for gates */
+	u_int slowoverthresh;	/* slow pool overthreshhold reseed count */
+	struct pool {
+		struct source {
+			u_int bits;	/* estimated bits of entropy */
+		} source[ENTROPYSOURCE];
+		u_int thresh;	/* pool reseed threshhold */
+		struct randomdev_hash hash;	/* accumulated entropy */
+	} pool[2];		/* pool[0] is fast, pool[1] is slow */
+	u_int which;		/* toggle - sets the current insertion pool */
+} random_state;
+
+RANDOM_CHECK_UINT(gengateinterval, 4, 64);
+RANDOM_CHECK_UINT(bins, 2, 16);
+RANDOM_CHECK_UINT(fastthresh, (BLOCKSIZE*8)/4, (BLOCKSIZE*8)); /* Bit counts */
+RANDOM_CHECK_UINT(slowthresh, (BLOCKSIZE*8)/4, (BLOCKSIZE*8)); /* Bit counts */
+RANDOM_CHECK_UINT(slowoverthresh, 1, 5);
+
+static void generator_gate(void);
+static void reseed(u_int);
+
+/* The reseed thread mutex */
+struct mtx random_reseed_mtx;
+
+/* 128-bit C = 0 */
+/* Nothing to see here, folks, just an ugly mess. */
+static void
+clear_counter(void)
+{
+	random_state.counter.qword[0] = 0UL;
+	random_state.counter.qword[1] = 0UL;
+}
+
+/* 128-bit C = C + 1 */
+/* Nothing to see here, folks, just an ugly mess. */
+/* TODO: Make a Galois counter instead? */
+static void
+increment_counter(void)
+{
+	random_state.counter.qword[0]++;
+	if (!random_state.counter.qword[0])
+		random_state.counter.qword[1]++;
+}
+
+/* Process a single stochastic event off the harvest queue */
+void
+random_process_event(struct harvest *event)
+{
+	u_int pl, overthreshhold[2];
+	struct source *source;
+	enum esource src;
+
+#if 0
+	/* Do this better with DTrace */
+	{
+		int i;
+
+		printf("Harvest:%16jX ", event->somecounter);
+		for (i = 0; i < event->size; i++)
+			printf("%02X", event->entropy[i]);
+		for (; i < 16; i++)
+			printf("  ");
+		printf(" %2d %2d %02X\n", event->size, event->bits, event->source);
+	}
+#endif
+
+	/* Accumulate the event into the appropriate pool */
+	pl = random_state.which;
+	source = &random_state.pool[pl].source[event->source];
+	randomdev_hash_iterate(&random_state.pool[pl].hash, event,
+		sizeof(*event));
+	source->bits += event->bits;
+
+	/* Count the over-threshold sources in each pool */
+	for (pl = 0; pl < 2; pl++) {
+		overthreshhold[pl] = 0;
+		for (src = RANDOM_START; src < ENTROPYSOURCE; src++) {
+			if (random_state.pool[pl].source[src].bits
+				> random_state.pool[pl].thresh)
+				overthreshhold[pl]++;
+		}
+	}
+
+	/* if any fast source over threshhold, reseed */
+	if (overthreshhold[FAST])
+		reseed(FAST);
+
+	/* if enough slow sources are over threshhold, reseed */
+	if (overthreshhold[SLOW] >= random_state.slowoverthresh)
+		reseed(SLOW);
+
+	/* Invert the fast/slow pool selector bit */
+	random_state.which = !random_state.which;
+}
+
+void
+random_yarrow_init_alg(struct sysctl_ctx_list *clist)
+{
+	int i;
+	struct sysctl_oid *random_yarrow_o;
+
+	/* Yarrow parameters. Do not adjust these unless you have
+	 * have a very good clue about what they do!
+	 */
+	random_yarrow_o = SYSCTL_ADD_NODE(clist,
+		SYSCTL_STATIC_CHILDREN(_kern_random),
+		OID_AUTO, "yarrow", CTLFLAG_RW, 0,
+		"Yarrow Parameters");
+
+	SYSCTL_ADD_PROC(clist,
+		SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO,
+		"gengateinterval", CTLTYPE_INT|CTLFLAG_RW,
+		&random_state.gengateinterval, 10,
+		random_check_uint_gengateinterval, "I",
+		"Generation gate interval");
+
+	SYSCTL_ADD_PROC(clist,
+		SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO,
+		"bins", CTLTYPE_INT|CTLFLAG_RW,
+		&random_state.bins, 10,
+		random_check_uint_bins, "I",
+		"Execution time tuner");
+
+	SYSCTL_ADD_PROC(clist,
+		SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO,
+		"fastthresh", CTLTYPE_INT|CTLFLAG_RW,
+		&random_state.pool[0].thresh, (3*(BLOCKSIZE*8))/4,
+		random_check_uint_fastthresh, "I",
+		"Fast reseed threshold");
+
+	SYSCTL_ADD_PROC(clist,
+		SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO,
+		"slowthresh", CTLTYPE_INT|CTLFLAG_RW,
+		&random_state.pool[1].thresh, (BLOCKSIZE*8),
+		random_check_uint_slowthresh, "I",
+		"Slow reseed threshold");
+
+	SYSCTL_ADD_PROC(clist,
+		SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO,
+		"slowoverthresh", CTLTYPE_INT|CTLFLAG_RW,
+		&random_state.slowoverthresh, 2,
+		random_check_uint_slowoverthresh, "I",
+		"Slow over-threshold reseed");
+
+	random_state.gengateinterval = 10;
+	random_state.bins = 10;
+	random_state.pool[0].thresh = (3*(BLOCKSIZE*8))/4;
+	random_state.pool[1].thresh = (BLOCKSIZE*8);
+	random_state.slowoverthresh = 2;
+	random_state.which = FAST;
+
+	/* Initialise the fast and slow entropy pools */
+	for (i = 0; i < 2; i++)
+		randomdev_hash_init(&random_state.pool[i].hash);
+
+	/* Clear the counter */
+	clear_counter();
+
+	/* Set up a lock for the reseed process */
+	mtx_init(&random_reseed_mtx, "Yarrow reseed", NULL, MTX_DEF);
+}
+
+void
+random_yarrow_deinit_alg(void)
+{
+	mtx_destroy(&random_reseed_mtx);
+}
+
+static void
+reseed(u_int fastslow)
+{
+	/* Interrupt-context stack is a limited resource; make large
+	 * structures static.
+	 */
+	static uint8_t v[TIMEBIN][KEYSIZE];	/* v[i] */
+	static struct randomdev_hash context;
+	uint8_t hash[KEYSIZE];			/* h' */
+	uint8_t temp[KEYSIZE];
+	u_int i;
+	enum esource j;
+
+#if 0
+	printf("Yarrow: %s reseed\n", fastslow == FAST ? "fast" : "slow");
+#endif
+
+	/* The reseed task must not be jumped on */
+	mtx_lock(&random_reseed_mtx);
+
+	/* 1. Hash the accumulated entropy into v[0] */
+
+	randomdev_hash_init(&context);
+	/* Feed the slow pool hash in if slow */
+	if (fastslow == SLOW)
+		randomdev_hash_iterate(&context,
+			&random_state.pool[SLOW].hash,
+			sizeof(struct randomdev_hash));
+	randomdev_hash_iterate(&context,
+		&random_state.pool[FAST].hash, sizeof(struct randomdev_hash));
+	randomdev_hash_finish(&context, v[0]);
+
+	/* 2. Compute hash values for all v. _Supposed_ to be computationally
+	 *    intensive.
+	 */
+
+	if (random_state.bins > TIMEBIN)
+		random_state.bins = TIMEBIN;
+	for (i = 1; i < random_state.bins; i++) {
+		randomdev_hash_init(&context);
+		/* v[i] #= h(v[i - 1]) */
+		randomdev_hash_iterate(&context, v[i - 1], KEYSIZE);
+		/* v[i] #= h(v[0]) */
+		randomdev_hash_iterate(&context, v[0], KEYSIZE);
+		/* v[i] #= h(i) */
+		randomdev_hash_iterate(&context, &i, sizeof(u_int));
+		/* Return the hashval */
+		randomdev_hash_finish(&context, v[i]);
+	}
+
+	/* 3. Compute a new key; h' is the identity function here;
+	 *    it is not being ignored!
+	 */
+
+	randomdev_hash_init(&context);
+	randomdev_hash_iterate(&context, &random_state.key, KEYSIZE);
+	for (i = 1; i < random_state.bins; i++)
+		randomdev_hash_iterate(&context, &v[i], KEYSIZE);
+	randomdev_hash_finish(&context, temp);
+	randomdev_encrypt_init(&random_state.key, temp);
+
+	/* 4. Recompute the counter */
+
+	clear_counter();
+	randomdev_encrypt(&random_state.key, random_state.counter.byte, temp, BLOCKSIZE);
+	memcpy(random_state.counter.byte, temp, BLOCKSIZE);
+
+	/* 5. Reset entropy estimate accumulators to zero */
+
+	for (i = 0; i <= fastslow; i++)
+		for (j = RANDOM_START; j < ENTROPYSOURCE; j++)
+			random_state.pool[i].source[j].bits = 0;
+
+	/* 6. Wipe memory of intermediate values */
+
+	memset((void *)v, 0, sizeof(v));
+	memset((void *)temp, 0, sizeof(temp));
+	memset((void *)hash, 0, sizeof(hash));
+
+	/* 7. Dump to seed file */
+	/* XXX Not done here yet */
+
+	/* Unblock the device if it was blocked due to being unseeded */
+	randomdev_unblock();
+
+	/* Release the reseed mutex */
+	mtx_unlock(&random_reseed_mtx);
+}
+
+/* Internal function to return processed entropy from the PRNG */
+int
+random_yarrow_read(void *buf, int count)
+{
+	static int cur = 0;
+	static int gate = 1;
+	static uint8_t genval[KEYSIZE];
+	size_t tomove;
+	int i;
+	int retval;
+
+	/* Check for final read request */
+	if (buf == NULL && count == 0)
+		return (0);
+
+	/* The reseed task must not be jumped on */
+	mtx_lock(&random_reseed_mtx);
+
+	if (gate) {
+		generator_gate();
+		random_state.outputblocks = 0;
+		gate = 0;
+	}
+	if (count > 0 && (size_t)count >= BLOCKSIZE) {
+		retval = 0;
+		for (i = 0; i < count; i += BLOCKSIZE) {
+			increment_counter();
+			randomdev_encrypt(&random_state.key, random_state.counter.byte, genval, BLOCKSIZE);
+			tomove = MIN(count - i, BLOCKSIZE);
+			memcpy((char *)buf + i, genval, tomove);
+			if (++random_state.outputblocks >= random_state.gengateinterval) {
+				generator_gate();
+				random_state.outputblocks = 0;
+			}
+			retval += (int)tomove;
+			cur = 0;
+		}
+	}
+	else {
+		if (!cur) {
+			increment_counter();
+			randomdev_encrypt(&random_state.key, random_state.counter.byte, genval, BLOCKSIZE);
+			memcpy(buf, genval, (size_t)count);
+			cur = BLOCKSIZE - count;
+			if (++random_state.outputblocks >= random_state.gengateinterval) {
+				generator_gate();
+				random_state.outputblocks = 0;
+			}
+			retval = count;
+		}
+		else {
+			retval = MIN(cur, count);
+			memcpy(buf, &genval[BLOCKSIZE - cur], (size_t)retval);
+			cur -= retval;
+		}
+	}
+	mtx_unlock(&random_reseed_mtx);
+	return (retval);
+}
+
+static void
+generator_gate(void)
+{
+	u_int i;
+	uint8_t temp[KEYSIZE];
+
+	for (i = 0; i < KEYSIZE; i += BLOCKSIZE) {
+		increment_counter();
+		randomdev_encrypt(&random_state.key, random_state.counter.byte, temp + i, BLOCKSIZE);
+	}
+
+	randomdev_encrypt_init(&random_state.key, temp);
+	memset((void *)temp, 0, KEYSIZE);
+}
+
+/* Helper routine to perform explicit reseeds */
+void
+random_yarrow_reseed(void)
+{
+#ifdef RANDOM_DEBUG
+	int i;
+
+	printf("%s(): fast:", __func__);
+	for (i = RANDOM_START; i < ENTROPYSOURCE; ++i)
+		printf(" %d", random_state.pool[FAST].source[i].bits);
+	printf("\n");
+	printf("%s(): slow:", __func__);
+	for (i = RANDOM_START; i < ENTROPYSOURCE; ++i)
+		printf(" %d", random_state.pool[SLOW].source[i].bits);
+	printf("\n");
+#endif
+	reseed(SLOW);
+}
diff --git a/bsd/sys/dev/random/yarrow.h b/bsd/sys/dev/random/yarrow.h
new file mode 100644
index 0000000000000000000000000000000000000000..f32313ee5773aa8b8cab3ae5278fc4bbe55c63c5
--- /dev/null
+++ b/bsd/sys/dev/random/yarrow.h
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2000-2013 Mark R V Murray
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef SYS_DEV_RANDOM_YARROW_H_INCLUDED
+#define SYS_DEV_RANDOM_YARROW_H_INCLUDED
+
+void random_yarrow_init_alg(struct sysctl_ctx_list *);
+void random_yarrow_deinit_alg(void);
+int random_yarrow_read(void *, int);
+void random_yarrow_reseed(void);
+
+#endif