RND(9) | Kernel Developer's Manual | RND(9)

# NAME

`RND`, `rnd_attach_source`, `rnd_detach_source`, `rnd_add_data`, `rnd_add_data_sync`, `rnd_add_uint32` —
functions to make a device available for entropy collection

# SYNOPSIS

`#include <sys/rndsource.h>`

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_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

These `RND` functions make a device available for entropy collection for the kernel entropy pool, which provides key material for the cprng(9) and rnd(4) (/dev/random) interfaces.

The caller must zero an rnd_source object before using it. Ideally the first argument rnd_source of these functions gets included in the devices' entity struct, but any means to permanently (statically) attach one such argument to one incarnation of the device is ok. Do not share rnd_source structures between two devices, and make sure to serialize all access to each rnd_source, for example with mutex(9).

`rndsource_setcb`(krndsource_t *rnd_source, void (*callback)(size_t, void *), void *cookie)
  This function sets a callback to be invoked when the kernel entropy pool is hungry. It is optional; if used, it must be used before `rnd_attach_source`(), and the caller must pass `RND_FLAG_HASCB` to `rnd_attach_source`() in order for the callback to be used. 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:
  - 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`() or `rnd_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`(), not `rnd_add_data`() or `rnd_add_uint32`().
`rnd_attach_source`(krndsource_t *rnd_source, char *devname, uint32_t source_type, uint32_t flags)
  This function announces the availability of a device for entropy collection. It must be called before the source struct pointed to by rnd_source is used in any of the following functions.

  devname is the name of the device. It is used to print a message (if the kernel is compiled with ``options RND_VERBOSE'') and also for status information printed with rndctl(8).

  source_type is `RND_TYPE_NET` for network devices, `RND_TYPE_DISK` for physical disks, `RND_TYPE_TAPE` for a tape drive, `RND_TYPE_TTY` for a tty, `RND_TYPE_RNG` for a random number generator, and `RND_TYPE_ENV` for an environment sensor. `RND_TYPE_UNKNOWN` is not to be used as a type. It is used internally to the rnd system.

  flags are the logical OR of `RND_FLAG_COLLECT_VALUE` (mix data provided by this source into the pool) `RND_FLAG_COLLECT_TIME` (mix timestamps from this source into the pool) `RND_FLAG_ESTIMATE_VALUE` (use a delta estimator to count bits of entropy from this source's data towards the pool estimate) `RND_FLAG_ESTIMATE_TIME` (use a delta estimator to count bits of entropy from this source's timestamps towards the pool estimate) `RND_FLAG_HASCB` (caller specified a callback with `rndsource_setcb`()). For many devices, `RND_FLAG_DEFAULT` (`RND_FLAG_COLLECT_VALUE` | `RND_FLAG_COLLECT_TIME` | `RND_FLAG_ESTIMATE_TIME`) is the best choice. Note that devices of type `RND_TYPE_NET` default to `RND_FLAG_COLLECT_VALUE` | `RND_FLAG_COLLECT_TIME` (no entropy counted).

`rnd_detach_source`(krndsource_t *rnd_source)
  This function disconnects the device from entropy collection.
`rnd_add_uint32`(krndsource_t *rnd_source, uint32_t datum)
  This function adds the value of datum to the entropy pool. No entropy is assumed to be collected from this value, it merely helps stir the entropy pool. All entropy is gathered from jitter between the timing of events.

  Note that using a constant for datum does not weaken security, but it does not help. Try to use something that can change, such as an interrupt status register which might have a bit set for receive ready or transmit ready, or other device status information.

  To allow the system to gather the timing information accurately, this call should be placed within the actual hardware interrupt service routine. Care must be taken to ensure that the interrupt was actually serviced by the interrupt handler, since on some systems interrupts can be shared.

  This function loses nearly all usefulness if it is called from a scheduled software interrupt. If that is the only way to add the device as an entropy source, don't.

  If it is desired to mix in the datum and to add in a timestamp, but not to actually estimate entropy from a source of randomness, passing `NULL` for rnd_source is permitted, and the device does not need to be attached.

  `rnd_add_uint32`() must not be used during a callback as set with `rndsource_setcb`(); use `rnd_add_data_sync`() instead.

`rnd_add_data`(krndsource_t *rnd_source, void *data, uint32_t len, uint32_t entropy)
  adds (hopefully) random data to the entropy pool. len is the number of bytes in data and entropy is an "entropy quality" measurement. If every bit of data is known to be random, entropy is the number of bits in data.

  Timing information is also used to add entropy into the system, using inter-event timings.

  If it is desired to mix in the data and to add in a timestamp, but not to actually estimate entropy from a source of randomness, passing `NULL` for rnd_source is permitted, and the device does not need to be attached.

  `rnd_add_data`() must not be used during a callback as set with `rndsource_setcb`(); use `rnd_add_data_sync`() instead.

# INTERNAL ENTROPY POOL MANAGEMENT

When a hardware event occurs (such as completion of a hard drive transfer or an interrupt from a network device) a timestamp is generated. This timestamp is compared to the previous timestamp recorded for the device, and the first, second, and third order differentials are calculated.

If any of these differentials is zero, no entropy is assumed to have been gathered. If all are non-zero, one bit is assumed. Next, data is mixed into the entropy pool using an LFSR (linear feedback shift register).

To extract data from the entropy pool, a cryptographically strong hash function is used. The output of this hash is mixed back into the pool using the LFSR, and then folded in half before being returned to the caller.

Mixing the actual hash into the pool causes the next extraction to return a different value, even if no timing events were added to the pool. Folding the data in half prevents the caller to derive the actual hash of the pool, preventing some attacks.

In the NetBSD kernel, values should be extracted from the entropy pool only via the cprng(9) interface. Direct access to the entropy pool is unsupported and may be dangerous. There is no supported API for direct access to the output of the entropy pool.

# FILES

These functions are declared in src/sys/sys/rndsource.h and defined in src/sys/kern/kern_rndq.c.

# SEE ALSO

rnd(4), rndctl(8), cprng(9)

# HISTORY

The random device was introduced in NetBSD 1.3.

# AUTHORS

This implementation was written by Michael Graff <explorer@flame.org> using ideas and algorithms gathered from many sources, including the driver written by Ted Ts'o.

# BUGS

The only good sources of randomness are quantum mechanical, and most computers avidly avoid having true sources of randomness included. Don't expect to surpass "pretty good".

August 10, 2014 | NetBSD 9.5