Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 25 Nov 2013 21:30:45 +0000 (UTC)
From:      Mark Murray <markm@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r258598 - in projects/random_number_generator: share/examples/kld/random_adaptor sys/dev/random sys/kern sys/sys
Message-ID:  <201311252130.rAPLUjdE045460@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: markm
Date: Mon Nov 25 21:30:45 2013
New Revision: 258598
URL: http://svnweb.freebsd.org/changeset/base/258598

Log:
  Snapshot.
  
  * More fixing of locking.
  
  * Re-add write mode; this is nowhwere near finished, but has the beginnings of functionality. It needs to have a low impact if an "overwhelm" attack is mounted.
  
  * Add unit test (again not finished by any means - in fact its disgusting).
  
  * More tweeking, simplifying and reviewing.
  
  * And with little fanfare, the first public exposure of my new Fortuna code!
  
  Don't try to run the above; its not ready for primetime yet.
  
  M

Added:
  projects/random_number_generator/sys/dev/random/build.sh   (contents, props changed)
  projects/random_number_generator/sys/dev/random/fortuna.c   (contents, props changed)
  projects/random_number_generator/sys/dev/random/fortuna.h   (contents, props changed)
  projects/random_number_generator/sys/dev/random/unit_test.c   (contents, props changed)
  projects/random_number_generator/sys/dev/random/unit_test.h   (contents, props changed)
Modified:
  projects/random_number_generator/share/examples/kld/random_adaptor/random_adaptor_example.c
  projects/random_number_generator/sys/dev/random/hash.c
  projects/random_number_generator/sys/dev/random/random_adaptors.c
  projects/random_number_generator/sys/dev/random/random_adaptors.h
  projects/random_number_generator/sys/dev/random/random_harvestq.c
  projects/random_number_generator/sys/dev/random/randomdev.c
  projects/random_number_generator/sys/dev/random/yarrow.c
  projects/random_number_generator/sys/dev/random/yarrow.h
  projects/random_number_generator/sys/kern/subr_bus.c
  projects/random_number_generator/sys/sys/random.h

Modified: projects/random_number_generator/share/examples/kld/random_adaptor/random_adaptor_example.c
==============================================================================
--- projects/random_number_generator/share/examples/kld/random_adaptor/random_adaptor_example.c	Mon Nov 25 21:17:14 2013	(r258597)
+++ projects/random_number_generator/share/examples/kld/random_adaptor/random_adaptor_example.c	Mon Nov 25 21:30:45 2013	(r258598)
@@ -35,17 +35,20 @@ __FBSDID("$FreeBSD$");
 #include <sys/random.h>
 #include <sys/systm.h>
 
-#include <dev/random/live_entropy_sources.h>
-#include <dev/random/random_adaptors.h>
 #include <dev/random/randomdev.h>
+#include <dev/random/randomdev_soft.h>
+#include <dev/random/random_adaptors.h>
+#include <dev/random/live_entropy_sources.h>
 
-static int random_example_read(void *, int);
-
-struct random_adaptor random_example = {
-	.ident = "Example RNG",
-	.source = RANDOM_PURE_BOGUS,	/* Make sure this is in
-					 * sys/random.h and is unique */
-	.read = random_example_read,
+static void live_random_example_init(void);
+static void live_random_example_deinit(void);
+static u_int live_random_example_read(void *, u_int);
+
+struct random_adaptor live_random_example = {
+	.les_ident = "Example RNG",
+	.les_source = RANDOM_PURE_BOGUS, /* Make sure this is in
+					  * sys/random.h and is unique */
+	.les_read = live_random_example_read,
 };
 
 /*
@@ -58,8 +61,26 @@ getRandomNumber(void)
 	return 4;   /* chosen by fair dice roll, guaranteed to be random */
 }
 
-static int
-random_example_read(void *buf, int c)
+static void
+live_random_example_init(void)
+{
+
+	/* Do initialisation stuff here */
+}
+
+static void
+live_random_example_deinit(void)
+{
+
+	/* Do de-initialisation stuff here */
+}
+
+/* get <c> bytes of random stuff into <buf>. You may presume
+ * that <c> is a multiple of 2^n, with n>=3. A typical value
+ * is c=16.
+ */
+static u_int
+live_random_example_read(void *buf, u_int c)
 {
 	uint8_t *b;
 	int count;
@@ -69,22 +90,23 @@ random_example_read(void *buf, int c)
 	for (count = 0; count < c; count++)
 		b[count] = getRandomNumber();
 
-	printf("returning %d bytes of pure randomness\n", c);
+	/* printf("returning %d bytes of pure randomness\n", c); */
 	return (c);
 }
 
+/* ARGSUSED */
 static int
-random_example_modevent(module_t mod, int type, void *unused)
+live_random_example_modevent(module_t mod __unused, int type, void *unused __unused)
 {
 	int error = 0;
 
 	switch (type) {
 	case MOD_LOAD:
-		live_entropy_source_register(&random_example);
+		live_entropy_source_register(&live_random_example);
 		break;
 
 	case MOD_UNLOAD:
-		live_entropy_source_deregister(&random_example);
+		live_entropy_source_deregister(&live_random_example);
 		break;
 
 	case MOD_SHUTDOWN:
@@ -98,4 +120,6 @@ random_example_modevent(module_t mod, in
 	return (error);
 }
 
-LIVE_ENTROPY_SRC_MODULE(live_entropy_source_example, random_example_modevent, 1);
+DEV_MODULE(live_random_example, live_random_example_modevent, NULL);
+MODULE_VERSION(live_random_example, 1);
+MODULE_DEPEND(live_random_example, randomdev, 1, 1, 1);

Added: projects/random_number_generator/sys/dev/random/build.sh
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/random_number_generator/sys/dev/random/build.sh	Mon Nov 25 21:30:45 2013	(r258598)
@@ -0,0 +1,2 @@
+cc -g -O0 -pthread -DRANDOM_DEBUG -DRANDOM_YARROW -I../.. -lstdthreads -Wall unit_test.c yarrow.c hash.c ../../crypto/rijndael/rijndael-api-fst.c ../../crypto/rijndael/rijndael-alg-fst.c ../../crypto/sha2/sha2.c -o yunit_test
+cc -g -O0 -pthread -DRANDOM_DEBUG -DRANDOM_FORTUNA -I../.. -lstdthreads -Wall unit_test.c fortuna.c hash.c ../../crypto/rijndael/rijndael-api-fst.c ../../crypto/rijndael/rijndael-alg-fst.c ../../crypto/sha2/sha2.c -o funit_test

Added: projects/random_number_generator/sys/dev/random/fortuna.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/random_number_generator/sys/dev/random/fortuna.c	Mon Nov 25 21:30:45 2013	(r258598)
@@ -0,0 +1,433 @@
+/*-
+ * 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$");
+
+#ifdef _KERNEL
+#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 <machine/cpu.h>
+
+#include <crypto/rijndael/rijndael-api-fst.h>
+#include <crypto/sha2/sha2.h>
+
+#include <dev/random/hash.h>
+#include <dev/random/randomdev.h>
+#include <dev/random/random_adaptors.h>
+#include <dev/random/random_harvestq.h>
+// #include <dev/random/randomdev_soft.h>
+#include <dev/random/fortuna.h>
+#else /* !_KERNEL */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <threads.h>
+
+#include "unit_test.h"
+
+#include <crypto/rijndael/rijndael-api-fst.h>
+#include <crypto/sha2/sha2.h>
+
+#include <dev/random/hash.h>
+#include <dev/random/yarrow.h>
+#endif /* _KERNEL */
+
+#define NPOOLS 32
+#define MINPOOLSIZE 64
+#define DEFPOOLSIZE 256
+#define MAXPOOLSIZE 65536
+
+/* This algorithm (and code) presumes that KEYSIZE is twice as large as BLOCKSIZE */
+CTASSERT(BLOCKSIZE == sizeof(__uint128_t));
+CTASSERT(KEYSIZE == 2*BLOCKSIZE);
+
+/* This is the beastie that needs protecting. It contains all of the
+ * state that we are excited about.
+ * Exactly one is instantiated.
+ */
+static struct fortuna_state {
+	/* P_i */
+	struct pool {
+		u_int length;
+		struct randomdev_hash hash;
+	} pool[NPOOLS];
+
+	/* ReseedCnt */
+	u_int reseedcount;
+
+	/* C - 128 bits */
+	union {
+		uint8_t byte[BLOCKSIZE];
+		__uint128_t whole;
+	} counter;
+
+	/* K */
+	struct randomdev_key key;
+
+	/* Extras */
+	u_int minpoolsize;
+
+	/* Extras for the OS */
+
+	/* The reseed thread mutex */
+	mtx_t *reseed_mtx;
+
+#ifdef _KERNEL
+	/* For use when 'pacing' the reseeds */
+	sbintime_t lasttime;
+#endif
+} fortuna_state;
+
+static struct fortuna_start_cache {
+	uint8_t junk[PAGE_SIZE];
+	size_t length;
+	struct randomdev_hash hash;
+} fortuna_start_cache;
+
+#ifdef _KERNEL
+RANDOM_CHECK_UINT(minpoolsize, MINPOOLSIZE, MAXPOOLSIZE);
+#endif
+
+void
+random_fortuna_init_alg(struct sysctl_ctx_list *clist, mtx_t *lock)
+{
+	int i;
+#ifdef _KERNEL
+	struct sysctl_oid *random_fortuna_o;
+#endif
+
+#ifdef RANDOM_DEBUG
+	printf("random: %s\n", __func__);
+#endif
+
+	memset((void *)(fortuna_start_cache.junk), 0, sizeof(fortuna_start_cache.junk));
+	fortuna_start_cache.length = 0U;
+	randomdev_hash_init(&fortuna_start_cache.hash);
+
+	/* Set up a lock for the reseed process */
+	fortuna_state.reseed_mtx = lock;
+
+#ifdef _KERNEL
+	/* Fortuna parameters. Do not adjust these unless you have
+	 * have a very good clue about what they do!
+	 */
+	random_fortuna_o = SYSCTL_ADD_NODE(clist,
+		SYSCTL_STATIC_CHILDREN(_kern_random),
+		OID_AUTO, "fortuna", CTLFLAG_RW, 0,
+		"Fortuna Parameters");
+
+	SYSCTL_ADD_PROC(clist,
+		SYSCTL_CHILDREN(random_fortuna_o), OID_AUTO,
+		"minpoolsize", CTLTYPE_UINT|CTLFLAG_RW,
+		&fortuna_state.minpoolsize, DEFPOOLSIZE,
+		random_check_uint_minpoolsize, "IU",
+		"Minimum pool size necessary to cause a reseed automatically");
+
+	fortuna_state.lasttime = 0U;
+#endif
+
+	fortuna_state.minpoolsize = DEFPOOLSIZE;
+
+	/* F&S - InitializePRNG() */
+
+	/* F&S - P_i = \epsilon */
+	for (i = 0; i < NPOOLS; i++) {
+		randomdev_hash_init(&fortuna_state.pool[i].hash);
+		fortuna_state.pool[i].length = 0U;
+	}
+
+	/* F&S - ReseedCNT = 0 */
+	fortuna_state.reseedcount = 0U;
+
+	/* F&S - InitializeGenerator() */
+
+	/* F&S - C = 0 */
+	fortuna_state.counter.whole = 0ULL;
+
+	/* F&S - K = 0 */
+	memset((void *)(&fortuna_state.key), 0, sizeof(struct randomdev_key));
+}
+
+void
+random_fortuna_deinit_alg(void)
+{
+
+#ifdef RANDOM_DEBUG
+	printf("random: %s\n", __func__);
+#endif
+	memset((void *)(&fortuna_state), 0, sizeof(struct fortuna_state));
+}
+
+/* F&S - AddRandomEvent() */
+/* Process a single stochastic event off the harvest queue */
+void
+random_fortuna_process_event(struct harvest_event *event)
+{
+	u_int pl;
+
+	/* We must be locked for all this as plenty of state gets messed with */
+	mtx_lock(fortuna_state.reseed_mtx);
+
+	/* Accumulate the event into the appropriate pool
+	 * where each event carries the destination information
+	 */
+	/* F&S - P_i = P_i|<harvested stuff> */
+	/* The hash_init and hash_finish are done in random_fortuna_read() below */
+	pl = event->he_destination % NPOOLS;
+	randomdev_hash_iterate(&fortuna_state.pool[pl].hash, event, sizeof(*event));
+	/* No point in counting above the outside maximum */
+	fortuna_state.pool[pl].length += event->he_size;
+	fortuna_state.pool[pl].length = MIN(fortuna_state.pool[pl].length, MAXPOOLSIZE);
+
+	/* Done with state-messing */
+	mtx_unlock(fortuna_state.reseed_mtx);
+}
+
+/* F&S - Reseed() */
+/* Reseed Mutex is held */
+static void
+reseed(uint8_t *junk, u_int length)
+{
+	struct randomdev_hash context;
+	uint8_t hash[KEYSIZE], temp[KEYSIZE];
+
+	KASSERT(fortuna_state.minpoolsize > 0, ("random: Fortuna threshold = 0"));
+#ifdef RANDOM_DEBUG
+	printf("random: %s %d %u\n", __func__, (fortuna_state.counter.whole != 0ULL), length);
+#endif
+#ifdef _KERNEL
+	mtx_assert(fortuna_state.reseed_mtx, MA_OWNED);
+#endif
+
+	/* F&S - temp = H(K|s) */
+	randomdev_hash_init(&context);
+	randomdev_hash_iterate(&context, &fortuna_state.key, sizeof(struct randomdev_key));
+	randomdev_hash_iterate(&context, junk, length);
+	randomdev_hash_finish(&context, temp);
+
+	/* F&S - hash = H(temp) */
+	randomdev_hash_init(&context);
+	randomdev_hash_iterate(&context, temp, KEYSIZE);
+	randomdev_hash_finish(&context, hash);
+
+	/* F&S - K = hash */
+	randomdev_encrypt_init(&fortuna_state.key, temp);
+	memset((void *)temp, 0, sizeof(temp));
+	memset((void *)hash, 0, sizeof(hash));
+
+	/* Unblock the device if it was blocked due to being unseeded */
+	if (fortuna_state.counter.whole == 0ULL)
+		random_adaptor_unblock();
+
+	/* F&S - C = C + 1 */
+	fortuna_state.counter.whole++;
+}
+
+/* F&S - GenerateBlocks() */
+/* Reseed Mutex is held, and buf points to a whole number of blocks. */
+static __inline void
+random_fortuna_genblocks(uint8_t *buf, u_int blockcount)
+{
+	u_int i;
+
+	for (i = 0u; i < blockcount; i++) {
+		/* F&S - r = r|E(K,C) */
+		randomdev_encrypt(&fortuna_state.key, fortuna_state.counter.byte, buf, BLOCKSIZE);
+		buf += BLOCKSIZE;
+
+		/* F&S - C = C + 1 */
+		fortuna_state.counter.whole++;
+	}
+}
+
+/* F&S - PseudoRandomData() */
+/* Reseed Mutex is held, and buf points to a whole number of blocks. */
+static __inline void
+random_fortuna_genrandom(uint8_t *buf, u_int bytecount)
+{
+	static uint8_t temp[BLOCKSIZE*(KEYSIZE/BLOCKSIZE)];
+	u_int blockcount;
+
+	/* F&S - assert(n < 2^20) */
+	KASSERT((bytecount <= (1 << 20)), ("invalid single read request to fortuna of %d bytes", bytecount));
+
+	/* F&S - r = first-n-bytes(GenerateBlocks(ceil(n/16))) */
+	blockcount = (bytecount + BLOCKSIZE - 1)/BLOCKSIZE;
+	random_fortuna_genblocks(buf, blockcount);
+
+	/* F&S - K = GenerateBlocks(2) */
+	random_fortuna_genblocks(temp, KEYSIZE/BLOCKSIZE);
+	randomdev_encrypt_init(&fortuna_state.key, temp);
+	memset((void *)temp, 0, sizeof(temp));
+}
+
+/* F&S - RandomData() */
+/* Used to return processed entropy from the PRNG */
+/* The argument buf points to a whole number of blocks. */
+void
+random_fortuna_read(uint8_t *buf, u_int bytecount)
+{
+#ifdef _KERNEL
+	sbintime_t thistime;
+#endif
+	struct randomdev_hash context;
+	uint8_t s[NPOOLS*KEYSIZE], temp[KEYSIZE];
+	int i;
+	u_int seedlength;
+
+	/* We must be locked for all this as plenty of state gets messed with */
+	mtx_lock(fortuna_state.reseed_mtx);
+
+	/* if buf == NULL and bytecount == 0 then this is the pre-read. */
+	/* if buf == NULL and bytecount != 0 then this is the post-read; ignore. */
+	if (buf == NULL) {
+		if (bytecount == 0) {
+			if (fortuna_state.pool[0].length >= fortuna_state.minpoolsize
+#ifdef _KERNEL
+			/* F&S - Use 'getsbinuptime()' to prevent reseed-spamming. */
+		    	&& ((thistime = getsbinuptime()) - fortuna_state.lasttime > hz/10)
+#endif
+		    	) {
+#ifdef _KERNEL
+				fortuna_state.lasttime = thistime;
+#endif
+
+				seedlength = 0U;
+				/* F&S - ReseedCNT = ReseedCNT + 1 */
+				fortuna_state.reseedcount++;
+				/* s = \epsilon by default */
+#ifdef RANDOM_DEBUG
+				printf("random: active reseed: reseedcount [%d] [", fortuna_state.reseedcount);
+#endif
+				for (i = 0; i < NPOOLS; i++) {
+					/* F&S - if Divides(ReseedCnt, 2^i) ... */
+					if ((fortuna_state.reseedcount % (1 << i)) == 0U) {
+#ifdef RANDOM_DEBUG
+						printf(" %d", i);
+#endif
+						seedlength += KEYSIZE;
+						/* F&S - temp = (P_i) */
+						randomdev_hash_finish(&fortuna_state.pool[i].hash, temp);
+						/* F&S - P_i = \epsilon */
+						randomdev_hash_init(&fortuna_state.pool[i].hash);
+						fortuna_state.pool[i].length = 0U;
+						/* F&S - s = s|H(temp) */
+						randomdev_hash_init(&context);
+						randomdev_hash_iterate(&context, temp, KEYSIZE);
+						randomdev_hash_finish(&context, s + i*KEYSIZE);
+					}
+					else
+						break;
+				}
+#ifdef RANDOM_DEBUG
+				printf(" ]\n");
+				printf("random: active reseed: ");
+				for (i = 0; i < NPOOLS; i++)
+					printf(" %d", fortuna_state.pool[i].length);
+				printf("\n");
+#endif
+				/* F&S */
+				reseed(s, seedlength);
+
+				/* Clean up */
+				memset((void *)s, 0, seedlength);
+				seedlength = 0U;
+				memset((void *)temp, 0, sizeof(temp));
+				memset((void *)&context, 0, sizeof(context));
+			}
+		}
+	}
+	/* if buf != NULL do a regular read. */
+	else
+		random_fortuna_genrandom(buf, bytecount);
+
+	mtx_unlock(fortuna_state.reseed_mtx);
+}
+
+/* Internal function to hand external entropy to the PRNG */
+void
+random_fortuna_write(uint8_t *buf, u_int count)
+{
+	uint8_t temp[KEYSIZE];
+	int i;
+	uintmax_t timestamp;
+
+	/* We must be locked for all this as plenty of state gets messed with */
+	mtx_lock(fortuna_state.reseed_mtx);
+
+	timestamp = get_cyclecount();
+	randomdev_hash_iterate(&fortuna_start_cache.hash, &timestamp, sizeof(timestamp));
+	randomdev_hash_iterate(&fortuna_start_cache.hash, buf, count);
+	timestamp = get_cyclecount();
+	randomdev_hash_iterate(&fortuna_start_cache.hash, &timestamp, sizeof(timestamp));
+	randomdev_hash_finish(&fortuna_start_cache.hash, temp);
+	for (i = 0; i < KEYSIZE; i++)
+		fortuna_start_cache.junk[(fortuna_start_cache.length + i)%PAGE_SIZE] ^= temp[i];
+	fortuna_start_cache.length += KEYSIZE;
+
+#ifdef RANDOM_DEBUG
+	printf("random: %s - ", __func__);
+	for (i = 0; i < KEYSIZE; i++)
+		printf("%02X", temp[i]);
+	printf("\n");
+#endif
+
+	memset((void *)(temp), 0, KEYSIZE);
+	randomdev_hash_init(&fortuna_start_cache.hash);
+
+	reseed(fortuna_start_cache.junk, MIN(PAGE_SIZE, fortuna_start_cache.length));
+	memset((void *)(fortuna_start_cache.junk), 0, sizeof(fortuna_start_cache.junk));
+
+	mtx_unlock(fortuna_state.reseed_mtx);
+}
+
+void
+random_fortuna_reseed(void)
+{
+
+	/* CWOT */
+}
+
+int
+random_fortuna_seeded(void)
+{
+
+	return (fortuna_state.counter.whole != 0ULL);
+}

Added: projects/random_number_generator/sys/dev/random/fortuna.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/random_number_generator/sys/dev/random/fortuna.h	Mon Nov 25 21:30:45 2013	(r258598)
@@ -0,0 +1,44 @@
+/*-
+ * 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_FORTUNA_H_INCLUDED
+#define SYS_DEV_RANDOM_FORTUNA_H_INCLUDED
+
+#ifdef _KERNEL
+typedef struct mtx mtx_t;
+#endif
+
+void random_fortuna_init_alg(struct sysctl_ctx_list *, mtx_t *);
+void random_fortuna_deinit_alg(void);
+void random_fortuna_read(uint8_t *, u_int);
+void random_fortuna_write(uint8_t *, u_int);
+void random_fortuna_reseed(void);
+int random_fortuna_seeded(void);
+void random_fortuna_process_event(struct harvest_event *event);
+
+#endif

Modified: projects/random_number_generator/sys/dev/random/hash.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/hash.c	Mon Nov 25 21:17:14 2013	(r258597)
+++ projects/random_number_generator/sys/dev/random/hash.c	Mon Nov 25 21:30:45 2013	(r258598)
@@ -28,18 +28,33 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#ifdef _KERNEL
 #include <sys/param.h>
 #include <sys/systm.h>
+#else /* !_KERNEL */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <threads.h>
+#include "unit_test.h"
+#endif /* _KERNEL */
 
 #include <crypto/rijndael/rijndael-api-fst.h>
 #include <crypto/sha2/sha2.h>
 
 #include <dev/random/hash.h>
 
+/* This code presumes that KEYSIZE is twice as large as BLOCKSIZE */
+CTASSERT(KEYSIZE == 2*BLOCKSIZE);
+
 /* Initialise the hash */
 void
 randomdev_hash_init(struct randomdev_hash *context)
 {
+
 	SHA256_Init(&context->sha);
 }
 
@@ -47,6 +62,7 @@ randomdev_hash_init(struct randomdev_has
 void
 randomdev_hash_iterate(struct randomdev_hash *context, void *data, size_t size)
 {
+
 	SHA256_Update(&context->sha, data, size);
 }
 
@@ -56,6 +72,7 @@ randomdev_hash_iterate(struct randomdev_
 void
 randomdev_hash_finish(struct randomdev_hash *context, void *buf)
 {
+
 	SHA256_Final(buf, &context->sha);
 }
 
@@ -66,6 +83,7 @@ randomdev_hash_finish(struct randomdev_h
 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);
 }
@@ -77,5 +95,6 @@ randomdev_encrypt_init(struct randomdev_
 void
 randomdev_encrypt(struct randomdev_key *context, void *d_in, void *d_out, u_int length)
 {
+
 	rijndael_blockEncrypt(&context->cipher, &context->key, d_in, length*8, d_out);
 }

Modified: projects/random_number_generator/sys/dev/random/random_adaptors.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/random_adaptors.c	Mon Nov 25 21:17:14 2013	(r258597)
+++ projects/random_number_generator/sys/dev/random/random_adaptors.c	Mon Nov 25 21:30:45 2013	(r258598)
@@ -1,7 +1,7 @@
 /*-
+ * Copyright (c) 2013 Mark R V Murray
  * 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
@@ -62,15 +62,16 @@ static struct adaptors_head random_adapt
 static struct random_adaptor *random_adaptor = NULL; /* Currently active adaptor */
 /* End of data items requiring random_adaptors_lock protection */
 
-/* The random_rate_mtx mutex protects the consistency of the read-rate logic. */
-struct mtx random_rate_mtx;
-int random_adaptor_read_rate_cache;
-/* End of data items requiring random_rate_mtx mutex protection */
+/* The random_readrate_mtx mutex protects the read-rate estimator.
+ */
+static struct mtx random_read_rate_mtx;
+static int random_adaptor_read_rate_cache;
+/* End of data items requiring random_readrate_mtx mutex protection */
 
 /* The random_reseed_mtx mutex protects seeding and polling/blocking.
  * This is passed into the software entropy hasher/processor.
  */
-struct mtx random_reseed_mtx;
+static struct mtx random_reseed_mtx;
 /* End of data items requiring random_reseed_mtx mutex protection */
 
 static struct selinfo rsel;
@@ -191,123 +192,71 @@ random_adaptor_deregister(const char *na
 	free(rra, M_ENTROPY);
 }
 
-/*
- * Per-instance structure.
- *
- * List of locks
- * XXX: FIX!!
- */
-struct random_adaptor_softc {
-	int oink;
-	int tweet;
-};
-
-static void
-random_adaptor_dtor(void *data)
-{
-	struct random_adaptor_softc *ras = data;
-
-	free(ras, M_ENTROPY);
-}
-
 /* ARGSUSED */
 int
-random_adaptor_open(struct cdev *dev __unused, int flags, int mode __unused, struct thread *td __unused)
+random_adaptor_read(struct cdev *dev __unused, struct uio *uio, int flags)
 {
-	struct random_adaptor_softc *ras;
+	void *random_buf;
+	int c, error;
+	ssize_t nbytes;
 
 	KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
 
-	ras = malloc(sizeof(struct random_adaptor_softc), M_ENTROPY, M_WAITOK|M_ZERO);
-	/* XXX: FIX!! Set up softc here */
-
-	devfs_set_cdevpriv(ras, random_adaptor_dtor);
+	sx_slock(&random_adaptors_lock);
 
-	/* Give the source a chance to do some pre-read/write startup */
-	if (flags & FREAD) {
-		sx_slock(&random_adaptors_lock);
-		(random_adaptor->ra_read)(NULL, 0);
-		sx_sunlock(&random_adaptors_lock);
-	} else if (flags & FWRITE) {
-		sx_slock(&random_adaptors_lock);
-		(random_adaptor->ra_write)(NULL, 0);
-		sx_sunlock(&random_adaptors_lock);
-	}
+	mtx_lock(&random_reseed_mtx);
 
-	return (0);
-}
+	/* Let the entropy source do any pre-read setup. */
+	(random_adaptor->ra_read)(NULL, 0);
 
-/* ARGSUSED */
-int
-random_adaptor_close(struct cdev *dev __unused, int flags, int fmt __unused, struct thread *td __unused)
-{
+	/* (Un)Blocking logic */
+	error = 0;
+	while (!random_adaptor->ra_seeded()) {
+		if (flags & O_NONBLOCK)	{
+			error = EWOULDBLOCK;
+			break;
+		}
 
-	KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
+		/* Sleep instead of going into a spin-frenzy */
+		msleep(&random_adaptor, &random_reseed_mtx, PUSER | PCATCH, "block", hz/10);
 
-	/* Give the source a chance to do some post-read/write shutdown */
-	if (flags & FREAD) {
-		sx_slock(&random_adaptors_lock);
-		(random_adaptor->ra_read)(NULL, 1);
-		sx_sunlock(&random_adaptors_lock);
-	} else if (flags & FWRITE) {
-		sx_slock(&random_adaptors_lock);
-		(random_adaptor->ra_write)(NULL, 1);
-		sx_sunlock(&random_adaptors_lock);
+		/* keep tapping away at the pre-read until we seed/unblock. */
+		(random_adaptor->ra_read)(NULL, 0);
 	}
 
-	return (0);
-}
-
-/* ARGSUSED */
-int
-random_adaptor_read(struct cdev *dev __unused, struct uio *uio, int flags __unused)
-{
-	void *random_buf;
-	int c, error;
-	u_int npages;
-	struct random_adaptor_softc *ras;
+	mtx_unlock(&random_reseed_mtx);
 
-	KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
+	mtx_lock(&random_read_rate_mtx);
 
-	error = devfs_get_cdevpriv((void **)&ras);
-	if (error == 0) {
+	/* The read-rate stuff is a rough indication of the instantaneous read rate,
+	 * used to increase the use of 'live' entropy sources when lots of reads are done.
+	 */
+	nbytes = (uio->uio_resid + 32 - 1)/32; /* Round up to units of 32 */
+	random_adaptor_read_rate_cache += nbytes*32;
+	random_adaptor_read_rate_cache = MIN(random_adaptor_read_rate_cache, 32);
 
-		sx_slock(&random_adaptors_lock);
+	mtx_unlock(&random_read_rate_mtx);
 
-		/* Blocking logic */
-		mtx_lock(&random_reseed_mtx);
-		while (!random_adaptor->ra_seeded() && !error) {
-			if (flags & O_NONBLOCK)
-				error = EWOULDBLOCK;
-			else
-				error = msleep(&random_adaptor, &random_reseed_mtx, PUSER | PCATCH, "block", 0);
-		}
-		mtx_unlock(&random_reseed_mtx);
+	if (!error) {
 
 		/* The actual read */
-		if (!error) {
-			/* The read-rate stuff is a *VERY* crude indication of the instantaneous read rate,
-			 * designed to increase the use of 'live' entropy sources when lots of reads are done.
-			 */
-			mtx_lock(&random_rate_mtx);
-			npages = (uio->uio_resid + PAGE_SIZE - 1)/PAGE_SIZE;
-			random_adaptor_read_rate_cache += npages;
-			random_adaptor_read_rate_cache = MIN(random_adaptor_read_rate_cache, 32);
-			mtx_unlock(&random_rate_mtx);
-
-			random_buf = (void *)malloc(npages*PAGE_SIZE, M_ENTROPY, M_WAITOK);
-			while (uio->uio_resid > 0 && !error) {
-				c = MIN(uio->uio_resid, npages*PAGE_SIZE);
-				(random_adaptor->ra_read)(random_buf, c);
-				error = uiomove(random_buf, c, uio);
-			}
-			free(random_buf, M_ENTROPY);
+
+		random_buf = (void *)malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK);
+
+		while (uio->uio_resid && !error) {
+			c = MIN(uio->uio_resid, PAGE_SIZE);
+			(random_adaptor->ra_read)(random_buf, c);
+			error = uiomove(random_buf, c, uio);
 		}
 
-		sx_sunlock(&random_adaptors_lock);
+		/* Let the entropy source do any post-read cleanup. */
+		(random_adaptor->ra_read)(NULL, 1);
 
+		free(random_buf, M_ENTROPY);
 	}
 
+	sx_sunlock(&random_adaptors_lock);
+
 	return (error);
 }
 
@@ -318,9 +267,12 @@ random_adaptor_read_rate(void)
 
 	KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
 
-	mtx_lock(&random_rate_mtx);
+	mtx_lock(&random_read_rate_mtx);
+
 	ret = random_adaptor_read_rate_cache;
-	mtx_unlock(&random_rate_mtx);
+	random_adaptor_read_rate_cache = 1;
+
+	mtx_unlock(&random_read_rate_mtx);
 
 	return (ret);
 }
@@ -329,26 +281,25 @@ random_adaptor_read_rate(void)
 int
 random_adaptor_write(struct cdev *dev __unused, struct uio *uio, int flags __unused)
 {
-	int error;
-	struct random_adaptor_softc *ras;
+	int c, error = 0;
+	void *random_buf;
 
 	KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
 
 	sx_slock(&random_adaptors_lock);
-	error = devfs_get_cdevpriv((void **)&ras);
-	if (error == 0) {
-		/* We used to allow this to insert userland entropy.
-		 * We don't any more because (1) this so-called entropy
-		 * is usually lousy and (b) its vaguely possible to
-		 * mess with entropy harvesting by overdoing a write.
-		 * Now we just ignore input like /dev/null does.
-		 */
-		/* XXX: FIX!! Now that RWFILE is gone, we need to get this back.
-		 * ALSO: See devfs_get_cdevpriv(9) and friends for ways to build per-session nodes.
-		 */
-		uio->uio_resid = 0;
-		/* c = (random_adaptor->ra_write)(random_buf, c); */
+
+	random_buf = (void *)malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK);
+
+	while (uio->uio_resid > 0) {
+		c = MIN((int)uio->uio_resid, PAGE_SIZE);
+		error = uiomove(random_buf, c, uio);
+		if (error)
+			break;
+		(random_adaptor->ra_write)(random_buf, c);
 	}
+
+	free(random_buf, M_ENTROPY);
+
 	sx_sunlock(&random_adaptors_lock);
 
 	return (error);
@@ -358,14 +309,9 @@ random_adaptor_write(struct cdev *dev __
 int
 random_adaptor_poll(struct cdev *dev __unused, int events, struct thread *td __unused)
 {
-	struct random_adaptor_softc *ras;
 
 	KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
 
-	if (devfs_get_cdevpriv((void **)&ras) != 0)
-		return (events &
-		    (POLLHUP|POLLIN|POLLRDNORM|POLLOUT|POLLWRNORM));
-
 	sx_slock(&random_adaptors_lock);
 	mtx_lock(&random_reseed_mtx);
 	if (events & (POLLIN | POLLRDNORM)) {
@@ -456,8 +402,7 @@ random_adaptors_init(void *unused __unus
 
 	sx_init(&random_adaptors_lock, "random_adaptors");
 
-	mtx_init(&random_rate_mtx, "read rate mutex", NULL, MTX_DEF);
-	mtx_init(&random_reseed_mtx, "read rate mutex", NULL, MTX_DEF);
+	mtx_init(&random_reseed_mtx, "reseed mutex", NULL, MTX_DEF);
 
 	/* The dummy adaptor is not a module by itself, but part of the
 	 * randomdev module.
@@ -475,7 +420,6 @@ random_adaptors_deinit(void *unused __un
 	/* random_adaptor_deregister("dummy"); */
 
 	mtx_destroy(&random_reseed_mtx);
-	mtx_destroy(&random_rate_mtx);
 
 	sx_destroy(&random_adaptors_lock);
 }
@@ -515,7 +459,9 @@ random_adaptors_seed(void *unused __unus
 	KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
 
 	sx_slock(&random_adaptors_lock);
+	mtx_lock(&random_reseed_mtx);
 	random_adaptor->ra_reseed();
+	mtx_unlock(&random_reseed_mtx);
 	sx_sunlock(&random_adaptors_lock);
 
 	arc4rand(NULL, 0, 1);

Modified: projects/random_number_generator/sys/dev/random/random_adaptors.h
==============================================================================
--- projects/random_number_generator/sys/dev/random/random_adaptors.h	Mon Nov 25 21:17:14 2013	(r258597)
+++ projects/random_number_generator/sys/dev/random/random_adaptors.h	Mon Nov 25 21:30:45 2013	(r258598)
@@ -61,10 +61,8 @@ extern struct random_adaptor randomdev_d
 void random_adaptor_register(const char *, struct random_adaptor *);
 void random_adaptor_deregister(const char *);
 
-int random_adaptor_open(struct cdev *, int, int, struct thread *);
 int random_adaptor_read(struct cdev *, struct uio *, int);
 int random_adaptor_write(struct cdev *, struct uio *, int);
-int random_adaptor_close(struct cdev *, int, int, struct thread *);
 int random_adaptor_poll(struct cdev *, int, struct thread *);
 
 int random_adaptor_read_rate(void);

Modified: projects/random_number_generator/sys/dev/random/random_harvestq.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/random_harvestq.c	Mon Nov 25 21:17:14 2013	(r258597)
+++ projects/random_number_generator/sys/dev/random/random_harvestq.c	Mon Nov 25 21:30:45 2013	(r258598)
@@ -169,15 +169,6 @@ random_harvestq_flush(void)
 	random_kthread_control = 1;
 	while (random_kthread_control)
 		pause("-", hz/10);
-
-#if 0
-#if defined(RANDOM_YARROW)
-	random_yarrow_reseed();
-#endif
-#if defined(RANDOM_FORTUNA)
-	random_fortuna_reseed();
-#endif
-#endif
 }
 
 /* ARGSUSED */
@@ -202,6 +193,49 @@ random_print_harvestmask(SYSCTL_HANDLER_
 	return (error);
 }
 
+static const char *(random_source_descr[]) = {
+	"CACHED",
+	"ATTACH",
+	"KEYBOARD",
+	"MOUSE",
+	"NET_TUN",
+	"NET_ETHER",
+	"NET_NG",
+	"INTERRUPT",
+	"SWI",
+	"UMA_ALLOC",
+	"", /* "ENVIRONMENTAL_END" */
+	"PURE_OCTEON",
+	"PURE_SAFE",
+	"PURE_GLXSB",
+	"PURE_UBSEC",

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



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