Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153382350
D2025.id4636.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
117 KB
Referenced Files
None
Subscribers
None
D2025.id4636.diff
View Options
Index: sys/amd64/conf/DEFAULTS
===================================================================
--- sys/amd64/conf/DEFAULTS
+++ sys/amd64/conf/DEFAULTS
@@ -22,3 +22,7 @@
options GEOM_PART_MBR
options NEW_PCIB
+
+# Random Number Generator
+options RANDOM_YARROW
+options RANDOM_FORTUNA
Index: sys/arm/conf/DEFAULTS
===================================================================
--- sys/arm/conf/DEFAULTS
+++ sys/arm/conf/DEFAULTS
@@ -5,3 +5,6 @@
device mem
+# Random Number Generator
+options RANDOM_YARROW
+options RANDOM_FORTUNA
Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -525,14 +525,14 @@
crypto/des/des_setkey.c optional crypto | ipsec | netsmb
crypto/rc4/rc4.c optional netgraph_mppc_encryption | kgssapi
crypto/rijndael/rijndael-alg-fst.c optional crypto | geom_bde | \
- ipsec | random | wlan_ccmp
-crypto/rijndael/rijndael-api-fst.c optional geom_bde | random
+ ipsec | random random_yarrow | random random_fortuna | wlan_ccmp
+crypto/rijndael/rijndael-api-fst.c optional geom_bde | random random_yarrow | random random_fortuna
crypto/rijndael/rijndael-api.c optional crypto | ipsec | wlan_ccmp
crypto/sha1.c optional carp | crypto | ipsec | \
netgraph_mppc_encryption | sctp
-crypto/sha2/sha2.c optional crypto | geom_bde | ipsec | random | \
+crypto/sha2/sha2.c optional crypto | geom_bde | ipsec | random random_yarrow | random random_fortuna | \
sctp | zfs
-crypto/sha2/sha256c.c optional crypto | geom_bde | ipsec | random | \
+crypto/sha2/sha256c.c optional crypto | geom_bde | ipsec | random random_yarrow | random random_fortuna | \
sctp | zfs
crypto/siphash/siphash.c optional inet | inet6
crypto/siphash/siphash_test.c optional inet | inet6
@@ -2135,12 +2135,11 @@
dev/random/randomdev.c standard
dev/random/random_adaptors.c standard
dev/random/dummy_rng.c standard
-dev/random/live_entropy_sources.c standard
-dev/random/random_harvestq.c standard
-dev/random/randomdev_soft.c optional random
-dev/random/yarrow.c optional random
-dev/random/fortuna.c optional random
-dev/random/hash.c optional random
+dev/random/live_entropy_sources.c optional random random_yarrow | random random_fortuna
+dev/random/random_harvestq.c optional random random_yarrow | random random_fortuna
+dev/random/yarrow.c optional random random_yarrow
+dev/random/fortuna.c optional random random_fortuna
+dev/random/hash.c optional random random_yarrow | random random_fortuna
dev/rc/rc.c optional rc
dev/re/if_re.c optional re
dev/rl/if_rl.c optional rl pci
Index: sys/conf/options
===================================================================
--- sys/conf/options
+++ sys/conf/options
@@ -932,6 +932,10 @@
RCTL opt_global.h
# Random number generator(s)
+# The DEBUG option is in global as the random harvesting
+# puts probes all over the place, and it makes little sense
+# to pollute these headers with an extra include.
+RANDOM_DEBUG opt_global.h
+# Which CSPRNG hashes we get. See the DEFAULTS files.
RANDOM_YARROW opt_random.h
RANDOM_FORTUNA opt_random.h
-RANDOM_DEBUG opt_random.h
Index: sys/dev/random/build.sh
===================================================================
--- sys/dev/random/build.sh
+++ sys/dev/random/build.sh
@@ -1,3 +1,29 @@
+#!/bin/sh
+#-
+# Copyright (c) 2013-2015 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$
#
# Basic script to build crude unit tests.
@@ -11,6 +37,7 @@
../../crypto/rijndael/rijndael-alg-fst.c \
../../crypto/sha2/sha2.c \
../../crypto/sha2/sha256c.c \
+ -lz \
-o yunit_test
cc -g -O0 -pthread -DRANDOM_DEBUG -DRANDOM_FORTUNA \
-I../.. -lstdthreads -Wall \
@@ -21,4 +48,5 @@
../../crypto/rijndael/rijndael-alg-fst.c \
../../crypto/sha2/sha2.c \
../../crypto/sha2/sha256c.c \
+ -lz \
-o funit_test
Index: sys/dev/random/dummy_rng.c
===================================================================
--- sys/dev/random/dummy_rng.c
+++ sys/dev/random/dummy_rng.c
@@ -28,8 +28,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include "opt_random.h"
-
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/fcntl.h>
@@ -60,43 +58,7 @@
dummy_random_init(void)
{
-#ifdef RANDOM_DEBUG
- printf("random: %s\n", __func__);
-#endif
-
- randomdev_init_reader(dummy_random_read_phony);
-}
-
-/* This is used only by the internal read_random(9) call, and then only
- * if no entropy processor is loaded.
- *
- * Make a token effort to provide _some_ kind of output. No warranty of
- * the quality of this output is made, mainly because its lousy.
- *
- * This is only used by the internal read_random(9) call when no other
- * adaptor is active.
- *
- * It has external scope due to the way things work in
- * randomdev_[de]init_reader() that the rest of the world doesn't need to
- * know about.
- *
- * Caveat Emptor.
- */
-void
-dummy_random_read_phony(uint8_t *buf, u_int count)
-{
- /* If no entropy device is loaded, don't spam the console with warnings */
- u_long randval;
- size_t size, i;
-
- /* srandom() is called in kern/init_main.c:proc0_post() */
-
- /* Fill buf[] with random(9) output */
- for (i = 0; i < count; i += sizeof(randval)) {
- randval = random();
- size = MIN(count - i, sizeof(randval));
- memcpy(buf + i, &randval, (size_t)size);
- }
+ randomdev_init_reader(NULL);
}
struct random_adaptor randomdev_dummy = {
Index: sys/dev/random/fortuna.h
===================================================================
--- sys/dev/random/fortuna.h
+++ sys/dev/random/fortuna.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2013 Mark R V Murray
+ * Copyright (c) 2013-2015 Mark R V Murray
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,18 +27,31 @@
*/
#ifndef SYS_DEV_RANDOM_FORTUNA_H_INCLUDED
-#define SYS_DEV_RANDOM_FORTUNA_H_INCLUDED
+#define SYS_DEV_RANDOM_FORTUNA_H_INCLUDED
#ifdef _KERNEL
typedef struct mtx mtx_t;
+#define RANDOM_RESEED_INIT_LOCK(x) mtx_init(&random_fortuna_reseed_mtx, "reseed mutex", NULL, MTX_DEF)
+#define RANDOM_RESEED_DEINIT_LOCK(x) mtx_destroy(&random_fortuna_reseed_mtx)
+#define RANDOM_RESEED_LOCK(x) mtx_lock(&random_fortuna_reseed_mtx)
+#define RANDOM_RESEED_UNLOCK(x) mtx_unlock(&random_fortuna_reseed_mtx)
+#define RANDOM_RESEED_ASSERT_LOCK_OWNED(x) mtx_assert(&random_fortuna_reseed_mtx, MA_OWNED)
+#else
+#define RANDOM_RESEED_INIT_LOCK(x) mtx_init(&random_fortuna_reseed_mtx, mtx_plain)
+#define RANDOM_RESEED_DEINIT_LOCK(x) mtx_destroy(&random_fortuna_reseed_mtx)
+#define RANDOM_RESEED_LOCK(x) mtx_lock(&random_fortuna_reseed_mtx)
+#define RANDOM_RESEED_UNLOCK(x) mtx_unlock(&random_fortuna_reseed_mtx)
+#define RANDOM_RESEED_ASSERT_LOCK_OWNED(x)
#endif
void random_fortuna_init_alg(void);
void random_fortuna_deinit_alg(void);
+void random_fortuna_pre_read(void);
void random_fortuna_read(uint8_t *, u_int);
+void random_fortuna_post_read(void);
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);
+void random_fortuna_process_event(struct harvest_event *);
-#endif
+#endif /* SYS_DEV_RANDOM_FORTUNA_H_INCLUDED */
Index: sys/dev/random/fortuna.c
===================================================================
--- sys/dev/random/fortuna.c
+++ sys/dev/random/fortuna.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2013-2014 Mark R V Murray
+ * Copyright (c) 2013-2015 Mark R V Murray
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,25 +25,24 @@
*
*/
-/* This implementation of Fortuna is based on the descriptions found in
- * ISBN 0-471-22357-3 "Practical Cryptography" by Ferguson and Schneier
- * ("F&S").
- *
- * The above book is superseded by ISBN 978-0-470-47424-2 "Cryptography
- * Engineering" by Ferguson, Schneier and Kohno ("FS&K"). The code has
- * not yet fully caught up with FS&K.
+/*
+ * This implementation of Fortuna is based on the descriptions found in
+ * ISBN 978-0-470-47424-2 "Cryptography Engineering" by Ferguson, Schneier
+ * and Kohno ("FS&K").
*/
-#include <sys/cdefs.h>
+#include <sys/types.h>
__FBSDID("$FreeBSD$");
-#ifdef _KERNEL
-#include "opt_random.h"
+#include <sys/limits.h>
+#ifdef _KERNEL
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/conf.h>
#include <sys/lock.h>
#include <sys/malloc.h>
+#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/random.h>
#include <sys/sysctl.h>
@@ -61,8 +60,6 @@
#include <dev/random/uint128.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>
@@ -79,69 +76,61 @@
#include <dev/random/fortuna.h>
#endif /* _KERNEL */
-#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
+/* Defined in FS&K */
+#define NPOOLS 32 /* The number of accumulation pools */
+#define DEFPOOLSIZE 256 /* The default pool size/length */
+#define RANDOM_MAX_READ (1 << 20) /* Max bytes in a single read */
-#if defined(RANDOM_FORTUNA)
-
-#define NPOOLS 32
-#define MINPOOLSIZE 64
-#define DEFPOOLSIZE 256
-#define MAXPOOLSIZE 65536
+/*
+ * The allowable range of DEFPOOLSIZE. The default value is above.
+ * Making DEFPOOLSIZE too large will mean a long time between reseeds,
+ * and too small may compromise initial security but get faster reseeds.
+ */
+#define MINPOOLSIZE 64
+#define MAXPOOLSIZE UINT_MAX
-/* This algorithm (and code) presumes that KEYSIZE is twice as large as BLOCKSIZE */
-CTASSERT(BLOCKSIZE == sizeof(uint128_t));
-CTASSERT(KEYSIZE == 2*BLOCKSIZE);
+/* This algorithm (and code) presumes that RANDOM_KEYSIZE is twice as large as RANDOM_BLOCKSIZE */
+CTASSERT(RANDOM_BLOCKSIZE == sizeof(uint128_t));
+CTASSERT(RANDOM_KEYSIZE == 2*RANDOM_BLOCKSIZE);
-/* This is the beastie that needs protecting. It contains all of the
- * state that we are excited about.
- * Exactly one is instantiated.
+/*
+ * 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];
+ struct fs_pool {
+ u_int fsp_length; /* Only the first one is used by Fortuna */
+ struct randomdev_hash fsp_hash;
+ } fs_pool[NPOOLS];
/* ReseedCnt */
- u_int reseedcount;
+ u_int fs_reseedcount;
- /* C - 128 bits */
- union {
- uint8_t byte[BLOCKSIZE];
- uint128_t whole;
- } counter;
+ /* C */
+ uint128_t fs_counter;
/* K */
- struct randomdev_key key;
+ struct randomdev_key fs_key;
/* Extras */
- u_int minpoolsize;
+ u_int fs_minpoolsize;
/* Extras for the OS */
-
#ifdef _KERNEL
/* For use when 'pacing' the reseeds */
- sbintime_t lasttime;
+ sbintime_t fs_lasttime;
#endif
} fortuna_state;
-/* The random_reseed_mtx mutex protects seeding and polling/blocking. */
-static mtx_t random_reseed_mtx;
-
-static struct fortuna_start_cache {
- uint8_t junk[PAGE_SIZE];
- size_t length;
- struct randomdev_hash hash;
-} fortuna_start_cache;
+/* The random_fortuna_reseed_mtx mutex protects seeding and polling/blocking. */
+static mtx_t random_fortuna_reseed_mtx;
#ifdef _KERNEL
static struct sysctl_ctx_list random_clist;
-RANDOM_CHECK_UINT(minpoolsize, MINPOOLSIZE, MAXPOOLSIZE);
+RANDOM_CHECK_UINT(fs_minpoolsize, MINPOOLSIZE, MAXPOOLSIZE);
+#else
+static uint8_t zero_region[RANDOM_ZERO_BLOCKSIZE];
#endif
void
@@ -152,19 +141,11 @@
struct sysctl_oid *random_fortuna_o;
#endif
- memset(fortuna_start_cache.junk, 0, sizeof(fortuna_start_cache.junk));
- fortuna_start_cache.length = 0U;
- randomdev_hash_init(&fortuna_start_cache.hash);
+ RANDOM_RESEED_INIT_LOCK();
- /* Set up a lock for the reseed process */
#ifdef _KERNEL
- mtx_init(&random_reseed_mtx, "reseed mutex", NULL, MTX_DEF);
-#else /* !_KERNEL */
- mtx_init(&random_reseed_mtx, mtx_plain);
-#endif /* _KERNEL */
-
-#ifdef _KERNEL
- /* Fortuna parameters. Do not adjust these unless you have
+ /*
+ * Fortuna parameters. Do not adjust these unless you have
* have a very good clue about what they do!
*/
random_fortuna_o = SYSCTL_ADD_NODE(&random_clist,
@@ -175,269 +156,417 @@
SYSCTL_ADD_PROC(&random_clist,
SYSCTL_CHILDREN(random_fortuna_o), OID_AUTO,
"minpoolsize", CTLTYPE_UINT|CTLFLAG_RW,
- &fortuna_state.minpoolsize, DEFPOOLSIZE,
- random_check_uint_minpoolsize, "IU",
+ &fortuna_state.fs_minpoolsize, DEFPOOLSIZE,
+ random_check_uint_fs_minpoolsize, "IU",
"Minimum pool size necessary to cause a reseed automatically");
- fortuna_state.lasttime = 0U;
+ fortuna_state.fs_lasttime = 0U;
#endif
- fortuna_state.minpoolsize = DEFPOOLSIZE;
+ fortuna_state.fs_minpoolsize = DEFPOOLSIZE;
- /* F&S - InitializePRNG() */
+ /* FS&K - InitializePRNG() */
- /* F&S - P_i = \epsilon */
+ /* FS&K - P_i = \epsilon */
for (i = 0; i < NPOOLS; i++) {
- randomdev_hash_init(&fortuna_state.pool[i].hash);
- fortuna_state.pool[i].length = 0U;
+ randomdev_hash_init(&fortuna_state.fs_pool[i].fsp_hash);
+ fortuna_state.fs_pool[i].fsp_length = 0U;
}
- /* F&S - ReseedCNT = 0 */
- fortuna_state.reseedcount = 0U;
+ /* FS&K - ReseedCNT = 0 */
+ fortuna_state.fs_reseedcount = 0U;
- /* F&S - InitializeGenerator() */
+ /* FS&K - InitializeGenerator() */
- /* F&S - C = 0 */
- uint128_clear(&fortuna_state.counter.whole);
+ /* FS&K - C = 0 */
+ fortuna_state.fs_counter = UINT128_ZERO;
- /* F&S - K = 0 */
- memset(&fortuna_state.key, 0, sizeof(fortuna_state.key));
+ /* FS&K - K = 0 */
+ bzero(&fortuna_state.fs_key, sizeof(fortuna_state.fs_key));
}
void
random_fortuna_deinit_alg(void)
{
- mtx_destroy(&random_reseed_mtx);
- memset(&fortuna_state, 0, sizeof(fortuna_state));
+ RANDOM_RESEED_DEINIT_LOCK();
+
+ bzero(&fortuna_state, sizeof(fortuna_state));
}
-/* F&S - AddRandomEvent() */
-/* Process a single stochastic event off the harvest queue */
+/*-
+ * FS&K - 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(&random_reseed_mtx);
+ RANDOM_RESEED_LOCK();
+
+ /*-
+ * FS&K - P_i = P_i|<harvested stuff>
+ * Accumulate the event into the appropriate pool
+ * where each event carries the destination information.
+ *
+ * The hash_init() and hash_finish() calls are done in
+ * random_fortuna_pre_read().
+ *
+ * We must be locked against pool state modification which can happen
+ * during accumulation/reseeding and reading/regating.
+ */
+ pl = event->he_destination % NPOOLS;
+ randomdev_hash_iterate(&fortuna_state.fs_pool[pl].fsp_hash, event, sizeof(*event));
+ /*-
+ * Don't wrap the length. Doing the the hard way so as not to wrap at MAXUINT.
+ * This is a "saturating" add.
+ * XXX: FIX!!: We don't actually need lengths for anything but fs_pool[0],
+ * but it's been useful debugging to see them all.
+ */
+ if (MAXPOOLSIZE - fortuna_state.fs_pool[pl].fsp_length > event->he_size)
+ fortuna_state.fs_pool[pl].fsp_length += event->he_size;
+ else
+ fortuna_state.fs_pool[pl].fsp_length = MAXPOOLSIZE;
+
+ RANDOM_RESEED_UNLOCK();
+}
- /* Accumulate the event into the appropriate pool
- * where each event carries the destination information
+/*
+ * Process a block of data suspected to be slightly stochastic
+ * The length is RANDOM_KEYSIZE bytes, but data is passed in words.
+ */
+static void
+random_fortuna_process_buffer(uint32_t *buf)
+{
+ static struct harvest_event event;
+ u_int i, pl;
+ static u_int dest = 0;
+
+ /*-
+ * FS&K - P_i = P_i|<buf entropy_data>
+ * Accumulate the data into the appropriate pools
+ * where each chunk will carry the destination information.
+ *
+ * The hash_init() and hash_finish() calls are done in
+ * random_fortuna_pre_read().
+ *
+ * We must be locked against pool state modification which can happen
+ * during accumulation/reseeding and reading/regating.
*/
- /* F&S - P_i = P_i|<harvested stuff> */
+
+ /* Implies: event.he_source = RANDOM_CACHED; */
+ bzero(&event, sizeof(event));
+
+ RANDOM_RESEED_LOCK();
+
/* 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);
+ for (i = 0; i < RANDOM_KEYSIZE_WORDS; i++) {
+ event.he_somecounter = get_cyclecount();
+ event.he_size = sizeof(uint32_t);
+ event.he_entropy[0] = buf[i];
+ /* Do the actual entropy insertion */
+ event.he_destination = dest++; /* Harmless cheating */
+ pl = event.he_destination % NPOOLS;
+ randomdev_hash_iterate(&fortuna_state.fs_pool[pl].fsp_hash, &event, sizeof(event));
+ /* Don't wrap the length. Doing the the hard way so as not to wrap at MAXPOOLSIZE.
+ * This is a "saturating add".
+ * XXX: FIX!!: We don't actually need lengths for anything but fs_pool[0],
+ * but it's been useful debugging to see them all.
+ */
+ if ((MAXPOOLSIZE - fortuna_state.fs_pool[pl].fsp_length) > event.he_size)
+ fortuna_state.fs_pool[pl].fsp_length += event.he_size;
+ else
+ fortuna_state.fs_pool[pl].fsp_length = MAXPOOLSIZE;
+ }
- /* Done with state-messing */
- mtx_unlock(&random_reseed_mtx);
+ RANDOM_RESEED_UNLOCK();
}
-/* F&S - Reseed() */
-/* Reseed Mutex is held */
+/*-
+ * FS&K - Reseed()
+ * This introduces new key material into the output generator.
+ * Additionaly it increments the output generator's counter
+ * variable C. When C > 0, the output generator is seeded and
+ * will deliver output.
+ * The entropy_data buffer passed is a very specific size; the
+ * product of NPOOLS and RANDOM_KEYSIZE.
+ */
static void
-reseed(uint8_t *junk, u_int length)
+random_fortuna_reseed_internal(uint32_t *entropy_data)
{
struct randomdev_hash context;
- uint8_t hash[KEYSIZE];
+ uint8_t hash[RANDOM_KEYSIZE];
- KASSERT(fortuna_state.minpoolsize > 0, ("random: Fortuna threshold = 0"));
-#ifdef _KERNEL
- mtx_assert(&random_reseed_mtx, MA_OWNED);
-#endif
+ KASSERT(fortuna_state.fs_minpoolsize > 0, ("random: Fortuna threshold = 0"));
+ RANDOM_RESEED_ASSERT_LOCK_OWNED();
/* FS&K - K = Hd(K|s) where Hd(m) is H(H(0^512|m)) */
randomdev_hash_init(&context);
- randomdev_hash_iterate(&context, zero_region, 512/8);
- randomdev_hash_iterate(&context, &fortuna_state.key, sizeof(fortuna_state.key));
- randomdev_hash_iterate(&context, junk, length);
+ randomdev_hash_iterate(&context, zero_region, RANDOM_ZERO_BLOCKSIZE);
+ randomdev_hash_iterate(&context, &fortuna_state.fs_key, sizeof(fortuna_state.fs_key));
+ randomdev_hash_iterate(&context, entropy_data, RANDOM_KEYSIZE*NPOOLS);
randomdev_hash_finish(&context, hash);
randomdev_hash_init(&context);
- randomdev_hash_iterate(&context, hash, KEYSIZE);
+ randomdev_hash_iterate(&context, hash, RANDOM_KEYSIZE);
randomdev_hash_finish(&context, hash);
- randomdev_encrypt_init(&fortuna_state.key, hash);
- memset(hash, 0, sizeof(hash));
+ randomdev_encrypt_init(&fortuna_state.fs_key, hash);
+ bzero(hash, sizeof(hash));
- /* Unblock the device if it was blocked due to being unseeded */
- if (uint128_is_zero(fortuna_state.counter.whole))
+ /* Unblock the device if this is the first time we are reseeding. */
+ if (uint128_is_zero(fortuna_state.fs_counter))
random_adaptor_unblock();
/* FS&K - C = C + 1 */
- uint128_increment(&fortuna_state.counter.whole);
+ uint128_increment(&fortuna_state.fs_counter);
}
-/* F&S - GenerateBlocks() */
-/* Reseed Mutex is held, and buf points to a whole number of blocks. */
+/*-
+ * FS&K - GenerateBlocks()
+ * Generate a number of complete blocks of random output.
+ */
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;
+ RANDOM_RESEED_ASSERT_LOCK_OWNED();
+
+ for (i = 0; i < blockcount; i++) {
+ /* FS&K - r = r|E(K,C) */
+ randomdev_encrypt(&fortuna_state.fs_key, &fortuna_state.fs_counter, buf, RANDOM_BLOCKSIZE);
+ buf += RANDOM_BLOCKSIZE;
- /* F&S - C = C + 1 */
- uint128_increment(&fortuna_state.counter.whole);
+ /* FS&K - C = C + 1 */
+ uint128_increment(&fortuna_state.fs_counter);
}
}
-/* F&S - PseudoRandomData() */
-/* Reseed Mutex is held, and buf points to a whole number of blocks. */
+/*-
+ * FS&K - PseudoRandomData()
+ * This generates no more than 2^20 bytes of data, and cleans up its
+ * internal state when finished. It is assumed that a whole number of
+ * blocks are available for writing; any excess generated will be
+ * ignored.
+ */
static __inline void
random_fortuna_genrandom(uint8_t *buf, u_int bytecount)
{
- static uint8_t temp[BLOCKSIZE*(KEYSIZE/BLOCKSIZE)];
+ static uint8_t temp[RANDOM_BLOCKSIZE*(RANDOM_KEYS_PER_BLOCK)];
u_int blockcount;
- /* F&S - assert(n < 2^20) */
- KASSERT((bytecount <= (1 << 20)), ("invalid single read request to fortuna of %d bytes", bytecount));
+ /* FS&K - assert(n < 2^20 (== 1 MB) */
+ KASSERT((bytecount <= RANDOM_MAX_READ), ("invalid single read request to fortuna of %d bytes", bytecount));
+ RANDOM_RESEED_ASSERT_LOCK_OWNED();
- /* F&S - r = first-n-bytes(GenerateBlocks(ceil(n/16))) */
- blockcount = bytecount / BLOCKSIZE;
+ /* FS&K - r = first-n-bytes(GenerateBlocks(ceil(n/16))) */
+ blockcount = (bytecount + RANDOM_BLOCKSIZE - 1)/RANDOM_BLOCKSIZE;
random_fortuna_genblocks(buf, blockcount);
- /* TODO: FIX! remove memcpy()! */
- if (bytecount % BLOCKSIZE > 0) {
- random_fortuna_genblocks(temp, 1);
- memcpy(buf + (blockcount * BLOCKSIZE), temp, bytecount % BLOCKSIZE);
- }
- /* F&S - K = GenerateBlocks(2) */
- random_fortuna_genblocks(temp, KEYSIZE/BLOCKSIZE);
- randomdev_encrypt_init(&fortuna_state.key, temp);
- memset(temp, 0, sizeof(temp));
+ /* FS&K - K = GenerateBlocks(2) */
+ random_fortuna_genblocks(temp, RANDOM_KEYS_PER_BLOCK);
+ randomdev_encrypt_init(&fortuna_state.fs_key, temp);
+ bzero(temp, sizeof(temp));
}
-/* F&S - RandomData() */
-/* Used to return processed entropy from the PRNG */
-/* The argument buf points to a whole number of blocks. */
+/*-
+ * FS&K - RandomData()
+ * Used to return processed entropy from the PRNG
+ * There is a pre_read and a post_read required to be present
+ * (but they can be null functions) in order to allow specific
+ * actions at the begin or the end of a read. Fortuna does its
+ * reseeding in the _pre_read() part, and _post_read() is not
+ * used.
+ */
void
-random_fortuna_read(uint8_t *buf, u_int bytecount)
+random_fortuna_pre_read(void)
{
#ifdef _KERNEL
- sbintime_t thistime;
+ sbintime_t now;
#endif
struct randomdev_hash context;
- uint8_t s[NPOOLS*KEYSIZE], temp[KEYSIZE];
+ uint32_t s[NPOOLS*RANDOM_KEYSIZE_WORDS];
+ uint8_t temp[RANDOM_KEYSIZE];
int i;
- u_int seedlength;
- /* We must be locked for all this as plenty of state gets messed with */
- mtx_lock(&random_reseed_mtx);
+#ifdef _KERNEL
+ /* FS&K - Use 'getsbinuptime()' to prevent reseed-spamming. */
+ now = getsbinuptime();
+#endif
+ RANDOM_RESEED_LOCK();
- /* 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
+ if (fortuna_state.fs_pool[0].fsp_length >= fortuna_state.fs_minpoolsize
#ifdef _KERNEL
- /* F&S - Use 'getsbinuptime()' to prevent reseed-spamming. */
- && ((thistime = getsbinuptime()) - fortuna_state.lasttime > hz/10)
+ /* FS&K - Use 'getsbinuptime()' to prevent reseed-spamming. */
+ && (now - fortuna_state.fs_lasttime > hz/10)
#endif
- ) {
+ ) {
#ifdef _KERNEL
- fortuna_state.lasttime = thistime;
+ fortuna_state.fs_lasttime = now;
#endif
- seedlength = 0U;
- /* F&S - ReseedCNT = ReseedCNT + 1 */
- fortuna_state.reseedcount++;
- /* s = \epsilon by default */
- for (i = 0; i < NPOOLS; i++) {
- /* F&S - if Divides(ReseedCnt, 2^i) ... */
- if ((fortuna_state.reseedcount % (1 << i)) == 0U) {
- 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;
- }
+ /* FS&K - ReseedCNT = ReseedCNT + 1 */
+ fortuna_state.fs_reseedcount++;
+ /* s = \epsilon by default */
+ for (i = 0; i < NPOOLS; i++) {
+ /* FS&K - if Divides(ReseedCnt, 2^i) ... */
+ if ((fortuna_state.fs_reseedcount % (1 << i)) == 0U) {
+ /* FS&K - temp = (P_i) */
+ randomdev_hash_finish(&fortuna_state.fs_pool[i].fsp_hash, temp);
+ /* FS&K - P_i = \epsilon */
+ randomdev_hash_init(&fortuna_state.fs_pool[i].fsp_hash);
+ fortuna_state.fs_pool[i].fsp_length = 0U;
+ /* FS&K - s = s|H(temp) */
+ randomdev_hash_init(&context);
+ randomdev_hash_iterate(&context, temp, RANDOM_KEYSIZE);
+ randomdev_hash_finish(&context, s + i*RANDOM_KEYSIZE_WORDS);
+ } else
+ break;
+ }
#ifdef RANDOM_DEBUG
- printf("random: active reseed: reseedcount [%d] ", fortuna_state.reseedcount);
- for (i = 0; i < NPOOLS; i++)
- printf(" %d", fortuna_state.pool[i].length);
- printf("\n");
+ /*-
+ * XXX: FIX!! This is a dangerously tedious thing to do with mutexes held.
+ * Or at least keep it as seldom-used debug-only code.
+ */
+ printf("random: reseedcount [%d]", fortuna_state.fs_reseedcount);
+ for (i = 0; i < NPOOLS; i++)
+ printf(" %X", fortuna_state.fs_pool[i].fsp_length);
+ printf("\n");
#endif
- /* F&S */
- reseed(s, seedlength);
-
- /* Clean up */
- memset(s, 0, seedlength);
- seedlength = 0U;
- memset(temp, 0, sizeof(temp));
- memset(&context, 0, sizeof(context));
- }
- }
+ /* FS&K */
+ random_fortuna_reseed_internal(s);
+
+ /* Clean up and secure */
+ bzero(s, sizeof(s));
+ bzero(temp, sizeof(temp));
+ bzero(&context, sizeof(context));
}
- /* if buf != NULL do a regular read. */
- else
- random_fortuna_genrandom(buf, bytecount);
- mtx_unlock(&random_reseed_mtx);
+ RANDOM_RESEED_UNLOCK();
+}
+
+void
+random_fortuna_read(uint8_t *buf, u_int bytecount)
+{
+
+ RANDOM_RESEED_LOCK();
+
+ /* The argument buf points to a whole number of blocks. */
+ random_fortuna_genrandom(buf, bytecount);
+
+ RANDOM_RESEED_UNLOCK();
+}
+
+void
+random_fortuna_post_read(void)
+{
+
+ /* CWOT */
}
/* 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;
+ struct randomdev_hash hash;
+ uint32_t entropy_data[RANDOM_KEYSIZE_WORDS];
uintmax_t timestamp;
+ randomdev_hash_init(&hash);
timestamp = get_cyclecount();
- randomdev_hash_iterate(&fortuna_start_cache.hash, ×tamp, sizeof(timestamp));
- randomdev_hash_iterate(&fortuna_start_cache.hash, buf, count);
+ randomdev_hash_iterate(&hash, ×tamp, sizeof(timestamp));
+ randomdev_hash_iterate(&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;
+ randomdev_hash_iterate(&hash, ×tamp, sizeof(timestamp));
+ randomdev_hash_finish(&hash, entropy_data);
+ bzero(&hash, sizeof(hash));
-#ifdef RANDOM_DEBUG
- printf("random: %s - ", __func__);
- for (i = 0; i < KEYSIZE; i++)
- printf("%02X", temp[i]);
- printf("\n");
-#endif
+ random_fortuna_process_buffer(entropy_data);
+ bzero(entropy_data, sizeof(entropy_data));
+}
+
+void
+random_fortuna_reseed(void)
+{
- memset(temp, 0, KEYSIZE);
+ /* CWOT */
+}
- /* We must be locked for all this as plenty of state gets messed with */
- mtx_lock(&random_reseed_mtx);
+int
+random_fortuna_seeded(void)
+{
- randomdev_hash_init(&fortuna_start_cache.hash);
+ return (!uint128_is_zero(fortuna_state.fs_counter));
+}
+
+/* MODULE */
+
+#ifdef _KERNEL
- reseed(fortuna_start_cache.junk, MIN(PAGE_SIZE, fortuna_start_cache.length));
- memset(fortuna_start_cache.junk, 0, sizeof(fortuna_start_cache.junk));
+static void random_fortuna_init(void);
+static void random_fortuna_deinit(void);
+
+static struct random_adaptor random_soft_processor = {
+ .ra_ident = "Fortuna",
+ .ra_priority = 100, /* High priority, so top of the list. Beat Yarrow. */
+ .ra_pre_read = random_fortuna_pre_read,
+ .ra_read = random_fortuna_read,
+ .ra_post_read = random_fortuna_post_read,
+ .ra_write = random_fortuna_write,
+ .ra_reseed = random_fortuna_reseed,
+ .ra_seeded = random_fortuna_seeded,
+ .ra_init = random_fortuna_init,
+ .ra_deinit = random_fortuna_deinit,
+};
- mtx_unlock(&random_reseed_mtx);
+void
+random_fortuna_init(void)
+{
+
+ random_fortuna_init_alg();
+ random_harvestq_init(random_fortuna_process_event, 32);
+ randomdev_init_harvester(random_harvestq_internal);
}
void
-random_fortuna_reseed(void)
+random_fortuna_deinit(void)
{
- /* CWOT */
+ randomdev_deinit_harvester();
+ random_harvestq_deinit();
+ random_fortuna_deinit_alg();
}
-int
-random_fortuna_seeded(void)
+/* ARGSUSED */
+static int
+random_fortuna_soft_modevent(module_t mod __unused, int type, void *unused __unused)
{
+ int error = 0;
+
+ switch (type) {
+ case MOD_LOAD:
+ printf("random: SOFT: fortuna\n");
+ random_adaptor_register("fortuna", &random_soft_processor);
+ break;
- return (!uint128_is_zero(fortuna_state.counter.whole));
+ case MOD_UNLOAD:
+ random_adaptor_deregister("fortuna");
+ break;
+
+ case MOD_SHUTDOWN:
+ break;
+
+ default:
+ error = EOPNOTSUPP;
+ break;
+
+ }
+ return (error);
}
-#endif /* RANDOM_FORTUNA */
+DEV_MODULE(fortuna, random_fortuna_soft_modevent, NULL);
+MODULE_VERSION(random_fortuna, 1);
+MODULE_DEPEND(random_fortuna, randomdev, 1, 1, 1);
+MODULE_DEPEND(random_fortuna, crypto, 1, 1, 1);
+
+#endif /* _KERNEL */
Index: sys/dev/random/hash.h
===================================================================
--- sys/dev/random/hash.h
+++ sys/dev/random/hash.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000-2013 Mark R V Murray
+ * Copyright (c) 2000-2015 Mark R V Murray
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,10 +27,14 @@
*/
#ifndef SYS_DEV_RANDOM_HASH_H_INCLUDED
-#define 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 */
+#define RANDOM_KEYSIZE 32 /* (in bytes) == 256 bits */
+#define RANDOM_KEYSIZE_WORDS (RANDOM_KEYSIZE/sizeof(uint32_t))
+#define RANDOM_BLOCKSIZE 16 /* (in bytes) == 128 bits */
+#define RANDOM_BLOCKSIZE_WORDS (RANDOM_BLOCKSIZE/sizeof(uint32_t))
+#define RANDOM_KEYS_PER_BLOCK (RANDOM_KEYSIZE/RANDOM_BLOCKSIZE)
+#define RANDOM_ZERO_BLOCKSIZE 64 /* (in bytes) == 512 zero bits */
struct randomdev_hash { /* Big! Make static! */
SHA256_CTX sha;
@@ -47,4 +51,4 @@
void randomdev_encrypt_init(struct randomdev_key *, const void *);
void randomdev_encrypt(struct randomdev_key *context, const void *, void *, u_int);
-#endif
+#endif /* SYS_DEV_RANDOM_HASH_H_INCLUDED */
Index: sys/dev/random/hash.c
===================================================================
--- sys/dev/random/hash.c
+++ sys/dev/random/hash.c
@@ -47,8 +47,8 @@
#include <dev/random/hash.h>
-/* This code presumes that KEYSIZE is twice as large as BLOCKSIZE */
-CTASSERT(KEYSIZE == 2*BLOCKSIZE);
+/* This code presumes that RANDOM_KEYSIZE is twice as large as RANDOM_BLOCKSIZE */
+CTASSERT(RANDOM_KEYSIZE == 2*RANDOM_BLOCKSIZE);
/* Initialise the hash */
void
@@ -67,7 +67,7 @@
}
/* Conclude by returning the hash in the supplied <*buf> which must be
- * KEYSIZE bytes long.
+ * RANDOM_KEYSIZE bytes long.
*/
void
randomdev_hash_finish(struct randomdev_hash *context, void *buf)
@@ -77,7 +77,7 @@
}
/* Initialise the encryption routine by setting up the key schedule
- * from the supplied <*data> which must be KEYSIZE bytes of binary
+ * from the supplied <*data> which must be RANDOM_KEYSIZE bytes of binary
* data. Use CBC mode for better avalanche.
*/
void
@@ -85,12 +85,12 @@
{
rijndael_cipherInit(&context->cipher, MODE_CBC, NULL);
- rijndael_makeKey(&context->key, DIR_ENCRYPT, KEYSIZE*8, data);
+ rijndael_makeKey(&context->key, DIR_ENCRYPT, RANDOM_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.
+ * a multiple of RANDOM_BLOCKSIZE.
*/
void
randomdev_encrypt(struct randomdev_key *context, const void *d_in, void *d_out, u_int length)
Index: sys/dev/random/ivy.c
===================================================================
--- sys/dev/random/ivy.c
+++ sys/dev/random/ivy.c
@@ -46,7 +46,6 @@
#include <machine/specialreg.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>
Index: sys/dev/random/live_entropy_sources.h
===================================================================
--- sys/dev/random/live_entropy_sources.h
+++ sys/dev/random/live_entropy_sources.h
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2013 Arthur Mesh <arthurmesh@gmail.com>
- * Copyright (c) 2013 Mark R V Murray
+ * Copyright (c) 2013-2015 Mark R V Murray
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,7 +28,7 @@
*/
#ifndef SYS_DEV_RANDOM_LIVE_ENTROPY_SOURCES_H_INCLUDED
-#define SYS_DEV_RANDOM_LIVE_ENTROPY_SOURCES_H_INCLUDED
+#define SYS_DEV_RANDOM_LIVE_ENTROPY_SOURCES_H_INCLUDED
typedef u_int random_live_read_func_t(void *, u_int);
@@ -54,6 +54,13 @@
void live_entropy_sources_deinit(void);
void live_entropy_source_register(struct live_entropy_source *);
void live_entropy_source_deregister(struct live_entropy_source *);
-void live_entropy_sources_feed(void);
+void live_entropy_sources_feed(u_int);
+
+#define LIVE_SOURCE_INIT_LOCK(x) sx_init(&les_lock, "live_entropy_sources")
+#define LIVE_SOURCE_DEINIT_LOCK(x) sx_destroy(&les_lock)
+#define LIVE_SOURCE_EXCLUSIVE_LOCK(x) sx_xlock(&les_lock)
+#define LIVE_SOURCE_EXCLUSIVE_UNLOCK(x) sx_xunlock(&les_lock)
+#define LIVE_SOURCE_SHARED_LOCK(x) sx_slock(&les_lock)
+#define LIVE_SOURCE_SHARED_UNLOCK(x) sx_sunlock(&les_lock)
#endif /* SYS_DEV_RANDOM_LIVE_ENTROPY_SOURCES_H_INCLUDED */
Index: sys/dev/random/live_entropy_sources.c
===================================================================
--- sys/dev/random/live_entropy_sources.c
+++ sys/dev/random/live_entropy_sources.c
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2013 Arthur Mesh <arthurmesh@gmail.com>
- * Copyright (c) 2013 Mark R V Murray
+ * Copyright (c) 2013-2015 Mark R V Murray
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,8 +28,6 @@
#include <sys/param.h>
__FBSDID("$FreeBSD$");
-#include "opt_random.h"
-
#include <sys/kernel.h>
#include <sys/libkern.h>
#include <sys/lock.h>
@@ -46,7 +44,6 @@
#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>
@@ -70,9 +67,9 @@
lles = malloc(sizeof(*lles), M_ENTROPY, M_WAITOK);
lles->lles_rsource = rsource;
- sx_xlock(&les_lock);
+ LIVE_SOURCE_EXCLUSIVE_LOCK();
LIST_INSERT_HEAD(&les_sources, lles, lles_entries);
- sx_xunlock(&les_lock);
+ LIVE_SOURCE_EXCLUSIVE_UNLOCK();
}
void
@@ -82,13 +79,13 @@
KASSERT(rsource != NULL, ("invalid input to %s", __func__));
- sx_xlock(&les_lock);
+ LIVE_SOURCE_EXCLUSIVE_LOCK();
LIST_FOREACH(lles, &les_sources, lles_entries)
if (lles->lles_rsource == rsource) {
LIST_REMOVE(lles, lles_entries);
break;
}
- sx_xunlock(&les_lock);
+ LIVE_SOURCE_EXCLUSIVE_UNLOCK();
if (lles != NULL)
free(lles, M_ENTROPY);
}
@@ -100,22 +97,20 @@
struct sbuf sbuf;
int error, count;
- sx_slock(&les_lock);
-
sbuf_new_for_sysctl(&sbuf, NULL, 64, req);
-
count = 0;
+
+ LIVE_SOURCE_SHARED_LOCK();
LIST_FOREACH(lles, &les_sources, lles_entries) {
sbuf_cat(&sbuf, (count++ ? ",'" : "'"));
sbuf_cat(&sbuf, lles->lles_rsource->les_ident);
sbuf_cat(&sbuf, "'");
}
+ LIVE_SOURCE_SHARED_UNLOCK();
error = sbuf_finish(&sbuf);
sbuf_delete(&sbuf);
- sx_sunlock(&les_lock);
-
return (error);
}
@@ -133,41 +128,38 @@
* read which can be quite expensive.
*/
void
-live_entropy_sources_feed(void)
+live_entropy_sources_feed(u_int pool_count)
{
static struct harvest_event event;
struct live_entropy_sources *lles;
- int i, read_rate;
- u_int n;
+ u_int i, n, read_rate;
- sx_slock(&les_lock);
/*
- * Walk over all of live entropy sources, and feed their output
+ * Step over all of live entropy sources, and feed their output
* to the system-wide RNG.
*/
read_rate = random_adaptor_read_rate();
+ LIVE_SOURCE_SHARED_LOCK();
LIST_FOREACH(lles, &les_sources, lles_entries) {
- for (i = 0; i < harvest_pool_count*read_rate; i++) {
+ for (i = 0; i < pool_count*read_rate; i++) {
/* This *must* be quick, since it's a live entropy source. */
- n = lles->lles_rsource->les_read(event.he_entropy, HARVESTSIZE);
- KASSERT((n > 0 && n <= HARVESTSIZE), ("very bad return from les_read (= %d) in %s", n, __func__));
- memset(event.he_entropy + n, 0, HARVESTSIZE - n);
+ n = lles->lles_rsource->les_read(event.he_entropy, sizeof(event.he_entropy));
+ KASSERT((n > 0 && n <= sizeof(event.he_entropy)), ("very bad return from les_read (= %d) in %s", n, __func__));
+ memset(event.he_entropy + n, 0, sizeof(event.he_entropy) - n);
event.he_somecounter = get_cyclecount();
event.he_size = n;
event.he_bits = (n*8)/2;
event.he_source = lles->lles_rsource->les_source;
- event.he_destination = harvest_destination[event.he_source]++;
/* Do the actual entropy insertion */
- harvest_process_event(&event);
+ harvest_fast_process_event(&event);
}
}
-
- sx_sunlock(&les_lock);
+ LIVE_SOURCE_SHARED_UNLOCK();
}
void
@@ -179,12 +171,12 @@
NULL, 0, live_entropy_source_handler, "",
"List of Active Live Entropy Sources");
- sx_init(&les_lock, "live_entropy_sources");
+ LIVE_SOURCE_INIT_LOCK();
}
void
live_entropy_sources_deinit(void)
{
- sx_destroy(&les_lock);
+ LIVE_SOURCE_DEINIT_LOCK();
}
Index: sys/dev/random/nehemiah.c
===================================================================
--- sys/dev/random/nehemiah.c
+++ sys/dev/random/nehemiah.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2013 Mark R V Murray
+ * Copyright (c) 2013-2015 Mark R V Murray
* Copyright (c) 2013 David E. O'Brien <obrien@NUXI.org>
* All rights reserved.
*
@@ -44,7 +44,6 @@
#include <machine/specialreg.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>
Index: sys/dev/random/random_adaptors.h
===================================================================
--- sys/dev/random/random_adaptors.h
+++ sys/dev/random/random_adaptors.h
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2013 Arthur Mesh <arthurmesh@gmail.com>
+ * Copyright (c) 2013-2015 Mark R V Murray
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,13 +28,17 @@
*/
#ifndef SYS_DEV_RANDOM_RANDOM_ADAPTORS_H_INCLUDED
-#define SYS_DEV_RANDOM_RANDOM_ADAPTORS_H_INCLUDED
+#define SYS_DEV_RANDOM_RANDOM_ADAPTORS_H_INCLUDED
MALLOC_DECLARE(M_ENTROPY);
+#define RANDOM_ADAPTOR_READ_RATE_MINIMUM 32
+
typedef void random_adaptor_init_func_t(void);
typedef void random_adaptor_deinit_func_t(void);
+typedef void random_adaptor_pre_read_func_t(void);
typedef void random_adaptor_read_func_t(uint8_t *, u_int);
+typedef void random_adaptor_post_read_func_t(void);
typedef void random_adaptor_write_func_t(uint8_t *, u_int);
typedef int random_adaptor_seeded_func_t(void);
typedef void random_adaptor_reseed_func_t(void);
@@ -43,7 +48,9 @@
int ra_priority;
random_adaptor_init_func_t *ra_init;
random_adaptor_deinit_func_t *ra_deinit;
+ random_adaptor_pre_read_func_t *ra_pre_read;
random_adaptor_read_func_t *ra_read;
+ random_adaptor_post_read_func_t *ra_post_read;
random_adaptor_write_func_t *ra_write;
random_adaptor_reseed_func_t *ra_reseed;
random_adaptor_seeded_func_t *ra_seeded;
@@ -68,7 +75,16 @@
int random_adaptor_write(struct cdev *, struct uio *, int);
int random_adaptor_poll(struct cdev *, int, struct thread *);
-int random_adaptor_read_rate(void);
+u_int random_adaptor_read_rate(void);
void random_adaptor_unblock(void);
+#define RANDOM_ADAPTOR_INIT_LOCK(x) sx_init(&random_adaptors_lock, "random_adaptors")
+#define RANDOM_ADAPTOR_DEINIT_LOCK(x) sx_destroy(&random_adaptors_lock)
+#define RANDOM_ADAPTOR_EXCLUSIVE_LOCK(x) sx_xlock(&random_adaptors_lock)
+#define RANDOM_ADAPTOR_EXCLUSIVE_UNLOCK(x) sx_xunlock(&random_adaptors_lock)
+#define RANDOM_ADAPTOR_SHARED_LOCK(x) sx_slock(&random_adaptors_lock)
+#define RANDOM_ADAPTOR_SHARED_UNLOCK(x) sx_sunlock(&random_adaptors_lock)
+#define RANDOM_ADAPTOR_ASSERT_LOCK_OWNED_EXCL(x) sx_assert(&random_adaptors_lock, SA_XLOCKED)
+#define RANDOM_ADAPTOR_LOCK_SLEEP(wmsg) sx_sleep(&random_adaptor, &random_adaptors_lock, PUSER | PCATCH, wmsg, hz/10)
+
#endif /* SYS_DEV_RANDOM_RANDOM_ADAPTORS_H_INCLUDED */
Index: sys/dev/random/random_adaptors.c
===================================================================
--- sys/dev/random/random_adaptors.c
+++ sys/dev/random/random_adaptors.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2013 Mark R V Murray
+ * Copyright (c) 2013-2015 Mark R V Murray
* Copyright (c) 2013 Arthur Mesh <arthurmesh@gmail.com>
* Copyright (c) 2013 David E. O'Brien <obrien@NUXI.org>
* All rights reserved.
@@ -29,8 +29,6 @@
#include <sys/param.h>
__FBSDID("$FreeBSD$");
-#include "opt_random.h"
-
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/fcntl.h>
@@ -51,9 +49,10 @@
#include <sys/uio.h>
#include <sys/unistd.h>
+#include <machine/atomic.h>
+
#include <dev/random/randomdev.h>
#include <dev/random/random_adaptors.h>
-#include <dev/random/live_entropy_sources.h>
/* The random_adaptors_lock protects random_adaptors_list and friends and random_adaptor.
* We need a sleepable lock for uiomove/block/poll/sbuf/sysctl.
@@ -64,12 +63,7 @@
static struct random_adaptor *random_adaptor = NULL; /* Currently active adaptor */
/* End of data items requiring random_adaptors_lock 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 */
-
+static volatile u_int random_adaptor_read_rate_cache = RANDOM_ADAPTOR_READ_RATE_MINIMUM;
static struct selinfo rsel;
/* Utility routine to change active adaptor when the random_adaptors_list
@@ -87,10 +81,8 @@
struct random_adaptor *random_adaptor_previous;
int primax;
- /* We are going to be messing with random_adaptor.
- * Exclusive lock is mandatory.
- */
- sx_assert(&random_adaptors_lock, SA_XLOCKED);
+ /* We are going to be changing random_adaptor. Exclusive lock is mandatory. */
+ RANDOM_ADAPTOR_ASSERT_LOCK_OWNED_EXCL();
random_adaptor_previous = random_adaptor;
@@ -144,11 +136,10 @@
/* If we are changing adaptors, deinit the old and init the new. */
if (random_adaptor != random_adaptor_previous) {
-#ifdef RANDOM_DEBUG
- printf("random: %s - changing from %s to %s\n", __func__,
- (random_adaptor_previous == NULL ? "NULL" : random_adaptor_previous->ra_ident),
- random_adaptor->ra_ident);
-#endif
+ if (bootverbose)
+ printf("random: %s - changing from %s to %s\n", __func__,
+ (random_adaptor_previous == NULL ? "NULL" : random_adaptor_previous->ra_ident),
+ random_adaptor->ra_ident);
if (random_adaptor_previous != NULL) {
randomdev_deinit_reader();
(random_adaptor_previous->ra_deinit)();
@@ -172,11 +163,11 @@
rra->rra_name = name;
rra->rra_ra = ra;
- sx_xlock(&random_adaptors_lock);
+ RANDOM_ADAPTOR_EXCLUSIVE_LOCK();
LIST_INSERT_HEAD(&random_adaptors_list, rra, rra_entries);
random_adaptor_choose();
+ RANDOM_ADAPTOR_EXCLUSIVE_UNLOCK();
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
- sx_xunlock(&random_adaptors_lock);
}
void
@@ -185,16 +176,16 @@
struct random_adaptors *rra;
KASSERT(name != NULL, ("invalid input to %s", __func__));
-
- sx_xlock(&random_adaptors_lock);
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
+
+ RANDOM_ADAPTOR_EXCLUSIVE_LOCK();
LIST_FOREACH(rra, &random_adaptors_list, rra_entries)
if (strcmp(rra->rra_name, name) == 0) {
LIST_REMOVE(rra, rra_entries);
break;
}
random_adaptor_choose();
- sx_xunlock(&random_adaptors_lock);
+ RANDOM_ADAPTOR_EXCLUSIVE_UNLOCK();
free(rra, M_ENTROPY);
}
@@ -207,18 +198,18 @@
int c, error;
ssize_t nbytes;
-#ifdef RANDOM_DEBUG_VERBOSE
+#ifdef RANDOM_DEBUG
printf("random: %s %ld\n", __func__, uio->uio_resid);
#endif
- random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK);
+ KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
- sx_slock(&random_adaptors_lock);
+ random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK);
- KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
+ RANDOM_ADAPTOR_SHARED_LOCK();
/* Let the entropy source do any pre-read setup. */
- (random_adaptor->ra_read)(NULL, 0);
+ (random_adaptor->ra_pre_read)();
/* (Un)Blocking logic */
error = 0;
@@ -229,25 +220,18 @@
}
/* Sleep instead of going into a spin-frenzy */
- error = sx_sleep(&random_adaptor, &random_adaptors_lock,
- PUSER | PCATCH, "randrd", hz/10);
+ error = RANDOM_ADAPTOR_LOCK_SLEEP("randrd");
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s",
__func__));
/* keep tapping away at the pre-read until we seed/unblock. */
- (random_adaptor->ra_read)(NULL, 0);
+ (random_adaptor->ra_pre_read)();
}
- mtx_lock(&random_read_rate_mtx);
-
/* 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);
-
- mtx_unlock(&random_read_rate_mtx);
+ atomic_add_int(&random_adaptor_read_rate_cache, (uio->uio_resid + sizeof(uint32_t))/sizeof(uint32_t));
if (error == 0) {
nbytes = uio->uio_resid;
@@ -260,53 +244,44 @@
}
/* Let the entropy source do any post-read cleanup. */
- (random_adaptor->ra_read)(NULL, 1);
+ (random_adaptor->ra_post_read)();
if (nbytes != uio->uio_resid && (error == ERESTART ||
error == EINTR) )
error = 0; /* Return partial read, not error. */
}
- sx_sunlock(&random_adaptors_lock);
+ RANDOM_ADAPTOR_SHARED_UNLOCK();
free(random_buf, M_ENTROPY);
return (error);
}
-int
+u_int
random_adaptor_read_rate(void)
{
- int ret;
- mtx_lock(&random_read_rate_mtx);
-
- ret = random_adaptor_read_rate_cache;
- random_adaptor_read_rate_cache = 1;
-
- mtx_unlock(&random_read_rate_mtx);
-
- return (ret);
+ return atomic_swap_int(&random_adaptor_read_rate_cache, RANDOM_ADAPTOR_READ_RATE_MINIMUM);
}
/* ARGSUSED */
int
random_adaptor_write(struct cdev *dev __unused, struct uio *uio, int flags __unused)
{
- int c, error = 0;
void *random_buf;
+ int c, error = 0;
ssize_t nbytes;
#ifdef RANDOM_DEBUG
printf("random: %s %zd\n", __func__, uio->uio_resid);
#endif
- random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK);
-
- sx_slock(&random_adaptors_lock);
-
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
+ random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK);
+
+ RANDOM_ADAPTOR_SHARED_LOCK();
nbytes = uio->uio_resid;
while (uio->uio_resid > 0 && error == 0) {
c = MIN(uio->uio_resid, PAGE_SIZE);
@@ -316,13 +291,11 @@
(random_adaptor->ra_write)(random_buf, c);
/* Introduce an annoying delay to stop swamping */
- error = sx_sleep(&random_adaptor, &random_adaptors_lock,
- PUSER | PCATCH, "randwr", hz/10);
+ error = RANDOM_ADAPTOR_LOCK_SLEEP("randwr");
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s",
__func__));
}
-
- sx_sunlock(&random_adaptors_lock);
+ RANDOM_ADAPTOR_SHARED_UNLOCK();
if (nbytes != uio->uio_resid && (error == ERESTART ||
error == EINTR) )
@@ -338,22 +311,16 @@
random_adaptor_poll(struct cdev *dev __unused, int events, struct thread *td __unused)
{
-#ifdef RANDOM_DEBUG
- printf("random: %s\n", __func__);
-#endif
-
- sx_slock(&random_adaptors_lock);
-
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
+ RANDOM_ADAPTOR_SHARED_LOCK();
if (events & (POLLIN | POLLRDNORM)) {
if (random_adaptor->ra_seeded())
events &= (POLLIN | POLLRDNORM);
else
selrecord(td, &rsel);
}
-
- sx_sunlock(&random_adaptors_lock);
+ RANDOM_ADAPTOR_SHARED_UNLOCK();
return (events);
}
@@ -367,7 +334,7 @@
wakeup(&random_adaptor);
printf("random: unblocking device.\n");
- /* Do arc4random(9) a favour while we are about it. */
+ /* Do random(9) a favour while we are about it. */
(void)atomic_cmpset_int(&arc4rand_iniseed_state, ARC4_ENTR_NONE, ARC4_ENTR_HAVE);
}
@@ -378,16 +345,15 @@
struct sbuf sbuf;
int error, count;
- sx_slock(&random_adaptors_lock);
sbuf_new_for_sysctl(&sbuf, NULL, 64, req);
count = 0;
+ RANDOM_ADAPTOR_SHARED_LOCK();
LIST_FOREACH(rra, &random_adaptors_list, rra_entries)
sbuf_printf(&sbuf, "%s%s(%d)",
(count++ ? "," : ""), rra->rra_name, rra->rra_ra->ra_priority);
-
+ RANDOM_ADAPTOR_SHARED_UNLOCK();
error = sbuf_finish(&sbuf);
sbuf_delete(&sbuf);
- sx_sunlock(&random_adaptors_lock);
return (error);
}
@@ -399,18 +365,18 @@
struct sbuf sbuf;
int error;
- sx_slock(&random_adaptors_lock);
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
sbuf_new_for_sysctl(&sbuf, NULL, 16, req);
+ RANDOM_ADAPTOR_SHARED_LOCK();
LIST_FOREACH(rra, &random_adaptors_list, rra_entries)
if (rra->rra_ra == random_adaptor) {
sbuf_cat(&sbuf, rra->rra_name);
break;
}
+ RANDOM_ADAPTOR_SHARED_UNLOCK();
error = sbuf_finish(&sbuf);
sbuf_delete(&sbuf);
- sx_sunlock(&random_adaptors_lock);
return (error);
}
@@ -419,10 +385,6 @@
random_adaptors_init(void)
{
-#ifdef RANDOM_DEBUG
- printf("random: %s\n", __func__);
-#endif
-
SYSCTL_PROC(_kern_random, OID_AUTO, adaptors,
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
NULL, 0, random_sysctl_adaptors_handler, "A",
@@ -433,34 +395,24 @@
NULL, 0, random_sysctl_active_adaptor_handler, "A",
"Active Random Number Generator Adaptor");
- sx_init(&random_adaptors_lock, "random_adaptors");
-
- mtx_init(&random_read_rate_mtx, "read rate mutex", NULL, MTX_DEF);
+ RANDOM_ADAPTOR_INIT_LOCK();
/* The dummy adaptor is not a module by itself, but part of the
* randomdev module.
*/
random_adaptor_register("dummy", &randomdev_dummy);
-
- live_entropy_sources_init();
}
void
random_adaptors_deinit(void)
{
-#ifdef RANDOM_DEBUG
- printf("random: %s\n", __func__);
+#if 0
+ /* Don't do this! Panic will surely follow! (Here for completeness) */
+ random_adaptor_deregister("dummy");
#endif
- live_entropy_sources_deinit();
-
- /* Don't do this! Panic will surely follow! */
- /* random_adaptor_deregister("dummy"); */
-
- mtx_destroy(&random_read_rate_mtx);
-
- sx_destroy(&random_adaptors_lock);
+ RANDOM_ADAPTOR_DEINIT_LOCK();
}
/*
@@ -470,12 +422,12 @@
static void
random_adaptors_seed(void *unused __unused)
{
-
- sx_slock(&random_adaptors_lock);
+
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
+ RANDOM_ADAPTOR_SHARED_LOCK();
random_adaptor->ra_reseed();
- sx_sunlock(&random_adaptors_lock);
+ RANDOM_ADAPTOR_SHARED_UNLOCK();
arc4rand(NULL, 0, 1);
}
Index: sys/dev/random/random_harvestq.h
===================================================================
--- sys/dev/random/random_harvestq.h
+++ sys/dev/random/random_harvestq.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2013-2014 Mark R V Murray
+ * Copyright (c) 2013-2015 Mark R V Murray
* Copyright (c) 2013 Arthur Mesh <arthurmesh@gmail.com>
* All rights reserved.
*
@@ -28,16 +28,16 @@
*/
#ifndef SYS_DEV_RANDOM_RANDOM_HARVESTQ_H_INCLUDED
-#define SYS_DEV_RANDOM_RANDOM_HARVESTQ_H_INCLUDED
+#define SYS_DEV_RANDOM_RANDOM_HARVESTQ_H_INCLUDED
-#define HARVESTSIZE 16 /* max size of each harvested entropy unit */
+#define HARVESTSIZE 4 /* Max length in words of each harvested entropy unit */
/* These are used to queue harvested packets of entropy. The entropy
* buffer size is pretty arbitrary.
*/
struct harvest_event {
uintmax_t he_somecounter; /* fast counter for clock jitter */
- uint8_t he_entropy[HARVESTSIZE];/* some harvested entropy */
+ uint32_t he_entropy[HARVESTSIZE];/* some harvested entropy */
u_int he_size; /* harvested entropy byte count */
u_int he_bits; /* stats about the entropy */
u_int he_destination; /* destination pool of this entropy */
@@ -48,23 +48,12 @@
void random_harvestq_deinit(void);
void random_harvestq_internal(const void *, u_int, u_int, enum random_entropy_source);
-/* Pool count is used by anything needing to know how many entropy
- * pools are currently being maintained.
- * This is of use to (e.g.) the live source feed where we need to give
- * all the pools a top-up.
- */
-extern int harvest_pool_count;
-
-/* This is in randomdev.c as it needs to be permanently in the kernel */
-void randomdev_set_wakeup_exit(void *);
-
-/* Force all currently pending queue contents to clear, and kick the software processor */
-void random_harvestq_flush(void);
+void harvest_fast_process_event(struct harvest_event *);
-/* Function called to process one harvested stochastic event */
-extern void (*harvest_process_event)(struct harvest_event *);
+#define RANDOM_HARVESTQ_BOOT_ENTROPY_FILE "/boot/entropy"
-/* Round-robin destination cache. */
-extern u_int harvest_destination[ENTROPYSOURCE];
+#define RANDOM_HARVEST_INIT_LOCK(x) mtx_init(&harvest_context.harvest_mtx, "entropy harvest mutex", NULL, MTX_SPIN)
+#define RANDOM_HARVEST_LOCK(x) mtx_lock_spin(&harvest_context.harvest_mtx)
+#define RANDOM_HARVEST_UNLOCK(x) mtx_unlock_spin(&harvest_context.harvest_mtx)
#endif /* SYS_DEV_RANDOM_RANDOM_HARVESTQ_H_INCLUDED */
Index: sys/dev/random/random_harvestq.c
===================================================================
--- sys/dev/random/random_harvestq.c
+++ sys/dev/random/random_harvestq.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000-2014 Mark R V Murray
+ * Copyright (c) 2000-2015 Mark R V Murray
* Copyright (c) 2013 Arthur Mesh
* Copyright (c) 2004 Robert N. M. Watson
* All rights reserved.
@@ -30,16 +30,16 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include "opt_random.h"
-
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/conf.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/module.h>
#include <sys/mutex.h>
#include <sys/random.h>
#include <sys/sbuf.h>
@@ -62,13 +62,42 @@
* supplied junk. When used, they are transferred back to the
* 'empty' queue.
*/
-#define RANDOM_FIFO_MAX 1024
+#define RANDOM_FIFO_MAX 1024
+
+/* 1 to let the kernel thread run, 0 to terminate */
+volatile int random_kthread_control;
/*
- * The harvest mutex protects the consistency of the entropy Fifos and
- * empty fifo and other associated structures.
+ * Put all the harvest queue context stuff in one place.
+ * this make is a bit easier to lock and protect.
*/
-static struct mtx harvest_mtx;
+static struct harvest_context {
+
+ /* Make multiple inits possible */
+ int harvest_initialised;
+
+ /*
+ * The harvest mutex protects the consistency of the entropy Fifos and
+ * empty fifo and other associated structures.
+ */
+ struct mtx harvest_mtx;
+
+ /* Round-robin destination cache. */
+ u_int harvest_destination[ENTROPYSOURCE];
+
+ /* Function called to process one harvested stochastic event */
+ void (*harvest_process_event)(struct harvest_event *);
+
+ /* Pool count is used by anything needing to know how many entropy
+ * pools are currently being maintained.
+ * This is of use to (e.g.) the live source feed where we need to give
+ * all the pools a top-up.
+ */
+ int harvest_pool_count;
+
+ struct proc *harvest_kthread_proc;
+
+} harvest_context;
/*
* Lockable FIFO ring buffer holding entropy events
@@ -91,28 +120,18 @@
volatile u_int ring_out;
} entropyfifo;
-/* Round-robin destination cache. */
-u_int harvest_destination[ENTROPYSOURCE];
-
-/* Function called to process one harvested stochastic event */
-void (*harvest_process_event)(struct harvest_event *);
-
-/* Allow the sysadmin to select the broad category of
- * entropy types to harvest.
- */
-static u_int harvest_source_mask = ((1U << RANDOM_ENVIRONMENTAL_END) - 1);
-
-/* Pool count is used by anything needing to know how many entropy
- * pools are currently being maintained.
- * This is of use to (e.g.) the live source feed where we need to give
- * all the pools a top-up.
+/*
+ * Pass the given event straight through to Fortuna/Yarrow/Whatever
+ * This is for high-rate, efficient sources only.
*/
-int harvest_pool_count;
-
-/* <0 to end the kthread, 0 to let it run, 1 to flush the harvest queues */
-static int random_kthread_control = 0;
+void
+harvest_fast_process_event(struct harvest_event *event)
+{
-static struct proc *random_kthread_proc;
+ /* sx_assert(&les_lock, SA_LOCKED); */
+ event->he_destination = harvest_context.harvest_destination[event->he_source%harvest_context.harvest_pool_count]++;
+ harvest_context.harvest_process_event(event);
+}
static void
random_kthread(void *arg __unused)
@@ -120,20 +139,20 @@
u_int maxloop, ring_out;
/*
- * Process until told to stop.
- *
* Locking is not needed as this is the only place we modify ring_out, and
* we only examine ring_in without changing it. Both of these are volatile,
* and this is a unique thread.
+ * XXX: FIX!! Is there a race when terminating?
*/
- while (random_kthread_control >= 0) {
+ for (random_kthread_control = 1; random_kthread_control;) {
/* Deal with events, if any. Restrict the number we do in one go. */
maxloop = RANDOM_FIFO_MAX;
while (entropyfifo.ring_out != entropyfifo.ring_in) {
ring_out = (entropyfifo.ring_out + 1)%RANDOM_FIFO_MAX;
- harvest_process_event(entropyfifo.ring + ring_out);
+ /* This is a direct call into Yarrow/Fortuna/Whatever */
+ harvest_context.harvest_process_event(entropyfifo.ring + ring_out);
/* Modifying ring_out here ONLY. Sufficient for atomicity? */
entropyfifo.ring_out = ring_out;
@@ -144,37 +163,28 @@
}
/*
- * Give the fast hardware sources a go
+ * Give the fast hardware sources a go. These will ultimately
+ * call back through the harvest_fast_process_event() function
+ * above.
*/
- live_entropy_sources_feed();
+ live_entropy_sources_feed(harvest_context.harvest_pool_count);
- /*
- * If a queue flush was commanded, it has now happened,
- * and we can mark this by resetting the command.
- * A negative value, however, terminates the thread.
- */
-
- if (random_kthread_control == 1)
- random_kthread_control = 0;
+ /* XXX: FIX!! This is a *great* place to pass hardware/live entropy to random(9) */
/* Some work is done, so give the rest of the OS a chance. */
- tsleep_sbt(&random_kthread_control, 0, "-", SBT_1S/10, 0, C_PREL(1));
+ tsleep_sbt(&harvest_context.harvest_kthread_proc, 0, "-", SBT_1S/10, 0, C_PREL(1));
}
- randomdev_set_wakeup_exit(&random_kthread_control);
+ wakeup(&harvest_context.harvest_kthread_proc);
+ kproc_exit(0);
/* NOTREACHED */
}
-void
-random_harvestq_flush(void)
-{
-
- /* Command a entropy queue flush and wait for it to finish */
- random_kthread_control = 1;
- while (random_kthread_control)
- pause("-", hz/10);
-}
+/* Allow the sysadmin to select the broad category of
+ * entropy types to harvest.
+ */
+static u_int harvest_source_mask = ((1U << RANDOM_ENVIRONMENTAL_END) - 1);
/* ARGSUSED */
RANDOM_CHECK_UINT(harvestmask, 0, ((1U << RANDOM_ENVIRONMENTAL_END) - 1));
@@ -250,83 +260,87 @@
size_t size, j;
struct sysctl_oid *random_sys_o;
-#ifdef RANDOM_DEBUG
- printf("random: %s\n", __func__);
-#endif
+ if (!harvest_context.harvest_initialised) {
- random_sys_o = SYSCTL_ADD_NODE(&random_clist,
- SYSCTL_STATIC_CHILDREN(_kern_random),
- OID_AUTO, "harvest", CTLFLAG_RW, 0,
- "Entropy Device Parameters");
+ random_sys_o = SYSCTL_ADD_NODE(&random_clist,
+ SYSCTL_STATIC_CHILDREN(_kern_random),
+ OID_AUTO, "harvest", CTLFLAG_RW, 0,
+ "Entropy Device Parameters");
- SYSCTL_ADD_PROC(&random_clist,
- SYSCTL_CHILDREN(random_sys_o),
- OID_AUTO, "mask", CTLTYPE_UINT | CTLFLAG_RW,
- &harvest_source_mask, ((1U << RANDOM_ENVIRONMENTAL_END) - 1),
- random_check_uint_harvestmask, "IU",
- "Entropy harvesting mask");
+ SYSCTL_ADD_PROC(&random_clist,
+ SYSCTL_CHILDREN(random_sys_o),
+ OID_AUTO, "mask", CTLTYPE_UINT | CTLFLAG_RW,
+ &harvest_source_mask, ((1U << RANDOM_ENVIRONMENTAL_END) - 1),
+ random_check_uint_harvestmask, "IU",
+ "Entropy harvesting mask");
- SYSCTL_ADD_PROC(&random_clist,
- SYSCTL_CHILDREN(random_sys_o),
- OID_AUTO, "mask_bin", CTLTYPE_STRING | CTLFLAG_RD,
- NULL, 0, random_print_harvestmask, "A", "Entropy harvesting mask (printable)");
+ SYSCTL_ADD_PROC(&random_clist,
+ SYSCTL_CHILDREN(random_sys_o),
+ OID_AUTO, "mask_bin", CTLTYPE_STRING | CTLFLAG_RD,
+ NULL, 0, random_print_harvestmask, "A", "Entropy harvesting mask (printable)");
- SYSCTL_ADD_PROC(&random_clist,
- SYSCTL_CHILDREN(random_sys_o),
- OID_AUTO, "mask_symbolic", CTLTYPE_STRING | CTLFLAG_RD,
- NULL, 0, random_print_harvestmask_symbolic, "A", "Entropy harvesting mask (symbolic)");
+ SYSCTL_ADD_PROC(&random_clist,
+ SYSCTL_CHILDREN(random_sys_o),
+ OID_AUTO, "mask_symbolic", CTLTYPE_STRING | CTLFLAG_RD,
+ NULL, 0, random_print_harvestmask_symbolic, "A", "Entropy harvesting mask (symbolic)");
- /* Point to the correct event_processing function */
- harvest_process_event = event_processor;
+ RANDOM_HARVEST_INIT_LOCK();
- /* Store the pool count (used by live source feed) */
- harvest_pool_count = poolcount;
+ /* Start the hash/reseed thread */
+ entropyfifo.ring_in = entropyfifo.ring_out = 0U;
+ error = kproc_create(random_kthread, NULL,
+ &harvest_context.harvest_kthread_proc, RFHIGHPID, 0, "rand_harvestq");
- /* Initialise the harvesting mutex and in/out indexes. */
- mtx_init(&harvest_mtx, "entropy harvest mutex", NULL, MTX_SPIN);
- entropyfifo.ring_in = entropyfifo.ring_out = 0U;
+ if (error != 0)
+ panic("Cannot create entropy maintenance thread.");
- /* Start the hash/reseed thread */
- error = kproc_create(random_kthread, NULL,
- &random_kthread_proc, RFHIGHPID, 0, "rand_harvestq");
+ harvest_context.harvest_initialised = 1;
- if (error != 0)
- panic("Cannot create entropy maintenance thread.");
+ }
+
+ RANDOM_HARVEST_LOCK();
+ harvest_context.harvest_pool_count = poolcount;
+ harvest_context.harvest_process_event = event_processor;
+ RANDOM_HARVEST_UNLOCK();
- /* Get entropy that may have been preloaded by loader(8)
+ /*
+ * Get entropy that may have been preloaded by loader(8)
* and use it to pre-charge the entropy harvest queue.
*/
- keyfile = preload_search_by_type("/boot/entropy");
+ keyfile = preload_search_by_type(RANDOM_HARVESTQ_BOOT_ENTROPY_FILE);
if (keyfile != NULL) {
data = preload_fetch_addr(keyfile);
size = preload_fetch_size(keyfile);
if (data != NULL && size != 0) {
for (j = 0; j < size; j += 16)
random_harvestq_internal(data + j, 16, 16, RANDOM_CACHED);
- printf("random: read %zu bytes from preloaded cache\n", size);
bzero(data, size);
+ if (bootverbose)
+ printf("random: read %zu bytes from preloaded cache\n", size);
}
else
- printf("random: no preloaded entropy cache\n");
+ if (bootverbose)
+ printf("random: no preloaded entropy cache\n");
}
+ live_entropy_sources_init();
+
}
void
random_harvestq_deinit(void)
{
-#ifdef RANDOM_DEBUG
- printf("random: %s\n", __func__);
-#endif
+ live_entropy_sources_deinit();
+
+ randomdev_deinit_harvester();
/*
* Command the hash/reseed thread to end and wait for it to finish
+ * XXX: FIX!! Is there a race when terminating the thread?
*/
- random_kthread_control = -1;
- tsleep(&random_kthread_control, 0, "term", 0);
-
- mtx_destroy(&harvest_mtx);
+ random_kthread_control = 0;
+ tsleep(&harvest_context.harvest_kthread_proc, 0, "term", 0);
sysctl_ctx_free(&random_clist);
}
@@ -359,24 +373,53 @@
if (!(harvest_source_mask & (1U << origin)))
return;
- /* Lock ring_in against multi-thread contention */
- mtx_lock_spin(&harvest_mtx);
+ RANDOM_HARVEST_LOCK();
ring_in = (entropyfifo.ring_in + 1)%RANDOM_FIFO_MAX;
if (ring_in != entropyfifo.ring_out) {
/* The ring is not full */
event = entropyfifo.ring + ring_in;
/* Stash the harvested stuff in the *event buffer */
- count = MIN(count, HARVESTSIZE);
+ count = MIN(count, sizeof(event->he_entropy));
event->he_somecounter = get_cyclecount();
event->he_size = count;
event->he_bits = bits;
event->he_source = origin;
- event->he_destination = harvest_destination[origin]++;
+ event->he_destination = harvest_context.harvest_destination[origin]++;
memcpy(event->he_entropy, entropy, count);
- memset(event->he_entropy + count, 0, HARVESTSIZE - count);
+ memset(event->he_entropy + count, 0, sizeof(event->he_entropy) - count);
entropyfifo.ring_in = ring_in;
}
- mtx_unlock_spin(&harvest_mtx);
+ RANDOM_HARVEST_UNLOCK();
}
+
+/* ARGSUSED */
+static int
+random_harvestq_modevent(module_t mod __unused, int type, void *data __unused)
+{
+ int error = 0;
+
+ switch (type) {
+ case MOD_LOAD:
+ printf("random: entropy device loadable infrastructure\n");
+ break;
+
+ case MOD_UNLOAD:
+ break;
+
+ case MOD_SHUTDOWN:
+ break;
+
+ default:
+ error = EOPNOTSUPP;
+ break;
+
+ }
+
+ return (error);
+}
+
+DEV_MODULE(random_harvestq, random_harvestq_modevent, NULL);
+MODULE_VERSION(random_harvestq, 1);
+MODULE_DEPEND(random_harvestq, randomdev, 1, 1, 1);
Index: sys/dev/random/randomdev.h
===================================================================
--- sys/dev/random/randomdev.h
+++ sys/dev/random/randomdev.h
@@ -27,7 +27,7 @@
*/
#ifndef SYS_DEV_RANDOM_RANDOMDEV_H_INCLUDED
-#define 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
@@ -41,15 +41,12 @@
void randomdev_deinit_harvester(void);
void randomdev_deinit_reader(void);
-/* Stub/fake routines for when no entropy processor is loaded */
-extern void dummy_random_read_phony(uint8_t *, u_int);
-
/* kern.random sysctls */
#ifdef SYSCTL_DECL /* from sysctl.h */
SYSCTL_DECL(_kern_random);
/* If this was C++, the macro below would be a template */
-#define RANDOM_CHECK_UINT(name, min, max) \
+#define RANDOM_CHECK_UINT(name, min, max) \
static int \
random_check_uint_##name(SYSCTL_HANDLER_ARGS) \
{ \
@@ -64,4 +61,4 @@
}
#endif /* SYSCTL_DECL */
-#endif
+#endif /* SYS_DEV_RANDOM_RANDOMDEV_H_INCLUDED */
Index: sys/dev/random/randomdev.c
===================================================================
--- sys/dev/random/randomdev.c
+++ sys/dev/random/randomdev.c
@@ -27,27 +27,13 @@
*/
/*
- * NOTE NOTE NOTE
- *
- * This file is compiled into the kernel unconditionally. Any random(4)
- * infrastructure that needs to be in the kernel by default goes here!
- *
- * Except ...
- *
- * The adaptor code all goes into random_adaptor.c, which is also compiled
- * the kernel by default. The module in that file is initialised before
- * this one.
- *
- * Other modules must be initialised after the above two, and are
- * software random processors which plug into random_adaptor.c.
- *
+ * The adaptor code all goes into random_adaptor.c. The module in
+ * that file is initialised before this one.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include "opt_random.h"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
@@ -66,11 +52,15 @@
#include <sys/uio.h>
#include <sys/unistd.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>
-#define RANDOM_MINOR 0
+#define RANDOM_MINOR 0
static d_ioctl_t randomdev_ioctl;
@@ -112,21 +102,6 @@
return (error);
}
-/* 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
-randomdev_set_wakeup_exit(void *control)
-{
-
- wakeup(control);
- kproc_exit(0);
- /* NOTREACHED */
-}
-
/* ARGSUSED */
static int
randomdev_modevent(module_t mod __unused, int type, void *data __unused)
@@ -135,7 +110,7 @@
switch (type) {
case MOD_LOAD:
- printf("random: entropy device infrastructure driver\n");
+ printf("random: entropy device fixed infrastructure\n");
random_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &random_cdevsw,
RANDOM_MINOR, NULL, UID_ROOT, GID_WHEEL, 0644, "random");
make_dev_alias(random_dev, "urandom"); /* compatibility */
@@ -159,7 +134,7 @@
return (error);
}
-DEV_MODULE_ORDERED(randomdev, randomdev_modevent, NULL, SI_ORDER_SECOND);
+DEV_MODULE(randomdev, randomdev_modevent, NULL);
MODULE_VERSION(randomdev, 1);
/* ================
@@ -214,7 +189,7 @@
*/
/* Hold the address of the routine which is actually called */
-static void (*read_func)(uint8_t *, u_int) = dummy_random_read_phony;
+static void (*read_func)(uint8_t *, u_int);
/* Initialise the reader when/if it is loaded */
void
@@ -229,7 +204,7 @@
randomdev_deinit_reader(void)
{
- read_func = dummy_random_read_phony;
+ read_func = NULL;
}
/* Kernel API version of read_random().
@@ -239,11 +214,13 @@
int
read_random(void *buf, int count)
{
+ uint8_t local_buf[count + RANDOM_BLOCKSIZE];
- if (count < 0)
+ if (count <= 0 || read_func == NULL)
return 0;
- read_func(buf, count);
+ read_func(local_buf, count);
+ memcpy(buf, local_buf, count);
return count;
}
Index: sys/dev/random/randomdev_soft.h
===================================================================
--- sys/dev/random/randomdev_soft.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*-
- * 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
- * specific to the entropy processor
- */
-
-void randomdev_init(void);
-void randomdev_deinit(void);
-
-#endif
Index: sys/dev/random/randomdev_soft.c
===================================================================
--- sys/dev/random/randomdev_soft.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*-
- * Copyright (c) 2000-2014 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.
- *
- */
-
-/*
- * This is the loadable infrastructure base file for software CSPRNG
- * drivers such as Yarrow or Fortuna.
- *
- * It is anticipated that one instance of this file will be used
- * for _each_ invocation of a CSPRNG, but with different #defines
- * set. See below.
- *
- */
-
-#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
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.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/sysctl.h>
-#include <sys/unistd.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 struct random_adaptor random_soft_processor = {
-#if defined(RANDOM_YARROW)
-#define RANDOM_CSPRNG_NAME "yarrow"
- .ra_ident = "Yarrow",
- .ra_priority = 90, /* High priority, so top of the list. Fortuna may still win. */
- .ra_read = random_yarrow_read,
- .ra_write = random_yarrow_write,
- .ra_reseed = random_yarrow_reseed,
- .ra_seeded = random_yarrow_seeded,
-#endif
-#if defined(RANDOM_FORTUNA)
-#define RANDOM_CSPRNG_NAME "fortuna"
- .ra_ident = "Fortuna",
- .ra_priority = 100, /* High priority, so top of the list. Beat Yarrow. */
- .ra_read = random_fortuna_read,
- .ra_write = random_fortuna_write,
- .ra_reseed = random_fortuna_reseed,
- .ra_seeded = random_fortuna_seeded,
-#endif
- .ra_init = randomdev_init,
- .ra_deinit = randomdev_deinit,
-};
-
-void
-randomdev_init(void)
-{
-
-#if defined(RANDOM_YARROW)
- random_yarrow_init_alg();
- random_harvestq_init(random_yarrow_process_event, 2);
-#endif
-#if defined(RANDOM_FORTUNA)
- random_fortuna_init_alg();
- random_harvestq_init(random_fortuna_process_event, 32);
-#endif
-
- /* Register the randomness harvesting routine */
- randomdev_init_harvester(random_harvestq_internal);
-}
-
-void
-randomdev_deinit(void)
-{
- /* Deregister the randomness harvesting routine */
- randomdev_deinit_harvester();
-
-#if defined(RANDOM_YARROW)
- random_yarrow_deinit_alg();
-#endif
-#if defined(RANDOM_FORTUNA)
- random_fortuna_deinit_alg();
-#endif
-}
-
-/* ARGSUSED */
-static int
-randomdev_soft_modevent(module_t mod __unused, int type, void *unused __unused)
-{
- int error = 0;
-
- switch (type) {
- case MOD_LOAD:
- printf("random: SOFT: %s init()\n", RANDOM_CSPRNG_NAME);
- random_adaptor_register(RANDOM_CSPRNG_NAME, &random_soft_processor);
- break;
-
- case MOD_UNLOAD:
- random_adaptor_deregister(RANDOM_CSPRNG_NAME);
- break;
-
- case MOD_SHUTDOWN:
- break;
-
- default:
- error = EOPNOTSUPP;
- break;
-
- }
- return (error);
-}
-
-#if defined(RANDOM_YARROW)
-DEV_MODULE(yarrow, randomdev_soft_modevent, NULL);
-MODULE_VERSION(yarrow, 1);
-MODULE_DEPEND(yarrow, randomdev, 1, 1, 1);
-#endif
-#if defined(RANDOM_FORTUNA)
-DEV_MODULE(fortuna, randomdev_soft_modevent, NULL);
-MODULE_VERSION(fortuna, 1);
-MODULE_DEPEND(fortuna, randomdev, 1, 1, 1);
-#endif
Index: sys/dev/random/uint128.h
===================================================================
--- sys/dev/random/uint128.h
+++ sys/dev/random/uint128.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2014 Mark R V Murray
+ * Copyright (c) 2015 Mark R V Murray
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,7 @@
*/
#ifndef SYS_DEV_RANDOM_UINT128_H_INCLUDED
-#define SYS_DEV_RANDOM_UINT128_H_INCLUDED
+#define SYS_DEV_RANDOM_UINT128_H_INCLUDED
/* This whole thing is a crock :-(
*
@@ -35,40 +35,41 @@
*/
#ifdef __SIZEOF_INT128__
-typedef __uint128_t uint128_t;
-#else
-typedef uint64_t uint128_t[2];
+#define USE_REAL_UINT128_T
#endif
-static __inline void
-uint128_clear(uint128_t *big_uint)
-{
-#ifdef __SIZEOF_INT128__
- (*big_uint) = 0ULL;
+#ifdef USE_REAL_UINT128_T
+typedef __uint128_t uint128_t;
+#define UINT128_ZERO 0ULL
#else
- (*big_uint)[0] = (*big_uint)[1] = 0UL;
+typedef struct {
+ /* Ignore endianness */
+ uint64_t u128t_word0;
+ uint64_t u128t_word1;
+} uint128_t;
+static const uint128_t very_long_zero = {0UL,0UL};
+#define UINT128_ZERO very_long_zero
#endif
-}
static __inline void
-uint128_increment(uint128_t *big_uint)
+uint128_increment(uint128_t *big_uintp)
{
-#ifdef __SIZEOF_INT128__
- (*big_uint)++;
+#ifdef USE_REAL_UINT128_T
+ (*big_uintp)++;
#else
- (*big_uint)[0]++;
- if ((*big_uint)[0] == 0UL)
- (*big_uint)[1]++;
+ big_uintp->word0++;
+ if (big_uintp->u128t_word0 == 0UL)
+ big_uintp->u128t_word1++;
#endif
}
static __inline int
uint128_is_zero(uint128_t big_uint)
{
-#ifdef __SIZEOF_INT128__
- return (big_uint == 0ULL);
+#ifdef USE_REAL_UINT128_T
+ return (big_uint == UINT128_ZERO);
#else
- return (big_uint[0] == 0UL && big_uint[1] == 0UL);
+ return (big_uint.u128t_word0 == 0UL && big_uint.u128t_word1 == 0UL);
#endif
}
Index: sys/dev/random/unit_test.h
===================================================================
--- sys/dev/random/unit_test.h
+++ sys/dev/random/unit_test.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2013 Mark R V Murray
+ * Copyright (c) 2013-2015 Mark R V Murray
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,20 +28,40 @@
#ifndef UNIT_TEST_H_INCLUDED
-#define UNIT_TEST_H_INCLUDED
+#define UNIT_TEST_H_INCLUDED
+
+#ifdef _KERNEL
+#error "Random unit tests cannot be compiled into the kernel."
+#endif
void random_adaptor_unblock(void);
+#if defined(clang) && __has_builtin(__builtin_readcyclecounter)
+#define rdtsc __builtin_readcyclecounter
+#else /* !clang */
+#if defined(__amd64__) || defined(__i386__)
+static __inline uint64_t
+rdtsc(void)
+{
+ uint32_t low, high;
+
+ __asm __volatile("rdtsc" : "=a" (low), "=d" (high));
+ return (low | ((uint64_t)high << 32));
+}
+#else /* __amd64__ || __i386__ */
+#error "No rdtsc() implementation available."
+#endif /* __amd64__ || __i386__ */
+#endif /* !clang */
+
static __inline uint64_t
get_cyclecount(void)
{
- /* Shaddup! */
- return (4ULL);
+ return (rdtsc());
}
-// #define PAGE_SIZE 4096
-#define HARVESTSIZE 16
+// #define PAGE_SIZE 4096
+#define HARVESTSIZE 4
enum random_entropy_source {
RANDOM_START = 0,
@@ -51,7 +71,7 @@
struct harvest_event {
uintmax_t he_somecounter; /* fast counter for clock jitter */
- uint8_t he_entropy[HARVESTSIZE];/* some harvested entropy */
+ uint32_t he_entropy[HARVESTSIZE];/* some harvested entropy */
u_int he_size; /* harvested entropy byte count */
u_int he_bits; /* stats about the entropy */
u_int he_destination; /* destination pool of this entropy */
Index: sys/dev/random/unit_test.c
===================================================================
--- sys/dev/random/unit_test.c
+++ sys/dev/random/unit_test.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000-2013 Mark R V Murray
+ * Copyright (c) 2000-2015 Mark R V Murray
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,6 +37,7 @@
../../crypto/rijndael/rijndael-api-fst.c \
../../crypto/rijndael/rijndael-alg-fst.c \
../../crypto/sha2/sha2.c \
+ -lz \
-o unit_test
./unit_test
@@ -49,6 +50,7 @@
#include <stdlib.h>
#include <threads.h>
#include <unistd.h>
+#include <zlib.h>
#include "unit_test.h"
@@ -59,10 +61,77 @@
#include "dev/random/fortuna.h"
#endif
-#define NUM_THREADS 3
+#define NUM_THREADS 3
+#define DEBUG
static volatile int stopseeding = 0;
+static __inline void
+check_err(int err, const char *func)
+{
+ if (err != Z_OK) {
+ fprintf(stderr, "Compress error in %s: %d\n", func, err);
+ exit(0);
+ }
+}
+
+void *
+myalloc(void *q, unsigned n, unsigned m)
+{
+ q = Z_NULL;
+ return (calloc(n, m));
+}
+
+void myfree(void *q, void *p)
+{
+ q = Z_NULL;
+ free(p);
+}
+
+size_t
+block_deflate(uint8_t *uncompr, uint8_t *compr, const size_t len)
+{
+ z_stream c_stream;
+ int err;
+
+ if (len == 0U)
+ return (0U);
+
+ c_stream.zalloc = myalloc;
+ c_stream.zfree = myfree;
+ c_stream.opaque = NULL;
+
+ err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+ check_err(err, "deflateInit");
+
+ c_stream.next_in = uncompr;
+ c_stream.next_out = compr;
+ c_stream.avail_in = len;
+ c_stream.avail_out = len*2u +512u;
+
+ while (c_stream.total_in != len && c_stream.total_out < (len*2u + 512u)) {
+ err = deflate(&c_stream, Z_NO_FLUSH);
+#ifdef DEBUG
+ printf("deflate: len = %zd total_in = %lu total_out = %lu\n", len, c_stream.total_in, c_stream.total_out);
+#endif
+ check_err(err, "deflate(..., Z_NO_FLUSH)");
+ }
+
+ for (;;) {
+ err = deflate(&c_stream, Z_FINISH);
+#ifdef DEBUG
+ printf("deflate: len = %zd total_in = %lu total_out = %lu\n", len, c_stream.total_in, c_stream.total_out);
+#endif
+ if (err == Z_STREAM_END) break;
+ check_err(err, "deflate(..., Z_STREAM_END)");
+ }
+
+ err = deflateEnd(&c_stream);
+ check_err(err, "deflateEnd");
+
+ return ((size_t)c_stream.total_out);
+}
+
void
random_adaptor_unblock(void)
{
@@ -128,6 +197,7 @@
if (i % 1000 == 0)
printf("Thread write 1 - %d\n", i);
if (buf != NULL) {
+ printf("Thread 1 writing.\n");
#ifdef RANDOM_YARROW
random_yarrow_write(buf, i);
#endif
@@ -149,9 +219,12 @@
static int
ReadCSPRNG(void *threadid)
{
- size_t tid;
- uint8_t *buf;
+ size_t tid, zsize;
+ uint8_t *buf, *zbuf;
int i;
+#ifdef DEBUG
+ int j;
+#endif
tid = (size_t)threadid;
printf("Thread #%zd starts\n", tid);
@@ -164,42 +237,50 @@
#endif
{
#ifdef RANDOM_YARROW
- random_yarrow_read(NULL, 0);
- random_yarrow_read(NULL, 1);
+ random_yarrow_pre_read();
+ random_yarrow_post_read();
#endif
#ifdef RANDOM_FORTUNA
- random_fortuna_read(NULL, 0);
- random_fortuna_read(NULL, 1);
+ random_fortuna_pre_read();
+ random_fortuna_post_read();
#endif
usleep(100);
}
for (i = 0; i < 100000; i++) {
buf = malloc(i);
+ zbuf = malloc(2*i + 1024);
if (i % 1000 == 0)
- printf("Thread read %zd - %d %p\n", tid, i, buf);
- if (buf != NULL) {
+ printf("Thread read %zd - %d\n", tid, i);
+ if (buf != NULL && zbuf != NULL) {
#ifdef RANDOM_YARROW
- random_yarrow_read(NULL, 0);
+ random_yarrow_pre_read();
random_yarrow_read(buf, i);
- random_yarrow_read(NULL, 1);
+ random_yarrow_post_read();
#endif
#ifdef RANDOM_FORTUNA
- random_fortuna_read(NULL, 0);
+ random_fortuna_pre_read();
random_fortuna_read(buf, i);
- random_fortuna_read(NULL, 1);
+ random_fortuna_post_read();
#endif
-#if 0
- {
- int j;
-
+ zsize = block_deflate(buf, zbuf, i);
+ if (zsize < i)
+ printf("ERROR!! Compressible RNG output!\n");
+#ifdef DEBUG
+ printf("RNG output:\n");
for (j = 0; j < i; j++) {
printf(" %02X", buf[j]);
if (j % 32 == 31 || j == i - 1)
printf("\n");
}
+ printf("Compressed output:\n");
+ for (j = 0; j < zsize; j++) {
+ printf(" %02X", zbuf[j]);
+ if (j % 32 == 31 || j == zsize - 1)
+ printf("\n");
}
#endif
+ free(zbuf);
free(buf);
}
usleep(100);
@@ -228,7 +309,7 @@
for (t = 0; t < NUM_THREADS; t++) {
printf("In main: creating thread %ld\n", t);
- rc = thrd_create(&threads[t], (t == 0 ? RunHarvester : (t == 1 ? WriteCSPRNG : ReadCSPRNG)), t);
+ rc = thrd_create(&threads[t], (t == 0 ? RunHarvester : (t == 1 ? WriteCSPRNG : ReadCSPRNG)), NULL);
if (rc != thrd_success) {
printf("ERROR; return code from thrd_create() is %d\n", rc);
exit(-1);
Index: sys/dev/random/yarrow.h
===================================================================
--- sys/dev/random/yarrow.h
+++ sys/dev/random/yarrow.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000-2013 Mark R V Murray
+ * Copyright (c) 2000-2015 Mark R V Murray
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,18 +27,31 @@
*/
#ifndef SYS_DEV_RANDOM_YARROW_H_INCLUDED
-#define SYS_DEV_RANDOM_YARROW_H_INCLUDED
+#define SYS_DEV_RANDOM_YARROW_H_INCLUDED
#ifdef _KERNEL
typedef struct mtx mtx_t;
+#define RANDOM_RESEED_INIT_LOCK(x) mtx_init(&random_yarrow_reseed_mtx, "reseed mutex", NULL, MTX_DEF)
+#define RANDOM_RESEED_DEINIT_LOCK(x) mtx_destroy(&random_yarrow_reseed_mtx)
+#define RANDOM_RESEED_LOCK(x) mtx_lock(&random_yarrow_reseed_mtx)
+#define RANDOM_RESEED_UNLOCK(x) mtx_unlock(&random_yarrow_reseed_mtx)
+#define RANDOM_RESEED_ASSERT_LOCK_OWNED(x) mtx_assert(&random_yarrow_reseed_mtx, MA_OWNED)
+#else
+#define RANDOM_RESEED_INIT_LOCK(x) mtx_init(&random_yarrow_reseed_mtx, mtx_plain)
+#define RANDOM_RESEED_DEINIT_LOCK(x) mtx_destroy(&random_yarrow_reseed_mtx)
+#define RANDOM_RESEED_LOCK(x) mtx_lock(&random_yarrow_reseed_mtx)
+#define RANDOM_RESEED_UNLOCK(x) mtx_unlock(&random_yarrow_reseed_mtx)
+#define RANDOM_RESEED_ASSERT_LOCK_OWNED(x)
#endif
void random_yarrow_init_alg(void);
void random_yarrow_deinit_alg(void);
+void random_yarrow_pre_read(void);
void random_yarrow_read(uint8_t *, u_int);
+void random_yarrow_post_read(void);
void random_yarrow_write(uint8_t *, u_int);
void random_yarrow_reseed(void);
int random_yarrow_seeded(void);
-void random_yarrow_process_event(struct harvest_event *event);
+void random_yarrow_process_event(struct harvest_event *);
-#endif
+#endif /* SYS_DEV_RANDOM_YARROW_H_INCLUDED */
Index: sys/dev/random/yarrow.c
===================================================================
--- sys/dev/random/yarrow.c
+++ sys/dev/random/yarrow.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000-2013 Mark R V Murray
+ * Copyright (c) 2000-2015 Mark R V Murray
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,12 +29,12 @@
__FBSDID("$FreeBSD$");
#ifdef _KERNEL
-#include "opt_random.h"
-
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/conf.h>
#include <sys/lock.h>
#include <sys/malloc.h>
+#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/random.h>
#include <sys/sysctl.h>
@@ -71,68 +71,47 @@
#include <dev/random/yarrow.h>
#endif /* _KERNEL */
-#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_YARROW)
+#define TIMEBIN 16 /* max value for Pt/t */
-#define TIMEBIN 16 /* max value for Pt/t */
+#define RANDOM_YARROW_FAST 0
+#define RANDOM_YARROW_SLOW 1
+#define RANDOM_YARROW_NPOOLS 2
-#define FAST 0
-#define SLOW 1
+/* This algorithm (and code) presumes that RANDOM_KEYSIZE is twice as large as RANDOM_BLOCKSIZE */
+CTASSERT(RANDOM_BLOCKSIZE == sizeof(uint128_t));
+CTASSERT(RANDOM_KEYSIZE == 2*RANDOM_BLOCKSIZE);
-/* 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.
+/*
+ * This is the beastie that needs protecting. It contains all of the
+ * state that we are excited about. Exactly one is instantiated.
*/
static struct yarrow_state {
- union {
- uint8_t byte[BLOCKSIZE];
- uint128_t whole;
- } 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];/* ... per source */
- u_int thresh; /* pool reseed threshhold */
- struct randomdev_hash hash; /* accumulated entropy */
- } pool[2]; /* pool[0] is fast, pool[1] is slow */
- int seeded;
-
- struct start_cache {
- uint8_t junk[KEYSIZE];
- struct randomdev_hash hash;
- } start_cache;
+ uint128_t ys_counter; /* C */
+ struct randomdev_key ys_key; /* K */
+ u_int ys_gengateinterval; /* Pg */
+ u_int ys_bins; /* Pt/t */
+ u_int ys_outputblocks; /* count output blocks for gates */
+ u_int ys_slowoverthresh; /* slow pool overthreshhold reseed count */
+ struct ys_pool {
+ u_int ysp_source_bits[ENTROPYSOURCE]; /* estimated bits of entropy per source */
+ u_int ysp_thresh; /* pool reseed threshhold */
+ struct randomdev_hash ysp_hash; /* accumulated entropy */
+ } ys_pool[RANDOM_YARROW_NPOOLS];/* pool[0] is fast, pool[1] is slow */
+ int ys_seeded;
} yarrow_state;
-/* The random_reseed_mtx mutex protects seeding and polling/blocking. */
-static mtx_t random_reseed_mtx;
+static mtx_t random_yarrow_reseed_mtx;
#ifdef _KERNEL
static struct sysctl_ctx_list random_clist;
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(bins, RANDOM_YARROW_NPOOLS, 16);
+RANDOM_CHECK_UINT(fastthresh, (RANDOM_BLOCKSIZE*8)/4, (RANDOM_BLOCKSIZE*8)); /* Bit counts */
+RANDOM_CHECK_UINT(slowthresh, (RANDOM_BLOCKSIZE*8)/4, (RANDOM_BLOCKSIZE*8)); /* Bit counts */
RANDOM_CHECK_UINT(slowoverthresh, 1, 5);
-#else /* !_KERNEL */
-static u_int harvest_destination[ENTROPYSOURCE];
#endif /* _KERNEL */
-static void generator_gate(void);
-static void reseed(u_int);
+static void random_yarrow_reseed_internal(u_int);
void
random_yarrow_init_alg(void)
@@ -142,21 +121,14 @@
struct sysctl_oid *random_yarrow_o;
#endif /* _KERNEL */
- memset(yarrow_state.start_cache.junk, 0, KEYSIZE);
- randomdev_hash_init(&yarrow_state.start_cache.hash);
-
- /* Set up the lock for the reseed/gate state */
-#ifdef _KERNEL
- mtx_init(&random_reseed_mtx, "reseed mutex", NULL, MTX_DEF);
-#else /* !_KERNEL */
- mtx_init(&random_reseed_mtx, mtx_plain);
-#endif /* _KERNEL */
+ RANDOM_RESEED_INIT_LOCK();
/* Start unseeded, therefore blocked. */
- yarrow_state.seeded = 0;
+ yarrow_state.ys_seeded = 0;
#ifdef _KERNEL
- /* Yarrow parameters. Do not adjust these unless you have
+ /*
+ * Yarrow parameters. Do not adjust these unless you have
* have a very good clue about what they do!
*/
random_yarrow_o = SYSCTL_ADD_NODE(&random_clist,
@@ -167,65 +139,66 @@
SYSCTL_ADD_PROC(&random_clist,
SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO,
"gengateinterval", CTLTYPE_INT|CTLFLAG_RW,
- &yarrow_state.gengateinterval, 10,
+ &yarrow_state.ys_gengateinterval, 10,
random_check_uint_gengateinterval, "I",
"Generation gate interval");
SYSCTL_ADD_PROC(&random_clist,
SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO,
"bins", CTLTYPE_INT|CTLFLAG_RW,
- &yarrow_state.bins, 10,
+ &yarrow_state.ys_bins, 10,
random_check_uint_bins, "I",
"Execution time tuner");
SYSCTL_ADD_PROC(&random_clist,
SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO,
"fastthresh", CTLTYPE_INT|CTLFLAG_RW,
- &yarrow_state.pool[0].thresh, (3*(BLOCKSIZE*8))/4,
+ &yarrow_state.ys_pool[0].ysp_thresh, (3*(RANDOM_BLOCKSIZE*8))/4,
random_check_uint_fastthresh, "I",
"Fast reseed threshold");
SYSCTL_ADD_PROC(&random_clist,
SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO,
"slowthresh", CTLTYPE_INT|CTLFLAG_RW,
- &yarrow_state.pool[1].thresh, (BLOCKSIZE*8),
+ &yarrow_state.ys_pool[1].ysp_thresh, (RANDOM_BLOCKSIZE*8),
random_check_uint_slowthresh, "I",
"Slow reseed threshold");
SYSCTL_ADD_PROC(&random_clist,
SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO,
"slowoverthresh", CTLTYPE_INT|CTLFLAG_RW,
- &yarrow_state.slowoverthresh, 2,
+ &yarrow_state.ys_slowoverthresh, 2,
random_check_uint_slowoverthresh, "I",
"Slow over-threshold reseed");
#endif /* _KERNEL */
- yarrow_state.gengateinterval = 10;
- yarrow_state.bins = 10;
- yarrow_state.pool[FAST].thresh = (3*(BLOCKSIZE*8))/4;
- yarrow_state.pool[SLOW].thresh = (BLOCKSIZE*8);
- yarrow_state.slowoverthresh = 2;
+ yarrow_state.ys_gengateinterval = 10;
+ yarrow_state.ys_bins = 10;
+ yarrow_state.ys_pool[RANDOM_YARROW_FAST].ysp_thresh = (3*(RANDOM_BLOCKSIZE*8))/4;
+ yarrow_state.ys_pool[RANDOM_YARROW_SLOW].ysp_thresh = (RANDOM_BLOCKSIZE*8);
+ yarrow_state.ys_slowoverthresh = 2;
/* Ensure that the first time we read, we are gated. */
- yarrow_state.outputblocks = yarrow_state.gengateinterval;
+ yarrow_state.ys_outputblocks = yarrow_state.ys_gengateinterval;
/* Initialise the fast and slow entropy pools */
- for (i = FAST; i <= SLOW; i++) {
- randomdev_hash_init(&yarrow_state.pool[i].hash);
+ for (i = RANDOM_YARROW_FAST; i <= RANDOM_YARROW_SLOW; i++) {
+ randomdev_hash_init(&yarrow_state.ys_pool[i].ysp_hash);
for (j = RANDOM_START; j < ENTROPYSOURCE; j++)
- yarrow_state.pool[i].source[j].bits = 0U;
+ yarrow_state.ys_pool[i].ysp_source_bits[j] = 0U;
}
/* Clear the counter */
- uint128_clear(&yarrow_state.counter.whole);
+ yarrow_state.ys_counter = UINT128_ZERO;
}
void
random_yarrow_deinit_alg(void)
{
- mtx_destroy(&random_reseed_mtx);
- memset(&yarrow_state, 0, sizeof(yarrow_state));
+ RANDOM_RESEED_DEINIT_LOCK();
+
+ bzero(&yarrow_state, sizeof(yarrow_state));
#ifdef _KERNEL
sysctl_ctx_free(&random_clist);
@@ -235,28 +208,28 @@
static __inline void
random_yarrow_post_insert(void)
{
- u_int pl, overthreshhold[2];
+ u_int pl, overthreshhold[RANDOM_YARROW_NPOOLS];
enum random_entropy_source src;
-#ifdef _KERNEL
- mtx_assert(&random_reseed_mtx, MA_OWNED);
-#endif
+ RANDOM_RESEED_ASSERT_LOCK_OWNED();
+
/* Count the over-threshold sources in each pool */
- for (pl = 0; pl < 2; pl++) {
+ for (pl = RANDOM_YARROW_FAST; pl <= RANDOM_YARROW_SLOW; pl++) {
overthreshhold[pl] = 0;
for (src = RANDOM_START; src < ENTROPYSOURCE; src++) {
- if (yarrow_state.pool[pl].source[src].bits > yarrow_state.pool[pl].thresh)
+ if (yarrow_state.ys_pool[pl].ysp_source_bits[src] > yarrow_state.ys_pool[pl].ysp_thresh)
overthreshhold[pl]++;
}
}
- /* If enough slow sources are over threshhold, then slow reseed
+ /*
+ * If enough slow sources are over threshhold, then slow reseed
* else if any fast source over threshhold, then fast reseed.
*/
- if (overthreshhold[SLOW] >= yarrow_state.slowoverthresh)
- reseed(SLOW);
- else if (overthreshhold[FAST] > 0 && yarrow_state.seeded)
- reseed(FAST);
+ if (overthreshhold[RANDOM_YARROW_SLOW] >= yarrow_state.ys_slowoverthresh)
+ random_yarrow_reseed_internal(RANDOM_YARROW_SLOW);
+ else if (overthreshhold[RANDOM_YARROW_FAST] > 0 && yarrow_state.ys_seeded)
+ random_yarrow_reseed_internal(RANDOM_YARROW_FAST);
}
/* Process a single stochastic event off the harvest queue */
@@ -265,153 +238,155 @@
{
u_int pl;
- mtx_lock(&random_reseed_mtx);
+ RANDOM_RESEED_LOCK();
- /* Accumulate the event into the appropriate pool
+ /*
+ * Accumulate the event into the appropriate pool
* where each event carries the destination information.
* We lock against pool state modification which can happen
* during accumulation/reseeding and reading/regating
*/
- pl = event->he_destination % 2;
- randomdev_hash_iterate(&yarrow_state.pool[pl].hash, event, sizeof(*event));
- yarrow_state.pool[pl].source[event->he_source].bits += event->he_bits;
+ pl = event->he_destination % RANDOM_YARROW_NPOOLS;
+ randomdev_hash_iterate(&yarrow_state.ys_pool[pl].ysp_hash, event, sizeof(*event));
+ yarrow_state.ys_pool[pl].ysp_source_bits[event->he_source] += event->he_bits;
random_yarrow_post_insert();
- mtx_unlock(&random_reseed_mtx);
+ RANDOM_RESEED_UNLOCK();
}
-/* Process a block of data suspected to be slightly stochastic */
+/*
+ * Process a block of data suspected to be slightly stochastic.
+ * The length is RANDOM_KEYSIZE bytes, but data is passed in words.
+ */
static void
-random_yarrow_process_buffer(uint8_t *buf, u_int length)
+random_yarrow_process_buffer(uint32_t *buf)
{
static struct harvest_event event;
u_int i, pl;
+ static u_int dest = 0;
- /* Accumulate the data into the appropriate pools
+ /*
+ * Accumulate the data into the appropriate pools
* where each event carries the destination information.
- * We lock against pool state modification which can happen
- * during accumulation/reseeding and reading/regating
*/
- memset(event.he_entropy + sizeof(uint32_t), 0, HARVESTSIZE - sizeof(uint32_t));
- for (i = 0; i < length/sizeof(uint32_t); i++) {
+
+ RANDOM_RESEED_LOCK();
+
+ bzero(event.he_entropy, sizeof(event.he_entropy));
+ for (i = 0; i < RANDOM_KEYSIZE_WORDS; i++) {
event.he_somecounter = get_cyclecount();
event.he_bits = 0; /* Fake */
event.he_source = RANDOM_CACHED;
- event.he_destination = harvest_destination[RANDOM_CACHED]++;
+ event.he_destination = dest++; /* Harmless cheating */
event.he_size = sizeof(uint32_t);
- *((uint32_t *)event.he_entropy) = *((uint32_t *)buf + i);
-
+ event.he_entropy[0] = buf[i];
/* Do the actual entropy insertion */
- pl = event.he_destination % 2;
- randomdev_hash_iterate(&yarrow_state.pool[pl].hash, &event, sizeof(event));
-#ifdef DONT_DO_THIS_HERE
- /* Don't do this here - do it in bulk at the end */
- yarrow_state.pool[pl].source[RANDOM_CACHED].bits += bits;
-#endif
+ pl = event.he_destination % RANDOM_YARROW_NPOOLS;
+ randomdev_hash_iterate(&yarrow_state.ys_pool[pl].ysp_hash, &event, sizeof(event));
}
- for (pl = FAST; pl <= SLOW; pl++)
- yarrow_state.pool[pl].source[RANDOM_CACHED].bits += (length >> 4);
+ /* The entropy is estimated as the buffer length divided by 16. This is very conservative. */
+ for (pl = RANDOM_YARROW_FAST; pl <= RANDOM_YARROW_SLOW; pl++)
+ yarrow_state.ys_pool[pl].ysp_source_bits[RANDOM_CACHED] += (RANDOM_KEYSIZE >> 4);
random_yarrow_post_insert();
+
+ RANDOM_RESEED_UNLOCK();
}
static void
-reseed(u_int fastslow)
+random_yarrow_reseed_internal(u_int fastslow)
{
- /* Interrupt-context stack is a limited resource; make large
+ /*
+ * Interrupt-context stack is a limited resource; make large
* structures static.
*/
- static uint8_t v[TIMEBIN][KEYSIZE]; /* v[i] */
- static uint8_t hash[KEYSIZE]; /* h' */
- static uint8_t temp[KEYSIZE];
+ static uint8_t v[TIMEBIN][RANDOM_KEYSIZE]; /* v[i] */
+ static uint128_t temp;
static struct randomdev_hash context;
u_int i;
enum random_entropy_source j;
- KASSERT(yarrow_state.pool[FAST].thresh > 0, ("random: Yarrow fast threshold = 0"));
- KASSERT(yarrow_state.pool[SLOW].thresh > 0, ("random: Yarrow slow threshold = 0"));
+ KASSERT(yarrow_state.ys_pool[RANDOM_YARROW_FAST].ysp_thresh > 0, ("random: Yarrow fast threshold = 0"));
+ KASSERT(yarrow_state.ys_pool[RANDOM_YARROW_SLOW].ysp_thresh > 0, ("random: Yarrow slow threshold = 0"));
+ RANDOM_RESEED_ASSERT_LOCK_OWNED();
#ifdef RANDOM_DEBUG
-#ifdef RANDOM_DEBUG_VERBOSE
- printf("random: %s %s\n", __func__, (fastslow == FAST ? "FAST" : "SLOW"));
-#endif
- if (!yarrow_state.seeded) {
- printf("random: %s - fast - thresh %d,1 - ", __func__, yarrow_state.pool[FAST].thresh);
- for (i = RANDOM_START; i < ENTROPYSOURCE; i++)
- printf(" %d", yarrow_state.pool[FAST].source[i].bits);
- printf("\n");
- printf("random: %s - slow - thresh %d,%d - ", __func__, yarrow_state.pool[SLOW].thresh, yarrow_state.slowoverthresh);
- for (i = RANDOM_START; i < ENTROPYSOURCE; i++)
- printf(" %d", yarrow_state.pool[SLOW].source[i].bits);
- printf("\n");
- }
-#endif
-#ifdef _KERNEL
- mtx_assert(&random_reseed_mtx, MA_OWNED);
+ /* WARNING! This is dangerously tedious to do with mutexes held! */
+ printf("random: %s %s seeded = %d\n", __func__, (fastslow == RANDOM_YARROW_FAST ? "RANDOM_YARROW_FAST" : "RANDOM_YARROW_SLOW"), yarrow_state.ys_seeded);
+ printf("random: %s - fast - thresh %d,1 - ", __func__, yarrow_state.ys_pool[RANDOM_YARROW_FAST].ysp_thresh);
+ for (i = RANDOM_START; i < ENTROPYSOURCE; i++)
+ printf(" %d", yarrow_state.ys_pool[RANDOM_YARROW_FAST].ysp_source_bits[i]);
+ printf("\n");
+ printf("random: %s - slow - thresh %d,%d - ", __func__, yarrow_state.ys_pool[RANDOM_YARROW_SLOW].ysp_thresh, yarrow_state.ys_slowoverthresh);
+ for (i = RANDOM_START; i < ENTROPYSOURCE; i++)
+ printf(" %d", yarrow_state.ys_pool[RANDOM_YARROW_SLOW].ysp_source_bits[i]);
+ printf("\n");
#endif
/* 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_finish(&yarrow_state.pool[SLOW].hash, temp);
- randomdev_hash_iterate(&context, temp, sizeof(temp));
+ if (fastslow == RANDOM_YARROW_SLOW) {
+ randomdev_hash_finish(&yarrow_state.ys_pool[RANDOM_YARROW_SLOW].ysp_hash, &temp);
+ randomdev_hash_iterate(&context, &temp, sizeof(temp));
}
- randomdev_hash_finish(&yarrow_state.pool[FAST].hash, temp);
- randomdev_hash_iterate(&context, temp, sizeof(temp));
+ randomdev_hash_finish(&yarrow_state.ys_pool[RANDOM_YARROW_FAST].ysp_hash, &temp);
+ randomdev_hash_iterate(&context, &temp, sizeof(temp));
randomdev_hash_finish(&context, v[0]);
- /* 2. Compute hash values for all v. _Supposed_ to be computationally
+ /*
+ * 2. Compute hash values for all v. _Supposed_ to be computationally
* intensive.
*/
- if (yarrow_state.bins > TIMEBIN)
- yarrow_state.bins = TIMEBIN;
- for (i = 1; i < yarrow_state.bins; i++) {
+ if (yarrow_state.ys_bins > TIMEBIN)
+ yarrow_state.ys_bins = TIMEBIN;
+ for (i = 1; i < yarrow_state.ys_bins; i++) {
randomdev_hash_init(&context);
/* v[i] #= h(v[i - 1]) */
- randomdev_hash_iterate(&context, v[i - 1], KEYSIZE);
+ randomdev_hash_iterate(&context, v[i - 1], RANDOM_KEYSIZE);
/* v[i] #= h(v[0]) */
- randomdev_hash_iterate(&context, v[0], KEYSIZE);
+ randomdev_hash_iterate(&context, v[0], RANDOM_KEYSIZE);
/* v[i] #= h(i) */
randomdev_hash_iterate(&context, &i, sizeof(i));
/* Return the hashval */
randomdev_hash_finish(&context, v[i]);
}
- /* 3. Compute a new key; h' is the identity function here;
+ /*
+ * 3. Compute a new key; h' is the identity function here;
* it is not being ignored!
*/
randomdev_hash_init(&context);
- randomdev_hash_iterate(&context, &yarrow_state.key, KEYSIZE);
- for (i = 1; i < yarrow_state.bins; i++)
- randomdev_hash_iterate(&context, v[i], KEYSIZE);
- randomdev_hash_finish(&context, temp);
- randomdev_encrypt_init(&yarrow_state.key, temp);
+ randomdev_hash_iterate(&context, &yarrow_state.ys_key, RANDOM_KEYSIZE);
+ for (i = 1; i < yarrow_state.ys_bins; i++)
+ randomdev_hash_iterate(&context, v[i], RANDOM_KEYSIZE);
+ randomdev_hash_finish(&context, &temp);
+ randomdev_encrypt_init(&yarrow_state.ys_key, &temp);
/* 4. Recompute the counter */
- uint128_clear(&yarrow_state.counter.whole);
- randomdev_encrypt(&yarrow_state.key, yarrow_state.counter.byte, temp, BLOCKSIZE);
- memcpy(yarrow_state.counter.byte, temp, BLOCKSIZE);
+ yarrow_state.ys_counter = UINT128_ZERO;
+ randomdev_encrypt(&yarrow_state.ys_key, &yarrow_state.ys_counter, &temp, RANDOM_BLOCKSIZE);
+ yarrow_state.ys_counter = temp;
/* 5. Reset entropy estimate accumulators to zero */
for (i = 0; i <= fastslow; i++)
for (j = RANDOM_START; j < ENTROPYSOURCE; j++)
- yarrow_state.pool[i].source[j].bits = 0;
+ yarrow_state.ys_pool[i].ysp_source_bits[j] = 0;
/* 6. Wipe memory of intermediate values */
- memset(v, 0, sizeof(v));
- memset(temp, 0, sizeof(temp));
- memset(hash, 0, sizeof(hash));
- memset(&context, 0, sizeof(context));
+ bzero(v, sizeof(v));
+ bzero(&temp, sizeof(temp));
+ bzero(&context, sizeof(context));
-#ifdef RANDOM_RWFILE_WRITE_IS_OK /* Not defined so writes ain't gonna happen */
+/* Not defined so writes ain't gonna happen. Kept for documenting. */
+#ifdef RANDOM_RWFILE_WRITE_IS_OK
/* 7. Dump to seed file */
/* This pseudo-code is documentation. Please leave it alone. */
@@ -422,111 +397,181 @@
#endif
/* Unblock the device if it was blocked due to being unseeded */
- if (!yarrow_state.seeded) {
- yarrow_state.seeded = 1;
+ if (!yarrow_state.ys_seeded) {
+ yarrow_state.ys_seeded = 1;
random_adaptor_unblock();
}
}
-/* Internal function to return processed entropy from the PRNG */
+static __inline void
+random_yarrow_generator_gate(void)
+{
+ u_int i;
+ uint8_t temp[RANDOM_KEYSIZE];
+
+ RANDOM_RESEED_ASSERT_LOCK_OWNED();
+
+ uint128_increment(&yarrow_state.ys_counter);
+ for (i = 0; i < RANDOM_KEYSIZE; i += RANDOM_BLOCKSIZE)
+ randomdev_encrypt(&yarrow_state.ys_key, &yarrow_state.ys_counter, temp + i, RANDOM_BLOCKSIZE);
+
+ randomdev_encrypt_init(&yarrow_state.ys_key, temp);
+ bzero(temp, sizeof(temp));
+}
+
+/*
+ * Used to return processed entropy from the PRNG
+ * There is a pre_read and a post_read required to be present
+ * (but they can be null functions) in order to allow specific
+ * actions at the begin or the end of a read. Yarrow does its
+ * reseeding in its own thread. The _pre_read() and _post_read()
+ * are not used.
+ */
+void
+random_yarrow_pre_read(void)
+{
+}
+
+/*
+ * Main read from Yarrow.
+ * The supplied buf MUST be a multiple (>=0) of RANDOM_BLOCKSIZE in size.
+ * Lots of code presumes this for efficiency, both here and in other
+ * routines. You are NOT allowed to break this!
+ */
void
random_yarrow_read(uint8_t *buf, u_int bytecount)
{
- uint8_t tbuf[BLOCKSIZE];
u_int blockcount, i;
- /* Check for initial/final read requests */
- if (buf == NULL)
- return;
+ RANDOM_RESEED_LOCK();
- /* The reseed task must not be jumped on */
- mtx_lock(&random_reseed_mtx);
-
- blockcount = (bytecount + BLOCKSIZE - 1)/BLOCKSIZE;
+ blockcount = (bytecount + RANDOM_BLOCKSIZE - 1)/RANDOM_BLOCKSIZE;
for (i = 0; i < blockcount; i++) {
- if (yarrow_state.outputblocks++ >= yarrow_state.gengateinterval) {
- generator_gate();
- yarrow_state.outputblocks = 0;
- }
- uint128_increment(&yarrow_state.counter.whole);
- if ((i + 1) * BLOCKSIZE > bytecount) {
- /* TODO: FIX! remove memcpy()! */
- randomdev_encrypt(&yarrow_state.key,
- yarrow_state.counter.byte, tbuf, BLOCKSIZE);
- memcpy(buf, tbuf, bytecount - i * BLOCKSIZE);
- } else {
- randomdev_encrypt(&yarrow_state.key,
- yarrow_state.counter.byte, buf, BLOCKSIZE);
- buf += BLOCKSIZE;
+ if (yarrow_state.ys_outputblocks++ >= yarrow_state.ys_gengateinterval) {
+ random_yarrow_generator_gate();
+ yarrow_state.ys_outputblocks = 0;
}
+ uint128_increment(&yarrow_state.ys_counter);
+ randomdev_encrypt(&yarrow_state.ys_key, &yarrow_state.ys_counter, buf, RANDOM_BLOCKSIZE);
+ buf += RANDOM_BLOCKSIZE;
}
- mtx_unlock(&random_reseed_mtx);
+ RANDOM_RESEED_UNLOCK();
+}
+
+void
+random_yarrow_post_read(void)
+{
}
/* Internal function to hand external entropy to the PRNG */
void
random_yarrow_write(uint8_t *buf, u_int count)
{
+ struct randomdev_hash hash;
uintmax_t timestamp;
+ uint32_t random_data[RANDOM_KEYSIZE_WORDS];
- /* We must be locked for all this as plenty of state gets messed with */
- mtx_lock(&random_reseed_mtx);
-
+ /* Extra timing here is helpful to scrape scheduler timing entropy */
+ randomdev_hash_init(&hash);
timestamp = get_cyclecount();
- randomdev_hash_iterate(&yarrow_state.start_cache.hash, ×tamp, sizeof(timestamp));
- randomdev_hash_iterate(&yarrow_state.start_cache.hash, buf, count);
+ randomdev_hash_iterate(&hash, ×tamp, sizeof(timestamp));
+ randomdev_hash_iterate(&hash, buf, count);
timestamp = get_cyclecount();
- randomdev_hash_iterate(&yarrow_state.start_cache.hash, ×tamp, sizeof(timestamp));
- randomdev_hash_finish(&yarrow_state.start_cache.hash, yarrow_state.start_cache.junk);
- randomdev_hash_init(&yarrow_state.start_cache.hash);
-
-#ifdef RANDOM_DEBUG_VERBOSE
- {
- int i;
-
- printf("random: %s - ", __func__);
- for (i = 0; i < KEYSIZE; i++)
- printf("%02X", yarrow_state.start_cache.junk[i]);
- printf("\n");
- }
-#endif
+ randomdev_hash_iterate(&hash, ×tamp, sizeof(timestamp));
+ randomdev_hash_finish(&hash, random_data);
+
+ random_yarrow_process_buffer(random_data);
+ bzero(random_data, sizeof(random_data));
+}
+
+void
+random_yarrow_reseed(void)
+{
- random_yarrow_process_buffer(yarrow_state.start_cache.junk, KEYSIZE);
- memset(yarrow_state.start_cache.junk, 0, KEYSIZE);
+ RANDOM_RESEED_LOCK();
- mtx_unlock(&random_reseed_mtx);
+ random_yarrow_reseed_internal(RANDOM_YARROW_SLOW);
+
+ RANDOM_RESEED_UNLOCK();
}
-static void
-generator_gate(void)
+int
+random_yarrow_seeded(void)
{
- u_int i;
- uint8_t temp[KEYSIZE];
- for (i = 0; i < KEYSIZE; i += BLOCKSIZE) {
- uint128_increment(&yarrow_state.counter.whole);
- randomdev_encrypt(&yarrow_state.key, yarrow_state.counter.byte, temp + i, BLOCKSIZE);
- }
+ return (yarrow_state.ys_seeded);
+}
+
+/* MODULE */
+
+#ifdef _KERNEL
- randomdev_encrypt_init(&yarrow_state.key, temp);
- memset(temp, 0, KEYSIZE);
+static void random_yarrow_init(void);
+static void random_yarrow_deinit(void);
+
+static struct random_adaptor random_soft_processor = {
+#define RANDOM_CSPRNG_NAME "yarrow"
+ .ra_ident = "Yarrow",
+ .ra_priority = 90, /* High priority, so top of the list. Fortuna may still win. */
+ .ra_pre_read = random_yarrow_pre_read,
+ .ra_read = random_yarrow_read,
+ .ra_post_read = random_yarrow_post_read,
+ .ra_write = random_yarrow_write,
+ .ra_reseed = random_yarrow_reseed,
+ .ra_seeded = random_yarrow_seeded,
+ .ra_init = random_yarrow_init,
+ .ra_deinit = random_yarrow_deinit,
+};
+
+void
+random_yarrow_init(void)
+{
+
+ random_yarrow_init_alg();
+ random_harvestq_init(random_yarrow_process_event, 2);
+ randomdev_init_harvester(random_harvestq_internal);
}
void
-random_yarrow_reseed(void)
+random_yarrow_deinit(void)
{
- mtx_lock(&random_reseed_mtx);
- reseed(SLOW);
- mtx_unlock(&random_reseed_mtx);
+ randomdev_deinit_harvester();
+ random_harvestq_deinit();
+ random_yarrow_deinit_alg();
}
-int
-random_yarrow_seeded(void)
+/* ARGSUSED */
+static int
+random_yarrow_soft_modevent(module_t mod __unused, int type, void *unused __unused)
{
+ int error = 0;
+
+ switch (type) {
+ case MOD_LOAD:
+ printf("random: SOFT: yarrow\n");
+ random_adaptor_register("yarrow", &random_soft_processor);
+ break;
+
+ case MOD_UNLOAD:
+ random_adaptor_deregister("yarrow");
+ break;
+
+ case MOD_SHUTDOWN:
+ break;
- return (yarrow_state.seeded);
+ default:
+ error = EOPNOTSUPP;
+ break;
+
+ }
+ return (error);
}
-#endif /* RANDOM_YARROW */
+DEV_MODULE(yarrow, random_yarrow_soft_modevent, NULL);
+MODULE_VERSION(random_yarrow, 1);
+MODULE_DEPEND(random_yarrow, randomdev, 1, 1, 1);
+MODULE_DEPEND(random_yarrow, crypto, 1, 1, 1);
+
+#endif /* _KERNEL */
Index: sys/i386/conf/DEFAULTS
===================================================================
--- sys/i386/conf/DEFAULTS
+++ sys/i386/conf/DEFAULTS
@@ -30,3 +30,7 @@
device atpic
options NEW_PCIB
+
+# Random Number Generator
+options RANDOM_YARROW
+options RANDOM_FORTUNA
Index: sys/kern/subr_bus.c
===================================================================
--- sys/kern/subr_bus.c
+++ sys/kern/subr_bus.c
@@ -28,7 +28,6 @@
__FBSDID("$FreeBSD$");
#include "opt_bus.h"
-#include "opt_random.h"
#include <sys/param.h>
#include <sys/conf.h>
Index: sys/mips/conf/DEFAULTS
===================================================================
--- sys/mips/conf/DEFAULTS
+++ sys/mips/conf/DEFAULTS
@@ -9,3 +9,7 @@
options GEOM_PART_BSD
options GEOM_PART_MBR
+
+# Random Number Generator
+options RANDOM_YARROW
+options RANDOM_FORTUNA
Index: sys/modules/Makefile
===================================================================
--- sys/modules/Makefile
+++ sys/modules/Makefile
@@ -289,7 +289,9 @@
${_qlxgbe} \
ral \
${_ralfw} \
- ${_random} \
+ ${_random_infra} \
+ ${_random_fortuna} \
+ ${_random_yarrow} \
rc4 \
${_rdma} \
${_rdrand_rng} \
@@ -394,7 +396,9 @@
_cryptodev= cryptodev
.endif
.if exists(${.CURDIR}/../crypto)
-_random= random
+_random_infra= random_infra
+_random_fortuna=random_fortuna
+_random_yarrow= random_yarrow
.endif
.endif
Index: sys/modules/crypto/Makefile
===================================================================
--- sys/modules/crypto/Makefile
+++ sys/modules/crypto/Makefile
@@ -12,7 +12,7 @@
KMOD = crypto
SRCS = crypto.c cryptodev_if.c
SRCS += criov.c cryptosoft.c xform.c
-SRCS += cast.c cryptodeflate.c rmd160.c rijndael-alg-fst.c rijndael-api.c
+SRCS += cast.c cryptodeflate.c rmd160.c rijndael-alg-fst.c rijndael-api.c rijndael-api-fst.c
SRCS += skipjack.c bf_enc.c bf_ecb.c bf_skey.c
SRCS += camellia.c camellia-api.c
SRCS += des_ecb.c des_enc.c des_setkey.c
Index: sys/modules/random/Makefile
===================================================================
--- sys/modules/random/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# $FreeBSD$
-
-.PATH: ${.CURDIR}/../../dev/random
-.PATH: ${.CURDIR}/../../crypto/rijndael
-.PATH: ${.CURDIR}/../../crypto/sha2
-
-KMOD= random
-SRCS= randomdev_soft.c
-SRCS+= yarrow.c fortuna.c hash.c
-SRCS+= rijndael-alg-fst.c rijndael-api-fst.c sha2.c sha256c.c
-SRCS+= bus_if.h device_if.h vnode_if.h opt_cpu.h opt_random.h
-
-CFLAGS+= -I${.CURDIR}/../..
-
-.include <bsd.kmod.mk>
Index: sys/modules/random_fortuna/Makefile
===================================================================
--- /dev/null
+++ sys/modules/random_fortuna/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../dev/random
+
+KMOD= random_fortuna
+SRCS= fortuna.c hash.c
+SRCS+= bus_if.h device_if.h vnode_if.h opt_cpu.h
+
+CFLAGS+= -I${.CURDIR}/../..
+
+.include <bsd.kmod.mk>
Index: sys/modules/random_infra/Makefile
===================================================================
--- /dev/null
+++ sys/modules/random_infra/Makefile
@@ -0,0 +1,13 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../dev/random
+.PATH: ${.CURDIR}/../../crypto/rijndael
+.PATH: ${.CURDIR}/../../crypto/sha2
+
+KMOD= random_infra
+SRCS= live_entropy_sources.c random_harvestq.c
+SRCS+= bus_if.h device_if.h vnode_if.h opt_cpu.h
+
+CFLAGS+= -I${.CURDIR}/../..
+
+.include <bsd.kmod.mk>
Index: sys/modules/random_yarrow/Makefile
===================================================================
--- /dev/null
+++ sys/modules/random_yarrow/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../dev/random
+
+KMOD= random_yarrow
+SRCS= yarrow.c hash.c
+SRCS+= bus_if.h device_if.h vnode_if.h opt_cpu.h
+
+CFLAGS+= -I${.CURDIR}/../..
+
+.include <bsd.kmod.mk>
Index: sys/pc98/conf/DEFAULTS
===================================================================
--- sys/pc98/conf/DEFAULTS
+++ sys/pc98/conf/DEFAULTS
@@ -29,3 +29,7 @@
device atpic
options NEW_PCIB
+
+# Random Number Generator
+options RANDOM_YARROW
+options RANDOM_FORTUNA
Index: sys/powerpc/conf/DEFAULTS
===================================================================
--- sys/powerpc/conf/DEFAULTS
+++ sys/powerpc/conf/DEFAULTS
@@ -13,3 +13,7 @@
options GEOM_PART_MBR
options NEW_PCIB
+
+# Random Number Generator
+options RANDOM_YARROW
+options RANDOM_FORTUNA
Index: sys/sparc64/conf/DEFAULTS
===================================================================
--- sys/sparc64/conf/DEFAULTS
+++ sys/sparc64/conf/DEFAULTS
@@ -21,3 +21,7 @@
options SUNKBD_EMULATE_ATKBD
options NEW_PCIB
+
+# Random Number Generator
+options RANDOM_YARROW
+options RANDOM_FORTUNA
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Apr 21, 8:14 PM (4 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31930960
Default Alt Text
D2025.id4636.diff (117 KB)
Attached To
Mode
D2025: Tidy up random(4) driver after developer feedback and code audit.
Attached
Detach File
Event Timeline
Log In to Comment