Page MenuHomeFreeBSD

D2025.id4636.diff
No OneTemporary

D2025.id4636.diff

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, &timestamp, sizeof(timestamp));
- randomdev_hash_iterate(&fortuna_start_cache.hash, buf, count);
+ randomdev_hash_iterate(&hash, &timestamp, sizeof(timestamp));
+ randomdev_hash_iterate(&hash, buf, count);
timestamp = get_cyclecount();
- randomdev_hash_iterate(&fortuna_start_cache.hash, &timestamp, sizeof(timestamp));
- randomdev_hash_finish(&fortuna_start_cache.hash, temp);
- for (i = 0; i < KEYSIZE; i++)
- fortuna_start_cache.junk[(fortuna_start_cache.length + i)%PAGE_SIZE] ^= temp[i];
- fortuna_start_cache.length += KEYSIZE;
+ randomdev_hash_iterate(&hash, &timestamp, 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, &timestamp, sizeof(timestamp));
- randomdev_hash_iterate(&yarrow_state.start_cache.hash, buf, count);
+ randomdev_hash_iterate(&hash, &timestamp, sizeof(timestamp));
+ randomdev_hash_iterate(&hash, buf, count);
timestamp = get_cyclecount();
- randomdev_hash_iterate(&yarrow_state.start_cache.hash, &timestamp, 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, &timestamp, 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

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)

Event Timeline