* Address review (and add a bit myself).

- Tweek man page.
 - Remove all mention of RANDOM_FORTUNA. If the system owner wants YARROW or DUMMY, they ask for it, otherwise they get FORTUNA.
 - Tidy up headers a bit.
 - Tidy up declarations a bit.
 - Make static in a couple of places where needed.
 - Move Yarrow/Fortuna SYSINIT/SYSUNINIT to randomdev.c, moving us towards a single file where the algorithm context is used.
 - Get rid of random_*_process_buffer() functions. They were only used in one place each, and are better subsumed into those places.
 - Remove *_post_read() functions as they are stubs everywhere.
 - Assert against buffer size illegalities.
 - Clean up some silly code in the randomdev_read() routine.
 - Make the harvesting more consistent.
 - Make some requested argument name changes.
 - Tidy up and clarify a few comments.
 - Make some requested comment changes.
 - Make some requested macro changes.

* NOTE: the thing calling itself a 'unit test' is not yet a proper
  unit test, but it helps me ensure things work. It may be a proper
  unit test at some time in the future, but for now please don't make
  any assumptions or hold any expectations.

Differential Revision:	https://reviews.freebsd.org/D2025
Approved by:	so (/dev/random blanket)
This commit is contained in:
Mark Murray 2015-07-12 18:14:38 +00:00
parent e7c14c38ba
commit 3aa77530ca
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=285422
13 changed files with 151 additions and 200 deletions

View File

@ -62,7 +62,7 @@ This sysctl will not return
random bytes unless random bytes unless
the the
.Xr random 4 .Xr random 4
is seeded. device is seeded.
.Pp .Pp
This initial seeding This initial seeding
of random number generators of random number generators

View File

@ -2978,8 +2978,8 @@ options MAXFILES=999
# Random number generator # Random number generator
# Only ONE of the below two may be used; they are mutually exclusive. # Only ONE of the below two may be used; they are mutually exclusive.
# If neither is present, then the Fortuna algorithm is used.
options RANDOM_YARROW # Yarrow CSPRNG (Default) options RANDOM_YARROW # Yarrow CSPRNG (Default)
#options RANDOM_FORTUNA # Fortuna CSPRNG
options RANDOM_DEBUG # Debugging messages options RANDOM_DEBUG # Debugging messages
# Module to enable execution of application via emulators like QEMU # Module to enable execution of application via emulators like QEMU

View File

@ -28,7 +28,14 @@
# #
# Basic script to build crude unit tests. # Basic script to build crude unit tests.
# #
cc -g -O0 -pthread -DRANDOM_DEBUG -DRANDOM_YARROW \ # Diff-reduction checking between Yarrow and fortuna is done like so:
#
# $ diff -u -B <(sed -e 's/yarrow/wombat/g' \
# -e 's/YARROW/WOMBAT/g' yarrow.c) \
# <(sed -e 's/fortuna/wombat/g' \
# -e 's/FORTUNA/WOMBAT/g' fortuna.c) | less
#
cc -g -O0 -pthread -DRANDOM_DEBUG \
-I../.. -lstdthreads -Wall \ -I../.. -lstdthreads -Wall \
unit_test.c \ unit_test.c \
yarrow.c \ yarrow.c \
@ -39,7 +46,7 @@ cc -g -O0 -pthread -DRANDOM_DEBUG -DRANDOM_YARROW \
../../crypto/sha2/sha256c.c \ ../../crypto/sha2/sha256c.c \
-lz \ -lz \
-o yunit_test -o yunit_test
cc -g -O0 -pthread -DRANDOM_DEBUG -DRANDOM_FORTUNA \ cc -g -O0 -pthread -DRANDOM_DEBUG \
-I../.. -lstdthreads -Wall \ -I../.. -lstdthreads -Wall \
unit_test.c \ unit_test.c \
fortuna.c \ fortuna.c \

View File

@ -39,10 +39,8 @@ __FBSDID("$FreeBSD$");
#ifdef _KERNEL #ifdef _KERNEL
#include <sys/param.h> #include <sys/param.h>
#include <sys/kernel.h> #include <sys/kernel.h>
#include <sys/conf.h>
#include <sys/lock.h> #include <sys/lock.h>
#include <sys/malloc.h> #include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h> #include <sys/mutex.h>
#include <sys/random.h> #include <sys/random.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
@ -71,6 +69,7 @@ __FBSDID("$FreeBSD$");
#include <crypto/sha2/sha2.h> #include <crypto/sha2/sha2.h>
#include <dev/random/hash.h> #include <dev/random/hash.h>
#include <dev/random/randomdev.h>
#include <dev/random/uint128.h> #include <dev/random/uint128.h>
#include <dev/random/fortuna.h> #include <dev/random/fortuna.h>
#endif /* _KERNEL */ #endif /* _KERNEL */
@ -125,26 +124,28 @@ static uint8_t zero_region[RANDOM_ZERO_BLOCKSIZE];
static void random_fortuna_pre_read(void); static void random_fortuna_pre_read(void);
static void random_fortuna_read(uint8_t *, u_int); static void random_fortuna_read(uint8_t *, u_int);
static void random_fortuna_post_read(void);
static void random_fortuna_write(uint8_t *, u_int); static void random_fortuna_write(uint8_t *, u_int);
static void random_fortuna_reseed(void); static void random_fortuna_reseed(void);
static int random_fortuna_seeded(void); static int random_fortuna_seeded(void);
static void random_fortuna_process_event(struct harvest_event *); static void random_fortuna_process_event(struct harvest_event *);
static void random_fortuna_init_alg(void *);
static void random_fortuna_deinit_alg(void *);
static void random_fortuna_reseed_internal(uint32_t *entropy_data, u_int blockcount);
#ifdef _KERNEL
/* Interface to Adaptors system */ /* Interface to Adaptors system */
struct random_algorithm random_alg_context = { struct random_algorithm random_alg_context = {
.ra_ident = "Fortuna", .ra_ident = "Fortuna",
.ra_init_alg = random_fortuna_init_alg,
.ra_deinit_alg = random_fortuna_deinit_alg,
.ra_pre_read = random_fortuna_pre_read, .ra_pre_read = random_fortuna_pre_read,
.ra_read = random_fortuna_read, .ra_read = random_fortuna_read,
.ra_post_read = random_fortuna_post_read,
.ra_write = random_fortuna_write, .ra_write = random_fortuna_write,
.ra_reseed = random_fortuna_reseed, .ra_reseed = random_fortuna_reseed,
.ra_seeded = random_fortuna_seeded, .ra_seeded = random_fortuna_seeded,
.ra_event_processor = random_fortuna_process_event, .ra_event_processor = random_fortuna_process_event,
.ra_poolcount = RANDOM_FORTUNA_NPOOLS, .ra_poolcount = RANDOM_FORTUNA_NPOOLS,
}; };
#endif
/* ARGSUSED */ /* ARGSUSED */
static void static void
@ -194,9 +195,6 @@ random_fortuna_init_alg(void *unused __unused)
fortuna_state.fs_counter = UINT128_ZERO; fortuna_state.fs_counter = UINT128_ZERO;
explicit_bzero(&fortuna_state.fs_key, sizeof(fortuna_state.fs_key)); explicit_bzero(&fortuna_state.fs_key, sizeof(fortuna_state.fs_key));
} }
#ifdef _KERNEL
SYSINIT(random_fortuna, SI_SUB_RANDOM, SI_ORDER_THIRD, random_fortuna_init_alg, NULL);
#endif
/* ARGSUSED */ /* ARGSUSED */
static void static void
@ -209,15 +207,12 @@ random_fortuna_deinit_alg(void *unused __unused)
sysctl_ctx_free(&random_clist); sysctl_ctx_free(&random_clist);
#endif #endif
} }
#ifdef _KERNEL
SYSUNINIT(random_fortuna, SI_SUB_RANDOM, SI_ORDER_THIRD, random_fortuna_deinit_alg, NULL);
#endif
/*- /*-
* FS&K - AddRandomEvent() * FS&K - AddRandomEvent()
* Process a single stochastic event off the harvest queue * Process a single stochastic event off the harvest queue
*/ */
void static void
random_fortuna_process_event(struct harvest_event *event) random_fortuna_process_event(struct harvest_event *event)
{ {
u_int pl; u_int pl;
@ -250,29 +245,6 @@ random_fortuna_process_event(struct harvest_event *event)
RANDOM_RESEED_UNLOCK(); RANDOM_RESEED_UNLOCK();
} }
/*-
* Process a block of data suspected to be slightly stochastic.
* Do this by breaking it up and inserting the pieces as if
* they were separate events.
*/
static void
random_fortuna_process_buffer(uint32_t *buf, u_int wordcount)
{
static struct harvest_event event;
static u_int destination = 0;
int i;
for (i = 0; i < wordcount; i += sizeof(event.he_entropy)/sizeof(event.he_entropy[0])) {
event.he_somecounter = (uint32_t)get_cyclecount();
event.he_size = sizeof(event.he_entropy);
event.he_bits = event.he_size/8;
event.he_source = RANDOM_CACHED;
event.he_destination = destination++; /* Harmless cheating */
memcpy(event.he_entropy, buf + i, sizeof(event.he_entropy));
random_fortuna_process_event(&event);
}
}
/*- /*-
* FS&K - Reseed() * FS&K - Reseed()
* This introduces new key material into the output generator. * This introduces new key material into the output generator.
@ -358,13 +330,10 @@ random_fortuna_genrandom(uint8_t *buf, u_int bytecount)
} }
/*- /*-
* FS&K - RandomData() * FS&K - RandomData() (Part 1)
* Used to return processed entropy from the PRNG. * Used to return processed entropy from the PRNG. There is a pre_read
* There is a pre_read and a post_read required to be present * required to be present (but it can be a stub) in order to allow
* (but they can be null functions) in order to allow specific * specific actions at the begin of the read.
* 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 void
random_fortuna_pre_read(void) random_fortuna_pre_read(void)
@ -435,8 +404,10 @@ random_fortuna_pre_read(void)
} }
/*- /*-
* Main read from Fortuna. * FS&K - RandomData() (Part 2)
* The supplied buf MUST be a multiple (>=0) of RANDOM_BLOCKSIZE in size. * Main read from Fortuna, continued. May be called multiple times after
* the random_fortuna_pre_read() above.
* The supplied buf MUST be a multiple of RANDOM_BLOCKSIZE in size.
* Lots of code presumes this for efficiency, both here and in other * Lots of code presumes this for efficiency, both here and in other
* routines. You are NOT allowed to break this! * routines. You are NOT allowed to break this!
*/ */
@ -444,24 +415,21 @@ void
random_fortuna_read(uint8_t *buf, u_int bytecount) random_fortuna_read(uint8_t *buf, u_int bytecount)
{ {
KASSERT((bytecount % RANDOM_BLOCKSIZE) == 0, ("%s(): bytecount (= %d) must be a multiple of %d", __func__, bytecount, RANDOM_BLOCKSIZE ));
RANDOM_RESEED_LOCK(); RANDOM_RESEED_LOCK();
random_fortuna_genrandom(buf, bytecount); random_fortuna_genrandom(buf, bytecount);
RANDOM_RESEED_UNLOCK(); RANDOM_RESEED_UNLOCK();
} }
void
random_fortuna_post_read(void)
{
/* CWOT */
}
/* Internal function to hand external entropy to the PRNG. */ /* Internal function to hand external entropy to the PRNG. */
void void
random_fortuna_write(uint8_t *buf, u_int count) random_fortuna_write(uint8_t *buf, u_int count)
{ {
static u_int destination = 0;
struct harvest_event event;
struct randomdev_hash hash; struct randomdev_hash hash;
uint32_t entropy_data[RANDOM_KEYSIZE_WORDS], timestamp; uint32_t entropy_data[RANDOM_KEYSIZE_WORDS], timestamp;
int i;
/* Extra timing here is helpful to scrape scheduler timing entropy */ /* Extra timing here is helpful to scrape scheduler timing entropy */
randomdev_hash_init(&hash); randomdev_hash_init(&hash);
@ -472,15 +440,21 @@ random_fortuna_write(uint8_t *buf, u_int count)
randomdev_hash_iterate(&hash, &timestamp, sizeof(timestamp)); randomdev_hash_iterate(&hash, &timestamp, sizeof(timestamp));
randomdev_hash_finish(&hash, entropy_data); randomdev_hash_finish(&hash, entropy_data);
explicit_bzero(&hash, sizeof(hash)); explicit_bzero(&hash, sizeof(hash));
random_fortuna_process_buffer(entropy_data, sizeof(entropy_data)/sizeof(entropy_data[0])); for (i = 0; i < RANDOM_KEYSIZE_WORDS; i += sizeof(event.he_entropy)/sizeof(event.he_entropy[0])) {
event.he_somecounter = (uint32_t)get_cyclecount();
event.he_size = sizeof(event.he_entropy);
event.he_bits = event.he_size/8;
event.he_source = RANDOM_CACHED;
event.he_destination = destination++; /* Harmless cheating */
memcpy(event.he_entropy, entropy_data + i, sizeof(event.he_entropy));
random_fortuna_process_event(&event);
}
explicit_bzero(entropy_data, sizeof(entropy_data)); explicit_bzero(entropy_data, sizeof(entropy_data));
} }
void void
random_fortuna_reseed(void) random_fortuna_reseed(void)
{ {
/* CWOT */
} }
int int

View File

@ -29,18 +29,21 @@
#ifndef SYS_DEV_RANDOM_HASH_H_INCLUDED #ifndef SYS_DEV_RANDOM_HASH_H_INCLUDED
#define SYS_DEV_RANDOM_HASH_H_INCLUDED #define SYS_DEV_RANDOM_HASH_H_INCLUDED
/* Keys are formed from cipher blocks */
#define RANDOM_KEYSIZE 32 /* (in bytes) == 256 bits */ #define RANDOM_KEYSIZE 32 /* (in bytes) == 256 bits */
#define RANDOM_KEYSIZE_WORDS (RANDOM_KEYSIZE/sizeof(uint32_t)) #define RANDOM_KEYSIZE_WORDS (RANDOM_KEYSIZE/sizeof(uint32_t))
#define RANDOM_BLOCKSIZE 16 /* (in bytes) == 128 bits */ #define RANDOM_BLOCKSIZE 16 /* (in bytes) == 128 bits */
#define RANDOM_BLOCKSIZE_WORDS (RANDOM_BLOCKSIZE/sizeof(uint32_t)) #define RANDOM_BLOCKSIZE_WORDS (RANDOM_BLOCKSIZE/sizeof(uint32_t))
#define RANDOM_KEYS_PER_BLOCK (RANDOM_KEYSIZE/RANDOM_BLOCKSIZE) #define RANDOM_KEYS_PER_BLOCK (RANDOM_KEYSIZE/RANDOM_BLOCKSIZE)
/* The size of the zero block portion used to form H_d(m) */
#define RANDOM_ZERO_BLOCKSIZE 64 /* (in bytes) == 512 zero bits */ #define RANDOM_ZERO_BLOCKSIZE 64 /* (in bytes) == 512 zero bits */
struct randomdev_hash { /* Big! Make static! */ struct randomdev_hash {
SHA256_CTX sha; SHA256_CTX sha;
}; };
struct randomdev_key { /* Big! Make static! */ struct randomdev_key {
keyInstance key; /* Key schedule */ keyInstance key; /* Key schedule */
cipherInstance cipher; /* Rijndael internal */ cipherInstance cipher; /* Rijndael internal */
}; };

View File

@ -74,8 +74,8 @@ volatile int random_kthread_control;
* this make is a bit easier to lock and protect. * this make is a bit easier to lock and protect.
*/ */
static struct harvest_context { static struct harvest_context {
/* The harvest mutex protects the consistency of the entropy Fifos and /* The harvest mutex protects all of harvest_context and
* empty fifo and other associated structures. * the related data.
*/ */
struct mtx hc_mtx; struct mtx hc_mtx;
/* Round-robin destination cache. */ /* Round-robin destination cache. */
@ -95,6 +95,9 @@ static struct harvest_context {
* If (ring.in + 1) == ring.out (mod RANDOM_RING_MAX), * If (ring.in + 1) == ring.out (mod RANDOM_RING_MAX),
* the buffer is full. * the buffer is full.
* *
* NOTE: ring.in points to the last added element,
* and ring.out points to the last consumed element.
*
* The ring.in variable needs locking as there are multiple * The ring.in variable needs locking as there are multiple
* sources to the ring. Only the sources may change ring.in, * sources to the ring. Only the sources may change ring.in,
* but the consumer may examine it. * but the consumer may examine it.
@ -110,7 +113,7 @@ static struct harvest_context {
} hc_entropy_ring; } hc_entropy_ring;
struct fast_entropy_accumulator { struct fast_entropy_accumulator {
volatile u_int pos; volatile u_int pos;
uint32_t buf[8]; uint32_t buf[RANDOM_ACCUM_MAX];
} hc_entropy_fast_accumulator; } hc_entropy_fast_accumulator;
} harvest_context; } harvest_context;
@ -150,7 +153,7 @@ random_kthread(void)
break; break;
} }
random_sources_feed(); random_sources_feed();
/* XXX: FIX!! This This seems a little slow; 8 items every 0.1s from UMA? */ /* XXX: FIX!! Increase the high-performance data rate? Need some measurements first. */
for (i = 0; i < RANDOM_ACCUM_MAX; i++) { for (i = 0; i < RANDOM_ACCUM_MAX; i++) {
if (harvest_context.hc_entropy_fast_accumulator.buf[i]) { if (harvest_context.hc_entropy_fast_accumulator.buf[i]) {
random_harvest_direct(harvest_context.hc_entropy_fast_accumulator.buf + i, sizeof(harvest_context.hc_entropy_fast_accumulator.buf[0]), 4, RANDOM_FAST); random_harvest_direct(harvest_context.hc_entropy_fast_accumulator.buf + i, sizeof(harvest_context.hc_entropy_fast_accumulator.buf[0]), 4, RANDOM_FAST);
@ -238,8 +241,6 @@ random_harvestq_init(void *unused __unused)
{ {
struct sysctl_oid *random_sys_o; struct sysctl_oid *random_sys_o;
if (bootverbose)
printf("random: %s\n", __func__);
random_sys_o = SYSCTL_ADD_NODE(&random_clist, random_sys_o = SYSCTL_ADD_NODE(&random_clist,
SYSCTL_STATIC_CHILDREN(_kern_random), SYSCTL_STATIC_CHILDREN(_kern_random),
OID_AUTO, "harvest", CTLFLAG_RW, 0, OID_AUTO, "harvest", CTLFLAG_RW, 0,
@ -285,6 +286,8 @@ random_harvestq_prime(void *unused __unused)
if (keyfile != NULL) { if (keyfile != NULL) {
data = preload_fetch_addr(keyfile); data = preload_fetch_addr(keyfile);
size = preload_fetch_size(keyfile); size = preload_fetch_size(keyfile);
/* Trim the size. If the admin has a file with a funny size, we lose some. Tough. */
size -= (size % sizeof(event.he_entropy));
if (data != NULL && size != 0) { if (data != NULL && size != 0) {
for (i = 0; i < size; i += sizeof(event.he_entropy)) { for (i = 0; i < size; i += sizeof(event.he_entropy)) {
count = sizeof(event.he_entropy); count = sizeof(event.he_entropy);
@ -314,7 +317,7 @@ random_harvestq_deinit(void *unused __unused)
/* Command the hash/reseed thread to end and wait for it to finish */ /* Command the hash/reseed thread to end and wait for it to finish */
random_kthread_control = 0; random_kthread_control = 0;
tsleep(&harvest_context.hc_kthread_proc, 0, "term", 0); tsleep(&harvest_context.hc_kthread_proc, 0, "harvqterm", 0);
sysctl_ctx_free(&random_clist); sysctl_ctx_free(&random_clist);
} }
SYSUNINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_SECOND, random_harvestq_deinit, NULL); SYSUNINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_SECOND, random_harvestq_deinit, NULL);
@ -334,7 +337,7 @@ SYSUNINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_SECOND, random_harvestq_
* read which can be quite expensive. * read which can be quite expensive.
*/ */
void void
random_harvest_queue(const void *entropy, u_int count, u_int bits, enum random_entropy_source origin) random_harvest_queue(const void *entropy, u_int size, u_int bits, enum random_entropy_source origin)
{ {
struct harvest_event *event; struct harvest_event *event;
u_int ring_in; u_int ring_in;
@ -351,14 +354,14 @@ random_harvest_queue(const void *entropy, u_int count, u_int bits, enum random_e
event->he_source = origin; event->he_source = origin;
event->he_destination = harvest_context.hc_destination[origin]++; event->he_destination = harvest_context.hc_destination[origin]++;
event->he_bits = bits; event->he_bits = bits;
if (count <= sizeof(event->he_entropy)) { if (size <= sizeof(event->he_entropy)) {
event->he_size = count; event->he_size = size;
memcpy(event->he_entropy, entropy, count); memcpy(event->he_entropy, entropy, size);
} }
else { else {
/* Big event, so squash it */ /* Big event, so squash it */
event->he_size = sizeof(event->he_entropy[0]); event->he_size = sizeof(event->he_entropy[0]);
event->he_entropy[0] = jenkins_hash(entropy, count, (uint32_t)(uintptr_t)event); event->he_entropy[0] = jenkins_hash(entropy, size, (uint32_t)(uintptr_t)event);
} }
harvest_context.hc_entropy_ring.in = ring_in; harvest_context.hc_entropy_ring.in = ring_in;
} }
@ -372,7 +375,7 @@ random_harvest_queue(const void *entropy, u_int count, u_int bits, enum random_e
* This is the right place for high-rate harvested data. * This is the right place for high-rate harvested data.
*/ */
void void
random_harvest_fast(const void *entropy, u_int count, u_int bits, enum random_entropy_source origin) random_harvest_fast(const void *entropy, u_int size, u_int bits, enum random_entropy_source origin)
{ {
u_int pos; u_int pos;
@ -381,7 +384,7 @@ random_harvest_fast(const void *entropy, u_int count, u_int bits, enum random_en
if (!(harvest_context.hc_source_mask & (1 << origin))) if (!(harvest_context.hc_source_mask & (1 << origin)))
return; return;
pos = harvest_context.hc_entropy_fast_accumulator.pos; pos = harvest_context.hc_entropy_fast_accumulator.pos;
harvest_context.hc_entropy_fast_accumulator.buf[pos] ^= jenkins_hash(entropy, count, (uint32_t)get_cyclecount()); harvest_context.hc_entropy_fast_accumulator.buf[pos] ^= jenkins_hash(entropy, size, (uint32_t)get_cyclecount());
harvest_context.hc_entropy_fast_accumulator.pos = (pos + 1)%RANDOM_ACCUM_MAX; harvest_context.hc_entropy_fast_accumulator.pos = (pos + 1)%RANDOM_ACCUM_MAX;
} }
@ -392,20 +395,20 @@ random_harvest_fast(const void *entropy, u_int count, u_int bits, enum random_en
* (e.g.) booting when initial entropy is being gathered. * (e.g.) booting when initial entropy is being gathered.
*/ */
void void
random_harvest_direct(const void *entropy, u_int count, u_int bits, enum random_entropy_source origin) random_harvest_direct(const void *entropy, u_int size, u_int bits, enum random_entropy_source origin)
{ {
struct harvest_event event; struct harvest_event event;
KASSERT(origin >= RANDOM_START && origin < ENTROPYSOURCE, ("%s: origin %d invalid\n", __func__, origin)); KASSERT(origin >= RANDOM_START && origin < ENTROPYSOURCE, ("%s: origin %d invalid\n", __func__, origin));
if (!(harvest_context.hc_source_mask & (1 << origin))) if (!(harvest_context.hc_source_mask & (1 << origin)))
return; return;
count = MIN(count, sizeof(event.he_entropy)); size = MIN(size, sizeof(event.he_entropy));
event.he_somecounter = (uint32_t)get_cyclecount(); event.he_somecounter = (uint32_t)get_cyclecount();
event.he_size = count; event.he_size = size;
event.he_bits = bits; event.he_bits = bits;
event.he_source = origin; event.he_source = origin;
event.he_destination = harvest_context.hc_destination[origin]++; event.he_destination = harvest_context.hc_destination[origin]++;
memcpy(event.he_entropy, entropy, count); memcpy(event.he_entropy, entropy, size);
random_harvestq_fast_process_event(&event); random_harvestq_fast_process_event(&event);
explicit_bzero(&event, sizeof(event)); explicit_bzero(&event, sizeof(event));
} }

View File

@ -62,7 +62,7 @@ __FBSDID("$FreeBSD$");
#error "Cannot define both RANDOM_DUMMY and RANDOM_YARROW" #error "Cannot define both RANDOM_DUMMY and RANDOM_YARROW"
#endif #endif
#define RANDOM_MINOR 0 #define RANDOM_UNIT 0
static d_read_t randomdev_read; static d_read_t randomdev_read;
static d_write_t randomdev_write; static d_write_t randomdev_write;
@ -107,12 +107,13 @@ dummy_random(void)
struct random_algorithm random_alg_context = { struct random_algorithm random_alg_context = {
.ra_ident = "Dummy", .ra_ident = "Dummy",
.ra_reseed = dummy_random, .ra_init_alg = NULL,
.ra_seeded = (random_alg_seeded_t *)dummy_random_zero, .ra_deinit_alg = NULL,
.ra_pre_read = dummy_random, .ra_pre_read = dummy_random,
.ra_read = (random_alg_read_t *)dummy_random_zero, .ra_read = (random_alg_read_t *)dummy_random_zero,
.ra_post_read = dummy_random,
.ra_write = (random_alg_write_t *)dummy_random_zero, .ra_write = (random_alg_write_t *)dummy_random_zero,
.ra_reseed = dummy_random,
.ra_seeded = (random_alg_seeded_t *)dummy_random_zero,
.ra_event_processor = NULL, .ra_event_processor = NULL,
.ra_poolcount = 0, .ra_poolcount = 0,
}; };
@ -123,6 +124,23 @@ LIST_HEAD(sources_head, random_sources);
static struct sources_head source_list = LIST_HEAD_INITIALIZER(source_list); static struct sources_head source_list = LIST_HEAD_INITIALIZER(source_list);
static u_int read_rate; static u_int read_rate;
static void
random_alg_context_ra_init_alg(void *data)
{
random_alg_context.ra_init_alg(data);
}
static void
random_alg_context_ra_deinit_alg(void *data)
{
random_alg_context.ra_deinit_alg(data);
}
SYSINIT(random_device, SI_SUB_RANDOM, SI_ORDER_THIRD, random_alg_context_ra_init_alg, NULL);
SYSUNINIT(random_device, SI_SUB_RANDOM, SI_ORDER_THIRD, random_alg_context_ra_deinit_alg, NULL);
#endif /* defined(RANDOM_DUMMY) */ #endif /* defined(RANDOM_DUMMY) */
static struct selinfo rsel; static struct selinfo rsel;
@ -142,15 +160,15 @@ randomdev_read(struct cdev *dev __unused, struct uio *uio, int flags)
random_alg_context.ra_pre_read(); random_alg_context.ra_pre_read();
/* (Un)Blocking logic */ /* (Un)Blocking logic */
error = 0; error = 0;
while (!random_alg_context.ra_seeded() && error == 0) { while (!random_alg_context.ra_seeded()) {
if (flags & O_NONBLOCK) { if (flags & O_NONBLOCK) {
error = EWOULDBLOCK; error = EWOULDBLOCK;
break; break;
} }
tsleep(&random_alg_context, 0, "randrd", hz/10); tsleep(&random_alg_context, 0, "randseed", hz/10);
/* keep tapping away at the pre-read until we seed/unblock. */ /* keep tapping away at the pre-read until we seed/unblock. */
random_alg_context.ra_pre_read(); random_alg_context.ra_pre_read();
printf("random: %s unblock (error = %d)\n", __func__, error); printf("random: %s unblock wait\n", __func__);
} }
if (error == 0) { if (error == 0) {
#if !defined(RANDOM_DUMMY) #if !defined(RANDOM_DUMMY)
@ -160,10 +178,10 @@ randomdev_read(struct cdev *dev __unused, struct uio *uio, int flags)
nbytes = uio->uio_resid; nbytes = uio->uio_resid;
while (uio->uio_resid && !error) { while (uio->uio_resid && !error) {
c = MIN(uio->uio_resid, PAGE_SIZE); c = MIN(uio->uio_resid, PAGE_SIZE);
/* See the random_buf size requirements in the Yarrow/Fortuna code */
random_alg_context.ra_read(random_buf, c); random_alg_context.ra_read(random_buf, c);
error = uiomove(random_buf, c, uio); error = uiomove(random_buf, c, uio);
} }
random_alg_context.ra_post_read();
if (nbytes != uio->uio_resid && (error == ERESTART || error == EINTR) ) if (nbytes != uio->uio_resid && (error == ERESTART || error == EINTR) )
/* Return partial read, not error. */ /* Return partial read, not error. */
error = 0; error = 0;
@ -204,7 +222,6 @@ read_random(void *random_buf, u_int len)
memcpy(random_buf, local_buf, len); memcpy(random_buf, local_buf, len);
} else } else
len = 0; len = 0;
random_alg_context.ra_post_read();
return (len); return (len);
} }
@ -382,7 +399,7 @@ randomdev_modevent(module_t mod __unused, int type, void *data __unused)
case MOD_LOAD: case MOD_LOAD:
printf("random: entropy device external interface\n"); printf("random: entropy device external interface\n");
random_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &random_cdevsw, random_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &random_cdevsw,
RANDOM_MINOR, NULL, UID_ROOT, GID_WHEEL, 0644, "random"); RANDOM_UNIT, NULL, UID_ROOT, GID_WHEEL, 0644, "random");
make_dev_alias(random_dev, "urandom"); /* compatibility */ make_dev_alias(random_dev, "urandom"); /* compatibility */
break; break;
case MOD_UNLOAD: case MOD_UNLOAD:

View File

@ -29,6 +29,8 @@
#ifndef SYS_DEV_RANDOM_RANDOMDEV_H_INCLUDED #ifndef SYS_DEV_RANDOM_RANDOMDEV_H_INCLUDED
#define SYS_DEV_RANDOM_RANDOMDEV_H_INCLUDED #define SYS_DEV_RANDOM_RANDOMDEV_H_INCLUDED
#ifdef _KERNEL
/* This header contains only those definitions that are global /* This header contains only those definitions that are global
* and non algorithm-specific for the entropy processor * and non algorithm-specific for the entropy processor
*/ */
@ -55,11 +57,12 @@ MALLOC_DECLARE(M_ENTROPY);
#define RANDOM_ALG_READ_RATE_MINIMUM 32 #define RANDOM_ALG_READ_RATE_MINIMUM 32
#endif /* _KERNEL */
struct harvest_event; struct harvest_event;
typedef void random_alg_pre_read_t(void); typedef void random_alg_pre_read_t(void);
typedef void random_alg_read_t(uint8_t *, u_int); typedef void random_alg_read_t(uint8_t *, u_int);
typedef void random_alg_post_read_t(void);
typedef void random_alg_write_t(uint8_t *, u_int); typedef void random_alg_write_t(uint8_t *, u_int);
typedef int random_alg_seeded_t(void); typedef int random_alg_seeded_t(void);
typedef void random_alg_reseed_t(void); typedef void random_alg_reseed_t(void);
@ -74,9 +77,10 @@ typedef u_int random_source_read_t(void *, u_int);
struct random_algorithm { struct random_algorithm {
const char *ra_ident; const char *ra_ident;
u_int ra_poolcount; u_int ra_poolcount;
void (*ra_init_alg)(void *);
void (*ra_deinit_alg)(void *);
random_alg_pre_read_t *ra_pre_read; random_alg_pre_read_t *ra_pre_read;
random_alg_read_t *ra_read; random_alg_read_t *ra_read;
random_alg_post_read_t *ra_post_read;
random_alg_write_t *ra_write; random_alg_write_t *ra_write;
random_alg_reseed_t *ra_reseed; random_alg_reseed_t *ra_reseed;
random_alg_seeded_t *ra_seeded; random_alg_seeded_t *ra_seeded;
@ -85,6 +89,8 @@ struct random_algorithm {
extern struct random_algorithm random_alg_context; extern struct random_algorithm random_alg_context;
#ifdef _KERNEL
/* /*
* Random Source is a source of entropy that can provide * Random Source is a source of entropy that can provide
* specified or approximate amount of entropy immediately * specified or approximate amount of entropy immediately
@ -108,6 +114,8 @@ void random_source_deregister(struct random_source *);
void random_sources_feed(void); void random_sources_feed(void);
#endif /* _KERNEL */
void randomdev_unblock(void); void randomdev_unblock(void);
#endif /* SYS_DEV_RANDOM_RANDOMDEV_H_INCLUDED */ #endif /* SYS_DEV_RANDOM_RANDOMDEV_H_INCLUDED */

View File

@ -52,15 +52,9 @@ Where <alg> is YARROW or FORTUNA.
#include <unistd.h> #include <unistd.h>
#include <zlib.h> #include <zlib.h>
#include "randomdev.h"
#include "unit_test.h" #include "unit_test.h"
#ifdef RANDOM_YARROW
#include "dev/random/yarrow.h"
#endif
#ifdef RANDOM_FORTUNA
#include "dev/random/fortuna.h"
#endif
#define NUM_THREADS 3 #define NUM_THREADS 3
#define DEBUG #define DEBUG
@ -112,7 +106,7 @@ block_deflate(uint8_t *uncompr, uint8_t *compr, const size_t len)
while (c_stream.total_in != len && c_stream.total_out < (len*2u + 512u)) { while (c_stream.total_in != len && c_stream.total_out < (len*2u + 512u)) {
err = deflate(&c_stream, Z_NO_FLUSH); err = deflate(&c_stream, Z_NO_FLUSH);
#ifdef DEBUG #ifdef DEBUG
printf("deflate: len = %zd total_in = %lu total_out = %lu\n", len, c_stream.total_in, c_stream.total_out); printf("deflate progress: len = %zd total_in = %lu total_out = %lu\n", len, c_stream.total_in, c_stream.total_out);
#endif #endif
check_err(err, "deflate(..., Z_NO_FLUSH)"); check_err(err, "deflate(..., Z_NO_FLUSH)");
} }
@ -120,7 +114,7 @@ block_deflate(uint8_t *uncompr, uint8_t *compr, const size_t len)
for (;;) { for (;;) {
err = deflate(&c_stream, Z_FINISH); err = deflate(&c_stream, Z_FINISH);
#ifdef DEBUG #ifdef DEBUG
printf("deflate: len = %zd total_in = %lu total_out = %lu\n", len, c_stream.total_in, c_stream.total_out); printf("deflate final: len = %zd total_in = %lu total_out = %lu\n", len, c_stream.total_in, c_stream.total_out);
#endif #endif
if (err == Z_STREAM_END) break; if (err == Z_STREAM_END) break;
check_err(err, "deflate(..., Z_STREAM_END)"); check_err(err, "deflate(..., Z_STREAM_END)");
@ -133,7 +127,7 @@ block_deflate(uint8_t *uncompr, uint8_t *compr, const size_t len)
} }
void void
random_adaptor_unblock(void) randomdev_unblock(void)
{ {
#if 0 #if 0
@ -166,12 +160,7 @@ RunHarvester(void *arg __unused)
e.he_destination = i; e.he_destination = i;
e.he_source = (i + 3)%7; e.he_source = (i + 3)%7;
e.he_next = NULL; e.he_next = NULL;
#ifdef RANDOM_YARROW random_alg_context.ra_event_processor(&e);
random_yarrow_process_event(&e);
#endif
#ifdef RANDOM_FORTUNA
random_fortuna_process_event(&e);
#endif
usleep(r); usleep(r);
} }
@ -198,12 +187,7 @@ WriteCSPRNG(void *threadid)
printf("Thread write 1 - %d\n", i); printf("Thread write 1 - %d\n", i);
if (buf != NULL) { if (buf != NULL) {
printf("Thread 1 writing.\n"); printf("Thread 1 writing.\n");
#ifdef RANDOM_YARROW random_alg_context.ra_write(buf, i);
random_yarrow_write(buf, i);
#endif
#ifdef RANDOM_FORTUNA
random_fortuna_write(buf, i);
#endif
free(buf); free(buf);
} }
usleep(1000000); usleep(1000000);
@ -220,6 +204,7 @@ static int
ReadCSPRNG(void *threadid) ReadCSPRNG(void *threadid)
{ {
size_t tid, zsize; size_t tid, zsize;
u_int buffersize;
uint8_t *buf, *zbuf; uint8_t *buf, *zbuf;
int i; int i;
#ifdef DEBUG #ifdef DEBUG
@ -229,40 +214,22 @@ ReadCSPRNG(void *threadid)
tid = (size_t)threadid; tid = (size_t)threadid;
printf("Thread #%zd starts\n", tid); printf("Thread #%zd starts\n", tid);
#ifdef RANDOM_YARROW while (!random_alg_context.ra_seeded())
while (!random_yarrow_seeded())
#endif
#ifdef RANDOM_FORTUNA
while (!random_fortuna_seeded())
#endif
{ {
#ifdef RANDOM_YARROW random_alg_context.ra_pre_read();
random_yarrow_pre_read();
random_yarrow_post_read();
#endif
#ifdef RANDOM_FORTUNA
random_fortuna_pre_read();
random_fortuna_post_read();
#endif
usleep(100); usleep(100);
} }
for (i = 0; i < 100000; i++) { for (i = 0; i < 100000; i++) {
buf = malloc(i); buffersize = i + RANDOM_BLOCKSIZE;
buffersize -= buffersize%RANDOM_BLOCKSIZE;
buf = malloc(buffersize);
zbuf = malloc(2*i + 1024); zbuf = malloc(2*i + 1024);
if (i % 1000 == 0) if (i % 1000 == 0)
printf("Thread read %zd - %d\n", tid, i); printf("Thread read %zd - %d\n", tid, i);
if (buf != NULL && zbuf != NULL) { if (buf != NULL && zbuf != NULL) {
#ifdef RANDOM_YARROW random_alg_context.ra_pre_read();
random_yarrow_pre_read(); random_alg_context.ra_read(buf, buffersize);
random_yarrow_read(buf, i);
random_yarrow_post_read();
#endif
#ifdef RANDOM_FORTUNA
random_fortuna_pre_read();
random_fortuna_read(buf, i);
random_fortuna_post_read();
#endif
zsize = block_deflate(buf, zbuf, i); zsize = block_deflate(buf, zbuf, i);
if (zsize < i) if (zsize < i)
printf("ERROR!! Compressible RNG output!\n"); printf("ERROR!! Compressible RNG output!\n");
@ -300,12 +267,7 @@ main(int argc, char *argv[])
int rc; int rc;
long t; long t;
#ifdef RANDOM_YARROW random_alg_context.ra_init_alg(NULL);
random_yarrow_init_alg();
#endif
#ifdef RANDOM_FORTUNA
random_fortuna_init_alg();
#endif
for (t = 0; t < NUM_THREADS; t++) { for (t = 0; t < NUM_THREADS; t++) {
printf("In main: creating thread %ld\n", t); printf("In main: creating thread %ld\n", t);
@ -324,12 +286,7 @@ main(int argc, char *argv[])
thrd_join(threads[1], &rc); thrd_join(threads[1], &rc);
thrd_join(threads[0], &rc); thrd_join(threads[0], &rc);
#ifdef RANDOM_YARROW random_alg_context.ra_deinit_alg(NULL);
random_yarrow_deinit_alg();
#endif
#ifdef RANDOM_FORTUNA
random_fortuna_deinit_alg();
#endif
/* Last thing that main() should do */ /* Last thing that main() should do */
thrd_exit(0); thrd_exit(0);

View File

@ -34,7 +34,9 @@
#error "Random unit tests cannot be compiled into the kernel." #error "Random unit tests cannot be compiled into the kernel."
#endif #endif
void random_adaptor_unblock(void); #include <sys/types.h>
#include <inttypes.h>
#include <stdint.h>
#if defined(clang) && __has_builtin(__builtin_readcyclecounter) #if defined(clang) && __has_builtin(__builtin_readcyclecounter)
#define rdtsc __builtin_readcyclecounter #define rdtsc __builtin_readcyclecounter
@ -61,6 +63,7 @@ get_cyclecount(void)
} }
#define HARVESTSIZE 2 #define HARVESTSIZE 2
#define RANDOM_BLOCKSIZE 16
enum random_entropy_source { enum random_entropy_source {
RANDOM_START = 0, RANDOM_START = 0,

View File

@ -30,11 +30,8 @@ __FBSDID("$FreeBSD$");
#ifdef _KERNEL #ifdef _KERNEL
#include <sys/param.h> #include <sys/param.h>
#include <sys/kernel.h>
#include <sys/conf.h>
#include <sys/lock.h> #include <sys/lock.h>
#include <sys/malloc.h> #include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h> #include <sys/mutex.h>
#include <sys/random.h> #include <sys/random.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
@ -54,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <inttypes.h> #include <inttypes.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
#include <string.h> #include <string.h>
#include <threads.h> #include <threads.h>
@ -63,6 +61,7 @@ __FBSDID("$FreeBSD$");
#include <crypto/sha2/sha2.h> #include <crypto/sha2/sha2.h>
#include <dev/random/hash.h> #include <dev/random/hash.h>
#include <dev/random/randomdev.h>
#include <dev/random/uint128.h> #include <dev/random/uint128.h>
#include <dev/random/yarrow.h> #include <dev/random/yarrow.h>
#endif /* _KERNEL */ #endif /* _KERNEL */
@ -109,27 +108,28 @@ RANDOM_CHECK_UINT(slowoverthresh, 1, 5);
static void random_yarrow_pre_read(void); static void random_yarrow_pre_read(void);
static void random_yarrow_read(uint8_t *, u_int); static void random_yarrow_read(uint8_t *, u_int);
static void random_yarrow_post_read(void);
static void random_yarrow_write(uint8_t *, u_int); static void random_yarrow_write(uint8_t *, u_int);
static void random_yarrow_reseed(void); static void random_yarrow_reseed(void);
static int random_yarrow_seeded(void); static int random_yarrow_seeded(void);
static void random_yarrow_reseed_internal(u_int);
static void random_yarrow_process_event(struct harvest_event *); static void random_yarrow_process_event(struct harvest_event *);
static void random_yarrow_init_alg(void *);
static void random_yarrow_deinit_alg(void *);
static void random_yarrow_reseed_internal(u_int);
#ifdef _KERNEL
/* Interface to Adaptors system */ /* Interface to Adaptors system */
struct random_algorithm random_alg_context = { struct random_algorithm random_alg_context = {
.ra_ident = "Yarrow", .ra_ident = "Yarrow",
.ra_init_alg = random_yarrow_init_alg,
.ra_deinit_alg = random_yarrow_deinit_alg,
.ra_pre_read = random_yarrow_pre_read, .ra_pre_read = random_yarrow_pre_read,
.ra_read = random_yarrow_read, .ra_read = random_yarrow_read,
.ra_post_read = random_yarrow_post_read,
.ra_write = random_yarrow_write, .ra_write = random_yarrow_write,
.ra_reseed = random_yarrow_reseed, .ra_reseed = random_yarrow_reseed,
.ra_seeded = random_yarrow_seeded, .ra_seeded = random_yarrow_seeded,
.ra_event_processor = random_yarrow_process_event, .ra_event_processor = random_yarrow_process_event,
.ra_poolcount = RANDOM_YARROW_NPOOLS, .ra_poolcount = RANDOM_YARROW_NPOOLS,
}; };
#endif
/* ARGSUSED */ /* ARGSUSED */
static void static void
@ -199,9 +199,6 @@ random_yarrow_init_alg(void *unused __unused)
/* Clear the counter */ /* Clear the counter */
yarrow_state.ys_counter = UINT128_ZERO; yarrow_state.ys_counter = UINT128_ZERO;
} }
#ifdef _KERNEL
SYSINIT(random_yarrow, SI_SUB_RANDOM, SI_ORDER_THIRD, random_yarrow_init_alg, NULL);
#endif
/* ARGSUSED */ /* ARGSUSED */
static void static void
@ -214,9 +211,6 @@ random_yarrow_deinit_alg(void *unused __unused)
sysctl_ctx_free(&random_clist); sysctl_ctx_free(&random_clist);
#endif #endif
} }
#ifdef _KERNEL
SYSUNINIT(random_yarrow, SI_SUB_RANDOM, SI_ORDER_THIRD, random_yarrow_deinit_alg, NULL);
#endif
/* Process a single stochastic event off the harvest queue */ /* Process a single stochastic event off the harvest queue */
static void static void
@ -255,25 +249,6 @@ random_yarrow_process_event(struct harvest_event *event)
RANDOM_RESEED_UNLOCK(); RANDOM_RESEED_UNLOCK();
} }
/* Process a block of data suspected to be slightly stochastic. */
static void
random_yarrow_process_buffer(uint32_t *buf, u_int wordcount)
{
static struct harvest_event event;
static u_int destination = 0;
int i;
for (i = 0; i < wordcount; i += sizeof(event.he_entropy)/sizeof(event.he_entropy[0])) {
event.he_somecounter = (uint32_t)get_cyclecount();
event.he_size = sizeof(event.he_entropy);
event.he_bits = event.he_size/8;
event.he_source = RANDOM_CACHED;
event.he_destination = destination++; /* Harmless cheating */
memcpy(event.he_entropy, buf + i, sizeof(event.he_entropy));
random_yarrow_process_event(&event);
}
}
static void static void
random_yarrow_reseed_internal(u_int fastslow) random_yarrow_reseed_internal(u_int fastslow)
{ {
@ -384,12 +359,11 @@ random_yarrow_generator_gate(void)
} }
/*- /*-
* Used to return processed entropy from the PRNG. * Used to return processed entropy from the PRNG. There is a pre_read
* There is a pre_read and a post_read required to be present * required to be present (but it can be a stub) in order to allow
* (but they can be null functions) in order to allow specific * specific actions at the begin of the read.
* actions at the begin or the end of a read. Yarrow does its * Yarrow does its reseeding in its own thread; _pre_read() is not used
* reseeding in its own thread. The _pre_read() and _post_read() * by Yarrow but must be kept for completeness.
* are not used here, and must be kept for completeness.
*/ */
void void
random_yarrow_pre_read(void) random_yarrow_pre_read(void)
@ -407,6 +381,7 @@ random_yarrow_read(uint8_t *buf, u_int bytecount)
{ {
u_int blockcount, i; u_int blockcount, i;
KASSERT((bytecount % RANDOM_BLOCKSIZE) == 0, ("%s(): bytecount (= %d) must be a multiple of %d", __func__, bytecount, RANDOM_BLOCKSIZE ));
RANDOM_RESEED_LOCK(); RANDOM_RESEED_LOCK();
blockcount = (bytecount + RANDOM_BLOCKSIZE - 1)/RANDOM_BLOCKSIZE; blockcount = (bytecount + RANDOM_BLOCKSIZE - 1)/RANDOM_BLOCKSIZE;
for (i = 0; i < blockcount; i++) { for (i = 0; i < blockcount; i++) {
@ -421,19 +396,15 @@ random_yarrow_read(uint8_t *buf, u_int bytecount)
RANDOM_RESEED_UNLOCK(); RANDOM_RESEED_UNLOCK();
} }
void
random_yarrow_post_read(void)
{
/* CWOT */
}
/* Internal function to hand external entropy to the PRNG. */ /* Internal function to hand external entropy to the PRNG. */
void void
random_yarrow_write(uint8_t *buf, u_int count) random_yarrow_write(uint8_t *buf, u_int count)
{ {
static u_int destination = 0;
static struct harvest_event event;
struct randomdev_hash hash; struct randomdev_hash hash;
uint32_t entropy_data[RANDOM_KEYSIZE_WORDS], timestamp; uint32_t entropy_data[RANDOM_KEYSIZE_WORDS], timestamp;
int i;
/* Extra timing here is helpful to scrape scheduler timing entropy */ /* Extra timing here is helpful to scrape scheduler timing entropy */
randomdev_hash_init(&hash); randomdev_hash_init(&hash);
@ -444,7 +415,15 @@ random_yarrow_write(uint8_t *buf, u_int count)
randomdev_hash_iterate(&hash, &timestamp, sizeof(timestamp)); randomdev_hash_iterate(&hash, &timestamp, sizeof(timestamp));
randomdev_hash_finish(&hash, entropy_data); randomdev_hash_finish(&hash, entropy_data);
explicit_bzero(&hash, sizeof(hash)); explicit_bzero(&hash, sizeof(hash));
random_yarrow_process_buffer(entropy_data, sizeof(entropy_data)/sizeof(entropy_data[0])); for (i = 0; i < RANDOM_KEYSIZE_WORDS; i += sizeof(event.he_entropy)/sizeof(event.he_entropy[0])) {
event.he_somecounter = (uint32_t)get_cyclecount();
event.he_size = sizeof(event.he_entropy);
event.he_bits = event.he_size/8;
event.he_source = RANDOM_CACHED;
event.he_destination = destination++; /* Harmless cheating */
memcpy(event.he_entropy, entropy_data + i, sizeof(event.he_entropy));
random_yarrow_process_event(&event);
}
explicit_bzero(entropy_data, sizeof(entropy_data)); explicit_bzero(entropy_data, sizeof(entropy_data));
} }

View File

@ -906,7 +906,7 @@ tunwrite(struct cdev *dev, struct uio *uio, int flag)
m_freem(m); m_freem(m);
return (EAFNOSUPPORT); return (EAFNOSUPPORT);
} }
random_harvest_queue(&(m->m_data), 12, 2, RANDOM_NET_TUN); random_harvest_queue(m, sizeof(*m), 2, RANDOM_NET_TUN);
if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len); if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len);
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
CURVNET_SET(ifp->if_vnet); CURVNET_SET(ifp->if_vnet);

View File

@ -705,7 +705,7 @@ ng_iface_rcvdata(hook_p hook, item_p item)
m_freem(m); m_freem(m);
return (EAFNOSUPPORT); return (EAFNOSUPPORT);
} }
random_harvest_queue(&(m->m_data), 12, 2, RANDOM_NET_NG); random_harvest_queue(m, sizeof(*m), 2, RANDOM_NET_NG);
M_SETFIB(m, ifp->if_fib); M_SETFIB(m, ifp->if_fib);
netisr_dispatch(isr, m); netisr_dispatch(isr, m);
return (0); return (0);