.\" $NetBSD: rnd.9,v 1.31 2022/05/17 01:39:57 riastradh Exp $
.\"
.\" Copyright (c) 1997 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This documentation is derived from text contributed to The NetBSD
.\" Foundation by S.P.Zeidler (aka stargazer).
.\"
.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``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 FOUNDATION OR CONTRIBUTORS
.\" 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.
.\"
.Dd April 25, 2020
.Dt RND 9
.Os
.Sh NAME
.Nm RND ,
.Nm rnd_attach_source ,
.Nm rnd_detach_source ,
.Nm rnd_add_data ,
.Nm rnd_add_data_sync ,
.Nm rnd_add_uint32
.Nd functions to make a device available for entropy collection
.Sh SYNOPSIS
.In sys/rndsource.h
.Vt typedef struct krndsource krndsource_t;
.Ft void
.Fn rndsource_setcb "krndsource_t *rnd_source" "void (*callback)(size_t, void *)" "void *cookie"
.Ft void
.Fn rnd_attach_source "krndsource_t *rnd_source" "char *devname" "uint32_t source_type" "uint32_t flags"
.Ft void
.Fn rnd_detach_source "krndsource_t *rnd_source"
.Ft void
.Fn rnd_add_data "krndsource_t *rnd_source" "void *data" "uint32_t len" "uint32_t entropy"
.Ft void
.Fn rnd_add_data_sync "krndsource_t *rnd_source" "void *data" "uint32_t len" "uint32_t entropy"
.Ft void
.Fn rnd_add_uint32 "krndsource_t *rnd_source" "uint32_t datum"
.Sh DESCRIPTION
The
.Nm
functions enable drivers to collect samples of physical observations,
such as network packet timings or hardware random number generator
outputs, into a kernel entropy pool to derive key material for
.Xr cprng 9
and
.Xr rnd 4
.Pq Pa /dev/random , Pa /dev/urandom .
.Pp
Usage model:
.Bl -enum -compact
.It
Allocate and zero a
.Vt struct krndsource
object before using the
.Nm
functions.
.It
Optionally, set a callback with
.Fn rndsource_setcb
if appropriate, e.g. for an on-demand hardware random number
generator.
.It
Attach the random source with
.Fn rnd_attach_source .
.It
Enter data with
.Fn rnd_add_data
or
.Fn rnd_add_uint32 ,
or, if in the callback,
.Fn rnd_add_data_sync .
.It
When the driver is done, detach it with
.Fn rnd_detach_source .
.El
.Pp
The following types of random sources are defined:
.Bl -tag -width "Dv RND_TYPE_UNKNOWN" -compact
.It Dv RND_TYPE_DISK
Disk devices, typically sampling seek timings.
.It Dv RND_TYPE_ENV
Environmental sensors.
.It Dv RND_TYPE_POWER
Power sensors and timing of power-related events.
.It Dv RND_TYPE_NET
Network interfaces, typically sampling packet timings.
By default, sample from network interfaces are ignored, for hysterical
raisins.
.It Dv RND_TYPE_RNG
Hardware random number generators.
.It Dv RND_TYPE_SKEW
Skew between clocks.
.It Dv RND_TYPE_TAPE
Tape devices, typically sampling I/O timings.
.It Dv RND_TYPE_TTY
Tty devices, typically sampling interrupt timings.
.It Dv RND_TYPE_VM
Virtual memory fault timings.
.It Dv RND_TYPE_UNKNOWN
Unknown sources, or sources not otherwise classified.
.El
.Sh FUNCTIONS
.Bl -tag -width abcd
.It Fn rndsource_setcb "rnd_source" "callback" "cookie"
Sets a callback to be invoked when the entropy pool is hungry
to draw data from this source on demand.
Optional; if used, must be used
.Em before
.Fn rnd_attach_source ,
and the caller must pass
.Dv RND_FLAG_HASCB
to
.Fn rnd_attach_source .
.Pp
The callback is invoked as
.Fo callback
.Fa nbytes
.Fa cookie
.Fc ,
where
.Fa nbytes
is the number of bytes requested for the entropy pool, and
.Fa cookie
is the cookie that was passed to
.Fn rndsource_setcb .
The callback normally does one of two things:
.Bl -dash
.It
Sends a request to a hardware device for entropy and returns.
The hardware will later return data asynchronously by an interrupt, and
the callback will use
.Fn rnd_add_data
or
.Fn rnd_add_uint32
to add the data to the pool.
.It
Synchronously gathers entropy from hardware \(em for example, by a CPU
instruction like Intel RDSEED.
In this case, in order to add data to the pool
.Em before
returning, the callback
.Em must
use
.Fn rnd_add_data_sync ,
not
.Fn rnd_add_data
or
.Fn rnd_add_uint32 .
.El
.Pp
.Nm
issues calls to each source's
.Fa callback
in serial \(em it never issues two calls to the same source's callback
at the same time in two differen threads or on two different CPUs.
.Pp
The callback may be invoked in thread context or soft interrupt
context, up to
.Dv SOFTINT_SERIAL ,
and as such must follow the rules of soft interrupt handlers in
.Xr softint 9
\(em that is, the callback must never sleep, except on adaptive
.Xr mutex 9
locks at
.Dv IPL_SOFTSERIAL .
The callback will never be called in hard interrupt context.
.It Fn rnd_attach_source "rnd_source" "devname" "type" "flags"
Makes
.Fa rnd_source
available for entropy collection.
Must be called
.Em before
the source struct pointed to by
.Fa rnd_source
is used in any of the following functions.
If a callback was specified with
.Fn rndsource_setcb ,
the kernel may invoke it at any time after
.Fn rnd_attach_source
until
.Fn rnd_detach_source ,
so the callback must be ready to be invoked
.Em before
calling
.Fn rnd_attach_source .
.Pp
The
.Fa devname
is exposed via
.Xr rnd 4
and
.Xr rndctl 8 .
The
.Fa type
must be one of the
.Dv RND_TYPE_*
constants above.
The
.Fa flags
are the bitwise-or of any of the following constants:
.Bl -tag -width abcd
.It Dv RND_FLAG_HASCB
The random source has a callback, which must have been set with
.Fn rndsource_setcb .
.It Dv RND_FLAG_COLLECT_TIME
Enter the timing of each
.Fn rnd_add_*
call into the entropy pool.
If not set, at most only the data arguments to
.Fn rnd_add_*
will be entered.
.It Dv RND_FLAG_COLLECT_VALUE
Enter the data arguments passed to the
.Fn rnd_add_*
functions into the pool.
If not set, the data will be ignored; at most the timing of the sample
will be entered.
.It Dv RND_FLAG_DEFAULT
Equivalent to
.Dv RND_FLAG_COLLECT_TIME | RND_FLAG_COLLECT_VALUE .
.It Dv RND_FLAG_ESTIMATE_TIME , RND_FLAG_ESTIMATE_VALUE
Legacy options no longer used.
.El
.It Fn rnd_detach_source "rnd_source"
Disconnects
.Fa rnd_source
from entropy collection.
The kernel will cease to invoke the callback, if any, and the caller
must not use
.Fa rnd_source
with any of the
.Fn rnd_add_*
functions after
.Fn rnd_detach_source .
The caller may release the memory for
.Fa rnd_source
afterward.
.It Fn rnd_add_data "rnd_source" "data" "len" "entropy"
Enters
.Fa len
bytes at
.Fa data
into the entropy pool, if
.Dv RND_FLAG_COLLECT_VALUE
was specified for
.Fa rnd_source ,
and a timestamp, if
.Dv RND_FLAG_COLLECT_TIME
was specified.
.Pp
The argument
.Fa entropy
provides a conservative estimate for the number of bits of entropy in
the
.Em physical process
that generated the data, given all the past samples.
Drivers for devices for which this is not known should pass zero;
typically only drivers for hardware random number generators pass
nonzero values.
Hardware random number generator drivers should perform on-line
self-tests before advertising nonzero entropy for samples.
.Pp
.Fn rnd_add_data
.Em must not
be used during a callback as set with
.Fn rndsource_setcb ;
use
.Fn rnd_add_data_sync
instead.
.It Fn rnd_add_data_sync "rnd_source" "data" "len" "entropy"
Like
.Fn rnd_add_data ,
but may be used in a callback as set with
.Fn rndsource_setcb .
.It Fn rnd_add_uint32 "rnd_source" "datum"
Equivalent to
.Li rnd_add_data Ns ( Ns Fa rnd_source , Li & Ns Fa datum , Li 4 , 0 ) .
.Pp
.Fn rnd_add_uint32
.Em must not
be used during a callback as set with
.Fn rndsource_setcb ;
use
.Fn rnd_add_data_sync
instead.
.El
.Sh FILES
These functions are declared in src/sys/sys/rndsource.h and defined in
src/sys/kern/kern_entropy.c.
.Sh EXAMPLES
.Bd -literal
struct xyz_softc {
...
struct krndsource sc_rndsource;
};
static void
xyz_attach(device_t parent, device_t self, void *aux)
{
struct xyz_softc *sc = device_private(self);
...
rndsource_setcb(&sc->sc_rndsource, xyz_get, sc);
rnd_attach_source(&sc->sc_rndsource, device_xname(self),
RND_TYPE_RNG, RND_FLAG_DEFAULT);
}
static int
xyz_detach(device_t self, int flags)
{
...
rnd_detach_source(&sc->sc_rndsource);
...
return 0;
}
static void
xyz_get(size_t nbytes, void *cookie)
{
struct xyz_softc *sc = cookie;
uint32_t v;
unsigned timo = 10;
while (nbytes) {
while (bus_space_read_4(sc->sc_bst, sc->sc_bsh,
XYZ_RNGREADY) == 0) {
if (--timo == 0)
return;
DELAY(10);
}
v = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
XYZ_RNGDATUM);
/* data sheet sez 18 bits entropy in 32-bit sample */
rnd_add_data_sync(&sc->sc_rndsource, &v, sizeof v, 18);
nbytes -= 18/NBBY;
}
}
static void
xyz_intr(void *cookie)
{
struct xyz_softc *sc = cookie;
uint32_t isr;
isr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, XYZ_ISR);
bus_space_write_4(sc->sc_bst, sc->sc_bsh, XYZ_ISR, isr);
rnd_add_uint32(&sc->sc_rndsource, isr);
...
}
.Ed
.Sh SEE ALSO
.Xr rnd 4 ,
.Xr rndctl 8 ,
.Xr cprng 9
.Sh HISTORY
The random device was introduced in
.Nx 1.3 .
It was substantially rewritten in
.Nx 6.0 ,
and again in
.Nx 10.0 .
.Sh AUTHORS
This implementation was written by
.An Taylor R Campbell Aq Mt riastradh@NetBSD.org .