Remove the Yarrow PRNG algorithm option in accordance with due notice
given in random(4). This includes updating of the relevant man pages, and no-longer-used harvesting parameters. Ensure that the pseudo-unit-test still does something useful, now also with the "other" algorithm instead of Yarrow. PR: 230870 Reviewed by: cem Approved by: so(delphij,gtetlow) Approved by: re(marius) Differential Revision: https://reviews.freebsd.org/D16898
This commit is contained in:
parent
a1b042f79d
commit
19fa89e938
5
UPDATING
5
UPDATING
@ -31,6 +31,11 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 12.x IS SLOW:
|
||||
disable the most expensive debugging functionality run
|
||||
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
|
||||
|
||||
20180826:
|
||||
The Yarrow CSPRNG has been removed from the kernel as it has not been
|
||||
supported by its designers since at least 2003. Fortuna has been the
|
||||
default since FreeBSD-11.
|
||||
|
||||
20170822:
|
||||
devctl freeze/that have gone into the tree, the rc scripts have been
|
||||
updated to use them and devmatch has been changed. You should update
|
||||
|
@ -23,7 +23,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 17, 2015
|
||||
.Dd August 26, 2018
|
||||
.Dt RANDOM 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -153,26 +153,15 @@ the
|
||||
device is not created
|
||||
until an "algorithm module"
|
||||
is loaded.
|
||||
Two of these modules
|
||||
are built by default,
|
||||
.Em random_fortuna
|
||||
and
|
||||
.Em random_yarrow .
|
||||
The only module built by default is
|
||||
.Em random_fortuna .
|
||||
The
|
||||
.Em random_yarrow
|
||||
module is deprecated,
|
||||
and will be removed in
|
||||
.Fx 12.
|
||||
Use of the Yarrow algorithm
|
||||
is not encouraged,
|
||||
but while still present
|
||||
in the kernel source,
|
||||
it can be selected with the
|
||||
.Cd "options RANDOM_YARROW"
|
||||
kernel option.
|
||||
Note that these loadable modules
|
||||
are slightly less efficient
|
||||
than their compiled-in equivalents.
|
||||
module was removed in
|
||||
.Fx 12 .
|
||||
Note that this loadable module
|
||||
is slightly less efficient
|
||||
than its compiled-in equivalent.
|
||||
This is because some functions
|
||||
must be locked against
|
||||
load and unload events,
|
||||
@ -351,4 +340,4 @@ introduced in
|
||||
The Yarrow algorithm
|
||||
is no longer supported
|
||||
by its authors,
|
||||
and is therefore deprecated.
|
||||
and is therefore no longer available.
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 13, 2015
|
||||
.Dd August 26, 2018
|
||||
.Dt RANDOM_HARVEST 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -38,21 +38,18 @@
|
||||
.Fo random_harvest_direct
|
||||
.Fa "void *entropy"
|
||||
.Fa "u_int size"
|
||||
.Fa "u_int bits"
|
||||
.Fa "enum esource source"
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fo random_harvest_fast
|
||||
.Fa "void *entropy"
|
||||
.Fa "u_int size"
|
||||
.Fa "u_int bits"
|
||||
.Fa "enum esource source"
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fo random_harvest_queue
|
||||
.Fa "void *entropy"
|
||||
.Fa "u_int size"
|
||||
.Fa "u_int bits"
|
||||
.Fa "enum esource source"
|
||||
.Fc
|
||||
.Sh DESCRIPTION
|
||||
@ -108,18 +105,6 @@ choice for most entropy sources
|
||||
such as interrupts
|
||||
or console events.
|
||||
.Pp
|
||||
The
|
||||
.Fa bits
|
||||
argument is only used
|
||||
by the deprecated Yarrow algorithm.
|
||||
For compatibility,
|
||||
the caller should
|
||||
.Em "very conservatively"
|
||||
estimate the number of random bits
|
||||
in the sample,
|
||||
and pass this in
|
||||
.Fa bits .
|
||||
.Pp
|
||||
Interrupt harvesting has been
|
||||
in part simplified
|
||||
for the kernel programmer.
|
||||
|
@ -75,8 +75,7 @@ aml8726_rng_harvest(void *arg)
|
||||
rn[0] = CSR_READ_4(sc, AML_RNG_0_REG);
|
||||
rn[1] = CSR_READ_4(sc, AML_RNG_1_REG);
|
||||
|
||||
random_harvest(rn, sizeof(rn), sizeof(rn) * NBBY / 2,
|
||||
RANDOM_PURE_AML8726);
|
||||
random_harvest(rn, sizeof(rn), RANDOM_PURE_AML8726);
|
||||
|
||||
callout_reset(&sc->co, sc->ticks, aml8726_rng_harvest, sc);
|
||||
}
|
||||
|
@ -289,8 +289,7 @@ bcm2835_rng_harvest(void *arg)
|
||||
|
||||
cnt = nread * sizeof(uint32_t);
|
||||
if (cnt > 0)
|
||||
random_harvest_queue(sc->sc_buf, cnt, cnt * NBBY / 2,
|
||||
RANDOM_PURE_BROADCOM);
|
||||
random_harvest_queue(sc->sc_buf, cnt, RANDOM_PURE_BROADCOM);
|
||||
|
||||
callout_reset(&sc->sc_rngto, RNG_CALLOUT_TICKS, bcm2835_rng_harvest, sc);
|
||||
}
|
||||
|
@ -3008,11 +3008,8 @@ options BROOKTREE_ALLOC_PAGES=(217*4+1)
|
||||
options MAXFILES=999
|
||||
|
||||
# Random number generator
|
||||
# Only ONE of the below two may be used; they are mutually exclusive.
|
||||
# If neither is present, then the Fortuna algorithm is selected.
|
||||
#options RANDOM_YARROW # Yarrow CSPRNG (old default)
|
||||
#options RANDOM_LOADABLE # Allow the algorithm to be loaded as
|
||||
# a module.
|
||||
# Allow the CSPRNG algorithm to be loaded as a module.
|
||||
#options RANDOM_LOADABLE
|
||||
# Select this to allow high-rate but potentially expensive
|
||||
# harvesting of Slab-Allocator entropy. In very high-rate
|
||||
# situations the value of doing this is dubious at best.
|
||||
|
@ -2821,12 +2821,9 @@ rt2860.fw optional rt2860fw | ralfw \
|
||||
clean "rt2860.fw"
|
||||
dev/random/random_infra.c optional random
|
||||
dev/random/random_harvestq.c optional random
|
||||
dev/random/randomdev.c optional random random_yarrow | \
|
||||
random !random_yarrow !random_loadable
|
||||
dev/random/yarrow.c optional random random_yarrow
|
||||
dev/random/fortuna.c optional random !random_yarrow !random_loadable
|
||||
dev/random/hash.c optional random random_yarrow | \
|
||||
random !random_yarrow !random_loadable
|
||||
dev/random/randomdev.c optional random
|
||||
dev/random/fortuna.c optional random !random_loadable
|
||||
dev/random/hash.c optional random
|
||||
dev/rc/rc.c optional rc
|
||||
dev/rccgpio/rccgpio.c optional rccgpio gpio
|
||||
dev/re/if_re.c optional re
|
||||
|
@ -983,9 +983,6 @@ RACCT_DEFAULT_TO_DISABLED opt_global.h
|
||||
RCTL opt_global.h
|
||||
|
||||
# Random number generator(s)
|
||||
# Which CSPRNG hash we get.
|
||||
# If Yarrow is not chosen, Fortuna is selected.
|
||||
RANDOM_YARROW opt_global.h
|
||||
# With this, no entropy processor is loaded, but the entropy
|
||||
# harvesting infrastructure is present. This means an entropy
|
||||
# processor may be loaded as a module.
|
||||
|
@ -457,7 +457,7 @@ glxsb_rnd(void *v)
|
||||
value = bus_read_4(sc->sc_sr, SB_RANDOM_NUM);
|
||||
/* feed with one uint32 */
|
||||
/* MarkM: FIX!! Check that this does not swamp the harvester! */
|
||||
random_harvest_queue(&value, sizeof(value), 32/2, RANDOM_PURE_GLXSB);
|
||||
random_harvest_queue(&value, sizeof(value), RANDOM_PURE_GLXSB);
|
||||
}
|
||||
|
||||
callout_reset(&sc->sc_rngco, sc->sc_rnghz, glxsb_rnd, sc);
|
||||
|
@ -259,7 +259,7 @@ static void
|
||||
default_harvest(struct rndtest_state *rsp, void *buf, u_int count)
|
||||
{
|
||||
/* MarkM: FIX!! Check that this does not swamp the harvester! */
|
||||
random_harvest_queue(buf, count, count*NBBY/2, RANDOM_PURE_HIFN);
|
||||
random_harvest_queue(buf, count, RANDOM_PURE_HIFN);
|
||||
}
|
||||
|
||||
static u_int
|
||||
|
@ -28,23 +28,23 @@
|
||||
#
|
||||
# Basic script to build crude unit tests.
|
||||
#
|
||||
# Diff-reduction checking between Yarrow and fortuna is done like so:
|
||||
# Diff-reduction checking between fortuna and the other algorithm 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
|
||||
# $ diff -u -B <(sed -e 's/random_other/random_wombat/g' \
|
||||
# -e 's/RANDOM_OTHER/RANDOM_WOMBAT/g' other_algorithm.c) \
|
||||
# <(sed -e 's/random_fortuna/random_wombat/g' \
|
||||
# -e 's/RANDOM_FORTUNA/RANDOM_WOMBAT/g' fortuna.c) | less
|
||||
#
|
||||
cc -g -O0 -pthread \
|
||||
-I../.. -lstdthreads -Wall \
|
||||
unit_test.c \
|
||||
yarrow.c \
|
||||
other_algorithm.c \
|
||||
hash.c \
|
||||
../../crypto/rijndael/rijndael-api-fst.c \
|
||||
../../crypto/rijndael/rijndael-alg-fst.c \
|
||||
../../crypto/sha2/sha256c.c \
|
||||
-lz \
|
||||
-o yunit_test
|
||||
-o other_unit_test
|
||||
cc -g -O0 -pthread \
|
||||
-I../.. -lstdthreads -Wall \
|
||||
unit_test.c \
|
||||
@ -54,4 +54,4 @@ cc -g -O0 -pthread \
|
||||
../../crypto/rijndael/rijndael-alg-fst.c \
|
||||
../../crypto/sha2/sha256c.c \
|
||||
-lz \
|
||||
-o funit_test
|
||||
-o fortuna_unit_test
|
||||
|
@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/random/uint128.h>
|
||||
#include <dev/random/fortuna.h>
|
||||
#else /* !_KERNEL */
|
||||
#include <sys/param.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
@ -97,9 +98,11 @@ CTASSERT(RANDOM_BLOCKSIZE == sizeof(uint128_t));
|
||||
CTASSERT(RANDOM_KEYSIZE == 2*RANDOM_BLOCKSIZE);
|
||||
|
||||
/* Probes for dtrace(1) */
|
||||
#ifdef _KERNEL
|
||||
SDT_PROVIDER_DECLARE(random);
|
||||
SDT_PROVIDER_DEFINE(random);
|
||||
SDT_PROBE_DEFINE2(random, fortuna, event_processor, debug, "u_int", "struct fs_pool *");
|
||||
#endif /* _KERNEL */
|
||||
|
||||
/*
|
||||
* This is the beastie that needs protecting. It contains all of the
|
||||
@ -398,7 +401,9 @@ random_fortuna_pre_read(void)
|
||||
} else
|
||||
break;
|
||||
}
|
||||
#ifdef _KERNEL
|
||||
SDT_PROBE2(random, fortuna, event_processor, debug, fortuna_state.fs_reseedcount, fortuna_state.fs_pool);
|
||||
#endif
|
||||
/* FS&K */
|
||||
random_fortuna_reseed_internal(s, i < RANDOM_FORTUNA_NPOOLS ? i + 1 : RANDOM_FORTUNA_NPOOLS);
|
||||
/* Clean up and secure */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Mark R V Murray
|
||||
* Copyright (c) 2015-2018 Mark R V Murray
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -30,19 +30,21 @@
|
||||
* containing an alternative entropy-processing algorithm for random(4).
|
||||
*
|
||||
* The functions below should be completed with the appropriate code,
|
||||
* and the nearby yarrow.c and fortuna.c may be consulted for examples
|
||||
* of working code.
|
||||
* and the nearby fortuna.c may be consulted for examples of working code.
|
||||
*
|
||||
* The author is willing to provide reasonable help to those wishing to
|
||||
* write such a module for themselves. Please use the markm@ FreeBSD
|
||||
* email address, and ensure that you are developing this on a suitably
|
||||
* supported branch (This is currently 11-CURRENT, and will be no
|
||||
* older than 11-STABLE in the future).
|
||||
* supported branch (This is currently 12-CURRENT, and may be no
|
||||
* older than 12-STABLE in the future).
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/limits.h>
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
@ -62,6 +64,24 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/random/random_harvestq.h>
|
||||
#include <dev/random/uint128.h>
|
||||
#include <dev/random/other_algorithm.h>
|
||||
#else /* !_KERNEL */
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <threads.h>
|
||||
|
||||
#include "unit_test.h"
|
||||
|
||||
#include <crypto/rijndael/rijndael-api-fst.h>
|
||||
#include <crypto/sha2/sha256.h>
|
||||
|
||||
#include <dev/random/hash.h>
|
||||
#include <dev/random/randomdev.h>
|
||||
#include <dev/random/uint128.h>
|
||||
#include <dev/random/other_algorithm.h>
|
||||
#endif /* _KERNEL */
|
||||
|
||||
static void random_other_pre_read(void);
|
||||
static void random_other_read(uint8_t *, u_int);
|
||||
@ -73,9 +93,7 @@ static void random_other_deinit_alg(void *);
|
||||
/*
|
||||
* RANDOM_OTHER_NPOOLS is used when reading hardware random
|
||||
* number sources to ensure that each pool gets one read sample
|
||||
* per loop iteration. Yarrow has 2 such pools (FAST and SLOW),
|
||||
* and fortuna has 32 (0-31). The RNG used prior to Yarrow and
|
||||
* ported from Linux had just 1 pool.
|
||||
* per loop iteration. Fortuna has 32 (0-31).
|
||||
*/
|
||||
#define RANDOM_OTHER_NPOOLS 1
|
||||
|
||||
|
@ -31,14 +31,13 @@
|
||||
* containing an alternative entropy-processing algorithm for random(4).
|
||||
*
|
||||
* The functions below should be completed with the appropriate code,
|
||||
* and the nearby yarrow.c and fortuna.c may be consulted for examples
|
||||
* of working code.
|
||||
* and the nearby fortuna.c may be consulted for examples of working code.
|
||||
*
|
||||
* The author is willing to provide reasonable help to those wishing to
|
||||
* write such a module for themselves. Please use the markm@ FreeBSD
|
||||
* email address, and ensure that you are developing this on a suitably
|
||||
* supported branch (This is currently 11-CURRENT, and will be no
|
||||
* older than 11-STABLE in the future).
|
||||
* supported branch (This is currently 12-CURRENT, and may be no
|
||||
* older than 12-STABLE in the future).
|
||||
*/
|
||||
|
||||
#ifndef SYS_DEV_RANDOM_OTHER_H_INCLUDED
|
||||
|
@ -140,7 +140,7 @@ static struct kproc_desc random_proc_kp = {
|
||||
&harvest_context.hc_kthread_proc,
|
||||
};
|
||||
|
||||
/* Pass the given event straight through to Fortuna/Yarrow/Whatever. */
|
||||
/* Pass the given event straight through to Fortuna/Whatever. */
|
||||
static __inline void
|
||||
random_harvestq_fast_process_event(struct harvest_event *event)
|
||||
{
|
||||
@ -178,7 +178,7 @@ random_kthread(void)
|
||||
/* XXX: FIX!! Increase the high-performance data rate? Need some measurements first. */
|
||||
for (i = 0; i < RANDOM_ACCUM_MAX; 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_UMA);
|
||||
random_harvest_direct(harvest_context.hc_entropy_fast_accumulator.buf + i, sizeof(harvest_context.hc_entropy_fast_accumulator.buf[0]), RANDOM_UMA);
|
||||
harvest_context.hc_entropy_fast_accumulator.buf[i] = 0;
|
||||
}
|
||||
}
|
||||
@ -197,8 +197,7 @@ SYSINIT(random_device_h_proc, SI_SUB_KICK_SCHEDULER, SI_ORDER_ANY, kproc_start,
|
||||
/*
|
||||
* Run through all fast sources reading entropy for the given
|
||||
* number of rounds, which should be a multiple of the number
|
||||
* of entropy accumulation pools in use; 2 for Yarrow and 32
|
||||
* for Fortuna.
|
||||
* of entropy accumulation pools in use; it is 32 for Fortuna.
|
||||
*/
|
||||
static void
|
||||
random_sources_feed(void)
|
||||
@ -234,7 +233,7 @@ random_sources_feed(void)
|
||||
printf("%s: rs_read for hardware device '%s' returned no entropy.\n", __func__, rrs->rrs_source->rs_ident);
|
||||
continue;
|
||||
}
|
||||
random_harvest_direct(entropy, n, (n*8)/2, rrs->rrs_source->rs_source);
|
||||
random_harvest_direct(entropy, n, rrs->rrs_source->rs_source);
|
||||
}
|
||||
}
|
||||
explicit_bzero(entropy, sizeof(entropy));
|
||||
@ -380,7 +379,7 @@ SYSINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_SECOND, random_harvestq_in
|
||||
/*
|
||||
* This is used to prime the RNG by grabbing any early random stuff
|
||||
* known to the kernel, and inserting it directly into the hashing
|
||||
* module, e.g. Fortuna or Yarrow.
|
||||
* module, currently Fortuna.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
@ -414,7 +413,6 @@ random_harvestq_prime(void *unused __unused)
|
||||
count = sizeof(event.he_entropy);
|
||||
event.he_somecounter = (uint32_t)get_cyclecount();
|
||||
event.he_size = count;
|
||||
event.he_bits = count/4; /* Underestimate the size for Yarrow */
|
||||
event.he_source = RANDOM_CACHED;
|
||||
event.he_destination = harvest_context.hc_destination[0]++;
|
||||
memcpy(event.he_entropy, data + i, sizeof(event.he_entropy));
|
||||
@ -459,8 +457,7 @@ SYSUNINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_SECOND, random_harvestq_
|
||||
* read which can be quite expensive.
|
||||
*/
|
||||
void
|
||||
random_harvest_queue_(const void *entropy, u_int size, u_int bits,
|
||||
enum random_entropy_source origin)
|
||||
random_harvest_queue_(const void *entropy, u_int size, enum random_entropy_source origin)
|
||||
{
|
||||
struct harvest_event *event;
|
||||
u_int ring_in;
|
||||
@ -474,7 +471,6 @@ random_harvest_queue_(const void *entropy, u_int size, u_int bits,
|
||||
event->he_somecounter = (uint32_t)get_cyclecount();
|
||||
event->he_source = origin;
|
||||
event->he_destination = harvest_context.hc_destination[origin]++;
|
||||
event->he_bits = bits;
|
||||
if (size <= sizeof(event->he_entropy)) {
|
||||
event->he_size = size;
|
||||
memcpy(event->he_entropy, entropy, size);
|
||||
@ -496,7 +492,7 @@ random_harvest_queue_(const void *entropy, u_int size, u_int bits,
|
||||
* This is the right place for high-rate harvested data.
|
||||
*/
|
||||
void
|
||||
random_harvest_fast_(const void *entropy, u_int size, u_int bits)
|
||||
random_harvest_fast_(const void *entropy, u_int size)
|
||||
{
|
||||
u_int pos;
|
||||
|
||||
@ -512,7 +508,7 @@ random_harvest_fast_(const void *entropy, u_int size, u_int bits)
|
||||
* (e.g.) booting when initial entropy is being gathered.
|
||||
*/
|
||||
void
|
||||
random_harvest_direct_(const void *entropy, u_int size, u_int bits, enum random_entropy_source origin)
|
||||
random_harvest_direct_(const void *entropy, u_int size, enum random_entropy_source origin)
|
||||
{
|
||||
struct harvest_event event;
|
||||
|
||||
@ -520,7 +516,6 @@ random_harvest_direct_(const void *entropy, u_int size, u_int bits, enum random_
|
||||
size = MIN(size, sizeof(event.he_entropy));
|
||||
event.he_somecounter = (uint32_t)get_cyclecount();
|
||||
event.he_size = size;
|
||||
event.he_bits = bits;
|
||||
event.he_source = origin;
|
||||
event.he_destination = harvest_context.hc_destination[origin]++;
|
||||
memcpy(event.he_entropy, entropy, size);
|
||||
|
@ -38,10 +38,9 @@ struct harvest_event {
|
||||
uint32_t he_somecounter; /* fast counter for clock jitter */
|
||||
uint32_t he_entropy[HARVESTSIZE];/* some harvested entropy */
|
||||
uint8_t he_size; /* harvested entropy byte count */
|
||||
uint8_t he_bits; /* stats about the entropy */
|
||||
uint8_t he_destination; /* destination pool of this entropy */
|
||||
uint8_t he_source; /* origin of the entropy */
|
||||
} __packed;
|
||||
};
|
||||
|
||||
void read_rate_increment(u_int);
|
||||
|
||||
|
@ -166,7 +166,7 @@ READ_RANDOM_UIO(struct uio *uio, bool nonblock)
|
||||
* Belt-and-braces.
|
||||
* Round up the read length to a crypto block size multiple,
|
||||
* which is what the underlying generator is expecting.
|
||||
* See the random_buf size requirements in the Yarrow/Fortuna code.
|
||||
* See the random_buf size requirements in the Fortuna code.
|
||||
*/
|
||||
read_len = roundup(read_len, RANDOM_BLOCKSIZE);
|
||||
/* Work in chunks page-sized or less */
|
||||
@ -250,7 +250,6 @@ randomdev_accumulate(uint8_t *buf, u_int count)
|
||||
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));
|
||||
|
@ -31,7 +31,6 @@
|
||||
|
||||
cc -g -O0 -pthread -DRANDOM_<alg> -I../.. -lstdthreads -Wall \
|
||||
unit_test.c \
|
||||
yarrow.c \
|
||||
fortuna.c \
|
||||
hash.c \
|
||||
../../crypto/rijndael/rijndael-api-fst.c \
|
||||
@ -41,7 +40,9 @@ cc -g -O0 -pthread -DRANDOM_<alg> -I../.. -lstdthreads -Wall \
|
||||
-o unit_test
|
||||
./unit_test
|
||||
|
||||
Where <alg> is YARROW or FORTUNA.
|
||||
Where <alg> is FORTUNA. The parameterisation is a leftover from
|
||||
when Yarrow was an option, and remains to enable the testing of
|
||||
possible future algorithms.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
@ -157,7 +158,6 @@ RunHarvester(void *arg __unused)
|
||||
e.he_somecounter = i;
|
||||
*((uint64_t *)e.he_entropy) = random();
|
||||
e.he_size = 8;
|
||||
e.he_bits = random()%4;
|
||||
e.he_destination = i;
|
||||
e.he_source = (i + 3)%7;
|
||||
e.he_next = NULL;
|
||||
|
@ -74,9 +74,8 @@ enum random_entropy_source {
|
||||
struct harvest_event {
|
||||
uintmax_t he_somecounter; /* fast counter for clock jitter */
|
||||
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 */
|
||||
uint8_t he_size; /* harvested entropy byte count */
|
||||
uint8_t he_destination; /* destination pool of this entropy */
|
||||
enum random_entropy_source he_source; /* origin of the entropy */
|
||||
void * he_next; /* next item on the list */
|
||||
};
|
||||
|
@ -1,395 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2000-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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/param.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/random.h>
|
||||
#include <sys/sdt.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
|
||||
#include <crypto/rijndael/rijndael-api-fst.h>
|
||||
#include <crypto/sha2/sha256.h>
|
||||
|
||||
#include <dev/random/hash.h>
|
||||
#include <dev/random/randomdev.h>
|
||||
#include <dev/random/random_harvestq.h>
|
||||
#include <dev/random/uint128.h>
|
||||
#include <dev/random/yarrow.h>
|
||||
#else /* !_KERNEL */
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <threads.h>
|
||||
|
||||
#include "unit_test.h"
|
||||
|
||||
#include <crypto/rijndael/rijndael-api-fst.h>
|
||||
#include <crypto/sha2/sha256.h>
|
||||
|
||||
#include <dev/random/hash.h>
|
||||
#include <dev/random/randomdev.h>
|
||||
#include <dev/random/uint128.h>
|
||||
#include <dev/random/yarrow.h>
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#define RANDOM_YARROW_TIMEBIN 16 /* max value for Pt/t */
|
||||
|
||||
#define RANDOM_YARROW_FAST 0
|
||||
#define RANDOM_YARROW_SLOW 1
|
||||
#define RANDOM_YARROW_NPOOLS 2
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Probes for dtrace(1) */
|
||||
SDT_PROVIDER_DECLARE(random);
|
||||
SDT_PROVIDER_DEFINE(random);
|
||||
SDT_PROBE_DEFINE3(random, yarrow, event_processor, debug, "boolean", "u_int", "struct ys_pool *");
|
||||
|
||||
/*
|
||||
* 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 {
|
||||
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 threshold */
|
||||
struct randomdev_hash ysp_hash; /* accumulated entropy */
|
||||
} ys_pool[RANDOM_YARROW_NPOOLS];/* pool[0] is fast, pool[1] is slow */
|
||||
bool ys_seeded;
|
||||
/* Reseed lock */
|
||||
mtx_t ys_mtx;
|
||||
} yarrow_state;
|
||||
|
||||
#ifdef _KERNEL
|
||||
static struct sysctl_ctx_list random_clist;
|
||||
RANDOM_CHECK_UINT(gengateinterval, 4, 64);
|
||||
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);
|
||||
#endif /* _KERNEL */
|
||||
|
||||
static void random_yarrow_pre_read(void);
|
||||
static void random_yarrow_read(uint8_t *, u_int);
|
||||
static bool random_yarrow_seeded(void);
|
||||
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);
|
||||
|
||||
struct random_algorithm random_alg_context = {
|
||||
.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_read = random_yarrow_read,
|
||||
.ra_seeded = random_yarrow_seeded,
|
||||
.ra_event_processor = random_yarrow_process_event,
|
||||
.ra_poolcount = RANDOM_YARROW_NPOOLS,
|
||||
};
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
random_yarrow_init_alg(void *unused __unused)
|
||||
{
|
||||
int i, j;
|
||||
#ifdef _KERNEL
|
||||
struct sysctl_oid *random_yarrow_o;
|
||||
#endif
|
||||
|
||||
RANDOM_RESEED_INIT_LOCK();
|
||||
/* Start unseeded, therefore blocked. */
|
||||
yarrow_state.ys_seeded = false;
|
||||
#ifdef _KERNEL
|
||||
/*
|
||||
* 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,
|
||||
SYSCTL_STATIC_CHILDREN(_kern_random),
|
||||
OID_AUTO, "yarrow", CTLFLAG_RW, 0,
|
||||
"Yarrow Parameters");
|
||||
SYSCTL_ADD_PROC(&random_clist,
|
||||
SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO,
|
||||
"gengateinterval", CTLTYPE_UINT | CTLFLAG_RWTUN,
|
||||
&yarrow_state.ys_gengateinterval, 0,
|
||||
random_check_uint_gengateinterval, "UI",
|
||||
"Generation gate interval");
|
||||
SYSCTL_ADD_PROC(&random_clist,
|
||||
SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO,
|
||||
"bins", CTLTYPE_UINT | CTLFLAG_RWTUN,
|
||||
&yarrow_state.ys_bins, 0,
|
||||
random_check_uint_bins, "UI",
|
||||
"Execution time tuner");
|
||||
SYSCTL_ADD_PROC(&random_clist,
|
||||
SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO,
|
||||
"fastthresh", CTLTYPE_UINT | CTLFLAG_RWTUN,
|
||||
&yarrow_state.ys_pool[0].ysp_thresh, 0,
|
||||
random_check_uint_fastthresh, "UI",
|
||||
"Fast reseed threshold");
|
||||
SYSCTL_ADD_PROC(&random_clist,
|
||||
SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO,
|
||||
"slowthresh", CTLTYPE_UINT | CTLFLAG_RWTUN,
|
||||
&yarrow_state.ys_pool[1].ysp_thresh, 0,
|
||||
random_check_uint_slowthresh, "UI",
|
||||
"Slow reseed threshold");
|
||||
SYSCTL_ADD_PROC(&random_clist,
|
||||
SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO,
|
||||
"slowoverthresh", CTLTYPE_UINT | CTLFLAG_RWTUN,
|
||||
&yarrow_state.ys_slowoverthresh, 0,
|
||||
random_check_uint_slowoverthresh, "UI",
|
||||
"Slow over-threshold reseed");
|
||||
#endif /* _KERNEL */
|
||||
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.ys_outputblocks = yarrow_state.ys_gengateinterval;
|
||||
/* Initialise the fast and slow entropy pools */
|
||||
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.ys_pool[i].ysp_source_bits[j] = 0;
|
||||
}
|
||||
/* Clear the counter */
|
||||
yarrow_state.ys_counter = UINT128_ZERO;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
random_yarrow_deinit_alg(void *unused __unused)
|
||||
{
|
||||
|
||||
RANDOM_RESEED_DEINIT_LOCK();
|
||||
explicit_bzero(&yarrow_state, sizeof(yarrow_state));
|
||||
#ifdef _KERNEL
|
||||
sysctl_ctx_free(&random_clist);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Process a single stochastic event off the harvest queue */
|
||||
static void
|
||||
random_yarrow_process_event(struct harvest_event *event)
|
||||
{
|
||||
u_int pl, overthreshhold[RANDOM_YARROW_NPOOLS];
|
||||
enum random_entropy_source src;
|
||||
|
||||
RANDOM_RESEED_LOCK();
|
||||
/*
|
||||
* 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 % 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;
|
||||
/* Count the over-threshold sources in each pool */
|
||||
for (pl = RANDOM_YARROW_FAST; pl <= RANDOM_YARROW_SLOW; pl++) {
|
||||
overthreshhold[pl] = 0;
|
||||
for (src = RANDOM_START; src < ENTROPYSOURCE; src++) {
|
||||
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 threshold, then slow reseed
|
||||
* else if any fast source over threshold, then fast reseed.
|
||||
*/
|
||||
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);
|
||||
explicit_bzero(event, sizeof(*event));
|
||||
RANDOM_RESEED_UNLOCK();
|
||||
}
|
||||
|
||||
static void
|
||||
random_yarrow_reseed_internal(u_int fastslow)
|
||||
{
|
||||
/*
|
||||
* Interrupt-context stack is a limited resource; make large
|
||||
* structures static.
|
||||
*/
|
||||
static uint8_t v[RANDOM_YARROW_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.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();
|
||||
SDT_PROBE3(random, yarrow, event_processor, debug, yarrow_state.ys_seeded, yarrow_state.ys_slowoverthresh, yarrow_state.ys_pool);
|
||||
/* 1. Hash the accumulated entropy into v[0] */
|
||||
randomdev_hash_init(&context);
|
||||
/* Feed the slow pool hash in if slow */
|
||||
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.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
|
||||
* intensive.
|
||||
*/
|
||||
if (yarrow_state.ys_bins > RANDOM_YARROW_TIMEBIN)
|
||||
yarrow_state.ys_bins = RANDOM_YARROW_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], RANDOM_KEYSIZE);
|
||||
/* v[i] #= h(v[0]) */
|
||||
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;
|
||||
* it is not being ignored!
|
||||
*/
|
||||
randomdev_hash_init(&context);
|
||||
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 */
|
||||
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.ys_pool[i].ysp_source_bits[j] = 0;
|
||||
/* 6. Wipe memory of intermediate values */
|
||||
explicit_bzero(v, sizeof(v));
|
||||
explicit_bzero(&temp, sizeof(temp));
|
||||
explicit_bzero(&context, sizeof(context));
|
||||
/* 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.
|
||||
*/
|
||||
seed_file = "<some file>";
|
||||
error = randomdev_write_file(seed_file, <generated entropy>, PAGE_SIZE);
|
||||
if (error == 0)
|
||||
printf("random: entropy seed file '%s' successfully written\n", seed_file);
|
||||
#endif
|
||||
/* Unblock the device if it was blocked due to being unseeded */
|
||||
if (!yarrow_state.ys_seeded) {
|
||||
yarrow_state.ys_seeded = true;
|
||||
randomdev_unblock();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
explicit_bzero(temp, sizeof(temp));
|
||||
}
|
||||
|
||||
/*-
|
||||
* Used to return processed entropy from the PRNG. There is a pre_read
|
||||
* required to be present (but it can be a stub) in order to allow
|
||||
* specific actions at the begin of the read.
|
||||
* Yarrow does its reseeding in its own thread; _pre_read() is not used
|
||||
* by Yarrow but must be kept for completeness.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
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();
|
||||
blockcount = howmany(bytecount, RANDOM_BLOCKSIZE);
|
||||
for (i = 0; i < blockcount; i++) {
|
||||
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;
|
||||
}
|
||||
RANDOM_RESEED_UNLOCK();
|
||||
}
|
||||
|
||||
bool
|
||||
random_yarrow_seeded(void)
|
||||
{
|
||||
|
||||
return (yarrow_state.ys_seeded);
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2000-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$
|
||||
*/
|
||||
|
||||
#ifndef 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(&yarrow_state.ys_mtx, "reseed mutex", NULL, MTX_DEF)
|
||||
#define RANDOM_RESEED_DEINIT_LOCK(x) mtx_destroy(&yarrow_state.ys_mtx)
|
||||
#define RANDOM_RESEED_LOCK(x) mtx_lock(&yarrow_state.ys_mtx)
|
||||
#define RANDOM_RESEED_UNLOCK(x) mtx_unlock(&yarrow_state.ys_mtx)
|
||||
#define RANDOM_RESEED_ASSERT_LOCK_OWNED(x) mtx_assert(&yarrow_state.ys_mtx, MA_OWNED)
|
||||
#else
|
||||
#define RANDOM_RESEED_INIT_LOCK(x) mtx_init(&yarrow_state.ys_mtx, mtx_plain)
|
||||
#define RANDOM_RESEED_DEINIT_LOCK(x) mtx_destroy(&yarrow_state.ys_mtx)
|
||||
#define RANDOM_RESEED_LOCK(x) mtx_lock(&yarrow_state.ys_mtx)
|
||||
#define RANDOM_RESEED_UNLOCK(x) mtx_unlock(&yarrow_state.ys_mtx)
|
||||
#define RANDOM_RESEED_ASSERT_LOCK_OWNED(x)
|
||||
#endif
|
||||
|
||||
#endif /* SYS_DEV_RANDOM_YARROW_H_INCLUDED */
|
@ -149,7 +149,7 @@ rndtest_harvest(struct rndtest_state *rsp, void *buf, u_int len)
|
||||
rndstats.rst_discard += len;
|
||||
else
|
||||
/* MarkM: FIX!! Check that this does not swamp the harvester! */
|
||||
random_harvest_queue(buf, len, len*NBBY/2, RANDOM_PURE_RNDTEST);
|
||||
random_harvest_queue(buf, len, RANDOM_PURE_RNDTEST);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -212,7 +212,7 @@ static void
|
||||
default_harvest(struct rndtest_state *rsp, void *buf, u_int count)
|
||||
{
|
||||
/* MarkM: FIX!! Check that this does not swamp the harvester! */
|
||||
random_harvest_queue(buf, count, count*NBBY/2, RANDOM_PURE_SAFE);
|
||||
random_harvest_queue(buf, count, RANDOM_PURE_SAFE);
|
||||
}
|
||||
#endif /* SAFE_NO_RNG */
|
||||
|
||||
|
@ -669,7 +669,7 @@ sc_mouse_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
|
||||
|
||||
mouse = (mouse_info_t*)data;
|
||||
|
||||
random_harvest_queue(mouse, sizeof(mouse_info_t), 2, RANDOM_MOUSE);
|
||||
random_harvest_queue(mouse, sizeof(mouse_info_t), RANDOM_MOUSE);
|
||||
|
||||
if (cmd == OLD_CONS_MOUSECTL) {
|
||||
static u_char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
|
||||
|
@ -3734,7 +3734,7 @@ scgetc(sc_softc_t *sc, u_int flags, struct sc_cnstate *sp)
|
||||
sc_touch_scrn_saver();
|
||||
|
||||
if (!(flags & SCGETC_CN))
|
||||
random_harvest_queue(&c, sizeof(c), 1, RANDOM_KEYBOARD);
|
||||
random_harvest_queue(&c, sizeof(c), RANDOM_KEYBOARD);
|
||||
|
||||
if (sc->kbd_open_level == 0 && scp->kbd_mode != K_XLATE)
|
||||
return KEYCHAR(c);
|
||||
|
@ -260,7 +260,7 @@ static void
|
||||
default_harvest(struct rndtest_state *rsp, void *buf, u_int count)
|
||||
{
|
||||
/* MarkM: FIX!! Check that this does not swamp the harvester! */
|
||||
random_harvest_queue(buf, count, count*NBBY/2, RANDOM_PURE_UBSEC);
|
||||
random_harvest_queue(buf, count, RANDOM_PURE_UBSEC);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -217,8 +217,7 @@ vtrnd_harvest(struct vtrnd_softc *sc)
|
||||
virtqueue_notify(vq);
|
||||
virtqueue_poll(vq, NULL);
|
||||
|
||||
random_harvest_queue(&value, sizeof(value), sizeof(value) * NBBY / 2,
|
||||
RANDOM_PURE_VIRTIO);
|
||||
random_harvest_queue(&value, sizeof(value), RANDOM_PURE_VIRTIO);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -815,7 +815,7 @@ vt_processkey(keyboard_t *kbd, struct vt_device *vd, int c)
|
||||
{
|
||||
struct vt_window *vw = vd->vd_curwindow;
|
||||
|
||||
random_harvest_queue(&c, sizeof(c), 1, RANDOM_KEYBOARD);
|
||||
random_harvest_queue(&c, sizeof(c), RANDOM_KEYBOARD);
|
||||
#if VT_ALT_TO_ESC_HACK
|
||||
if (c & RELKEY) {
|
||||
switch (c & ~RELKEY) {
|
||||
|
@ -214,7 +214,7 @@ sysmouse_process_event(mouse_info_t *mi)
|
||||
unsigned char buf[MOUSE_SYS_PACKETSIZE];
|
||||
int x, y, iy, z;
|
||||
|
||||
random_harvest_queue(mi, sizeof *mi, 2, RANDOM_MOUSE);
|
||||
random_harvest_queue(mi, sizeof *mi, RANDOM_MOUSE);
|
||||
|
||||
mtx_lock(&sysmouse_lock);
|
||||
switch (mi->operation) {
|
||||
|
@ -1823,7 +1823,7 @@ tmpfs_itimes(struct vnode *vp, const struct timespec *acc,
|
||||
TMPFS_NODE_UNLOCK(node);
|
||||
|
||||
/* XXX: FIX? The entropy here is desirable, but the harvesting may be expensive */
|
||||
random_harvest_queue(node, sizeof(*node), 1, RANDOM_FS_ATIME);
|
||||
random_harvest_queue(node, sizeof(*node), RANDOM_FS_ATIME);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -868,7 +868,7 @@ intr_event_schedule_thread(struct intr_event *ie)
|
||||
if (ie->ie_flags & IE_ENTROPY) {
|
||||
entropy.event = (uintptr_t)ie;
|
||||
entropy.td = ctd;
|
||||
random_harvest_queue(&entropy, sizeof(entropy), 2, RANDOM_INTERRUPT);
|
||||
random_harvest_queue(&entropy, sizeof(entropy), RANDOM_INTERRUPT);
|
||||
}
|
||||
|
||||
KASSERT(td->td_proc != NULL, ("ithread %s has no process", ie->ie_name));
|
||||
@ -958,7 +958,7 @@ swi_sched(void *cookie, int flags)
|
||||
|
||||
entropy.event = (uintptr_t)ih;
|
||||
entropy.td = curthread;
|
||||
random_harvest_queue(&entropy, sizeof(entropy), 1, RANDOM_SWI);
|
||||
random_harvest_queue(&entropy, sizeof(entropy), RANDOM_SWI);
|
||||
|
||||
/*
|
||||
* Set ih_need for this handler so that if the ithread is already
|
||||
|
@ -2925,6 +2925,7 @@ int
|
||||
device_attach(device_t dev)
|
||||
{
|
||||
uint64_t attachtime;
|
||||
uint16_t attachentropy;
|
||||
int error;
|
||||
|
||||
if (resource_disabled(dev->driver->name, dev->unit)) {
|
||||
@ -2951,19 +2952,11 @@ device_attach(device_t dev)
|
||||
return (error);
|
||||
}
|
||||
dev->flags |= DF_ATTACHED_ONCE;
|
||||
attachtime = get_cyclecount() - attachtime;
|
||||
/*
|
||||
* 4 bits per device is a reasonable value for desktop and server
|
||||
* hardware with good get_cyclecount() implementations, but WILL
|
||||
* need to be adjusted on other platforms.
|
||||
/* We only need the low bits of this time, but ranges from tens to thousands
|
||||
* have been seen, so keep 2 bytes' worth.
|
||||
*/
|
||||
#define RANDOM_PROBE_BIT_GUESS 4
|
||||
if (bootverbose)
|
||||
printf("random: harvesting attach, %zu bytes (%d bits) from %s%d\n",
|
||||
sizeof(attachtime), RANDOM_PROBE_BIT_GUESS,
|
||||
dev->driver->name, dev->unit);
|
||||
random_harvest_direct(&attachtime, sizeof(attachtime),
|
||||
RANDOM_PROBE_BIT_GUESS, RANDOM_ATTACH);
|
||||
attachentropy = (uint16_t)(get_cyclecount() - attachtime);
|
||||
random_harvest_direct(&attachentropy, sizeof(attachentropy), RANDOM_ATTACH);
|
||||
device_sysctl_update(dev);
|
||||
if (dev->busy)
|
||||
dev->state = DS_BUSY;
|
||||
|
@ -128,8 +128,7 @@ octeon_rnd_harvest(void *arg)
|
||||
for (i = 0; i < OCTEON_RND_WORDS; i++)
|
||||
sc->sc_entropy[i] = cvmx_rng_get_random64();
|
||||
/* MarkM: FIX!! Check that this does not swamp the harvester! */
|
||||
random_harvest_queue(sc->sc_entropy, sizeof sc->sc_entropy,
|
||||
(sizeof(sc->sc_entropy)*8)/2, RANDOM_PURE_OCTEON);
|
||||
random_harvest_queue(sc->sc_entropy, sizeof sc->sc_entropy, RANDOM_PURE_OCTEON);
|
||||
|
||||
callout_reset(&sc->sc_callout, hz * 5, octeon_rnd_harvest, sc);
|
||||
}
|
||||
|
@ -321,7 +321,6 @@ SUBDIR= \
|
||||
ral \
|
||||
${_ralfw} \
|
||||
${_random_fortuna} \
|
||||
${_random_yarrow} \
|
||||
${_random_other} \
|
||||
rc4 \
|
||||
${_rdma} \
|
||||
@ -435,7 +434,6 @@ SUBDIR+= opensolaris
|
||||
_crypto= crypto
|
||||
_cryptodev= cryptodev
|
||||
_random_fortuna=random_fortuna
|
||||
_random_yarrow= random_yarrow
|
||||
_random_other= random_other
|
||||
.endif
|
||||
.endif
|
||||
|
@ -1,11 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${SRCTOP}/sys/dev/random
|
||||
|
||||
KMOD = random_yarrow
|
||||
SRCS = randomdev.c hash.c yarrow.c
|
||||
SRCS += opt_param.h bus_if.h device_if.h
|
||||
SRCS += opt_ddb.h
|
||||
CFLAGS += -DRANDOM_LOADABLE
|
||||
|
||||
.include <bsd.kmod.mk>
|
@ -514,7 +514,7 @@ ether_input_internal(struct ifnet *ifp, struct mbuf *m)
|
||||
}
|
||||
eh = mtod(m, struct ether_header *);
|
||||
etype = ntohs(eh->ether_type);
|
||||
random_harvest_queue_ether(m, sizeof(*m), 2);
|
||||
random_harvest_queue_ether(m, sizeof(*m));
|
||||
|
||||
CURVNET_SET_QUIET(ifp->if_vnet);
|
||||
|
||||
|
@ -910,7 +910,7 @@ tunwrite(struct cdev *dev, struct uio *uio, int flag)
|
||||
m_freem(m);
|
||||
return (EAFNOSUPPORT);
|
||||
}
|
||||
random_harvest_queue(m, sizeof(*m), 2, RANDOM_NET_TUN);
|
||||
random_harvest_queue(m, sizeof(*m), RANDOM_NET_TUN);
|
||||
if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len);
|
||||
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
|
||||
CURVNET_SET(ifp->if_vnet);
|
||||
|
@ -720,7 +720,7 @@ ng_iface_rcvdata(hook_p hook, item_p item)
|
||||
m_freem(m);
|
||||
return (EAFNOSUPPORT);
|
||||
}
|
||||
random_harvest_queue(m, sizeof(*m), 2, RANDOM_NET_NG);
|
||||
random_harvest_queue(m, sizeof(*m), RANDOM_NET_NG);
|
||||
M_SETFIB(m, ifp->if_fib);
|
||||
netisr_dispatch(isr, m);
|
||||
return (0);
|
||||
|
@ -35,12 +35,6 @@
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#if !defined(KLD_MODULE)
|
||||
#if defined(RANDOM_LOADABLE) && defined(RANDOM_YARROW)
|
||||
#error "Cannot define both RANDOM_LOADABLE and RANDOM_YARROW"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct uio;
|
||||
|
||||
#if defined(DEV_RANDOM)
|
||||
@ -108,57 +102,54 @@ enum random_entropy_source {
|
||||
|
||||
#if defined(DEV_RANDOM)
|
||||
extern u_int hc_source_mask;
|
||||
void random_harvest_queue_(const void *, u_int, u_int, enum random_entropy_source);
|
||||
void random_harvest_fast_(const void *, u_int, u_int);
|
||||
void random_harvest_direct_(const void *, u_int, u_int, enum random_entropy_source);
|
||||
void random_harvest_queue_(const void *, u_int, enum random_entropy_source);
|
||||
void random_harvest_fast_(const void *, u_int);
|
||||
void random_harvest_direct_(const void *, u_int, enum random_entropy_source);
|
||||
|
||||
static __inline void
|
||||
random_harvest_queue(const void *entropy, u_int size, u_int bits,
|
||||
enum random_entropy_source origin)
|
||||
random_harvest_queue(const void *entropy, u_int size, enum random_entropy_source origin)
|
||||
{
|
||||
|
||||
if (hc_source_mask & (1 << origin))
|
||||
random_harvest_queue_(entropy, size, bits, origin);
|
||||
random_harvest_queue_(entropy, size, origin);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
random_harvest_fast(const void *entropy, u_int size, u_int bits,
|
||||
enum random_entropy_source origin)
|
||||
random_harvest_fast(const void *entropy, u_int size, enum random_entropy_source origin)
|
||||
{
|
||||
|
||||
if (hc_source_mask & (1 << origin))
|
||||
random_harvest_fast_(entropy, size, bits);
|
||||
random_harvest_fast_(entropy, size);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
random_harvest_direct(const void *entropy, u_int size, u_int bits,
|
||||
enum random_entropy_source origin)
|
||||
random_harvest_direct(const void *entropy, u_int size, enum random_entropy_source origin)
|
||||
{
|
||||
|
||||
if (hc_source_mask & (1 << origin))
|
||||
random_harvest_direct_(entropy, size, bits, origin);
|
||||
random_harvest_direct_(entropy, size, origin);
|
||||
}
|
||||
|
||||
void random_harvest_register_source(enum random_entropy_source);
|
||||
void random_harvest_deregister_source(enum random_entropy_source);
|
||||
#else
|
||||
#define random_harvest_queue(a, b, c, d) do {} while (0)
|
||||
#define random_harvest_fast(a, b, c, d) do {} while (0)
|
||||
#define random_harvest_direct(a, b, c, d) do {} while (0)
|
||||
#define random_harvest_queue(a, b, c) do {} while (0)
|
||||
#define random_harvest_fast(a, b, c) do {} while (0)
|
||||
#define random_harvest_direct(a, b, c) do {} while (0)
|
||||
#define random_harvest_register_source(a) do {} while (0)
|
||||
#define random_harvest_deregister_source(a) do {} while (0)
|
||||
#endif
|
||||
|
||||
#if defined(RANDOM_ENABLE_UMA)
|
||||
#define random_harvest_fast_uma(a, b, c, d) random_harvest_fast(a, b, c, d)
|
||||
#define random_harvest_fast_uma(a, b, c) random_harvest_fast(a, b, c)
|
||||
#else /* !defined(RANDOM_ENABLE_UMA) */
|
||||
#define random_harvest_fast_uma(a, b, c, d) do {} while (0)
|
||||
#define random_harvest_fast_uma(a, b, c) do {} while (0)
|
||||
#endif /* defined(RANDOM_ENABLE_UMA) */
|
||||
|
||||
#if defined(RANDOM_ENABLE_ETHER)
|
||||
#define random_harvest_queue_ether(a, b, c) random_harvest_queue(a, b, c, RANDOM_NET_ETHER)
|
||||
#define random_harvest_queue_ether(a, b) random_harvest_queue(a, b, RANDOM_NET_ETHER)
|
||||
#else /* !defined(RANDOM_ENABLE_ETHER) */
|
||||
#define random_harvest_queue_ether(a, b, c) do {} while (0)
|
||||
#define random_harvest_queue_ether(a, b) do {} while (0)
|
||||
#endif /* defined(RANDOM_ENABLE_ETHER) */
|
||||
|
||||
|
||||
|
@ -149,12 +149,12 @@ ffs_update(vp, waitfor)
|
||||
*((struct ufs1_dinode *)bp->b_data +
|
||||
ino_to_fsbo(fs, ip->i_number)) = *ip->i_din1;
|
||||
/* XXX: FIX? The entropy here is desirable, but the harvesting may be expensive */
|
||||
random_harvest_queue(&(ip->i_din1), sizeof(ip->i_din1), 1, RANDOM_FS_ATIME);
|
||||
random_harvest_queue(&(ip->i_din1), sizeof(ip->i_din1), RANDOM_FS_ATIME);
|
||||
} else {
|
||||
*((struct ufs2_dinode *)bp->b_data +
|
||||
ino_to_fsbo(fs, ip->i_number)) = *ip->i_din2;
|
||||
/* XXX: FIX? The entropy here is desirable, but the harvesting may be expensive */
|
||||
random_harvest_queue(&(ip->i_din2), sizeof(ip->i_din2), 1, RANDOM_FS_ATIME);
|
||||
random_harvest_queue(&(ip->i_din2), sizeof(ip->i_din2), RANDOM_FS_ATIME);
|
||||
}
|
||||
if (waitfor)
|
||||
error = bwrite(bp);
|
||||
|
@ -2363,7 +2363,7 @@ uma_zalloc_arg(uma_zone_t zone, void *udata, int flags)
|
||||
#endif
|
||||
|
||||
/* Enable entropy collection for RANDOM_ENABLE_UMA kernel option */
|
||||
random_harvest_fast_uma(&zone, sizeof(zone), 1, RANDOM_UMA);
|
||||
random_harvest_fast_uma(&zone, sizeof(zone), RANDOM_UMA);
|
||||
|
||||
/* This is the fast path allocation */
|
||||
CTR4(KTR_UMA, "uma_zalloc_arg thread %x zone %s(%p) flags %d",
|
||||
@ -2572,7 +2572,7 @@ uma_zalloc_domain(uma_zone_t zone, void *udata, int domain, int flags)
|
||||
{
|
||||
|
||||
/* Enable entropy collection for RANDOM_ENABLE_UMA kernel option */
|
||||
random_harvest_fast_uma(&zone, sizeof(zone), 1, RANDOM_UMA);
|
||||
random_harvest_fast_uma(&zone, sizeof(zone), RANDOM_UMA);
|
||||
|
||||
/* This is the fast path allocation */
|
||||
CTR5(KTR_UMA,
|
||||
@ -3032,7 +3032,7 @@ uma_zfree_arg(uma_zone_t zone, void *item, void *udata)
|
||||
#endif
|
||||
|
||||
/* Enable entropy collection for RANDOM_ENABLE_UMA kernel option */
|
||||
random_harvest_fast_uma(&zone, sizeof(zone), 1, RANDOM_UMA);
|
||||
random_harvest_fast_uma(&zone, sizeof(zone), RANDOM_UMA);
|
||||
|
||||
CTR2(KTR_UMA, "uma_zfree_arg thread %x zone %s", curthread,
|
||||
zone->uz_name);
|
||||
@ -3208,7 +3208,7 @@ uma_zfree_domain(uma_zone_t zone, void *item, void *udata)
|
||||
{
|
||||
|
||||
/* Enable entropy collection for RANDOM_ENABLE_UMA kernel option */
|
||||
random_harvest_fast_uma(&zone, sizeof(zone), 1, RANDOM_UMA);
|
||||
random_harvest_fast_uma(&zone, sizeof(zone), RANDOM_UMA);
|
||||
|
||||
CTR2(KTR_UMA, "uma_zfree_domain thread %x zone %s", curthread,
|
||||
zone->uz_name);
|
||||
|
@ -1121,21 +1121,6 @@ kern.random.sys.harvest.swi
|
||||
---
|
||||
kern.random.sys.seeded
|
||||
|
||||
---
|
||||
kern.random.yarrow.bins
|
||||
|
||||
---
|
||||
kern.random.yarrow.fastthresh
|
||||
|
||||
---
|
||||
kern.random.yarrow.gengateinterval
|
||||
|
||||
---
|
||||
kern.random.yarrow.slowoverthresh
|
||||
|
||||
---
|
||||
kern.random.yarrow.slowthresh
|
||||
|
||||
---
|
||||
kern.randompid
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user