| 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_DISKRND_TYPE_ENVRND_TYPE_POWERRND_TYPE_NETRND_TYPE_RNGRND_TYPE_SKEWRND_TYPE_TAPERND_TYPE_TTYRND_TYPE_VMRND_TYPE_UNKNOWNrndsource_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_HASCBrndsource_setcb().RND_FLAG_COLLECT_TIMErnd_add_*() call into
          the entropy pool. If not set, at most only the data arguments to
          rnd_add_*() will be entered.RND_FLAG_COLLECT_VALUErnd_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_DEFAULTRND_FLAG_COLLECT_TIME |
          RND_FLAG_COLLECT_VALUE.RND_FLAG_ESTIMATE_TIME,
        RND_FLAG_ESTIMATE_VALUErnd_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 |