Page MenuHomeFreeBSD

D19744.id55895.diff
No OneTemporary

D19744.id55895.diff

Index: share/man/man4/random.4
===================================================================
--- share/man/man4/random.4
+++ share/man/man4/random.4
@@ -23,7 +23,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 26, 2018
+.Dd March 28, 2019
.Dt RANDOM 4
.Os
.Sh NAME
@@ -32,62 +32,43 @@
.Sh SYNOPSIS
.Cd "device random"
.Cd "options RANDOM_LOADABLE"
+.Cd "options RANDOM_ENABLE_ETHER"
.Cd "options RANDOM_ENABLE_UMA"
.Sh DESCRIPTION
The
.Nm
-device
-returns an endless supply of random bytes when read.
-It also accepts and reads data
-as any ordinary file.
+device returns an endless supply of random bytes when read.
.Pp
The generator will start in an
.Em unseeded
-state, and will block reads until
-it is seeded for the first time.
-This may cause trouble at system boot
-when keys and the like
-are generated from
-.Nm
-so steps should be taken to ensure a
-seeding as soon as possible.
-.Pp
-It is also possible
-to read random bytes
-by using the KERN_ARND sysctl.
-On the command line
-this could be done by
-.Pp
-.Dl "sysctl -x -B 16 kern.arandom"
-.Pp
-This sysctl will not return
-random bytes unless
-the
-.Nm
-device is seeded.
+state, and will block reads until it is seeded for the first time.
.Pp
-This initial seeding
-of random number generators
-is a bootstrapping problem
-that needs very careful attention.
-In some cases,
-it may be difficult
-to find enough randomness
-to seed a random number generator
-until a system is fully operational,
-but the system requires random numbers
-to become fully operational.
-It is (or more accurately should be)
-critically important that the
-.Nm
-device is seeded
-before the first time it is used.
-In the case where a dummy or "blocking-only"
-device is used,
-it is the responsibility
-of the system architect
-to ensure that no blocking reads
-hold up critical processes.
+To provide prompt access to the random device at boot time,
+.Fx
+automatically persists some entropy data in
+.Pa /boot/entropy
+for the loader to provide to the kernel.
+Additional entropy is regularly saved in
+.Pa /var/db/entropy .
+This saved entropy is sufficient to unblock the random device on devices with
+writeable media.
+.Pp
+Embedded applications without writable media must determine their own scheme
+for re-seeding the random device on boot, or accept that the device
+will remain unseeded and block reads indefinitely.
+See
+.Sx SECURITY CONSIDERATIONS
+for more detail.
+.Pp
+In addition to
+.Xr read 2 ,
+the direct output of the abstract kernel entropy device can be read with
+.Xr getrandom 2 ,
+.Xr getentropy 3 ,
+or the
+.Xr sysctl 8
+pseudo-variable
+.Va kern.arandom .
.Pp
To see the current settings of the software
.Nm
@@ -98,16 +79,17 @@
which results in something like:
.Bd -literal -offset indent
kern.random.fortuna.minpoolsize: 64
-kern.random.harvest.mask_symbolic: [HIGH_PERFORMANCE], ... ,CACHED
-kern.random.harvest.mask_bin: 00111111111
-kern.random.harvest.mask: 511
+kern.random.harvest.mask_symbolic: ENABLEDSOURCE,[DISABLEDSOURCE],...,CACHED
+kern.random.harvest.mask_bin: 00000010000000111011111
+kern.random.harvest.mask: 66015
+kern.random.use_chacha20_cipher: 0
kern.random.random_sources: 'Intel Secure Key RNG'
.Ed
.Pp
Other than
-.Dl kern.random.fortuna.minpoolsize
+.Va kern.random.fortuna.minpoolsize
and
-.Dl kern.random.harvest.mask
+.Va kern.random.harvest.mask ,
all settings are read-only.
.Pp
The
@@ -137,173 +119,23 @@
.Va kern.random.harvest.mask_symbolic
sysctls
can be used to confirm
-that the choices are correct.
-Note that disabled items
+settings in a human readable form.
+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.
-The only module built by default is
-.Em random_fortuna .
-The
-.Em random_yarrow
-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,
-and also must be indirect calls
-to allow for removal.
-.Pp
-When
-.Cd "options RANDOM_ENABLE_UMA"
-is used,
-the
-.Pa /dev/random
-device will obtain entropy
-from the zone allocator.
-This is potentially very high rate,
-and if so will be of questionable use.
-If this is the case,
-use of this option
-is not recommended.
-Determining this is not trivial,
-so experimenting and measurement
-using tools such as
-.Xr dtrace 1
-will be required.
-.Sh RANDOMNESS
-The use of randomness in the field of computing
-is a rather subtle issue because randomness means
-different things to different people.
-Consider generating a password randomly,
-simulating a coin tossing experiment or
-choosing a random back-off period when a server does not respond.
-Each of these tasks requires random numbers,
-but the random numbers in each case have different requirements.
-.Pp
-Generation of passwords, session keys and the like
-requires cryptographic randomness.
-A cryptographic random number generator should be designed
-so that its output is difficult to guess,
-even if a lot of auxiliary information is known
-(such as when it was seeded, subsequent or previous output, and so on).
-On
-.Fx ,
-seeding for cryptographic random number generators is provided by the
-.Nm
-device,
-which provides real randomness.
-The
-.Xr arc4random 3
-library call provides a pseudo-random sequence
-which is generally reckoned to be suitable for
-simple cryptographic use.
-The OpenSSL library also provides functions for managing randomness
-via functions such as
-.Xr RAND_bytes 3
-and
-.Xr RAND_add 3 .
-Note that OpenSSL uses the
-.Nm
-device for seeding automatically.
-.Pp
-Randomness for simulation is required in engineering or
-scientific software and games.
-The first requirement of these applications is
-that the random numbers produced conform to some well-known,
-usually uniform, distribution.
-The sequence of numbers should also appear numerically uncorrelated,
-as simulation often assumes independence of its random inputs.
-Often it is desirable to reproduce
-the results of a simulation exactly,
-so that if the generator is seeded in the same way,
-it should produce the same results.
-A peripheral concern for simulation is
-the speed of a random number generator.
-.Pp
-Another issue in simulation is
-the size of the state associated with the random number generator, and
-how frequently it repeats itself.
-For example,
-a program which shuffles a pack of cards should have 52!\& possible outputs,
-which requires the random number generator to have 52!\& starting states.
-This means the seed should have at least log_2(52!) ~ 226 bits of state
-if the program is to stand a chance of outputting all possible sequences,
-and the program needs some unbiased way of generating these bits.
-Again,
-the
-.Nm
-device could be used for seeding here,
-but in practice, smaller seeds are usually considered acceptable.
-.Pp
-.Fx
-provides two families of functions which are considered
-suitable for simulation.
-The
-.Xr random 3
-family of functions provides a random integer
-between 0 to
-.if t 2\u\s731\s10\d\(mi1.
-.if n (2**31)\(mi1.
-The functions
-.Xr srandom 3 ,
-.Xr initstate 3
-and
-.Xr setstate 3
-are provided for deterministically setting
-the state of the generator and
-the function
-.Xr srandomdev 3
-is provided for setting the state via the
-.Nm
-device.
-The
-.Xr drand48 3
-family of functions are also provided,
-which provide random floating point numbers in various ranges.
-.Pp
-Randomness that is used for collision avoidance
-(for example, in certain network protocols)
-has slightly different semantics again.
-It is usually expected that the numbers will be uniform,
-as this produces the lowest chances of collision.
-Here again,
-the seeding of the generator is very important,
-as it is required that different instances of
-the generator produce independent sequences.
-However, the guessability or reproducibility of the sequence is unimportant,
-unlike the previous cases.
-.Pp
-.Fx
-does also provide the traditional
-.Xr rand 3
-library call,
-for compatibility purposes.
-However,
-it is known to be poor for simulation and
-absolutely unsuitable for cryptographic purposes,
-so its use is discouraged.
.Sh FILES
-.Bl -tag -width ".Pa /dev/random"
+.Bl -tag -width ".Pa /dev/urandom"
.It Pa /dev/random
+.It Pa /dev/urandom
.El
.Sh SEE ALSO
+.Xr getrandom 2 ,
.Xr arc4random 3 ,
.Xr drand48 3 ,
+.Xr getentropy 3 ,
.Xr rand 3 ,
.Xr RAND_add 3 ,
.Xr RAND_bytes 3 ,
@@ -323,21 +155,80 @@
.Nm
device appeared in
.Fx 2.2 .
-The current software implementation,
-introduced in
-.Fx 10.0 ,
-is by
+The implementation was changed to the
+.Em Yarrow algorithm in
+.Fx 5.0 .
+In
+.Fx 11.0 ,
+the Fortuna algorithm was introduced as the default.
+In
+.Fx 12.0 ,
+Yarrow was removed entirely.
+.Sh AUTHORS
+.An -nosplit
+The current
+.Nm
+code was authored by
.An Mark R V Murray ,
-and is an implementation of the
+with significant contributions from many people.
+.Pp
+The
.Em Fortuna
-algorithm by Ferguson
-.Em et al .
-It replaces the previous
-.Em Yarrow
-implementation,
-introduced in
-.Fx 5.0 .
-The Yarrow algorithm
-is no longer supported
-by its authors,
-and is therefore no longer available.
+algorithm was designed by
+.An Niels Ferguson ,
+.An Bruce Schneier ,
+and
+.An Tadayoshi Kohno .
+.Sh CAVEATS
+When
+.Cd "options RANDOM_LOADABLE"
+is enabled,
+the
+.Pa /dev/random
+device is not created
+until an "algorithm module"
+is loaded.
+The only module built by default is
+.Em random_fortuna .
+Loadable random modules
+are 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.
+.Pp
+When
+.Cd "options RANDOM_ENABLE_UMA"
+is enabled,
+the
+.Pa /dev/random
+device will obtain entropy
+from the zone allocator.
+This is a very high rate source with significant performance impact.
+Therefore, it is disabled by default.
+.Pp
+When
+.Cd "options RANDOM_ENABLE_ETHER"
+is enabled, the
+.Nm
+device will obtain entropy from
+.Vt mbuf
+structures passing through the network stack.
+This source is both extremely expensive and a poor source of entropy, so it is
+disabled by default.
+.Sh SECURITY CONSIDERATIONS
+The initial seeding
+of random number generators
+is a bootstrapping problem
+that needs very careful attention.
+When writable media is available, the
+.Em Fortuna
+paper describes a robust system for rapidly reseeding the device.
+.Pp
+In some embedded cases, it may be difficult to find enough randomness to seed a
+random number generator until a system is fully operational.
+In these cases, is the responsibility of the system architect to ensure that
+blocking is acceptable, or that the random device is seeded.
+(This advice does not apply to typical consumer systems.)
Index: share/man/man9/random.9
===================================================================
--- share/man/man9/random.9
+++ share/man/man9/random.9
@@ -26,12 +26,13 @@
.\"
.\" $FreeBSD$
.\" "
-.Dd July 16, 2015
+.Dd March 28, 2019
.Dt RANDOM 9
.Os
.Sh NAME
.Nm arc4rand ,
.Nm arc4random ,
+.Nm arc4random_buf ,
.Nm random ,
.Nm read_random ,
.Nm read_random_uio ,
@@ -39,86 +40,72 @@
.Nd supply pseudo-random numbers
.Sh SYNOPSIS
.In sys/libkern.h
+.Ft uint32_t
+.Fn arc4random "void"
.Ft void
-.Fn srandom "u_long seed"
-.Ft u_long
-.Fn random "void"
+.Fn arc4random_buf "void *ptr" "size_t len"
.Ft void
.Fn arc4rand "void *ptr" "u_int length" "int reseed"
-.Ft uint32_t
-.Fn arc4random "void"
.Pp
.In sys/random.h
-.Ft int
+.Ft void
.Fn read_random "void *buffer" "int count"
.Ft int
.Fn read_random_uio "struct uio *uio" "bool nonblock"
+.Ss LEGACY ROUTINES
+.In sys/libkern.h
+.Ft void
+.Fn srandom "u_long seed"
+.Ft u_long
+.Fn random "void"
.Sh DESCRIPTION
The
-.Fn random
-function will by default produce
-a sequence of numbers
-that can be duplicated
-by calling
-.Fn srandom
-with some constant
-as the
-.Fa seed .
-The
-.Fn srandom
-function may be called with any arbitrary
-.Fa seed
-value to get slightly more unpredictable numbers.
-It is important to remember that the
-.Fn random
-function is entirely predictable,
-and is therefore not of use where
-knowledge of the sequence of numbers
-may be of benefit to an attacker.
+.Fn arc4random
+and
+.Fn arc4random_buf
+functions will return very good quality random numbers, suited for
+security-related purposes.
+Both are wrappers around the underlying
+.Fn arc4rand
+interface.
+.Fn arc4random
+returns a 32-bit random value, while
+.Fn arc4random_buf
+fills
+.Fa ptr
+with
+.Fa len
+bytes of random data.
.Pp
The
.Fn arc4rand
-function will return very good quality random numbers,
-better suited
-for security-related purposes.
-The random numbers from
-.Fn arc4rand
-are seeded from the entropy device
-if it is available.
-Automatic reseeds happen
-after a certain timeinterval
-and after a certain number of bytes
-have been delivered.
-A forced reseed
-can be forced
-by passing a non-zero
-value in the
+CSPRNG
+is seeded from the
+.Xr random 4
+kernel abstract entropy device.
+Automatic reseeding happens at unspecified time and bytes (of output)
+intervals.
+A reseed can be forced by passing a non-zero
.Fa reseed
-argument.
+value.
.Pp
The
.Fn read_random
-function is used to return entropy directly from the entropy device
-if it has been loaded.
-If the entropy device is not loaded, then
-the
-.Fa buffer
-is ignored
-and zero is returned.
-The
+function is used to read entropy directly from the kernel abstract entropy
+device.
+.Fn read_random
+blocks if and until the entropy device is seeded.
+The provided
.Fa buffer
is filled with no more than
.Fa count
bytes.
It is strongly advised that
.Fn read_random
-is not used;
-instead use
+is not used directly;
+instead, use the
.Fn arc4rand
-unless it is
-necessary to know
-that no entropy
-has been returned.
+family of functions.
.Pp
The
.Fn read_random_uio
@@ -129,50 +116,35 @@
The
.Fa uio
argument points to a buffer where random data should be stored.
-This function only returns data if the random device is seeded.
-It blocks if unseeded,
-except when the
+If
.Fa nonblock
-argument is true.
+is true and the random device is not seeded, this function does not return any
+data.
+Otherwise, this function may block interruptibly until the random device is seeded.
+If the function is interrupted before the random device is seeded, no data is
+returned.
.Pp
-All the bits returned by
-.Fn random ,
-.Fn arc4rand ,
-.Fn read_random ,
-and
-.Fn read_random_uio
-are usable.
-For example,
-.Sq Li random()&01
-will produce a random binary value.
-.Pp
-The
-.Fn arc4random
-is a convenience function which calls
-.Fn arc4rand
-to return a 32 bit pseudo-random integer.
-.Sh RETURN VALUES
-The
+The legacy
.Fn random
-function uses
-a non-linear additive feedback random number generator
-employing a default table
-of size 31
-containing long integers
-to return successive pseudo-random
-numbers in the range from 0 to
-.if t 2\u\s731\s10\d\(mi1.
-.if n (2**31)\(mi1.
-The period of this random number generator
-is very large,
-approximately
-.if t 16\(mu(2\u\s731\s10\d\(mi1).
-.if n 16*((2**31)\(mi1).
-.Pp
+function will produce a sequence of numbers that can be duplicated by calling
+.Fn srandom
+with some constant as the
+.Fa seed .
+The legacy
+.Fn srandom
+function may be called with any
+.Fa seed
+value.
+It is strongly advised that the
+.Fn random
+function not be used to generate random numbers.
+See
+.Sx SECURITY CONSIDERATIONS .
+.Sh RETURN VALUES
The
.Fn arc4rand
-function uses the RC4 algorithm
-to generate successive pseudo-random bytes.
+function uses the Chacha20 algorithm to generate a pseudo-random sequence of
+bytes.
The
.Fn arc4random
function uses
@@ -191,6 +163,23 @@
.Fn read_random_uio
returns zero when successful,
otherwise an error code is returned.
+.Pp
+The legacy
+.Fn random
+function uses
+a non-linear additive feedback random number generator
+employing a default table
+of size 31
+containing long integers
+to return successive pseudo-random
+numbers in the range from 0 to
+.if t 2\u\s731\s10\d\(mi1.
+.if n (2**31)\(mi1.
+The period of this random number generator
+is very large,
+approximately
+.if t 16\(mu(2\u\s731\s10\d\(mi1).
+.if n 16*((2**31)\(mi1).
.Sh ERRORS
.Fn read_random_uio
may fail if:
@@ -210,3 +199,19 @@
.An Mark R V Murray
wrote
.Fn read_random .
+.Sh SECURITY CONSIDERATIONS
+Do not use
+.Fn random
+or
+.Fn srandom
+in new code.
+.Pp
+It is important to remember that the
+.Fn random
+function is entirely predictable.
+It is easy for attackers to predict future output of
+.Fn random
+by recording some generated values.
+We cannot emphasize strongly enough that
+.Fn random
+must not be used to generate values that are intended to be unpredictable.
Index: sys/dev/random/random_harvestq.c
===================================================================
--- sys/dev/random/random_harvestq.c
+++ sys/dev/random/random_harvestq.c
@@ -421,11 +421,6 @@
if (keyfile != NULL) {
data = preload_fetch_addr(keyfile);
size = preload_fetch_size(keyfile);
- /* skip the first bit of the stash so others like arc4 can also have some. */
- if (size > RANDOM_CACHED_SKIP_START) {
- data += RANDOM_CACHED_SKIP_START;
- size -= RANDOM_CACHED_SKIP_START;
- }
/* Trim the size. If the admin has a file with a funny size, we lose some. Tough. */
size -= (size % sizeof(event.he_entropy));
if (data != NULL && size != 0) {
Index: sys/dev/random/random_infra.c
===================================================================
--- sys/dev/random/random_infra.c
+++ sys/dev/random/random_infra.c
@@ -57,12 +57,18 @@
#if defined(RANDOM_LOADABLE)
+static void
+null_read_random(void *dummy __unused, u_int dummy2 __unused)
+{
+ panic("%s: no random module is loaded", __func__);
+}
+
struct random_readers {
int (*read_random_uio)(struct uio *, bool);
- u_int (*read_random)(void *, u_int);
+ void (*read_random)(void *, u_int);
} random_reader_context = {
(int (*)(struct uio *, bool))nullop,
- (u_int (*)(void *, u_int))nullop,
+ null_read_random,
};
struct sx randomdev_config_lock;
@@ -76,7 +82,7 @@
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_infra_init(int (*p_random_read_uio)(struct uio *, bool), void (*p_random_read)(void *, u_int))
{
RANDOM_CONFIG_X_LOCK();
@@ -91,7 +97,7 @@
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_reader_context.read_random = null_read_random;
RANDOM_CONFIG_X_UNLOCK();
}
@@ -114,15 +120,13 @@
return (retval);
}
-u_int
+void
read_random(void *buf, u_int len)
{
- u_int retval;
RANDOM_CONFIG_S_LOCK();
- retval = random_reader_context.read_random(buf, len);
+ random_reader_context.read_random(buf, len);
RANDOM_CONFIG_S_UNLOCK();
- return (retval);
}
#endif /* defined(RANDOM_LOADABLE) */
Index: sys/dev/random/randomdev.h
===================================================================
--- sys/dev/random/randomdev.h
+++ sys/dev/random/randomdev.h
@@ -118,7 +118,7 @@
#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_init(int (*)(struct uio *, bool), void (*)(void *, u_int));
void random_infra_uninit(void);
#endif
Index: sys/dev/random/randomdev.c
===================================================================
--- sys/dev/random/randomdev.c
+++ sys/dev/random/randomdev.c
@@ -63,7 +63,7 @@
#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);
+static void READ_RANDOM(void *, u_int);
#else
#define READ_RANDOM_UIO read_random_uio
#define READ_RANDOM read_random
@@ -124,43 +124,60 @@
return (READ_RANDOM_UIO(uio, (flags & O_NONBLOCK) != 0));
}
-int
-READ_RANDOM_UIO(struct uio *uio, bool nonblock)
+static int
+randomdev_wait_until_seeded(int slpflags)
{
- uint8_t *random_buf;
int error, spamcount;
- ssize_t read_len, total_read, c;
- /* 16 MiB takes about 0.08 s CPU time on my 2017 AMD Zen CPU */
-#define SIGCHK_PERIOD (16 * 1024 * 1024)
- const size_t sigchk_period = SIGCHK_PERIOD;
- CTASSERT(SIGCHK_PERIOD % PAGE_SIZE == 0);
-#undef SIGCHK_PERIOD
+ KASSERT((slpflags & ~PCATCH) == 0, ("unrecognized flag %x", slpflags));
- random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK);
- p_random_alg_context->ra_pre_read();
error = 0;
spamcount = 0;
- /* (Un)Blocking logic */
while (!p_random_alg_context->ra_seeded()) {
- if (nonblock) {
- error = EWOULDBLOCK;
- break;
- }
/* keep tapping away at the pre-read until we seed/unblock. */
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__);
- spamcount = (spamcount + 1)%100;
- error = tsleep(&random_alg_context, PCATCH, "randseed", hz/10);
- if (error == ERESTART || error == EINTR)
+ spamcount = (spamcount + 1) % 100;
+ error = tsleep(&random_alg_context, slpflags, "randseed",
+ hz / 10);
+ if (error == ERESTART || error == EINTR) {
+ KASSERT(slpflags & PCATCH,
+ ("unexpected wake of non-interruptible sleep"));
break;
+ }
/* Squash tsleep timeout condition */
if (error == EWOULDBLOCK)
error = 0;
KASSERT(error == 0, ("unexpected tsleep error %d", error));
}
+ return (error);
+}
+
+int
+READ_RANDOM_UIO(struct uio *uio, bool nonblock)
+{
+ uint8_t *random_buf;
+ int error;
+ ssize_t read_len, total_read, c;
+ /* 16 MiB takes about 0.08 s CPU time on my 2017 AMD Zen CPU */
+#define SIGCHK_PERIOD (16 * 1024 * 1024)
+ const size_t sigchk_period = SIGCHK_PERIOD;
+
+ CTASSERT(SIGCHK_PERIOD % PAGE_SIZE == 0);
+#undef SIGCHK_PERIOD
+
+ random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK);
+ p_random_alg_context->ra_pre_read();
+ error = 0;
+ /* (Un)Blocking logic */
+ if (!p_random_alg_context->ra_seeded()) {
+ if (nonblock)
+ error = EWOULDBLOCK;
+ else
+ error = randomdev_wait_until_seeded(PCATCH);
+ }
if (error == 0) {
read_rate_increment((uio->uio_resid + sizeof(uint32_t))/sizeof(uint32_t));
total_read = 0;
@@ -210,30 +227,36 @@
* It cannot assumed that random_buf is a multiple of
* RANDOM_BLOCKSIZE bytes.
*/
-u_int
+void
READ_RANDOM(void *random_buf, u_int len)
{
- u_int read_len;
- uint8_t local_buf[len + RANDOM_BLOCKSIZE];
+ u_int read_directly_len;
KASSERT(random_buf != NULL, ("No suitable random buffer in %s", __func__));
p_random_alg_context->ra_pre_read();
- /* (Un)Blocking logic; if not seeded, return nothing. */
- if (p_random_alg_context->ra_seeded()) {
- read_rate_increment((len + sizeof(uint32_t))/sizeof(uint32_t));
- if (len > 0) {
- /*
- * Belt-and-braces.
- * Round up the read length to a crypto block size multiple,
- * which is what the underlying generator is expecting.
- */
- read_len = roundup(len, RANDOM_BLOCKSIZE);
- p_random_alg_context->ra_read(local_buf, read_len);
- memcpy(random_buf, local_buf, len);
- }
- } else
- len = 0;
- return (len);
+ /* (Un)Blocking logic */
+ if (!p_random_alg_context->ra_seeded())
+ (void)randomdev_wait_until_seeded(0);
+ read_rate_increment(roundup2(len, sizeof(uint32_t)));
+ if (len == 0)
+ return;
+ /*
+ * The underlying generator expects multiples of
+ * RANDOM_BLOCKSIZE.
+ */
+ read_directly_len = rounddown(len, RANDOM_BLOCKSIZE);
+ if (read_directly_len > 0)
+ p_random_alg_context->ra_read(random_buf, read_directly_len);
+ if (read_directly_len < len) {
+ uint8_t remainder_buf[RANDOM_BLOCKSIZE];
+
+ p_random_alg_context->ra_read(remainder_buf,
+ sizeof(remainder_buf));
+ memcpy((char *)random_buf + read_directly_len, remainder_buf,
+ len - read_directly_len);
+
+ explicit_bzero(remainder_buf, sizeof(remainder_buf));
+ }
}
static __inline void
Index: sys/kern/kern_mib.c
===================================================================
--- sys/kern/kern_mib.c
+++ sys/kern/kern_mib.c
@@ -159,15 +159,8 @@
char buf[256];
size_t len;
- /*-
- * This is one of the very few legitimate uses of read_random(9).
- * Use of arc4random(9) is not recommended as that will ignore
- * an unsafe (i.e. unseeded) random(4).
- *
- * If random(4) is not seeded, then this returns 0, so the
- * sysctl will return a zero-length buffer.
- */
- len = read_random(buf, MIN(req->oldlen, sizeof(buf)));
+ len = MIN(req->oldlen, sizeof(buf));
+ read_random(buf, len);
return (SYSCTL_OUT(req, buf, len));
}
Index: sys/libkern/arc4random.c
===================================================================
--- sys/libkern/arc4random.c
+++ sys/libkern/arc4random.c
@@ -56,7 +56,6 @@
struct chacha20_s {
struct mtx mtx;
int numbytes;
- int first_time_done;
time_t t_reseed;
u_int8_t m_buffer[CHACHA20_BUFFER_SIZE];
struct chacha_ctx ctx;
@@ -76,32 +75,14 @@
chacha20_randomstir(struct chacha20_s* chacha20)
{
struct timeval tv_now;
- size_t n, size;
- u_int8_t key[CHACHA20_KEYBYTES], *data;
- caddr_t keyfile;
+ u_int8_t key[CHACHA20_KEYBYTES];
/*
- * This is making the best of what may be an insecure
- * Situation. If the loader(8) did not have an entropy
- * stash from the previous shutdown to load, then we will
- * be improperly seeded. The answer is to make sure there
- * is an entropy stash at shutdown time.
+ * If the loader(8) did not have an entropy stash from the previous
+ * shutdown to load, then we will block. The answer is to make sure
+ * there is an entropy stash at shutdown time.
*/
- (void)read_random(key, CHACHA20_KEYBYTES);
- if (!chacha20->first_time_done) {
- keyfile = preload_search_by_type(RANDOM_CACHED_BOOT_ENTROPY_MODULE);
- if (keyfile != NULL) {
- data = preload_fetch_addr(keyfile);
- size = MIN(preload_fetch_size(keyfile), CHACHA20_KEYBYTES);
- for (n = 0; n < size; n++)
- key[n] ^= data[n];
- explicit_bzero(data, size);
- if (bootverbose)
- printf("arc4random: read %zu bytes from preloaded cache\n", size);
- } else
- printf("arc4random: no preloaded entropy cache\n");
- chacha20->first_time_done = 1;
- }
+ read_random(key, CHACHA20_KEYBYTES);
getmicrouptime(&tv_now);
mtx_lock(&chacha20->mtx);
chacha_keysetup(&chacha20->ctx, key, CHACHA20_KEYBYTES*8);
@@ -128,7 +109,6 @@
mtx_init(&chacha20->mtx, "chacha20_mtx", NULL, MTX_DEF);
chacha20->t_reseed = -1;
chacha20->numbytes = 0;
- chacha20->first_time_done = 0;
explicit_bzero(chacha20->m_buffer, CHACHA20_BUFFER_SIZE);
explicit_bzero(&chacha20->ctx, sizeof(chacha20->ctx));
}
Index: sys/sys/random.h
===================================================================
--- sys/sys/random.h
+++ sys/sys/random.h
@@ -34,11 +34,12 @@
#include <sys/types.h>
#ifdef _KERNEL
+#include <sys/systm.h>
struct uio;
#if defined(DEV_RANDOM)
-u_int read_random(void *, u_int);
+void read_random(void *, u_int);
int read_random_uio(struct uio *, bool);
#else
static __inline int
@@ -46,10 +47,10 @@
{
return (0);
}
-static __inline u_int
+static __inline void
read_random(void *a __unused, u_int b __unused)
{
- return (0);
+ panic("!defined(DEV_RANDOM) read_random");
}
#endif
@@ -95,7 +96,6 @@
#define RANDOM_LEGACY_BOOT_ENTROPY_MODULE "/boot/entropy"
#define RANDOM_CACHED_BOOT_ENTROPY_MODULE "boot_entropy_cache"
-#define RANDOM_CACHED_SKIP_START 256
#if defined(DEV_RANDOM)
extern u_int hc_source_mask;

File Metadata

Mime Type
text/plain
Expires
Wed, Mar 25, 1:55 PM (25 m, 5 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30326845
Default Alt Text
D19744.id55895.diff (27 KB)

Event Timeline