Updated: 2022/Sep/29

Please read Privacy Policy. It's for your privacy.


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

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

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
     The 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:
     1.   Allocate and zero a struct krndsource object before using the RND
          functions.
     2.   Optionally, set a callback with rndsource_setcb() if appropriate,
          e.g. for an on-demand hardware random number generator.
     3.   Attach the random source with rnd_attach_source().
     4.   Enter data with rnd_add_data(), rnd_add_data_intr(), or
          rnd_add_uint32(), or, if in the callback, rnd_add_data_sync().
     5.   When the driver is done, detach it with rnd_detach_source().

     The following types of random sources are defined:
     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 to
           draw data from this source on demand.  Optional; if used, must be
           used before 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:

           -   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(), 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(), 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)
           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().

           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
                 with rndsource_setcb().

           RND_FLAG_COLLECT_TIME
                 Enter the timing of each 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
                 Enter the data arguments passed to the 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
                 Equivalent to RND_FLAG_COLLECT_TIME | RND_FLAG_COLLECT_VALUE.

           RND_FLAG_ESTIMATE_TIME, RND_FLAG_ESTIMATE_VALUE
                 Legacy options no longer used.

     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.

     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.

           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)
           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.

           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.

     rnd_add_uint32(rnd_source, datum)
           Equivalent to 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.

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

EXAMPLES
     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
     rnd(4), rndctl(8), cprng(9)

HISTORY
     The random device was introduced in NetBSD 1.3.  It was substantially
     rewritten in NetBSD 6.0, and again in NetBSD 10.0.

AUTHORS
     This implementation was written by Taylor R Campbell
     <riastradh@NetBSD.org>.

NetBSD 10.99                    April 25, 2020                    NetBSD 10.99