freebsd-dev/share/man/man9/random.9
Conrad Meyer 13774e8228 random(4): Block read_random(9) on initial seeding
read_random() is/was used, mostly without error checking, in a lot of
very sensitive places in the kernel -- including seeding the widely used
arc4random(9).

Most uses, especially arc4random(9), should block until the device is seeded
rather than proceeding with a bogus or empty seed.  I did not spy any
obvious kernel consumers where blocking would be inappropriate (in the
sense that lack of entropy would be ok -- I did not investigate locking
angle thoroughly).  In many instances, arc4random_buf(9) or that family
of APIs would be more appropriate anyway; that work was done in r345865.

A minor cleanup was made to the implementation of the READ_RANDOM function:
instead of using a variable-length array on the stack to temporarily store
all full random blocks sufficient to satisfy the requested 'len', only store
a single block on the stack.  This has some benefit in terms of reducing
stack usage, reducing memcpy overhead and reducing devrandom output leakage
via the stack.  Additionally, the stack block is now safely zeroed if it was
used.

One caveat of this change is that the kern.arandom sysctl no longer returns
zero bytes immediately if the random device is not seeded.  This means that
FreeBSD-specific userspace applications which attempted to handle an
unseeded random device may be broken by this change.  If such behavior is
needed, it can be replaced by the more portable getrandom(2) GRND_NONBLOCK
option.

On any typical FreeBSD system, entropy is persisted on read/write media and
used to seed the random device very early in boot, and blocking is never a
problem.

This change primarily impacts the behavior of /dev/random on embedded
systems with read-only media that do not configure "nodevice random".  We
toggle the default from 'charge on blindly with no entropy' to 'block
indefinitely.'  This default is safer, but may cause frustration.  Embedded
system designers using FreeBSD have several options.  The most obvious is to
plan to have a small writable NVRAM or NAND to persist entropy, like larger
systems.  Early entropy can be fed from any loader, or by writing directly
to /dev/random during boot.  Some embedded SoCs now provide a fast hardware
entropy source; this would also work for quickly seeding Fortuna.  A 3rd
option would be creating an embedded-specific, more simplistic random
module, like that designed by DJB in [1] (this design still requires a small
rewritable media for forward secrecy).  Finally, the least preferred option
might be "nodevice random", although I plan to remove this in a subsequent
revision.

To help developers emulate the behavior of these embedded systems on
ordinary workstations, the tunable kern.random.block_seeded_status was
added.  When set to 1, it blocks the random device.

I attempted to document this change in random.4 and random.9 and ran into a
bunch of out-of-date or irrelevant or inaccurate content and ended up
rototilling those documents more than I intended to.  Sorry.  I think
they're in a better state now.

PR:		230875
Reviewed by:	delphij, markm (earlier version)
Approved by:	secteam(delphij), devrandom(markm)
Relnotes:	yes
Differential Revision:	https://reviews.freebsd.org/D19744
2019-04-15 18:40:36 +00:00

218 lines
5.2 KiB
Groff

.\"
.\" Copyright (c) 2015
.\" Mark R V Murray
.\" Copyright (c) 2000
.\" The Regents of the University of California. 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.
.\" 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 DEVELOPERS ``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 DEVELOPERS 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$
.\" "
.Dd April 15, 2019
.Dt RANDOM 9
.Os
.Sh NAME
.Nm arc4rand ,
.Nm arc4random ,
.Nm arc4random_buf ,
.Nm random ,
.Nm read_random ,
.Nm read_random_uio ,
.Nm srandom
.Nd supply pseudo-random numbers
.Sh SYNOPSIS
.In sys/libkern.h
.Ft uint32_t
.Fn arc4random "void"
.Ft void
.Fn arc4random_buf "void *ptr" "size_t len"
.Ft void
.Fn arc4rand "void *ptr" "u_int length" "int reseed"
.Pp
.In sys/random.h
.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 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
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
value.
.Pp
The
.Fn read_random
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 directly;
instead, use the
.Fn arc4rand
family of functions.
.Pp
The
.Fn read_random_uio
function behaves identically to
.Xr read 2
on
.Pa /dev/random .
The
.Fa uio
argument points to a buffer where random data should be stored.
If
.Fa nonblock
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
The legacy
.Fn random
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 Chacha20 algorithm to generate a pseudo-random sequence of
bytes.
The
.Fn arc4random
function uses
.Fn arc4rand
to generate pseudo-random numbers
in the range from 0 to
.if t 2\u\s732\s10\d\(mi1.
.if n (2**32)\(mi1.
.Pp
The
.Fn read_random
function returns
the number of bytes placed in
.Fa buffer .
.Pp
.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:
.Bl -tag -width Er
.It Bq Er EFAULT
.Fa uio
points to an invalid memory region.
.It Bq Er EWOULDBLOCK
The random device is unseeded and
.Fa nonblock
is true.
.El
.Sh AUTHORS
.An Dan Moschuk
wrote
.Fn arc4random .
.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.