svn commit: r258598 - in projects/random_number_generator: share/examples/kld/random_adaptor sys/dev/random sys/kern sys/sys
Mark Murray
markm at FreeBSD.org
Mon Nov 25 21:30:47 UTC 2013
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, ×tamp, sizeof(timestamp));
+ randomdev_hash_iterate(&fortuna_start_cache.hash, buf, count);
+ timestamp = get_cyclecount();
+ randomdev_hash_iterate(&fortuna_start_cache.hash, ×tamp, 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 at gmail.com>
* Copyright (c) 2013 David E. O'Brien <obrien at 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 ***
More information about the svn-src-projects
mailing list