RND(9) | Kernel Developer's Manual | RND(9) |
RND
, rnd_attach_source
,
rnd_detach_source
,
rnd_add_data
,
rnd_add_data_intr
,
rnd_add_data_sync
,
rnd_add_uint32
—
#include <sys/rndsource.h>
typedef struct krndsource krndsource_t;
void
rndsource_setcb
(krndsource_t
*rnd_source, void
(*callback)(size_t, void *),
void *cookie);
void
rnd_attach_source
(krndsource_t
*rnd_source, char
*devname, uint32_t
source_type, uint32_t
flags);
void
rnd_detach_source
(krndsource_t
*rnd_source);
void
rnd_add_data
(krndsource_t
*rnd_source, void
*data, uint32_t
len, uint32_t
entropy);
void
rnd_add_data_intr
(krndsource_t
*rnd_source, void
*data, uint32_t
len, uint32_t
entropy);
void
rnd_add_data_sync
(krndsource_t
*rnd_source, void
*data, uint32_t
len, uint32_t
entropy);
void
rnd_add_uint32
(krndsource_t
*rnd_source, uint32_t
datum);
RND
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 cprng(9) and
rnd(4)
(/dev/random, /dev/urandom).
Usage model:
RND
functions.rndsource_setcb
()
if appropriate, e.g. for an on-demand hardware random number
generator.rnd_attach_source
().rnd_add_data
(),
rnd_add_data_intr
(), or
rnd_add_uint32
(), or, if in the callback,
rnd_add_data_sync
().rnd_detach_source
().The following types of random sources are defined:
RND_TYPE_DISK
RND_TYPE_ENV
RND_TYPE_POWER
RND_TYPE_NET
RND_TYPE_RNG
RND_TYPE_SKEW
RND_TYPE_TAPE
RND_TYPE_TTY
RND_TYPE_VM
RND_TYPE_UNKNOWN
rndsource_setcb
(rnd_source,
callback, cookie)rnd_attach_source
(), and
the caller must pass RND_FLAG_HASCB
to
rnd_attach_source
().
The callback is invoked as
callback
(nbytes,
cookie);, where nbytes is
the number of bytes requested for the entropy pool, and
cookie is the cookie that was passed to
rndsource_setcb
(). The callback normally does
one of two things:
rnd_add_data
(),
rnd_add_data_intr
(), or
rnd_add_uint32
() to add the data to the
pool.rnd_add_data_sync
(), not
rnd_add_data
(),
rnd_add_data_intr
() or
rnd_add_uint32
().RND
issues calls to each source's
callback in serial — it never issues two
calls to the same source's callback at the same time in two differen
threads or on two different CPUs.
The callback may be invoked in thread context or soft
interrupt context, up to SOFTINT_SERIAL
, and as
such must follow the rules of soft interrupt handlers in
softint(9) — that
is, the callback must never sleep, except on adaptive
mutex(9) locks at
IPL_SOFTSERIAL
. The callback will never be
called in hard interrupt context.
rnd_attach_source
(rnd_source,
devname, type,
flags)rndsource_setcb
(), the kernel may invoke it at any
time after rnd_attach_source
() until
rnd_detach_source
(), so the callback must be ready
to be invoked before calling
rnd_attach_source
().
The devname is exposed via
rnd(4) and
rndctl(8). The
type must be one of the
RND_TYPE_*
constants above. The
flags are the bitwise-or of any of the following
constants:
RND_FLAG_HASCB
rndsource_setcb
().RND_FLAG_COLLECT_TIME
rnd_add_*
() call into
the entropy pool. If not set, at most only the data arguments to
rnd_add_*
() will be entered.RND_FLAG_COLLECT_VALUE
rnd_add_*
() functions into the pool. If not
set, the data will be ignored; at most the timing of the sample will
be entered.RND_FLAG_DEFAULT
RND_FLAG_COLLECT_TIME
|
RND_FLAG_COLLECT_VALUE
.RND_FLAG_ESTIMATE_TIME
,
RND_FLAG_ESTIMATE_VALUE
rnd_detach_source
(rnd_source)rnd_add_*
() functions after
rnd_detach_source
(). The caller may release the
memory for rnd_source afterward.rnd_add_data
(rnd_source,
data, len,
entropy)RND_FLAG_COLLECT_VALUE
was
specified for rnd_source, and a timestamp, if
RND_FLAG_COLLECT_TIME
was specified.
The argument entropy provides a conservative estimate for the number of bits of entropy in the 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.
rnd_add_data
() must
not be used during a callback as set with
rndsource_setcb
(); use
rnd_add_data_sync
() instead.
rnd_add_data
() must
not be called from thread context with spin locks held.
For compatibility, rnd_add_data
()
currently may but should not be
called from interrupt context, possibly with spin locks held. However,
this may be forbidden in the future; use
rnd_add_data_intr
() from interrupt context
instead, if the work can't be usefully deferred to softint or
thread.
rnd_add_data_intr
(rnd_source,
data, len,
entropy)rnd_add_data
(), but if this fills or would
overflow a sample buffer, schedules a softint to process it and discards
an unspecified subset of the data while counting zero entropy for the
sample.
rnd_add_data_intr
() may be called from
any context, including hard interrupt context, including contexts where
spin locks are held, except that it must not be used
during a callback as set with rndsource_setcb
();
use rnd_add_data_sync
() in that context
instead.
rnd_add_data_sync
(rnd_source,
data, len,
entropy)rnd_add_data
(), but may be used in a callback
as set with rndsource_setcb
(). Must always be
called in thread context.rnd_add_uint32
(rnd_source,
datum)rnd_add_data_intr
(rnd_source,
&
datum,
4
, 0
).
rnd_add_uint32
() may be called from
any context, including hard interrupt context, including contexts where
spin locks are held, except that it must not be used
during a callback as set with rndsource_setcb
();
use rnd_add_data_sync
() in that context
instead.
rnd_add_uint32
() is meant for cheaply
taking samples from devices that aren't designed to be hardware random
number generators.
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); ... }
April 25, 2020 | NetBSD 10.0 |