Add DEV_RANDOM pseudo-option and use it to "include out" random(4)
if desired. Retire randomdev_none.c and introduce random_infra.c for resident infrastructure. Completely stub out random(4) calls in the "without DEV_RANDOM" case. Add RANDOM_LOADABLE option to allow loadable Yarrow/Fortuna/LocallyWritten algorithm. Add a skeleton "other" algorithm framework for folks to add their own processing code. NIST, anyone? Retire the RANDOM_DUMMY option. Build modules for Yarrow, Fortuna and "other". Use atomics for the live entropy rate-tracking. Convert ints to bools for the 'seeded' logic. Move _write() function from the algorithm-specific areas to randomdev.c Get rid of reseed() function - it is unused. Tidy up the opt_*.h includes. Update documentation for random(4) modules. Fix test program (reviewers, please leave this). Differential Revision: https://reviews.freebsd.org/D3354 Reviewed by: wblock,delphij,jmg,bjk Approved by: so (/dev/random blanket)
This commit is contained in:
parent
7a40703db9
commit
646041a89a
15
UPDATING
15
UPDATING
@ -31,6 +31,21 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW:
|
||||
disable the most expensive debugging functionality run
|
||||
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
|
||||
|
||||
20150817:
|
||||
Kernel-loadable modules for the random(4) device are back. To use
|
||||
them, the kernel must have
|
||||
|
||||
device random
|
||||
options RANDOM_LOADABLE
|
||||
|
||||
kldload(8) can then be used to load random_fortuna.ko
|
||||
or random_yarrow.ko. Please note that due to the indirect
|
||||
function calls that the loadable modules need to provide,
|
||||
the build-in variants will be slightly more efficient.
|
||||
|
||||
The random(4) kernel option RANDOM_DUMMY has been retired due to
|
||||
unpopularity. It was not all that useful anyway.
|
||||
|
||||
20150813:
|
||||
The WITHOUT_ELFTOOLCHAIN_TOOLS src.conf(5) knob has been retired.
|
||||
Control over building the ELF Tool Chain tools is now provided by
|
||||
|
@ -23,7 +23,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 30, 2015
|
||||
.Dd August 17, 2015
|
||||
.Dt RANDOM 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -31,6 +31,7 @@
|
||||
.Nd the entropy device
|
||||
.Sh SYNOPSIS
|
||||
.Cd "device random"
|
||||
.Cd "options RANDOM_LOADABLE"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
@ -133,15 +134,49 @@ The
|
||||
.Va kern.random.harvest.mask_bin
|
||||
and
|
||||
.Va kern.random.harvest.mask_symbolic
|
||||
sysctl
|
||||
can be used confirm
|
||||
that your choices are correct.
|
||||
sysctls
|
||||
can be used to confirm
|
||||
that the choices are correct.
|
||||
Note that disabled items
|
||||
in the latter item
|
||||
are listed in square brackets.
|
||||
See
|
||||
.Xr random_harvest 9
|
||||
for more on the harvesting of entropy.
|
||||
.Pp
|
||||
When
|
||||
.Cd "options RANDOM_LOADABLE"
|
||||
is used,
|
||||
the
|
||||
.Pa /dev/random
|
||||
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
|
||||
.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.
|
||||
This is because some functions
|
||||
must be locked against
|
||||
load and unload events,
|
||||
and also must be indirect calls
|
||||
to allow for removal.
|
||||
.Sh RANDOMNESS
|
||||
The use of randomness in the field of computing
|
||||
is a rather subtle issue because randomness means
|
||||
@ -294,7 +329,7 @@ It replaces the previous
|
||||
implementation,
|
||||
introduced in
|
||||
.Fx 5.0 .
|
||||
The older
|
||||
.Em Yarrow
|
||||
algorithm remains available
|
||||
as a compile-time fallback.
|
||||
The Yarrow algorithm
|
||||
is no longer supported
|
||||
by its authors,
|
||||
and is therefore deprecated.
|
||||
|
@ -2981,9 +2981,10 @@ 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 used.
|
||||
options RANDOM_YARROW # Yarrow CSPRNG (old default)
|
||||
#options RANDOM_DUMMY # Dummy CSPRNG that always blocks
|
||||
# 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.
|
||||
# For developers.
|
||||
options RANDOM_DEBUG # Extra debugging messages
|
||||
|
||||
|
@ -550,14 +550,14 @@ crypto/des/des_ecb.c optional crypto | ipsec | netsmb
|
||||
crypto/des/des_setkey.c optional crypto | ipsec | netsmb
|
||||
crypto/rc4/rc4.c optional netgraph_mppc_encryption | kgssapi
|
||||
crypto/rijndael/rijndael-alg-fst.c optional crypto | geom_bde | \
|
||||
ipsec | random random_yarrow | random !random_yarrow !random_dummy | wlan_ccmp
|
||||
crypto/rijndael/rijndael-api-fst.c optional geom_bde | random random_yarrow | random !random_yarrow !random_dummy
|
||||
ipsec | random !random_loadable | wlan_ccmp
|
||||
crypto/rijndael/rijndael-api-fst.c optional geom_bde | random !random_loadable
|
||||
crypto/rijndael/rijndael-api.c optional crypto | ipsec | wlan_ccmp
|
||||
crypto/sha1.c optional carp | crypto | ipsec | \
|
||||
netgraph_mppc_encryption | sctp
|
||||
crypto/sha2/sha2.c optional crypto | geom_bde | ipsec | random random_yarrow | random !random_yarrow !random_dummy | \
|
||||
crypto/sha2/sha2.c optional crypto | geom_bde | ipsec | random !random_loadable | \
|
||||
sctp | zfs
|
||||
crypto/sha2/sha256c.c optional crypto | geom_bde | ipsec | random random_yarrow | random !random_yarrow !random_dummy | \
|
||||
crypto/sha2/sha256c.c optional crypto | geom_bde | ipsec | random !random_loadable | \
|
||||
sctp | zfs
|
||||
crypto/siphash/siphash.c optional inet | inet6
|
||||
crypto/siphash/siphash_test.c optional inet | inet6
|
||||
@ -2314,12 +2314,14 @@ rt2860.fw optional rt2860fw | ralfw \
|
||||
compile-with "${NORMAL_FW}" \
|
||||
no-obj no-implicit-rule \
|
||||
clean "rt2860.fw"
|
||||
dev/random/randomdev_none.c optional !random
|
||||
dev/random/randomdev.c optional random
|
||||
dev/random/random_harvestq.c optional random random_yarrow | random !random_dummy
|
||||
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_dummy
|
||||
dev/random/hash.c optional random random_yarrow | random !random_dummy
|
||||
dev/random/fortuna.c optional random !random_yarrow !random_loadable
|
||||
dev/random/hash.c optional random random_yarrow | \
|
||||
random !random_yarrow !random_loadable
|
||||
dev/rc/rc.c optional rc
|
||||
dev/re/if_re.c optional re
|
||||
dev/rl/if_rl.c optional rl pci
|
||||
|
@ -711,6 +711,7 @@ DEV_PCI opt_pci.h
|
||||
DEV_PF opt_pf.h
|
||||
DEV_PFLOG opt_pf.h
|
||||
DEV_PFSYNC opt_pf.h
|
||||
DEV_RANDOM opt_global.h
|
||||
DEV_SPLASH opt_splash.h
|
||||
DEV_VLAN opt_vlan.h
|
||||
|
||||
@ -946,13 +947,14 @@ RCTL opt_global.h
|
||||
# The DEBUG option is in global.h as the random harvesting
|
||||
# puts probes all over the place, and it makes little sense
|
||||
# to pollute these headers with an extra include.
|
||||
# the DUMMY option is in global.h because it is used to
|
||||
# turn off harvesting all over the kernel.
|
||||
RANDOM_DEBUG opt_global.h
|
||||
RANDOM_DEBUG opt_random.h
|
||||
# Which CSPRNG hashes we get.
|
||||
# These are mutually exclusive. With neither, Fortuna is selected.
|
||||
RANDOM_DUMMY opt_global.h
|
||||
# If Yarrow is not chosen, Fortuna is selected.
|
||||
RANDOM_YARROW opt_random.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.
|
||||
RANDOM_LOADABLE opt_random.h
|
||||
|
||||
# Intel em(4) driver
|
||||
EM_MULTIQUEUE opt_em.h
|
||||
|
@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/random/fortuna.h>
|
||||
#else /* !_KERNEL */
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -124,9 +125,7 @@ static uint8_t zero_region[RANDOM_ZERO_BLOCKSIZE];
|
||||
|
||||
static void random_fortuna_pre_read(void);
|
||||
static void random_fortuna_read(uint8_t *, u_int);
|
||||
static void random_fortuna_write(uint8_t *, u_int);
|
||||
static void random_fortuna_reseed(void);
|
||||
static int random_fortuna_seeded(void);
|
||||
static bool random_fortuna_seeded(void);
|
||||
static void random_fortuna_process_event(struct harvest_event *);
|
||||
static void random_fortuna_init_alg(void *);
|
||||
static void random_fortuna_deinit_alg(void *);
|
||||
@ -139,8 +138,6 @@ struct random_algorithm random_alg_context = {
|
||||
.ra_deinit_alg = random_fortuna_deinit_alg,
|
||||
.ra_pre_read = random_fortuna_pre_read,
|
||||
.ra_read = random_fortuna_read,
|
||||
.ra_write = random_fortuna_write,
|
||||
.ra_reseed = random_fortuna_reseed,
|
||||
.ra_seeded = random_fortuna_seeded,
|
||||
.ra_event_processor = random_fortuna_process_event,
|
||||
.ra_poolcount = RANDOM_FORTUNA_NPOOLS,
|
||||
@ -420,43 +417,7 @@ random_fortuna_read(uint8_t *buf, u_int bytecount)
|
||||
RANDOM_RESEED_UNLOCK();
|
||||
}
|
||||
|
||||
/* Internal function to hand external entropy to the PRNG. */
|
||||
void
|
||||
random_fortuna_write(uint8_t *buf, u_int count)
|
||||
{
|
||||
static u_int destination = 0;
|
||||
struct harvest_event event;
|
||||
struct randomdev_hash hash;
|
||||
uint32_t entropy_data[RANDOM_KEYSIZE_WORDS], timestamp;
|
||||
int i;
|
||||
|
||||
/* Extra timing here is helpful to scrape scheduler timing entropy */
|
||||
randomdev_hash_init(&hash);
|
||||
timestamp = (uint32_t)get_cyclecount();
|
||||
randomdev_hash_iterate(&hash, ×tamp, sizeof(timestamp));
|
||||
randomdev_hash_iterate(&hash, buf, count);
|
||||
timestamp = (uint32_t)get_cyclecount();
|
||||
randomdev_hash_iterate(&hash, ×tamp, sizeof(timestamp));
|
||||
randomdev_hash_finish(&hash, entropy_data);
|
||||
explicit_bzero(&hash, sizeof(hash));
|
||||
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));
|
||||
}
|
||||
|
||||
void
|
||||
random_fortuna_reseed(void)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
bool
|
||||
random_fortuna_seeded(void)
|
||||
{
|
||||
|
||||
|
209
sys/dev/random/other_algorithm.c
Normal file
209
sys/dev/random/other_algorithm.c
Normal file
@ -0,0 +1,209 @@
|
||||
/*-
|
||||
* Copyright (c) 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*-
|
||||
* This is a skeleton for folks who wish to build a loadable module
|
||||
* 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.
|
||||
*
|
||||
* 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).
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/random.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
|
||||
#include <crypto/rijndael/rijndael-api-fst.h>
|
||||
#include <crypto/sha2/sha2.h>
|
||||
|
||||
#include <dev/random/hash.h>
|
||||
#include <dev/random/randomdev.h>
|
||||
#include <dev/random/random_harvestq.h>
|
||||
#include <dev/random/uint128.h>
|
||||
#include <dev/random/other_algorithm.h>
|
||||
|
||||
static void random_other_pre_read(void);
|
||||
static void random_other_read(uint8_t *, u_int);
|
||||
static bool random_other_seeded(void);
|
||||
static void random_other_process_event(struct harvest_event *);
|
||||
static void random_other_init_alg(void *);
|
||||
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.
|
||||
*/
|
||||
#define RANDOM_OTHER_NPOOLS 1
|
||||
|
||||
struct random_algorithm random_alg_context = {
|
||||
.ra_ident = "other",
|
||||
.ra_init_alg = random_other_init_alg,
|
||||
.ra_deinit_alg = random_other_deinit_alg,
|
||||
.ra_pre_read = random_other_pre_read,
|
||||
.ra_read = random_other_read,
|
||||
.ra_seeded = random_other_seeded,
|
||||
.ra_event_processor = random_other_process_event,
|
||||
.ra_poolcount = RANDOM_OTHER_NPOOLS,
|
||||
};
|
||||
|
||||
/* Use a mutex to protect your reseed variables? */
|
||||
static mtx_t other_mtx;
|
||||
|
||||
/*
|
||||
* void random_other_init_alg(void *unused __unused)
|
||||
*
|
||||
* Do algorithm-specific initialisation here.
|
||||
*/
|
||||
void
|
||||
random_other_init_alg(void *unused __unused)
|
||||
{
|
||||
|
||||
RANDOM_RESEED_INIT_LOCK();
|
||||
/*
|
||||
* Do set-up work here!
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* void random_other_deinit_alg(void *unused __unused)
|
||||
*
|
||||
* Do algorithm-specific deinitialisation here.
|
||||
*/
|
||||
static void
|
||||
random_other_deinit_alg(void *unused __unused)
|
||||
{
|
||||
|
||||
/*
|
||||
* Do tear-down work here!
|
||||
*/
|
||||
RANDOM_RESEED_DEINIT_LOCK();
|
||||
}
|
||||
|
||||
/*
|
||||
* void random_other_pre_read(void)
|
||||
*
|
||||
* Do any pre-read preparation you need to. This will be called
|
||||
* before >=1 calls to random_other_read() corresponding to one
|
||||
* read(2).
|
||||
*
|
||||
* This routine will be called periodically while the generator is
|
||||
* still blocked and a read is being attempted, giving you an
|
||||
* opportunity to unblock.
|
||||
*/
|
||||
static void
|
||||
random_other_pre_read(void)
|
||||
{
|
||||
|
||||
RANDOM_RESEED_LOCK();
|
||||
/*
|
||||
* Do pre-read housekeeping work here!
|
||||
* You may use this as a chance to unblock the generator.
|
||||
*/
|
||||
RANDOM_RESEED_UNLOCK();
|
||||
}
|
||||
|
||||
/*
|
||||
* void random_other_read(uint8_t *buf, u_int count)
|
||||
*
|
||||
* Generate <count> bytes of output into <*buf>.
|
||||
* You may use the fact that <count> will be a multiple of
|
||||
* RANDOM_BLOCKSIZE for optimization purposes.
|
||||
*
|
||||
* This function will always be called with your generator
|
||||
* unblocked and ready. If you are not ready to generate
|
||||
* output here, then feel free to KASSERT() or panic().
|
||||
*/
|
||||
static void
|
||||
random_other_read(uint8_t *buf, u_int count)
|
||||
{
|
||||
|
||||
RANDOM_RESEED_LOCK();
|
||||
/*
|
||||
* Do random-number generation work here!
|
||||
*/
|
||||
RANDOM_RESEED_UNLOCK();
|
||||
}
|
||||
|
||||
/*
|
||||
* bool random_other_seeded(void)
|
||||
*
|
||||
* Return true if your generator is ready to generate
|
||||
* output, and false otherwise.
|
||||
*/
|
||||
static bool
|
||||
random_other_seeded(void)
|
||||
{
|
||||
bool seeded = false;
|
||||
|
||||
/*
|
||||
* Find out if your generator is seeded here!
|
||||
*/
|
||||
return (seeded);
|
||||
}
|
||||
|
||||
/*
|
||||
* void random_other_process_event(struct harvest_event *event)
|
||||
*
|
||||
* Process one stochastic event <*event> into your entropy
|
||||
* processor.
|
||||
*
|
||||
* The structure of the event may change, so it is easier to
|
||||
* just grab the whole thing into your accumulation system.
|
||||
* You may pick-and-choose bits, but please don't complain
|
||||
* when/if these change.
|
||||
*/
|
||||
static void
|
||||
random_other_process_event(struct harvest_event *event)
|
||||
{
|
||||
|
||||
RANDOM_RESEED_LOCK();
|
||||
/*
|
||||
* Do entropy accumulation work here!
|
||||
* You may use this as a chance to unblock the generator.
|
||||
*/
|
||||
RANDOM_RESEED_UNLOCK();
|
||||
}
|
62
sys/dev/random/other_algorithm.h
Normal file
62
sys/dev/random/other_algorithm.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*-
|
||||
* Copyright (c) 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$
|
||||
*/
|
||||
|
||||
/*-
|
||||
* This is a skeleton for folks who wish to build a loadable module
|
||||
* 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.
|
||||
*
|
||||
* 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).
|
||||
*/
|
||||
|
||||
#ifndef SYS_DEV_RANDOM_OTHER_H_INCLUDED
|
||||
#define SYS_DEV_RANDOM_OTHER_H_INCLUDED
|
||||
|
||||
#ifdef _KERNEL
|
||||
typedef struct mtx mtx_t;
|
||||
#define RANDOM_RESEED_INIT_LOCK(x) mtx_init(&other_mtx, "reseed mutex", NULL, MTX_DEF)
|
||||
#define RANDOM_RESEED_DEINIT_LOCK(x) mtx_destroy(&other_mtx)
|
||||
#define RANDOM_RESEED_LOCK(x) mtx_lock(&other_mtx)
|
||||
#define RANDOM_RESEED_UNLOCK(x) mtx_unlock(&other_mtx)
|
||||
#define RANDOM_RESEED_ASSERT_LOCK_OWNED(x) mtx_assert(&other_mtx, MA_OWNED)
|
||||
#else
|
||||
#define RANDOM_RESEED_INIT_LOCK(x) mtx_init(&other_mtx, mtx_plain)
|
||||
#define RANDOM_RESEED_DEINIT_LOCK(x) mtx_destroy(&other_mtx)
|
||||
#define RANDOM_RESEED_LOCK(x) mtx_lock(&other_mtx)
|
||||
#define RANDOM_RESEED_UNLOCK(x) mtx_unlock(&other_mtx)
|
||||
#define RANDOM_RESEED_ASSERT_LOCK_OWNED(x)
|
||||
#endif
|
||||
|
||||
#endif /* SYS_DEV_RANDOM_OTHER_H_INCLUDED */
|
@ -47,12 +47,21 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/unistd.h>
|
||||
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
#include <sys/lock.h>
|
||||
#include <sys/sx.h>
|
||||
#endif
|
||||
|
||||
#include <machine/atomic.h>
|
||||
#include <machine/cpu.h>
|
||||
|
||||
#include <dev/random/randomdev.h>
|
||||
#include <dev/random/random_harvestq.h>
|
||||
|
||||
static void random_kthread(void);
|
||||
static void random_sources_feed(void);
|
||||
|
||||
static u_int read_rate;
|
||||
|
||||
/* List for the dynamic sysctls */
|
||||
static struct sysctl_ctx_list random_clist;
|
||||
@ -66,7 +75,7 @@ static struct sysctl_ctx_list random_clist;
|
||||
#define RANDOM_RING_MAX 1024
|
||||
#define RANDOM_ACCUM_MAX 8
|
||||
|
||||
/* 1 to let the kernel thread run, 0 to terminate */
|
||||
/* 1 to let the kernel thread run, 0 to terminate, -1 to mark completion */
|
||||
volatile int random_kthread_control;
|
||||
|
||||
/*
|
||||
@ -123,13 +132,18 @@ static struct kproc_desc random_proc_kp = {
|
||||
&harvest_context.hc_kthread_proc,
|
||||
};
|
||||
|
||||
|
||||
/* Pass the given event straight through to Fortuna/Yarrow/Whatever. */
|
||||
static __inline void
|
||||
random_harvestq_fast_process_event(struct harvest_event *event)
|
||||
{
|
||||
if (random_alg_context.ra_event_processor)
|
||||
random_alg_context.ra_event_processor(event);
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
RANDOM_CONFIG_S_LOCK();
|
||||
if (p_random_alg_context)
|
||||
#endif
|
||||
p_random_alg_context->ra_event_processor(event);
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
RANDOM_CONFIG_S_UNLOCK();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
@ -163,12 +177,58 @@ random_kthread(void)
|
||||
/* XXX: FIX!! This is a *great* place to pass hardware/live entropy to random(9) */
|
||||
tsleep_sbt(&harvest_context.hc_kthread_proc, 0, "-", SBT_1S/10, 0, C_PREL(1));
|
||||
}
|
||||
random_kthread_control = -1;
|
||||
wakeup(&harvest_context.hc_kthread_proc);
|
||||
kproc_exit(0);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
/* This happens well after SI_SUB_RANDOM */
|
||||
SYSINIT(random_device_h_proc, SI_SUB_CREATE_INIT, SI_ORDER_ANY, kproc_start, &random_proc_kp);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
static void
|
||||
random_sources_feed(void)
|
||||
{
|
||||
uint32_t entropy[HARVESTSIZE];
|
||||
struct random_sources *rrs;
|
||||
u_int i, n, local_read_rate;
|
||||
|
||||
/*
|
||||
* Step over all of live entropy sources, and feed their output
|
||||
* to the system-wide RNG.
|
||||
*/
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
RANDOM_CONFIG_S_LOCK();
|
||||
if (p_random_alg_context) {
|
||||
/* It's an indenting error. Yeah, Yeah. */
|
||||
#endif
|
||||
local_read_rate = atomic_readandclear_32(&read_rate);
|
||||
LIST_FOREACH(rrs, &source_list, rrs_entries) {
|
||||
for (i = 0; i < p_random_alg_context->ra_poolcount*(local_read_rate + 1); i++) {
|
||||
n = rrs->rrs_source->rs_read(entropy, sizeof(entropy));
|
||||
KASSERT((n > 0 && n <= sizeof(entropy)), ("very bad return from rs_read (= %d) in %s", n, __func__));
|
||||
random_harvest_direct(entropy, n, (n*8)/2, rrs->rrs_source->rs_source);
|
||||
}
|
||||
}
|
||||
explicit_bzero(entropy, sizeof(entropy));
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
}
|
||||
RANDOM_CONFIG_S_UNLOCK();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
read_rate_increment(u_int chunk)
|
||||
{
|
||||
|
||||
atomic_add_32(&read_rate, chunk);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
RANDOM_CHECK_UINT(harvestmask, 0, RANDOM_HARVEST_EVERYTHING_MASK);
|
||||
|
||||
@ -317,7 +377,8 @@ random_harvestq_deinit(void *unused __unused)
|
||||
|
||||
/* Command the hash/reseed thread to end and wait for it to finish */
|
||||
random_kthread_control = 0;
|
||||
tsleep(&harvest_context.hc_kthread_proc, 0, "harvqterm", 0);
|
||||
while (random_kthread_control >= 0)
|
||||
tsleep(&harvest_context.hc_kthread_proc, 0, "harvqterm", hz/5);
|
||||
sysctl_ctx_free(&random_clist);
|
||||
}
|
||||
SYSUNINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_SECOND, random_harvestq_deinit, NULL);
|
||||
@ -412,3 +473,5 @@ random_harvest_direct(const void *entropy, u_int size, u_int bits, enum random_e
|
||||
random_harvestq_fast_process_event(&event);
|
||||
explicit_bzero(&event, sizeof(event));
|
||||
}
|
||||
|
||||
MODULE_VERSION(random_harvestq, 1);
|
||||
|
@ -43,6 +43,8 @@ struct harvest_event {
|
||||
uint8_t he_source; /* origin of the entropy */
|
||||
} __packed;
|
||||
|
||||
void read_rate_increment(u_int);
|
||||
|
||||
#define RANDOM_HARVESTQ_BOOT_ENTROPY_FILE "/boot/entropy"
|
||||
|
||||
#define RANDOM_HARVEST_INIT_LOCK(x) mtx_init(&harvest_context.hc_mtx, "entropy harvest mutex", NULL, MTX_SPIN)
|
||||
|
128
sys/dev/random/random_infra.c
Normal file
128
sys/dev/random/random_infra.c
Normal file
@ -0,0 +1,128 @@
|
||||
/*-
|
||||
* Copyright (c) 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$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/random.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
#include <sys/lock.h>
|
||||
#include <sys/sx.h>
|
||||
#endif
|
||||
|
||||
#include <dev/random/randomdev.h>
|
||||
|
||||
/* Set up the sysctl root node for the entropy device */
|
||||
SYSCTL_NODE(_kern, OID_AUTO, random, CTLFLAG_RW, 0, "Cryptographically Secure Random Number Generator");
|
||||
|
||||
MALLOC_DEFINE(M_ENTROPY, "entropy", "Entropy harvesting buffers and data structures");
|
||||
|
||||
struct sources_head source_list = LIST_HEAD_INITIALIZER(source_list);
|
||||
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
struct random_algorithm *p_random_alg_context = NULL;
|
||||
#else /* !defined(RANDOM_LOADABLE) */
|
||||
struct random_algorithm *p_random_alg_context = &random_alg_context;
|
||||
#endif /* defined(RANDOM_LOADABLE) */
|
||||
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
|
||||
struct random_readers {
|
||||
int (*read_random_uio)(struct uio *, bool);
|
||||
u_int (*read_random)(void *, u_int);
|
||||
} random_reader_context = {
|
||||
(int (*)(struct uio *, bool))nullop,
|
||||
(u_int (*)(void *, u_int))nullop,
|
||||
};
|
||||
|
||||
struct sx randomdev_config_lock;
|
||||
|
||||
static void
|
||||
random_infra_sysinit(void *dummy __unused)
|
||||
{
|
||||
|
||||
RANDOM_CONFIG_INIT_LOCK();
|
||||
}
|
||||
SYSINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_FIRST, random_infra_sysinit, NULL);
|
||||
|
||||
void
|
||||
random_infra_init(int (*p_random_read_uio)(struct uio *, bool), u_int (*p_random_read)(void *, u_int))
|
||||
{
|
||||
|
||||
RANDOM_CONFIG_X_LOCK();
|
||||
random_reader_context.read_random_uio = p_random_read_uio;
|
||||
random_reader_context.read_random = p_random_read;
|
||||
RANDOM_CONFIG_X_UNLOCK();
|
||||
}
|
||||
|
||||
void
|
||||
random_infra_uninit(void)
|
||||
{
|
||||
|
||||
RANDOM_CONFIG_X_LOCK();
|
||||
random_reader_context.read_random_uio = (int (*)(struct uio *, bool))nullop;
|
||||
random_reader_context.read_random = (u_int (*)(void *, u_int))nullop;
|
||||
RANDOM_CONFIG_X_UNLOCK();
|
||||
}
|
||||
|
||||
static void
|
||||
random_infra_sysuninit(void *dummy __unused)
|
||||
{
|
||||
|
||||
RANDOM_CONFIG_DEINIT_LOCK();
|
||||
}
|
||||
SYSUNINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_FIRST, random_infra_sysuninit, NULL);
|
||||
|
||||
int
|
||||
read_random_uio(struct uio *uio, bool nonblock)
|
||||
{
|
||||
int retval;
|
||||
|
||||
RANDOM_CONFIG_S_LOCK();
|
||||
retval = random_reader_context.read_random_uio(uio, nonblock);
|
||||
RANDOM_CONFIG_S_UNLOCK();
|
||||
return (retval);
|
||||
}
|
||||
|
||||
u_int
|
||||
read_random(void *buf, u_int len)
|
||||
{
|
||||
u_int retval;
|
||||
|
||||
RANDOM_CONFIG_S_LOCK();
|
||||
retval = random_reader_context.read_random(buf, len);
|
||||
RANDOM_CONFIG_S_UNLOCK();
|
||||
return (retval);
|
||||
}
|
||||
|
||||
#endif /* defined(RANDOM_LOADABLE) */
|
@ -56,14 +56,18 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/random/randomdev.h>
|
||||
#include <dev/random/random_harvestq.h>
|
||||
|
||||
#include "opt_random.h"
|
||||
|
||||
#if defined(RANDOM_DUMMY) && defined(RANDOM_YARROW)
|
||||
#error "Cannot define both RANDOM_DUMMY and RANDOM_YARROW"
|
||||
#endif
|
||||
|
||||
#define RANDOM_UNIT 0
|
||||
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
#define READ_RANDOM_UIO _read_random_uio
|
||||
#define READ_RANDOM _read_random
|
||||
static int READ_RANDOM_UIO(struct uio *, bool);
|
||||
static u_int READ_RANDOM(void *, u_int);
|
||||
#else
|
||||
#define READ_RANDOM_UIO read_random_uio
|
||||
#define READ_RANDOM read_random
|
||||
#endif
|
||||
|
||||
/* Return the largest number >= x that is a multiple of m */
|
||||
#define CEIL_TO_MULTIPLE(x, m) ((((x) + (m) - 1)/(m))*(m))
|
||||
|
||||
@ -84,68 +88,31 @@ static struct cdevsw random_cdevsw = {
|
||||
/* For use with make_dev(9)/destroy_dev(9). */
|
||||
static struct cdev *random_dev;
|
||||
|
||||
/* Set up the sysctl root node for the entropy device */
|
||||
SYSCTL_NODE(_kern, OID_AUTO, random, CTLFLAG_RW, 0, "Cryptographically Secure Random Number Generator");
|
||||
|
||||
MALLOC_DEFINE(M_ENTROPY, "entropy", "Entropy harvesting buffers and data structures");
|
||||
|
||||
#if defined(RANDOM_DUMMY)
|
||||
|
||||
/*-
|
||||
* Dummy "always block" pseudo algorithm, used when there is no real
|
||||
* random(4) driver to provide a CSPRNG.
|
||||
*/
|
||||
|
||||
static u_int
|
||||
dummy_random_zero(void)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
dummy_random(void)
|
||||
{
|
||||
}
|
||||
|
||||
struct random_algorithm random_alg_context = {
|
||||
.ra_ident = "Dummy",
|
||||
.ra_init_alg = NULL,
|
||||
.ra_deinit_alg = NULL,
|
||||
.ra_pre_read = dummy_random,
|
||||
.ra_read = (random_alg_read_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_poolcount = 0,
|
||||
};
|
||||
|
||||
#else /* !defined(RANDOM_DUMMY) */
|
||||
|
||||
LIST_HEAD(sources_head, random_sources);
|
||||
static struct sources_head source_list = LIST_HEAD_INITIALIZER(source_list);
|
||||
static u_int read_rate;
|
||||
|
||||
static void
|
||||
random_alg_context_ra_init_alg(void *data)
|
||||
{
|
||||
|
||||
random_alg_context.ra_init_alg(data);
|
||||
p_random_alg_context = &random_alg_context;
|
||||
p_random_alg_context->ra_init_alg(data);
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
random_infra_init(READ_RANDOM_UIO, READ_RANDOM);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
random_alg_context_ra_deinit_alg(void *data)
|
||||
{
|
||||
|
||||
random_alg_context.ra_deinit_alg(data);
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
random_infra_uninit();
|
||||
#endif
|
||||
p_random_alg_context->ra_deinit_alg(data);
|
||||
p_random_alg_context = NULL;
|
||||
}
|
||||
|
||||
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) */
|
||||
|
||||
static struct selinfo rsel;
|
||||
|
||||
/*
|
||||
@ -156,28 +123,28 @@ static int
|
||||
randomdev_read(struct cdev *dev __unused, struct uio *uio, int flags)
|
||||
{
|
||||
|
||||
return (read_random_uio(uio, (flags & O_NONBLOCK) != 0));
|
||||
return (READ_RANDOM_UIO(uio, (flags & O_NONBLOCK) != 0));
|
||||
}
|
||||
|
||||
int
|
||||
read_random_uio(struct uio *uio, bool nonblock)
|
||||
READ_RANDOM_UIO(struct uio *uio, bool nonblock)
|
||||
{
|
||||
uint8_t *random_buf;
|
||||
int error, spamcount;
|
||||
ssize_t read_len, total_read, c;
|
||||
|
||||
random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK);
|
||||
random_alg_context.ra_pre_read();
|
||||
p_random_alg_context->ra_pre_read();
|
||||
error = 0;
|
||||
spamcount = 0;
|
||||
/* (Un)Blocking logic */
|
||||
while (!random_alg_context.ra_seeded()) {
|
||||
while (!p_random_alg_context->ra_seeded()) {
|
||||
if (nonblock) {
|
||||
error = EWOULDBLOCK;
|
||||
break;
|
||||
}
|
||||
/* keep tapping away at the pre-read until we seed/unblock. */
|
||||
random_alg_context.ra_pre_read();
|
||||
p_random_alg_context->ra_pre_read();
|
||||
/* Only bother the console every 10 seconds or so */
|
||||
if (spamcount == 0)
|
||||
printf("random: %s unblock wait\n", __func__);
|
||||
@ -187,10 +154,7 @@ read_random_uio(struct uio *uio, bool nonblock)
|
||||
break;
|
||||
}
|
||||
if (error == 0) {
|
||||
#if !defined(RANDOM_DUMMY)
|
||||
/* XXX: FIX!! Next line as an atomic operation? */
|
||||
read_rate += (uio->uio_resid + sizeof(uint32_t))/sizeof(uint32_t);
|
||||
#endif
|
||||
read_rate_increment((uio->uio_resid + sizeof(uint32_t))/sizeof(uint32_t));
|
||||
total_read = 0;
|
||||
while (uio->uio_resid && !error) {
|
||||
read_len = uio->uio_resid;
|
||||
@ -203,7 +167,7 @@ read_random_uio(struct uio *uio, bool nonblock)
|
||||
read_len = CEIL_TO_MULTIPLE(read_len, RANDOM_BLOCKSIZE);
|
||||
/* Work in chunks page-sized or less */
|
||||
read_len = MIN(read_len, PAGE_SIZE);
|
||||
random_alg_context.ra_read(random_buf, read_len);
|
||||
p_random_alg_context->ra_read(random_buf, read_len);
|
||||
c = MIN(uio->uio_resid, read_len);
|
||||
error = uiomove(random_buf, c, uio);
|
||||
total_read += c;
|
||||
@ -224,19 +188,16 @@ read_random_uio(struct uio *uio, bool nonblock)
|
||||
* RANDOM_BLOCKSIZE bytes.
|
||||
*/
|
||||
u_int
|
||||
read_random(void *random_buf, u_int len)
|
||||
READ_RANDOM(void *random_buf, u_int len)
|
||||
{
|
||||
u_int read_len;
|
||||
uint8_t local_buf[len + RANDOM_BLOCKSIZE];
|
||||
|
||||
KASSERT(random_buf != NULL, ("No suitable random buffer in %s", __func__));
|
||||
random_alg_context.ra_pre_read();
|
||||
p_random_alg_context->ra_pre_read();
|
||||
/* (Un)Blocking logic; if not seeded, return nothing. */
|
||||
if (random_alg_context.ra_seeded()) {
|
||||
#if !defined(RANDOM_DUMMY)
|
||||
/* XXX: FIX!! Next line as an atomic operation? */
|
||||
read_rate += (len + sizeof(uint32_t))/sizeof(uint32_t);
|
||||
#endif
|
||||
if (p_random_alg_context->ra_seeded()) {
|
||||
read_rate_increment((len + sizeof(uint32_t))/sizeof(uint32_t));
|
||||
if (len > 0) {
|
||||
/*
|
||||
* Belt-and-braces.
|
||||
@ -244,7 +205,7 @@ read_random(void *random_buf, u_int len)
|
||||
* which is what the underlying generator is expecting.
|
||||
*/
|
||||
read_len = CEIL_TO_MULTIPLE(len, RANDOM_BLOCKSIZE);
|
||||
random_alg_context.ra_read(local_buf, read_len);
|
||||
p_random_alg_context->ra_read(local_buf, read_len);
|
||||
memcpy(random_buf, local_buf, len);
|
||||
}
|
||||
} else
|
||||
@ -252,6 +213,37 @@ read_random(void *random_buf, u_int len)
|
||||
return (len);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
randomdev_accumulate(uint8_t *buf, u_int count)
|
||||
{
|
||||
static u_int destination = 0;
|
||||
static struct harvest_event event;
|
||||
static struct randomdev_hash hash;
|
||||
static uint32_t entropy_data[RANDOM_KEYSIZE_WORDS];
|
||||
uint32_t timestamp;
|
||||
int i;
|
||||
|
||||
/* Extra timing here is helpful to scrape scheduler jitter entropy */
|
||||
randomdev_hash_init(&hash);
|
||||
timestamp = (uint32_t)get_cyclecount();
|
||||
randomdev_hash_iterate(&hash, ×tamp, sizeof(timestamp));
|
||||
randomdev_hash_iterate(&hash, buf, count);
|
||||
timestamp = (uint32_t)get_cyclecount();
|
||||
randomdev_hash_iterate(&hash, ×tamp, sizeof(timestamp));
|
||||
randomdev_hash_finish(&hash, entropy_data);
|
||||
explicit_bzero(&hash, sizeof(hash));
|
||||
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));
|
||||
p_random_alg_context->ra_event_processor(&event);
|
||||
}
|
||||
explicit_bzero(entropy_data, sizeof(entropy_data));
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
randomdev_write(struct cdev *dev __unused, struct uio *uio, int flags __unused)
|
||||
@ -267,7 +259,7 @@ randomdev_write(struct cdev *dev __unused, struct uio *uio, int flags __unused)
|
||||
error = uiomove(random_buf, c, uio);
|
||||
if (error)
|
||||
break;
|
||||
random_alg_context.ra_write(random_buf, c);
|
||||
randomdev_accumulate(random_buf, c);
|
||||
tsleep(&random_alg_context, 0, "randwr", hz/10);
|
||||
}
|
||||
if (nbytes != uio->uio_resid && (error == ERESTART || error == EINTR))
|
||||
@ -283,7 +275,7 @@ randomdev_poll(struct cdev *dev __unused, int events, struct thread *td __unused
|
||||
{
|
||||
|
||||
if (events & (POLLIN | POLLRDNORM)) {
|
||||
if (random_alg_context.ra_seeded())
|
||||
if (p_random_alg_context->ra_seeded())
|
||||
events &= (POLLIN | POLLRDNORM);
|
||||
else
|
||||
selrecord(td, &rsel);
|
||||
@ -325,9 +317,6 @@ randomdev_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t addr __unused,
|
||||
void
|
||||
random_source_register(struct random_source *rsource)
|
||||
{
|
||||
#if defined(RANDOM_DUMMY)
|
||||
(void)rsource;
|
||||
#else /* !defined(RANDOM_DUMMY) */
|
||||
struct random_sources *rrs;
|
||||
|
||||
KASSERT(rsource != NULL, ("invalid input to %s", __func__));
|
||||
@ -337,15 +326,11 @@ random_source_register(struct random_source *rsource)
|
||||
|
||||
printf("random: registering fast source %s\n", rsource->rs_ident);
|
||||
LIST_INSERT_HEAD(&source_list, rrs, rrs_entries);
|
||||
#endif /* defined(RANDOM_DUMMY) */
|
||||
}
|
||||
|
||||
void
|
||||
random_source_deregister(struct random_source *rsource)
|
||||
{
|
||||
#if defined(RANDOM_DUMMY)
|
||||
(void)rsource;
|
||||
#else /* !defined(RANDOM_DUMMY) */
|
||||
struct random_sources *rrs = NULL;
|
||||
|
||||
KASSERT(rsource != NULL, ("invalid input to %s", __func__));
|
||||
@ -356,41 +341,6 @@ random_source_deregister(struct random_source *rsource)
|
||||
}
|
||||
if (rrs != NULL)
|
||||
free(rrs, M_ENTROPY);
|
||||
#endif /* defined(RANDOM_DUMMY) */
|
||||
}
|
||||
|
||||
#if !defined(RANDOM_DUMMY)
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* BEWARE!!!
|
||||
* This function runs inside the RNG thread! Don't do anything silly!
|
||||
*/
|
||||
void
|
||||
random_sources_feed(void)
|
||||
{
|
||||
uint32_t entropy[HARVESTSIZE];
|
||||
struct random_sources *rrs;
|
||||
u_int i, n, local_read_rate;
|
||||
|
||||
/*
|
||||
* Step over all of live entropy sources, and feed their output
|
||||
* to the system-wide RNG.
|
||||
*/
|
||||
/* XXX: FIX!! Next lines as an atomic operation? */
|
||||
local_read_rate = read_rate;
|
||||
read_rate = RANDOM_ALG_READ_RATE_MINIMUM;
|
||||
LIST_FOREACH(rrs, &source_list, rrs_entries) {
|
||||
for (i = 0; i < random_alg_context.ra_poolcount*local_read_rate; i++) {
|
||||
n = rrs->rrs_source->rs_read(entropy, sizeof(entropy));
|
||||
KASSERT((n > 0 && n <= sizeof(entropy)), ("very bad return from rs_read (= %d) in %s", n, __func__));
|
||||
random_harvest_direct(entropy, n, (n*8)/2, rrs->rrs_source->rs_source);
|
||||
}
|
||||
}
|
||||
explicit_bzero(entropy, sizeof(entropy));
|
||||
}
|
||||
|
||||
static int
|
||||
@ -414,7 +364,6 @@ random_source_handler(SYSCTL_HANDLER_ARGS)
|
||||
SYSCTL_PROC(_kern_random, OID_AUTO, random_sources, CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
|
||||
NULL, 0, random_source_handler, "A",
|
||||
"List of active fast entropy sources.");
|
||||
#endif /* !defined(RANDOM_DUMMY) */
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
@ -449,3 +398,5 @@ static moduledata_t randomdev_mod = {
|
||||
|
||||
DECLARE_MODULE(random_device, randomdev_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
|
||||
MODULE_VERSION(random_device, 1);
|
||||
MODULE_DEPEND(random_device, crypto, 1, 1, 1);
|
||||
MODULE_DEPEND(random_device, random_harvestq, 1, 1, 1);
|
||||
|
@ -55,16 +55,15 @@ random_check_uint_##name(SYSCTL_HANDLER_ARGS) \
|
||||
|
||||
MALLOC_DECLARE(M_ENTROPY);
|
||||
|
||||
#define RANDOM_ALG_READ_RATE_MINIMUM 32
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
struct harvest_event;
|
||||
|
||||
typedef void random_alg_init_t(void *);
|
||||
typedef void random_alg_deinit_t(void *);
|
||||
typedef void random_alg_pre_read_t(void);
|
||||
typedef void random_alg_read_t(uint8_t *, u_int);
|
||||
typedef void random_alg_write_t(uint8_t *, u_int);
|
||||
typedef int random_alg_seeded_t(void);
|
||||
typedef bool random_alg_seeded_t(void);
|
||||
typedef void random_alg_reseed_t(void);
|
||||
typedef void random_alg_eventprocessor_t(struct harvest_event *);
|
||||
|
||||
@ -81,13 +80,11 @@ struct random_algorithm {
|
||||
void (*ra_deinit_alg)(void *);
|
||||
random_alg_pre_read_t *ra_pre_read;
|
||||
random_alg_read_t *ra_read;
|
||||
random_alg_write_t *ra_write;
|
||||
random_alg_reseed_t *ra_reseed;
|
||||
random_alg_seeded_t *ra_seeded;
|
||||
random_alg_eventprocessor_t *ra_event_processor;
|
||||
};
|
||||
|
||||
extern struct random_algorithm random_alg_context;
|
||||
extern struct random_algorithm random_alg_context, *p_random_alg_context;
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
@ -97,22 +94,33 @@ extern struct random_algorithm random_alg_context;
|
||||
* upon request.
|
||||
*/
|
||||
struct random_source {
|
||||
const char *rs_ident;
|
||||
enum random_entropy_source rs_source;
|
||||
random_source_read_t *rs_read;
|
||||
const char *rs_ident;
|
||||
enum random_entropy_source rs_source;
|
||||
random_source_read_t *rs_read;
|
||||
};
|
||||
|
||||
#if !defined(RANDOM_DUMMY)
|
||||
struct random_sources {
|
||||
LIST_ENTRY(random_sources) rrs_entries;
|
||||
struct random_source *rrs_source;
|
||||
LIST_ENTRY(random_sources) rrs_entries;
|
||||
struct random_source *rrs_source;
|
||||
};
|
||||
#endif /* !defined(RANDOM_DUMMY) */
|
||||
|
||||
LIST_HEAD(sources_head, random_sources);
|
||||
extern struct sources_head source_list;
|
||||
|
||||
void random_source_register(struct random_source *);
|
||||
void random_source_deregister(struct random_source *);
|
||||
|
||||
void random_sources_feed(void);
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
extern struct sx randomdev_config_lock;
|
||||
#define RANDOM_CONFIG_INIT_LOCK(x) sx_init(&randomdev_config_lock, "configuration change lock")
|
||||
#define RANDOM_CONFIG_X_LOCK(x) sx_xlock(&randomdev_config_lock)
|
||||
#define RANDOM_CONFIG_X_UNLOCK(x) sx_xunlock(&randomdev_config_lock)
|
||||
#define RANDOM_CONFIG_S_LOCK(x) sx_slock(&randomdev_config_lock)
|
||||
#define RANDOM_CONFIG_S_UNLOCK(x) sx_sunlock(&randomdev_config_lock)
|
||||
#define RANDOM_CONFIG_DEINIT_LOCK(x) sx_destroy(&randomdev_config_lock)
|
||||
void random_infra_init(int (*)(struct uio *, bool), u_int (*)(void *, u_int));
|
||||
void random_infra_uninit(void);
|
||||
#endif
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
|
@ -1,72 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 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$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/random.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <dev/random/randomdev.h>
|
||||
|
||||
#include "opt_random.h"
|
||||
|
||||
#if defined(RANDOM_DUMMY) || defined(RANDOM_YARROW)
|
||||
#error "Cannot define any of RANDOM_DUMMY and RANDOM_YARROW without 'device random'"
|
||||
#endif
|
||||
|
||||
/*-
|
||||
* Dummy "not even here" device. Stub out all routines that the kernel would need.
|
||||
*/
|
||||
|
||||
/* ARGSUSED */
|
||||
u_int
|
||||
read_random(void *random_buf __unused, u_int len __unused)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
random_harvest_direct(const void *entropy __unused, u_int count __unused, u_int bits __unused, enum random_entropy_source origin __unused)
|
||||
{
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
random_harvest_queue(const void *entropy __unused, u_int count __unused, u_int bits __unused, enum random_entropy_source origin __unused)
|
||||
{
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
random_harvest_fast(const void *entropy __unused, u_int count __unused, u_int bits __unused, enum random_entropy_source origin __unused)
|
||||
{
|
||||
}
|
@ -46,6 +46,7 @@ Where <alg> is YARROW or FORTUNA.
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <threads.h>
|
||||
@ -171,35 +172,6 @@ RunHarvester(void *arg __unused)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
WriteCSPRNG(void *threadid)
|
||||
{
|
||||
uint8_t *buf;
|
||||
int i;
|
||||
|
||||
printf("Thread #1 starts\n");
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
if (stopseeding)
|
||||
break;
|
||||
buf = malloc(4096);
|
||||
if (i % 1000 == 0)
|
||||
printf("Thread write 1 - %d\n", i);
|
||||
if (buf != NULL) {
|
||||
printf("Thread 1 writing.\n");
|
||||
random_alg_context.ra_write(buf, i);
|
||||
free(buf);
|
||||
}
|
||||
usleep(1000000);
|
||||
}
|
||||
|
||||
printf("Thread #1 ends\n");
|
||||
|
||||
thrd_exit(0);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ReadCSPRNG(void *threadid)
|
||||
{
|
||||
@ -271,7 +243,7 @@ main(int argc, char *argv[])
|
||||
|
||||
for (t = 0; t < NUM_THREADS; t++) {
|
||||
printf("In main: creating thread %ld\n", t);
|
||||
rc = thrd_create(&threads[t], (t == 0 ? RunHarvester : (t == 1 ? WriteCSPRNG : ReadCSPRNG)), NULL);
|
||||
rc = thrd_create(&threads[t], (t == 0 ? RunHarvester : ReadCSPRNG), NULL);
|
||||
if (rc != thrd_success) {
|
||||
printf("ERROR; return code from thrd_create() is %d\n", rc);
|
||||
exit(-1);
|
||||
|
@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/random/yarrow.h>
|
||||
#else /* !_KERNEL */
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
@ -92,7 +93,7 @@ static struct yarrow_state {
|
||||
u_int ysp_thresh; /* pool reseed threshhold */
|
||||
struct randomdev_hash ysp_hash; /* accumulated entropy */
|
||||
} ys_pool[RANDOM_YARROW_NPOOLS];/* pool[0] is fast, pool[1] is slow */
|
||||
int ys_seeded;
|
||||
bool ys_seeded;
|
||||
/* Reseed lock */
|
||||
mtx_t ys_mtx;
|
||||
} yarrow_state;
|
||||
@ -108,9 +109,7 @@ RANDOM_CHECK_UINT(slowoverthresh, 1, 5);
|
||||
|
||||
static void random_yarrow_pre_read(void);
|
||||
static void random_yarrow_read(uint8_t *, u_int);
|
||||
static void random_yarrow_write(uint8_t *, u_int);
|
||||
static void random_yarrow_reseed(void);
|
||||
static int random_yarrow_seeded(void);
|
||||
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 *);
|
||||
@ -123,8 +122,6 @@ struct random_algorithm random_alg_context = {
|
||||
.ra_deinit_alg = random_yarrow_deinit_alg,
|
||||
.ra_pre_read = random_yarrow_pre_read,
|
||||
.ra_read = random_yarrow_read,
|
||||
.ra_write = random_yarrow_write,
|
||||
.ra_reseed = random_yarrow_reseed,
|
||||
.ra_seeded = random_yarrow_seeded,
|
||||
.ra_event_processor = random_yarrow_process_event,
|
||||
.ra_poolcount = RANDOM_YARROW_NPOOLS,
|
||||
@ -141,7 +138,7 @@ random_yarrow_init_alg(void *unused __unused)
|
||||
|
||||
RANDOM_RESEED_INIT_LOCK();
|
||||
/* Start unseeded, therefore blocked. */
|
||||
yarrow_state.ys_seeded = 0;
|
||||
yarrow_state.ys_seeded = false;
|
||||
#ifdef _KERNEL
|
||||
/*
|
||||
* Yarrow parameters. Do not adjust these unless you have
|
||||
@ -266,12 +263,14 @@ random_yarrow_reseed_internal(u_int fastslow)
|
||||
RANDOM_RESEED_ASSERT_LOCK_OWNED();
|
||||
#ifdef RANDOM_DEBUG
|
||||
/* WARNING! This is dangerously tedious to do with mutexes held! */
|
||||
printf("random: %s %s seeded = %d\n", __func__, (fastslow == RANDOM_YARROW_FAST ? "RANDOM_YARROW_FAST" : "RANDOM_YARROW_SLOW"), yarrow_state.ys_seeded);
|
||||
printf("random: %s - fast - thresh %d,1 - ", __func__, yarrow_state.ys_pool[RANDOM_YARROW_FAST].ysp_thresh);
|
||||
printf("random: %s ", __func__);
|
||||
printf("type/pool = %s ", fastslow == RANDOM_YARROW_FAST ? "RANDOM_YARROW_FAST" : "RANDOM_YARROW_SLOW");
|
||||
printf("seeded = %s\n", yarrow_state.ys_seeded ? "true" : "false");
|
||||
printf("random: fast - thresh %d,1 - ", yarrow_state.ys_pool[RANDOM_YARROW_FAST].ysp_thresh);
|
||||
for (i = RANDOM_START; i < ENTROPYSOURCE; i++)
|
||||
printf(" %d", yarrow_state.ys_pool[RANDOM_YARROW_FAST].ysp_source_bits[i]);
|
||||
printf("\n");
|
||||
printf("random: %s - slow - thresh %d,%d - ", __func__, yarrow_state.ys_pool[RANDOM_YARROW_SLOW].ysp_thresh, yarrow_state.ys_slowoverthresh);
|
||||
printf("random: slow - thresh %d,%d - ", yarrow_state.ys_pool[RANDOM_YARROW_SLOW].ysp_thresh, yarrow_state.ys_slowoverthresh);
|
||||
for (i = RANDOM_START; i < ENTROPYSOURCE; i++)
|
||||
printf(" %d", yarrow_state.ys_pool[RANDOM_YARROW_SLOW].ysp_source_bits[i]);
|
||||
printf("\n");
|
||||
@ -338,7 +337,7 @@ random_yarrow_reseed_internal(u_int fastslow)
|
||||
#endif
|
||||
/* Unblock the device if it was blocked due to being unseeded */
|
||||
if (!yarrow_state.ys_seeded) {
|
||||
yarrow_state.ys_seeded = 1;
|
||||
yarrow_state.ys_seeded = true;
|
||||
randomdev_unblock();
|
||||
}
|
||||
}
|
||||
@ -395,47 +394,7 @@ random_yarrow_read(uint8_t *buf, u_int bytecount)
|
||||
RANDOM_RESEED_UNLOCK();
|
||||
}
|
||||
|
||||
/* Internal function to hand external entropy to the PRNG. */
|
||||
void
|
||||
random_yarrow_write(uint8_t *buf, u_int count)
|
||||
{
|
||||
static u_int destination = 0;
|
||||
static struct harvest_event event;
|
||||
struct randomdev_hash hash;
|
||||
uint32_t entropy_data[RANDOM_KEYSIZE_WORDS], timestamp;
|
||||
int i;
|
||||
|
||||
/* Extra timing here is helpful to scrape scheduler timing entropy */
|
||||
randomdev_hash_init(&hash);
|
||||
timestamp = (uint32_t)get_cyclecount();
|
||||
randomdev_hash_iterate(&hash, ×tamp, sizeof(timestamp));
|
||||
randomdev_hash_iterate(&hash, buf, count);
|
||||
timestamp = (uint32_t)get_cyclecount();
|
||||
randomdev_hash_iterate(&hash, ×tamp, sizeof(timestamp));
|
||||
randomdev_hash_finish(&hash, entropy_data);
|
||||
explicit_bzero(&hash, sizeof(hash));
|
||||
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));
|
||||
}
|
||||
|
||||
void
|
||||
random_yarrow_reseed(void)
|
||||
{
|
||||
|
||||
RANDOM_RESEED_LOCK();
|
||||
random_yarrow_reseed_internal(RANDOM_YARROW_SLOW);
|
||||
RANDOM_RESEED_UNLOCK();
|
||||
}
|
||||
|
||||
int
|
||||
bool
|
||||
random_yarrow_seeded(void)
|
||||
{
|
||||
|
||||
|
@ -296,6 +296,9 @@ SUBDIR= \
|
||||
${_qlxgbe} \
|
||||
ral \
|
||||
${_ralfw} \
|
||||
${_random_fortuna} \
|
||||
${_random_yarrow} \
|
||||
${_random_other} \
|
||||
rc4 \
|
||||
${_rdma} \
|
||||
${_rdrand_rng} \
|
||||
@ -398,6 +401,9 @@ _autofs= autofs
|
||||
.if exists(${.CURDIR}/../opencrypto)
|
||||
_crypto= crypto
|
||||
_cryptodev= cryptodev
|
||||
_random_fortuna=random_fortuna
|
||||
_random_yarrow= random_yarrow
|
||||
_random_other= random_other
|
||||
.endif
|
||||
.endif
|
||||
|
||||
|
11
sys/modules/random_fortuna/Makefile
Normal file
11
sys/modules/random_fortuna/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../dev/random
|
||||
|
||||
KMOD = random_fortuna
|
||||
SRCS = randomdev.c hash.c fortuna.c
|
||||
SRCS += opt_param.h bus_if.h device_if.h
|
||||
SRCS += opt_ddb.h
|
||||
CFLAGS += -DRANDOM_LOADABLE
|
||||
|
||||
.include <bsd.kmod.mk>
|
11
sys/modules/random_other/Makefile
Normal file
11
sys/modules/random_other/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../dev/random
|
||||
|
||||
KMOD = random_OTHER
|
||||
SRCS = randomdev.c hash.c other_algorithm.c
|
||||
SRCS += opt_param.h bus_if.h device_if.h
|
||||
SRCS += opt_ddb.h
|
||||
CFLAGS += -DRANDOM_LOADABLE
|
||||
|
||||
.include <bsd.kmod.mk>
|
11
sys/modules/random_yarrow/Makefile
Normal file
11
sys/modules/random_yarrow/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../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>
|
@ -33,10 +33,29 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "opt_random.h"
|
||||
|
||||
#if defined(RANDOM_LOADABLE) && defined(RANDOM_YARROW)
|
||||
#error "Cannot define both RANDOM_LOADABLE and RANDOM_YARROW"
|
||||
#endif
|
||||
|
||||
struct uio;
|
||||
|
||||
#if defined(DEV_RANDOM)
|
||||
u_int read_random(void *, u_int);
|
||||
int read_random_uio(struct uio *, bool);
|
||||
#else
|
||||
static __inline int
|
||||
read_random_uio(void *a __unused, u_int b __unused)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
static __inline u_int
|
||||
read_random(void *a __unused, u_int b __unused)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Note: if you add or remove members of random_entropy_source, remember to also update the
|
||||
@ -76,15 +95,15 @@ enum random_entropy_source {
|
||||
|
||||
#define RANDOM_HARVEST_EVERYTHING_MASK ((1 << (RANDOM_ENVIRONMENTAL_END + 1)) - 1)
|
||||
|
||||
#if defined(RANDOM_DUMMY)
|
||||
#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)
|
||||
#else /* !defined(RANDOM_DUMMY) */
|
||||
#if defined(DEV_RANDOM)
|
||||
void random_harvest_queue(const void *, u_int, u_int, enum random_entropy_source);
|
||||
void random_harvest_fast(const void *, u_int, u_int, enum random_entropy_source);
|
||||
void random_harvest_direct(const void *, u_int, u_int, enum random_entropy_source);
|
||||
#endif /* defined(RANDOM_DUMMY) */
|
||||
#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)
|
||||
#endif
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user