RND(9)
π RND(9) β Kernel Developer's Manual, but make it entropy π
okay so bestie, welcome to RND(9) β aka the functions that let you make a device available for entropy collection. yes it's the kernel developer's manual page, yes it's long, and yes we're gonna get through it together because this stuff is genuinely iconic. grab a snack π
β¨ NAME β¨
RND, rnd_attach_source, rnd_detach_source, rnd_add_data, rnd_add_data_intr, rnd_add_data_sync, rnd_add_uint32 β functions to make a device available for entropy collection. that's the whole squad right there π«Ά
β¨ SYNOPSIS β¨
#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);
β¨ DESCRIPTION β¨
so the RND functions are literally how drivers collect samples of physical observations β think network packet timings, or hardware random number generator outputs β and feed them into a kernel entropy pool. that pool then derives key material for cprng(9) and rnd(4) (/dev/random, /dev/urandom). it's giving β¨chaos into orderβ¨
The usage model, bestie β follow it in order:
- Allocate and zero a
struct krndsourceobject before using theRNDfunctions. (zero it. do not skip. π) - Optionally, set a callback with
rndsource_setcb()if appropriate, e.g. for an on-demand hardware random number generator. - Attach the random source with
rnd_attach_source(). - Enter data with
rnd_add_data(),rnd_add_data_intr(), orrnd_add_uint32(), or, if in the callback,rnd_add_data_sync(). - When the driver is done, detach it with
rnd_detach_source().
The types of random sources that are defined (the whole roster π):
RND_TYPE_DISKβ Disk devices, typically sampling seek timings.RND_TYPE_ENVβ Environmental sensors.RND_TYPE_POWERβ Power sensors and timing of power-related events.RND_TYPE_NETβ Network interfaces, typically sampling packet timings. By default, sample from network interfaces are ignored, for hysterical raisins. πRND_TYPE_RNGβ Hardware random number generators.RND_TYPE_SKEWβ Skew between clocks.RND_TYPE_TAPEβ Tape devices, typically sampling I/O timings.RND_TYPE_TTYβ Tty devices, typically sampling interrupt timings.RND_TYPE_VMβ Virtual memory fault timings.RND_TYPE_UNKNOWNβ Unknown sources, or sources not otherwise classified.
β¨ FUNCTIONS β¨
π«Ά rndsource_setcb(rnd_source, callback, cookie)
Sets a callback to be invoked when the entropy pool is hungry and wants to draw data from this source on demand. it's optional, but if you're gonna use it, it must be used before rnd_attach_source(), and the caller must pass RND_FLAG_HASCB to rnd_attach_source(). no cap, order matters π
The callback gets 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(). and the callback normally does one of two things:
- 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
rnd_add_data(),rnd_add_data_intr(), orrnd_add_uint32()to add the data to the pool. - Synchronously gathers entropy from hardware β for example, by a CPU instruction like Intel RDSEED. In this case, in order to add data to the pool before returning, the callback must use
rnd_add_data_sync(), notrnd_add_data(),rnd_add_data_intr()orrnd_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 different threads or on two different CPUs. so no race-y bestie behaviour here, it's very main character of it π₯
β οΈ The callback may be invoked in thread context or soft interrupt context, up toSOFTINT_SERIAL, and as such must follow the rules of soft interrupt handlers insoftint(9)β that is, the callback must never sleep, except on adaptivemutex(9)locks atIPL_SOFTSERIAL. The callback will never be called in hard interrupt context.
π«Ά rnd_attach_source(rnd_source, devname, type, flags)
Makes rnd_source available for entropy collection. Must be called before the source struct pointed to by rnd_source is used in any of the following functions. If a callback was specified with 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(). like, be ready, bestie, it can come through any second β°
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β The random source has a callback, which must have been set withrndsource_setcb().RND_FLAG_COLLECT_TIMEβ Enter the timing of eachrnd_add_*()call into the entropy pool. If not set, at most only the data arguments tornd_add_*()will be entered.RND_FLAG_COLLECT_VALUEβ Enter the data arguments passed to thernd_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β Equivalent toRND_FLAG_COLLECT_TIME | RND_FLAG_COLLECT_VALUE.RND_FLAG_ESTIMATE_TIME,RND_FLAG_ESTIMATE_VALUEβ Legacy options no longer used. π§ (they ate, back in the day, but that era is over)
π«Ά rnd_detach_source(rnd_source)
Disconnects rnd_source from entropy collection. The kernel will cease to invoke the callback, if any, and the caller must not use rnd_source with any of the rnd_add_*() functions after rnd_detach_source(). The caller may release the memory for rnd_source afterward. it's the breakup arc π once you detach, you don't text back.
π«Ά rnd_add_data(rnd_source, data, len, entropy)
Enters len bytes at data into the entropy pool, if 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. lowkey do not lie about your entropy, the pool will know π
β οΈrnd_add_data()must not be used during a callback as set withrndsource_setcb(); usernd_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. (it's giving deprecated-but-not-yet, so don't get comfy π¬)
π«Ά rnd_add_data_intr(rnd_source, data, len, entropy)
Tries to enter len bytes at data into the entropy pool like 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. so yeah, some of your data may simply β¨leaveβ¨
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)
Like rnd_add_data(), but may be used in a callback as set with rndsource_setcb(). Must always be called in thread context. that's the whole vibe check for this one π¦
π«Ά rnd_add_uint32(rnd_source, datum)
Equivalent to rnd_add_data_intr(rnd_source, &datum, 4, 0). short and sweet, we love a one-liner π
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. like, they're doing their best, and honestly? iconic of them π
β¨ FILES β¨
These functions are declared in src/sys/sys/rndsource.h and defined in src/sys/kern/kern_entropy.c. the receipts, if you will π§Ύ
β¨ EXAMPLES β¨
okay this is the part where it all comes together β look at this gorgeous little driver:
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);
...
}
β¨ SEE ALSO β¨
β¨ HISTORY β¨
The random device was introduced in NetBSD 1.3. It was substantially rewritten in NetBSD 6.0, and again in NetBSD 10.0. glow-up after glow-up after glow-up, honestly π
π AUTHORS π
Okay so bestie, this whole gorgeous implementation? Literally written by Taylor R Campbell π β and yes, you can slide into his inbox at <riastradh@NetBSD.org> if you wanna talk shop, report a vibe-killing bug, or just say thanks π«Ά
Like, one person. Wrote it. The entire thing. Not me being dramatic, that's just the facts π
He's riastradh on NetBSD dot org, no cap β that's the email, character for character, don't @ me with a typo π
Fr fr, if you're gonna email the man about a bug, be nice and be specific. Bestie etiquette π
And that's the whole page, bestie β you made it to the end, I'm so proud of you honestly π₯Ήβ¨
πΈ Just so we're keeping it a hundred: this writeup is from the Debian edition of the page, dated April 25, 2020, and the page goes by RND(9) π¦ Slay, go forth, and may all your random numbers be genuinely random ππ
π¦ where this page comes from
- nixpkgs unstable: netbsd-source 11.0
- Copyright (c) 1997 The NetBSD Foundation, Inc
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms