tech-security archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Patch: rework kernel random number subsystem



The attached diff includes many changes to the kernel random number
subsystem.

It is (most of) the first step in a three step process I envision for major
overhaul of this subsystem:

        1) Provide infrastructure needed to separate entropy
           harvesting from random stream generation.  Clean up
           interfaces between existing kernel components that
           deal with random number generation and consumption.

        2) Replace all direct read access to the entropy pool with
           an appropriate random stream generator, keyed from the pool.
           Clean up the current mess in which the same source files
           implement the entropy pool and the userspace pseudodevices
           /dev/random and /dev/urandom.

        3) Replace the entropy pool itself with a more modern design
           such as Fortuna.

Here are the changes you will find in this patch:

        1) Two new components are provided, "rngtest" (subr_rngtest.c)
           and "nist_ctr_drbg" (crypto/nist_ctr_drbg).  The rngtest component
           implements the FIPS 140-2 statistical RNG test.  It is based on
           work by Greg Rose at Qualcomm.  The nist_ctr_drbg component
           implements the NIST SP800-90 CTR_DRBG, which uses AES in a
           modified counter mode to generate a backtracking-resistant random
           stream.  It is based on work by Henric Jungheim.

           Additionally, an abstration layer "cprng" (subr_cprng.c) is
           provided for in-kernel consumers of randomness; see below.

        2) A generic interface, "rndsink", for stream generators to request
           that they be re-keyed with good quality entropy from the pool
           as soon as it is available, is provided.

        3) The arc4random/arc4randbytes implementation in libkern is
           adjusted to use the rndsink interface for rekeying, which
           helps address the problem of low quality keys at boot time.

        4) The arc4random/arc4randbytes API is deprecated for in-kernel
           use.  It is replaced by "cprng_fast".  The rnd_extract_data
           interface is deprecated for in-kernel use.  It is replaced
           by "cprng_strong".  The current cprng_fast implementation
           wraps the existing arc4random implementation.  The current
           cprng_strong implementation wraps the CTR_DRBG implementation,
           allowing as many private instances of the CTR_DRBG as desired.

           Both interfaces are rekeyed from the entropy pool automatically
           at intervals justifiable from best current cryptographic practice.

           *When these generators are rekeyed, the 'rngtest' test is run
           on their output and the kernel will panic if it fails.*  It
           is not the long-term intent to panic on a rngtest failure,
           but rather to rekey; but this is a good way to detect bugs in
           the implementation (see below).

        5) The AES code in src/crypto/rijndael is no longer an optional
           kernel component, as it is required by cprng_strong, which is
           not an optional kernel component.

        6) The entropy pool output is subjected to the rngtest tests at
           startup time.  Entropy pool _input_ from hardware random
           number generators is subjected to the rngtest tests at attach
           time, as well as the FIPS continuous-output test, to detect
           bad or stuck hardware RNGs.

        7) The sysctl node kern.urandom is now connected to cprng_strong
           rather than the entropy pool (this allows cprng_strong testing
           from userspace without replacing the pseudodevice yet).

        8) The set of printfs triggered by RND_VERBOSE has been expanded.

WARNING:        #7 and #8 reveal some kind of synchronization or locking
                bug in this patch.  #8 causes the entropy pool to log to
                the console whenever it supplies rekeying entropy.  #7
                causes 'sysctl kern.urandom' to read from a cprng_strong
                instance.

                Performing around 1000 consecutive such sysctl calls will
                reveal corruption of the cprng_strong state: it is not
                rekeyed (nor should it yet be), but is corrupted in such
                a way that it thinks it has been, triggering the rngtest
                statistical test, which then fails.

                Score 1 for the test, detecting a bug I can't sort out
                yet; score 0 for me for not seeing what happens.  Help
                with this one (it's easy to reproduce!) much appreciated.

        9) some API mess in rnd.c/rnd.h is cleaned up, such as exposing
           structures with in-kernel void * to userspace in arrays, thus
           causing compat32 issues.

        10) I have made a start at letting the entropy pool supply useful
            output *much* earlier in the boot process.  There is a lot
            more to do here.

This patch is against last night's sources and builds release successfully
for amd64.  Works, too, except the bug noted at WARNING above.  I am
aware there are KNF issues and would prefer to fix them later.  Help,
comments, criticism much appreciated.

Thanks!

Thor
Index: sys/altq/altq_blue.c
===================================================================
RCS file: /cvsroot/src/sys/altq/altq_blue.c,v
retrieving revision 1.22
diff -u -b -r1.22 altq_blue.c
--- sys/altq/altq_blue.c        4 Mar 2007 05:59:00 -0000       1.22
+++ sys/altq/altq_blue.c        21 Oct 2011 20:31:02 -0000
@@ -80,6 +80,7 @@
 #include <sys/errno.h>
 #include <sys/kernel.h>
 #include <sys/kauth.h>
+#include <sys/cprng.h>
 
 #include <net/if.h>
 #include <net/if_types.h>
@@ -504,7 +505,7 @@
 static int
 drop_early(blue_t *rp)
 {
-       if ((arc4random() % rp->blue_max_pmark) < rp->blue_pmark) {
+       if ((cprng_fast32() % rp->blue_max_pmark) < rp->blue_pmark) {
                /* drop or mark */
                return (1);
        }
Index: sys/altq/altq_cdnr.c
===================================================================
RCS file: /cvsroot/src/sys/altq/altq_cdnr.c,v
retrieving revision 1.19
diff -u -b -r1.19 altq_cdnr.c
--- sys/altq/altq_cdnr.c        4 Mar 2007 05:59:01 -0000       1.19
+++ sys/altq/altq_cdnr.c        21 Oct 2011 20:31:02 -0000
@@ -46,6 +46,7 @@
 #include <sys/kernel.h>
 #include <sys/queue.h>
 #include <sys/kauth.h>
+#include <sys/cprng.h>
 
 #include <net/if.h>
 #include <net/if_types.h>
@@ -801,7 +802,7 @@
         * marker
         */
        if (avg_rate > tsw->cmtd_rate) {
-               u_int32_t randval = arc4random() % avg_rate;
+               u_int32_t randval = cprng_fast32() % avg_rate;
 
                if (avg_rate > tsw->peak_rate) {
                        if (randval < avg_rate - tsw->peak_rate) {
Index: sys/altq/altq_red.c
===================================================================
RCS file: /cvsroot/src/sys/altq/altq_red.c,v
retrieving revision 1.28
diff -u -b -r1.28 altq_red.c
--- sys/altq/altq_red.c 18 Jun 2008 09:06:27 -0000      1.28
+++ sys/altq/altq_red.c 21 Oct 2011 20:31:02 -0000
@@ -87,6 +87,7 @@
 #include <sys/time.h>
 #endif
 #endif /* ALTQ3_COMPAT */
+#include <sys/cprng.h>
 
 #include <net/if.h>
 
@@ -505,7 +506,7 @@
         * drop probability = (avg - TH_MIN) / d
         */
 
-       if ((arc4random() % d) < fp_len) {
+       if ((cprng_fast32() % d) < fp_len) {
                /* drop or mark */
                return (1);
        }
Index: sys/altq/altq_rmclass.c
===================================================================
RCS file: /cvsroot/src/sys/altq/altq_rmclass.c,v
retrieving revision 1.21
diff -u -b -r1.21 altq_rmclass.c
--- sys/altq/altq_rmclass.c     15 Jul 2008 16:18:08 -0000      1.21
+++ sys/altq/altq_rmclass.c     21 Oct 2011 20:31:03 -0000
@@ -59,6 +59,7 @@
 #ifdef ALTQ3_COMPAT
 #include <sys/kernel.h>
 #endif
+#include <sys/cprng.h>
 
 #include <net/if.h>
 #ifdef ALTQ3_COMPAT
@@ -1777,7 +1778,7 @@
        } else {
                struct mbuf *prev = NULL;
 
-               n = arc4random() % qlen(q) + 1;
+               n = cprng_fast32() % qlen(q) + 1;
                for (i = 0; i < n; i++) {
                        prev = m;
                        m = m->m_nextpkt;
Index: sys/arch/acorn26/ioc/arckbd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/acorn26/ioc/arckbd.c,v
retrieving revision 1.20
diff -u -b -r1.20 arckbd.c
--- sys/arch/acorn26/ioc/arckbd.c       19 Jul 2011 16:05:10 -0000      1.20
+++ sys/arch/acorn26/ioc/arckbd.c       21 Oct 2011 20:31:03 -0000
@@ -139,7 +139,7 @@
        struct irq_handler      *sc_rirq;
        struct evcnt            sc_rev;
 #if NRND > 0
-       rndsource_element_t     sc_rnd_source;
+       krndsource_t    sc_rnd_source;
 #endif
 };
 
Index: sys/arch/arm/at91/at91dbguvar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/at91/at91dbguvar.h,v
retrieving revision 1.3
diff -u -b -r1.3 at91dbguvar.h
--- sys/arch/arm/at91/at91dbguvar.h     23 Oct 2009 06:53:13 -0000      1.3
+++ sys/arch/arm/at91/at91dbguvar.h     21 Oct 2011 20:31:03 -0000
@@ -82,7 +82,7 @@
 
        int                     enabled;
 #if NRND > 0 && defined(RND_COM)
-       rndsource_element_t  rnd_source;
+       krndsource_t  rnd_source;
 #endif
 };
 
Index: sys/arch/arm/at91/at91usartvar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/at91/at91usartvar.h,v
retrieving revision 1.3
diff -u -b -r1.3 at91usartvar.h
--- sys/arch/arm/at91/at91usartvar.h    23 Oct 2009 06:53:13 -0000      1.3
+++ sys/arch/arm/at91/at91usartvar.h    21 Oct 2011 20:31:03 -0000
@@ -86,7 +86,7 @@
 
        int                     enabled;
 #if NRND > 0 && defined(RND_COM)
-       rndsource_element_t  rnd_source;
+       krndsource_t  rnd_source;
 #endif
 };
 
Index: sys/arch/arm/ep93xx/epcomvar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/ep93xx/epcomvar.h,v
retrieving revision 1.4
diff -u -b -r1.4 epcomvar.h
--- sys/arch/arm/ep93xx/epcomvar.h      23 Oct 2009 00:39:30 -0000      1.4
+++ sys/arch/arm/ep93xx/epcomvar.h      21 Oct 2011 20:31:03 -0000
@@ -83,7 +83,7 @@
 
        int                     enabled;
 #if NRND > 0 && defined(RND_COM)
-       rndsource_element_t  rnd_source;
+       krndsource_t  rnd_source;
 #endif
 };
 
Index: sys/arch/arm/s3c2xx0/sscom_var.h
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/s3c2xx0/sscom_var.h,v
retrieving revision 1.8
diff -u -b -r1.8 sscom_var.h
--- sys/arch/arm/s3c2xx0/sscom_var.h    1 Jul 2011 20:31:39 -0000       1.8
+++ sys/arch/arm/s3c2xx0/sscom_var.h    21 Oct 2011 20:31:03 -0000
@@ -172,7 +172,7 @@
 #endif
 
 #if NRND > 0 && defined(RND_COM)
-       rndsource_element_t  rnd_source;
+       krndsource_t  rnd_source;
 #endif
 #if (defined(MULTIPROCESSOR) || defined(LOCKDEBUG)) && defined(SSCOM_MPLOCK)
        struct simplelock       sc_lock;
Index: sys/arch/arm/sa11x0/sa1111_kbc.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/sa11x0/sa1111_kbc.c,v
retrieving revision 1.12
diff -u -b -r1.12 sa1111_kbc.c
--- sys/arch/arm/sa11x0/sa1111_kbc.c    13 Mar 2010 11:13:31 -0000      1.12
+++ sys/arch/arm/sa11x0/sa1111_kbc.c    21 Oct 2011 20:31:03 -0000
@@ -96,7 +96,7 @@
        int     poll_data;      /* status read from intr handler if polling */
 
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
        pckbport_tag_t pt;
 };
Index: sys/arch/arm/xscale/ixp425_if_npe.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/xscale/ixp425_if_npe.c,v
retrieving revision 1.20
diff -u -b -r1.20 ixp425_if_npe.c
--- sys/arch/arm/xscale/ixp425_if_npe.c 1 Jul 2011 20:32:51 -0000       1.20
+++ sys/arch/arm/xscale/ixp425_if_npe.c 21 Oct 2011 20:31:04 -0000
@@ -127,7 +127,7 @@
        bus_addr_t      sc_stats_phys;  /* phys addr of sc_stats */
        int             sc_if_flags;    /* keep last if_flags */
 #if NRND > 0
-       rndsource_element_t rnd_source; /* random source */
+       krndsource_t rnd_source; /* random source */
 #endif
 };
 
Index: sys/arch/emips/ebus/ace_ebus.c
===================================================================
RCS file: /cvsroot/src/sys/arch/emips/ebus/ace_ebus.c,v
retrieving revision 1.2
diff -u -b -r1.2 ace_ebus.c
--- sys/arch/emips/ebus/ace_ebus.c      18 Jun 2011 17:47:20 -0000      1.2
+++ sys/arch/emips/ebus/ace_ebus.c      21 Oct 2011 20:31:04 -0000
@@ -193,7 +193,7 @@
        int retries; /* number of xfer retry */
 
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
 };
 
Index: sys/arch/emips/ebus/flash_ebus.c
===================================================================
RCS file: /cvsroot/src/sys/arch/emips/ebus/flash_ebus.c,v
retrieving revision 1.2
diff -u -b -r1.2 flash_ebus.c
--- sys/arch/emips/ebus/flash_ebus.c    12 Jun 2011 03:29:33 -0000      1.2
+++ sys/arch/emips/ebus/flash_ebus.c    21 Oct 2011 20:31:05 -0000
@@ -202,7 +202,7 @@
        int retries; /* number of xfer retry */
 
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
 
     /* flash-specific state */
Index: sys/arch/emips/ebus/if_le_ebus.c
===================================================================
RCS file: /cvsroot/src/sys/arch/emips/ebus/if_le_ebus.c,v
retrieving revision 1.2
diff -u -b -r1.2 if_le_ebus.c
--- sys/arch/emips/ebus/if_le_ebus.c    12 Jun 2011 14:31:31 -0000      1.2
+++ sys/arch/emips/ebus/if_le_ebus.c    21 Oct 2011 20:31:05 -0000
@@ -115,7 +115,7 @@
        uint8_t sc_enaddr[ETHER_ADDR_LEN];
        uint8_t sc_pad[2];
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
 };
 
Index: sys/arch/evbarm/dev/plcomvar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/evbarm/dev/plcomvar.h,v
retrieving revision 1.6
diff -u -b -r1.6 plcomvar.h
--- sys/arch/evbarm/dev/plcomvar.h      5 Jan 2008 12:40:34 -0000       1.6
+++ sys/arch/evbarm/dev/plcomvar.h      21 Oct 2011 20:31:05 -0000
@@ -134,7 +134,7 @@
        pps_params_t ppsparam;
 
 #if NRND > 0 && defined(RND_COM)
-       rndsource_element_t  rnd_source;
+       krndsource_t  rnd_source;
 #endif
        struct simplelock       sc_lock;
 };
Index: sys/arch/hp300/dev/rdvar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/hp300/dev/rdvar.h,v
retrieving revision 1.20
diff -u -b -r1.20 rdvar.h
--- sys/arch/hp300/dev/rdvar.h  8 Feb 2011 20:20:13 -0000       1.20
+++ sys/arch/hp300/dev/rdvar.h  21 Oct 2011 20:31:06 -0000
@@ -81,7 +81,7 @@
        int     sc_errcnt;
        struct  rdstats sc_stats;
 #if NRND > 0
-       rndsource_element_t rnd_source;
+       krndsource_t rnd_source;
 #endif
 };
 
Index: sys/arch/hp700/gsc/harmonyvar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/hp700/gsc/harmonyvar.h,v
retrieving revision 1.4
diff -u -b -r1.4 harmonyvar.h
--- sys/arch/hp700/gsc/harmonyvar.h     25 Apr 2008 08:17:52 -0000      1.4
+++ sys/arch/hp700/gsc/harmonyvar.h     21 Oct 2011 20:31:06 -0000
@@ -105,7 +105,7 @@
        int sc_teleshare;
 
 #if NRND > 0
-       rndsource_element_t sc_rnd_source;
+       krndsource_t sc_rnd_source;
        struct callout sc_acc_tmo;
        uint32_t sc_acc, sc_acc_num, sc_acc_cnt;
 #endif
Index: sys/arch/i386/pci/glxsb.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/pci/glxsb.c,v
retrieving revision 1.9
diff -u -b -r1.9 glxsb.c
--- sys/arch/i386/pci/glxsb.c   16 May 2009 16:52:03 -0000      1.9
+++ sys/arch/i386/pci/glxsb.c   21 Oct 2011 20:31:06 -0000
@@ -34,8 +34,8 @@
 #include <sys/mbuf.h>
 #include <sys/types.h>
 #include <sys/callout.h>
-#include <sys/rnd.h>
 #include <sys/bus.h>
+#include <sys/cprng.h>
 
 #include <machine/cpufunc.h>
 
@@ -165,7 +165,7 @@
        int                     sc_nsessions;
        struct glxsb_session    *sc_sessions;
 
-       rndsource_element_t     sc_rnd_source;
+       krndsource_t    sc_rnd_source;
 };
 
 int    glxsb_match(device_t, cfdata_t, void *);
@@ -343,7 +343,7 @@
        memset(ses, 0, sizeof(*ses));
        ses->ses_used = 1;
 
-       arc4randbytes(ses->ses_iv, sizeof(ses->ses_iv));
+       cprng_fast(ses->ses_iv, sizeof(ses->ses_iv));
        ses->ses_klen = cri->cri_klen;
 
        /* Copy the key (Geode LX wants the primary key only) */
Index: sys/arch/macppc/dev/if_gm.c
===================================================================
RCS file: /cvsroot/src/sys/arch/macppc/dev/if_gm.c,v
retrieving revision 1.39
diff -u -b -r1.39 if_gm.c
--- sys/arch/macppc/dev/if_gm.c 18 Jun 2011 08:08:28 -0000      1.39
+++ sys/arch/macppc/dev/if_gm.c 21 Oct 2011 20:31:06 -0000
@@ -87,7 +87,7 @@
        char sc_laddr[6];
 
 #if NRND > 0
-       rndsource_element_t sc_rnd_source; /* random source */
+       krndsource_t sc_rnd_source; /* random source */
 #endif
 };
 
Index: sys/arch/mips/alchemy/dev/if_aumac.c
===================================================================
RCS file: /cvsroot/src/sys/arch/mips/alchemy/dev/if_aumac.c,v
retrieving revision 1.31
diff -u -b -r1.31 if_aumac.c
--- sys/arch/mips/alchemy/dev/if_aumac.c        10 Jul 2011 23:13:23 -0000      
1.31
+++ sys/arch/mips/alchemy/dev/if_aumac.c        21 Oct 2011 20:31:07 -0000
@@ -143,7 +143,7 @@
        int sc_rxptr;                   /* next ready Rx descriptor */
 
 #if NRND > 0
-       rndsource_element_t rnd_source;
+       krndsource_t rnd_source;
 #endif
 
 #ifdef AUMAC_EVENT_COUNTERS
Index: sys/arch/mips/atheros/dev/aevar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/mips/atheros/dev/aevar.h,v
retrieving revision 1.3
diff -u -b -r1.3 aevar.h
--- sys/arch/mips/atheros/dev/aevar.h   28 Apr 2008 20:23:28 -0000      1.3
+++ sys/arch/mips/atheros/dev/aevar.h   21 Oct 2011 20:31:07 -0000
@@ -187,7 +187,7 @@
        int     sc_rxptr;               /* next ready RX descriptor/descsoft */
 
 #if NRND > 0
-       rndsource_element_t sc_rnd_source; /* random source */
+       krndsource_t sc_rnd_source; /* random source */
 #endif
 };
 #endif
Index: sys/arch/mips/sibyte/dev/sbscnvar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/mips/sibyte/dev/sbscnvar.h,v
retrieving revision 1.4
diff -u -b -r1.4 sbscnvar.h
--- sys/arch/mips/sibyte/dev/sbscnvar.h 1 Feb 2011 03:16:54 -0000       1.4
+++ sys/arch/mips/sibyte/dev/sbscnvar.h 21 Oct 2011 20:31:08 -0000
@@ -157,7 +157,7 @@
        u_char          ch_o_dtr_pin, ch_o_rts_pin;
 
 #if NRND > 0 && defined(RND_SBSCN)
-       rndsource_element_t  ch_rnd_source;
+       krndsource_t  ch_rnd_source;
 #endif
 };
 
Index: sys/arch/next68k/dev/mb8795var.h
===================================================================
RCS file: /cvsroot/src/sys/arch/next68k/dev/mb8795var.h,v
retrieving revision 1.11
diff -u -b -r1.11 mb8795var.h
--- sys/arch/next68k/dev/mb8795var.h    24 Apr 2010 19:58:13 -0000      1.11
+++ sys/arch/next68k/dev/mb8795var.h    21 Oct 2011 20:31:08 -0000
@@ -72,7 +72,7 @@
        struct ifmedia sc_media;
 
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t     rnd_source;
 #endif /* NRND */
 
 };
Index: sys/arch/sgimips/hpc/sqvar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/sgimips/hpc/sqvar.h,v
retrieving revision 1.12
diff -u -b -r1.12 sqvar.h
--- sys/arch/sgimips/hpc/sqvar.h        25 Jan 2011 13:12:39 -0000      1.12
+++ sys/arch/sgimips/hpc/sqvar.h        21 Oct 2011 20:31:08 -0000
@@ -157,7 +157,7 @@
        struct evcnt            sq_intrcnt;     /* count interrupts */
 
 #if NRND > 0
-       rndsource_element_t     rnd_source;     /* random source */
+       krndsource_t    rnd_source;     /* random source */
 #endif
        struct hpc_values       *hpc_regs;      /* HPC register definitions */
 
Index: sys/arch/sgimips/mace/if_mec.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sgimips/mace/if_mec.c,v
retrieving revision 1.46
diff -u -b -r1.46 if_mec.c
--- sys/arch/sgimips/mace/if_mec.c      1 Jul 2011 18:53:47 -0000       1.46
+++ sys/arch/sgimips/mace/if_mec.c      21 Oct 2011 20:31:08 -0000
@@ -317,7 +317,7 @@
        int sc_rxptr;                   /* next ready RX buffer */
 
 #if NRND > 0
-       rndsource_element_t sc_rnd_source; /* random source */
+       krndsource_t sc_rnd_source; /* random source */
 #endif
 #ifdef MEC_EVENT_COUNTERS
        struct evcnt sc_ev_txpkts;      /* TX packets queued total */
Index: sys/arch/sun2/dev/if_ec.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sun2/dev/if_ec.c,v
retrieving revision 1.18
diff -u -b -r1.18 if_ec.c
--- sys/arch/sun2/dev/if_ec.c   5 Apr 2010 07:19:32 -0000       1.18
+++ sys/arch/sun2/dev/if_ec.c   21 Oct 2011 20:31:09 -0000
@@ -102,7 +102,7 @@
        uint32_t sc_backoff_seed;       /* seed for the backoff PRNG */
 
 #if NRND > 0
-       rndsource_element_t rnd_source;
+       krndsource_t rnd_source;
 #endif
 };
 
Index: sys/arch/x68k/dev/fd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x68k/dev/fd.c,v
retrieving revision 1.94
diff -u -b -r1.94 fd.c
--- sys/arch/x68k/dev/fd.c      10 Apr 2011 15:23:06 -0000      1.94
+++ sys/arch/x68k/dev/fd.c      21 Oct 2011 20:31:09 -0000
@@ -245,7 +245,7 @@
 #define        SEC_P11 0x03            /* both part */
 
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
 };
 
Index: sys/arch/x86/include/via_padlock.h
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/include/via_padlock.h,v
retrieving revision 1.6
diff -u -b -r1.6 via_padlock.h
--- sys/arch/x86/include/via_padlock.h  19 Feb 2011 13:52:28 -0000      1.6
+++ sys/arch/x86/include/via_padlock.h  21 Oct 2011 20:31:09 -0000
@@ -61,7 +61,7 @@
 
        int                     sc_rnd_hz;
        struct callout          sc_rnd_co;
-       rndsource_element_t     sc_rnd_source;
+       krndsource_t    sc_rnd_source;
        bool                    sc_rnd_attached;
 
        /* normal softc stuff */
Index: sys/arch/x86/pci/fwhrng.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/pci/fwhrng.c,v
retrieving revision 1.3
diff -u -b -r1.3 fwhrng.c
--- sys/arch/x86/pci/fwhrng.c   1 Jul 2011 18:22:08 -0000       1.3
+++ sys/arch/x86/pci/fwhrng.c   21 Oct 2011 20:31:09 -0000
@@ -54,7 +54,7 @@
        bus_space_handle_t sc_sh;
 
        struct callout sc_rnd_ch;
-       rndsource_element_t sc_rnd_source;
+       krndsource_t sc_rnd_source;
 
        int sc_rnd_i;
        uint32_t sc_rnd_ax;
Index: sys/arch/x86/x86/via_padlock.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/x86/via_padlock.c,v
retrieving revision 1.15
diff -u -b -r1.15 via_padlock.c
--- sys/arch/x86/x86/via_padlock.c      24 May 2011 18:59:21 -0000      1.15
+++ sys/arch/x86/x86/via_padlock.c      21 Oct 2011 20:31:09 -0000
@@ -258,8 +258,7 @@
                                C3_CRYPT_CWLO_KEYGEN_SW |
                                C3_CRYPT_CWLO_NORMAL;
 
-                       rnd_extract_data(ses->ses_iv, sizeof(ses->ses_iv),
-                           RND_EXTRACT_ANY);
+                       arc4randbytes(ses->ses_iv, sizeof(ses->ses_iv));
                        ses->ses_klen = c->cri_klen;
                        ses->ses_cw0 = cw0;
 
Index: sys/arch/xen/include/xbdvar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/include/xbdvar.h,v
retrieving revision 1.12
diff -u -b -r1.12 xbdvar.h
--- sys/arch/xen/include/xbdvar.h       23 Oct 2009 02:32:33 -0000      1.12
+++ sys/arch/xen/include/xbdvar.h       21 Oct 2011 20:31:09 -0000
@@ -40,7 +40,7 @@
        struct simplelock       sc_slock;       /* our lock */
        int                     sc_shutdown;    /* about to be removed */
 #if NRND > 0
-       rndsource_element_t     sc_rnd_source;
+       krndsource_t    sc_rnd_source;
 #endif
 };
 
Index: sys/arch/xen/xen/if_xennet_xenbus.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/xen/if_xennet_xenbus.c,v
retrieving revision 1.53
diff -u -b -r1.53 if_xennet_xenbus.c
--- sys/arch/xen/xen/if_xennet_xenbus.c 26 Sep 2011 21:44:09 -0000      1.53
+++ sys/arch/xen/xen/if_xennet_xenbus.c 21 Oct 2011 20:31:10 -0000
@@ -203,7 +203,7 @@
 #define FEATURE_RX_FLIP                0
 #define FEATURE_RX_COPY                1
 #if NRND > 0
-       rndsource_element_t     sc_rnd_source;
+       krndsource_t     sc_rnd_source;
 #endif
 };
 #define SC_NLIVEREQ(sc) ((sc)->sc_rx_ring.req_prod_pvt - \
Index: sys/arch/xen/xen/xbd_xenbus.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/xen/xbd_xenbus.c,v
retrieving revision 1.48
diff -u -b -r1.48 xbd_xenbus.c
--- sys/arch/xen/xen/xbd_xenbus.c       20 Sep 2011 00:12:24 -0000      1.48
+++ sys/arch/xen/xen/xbd_xenbus.c       21 Oct 2011 20:31:10 -0000
@@ -155,7 +155,7 @@
        u_long sc_handle; /* from backend */
        int sc_cache_flush; /* backend supports BLKIF_OP_FLUSH_DISKCACHE */
 #if NRND > 0
-       rndsource_element_t     sc_rnd_source;
+       krndsource_t     sc_rnd_source;
 #endif
 };
 
Index: sys/conf/files
===================================================================
RCS file: /cvsroot/src/sys/conf/files,v
retrieving revision 1.1029
diff -u -b -r1.1029 files
--- sys/conf/files      15 Oct 2011 00:23:08 -0000      1.1029
+++ sys/conf/files      21 Oct 2011 20:31:10 -0000
@@ -165,10 +165,12 @@
 include "crypto/rijndael/files.rijndael"
 include "crypto/skipjack/files.skipjack"
 include "crypto/camellia/files.camellia"
-
 # General-purpose crypto processing framework.
 include "opencrypto/files.opencrypto"
 
+# NIST SP800.90 CTR DRBG
+include "crypto/nist_ctr_drbg/files.nist_ctr_drbg"
+
 #
 # Kernel history/tracing. Old UVMHIST depends upon this.
 #
@@ -392,7 +394,7 @@
 define ieee1394
 define token
 define sppp
-define wlan: rijndael
+define wlan
 define crypto
 
 # devices ARPing IPv4 pull this in:
@@ -1280,7 +1282,7 @@
 defpseudodev vnd:      disk
 defflag opt_vnd.h      VND_COMPRESSION
 defpseudo ccd:         disk
-defpseudodev cgd:      disk, des, blowfish, cast128, rijndael
+defpseudodev cgd:      disk, des, blowfish, cast128
 defpseudodev md:       disk
 defpseudodev fss:      disk
 
@@ -1521,10 +1523,12 @@
 file   kern/kgdb_stub.c                kgdb
 file   kern/sched_4bsd.c               sched_4bsd
 file   kern/sched_m2.c                 sched_m2
+file   kern/subr_rngtest.c
 file   kern/subr_autoconf.c
 file   kern/subr_blist.c               vmswap
 file   kern/subr_bufq.c
 file   kern/subr_callback.c
+file   kern/subr_cprng.c
 file   kern/subr_cpufreq.c
 file   kern/subr_copy.c
 file   kern/subr_debug.c               debug
Index: sys/crypto/nist_ctr_drbg/files.nist_ctr_drbg
===================================================================
RCS file: sys/crypto/nist_ctr_drbg/files.nist_ctr_drbg
diff -N sys/crypto/nist_ctr_drbg/files.nist_ctr_drbg
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sys/crypto/nist_ctr_drbg/files.nist_ctr_drbg        21 Oct 2011 20:31:10 
-0000
@@ -0,0 +1,3 @@
+#      $NetBSD: files.rijndael,v 1.5 2005/12/11 12:20:52 christos Exp $
+
+file   crypto/nist_ctr_drbg/nist_ctr_drbg.c
Index: sys/crypto/nist_ctr_drbg/nist_ctr_aes_rijndael.h
===================================================================
RCS file: sys/crypto/nist_ctr_drbg/nist_ctr_aes_rijndael.h
diff -N sys/crypto/nist_ctr_drbg/nist_ctr_aes_rijndael.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sys/crypto/nist_ctr_drbg/nist_ctr_aes_rijndael.h    21 Oct 2011 20:31:10 
-0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2007 Henric Jungheim <software%henric.info@localhost>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Interface adapter for Rijndael implmentation (for use by NIST SP 800-90 
CTR_DRBG)
+ */
+
+#ifndef NIST_AES_RIJNDAEL_H
+#define NIST_AES_RIJNDAEL_H
+
+#include <crypto/rijndael/rijndael.h>
+
+#define NIST_AES_MAXKEYBITS            256
+#define NIST_AES_MAXKEYBYTES   (NIST_AES_MAXKEYBITS / 8)
+#define NIST_AES_MAXKEYINTS    (NIST_AES_MAXKEYBYTES / sizeof(int))
+
+#define NIST_AES_BLOCKSIZEBITS 128
+#define NIST_AES_BLOCKSIZEBYTES        (NIST_AES_BLOCKSIZEBITS / 8)
+#define NIST_AES_BLOCKSIZEINTS (NIST_AES_BLOCKSIZEBYTES / sizeof(int))
+
+typedef rijndael_ctx NIST_AES_ENCRYPT_CTX;
+
+static __inline void
+NIST_AES_ECB_Encrypt(const NIST_AES_ENCRYPT_CTX* ctx, const void* src, void* 
dst)
+{
+       rijndael_encrypt(ctx, src, dst);
+}
+
+static __inline int
+NIST_AES_Schedule_Encryption(NIST_AES_ENCRYPT_CTX* ctx, const void* key, int 
bits)
+{
+       rijndael_set_key(ctx, key, bits);
+       return 0;
+}
+
+#endif /* NIST_AES_RIJNDAEL_H */
Index: sys/crypto/nist_ctr_drbg/nist_ctr_drbg.c
===================================================================
RCS file: sys/crypto/nist_ctr_drbg/nist_ctr_drbg.c
diff -N sys/crypto/nist_ctr_drbg/nist_ctr_drbg.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sys/crypto/nist_ctr_drbg/nist_ctr_drbg.c    21 Oct 2011 20:31:10 -0000
@@ -0,0 +1,598 @@
+/*
+ * Copyright (c) 2007 Henric Jungheim <software%henric.info@localhost>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * NIST SP 800-90 CTR_DRBG (Random Number Generator)
+ */
+#include <sys/types.h>
+#include <sys/systm.h>
+
+#include <crypto/nist_ctr_drbg/nist_ctr_drbg.h>
+
+/*
+ * NIST SP 800-90 March 2007
+ * 10.4.2 Derivation Function Using a Block Cipher Algorithm
+ * Global Constants
+ */
+static NIST_Key nist_cipher_df_ctx;
+static unsigned char nist_cipher_df_encrypted_iv[NIST_BLOCK_SEEDLEN / 
NIST_BLOCK_OUTLEN][NIST_BLOCK_OUTLEN_BYTES];
+
+/*
+ * NIST SP 800-90 March 2007
+ * 10.2.1.3.2 The Process Steps for Instantiation When a Derivation
+ *            Function is Used
+ * Global Constants
+ */
+static NIST_Key nist_cipher_zero_ctx;
+
+/*
+ * NIST SP 800-90 March 2007
+ * 10.2.1.5.2 The Process Steps for Generating Pseudorandom Bits When a
+ *            Derivation Function is Used for the DRBG Implementation
+ * Global Constants
+ */
+static const unsigned int 
nist_ctr_drgb_generate_null_input[NIST_BLOCK_SEEDLEN_INTS] = { 0 };
+
+
+/*
+ * Utility
+ */
+/*
+ * nist_increment_block
+ *    Increment the output block as a big-endian number.
+ */
+static void
+nist_increment_block(unsigned int* V)
+{
+       int i;
+       unsigned int x;
+
+       for (i = NIST_BLOCK_OUTLEN_INTS - 1; i >= 0; --i) {
+               x = NIST_NTOHL(V[i]) + 1;
+               V[i] = NIST_HTONL(x);
+               if (x)  /* There was only a carry if we are zero */
+                       return;
+       }
+}
+
+/*
+ * NIST SP 800-90 March 2007
+ * 10.4.3 BCC Function
+ */
+static void
+nist_ctr_drbg_bcc_update(const NIST_Key* ctx, const unsigned int* data, int n, 
unsigned int *chaining_value)
+{
+       int i, j;
+       unsigned int input_block[NIST_BLOCK_OUTLEN_INTS];
+
+       /* [4] for i = 1 to n */
+       for (i = 0; i < n; ++i) {
+
+               /* [4.1] input_block = chaining_value XOR block_i */
+               for (j = 0; j < NIST_BLOCK_OUTLEN_INTS; ++j)
+                       input_block[j] = chaining_value[j] ^ *data++;
+
+               /* [4.2] chaining_value = Block_Encrypt(Key, input_block) */
+               Block_Encrypt(ctx, &input_block[0], &chaining_value[0]);
+       }
+
+       /* [5] output_block = chaining_value */
+       /* chaining_value already is output_block, so no copy is required */
+}
+
+static void
+nist_ctr_drbg_bcc(NIST_Key* ctx, const unsigned int* data, int n, unsigned int 
*output_block)
+{
+       unsigned int* chaining_value = output_block;
+
+       /* [1] chaining_value = 0^outlen */
+       memset(&chaining_value[0], 0, NIST_BLOCK_OUTLEN_BYTES);
+
+       nist_ctr_drbg_bcc_update(ctx, data, n, output_block);
+}
+
+/*
+ * NIST SP 800-90 March 2007
+ * 10.4.2 Derivation Function Using a Block Cipher Algorithm
+ */
+
+typedef struct {
+       int index;
+       unsigned char S[NIST_BLOCK_OUTLEN_BYTES];
+} NIST_CTR_DRBG_DF_BCC_CTX;
+
+static __inline int
+check_int_alignment(const void* p)
+{
+       intptr_t ip = (const char *)p - (const char *)0;
+
+       if (ip & (sizeof(int) - 1))
+               return 0;
+       
+       return 1;
+}
+
+static void
+nist_ctr_drbg_df_bcc_init(NIST_CTR_DRBG_DF_BCC_CTX* ctx, int L, int N)
+{
+       unsigned int* S = (unsigned int *)ctx->S;
+
+       /* [4] S = L || N || input_string || 0x80 */
+       S[0] = NIST_HTONL(L);
+       S[1] = NIST_HTONL(N);
+       ctx->index = 2 * sizeof(S[0]);
+}
+
+static void
+nist_ctr_drbg_df_bcc_update(NIST_CTR_DRBG_DF_BCC_CTX* ctx, const char* 
input_string, int input_string_length, unsigned int* temp)
+{
+       int i, len;
+       int index = ctx->index;
+       unsigned char* S = ctx->S;
+
+       if (index) {
+               KASSERT(index < NIST_BLOCK_OUTLEN_BYTES);
+               len = NIST_BLOCK_OUTLEN_BYTES - index;
+               if (input_string_length < len)
+                       len = input_string_length;
+               
+               memcpy(&S[index], input_string, len);
+
+               index += len;
+               input_string += len;
+               input_string_length -= len;
+
+               if (index < NIST_BLOCK_OUTLEN_BYTES) {
+                       ctx->index = index;
+
+                       return;
+               }
+
+               /* We have a full block in S, so let's process it */
+               /* [9.2] BCC */
+               nist_ctr_drbg_bcc_update(&nist_cipher_df_ctx, (unsigned int 
*)&S[0], 1, temp);
+               index = 0;
+       }
+
+       /* ctx->S is empty, so let's handle as many input blocks as we can */
+       len = input_string_length / NIST_BLOCK_OUTLEN_BYTES;
+       if (len > 0) {
+               if (check_int_alignment(input_string)) {
+                       /* [9.2] BCC */
+                       nist_ctr_drbg_bcc_update(&nist_cipher_df_ctx, (const 
unsigned int *)input_string, len, temp);
+
+                       input_string += len * NIST_BLOCK_OUTLEN_BYTES;
+                       input_string_length -= len * NIST_BLOCK_OUTLEN_BYTES;
+               } else {
+                       for (i = 0; i < len; ++i) {
+                               memcpy(&S[0], input_string, 
NIST_BLOCK_OUTLEN_BYTES);
+
+                               /* [9.2] BCC */
+                               nist_ctr_drbg_bcc_update(&nist_cipher_df_ctx, 
(unsigned int *)&S[0], 1, temp);
+
+                               input_string += NIST_BLOCK_OUTLEN_BYTES;
+                               input_string_length -= NIST_BLOCK_OUTLEN_BYTES;
+                       }
+               }
+       }
+
+       KASSERT(input_string_length < NIST_BLOCK_OUTLEN_BYTES);
+
+       if (input_string_length) {
+               memcpy(&S[0], input_string, input_string_length);
+               index = input_string_length;
+       }
+
+       ctx->index = index;
+}
+
+static void
+nist_ctr_drbg_df_bcc_final(NIST_CTR_DRBG_DF_BCC_CTX* ctx, unsigned int* temp)
+{
+       int index;
+       unsigned char* S = ctx->S;
+       static const char endmark[] = { 0x80 };
+
+       nist_ctr_drbg_df_bcc_update(ctx, endmark, sizeof(endmark), temp);
+
+       index = ctx->index;
+       if (index) {
+               memset(&S[index], 0, NIST_BLOCK_OUTLEN_BYTES - index);
+
+               /* [9.2] BCC */
+               nist_ctr_drbg_bcc_update(&nist_cipher_df_ctx, (unsigned int 
*)&S[0], 1, temp);
+       }
+}
+
+static int
+nist_ctr_drbg_block_cipher_df(const char* input_string[], unsigned int L[],
+    int input_string_count, unsigned char* output_string, unsigned int N)
+{
+       int j, k, blocks, sum_L;
+       unsigned int *temp;
+       unsigned int *X;
+       NIST_Key ctx;
+       NIST_CTR_DRBG_DF_BCC_CTX df_bcc_ctx;
+       unsigned int buffer[NIST_BLOCK_SEEDLEN_INTS];
+       /*
+        * NIST SP 800-90 March 2007 10.4.2 states that 512 bits is
+        * the maximum length for the approved block cipher algorithms.
+        */
+       unsigned int output_buffer[512 / 8 / sizeof(unsigned int)];
+
+       if (N > sizeof(output_buffer) || N < 1)
+               return 0;
+
+       sum_L = 0;
+       for (j = 0; j < input_string_count; ++j)
+               sum_L += L[j];
+
+       /* [6] temp = Null string */
+       temp = buffer;
+
+       /* [9] while len(temp) < keylen + outlen, do */
+       for (j = 0; j < NIST_BLOCK_SEEDLEN / NIST_BLOCK_OUTLEN; ++j) {
+               /* [9.2] temp = temp || BCC(K, (IV || S)) */
+
+               /* Since we have precomputed BCC(K, IV), we start with that... 
*/ 
+               memcpy(&temp[0], &nist_cipher_df_encrypted_iv[j][0], 
NIST_BLOCK_OUTLEN_BYTES);
+
+               nist_ctr_drbg_df_bcc_init(&df_bcc_ctx, sum_L, N);
+
+               /* Compute the rest of BCC(K, (IV || S)) */
+               for (k = 0; k < input_string_count; ++k)
+                       nist_ctr_drbg_df_bcc_update(&df_bcc_ctx, 
input_string[k], L[k], temp);
+
+               nist_ctr_drbg_df_bcc_final(&df_bcc_ctx, temp);
+
+               temp += NIST_BLOCK_OUTLEN_INTS;
+       }
+
+       nist_zeroize(&df_bcc_ctx, sizeof(df_bcc_ctx));
+
+       /* [6] temp = Null string */
+       temp = buffer;
+
+       /* [10] K = Leftmost keylen bits of temp */
+       Block_Schedule_Encryption(&ctx, &temp[0]);
+
+       /* [11] X = next outlen bits of temp */
+       X = &temp[NIST_BLOCK_KEYLEN_INTS];
+
+       /* [12] temp = Null string */
+       temp = output_buffer;
+
+       /* [13] While len(temp) < number_of_bits_to_return, do */
+       blocks = (int)(N / NIST_BLOCK_OUTLEN_BYTES);
+       if (N & (NIST_BLOCK_OUTLEN_BYTES - 1))
+               ++blocks;
+       for (j = 0; j < blocks; ++j) {
+               /* [13.1] X = Block_Encrypt(K, X) */
+               Block_Encrypt(&ctx, X, temp);
+               X = temp;
+               temp += NIST_BLOCK_OUTLEN_INTS;
+       }
+
+       /* [14] requested_bits = Leftmost number_of_bits_to_return of temp */
+       memcpy(output_string, output_buffer, N);
+
+       nist_zeroize(&ctx, sizeof(ctx));
+
+       return 0;
+}
+
+
+static int
+nist_ctr_drbg_block_cipher_df_initialize(void)
+{
+       int i, err;
+       unsigned char K[NIST_BLOCK_KEYLEN_BYTES];
+       unsigned int IV[NIST_BLOCK_OUTLEN_INTS];
+
+       /* [8] K = Leftmost keylen bits of 0x00010203 ... 1D1E1F */
+       for (i = 0; i < sizeof(K); ++i)
+               K[i] = (unsigned char)i;
+
+       err = Block_Schedule_Encryption(&nist_cipher_df_ctx, K);
+       if (err)
+               return err;
+
+       /*
+        * Precompute the partial BCC result from encrypting the IVs:
+        *     nist_cipher_df_encrypted_iv[i] = BCC(K, IV(i))
+        */
+
+       /* [7] i = 0 */
+       /* [9.1] IV = i || 0^(outlen - len(i)) */
+       memset(&IV[0], 0, sizeof(IV));
+
+               /* [9.3] i = i + 1 */
+       for (i = 0; i < NIST_BLOCK_SEEDLEN / NIST_BLOCK_OUTLEN; ++i) {
+
+               /* [9.1] IV = i || 0^(outlen - len(i)) */
+               IV[0] = NIST_HTONL(i);
+
+               /* [9.2] temp = temp || BCC(K, (IV || S))  (the IV part, at 
least) */
+               nist_ctr_drbg_bcc(&nist_cipher_df_ctx, &IV[0], 1, (unsigned int 
*)&nist_cipher_df_encrypted_iv[i][0]); 
+       }
+
+       return 0;
+}
+
+/*
+ * NIST SP 800-90 March 2007
+ * 10.2.1.2 The Update Function
+ */
+static void
+nist_ctr_drbg_update(NIST_CTR_DRBG* drbg, const unsigned int* provided_data)
+{
+       int i;
+       unsigned int temp[NIST_BLOCK_SEEDLEN_INTS];
+       unsigned int* output_block;
+
+       /* 2. while (len(temp) < seedlen) do */
+       for (output_block = temp; output_block < &temp[NIST_BLOCK_SEEDLEN_INTS];
+               output_block += NIST_BLOCK_OUTLEN_INTS) {
+
+               /* 2.1 V = (V + 1) mod 2^outlen */
+               nist_increment_block(&drbg->V[0]);
+
+               /* 2.2 output_block = Block_Encrypt(K, V) */
+               Block_Encrypt(&drbg->ctx, drbg->V, output_block);
+       }
+
+       /* 3 temp is already of size seedlen (NIST_BLOCK_SEEDLEN_INTS) */
+
+       /* 4 (part 1) temp = temp XOR provided_data */
+       for (i = 0; i < NIST_BLOCK_KEYLEN_INTS; ++i)
+               temp[i] ^= *provided_data++;
+
+       /* 5 Key = leftmost keylen bits of temp */
+       Block_Schedule_Encryption(&drbg->ctx, &temp[0]);
+
+       /* 4 (part 2) combined with 6 V = rightmost outlen bits of temp */
+       for (i = 0; i < NIST_BLOCK_OUTLEN_INTS; ++i)
+               drbg->V[i] = temp[NIST_BLOCK_KEYLEN_INTS + i] ^ 
*provided_data++;
+}
+
+/*
+ * NIST SP 800-90 March 2007
+ * 10.2.1.3.2 The Process Steps for Instantiation When a Derivation
+ *            Function is Used
+ */
+int
+nist_ctr_drbg_instantiate(NIST_CTR_DRBG* drbg,
+       const void* entropy_input, int entropy_input_length,
+       const void* nonce, int nonce_length,
+       const void* personalization_string, int personalization_string_length)
+{
+       int err, count;
+       unsigned int seed_material[NIST_BLOCK_SEEDLEN_INTS];
+       unsigned int length[3];
+       const char *input_string[3];
+
+       /* [1] seed_material = entropy_input || nonce || personalization_string 
*/
+       
+       input_string[0] = entropy_input;
+       length[0] = entropy_input_length;
+
+       input_string[1] = nonce;
+       length[1] = nonce_length;
+
+       count = 2;
+       if (personalization_string) {
+               input_string[count] = personalization_string;
+               length[count] = personalization_string_length;
+               ++count;
+       }
+       /* [2] seed_material = Block_Cipher_df(seed_material, seedlen) */
+       err = nist_ctr_drbg_block_cipher_df(input_string, length, count,
+                       (unsigned char *)seed_material, sizeof(seed_material));
+       if (err)
+               return err;
+
+       /* [3] Key = 0^keylen */
+       memcpy(&drbg->ctx, &nist_cipher_zero_ctx, sizeof(drbg->ctx));
+
+       /* [4] V = 0^outlen */
+       memset(&drbg->V, 0, sizeof(drbg->V));
+
+       /* [5] (Key, V) = Update(seed_material, Key, V) */
+       nist_ctr_drbg_update(drbg, seed_material);
+
+       /* [6] reseed_counter = 1 */
+       drbg->reseed_counter = 1;
+
+       return 0;
+}
+
+static int
+nist_ctr_drbg_instantiate_initialize(void)
+{
+       int err;
+       unsigned char K[NIST_BLOCK_KEYLEN_BYTES];
+
+       memset(&K[0], 0, sizeof(K));
+
+       err = Block_Schedule_Encryption(&nist_cipher_zero_ctx, &K[0]);
+
+       return err;
+}
+
+/*
+ * NIST SP 800-90 March 2007
+ * 10.2.1.4.2 The Process Steps for Reseeding When a Derivation
+ *            Function is Used
+ */
+int
+nist_ctr_drbg_reseed(NIST_CTR_DRBG* drbg,
+       const void* entropy_input, int entropy_input_length,
+       const void* additional_input, int additional_input_length)
+{
+       int err, count;
+       const char *input_string[2];
+       unsigned int length[2];
+       unsigned int seed_material[NIST_BLOCK_SEEDLEN_INTS];
+
+       /* [1] seed_material = entropy_input || additional_input */
+       input_string[0] = entropy_input;
+       length[0] = entropy_input_length;
+       count = 1;
+
+       if (additional_input) {
+               input_string[count] = additional_input;
+               length[count] = additional_input_length;
+               
+               ++count;
+       }
+       /* [2] seed_material = Block_Cipher_df(seed_material, seedlen) */
+       err = nist_ctr_drbg_block_cipher_df(input_string, length, count,
+                       (unsigned char *)seed_material, sizeof(seed_material));
+       if (err)
+               return err;
+
+       /* [3] (Key, V) = Update(seed_material, Key, V) */
+       nist_ctr_drbg_update(drbg, seed_material);
+
+       /* [4] reseed_counter = 1 */
+       drbg->reseed_counter = 1;
+
+       return 0;
+}
+
+/*
+ * NIST SP 800-90 March 2007
+ * 10.2.1.5.2 The Process Steps for Generating Pseudorandom Bits When a
+ *            Derivation Function is Used for the DRBG Implementation
+ */
+static void
+nist_ctr_drbg_generate_block(NIST_CTR_DRBG* drbg, unsigned int* output_block)
+{
+
+       /* [4.1] V = (V + 1) mod 2^outlen */
+       nist_increment_block(&drbg->V[0]);
+
+       /* [4.2] output_block = Block_Encrypt(Key, V) */
+       Block_Encrypt(&drbg->ctx, &drbg->V[0], output_block);
+
+}
+
+int
+nist_ctr_drbg_generate(NIST_CTR_DRBG* drbg,
+       void* output_string, int output_string_length,
+       const void* additional_input, int additional_input_length)
+{
+       int i, len, err;
+       int blocks = output_string_length / NIST_BLOCK_OUTLEN_BYTES;
+       unsigned char* p;
+       unsigned int* temp;
+       const char *input_string[1];
+       unsigned int length[1];
+       unsigned int buffer[NIST_BLOCK_OUTLEN_BYTES];
+       unsigned int additional_input_buffer[NIST_BLOCK_SEEDLEN_INTS];
+       int ret = 0;
+
+       if (output_string_length < 1)
+               return 1;
+
+       /* [1] If reseed_counter > reseed_interval ... */
+       if (drbg->reseed_counter >= NIST_CTR_DRBG_RESEED_INTERVAL) {
+               ret = 1;
+               goto out;
+       }
+
+       /* [2] If (addional_input != Null), then */
+       if (additional_input) {
+               input_string[0] = additional_input;
+               length[0] = additional_input_length;
+               /* [2.1] additional_input = Block_Cipher_df(additional_input, 
seedlen) */
+               err = nist_ctr_drbg_block_cipher_df(input_string, length, 1,
+                               (unsigned char *)additional_input_buffer, 
sizeof(additional_input_buffer));
+               if (err) {
+                       ret = err;
+                       goto out;
+               }
+
+               /* [2.2] (Key, V) = Update(additional_input, Key, V) */
+               nist_ctr_drbg_update(drbg, additional_input_buffer);
+       }
+
+       if (blocks && check_int_alignment(output_string)) {
+               /* [3] temp = Null */
+               temp = (unsigned int *)output_string;
+               for (i = 0; i < blocks; ++i) {
+                       nist_ctr_drbg_generate_block(drbg, temp);
+
+                       temp += NIST_BLOCK_OUTLEN_INTS;
+                       output_string_length -= NIST_BLOCK_OUTLEN_BYTES;
+               }
+
+               output_string = (unsigned char *)temp;
+       }
+       
+       /* [3] temp = Null */
+       temp = buffer;
+
+       len = NIST_BLOCK_OUTLEN_BYTES;
+
+       /* [4] While (len(temp) < requested_number_of_bits) do: */
+       p = output_string;
+       while (output_string_length > 0) {
+               nist_ctr_drbg_generate_block(drbg, temp);
+
+               if (output_string_length < NIST_BLOCK_OUTLEN_BYTES)
+                       len = output_string_length;
+
+               memcpy(p, temp, len);
+
+               p += len;
+               output_string_length -= len;
+       }
+
+       /* [6] (Key, V) = Update(additional_input, Key, V) */
+       nist_ctr_drbg_update(drbg, additional_input ?
+               &additional_input_buffer[0] :
+               &nist_ctr_drgb_generate_null_input[0]);
+
+       /* [7] reseed_counter = reseed_counter + 1 */
+       ++drbg->reseed_counter;
+
+out:
+       return ret;
+}
+
+int
+nist_ctr_initialize(void)
+{
+       int err;
+
+       err = nist_ctr_drbg_instantiate_initialize();
+       if (err)
+               return err;
+       err = nist_ctr_drbg_block_cipher_df_initialize();
+       if (err)
+               return err;
+
+       return 0;
+}
+
+int
+nist_ctr_drbg_destroy(NIST_CTR_DRBG* drbg)
+{
+       nist_zeroize(drbg, sizeof(*drbg));
+       drbg->reseed_counter = ~0U;
+       return 1;
+}
Index: sys/crypto/nist_ctr_drbg/nist_ctr_drbg.h
===================================================================
RCS file: sys/crypto/nist_ctr_drbg/nist_ctr_drbg.h
diff -N sys/crypto/nist_ctr_drbg/nist_ctr_drbg.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sys/crypto/nist_ctr_drbg/nist_ctr_drbg.h    21 Oct 2011 20:31:10 -0000
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2007 Henric Jungheim <software%henric.info@localhost>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * NIST SP 800-90 CTR_DRBG (Random Number Generator)
+ */
+
+#ifndef NIST_CTR_DRBG_H
+#define NIST_CTR_DRBG_H
+
+#include <crypto/nist_ctr_drbg/nist_ctr_drbg_config.h>
+
+#define NIST_BLOCK_SEEDLEN             (NIST_BLOCK_KEYLEN + NIST_BLOCK_OUTLEN)
+#define NIST_BLOCK_SEEDLEN_BYTES       (NIST_BLOCK_SEEDLEN / 8)
+#define NIST_BLOCK_SEEDLEN_INTS                (NIST_BLOCK_SEEDLEN_BYTES / 
sizeof(int))
+
+typedef struct {
+       unsigned int reseed_counter;
+       NIST_Key ctx;
+       unsigned int V[NIST_BLOCK_OUTLEN_INTS];
+} NIST_CTR_DRBG;
+
+int
+nist_ctr_initialize(void);
+
+int 
+nist_ctr_drbg_generate(NIST_CTR_DRBG* drbg,
+       void* output_string, int output_string_length,
+       const void* additional_input, int additional_input_length);
+
+int
+nist_ctr_drbg_reseed(NIST_CTR_DRBG* drbg,
+       const void* entropy_input, int entropy_input_length,
+       const void* additional_input, int additional_input_length);
+
+int
+nist_ctr_drbg_instantiate(NIST_CTR_DRBG* drbg,
+       const void* entropy_input, int entropy_input_length,
+       const void* nonce, int nonce_length,
+       const void* personalization_string, int personalization_string_length);
+
+int
+nist_ctr_drbg_destroy(NIST_CTR_DRBG* );
+
+void
+nist_dump_simple_hex(const void* data, int length);
+
+void
+nist_dump_hex(const void* data, int length);
+
+void
+nist_dump_named_hex(const char* name, const void* data, int length);
+
+void
+nist_dump_ctr_drbg(const NIST_CTR_DRBG* drbg);
+
+void
+nist_dump_block_ctx(const NIST_Key* ctx);
+
+
+#ifdef NIST_ZEROIZE
+#define nist_zeroize(p, s) memset(p, 0, s)
+#else
+#define nist_zeroize(p, s) do { } while(0)
+#endif
+
+#define NIST_HTONL(x) htonl(x)
+#define NIST_NTOHL(x) ntohl(x)
+
+#endif /* NIST_CTR_DRBG_H */
Index: sys/crypto/nist_ctr_drbg/nist_ctr_drbg_aes128.h
===================================================================
RCS file: sys/crypto/nist_ctr_drbg/nist_ctr_drbg_aes128.h
diff -N sys/crypto/nist_ctr_drbg/nist_ctr_drbg_aes128.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sys/crypto/nist_ctr_drbg/nist_ctr_drbg_aes128.h     21 Oct 2011 20:31:10 
-0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007 Henric Jungheim <software%henric.info@localhost>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * NIST SP 800-90 CTR_DRBG (Random Number Generator)
+ */
+
+#ifndef NIST_CTR_DRBG_AES128_H
+#define NIST_CTR_DRBG_AES128_H
+
+/* Choose AES-128 as the underlying block cipher */
+#define NIST_BLOCK_KEYLEN              (128)
+#define NIST_BLOCK_KEYLEN_BYTES        (NIST_BLOCK_KEYLEN / 8)
+#define NIST_BLOCK_KEYLEN_INTS (NIST_BLOCK_KEYLEN_BYTES / sizeof(int))
+
+#define NIST_BLOCK_OUTLEN              (NIST_AES_BLOCKSIZEBITS)
+#define NIST_BLOCK_OUTLEN_BYTES        (NIST_BLOCK_OUTLEN / 8)
+#define NIST_BLOCK_OUTLEN_INTS (NIST_BLOCK_OUTLEN_BYTES / sizeof(int))
+
+typedef NIST_AES_ENCRYPT_CTX NIST_Key;
+
+#define Block_Encrypt(ctx, src, dst) NIST_AES_ECB_Encrypt(ctx, src, dst)
+#define Block_Schedule_Encryption(ctx, key) NIST_AES_Schedule_Encryption(ctx, 
key, NIST_BLOCK_KEYLEN)
+
+/*
+ * NIST SP 800-90 March 2007
+ * 10.2 DRBG Mechanism Based on Block Ciphers
+ *
+ * Table 3 specifies the reseed interval as
+ * <= 2^48.  We are only using a 32-bit counter,
+ * so we set the reseed interval a bit lower.
+ */
+#define NIST_CTR_DRBG_RESEED_INTERVAL  (100000)
+
+#endif /* NIST_CTR_DRBG_AES128_H */
Index: sys/crypto/nist_ctr_drbg/nist_ctr_drbg_aes256.h
===================================================================
RCS file: sys/crypto/nist_ctr_drbg/nist_ctr_drbg_aes256.h
diff -N sys/crypto/nist_ctr_drbg/nist_ctr_drbg_aes256.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sys/crypto/nist_ctr_drbg/nist_ctr_drbg_aes256.h     21 Oct 2011 20:31:10 
-0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007 Henric Jungheim <software%henric.info@localhost>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * NIST SP 800-90 CTR_DRBG (Random Number Generator)
+ */
+
+#ifndef NIST_CTR_DRBG_AES256_H
+#define NIST_CTR_DRBG_AES256_H
+
+/* Choose AES-256 as the underlying block cipher */
+#define NIST_BLOCK_KEYLEN              (256)
+#define NIST_BLOCK_KEYLEN_BYTES        (NIST_BLOCK_KEYLEN / 8)
+#define NIST_BLOCK_KEYLEN_INTS (NIST_BLOCK_KEYLEN_BYTES / sizeof(int))
+
+#define NIST_BLOCK_OUTLEN              (NIST_AES_BLOCKSIZEBITS)
+#define NIST_BLOCK_OUTLEN_BYTES        (NIST_BLOCK_OUTLEN / 8)
+#define NIST_BLOCK_OUTLEN_INTS (NIST_BLOCK_OUTLEN_BYTES / sizeof(int))
+
+typedef NIST_AES_ENCRYPT_CTX NIST_Key;
+
+#define Block_Encrypt(ctx, src, dst) NIST_AES_ECB_Encrypt(ctx, src, dst)
+#define Block_Schedule_Encryption(ctx, key) NIST_AES_Schedule_Encryption(ctx, 
key, NIST_BLOCK_KEYLEN)
+
+/*
+ * NIST SP 800-90 March 2007
+ * 10.2 DRBG Mechanism Based on Block Ciphers
+ *
+ * Table 3 specifies the reseed interval as
+ * <= 2^48.  We are only using a 32-bit counter,
+ * so we set the reseed interval a bit lower.
+ */
+#define NIST_CTR_DRBG_RESEED_INTERVAL  (100000)
+
+#endif /* NIST_CTR_DRBG_AES256_H */
Index: sys/crypto/nist_ctr_drbg/nist_ctr_drbg_config.h
===================================================================
RCS file: sys/crypto/nist_ctr_drbg/nist_ctr_drbg_config.h
diff -N sys/crypto/nist_ctr_drbg/nist_ctr_drbg_config.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sys/crypto/nist_ctr_drbg/nist_ctr_drbg_config.h     21 Oct 2011 20:31:10 
-0000
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2007 Henric Jungheim <software%henric.info@localhost>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * NIST SP 800-90 Configuration (Random Number Generator)
+ */
+
+#ifndef NIST_CTR_DRBG_CONFIG_H
+#define NIST_CTR_DRBG_CONFIG_H
+
+/*
+ * The test vectors will indicate failure if the
+ * byte ordering is set incorrectly.
+ * Pretending to be little endian will improve performance
+ * slightly but should not have an impact on
+ * security (a byte-swapped nonce is still a nonce).
+ */
+#define NIST_IS_LITTLE_ENDIAN 1
+
+/* #define NIST_ZEROIZE 1 */
+
+#include <crypto/nist_ctr_drbg/nist_ctr_aes_rijndael.h>
+
+/* Use AES-128 as the block cipher */
+#include <crypto/nist_ctr_drbg/nist_ctr_drbg_aes128.h>
+
+#endif /* NIST_CTR_DRBG_CONFIG_H */
Index: sys/crypto/rijndael/files.rijndael
===================================================================
RCS file: /cvsroot/src/sys/crypto/rijndael/files.rijndael,v
retrieving revision 1.5
diff -u -b -r1.5 files.rijndael
--- sys/crypto/rijndael/files.rijndael  11 Dec 2005 12:20:52 -0000      1.5
+++ sys/crypto/rijndael/files.rijndael  21 Oct 2011 20:31:10 -0000
@@ -1,7 +1,5 @@
 #      $NetBSD: files.rijndael,v 1.5 2005/12/11 12:20:52 christos Exp $
 
-define rijndael
-
-file   crypto/rijndael/rijndael-alg-fst.c      rijndael
-file   crypto/rijndael/rijndael-api-fst.c      rijndael
-file   crypto/rijndael/rijndael.c              rijndael
+file   crypto/rijndael/rijndael-alg-fst.c
+file   crypto/rijndael/rijndael-api-fst.c
+file   crypto/rijndael/rijndael.c      
Index: sys/dev/ldvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ldvar.h,v
retrieving revision 1.18
diff -u -b -r1.18 ldvar.h
--- sys/dev/ldvar.h     20 Sep 2010 06:54:06 -0000      1.18
+++ sys/dev/ldvar.h     21 Oct 2011 20:31:10 -0000
@@ -46,7 +46,7 @@
        struct  bufq_state *sc_bufq;
        kmutex_t sc_mutex;
 #if NRND > 0
-       rndsource_element_t     sc_rnd_source;
+       krndsource_t    sc_rnd_source;
 #endif
        int     sc_queuecnt;            /* current h/w queue depth */
        int     sc_ncylinders;          /* # cylinders */
Index: sys/dev/rnd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/rnd.c,v
retrieving revision 1.82
diff -u -b -r1.82 rnd.c
--- sys/dev/rnd.c       11 Oct 2011 23:55:30 -0000      1.82
+++ sys/dev/rnd.c       21 Oct 2011 20:31:10 -0000
@@ -50,6 +50,7 @@
 #include <sys/pool.h>
 #include <sys/kauth.h>
 #include <sys/once.h>
+#include <sys/rngtest.h>
 
 #if defined(__HAVE_CPU_COUNTER) && !defined(_RUMPKERNEL) /* XXX: bad pooka */
 #include <machine/cpu_counter.h>
@@ -89,7 +90,7 @@
 #define        RND_SAMPLE_COUNT        64      /* collect N samples, then 
compress */
 typedef struct _rnd_sample_t {
        SIMPLEQ_ENTRY(_rnd_sample_t) next;
-       rndsource_t     *source;
+       krndsource_t    *source;
        int             cursor;
        int             entropy;
        u_int32_t       ts[RND_SAMPLE_COUNT];
@@ -105,6 +106,13 @@
 kmutex_t                       rnd_mtx;
 
 /*
+ * Entropy sinks: usually other generators waiting to be rekeyed.
+ * The list is protected by the rndpool_mtx.  A sink's callback MUST
+ * NOT re-add the sink to the list, or list corruption will occur.
+ */
+TAILQ_HEAD(, rndsink)          rnd_sinks;
+
+/*
  * our select/poll queue
  */
 struct selinfo rnd_selq;
@@ -130,12 +138,18 @@
  * This source is used to easily "remove" queue entries when the source
  * which actually generated the events is going away.
  */
-static rndsource_t rnd_source_no_collect = {
-       { 'N', 'o', 'C', 'o', 'l', 'l', 'e', 'c', 't', 0, 0, 0, 0, 0, 0, 0 },
-       0, 0, 0, 0,
-       RND_TYPE_UNKNOWN,
-       (RND_FLAG_NO_COLLECT | RND_FLAG_NO_ESTIMATE | RND_TYPE_UNKNOWN),
-       NULL
+static krndsource_t rnd_source_no_collect = {
+       /* LIST_ENTRY list */
+       .name = { 'N', 'o', 'C', 'o', 'l', 'l', 'e', 'c', 't',
+                  0, 0, 0, 0, 0, 0, 0 },
+       .last_time = 0, .last_delta = 0, .last_delta2 = 0, .total = 0,
+       .type = RND_TYPE_UNKNOWN,
+       .flags = (RND_FLAG_NO_COLLECT |
+                 RND_FLAG_NO_ESTIMATE |
+                 RND_TYPE_UNKNOWN),
+       .state = NULL,
+       .test_cnt = 0,
+       .test = NULL
 };
 
 struct callout rnd_callout;
@@ -155,15 +169,17 @@
 };
 
 static inline void     rnd_wakeup_readers(void);
-static inline u_int32_t rnd_estimate_entropy(rndsource_t *, u_int32_t);
+static inline u_int32_t rnd_estimate_entropy(krndsource_t *, u_int32_t);
 static inline u_int32_t rnd_counter(void);
 static        void     rnd_timeout(void *);
+static       void      rnd_process_events(void *);
 static u_int32_t       rnd_extract_data_locked(void *, u_int32_t, u_int32_t);
 
 static int             rnd_ready = 0;
 static int             rnd_have_entropy = 0;
+static int             rnd_tested = 0;
 
-LIST_HEAD(, __rndsource_element)       rnd_sources;
+LIST_HEAD(, krndsource)        rnd_sources;
 
 /*
  * Generate a 32-bit counter.  This should be more machine dependent,
@@ -192,12 +208,37 @@
 static inline void
 rnd_wakeup_readers(void)
 {
+       rndsink_t *sink, *tsink;
+       TAILQ_HEAD(, rndsink) sunk = TAILQ_HEAD_INITIALIZER(sunk);
+
+       mutex_enter(&rndpool_mtx);
+       if (rndpool_get_entropy_count(&rnd_pool) < RND_ENTROPY_THRESHOLD * 8) {
+               mutex_exit(&rndpool_mtx);
+               return;
+       }
 
        /*
-        * If we have added new bits, and now have enough to do something,
-        * wake up sleeping readers.
+        * First, take care of in-kernel consumers needing rekeying.
+        */
+       TAILQ_FOREACH_SAFE(sink, &rnd_sinks, tailq, tsink) {
+               if ((sink->len + RND_ENTROPY_THRESHOLD) * 8 <
+                       rndpool_get_entropy_count(&rnd_pool)) {
+                       /* We have enough entropy to sink some here. */
+                       if (rndpool_extract_data(&rnd_pool, sink->data,
+                                                sink->len, RND_EXTRACT_GOOD)
+                           != sink->len) {
+                               panic("could not extract estimated "
+                                     "entropy from pool");
+                       }
+                       /* Move this sink to the list of pending callbacks */
+                       TAILQ_REMOVE(&rnd_sinks, sink, tailq);
+                       TAILQ_INSERT_HEAD(&sunk, sink, tailq);
+               }
+       }
+               
+       /*
+        * If we still have enough new bits to do something, feed userspace.
         */
-       mutex_enter(&rndpool_mtx);
        if (rndpool_get_entropy_count(&rnd_pool) > RND_ENTROPY_THRESHOLD * 8) {
                cv_broadcast(&rndpool_cv);
                selnotify(&rnd_selq, 0, 0);
@@ -210,6 +251,22 @@
                rnd_have_entropy = 1;
        }
        mutex_exit(&rndpool_mtx);
+
+       /*
+        * Now that we have dropped the mutex, we can run sinks' callbacks.
+        * Since we have reused the "tailq" member of the sink structure for
+        * this temporary on-stack queue, the callback must NEVER re-add
+        * the sink to the main queue, or our on-stack queue will become
+        * corrupt.
+        */
+       while ((sink = TAILQ_FIRST(&sunk))) {
+#ifdef RND_VERBOSE
+               printf("supplying %d bytes to entropy sink \"%s\".\n",
+                      (int)sink->len, sink->name);
+#endif
+               sink->cb(sink->arg);
+               TAILQ_REMOVE(&sunk, sink, tailq);
+       }
 }
 
 /*
@@ -218,7 +275,7 @@
  * non-zero.  If any of these are zero, return zero.
  */
 static inline u_int32_t
-rnd_estimate_entropy(rndsource_t *rs, u_int32_t t)
+rnd_estimate_entropy(krndsource_t *rs, u_int32_t t)
 {
        int32_t delta, delta2, delta3;
 
@@ -315,6 +372,7 @@
 
        LIST_INIT(&rnd_sources);
        SIMPLEQ_INIT(&rnd_samples);
+       TAILQ_INIT(&rnd_sinks);
        selinit(&rnd_selq);
 
        rndpool_init(&rnd_pool);
@@ -470,11 +528,21 @@
        return (ret);
 }
 
+static void
+krndsource_to_rndsource(krndsource_t *kr, rndsource_t *r)
+{
+       memset(r, 0, sizeof(r));
+       strlcpy(r->name, kr->name, sizeof(r->name));
+        r->total = kr->total;
+        r->type = kr->type;
+        r->flags = kr->flags;
+}
+
 int
 rndioctl(dev_t dev, u_long cmd, void *addr, int flag,
     struct lwp *l)
 {
-       rndsource_element_t *rse;
+       krndsource_t *kr;
        rndstat_t *rst;
        rndstat_name_t *rstnm;
        rndctl_t *rctl;
@@ -552,10 +620,10 @@
                 * Find the starting source by running through the
                 * list of sources.
                 */
-               rse = rnd_sources.lh_first;
+               kr = rnd_sources.lh_first;
                start = rst->start;
-               while (rse != NULL && start >= 1) {
-                       rse = rse->list.le_next;
+               while (kr != NULL && start >= 1) {
+                       kr = kr->list.le_next;
                        start--;
                }
 
@@ -564,15 +632,9 @@
                 * for.  If we run out of sources, a count of zero
                 * will be returned, without an error.
                 */
-               for (count = 0; count < rst->count && rse != NULL; count++) {
-                       memcpy(&rst->source[count], &rse->data,
-                           sizeof(rndsource_t));
-                       /* Zero out information which may leak */
-                       rst->source[count].last_time = 0;
-                       rst->source[count].last_delta = 0;
-                       rst->source[count].last_delta2 = 0;
-                       rst->source[count].state = 0;
-                       rse = rse->list.le_next;
+               for (count = 0; count < rst->count && kr != NULL; count++) {
+                       krndsource_to_rndsource(kr, &rst->source[count]);
+                       kr = kr->list.le_next;
                }
 
                rst->count = count;
@@ -584,15 +646,13 @@
                 * Scan through the list, trying to find the name.
                 */
                rstnm = (rndstat_name_t *)addr;
-               rse = rnd_sources.lh_first;
-               while (rse != NULL) {
-                       if (strncmp(rse->data.name, rstnm->name, 16) == 0) {
-                               memcpy(&rstnm->source, &rse->data,
-                                   sizeof(rndsource_t));
-
+               kr = rnd_sources.lh_first;
+               while (kr != NULL) {
+                       if (strncmp(kr->name, rstnm->name, 16) == 0) {
+                               krndsource_to_rndsource(kr, &rstnm->source);
                                return (0);
                        }
-                       rse = rse->list.le_next;
+                       kr = kr->list.le_next;
                }
 
                ret = ENOENT;           /* name not found */
@@ -605,19 +665,19 @@
                 * collection.
                 */
                rctl = (rndctl_t *)addr;
-               rse = rnd_sources.lh_first;
+               kr = rnd_sources.lh_first;
 
                /*
                 * Flags set apply to all sources of this type.
                 */
                if (rctl->type != 0xff) {
-                       while (rse != NULL) {
-                               if (rse->data.type == rctl->type) {
-                                       rse->data.flags &= ~rctl->mask;
-                                       rse->data.flags |=
+                       while (kr != NULL) {
+                               if (kr->type == rctl->type) {
+                                       kr->flags &= ~rctl->mask;
+                                       kr->flags |=
                                            (rctl->flags & rctl->mask);
                                }
-                               rse = rse->list.le_next;
+                               kr = kr->list.le_next;
                        }
 
                        return (0);
@@ -626,14 +686,14 @@
                /*
                 * scan through the list, trying to find the name
                 */
-               while (rse != NULL) {
-                       if (strncmp(rse->data.name, rctl->name, 16) == 0) {
-                               rse->data.flags &= ~rctl->mask;
-                               rse->data.flags |= (rctl->flags & rctl->mask);
+               while (kr != NULL) {
+                       if (strncmp(kr->name, rctl->name, 16) == 0) {
+                               kr->flags &= ~rctl->mask;
+                               kr->flags |= (rctl->flags & rctl->mask);
 
                                return (0);
                        }
-                       rse = rse->list.le_next;
+                       kr = kr->list.le_next;
                }
 
                ret = ENOENT;           /* name not found */
@@ -763,7 +823,7 @@
 }
 
 static rnd_sample_t *
-rnd_sample_allocate(rndsource_t *source)
+rnd_sample_allocate(krndsource_t *source)
 {
        rnd_sample_t *c;
 
@@ -782,7 +842,7 @@
  * Don't wait on allocation.  To be used in an interrupt context.
  */
 static rnd_sample_t *
-rnd_sample_allocate_isr(rndsource_t *source)
+rnd_sample_allocate_isr(krndsource_t *source)
 {
        rnd_sample_t *c;
 
@@ -808,7 +868,7 @@
  * Add a source to our list of sources.
  */
 void
-rnd_attach_source(rndsource_element_t *rs, const char *name, u_int32_t type,
+rnd_attach_source(krndsource_t *rs, const char *name, u_int32_t type,
     u_int32_t flags)
 {
        u_int32_t ts;
@@ -817,11 +877,11 @@
 
        ts = rnd_counter();
 
-       strlcpy(rs->data.name, name, sizeof(rs->data.name));
-       rs->data.last_time = ts;
-       rs->data.last_delta = 0;
-       rs->data.last_delta2 = 0;
-       rs->data.total = 0;
+       strlcpy(rs->name, name, sizeof(rs->name));
+       rs->last_time = ts;
+       rs->last_delta = 0;
+       rs->last_delta2 = 0;
+       rs->total = 0;
 
        /*
         * Force network devices to not collect any entropy by
@@ -830,15 +890,26 @@
        if (type == RND_TYPE_NET)
                flags |= (RND_FLAG_NO_COLLECT | RND_FLAG_NO_ESTIMATE);
 
-       rs->data.type = type;
-       rs->data.flags = flags;
+       /*
+        * Hardware RNGs get extra space for statistical testing.
+        */
+       if (type == RND_TYPE_RNG) {
+               rs->test = kmem_alloc(sizeof(rngtest_t), KM_NOSLEEP);
+               rs->test_cnt = 0;
+       } else {
+               rs->test = NULL;
+               rs->test_cnt = -1;
+       }
+
+       rs->type = type;
+       rs->flags = flags;
 
-       rs->data.state = rnd_sample_allocate(&rs->data);
+       rs->state = rnd_sample_allocate(rs);
 
        LIST_INSERT_HEAD(&rnd_sources, rs, list);
 
 #ifdef RND_VERBOSE
-       printf("rnd: %s attached as an entropy source (", rs->data.name);
+       printf("rnd: %s attached as an entropy source (", rs->name);
        if (!(flags & RND_FLAG_NO_COLLECT)) {
                printf("collecting");
                if (flags & RND_FLAG_NO_ESTIMATE)
@@ -860,22 +931,23 @@
  * Remove a source from our list of sources.
  */
 void
-rnd_detach_source(rndsource_element_t *rs)
+rnd_detach_source(krndsource_t *source)
 {
        rnd_sample_t *sample;
-       rndsource_t *source;
-
-       mutex_enter(&rnd_mtx);
 
-       LIST_REMOVE(rs, list);
+       mutex_spin_enter(&rnd_mtx);
 
-       source = &rs->data;
+       LIST_REMOVE(source, list);
 
        if (source->state) {
                rnd_sample_free(source->state);
                source->state = NULL;
        }
 
+       if (source->test) {
+               kmem_free(source->test, sizeof(rngtest_t));
+       }
+
        /*
         * If there are samples queued up "remove" them from the sample queue
         * by setting the source to the no-collect pseudosource.
@@ -888,9 +960,9 @@
                sample = SIMPLEQ_NEXT(sample, next);
        }
 
-       mutex_exit(&rnd_mtx);
+       mutex_spin_exit(&rnd_mtx);
 #ifdef RND_VERBOSE
-       printf("rnd: %s detached as an entropy source\n", rs->data.name);
+       printf("rnd: %s detached as an entropy source\n", source->name);
 #endif
 }
 
@@ -899,16 +971,12 @@
  * source-specific source structure.
  */
 void
-rnd_add_uint32(rndsource_element_t *rs, u_int32_t val)
+rnd_add_uint32(krndsource_t *rs, u_int32_t val)
 {
-       rndsource_t *rst;
        rnd_sample_t *state;
        u_int32_t ts;
 
-
-       rst = &rs->data;
-
-       if (rst->flags & RND_FLAG_NO_COLLECT)
+       if (rs->flags & RND_FLAG_NO_COLLECT)
                return;
 
        /*
@@ -921,12 +989,12 @@
         * If the sample buffer is NULL, try to allocate one here.  If this
         * fails, drop this sample.
         */
-       state = rst->state;
+       state = rs->state;
        if (state == NULL) {
-               state = rnd_sample_allocate_isr(rst);
+               state = rnd_sample_allocate_isr(rs);
                if (state == NULL)
                        return;
-               rst->state = state;
+               rs->state = state;
        }
 
        /*
@@ -934,8 +1002,8 @@
         * calculate differentials.
         */
 
-       if ((rst->flags & RND_FLAG_NO_ESTIMATE) == 0)
-               state->entropy += rnd_estimate_entropy(rst, ts);
+       if ((rs->flags & RND_FLAG_NO_ESTIMATE) == 0)
+               state->entropy += rnd_estimate_entropy(rs, ts);
 
        state->ts[state->cursor] = ts;
        state->values[state->cursor] = val;
@@ -950,18 +1018,27 @@
        /*
         * State arrays are full.  Queue this chunk on the processing queue.
         */
-       mutex_enter(&rnd_mtx);
+       mutex_spin_enter(&rnd_mtx);
        SIMPLEQ_INSERT_HEAD(&rnd_samples, state, next);
-       rst->state = NULL;
+       rs->state = NULL;
 
        /*
-        * If the timeout isn't pending, have it run in the near future.
+        * If we are still starting up, cause immediate processing of
+        * the queued samples.  Otherwise, if the timeout isn't pending,
+        * have it run in the near future.
         */
+       if (__predict_false(cold)) {
+#ifdef RND_VERBOSE
+               printf("rnd: directly processing boot-time events.\n");
+#endif
+               rnd_process_events(NULL);       /* Drops lock! */
+       } else {
        if (rnd_timeout_pending == 0) {
                rnd_timeout_pending = 1;
                callout_reset(&rnd_callout, 1, rnd_timeout, NULL);
        }
-       mutex_exit(&rnd_mtx);
+               mutex_spin_exit(&rnd_mtx);
+       }
 
        /*
         * To get here we have to have queued the state up, and therefore
@@ -969,23 +1046,21 @@
         * if we don't get it, it doesn't matter; we'll try again on
         * the next random event.
         */
-       rst->state = rnd_sample_allocate_isr(rst);
+       rs->state = rnd_sample_allocate_isr(rs);
 }
 
 void
-rnd_add_data(rndsource_element_t *rs, void *data, u_int32_t len,
+rnd_add_data(krndsource_t *rs, void *data, u_int32_t len,
     u_int32_t entropy)
 {
-       rndsource_t *rst;
 
        /* Mix in the random data directly into the pool. */
        rndpool_add_data(&rnd_pool, data, len, entropy);
 
        if (rs != NULL) {
-               rst = &rs->data;
-               rst->total += entropy;
+               rs->total += entropy;
 
-               if ((rst->flags & RND_FLAG_NO_ESTIMATE) == 0)
+               if ((rs->flags & RND_FLAG_NO_ESTIMATE) == 0)
                        /* Estimate entropy using timing information */
                        rnd_add_uint32(rs, *(u_int8_t *)data);
        }
@@ -994,58 +1069,152 @@
        rnd_wakeup_readers();
 }
 
+static int
+rnd_hwrng_test(rnd_sample_t *sample)
+{
+       krndsource_t *source = sample->source;
+       size_t cmplen;
+       uint8_t *v1, *v2;
+       size_t resid, totest;
+
+       KASSERT(source->type = RND_TYPE_RNG);
+
+       /*
+        * Continuous-output test: compare two halves of the
+        * sample buffer to each other.  The sample buffer (64 ints,
+        * so either 256 or 512 bytes on any modern machine) should be
+        * much larger than a typical hardware RNG output, so this seems
+        * a reasonable way to do it without retaining extra data.
+        */
+       cmplen = sizeof(sample->values) / 2;
+       v1 = (uint8_t *)sample->values;
+       v2 = (uint8_t *)sample->values + cmplen;
+
+       if (__predict_false(memcmp(v1, v2, cmplen))) {
+               printf("rnd: source \"%s\" failed continuous-output test.",
+                      source->name);
+               return 1;
+       }
+
+       /*
+        * FIPS 140 statistical RNG test.  We must accumulate 20,000 bits.
+        */
+       if (__predict_true(source->test_cnt == -1)) {
+               /* already passed the test */
+               return 0;
+       }
+       resid = FIPS140_RNG_TEST_BYTES - source->test_cnt;
+       totest = MIN(RND_SAMPLE_COUNT * 4, resid);
+       memcpy(source->test->rt_b + source->test_cnt, sample->values, totest);
+       resid -= totest;
+       source->test_cnt += totest;
+       if (resid == 0) {
+               strlcpy(source->test->rt_name, source->name,
+                       sizeof(source->test->rt_name));
+               if (rngtest(source->test)) {
+                       printf("rnd: source \"%s\" failed statistical test.",
+                              source->name);
+                       return 1;
+               }
+               source->test_cnt = -1;
+               memset(source->test, 0, sizeof(source->test));
+       }
+       return 0;
+}
+
 /*
- * Timeout, run to process the events in the ring buffer. 
+ * Process the events in the ring buffer.  Called by rnd_timeout or
+ * by the add routines directly if the callout has never fired (that
+ * is, if we are "cold" -- just booted).
+ *
+ * Call with rnd_mtx held -- WILL RELEASE IT.
  */
 static void
-rnd_timeout(void *arg)
+rnd_process_events(void *arg)
 {
        rnd_sample_t *sample;
-       rndsource_t *source;
+       krndsource_t *source, *badsource = NULL;
        u_int32_t entropy;
+       SIMPLEQ_HEAD(, _rnd_sample_t) dq_samples =
+                       SIMPLEQ_HEAD_INITIALIZER(dq_samples);
+       SIMPLEQ_HEAD(, _rnd_sample_t) df_samples =
+                       SIMPLEQ_HEAD_INITIALIZER(df_samples);
 
        /*
-        * Sample queue is protected by rnd_mtx, take it briefly to dequeue.
+        * Sample queue is protected by rnd_mtx, drain to onstack queue
+        * and drop lock.
         */
-       mutex_enter(&rnd_mtx);
-       rnd_timeout_pending = 0;
 
-       sample = SIMPLEQ_FIRST(&rnd_samples);
-       while (sample != NULL) {
+       while ((sample = SIMPLEQ_FIRST(&rnd_samples))) {
                SIMPLEQ_REMOVE_HEAD(&rnd_samples, next);
-               mutex_exit(&rnd_mtx);
-
-               source = sample->source;
-
                /*
-                * We repeat this check here, since it is possible the source
-                * was disabled before we were called, but after the entry
-                * was queued.
+                * We repeat this check here, since it is possible
+                * the source was disabled before we were called, but
+                * after the entry was queued.
                 */
-               if ((source->flags & RND_FLAG_NO_COLLECT) == 0) {
+               if (__predict_false(sample->source->flags
+                                   & RND_FLAG_NO_COLLECT)) {
+                       SIMPLEQ_INSERT_TAIL(&df_samples, sample, next);
+               } else {
+                       SIMPLEQ_INSERT_TAIL(&dq_samples, sample, next);
+               }
+       }
+       mutex_spin_exit(&rnd_mtx);
+
+       /* Don't thrash the rndpool mtx either.  Hold, add all samples. */
+       mutex_enter(&rndpool_mtx);
+       while ((sample = SIMPLEQ_FIRST(&dq_samples))) {
+               SIMPLEQ_REMOVE_HEAD(&dq_samples, next);
+               source = sample->source;
                        entropy = sample->entropy;
                        if (source->flags & RND_FLAG_NO_ESTIMATE)
                                entropy = 0;
 
-                       mutex_enter(&rndpool_mtx);
+               /*
+                * Hardware generators are great but sometimes they
+                * have...hardware issues.  Don't use any data from
+                * them unless it passes some tests.
+                */
+               if (source->type == RND_TYPE_RNG) {
+                       if (__predict_false(rnd_hwrng_test(sample))) {
+                               /*
+                                * Detach the bad source.  See below.
+                                */
+                               badsource = source;
+                               printf("rnd: detaching source \"%s\".",
+                                      badsource->name);
+                               break;
+                       }
+               }
                        rndpool_add_data(&rnd_pool, sample->values,
                            RND_SAMPLE_COUNT * 4, 0);
 
                        rndpool_add_data(&rnd_pool, sample->ts,
-                           RND_SAMPLE_COUNT * 4,
-                           entropy);
-                       mutex_exit(&rndpool_mtx);
+                   RND_SAMPLE_COUNT * 4, entropy);
 
                        source->total += sample->entropy;
+               SIMPLEQ_INSERT_TAIL(&df_samples, sample, next);
                }
+       mutex_exit(&rndpool_mtx);
 
+       /* Now we hold no locks: clean up. */
+       if (__predict_false(badsource)) {
+               /*
+                * The detach routine frees any samples we have not
+                * dequeued ourselves.  For sanity's sake, we simply
+                * free (without using) all dequeued samples from the
+                * point at which we detected a problem onwards.
+                */
+               rnd_detach_source(badsource);
+               while ((sample = SIMPLEQ_FIRST(&dq_samples))) {
+                       SIMPLEQ_REMOVE_HEAD(&dq_samples, next);
+                       rnd_sample_free(sample);
+               }
+       }
+       while ((sample = SIMPLEQ_FIRST(&df_samples))) {
+               SIMPLEQ_REMOVE_HEAD(&df_samples, next);
                rnd_sample_free(sample);
-
-               /* Get mtx back to dequeue the next one.. */
-               mutex_enter(&rnd_mtx);
-               sample = SIMPLEQ_FIRST(&rnd_samples);
        }
-       mutex_exit(&rnd_mtx);
 
        /*
         * Wake up any potential readers waiting.
@@ -1053,6 +1222,17 @@
        rnd_wakeup_readers();
 }
 
+/*
+ * Timeout, run to process the events in the ring buffer.
+ */
+static void
+rnd_timeout(void *arg)
+{
+        mutex_spin_enter(&rnd_mtx);
+        rnd_timeout_pending = 0;
+        rnd_process_events(arg);
+}
+
 static u_int32_t
 rnd_extract_data_locked(void *p, u_int32_t len, u_int32_t flags)
 {
@@ -1069,6 +1249,42 @@
                c = rnd_counter();
                rndpool_add_data(&rnd_pool, &c, sizeof(u_int32_t), 1);
        }
+       if (!rnd_tested) {
+               rngtest_t rt;
+               uint8_t testbits[sizeof(rt.rt_b)];
+               int entropy_count;
+
+               entropy_count = rndpool_get_entropy_count(&rnd_pool);
+#ifdef RND_VERBOSE
+               printf("rnd: starting statistical RNG test, entropy = %d.\n",
+                       entropy_count);
+#endif
+               if (rndpool_extract_data(&rnd_pool, rt.rt_b,
+                   sizeof(rt.rt_b), RND_EXTRACT_ANY) != sizeof(rt.rt_b)) {
+                       panic("rnd: could not get bits for statistical test");
+               }
+               /*
+                * Stash the tested bits so we can put them back in the
+                * pool, restoring the entropy count.  DO NOT rely on
+                * rngtest to maintain the bits pristine -- we could end
+                * up adding back non-random data claiming it were pure
+                * entropy.
+                */
+               memcpy(testbits, rt.rt_b, sizeof(rt.rt_b));
+               strlcpy(rt.rt_name, "entropy pool", sizeof(rt.rt_name));
+               if (rngtest(&rt)) {
+                       panic("rnd: entropy pool failed statistical test");
+               }
+               memset(&rt, 0, sizeof(rt));
+               rndpool_add_data(&rnd_pool, testbits, sizeof(testbits),
+                                entropy_count);
+               memset(testbits, 0, sizeof(testbits));
+#ifdef RND_VERBOSE
+               printf("rnd: statistical RNG test done, entropy = %d.\n",
+                      rndpool_get_entropy_count(&rnd_pool));
+#endif
+               rnd_tested++;
+       }
        return rndpool_extract_data(&rnd_pool, p, len, flags);
 }
 
@@ -1082,3 +1298,26 @@
        mutex_exit(&rndpool_mtx);
        return retval;
 }
+
+void
+rndsink_attach(rndsink_t *rs)
+{
+#ifdef RND_VERBOSE
+       printf("rnd: entropy sink \"%s\" wants %d bytes of data.\n",
+              rs->name, (int)rs->len);
+#endif
+       mutex_enter(&rndpool_mtx);
+       TAILQ_INSERT_TAIL(&rnd_sinks, rs, tailq);
+       mutex_exit(&rndpool_mtx);
+}
+
+void
+rndsink_detach(rndsink_t *rs)
+{
+#ifdef RND_VERBOSE
+       printf("rnd: entropy sink \"%s\" no longer wants data.\n", rs->name);
+#endif
+       mutex_enter(&rndpool_mtx);
+       TAILQ_REMOVE(&rnd_sinks, rs, tailq);
+       mutex_exit(&rndpool_mtx);
+}
Index: sys/dev/ata/wdvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ata/wdvar.h,v
retrieving revision 1.38
diff -u -b -r1.38 wdvar.h
--- sys/dev/ata/wdvar.h 17 Dec 2009 21:03:10 -0000      1.38
+++ sys/dev/ata/wdvar.h 21 Oct 2011 20:31:11 -0000
@@ -67,7 +67,7 @@
        u_int sc_bscount;
 #endif
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
 };
 
Index: sys/dev/gpib/rd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/gpib/rd.c,v
retrieving revision 1.28
diff -u -b -r1.28 rd.c
--- sys/dev/gpib/rd.c   8 Feb 2011 20:20:27 -0000       1.28
+++ sys/dev/gpib/rd.c   21 Oct 2011 20:31:11 -0000
@@ -143,7 +143,7 @@
        struct  callout sc_restart_ch;
 
 #if NRND > 0
-       rndsource_element_t rnd_source;
+       krndsource_t rnd_source;
 #endif
 };
 
Index: sys/dev/ic/comvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/comvar.h,v
retrieving revision 1.71
diff -u -b -r1.71 comvar.h
--- sys/dev/ic/comvar.h 13 Nov 2010 15:35:50 -0000      1.71
+++ sys/dev/ic/comvar.h 21 Oct 2011 20:31:11 -0000
@@ -228,7 +228,7 @@
        struct pps_state sc_pps_state;  /* pps state */
 
 #if NRND > 0 && defined(RND_COM)
-       rndsource_element_t  rnd_source;
+       krndsource_t  rnd_source;
 #endif
        kmutex_t                sc_lock;
 };
Index: sys/dev/ic/cs89x0var.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/cs89x0var.h,v
retrieving revision 1.14
diff -u -b -r1.14 cs89x0var.h
--- sys/dev/ic/cs89x0var.h      22 Sep 2009 14:55:19 -0000      1.14
+++ sys/dev/ic/cs89x0var.h      21 Oct 2011 20:31:11 -0000
@@ -105,7 +105,7 @@
        u_int16_t *eeprom_data;         /* copy of the eeprom data */
 
 #if NRND > 0
-       rndsource_element_t rnd_source; /* random source */
+       krndsource_t rnd_source; /* random source */
 #endif
 
        /* power management */
Index: sys/dev/ic/dp8390var.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/dp8390var.h,v
retrieving revision 1.30
diff -u -b -r1.30 dp8390var.h
--- sys/dev/ic/dp8390var.h      12 May 2009 14:25:17 -0000      1.30
+++ sys/dev/ic/dp8390var.h      21 Oct 2011 20:31:11 -0000
@@ -72,7 +72,7 @@
        int     sc_enabled;     /* boolean; power enabled on interface */
 
 #if NRND > 0
-       rndsource_element_t rnd_source; /* random source */
+       krndsource_t rnd_source; /* random source */
 #endif
 
        int     (*test_mem)(struct dp8390_softc *);
Index: sys/dev/ic/elink3var.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/elink3var.h,v
retrieving revision 1.36
diff -u -b -r1.36 elink3var.h
--- sys/dev/ic/elink3var.h      5 Sep 2009 12:30:59 -0000       1.36
+++ sys/dev/ic/elink3var.h      21 Oct 2011 20:31:11 -0000
@@ -102,7 +102,7 @@
        int ep_pktlenshift;             /* scale factor for pkt lengths */
 
 #if NRND > 0
-       rndsource_element_t rnd_source;
+       krndsource_t rnd_source;
 #endif
 
        /* power management hooks */
Index: sys/dev/ic/elinkxlvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/elinkxlvar.h,v
retrieving revision 1.22
diff -u -b -r1.22 elinkxlvar.h
--- sys/dev/ic/elinkxlvar.h     22 Mar 2010 23:03:30 -0000      1.22
+++ sys/dev/ic/elinkxlvar.h     21 Oct 2011 20:31:11 -0000
@@ -110,7 +110,7 @@
 #define EX_FLAGS_ATTACHED              0x4000  /* attach has succeeded */
 
 #if NRND > 0
-       rndsource_element_t rnd_source;
+       krndsource_t rnd_source;
 #endif
 
        /* power management hooks */
Index: sys/dev/ic/gemvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/gemvar.h,v
retrieving revision 1.21
diff -u -b -r1.21 gemvar.h
--- sys/dev/ic/gemvar.h 24 Feb 2010 22:37:58 -0000      1.21
+++ sys/dev/ic/gemvar.h 21 Oct 2011 20:31:11 -0000
@@ -217,7 +217,7 @@
        void    (*sc_hwinit)(struct gem_softc *);
 
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
 
        struct evcnt sc_ev_intr;
Index: sys/dev/ic/hmevar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/hmevar.h,v
retrieving revision 1.21
diff -u -b -r1.21 hmevar.h
--- sys/dev/ic/hmevar.h 18 Sep 2009 12:40:15 -0000      1.21
+++ sys/dev/ic/hmevar.h 21 Oct 2011 20:31:11 -0000
@@ -95,7 +95,7 @@
        void    (*sc_hwinit)(struct hme_softc *);
 
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
 };
 
Index: sys/dev/ic/i82557var.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/i82557var.h,v
retrieving revision 1.48
diff -u -b -r1.48 i82557var.h
--- sys/dev/ic/i82557var.h      25 Feb 2010 23:40:39 -0000      1.48
+++ sys/dev/ic/i82557var.h      21 Oct 2011 20:31:11 -0000
@@ -242,7 +242,7 @@
 
        int     sc_eeprom_size;         /* log2 size of EEPROM */
 #if NRND > 0
-       rndsource_element_t rnd_source; /* random source */
+       krndsource_t rnd_source;        /* random source */
 #endif
 
 };
Index: sys/dev/ic/lan9118var.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/lan9118var.h,v
retrieving revision 1.2
diff -u -b -r1.2 lan9118var.h
--- sys/dev/ic/lan9118var.h     28 Nov 2009 08:44:00 -0000      1.2
+++ sys/dev/ic/lan9118var.h     21 Oct 2011 20:31:11 -0000
@@ -76,7 +76,7 @@
 #define LAN9118_FLAGS_NO_EEPROM        0x00000002
 
 #if NRND > 0
-       rndsource_element_t rnd_source;
+       krndsource_t rnd_source;
 #endif
 };
 
Index: sys/dev/ic/lancevar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/lancevar.h,v
retrieving revision 1.13
diff -u -b -r1.13 lancevar.h
--- sys/dev/ic/lancevar.h       4 Sep 2009 16:21:24 -0000       1.13
+++ sys/dev/ic/lancevar.h       21 Oct 2011 20:31:11 -0000
@@ -116,7 +116,7 @@
        uint8_t sc_enaddr[ETHER_ADDR_LEN];
        uint8_t sc_pad[2];
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
 
        void (*sc_meminit)(struct lance_softc *);
Index: sys/dev/ic/lemacvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/lemacvar.h,v
retrieving revision 1.9
diff -u -b -r1.9 lemacvar.h
--- sys/dev/ic/lemacvar.h       11 Dec 2005 12:21:27 -0000      1.9
+++ sys/dev/ic/lemacvar.h       21 Oct 2011 20:31:11 -0000
@@ -80,7 +80,7 @@
     char sc_prodname[LEMAC_EEP_PRDNMSZ+1]; /* product name DE20x-xx */
     u_int8_t sc_eeprom[LEMAC_EEP_SIZE];        /* local copy eeprom */
 #if NRND > 0
-    rndsource_element_t rnd_source;
+    krndsource_t rnd_source;
 #endif
 } lemac_softc_t;
 
Index: sys/dev/ic/mb86950var.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/mb86950var.h,v
retrieving revision 1.5
diff -u -b -r1.5 mb86950var.h
--- sys/dev/ic/mb86950var.h     12 May 2009 14:25:17 -0000      1.5
+++ sys/dev/ic/mb86950var.h     21 Oct 2011 20:31:11 -0000
@@ -60,7 +60,7 @@
        u_int8_t sc_enaddr[ETHER_ADDR_LEN];
 
 #if NRND > 0
-       rndsource_element_t rnd_source;
+       krndsource_t rnd_source;
 #endif
 
        u_int32_t sc_stat;      /* driver status */
Index: sys/dev/ic/mb86960var.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/mb86960var.h,v
retrieving revision 1.37
diff -u -b -r1.37 mb86960var.h
--- sys/dev/ic/mb86960var.h     12 May 2009 14:25:17 -0000      1.37
+++ sys/dev/ic/mb86960var.h     21 Oct 2011 20:31:11 -0000
@@ -162,7 +162,7 @@
        uint8_t sc_enaddr[ETHER_ADDR_LEN];
 
 #if NRND > 0
-       rndsource_element_t rnd_source;
+       krndsource_t rnd_source;
 #endif
 
        uint32_t sc_stat;       /* driver status */
Index: sys/dev/ic/mtd803var.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/mtd803var.h,v
retrieving revision 1.6
diff -u -b -r1.6 mtd803var.h
--- sys/dev/ic/mtd803var.h      28 Apr 2008 20:23:50 -0000      1.6
+++ sys/dev/ic/mtd803var.h      21 Oct 2011 20:31:11 -0000
@@ -75,7 +75,7 @@
        bus_dmamap_t            buf_dma_map;
 
 #if NRND > 0
-       rndsource_element_t     rnd_src;
+       krndsource_t    rnd_src;
 #endif
 };
 
Index: sys/dev/ic/pckbc.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/pckbc.c,v
retrieving revision 1.51
diff -u -b -r1.51 pckbc.c
--- sys/dev/ic/pckbc.c  8 Aug 2010 09:33:05 -0000       1.51
+++ sys/dev/ic/pckbc.c  21 Oct 2011 20:31:12 -0000
@@ -59,7 +59,7 @@
        int poll_data;  /* data read from inr handler if polling */
        int poll_stat;  /* status read from inr handler if polling */
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
 };
 
Index: sys/dev/ic/rtl81x9var.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/rtl81x9var.h,v
retrieving revision 1.50
diff -u -b -r1.50 rtl81x9var.h
--- sys/dev/ic/rtl81x9var.h     27 Jul 2010 21:02:00 -0000      1.50
+++ sys/dev/ic/rtl81x9var.h     21 Oct 2011 20:31:12 -0000
@@ -226,7 +226,7 @@
        int     (*sc_enable)    (struct rtk_softc *);
        void    (*sc_disable)   (struct rtk_softc *);
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t     rnd_source;
 #endif
 };
 
Index: sys/dev/ic/seeq8005var.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/seeq8005var.h,v
retrieving revision 1.5
diff -u -b -r1.5 seeq8005var.h
--- sys/dev/ic/seeq8005var.h    7 Nov 2001 20:01:58 -0000       1.5
+++ sys/dev/ic/seeq8005var.h    21 Oct 2011 20:31:12 -0000
@@ -86,7 +86,7 @@
        int sc_flags;
 #define SF_8BIT                0x01
 #if NRND > 0
-       rndsource_element_t rnd_source;
+       krndsource_t rnd_source;
 #endif
 };
 
Index: sys/dev/ic/smc91cxxvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/smc91cxxvar.h,v
retrieving revision 1.16
diff -u -b -r1.16 smc91cxxvar.h
--- sys/dev/ic/smc91cxxvar.h    12 May 2009 14:25:18 -0000      1.16
+++ sys/dev/ic/smc91cxxvar.h    21 Oct 2011 20:31:12 -0000
@@ -61,7 +61,7 @@
        uint8_t         sc_intmask;
        uint8_t         sc_txpacketno;          /* cached packetno */
 #if NRND > 0
-       rndsource_element_t rnd_source;
+       krndsource_t rnd_source;
 #endif
 };
 
Index: sys/dev/ic/tulipvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/tulipvar.h,v
retrieving revision 1.65
diff -u -b -r1.65 tulipvar.h
--- sys/dev/ic/tulipvar.h       9 Jul 2011 23:18:05 -0000       1.65
+++ sys/dev/ic/tulipvar.h       21 Oct 2011 20:31:12 -0000
@@ -448,7 +448,7 @@
        int     sc_rxptr;               /* next ready RX descriptor/descsoft */
 
 #if NRND > 0
-       rndsource_element_t sc_rnd_source; /* random source */
+       krndsource_t sc_rnd_source; /* random source */
 #endif
 };
 #endif
Index: sys/dev/isa/fdvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/isa/fdvar.h,v
retrieving revision 1.6
diff -u -b -r1.6 fdvar.h
--- sys/dev/isa/fdvar.h 28 Apr 2008 20:23:52 -0000      1.6
+++ sys/dev/isa/fdvar.h 21 Oct 2011 20:31:12 -0000
@@ -91,6 +91,6 @@
        int sc_active;          /* number of active I/O operations */
 
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
 };
Index: sys/dev/isa/if_eg.c
===================================================================
RCS file: /cvsroot/src/sys/dev/isa/if_eg.c,v
retrieving revision 1.82
diff -u -b -r1.82 if_eg.c
--- sys/dev/isa/if_eg.c 5 Apr 2010 07:20:24 -0000       1.82
+++ sys/dev/isa/if_eg.c 21 Oct 2011 20:31:12 -0000
@@ -114,7 +114,7 @@
        void *  eg_outbuf;              /* Outgoing packet buffer */
 
 #if NRND > 0
-       rndsource_element_t rnd_source;
+       krndsource_t rnd_source;
 #endif
 };
 
Index: sys/dev/isa/if_el.c
===================================================================
RCS file: /cvsroot/src/sys/dev/isa/if_el.c,v
retrieving revision 1.86
diff -u -b -r1.86 if_el.c
--- sys/dev/isa/if_el.c 5 Apr 2010 07:20:24 -0000       1.86
+++ sys/dev/isa/if_el.c 21 Oct 2011 20:31:12 -0000
@@ -80,7 +80,7 @@
        bus_space_handle_t sc_ioh;      /* i/o handle */
 
 #if NRND > 0
-       rndsource_element_t rnd_source;
+       krndsource_t rnd_source;
 #endif
 };
 
Index: sys/dev/isa/if_iy.c
===================================================================
RCS file: /cvsroot/src/sys/dev/isa/if_iy.c,v
retrieving revision 1.88
diff -u -b -r1.88 if_iy.c
--- sys/dev/isa/if_iy.c 5 Apr 2010 07:20:24 -0000       1.88
+++ sys/dev/isa/if_iy.c 21 Oct 2011 20:31:12 -0000
@@ -129,7 +129,7 @@
 #endif
 
 #if NRND > 0
-       rndsource_element_t rnd_source;
+       krndsource_t rnd_source;
 #endif
 };
 
Index: sys/dev/marvell/if_gfevar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/marvell/if_gfevar.h,v
retrieving revision 1.10
diff -u -b -r1.10 if_gfevar.h
--- sys/dev/marvell/if_gfevar.h 28 Apr 2010 13:51:56 -0000      1.10
+++ sys/dev/marvell/if_gfevar.h 21 Oct 2011 20:31:12 -0000
@@ -168,7 +168,7 @@
        struct gfe_rxqueue sc_rxq[4];   /* Hi/MedHi/MedLo/Lo receive queues */
 
 #if NRND > 0 
-       rndsource_element_t sc_rnd_source;
+       krndsource_t sc_rnd_source;
 #endif
 };
 #endif /* _IF_GFEVAR_H_ */
Index: sys/dev/marvell/if_mvgbe.c
===================================================================
RCS file: /cvsroot/src/sys/dev/marvell/if_mvgbe.c,v
retrieving revision 1.13
diff -u -b -r1.13 if_mvgbe.c
--- sys/dev/marvell/if_mvgbe.c  6 Sep 2011 19:38:23 -0000       1.13
+++ sys/dev/marvell/if_mvgbe.c  21 Oct 2011 20:31:12 -0000
@@ -216,7 +216,7 @@
        SIMPLEQ_HEAD(__mvgbe_txmaphead, mvgbe_txmap_entry) sc_txmap_head;
 
 #if NRND > 0
-       rndsource_element_t sc_rnd_source;
+       krndsource_t sc_rnd_source;
 #endif
 };
 
Index: sys/dev/mca/edvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/mca/edvar.h,v
retrieving revision 1.13
diff -u -b -r1.13 edvar.h
--- sys/dev/mca/edvar.h 4 May 2008 13:11:14 -0000       1.13
+++ sys/dev/mca/edvar.h 21 Oct 2011 20:31:12 -0000
@@ -61,6 +61,6 @@
        u_int32_t rba;          /* # of RBAs */
 
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
 };
Index: sys/dev/pci/amdpmvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/amdpmvar.h,v
retrieving revision 1.6
diff -u -b -r1.6 amdpmvar.h
--- sys/dev/pci/amdpmvar.h      28 Apr 2008 20:23:54 -0000      1.6
+++ sys/dev/pci/amdpmvar.h      21 Oct 2011 20:31:12 -0000
@@ -52,7 +52,7 @@
        void *sc_ih;
 
        struct callout sc_rnd_ch;
-       rndsource_element_t sc_rnd_source;
+       krndsource_t sc_rnd_source;
 #ifdef AMDPM_RND_COUNTERS
        struct evcnt sc_rnd_hits;
        struct evcnt sc_rnd_miss;
Index: sys/dev/pci/hifn7751.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/hifn7751.c,v
retrieving revision 1.46
diff -u -b -r1.46 hifn7751.c
--- sys/dev/pci/hifn7751.c      13 Nov 2010 13:52:05 -0000      1.46
+++ sys/dev/pci/hifn7751.c      21 Oct 2011 20:31:13 -0000
@@ -50,13 +50,6 @@
 #include <sys/cdefs.h>
 __KERNEL_RCSID(0, "$NetBSD: hifn7751.c,v 1.46 2010/11/13 13:52:05 uebayasi Exp 
$");
 
-#include "rnd.h"
-
-#if NRND == 0
-#error hifn7751 requires rnd pseudo-devices
-#endif
-
-
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/proc.h>
@@ -71,7 +64,7 @@
 #include <dev/rndvar.h>
 #else
 #include <opencrypto/cryptodev.h>
-#include <sys/rnd.h>
+#include <sys/cprng.h>
 #endif
 
 #include <dev/pci/pcireg.h>
@@ -2077,7 +2070,7 @@
                           to generate IVs has been FIPS140-2
                           certified by several labs. */
 #ifdef __NetBSD__
-                       arc4randbytes(sc->sc_sessions[i].hs_iv,
+                       cprng_fast(sc->sc_sessions[i].hs_iv,
                            c->cri_alg == CRYPTO_AES_CBC ?
                                HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
 #else  /* FreeBSD and OpenBSD have get_random_bytes */
Index: sys/dev/pci/hifn7751var.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/hifn7751var.h,v
retrieving revision 1.7
diff -u -b -r1.7 hifn7751var.h
--- sys/dev/pci/hifn7751var.h   11 Dec 2005 12:22:49 -0000      1.7
+++ sys/dev/pci/hifn7751var.h   21 Oct 2011 20:31:13 -0000
@@ -168,7 +168,7 @@
 
        struct callout          sc_rngto;       /* rng timeout */
        struct callout          sc_tickto;      /* led-clear timeout */
-       rndsource_element_t     sc_rnd_source;
+       krndsource_t    sc_rnd_source;
        int                     sc_rngfirst;
        int                     sc_rnghz;
        int                     sc_c_busy;      /* command ring busy */
Index: sys/dev/pci/if_bce.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_bce.c,v
retrieving revision 1.33
diff -u -b -r1.33 if_bce.c
--- sys/dev/pci/if_bce.c        13 Nov 2010 13:52:05 -0000      1.33
+++ sys/dev/pci/if_bce.c        21 Oct 2011 20:31:13 -0000
@@ -139,7 +139,7 @@
        int                     bce_txsnext;    /* next available tx slot */
        callout_t               bce_timeout;
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
 };
 
Index: sys/dev/pci/if_bgevar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_bgevar.h,v
retrieving revision 1.7
diff -u -b -r1.7 if_bgevar.h
--- sys/dev/pci/if_bgevar.h     18 May 2011 01:02:43 -0000      1.7
+++ sys/dev/pci/if_bgevar.h     21 Oct 2011 20:31:13 -0000
@@ -290,7 +290,7 @@
        struct sysctllog        *bge_log;
 
 #if NRND > 0
-       rndsource_element_t     rnd_source;     /* random source */
+       krndsource_t    rnd_source;     /* random source */
 #endif
 };
 
Index: sys/dev/pci/if_casvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_casvar.h,v
retrieving revision 1.2
diff -u -b -r1.2 if_casvar.h
--- sys/dev/pci/if_casvar.h     18 Jan 2010 18:09:22 -0000      1.2
+++ sys/dev/pci/if_casvar.h     21 Oct 2011 20:31:13 -0000
@@ -195,7 +195,7 @@
        void                    *sc_sh;         /* shutdownhook cookie */
 
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
 
        struct evcnt            sc_ev_intr;
Index: sys/dev/pci/if_devar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_devar.h,v
retrieving revision 1.55
diff -u -b -r1.55 if_devar.h
--- sys/dev/pci/if_devar.h      5 Apr 2010 07:20:25 -0000       1.55
+++ sys/dev/pci/if_devar.h      21 Oct 2011 20:31:13 -0000
@@ -695,7 +695,7 @@
     tulip_desc_t *tulip_rxdescs;
     tulip_desc_t *tulip_txdescs;
 #if defined(__NetBSD__) && NRND > 0
-    rndsource_element_t    tulip_rndsource;
+    krndsource_t    tulip_rndsource;
 #endif
 };
 
Index: sys/dev/pci/if_dge.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_dge.c,v
retrieving revision 1.31
diff -u -b -r1.31 if_dge.c
--- sys/dev/pci/if_dge.c        13 Nov 2010 13:52:06 -0000      1.31
+++ sys/dev/pci/if_dge.c        21 Oct 2011 20:31:14 -0000
@@ -334,7 +334,7 @@
        uint16_t sc_eeprom[EEPROM_SIZE];
 
 #if NRND > 0
-       rndsource_element_t rnd_source; /* random source */
+       krndsource_t rnd_source; /* random source */
 #endif
 #ifdef DGE_OFFBYONE_RXBUG
        void *sc_bugbuf;
Index: sys/dev/pci/if_iwi.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_iwi.c,v
retrieving revision 1.87
diff -u -b -r1.87 if_iwi.c
--- sys/dev/pci/if_iwi.c        23 May 2011 15:37:36 -0000      1.87
+++ sys/dev/pci/if_iwi.c        21 Oct 2011 20:31:14 -0000
@@ -38,6 +38,7 @@
 #include <sys/conf.h>
 #include <sys/kauth.h>
 #include <sys/proc.h>
+#include <sys/cprng.h>
 
 #include <sys/bus.h>
 #include <machine/endian.h>
@@ -2386,7 +2387,8 @@
                        return error;
        }
 
-       data = htole32(arc4random());
+       cprng_fast(&data, sizeof(data));
+       data = htole32(data);
        DPRINTF(("Setting initialization vector to %u\n", le32toh(data)));
        error = iwi_cmd(sc, IWI_CMD_SET_IV, &data, sizeof data, 0);
        if (error != 0)
Index: sys/dev/pci/if_jme.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_jme.c,v
retrieving revision 1.17
diff -u -b -r1.17 if_jme.c
--- sys/dev/pci/if_jme.c        30 Mar 2011 18:11:37 -0000      1.17
+++ sys/dev/pci/if_jme.c        21 Oct 2011 20:31:15 -0000
@@ -168,7 +168,7 @@
        uint32_t jme_txcsr;             /* TX config register */
        uint32_t jme_rxcsr;             /* RX config register */
 #if NRND > 0
-       rndsource_element_t rnd_source;
+       krndsource_t rnd_source;
 #endif
        /* interrupt coalition parameters */
        struct sysctllog *jme_clog;
Index: sys/dev/pci/if_mskvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_mskvar.h,v
retrieving revision 1.8
diff -u -b -r1.8 if_mskvar.h
--- sys/dev/pci/if_mskvar.h     24 Dec 2009 18:27:32 -0000      1.8
+++ sys/dev/pci/if_mskvar.h     21 Oct 2011 20:31:15 -0000
@@ -210,7 +210,7 @@
        int                     sk_status_idx;
        int                     sk_status_own_idx;
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t     rnd_source;
 #endif
 };
 
Index: sys/dev/pci/if_pcn.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_pcn.c,v
retrieving revision 1.52
diff -u -b -r1.52 if_pcn.c
--- sys/dev/pci/if_pcn.c        13 Nov 2010 13:52:06 -0000      1.52
+++ sys/dev/pci/if_pcn.c        21 Oct 2011 20:31:15 -0000
@@ -313,7 +313,7 @@
        uint32_t sc_mode;               /* prototype MODE register */
 
 #if NRND > 0
-       rndsource_element_t rnd_source; /* random source */
+       krndsource_t rnd_source;        /* random source */
 #endif
 };
 
Index: sys/dev/pci/if_sip.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_sip.c,v
retrieving revision 1.150
diff -u -b -r1.150 if_sip.c
--- sys/dev/pci/if_sip.c        15 Oct 2011 19:50:20 -0000      1.150
+++ sys/dev/pci/if_sip.c        21 Oct 2011 20:31:15 -0000
@@ -355,7 +355,7 @@
        void (*sc_rxintr)(struct sip_softc *);
 
 #if NRND > 0
-       rndsource_element_t rnd_source; /* random source */
+       krndsource_t rnd_source;        /* random source */
 #endif
 };
 
Index: sys/dev/pci/if_skvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_skvar.h,v
retrieving revision 1.15
diff -u -b -r1.15 if_skvar.h
--- sys/dev/pci/if_skvar.h      8 Sep 2008 21:20:03 -0000       1.15
+++ sys/dev/pci/if_skvar.h      21 Oct 2011 20:31:15 -0000
@@ -205,7 +205,7 @@
        bus_dma_tag_t           sc_dmatag;
        struct sk_if_softc      *sk_if[2];
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t     rnd_source;
 #endif
 };
 
Index: sys/dev/pci/if_tlvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_tlvar.h,v
retrieving revision 1.14
diff -u -b -r1.14 if_tlvar.h
--- sys/dev/pci/if_tlvar.h      19 Oct 2009 18:41:15 -0000      1.14
+++ sys/dev/pci/if_tlvar.h      21 Oct 2011 20:31:15 -0000
@@ -85,7 +85,7 @@
        int oerr_mcopy;
 #endif
 #if NRND > 0
-       rndsource_element_t rnd_source;
+       krndsource_t rnd_source;
 #endif
 };
 #define tl_if            tl_ec.ec_if
Index: sys/dev/pci/if_vr.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_vr.c,v
retrieving revision 1.107
diff -u -b -r1.107 if_vr.c
--- sys/dev/pci/if_vr.c 16 Dec 2010 17:07:44 -0000      1.107
+++ sys/dev/pci/if_vr.c 21 Oct 2011 20:31:16 -0000
@@ -234,7 +234,7 @@
        uint32_t        vr_save_irq;
 
 #if NRND > 0
-       rndsource_element_t rnd_source; /* random source */
+       krndsource_t rnd_source;        /* random source */
 #endif
 };
 
Index: sys/dev/pci/if_vtevar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_vtevar.h,v
retrieving revision 1.1
diff -u -b -r1.1 if_vtevar.h
--- sys/dev/pci/if_vtevar.h     26 Jan 2011 18:48:13 -0000      1.1
+++ sys/dev/pci/if_vtevar.h     21 Oct 2011 20:31:16 -0000
@@ -139,7 +139,7 @@
        int                     vte_int_tx_mod;
 
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
 };
 
Index: sys/dev/pci/if_wm.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_wm.c,v
retrieving revision 1.223
diff -u -b -r1.223 if_wm.c
--- sys/dev/pci/if_wm.c 1 Jul 2011 07:45:39 -0000       1.223
+++ sys/dev/pci/if_wm.c 21 Oct 2011 20:31:17 -0000
@@ -379,7 +379,7 @@
        int sc_mchash_type;             /* multicast filter offset */
 
 #if NRND > 0
-       rndsource_element_t rnd_source; /* random source */
+       krndsource_t rnd_source;        /* random source */
 #endif
 };
 
Index: sys/dev/pci/ubsec.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/ubsec.c,v
retrieving revision 1.25
diff -u -b -r1.25 ubsec.c
--- sys/dev/pci/ubsec.c 13 Nov 2010 13:52:09 -0000      1.25
+++ sys/dev/pci/ubsec.c 21 Oct 2011 20:31:17 -0000
@@ -65,7 +65,7 @@
  #include <dev/rndvar.h>
  #include <sys/md5k.h>
 #else
- #include <sys/rnd.h>
+ #include <sys/cprng.h>
  #include <sys/md5.h>
 #endif
 #include <sys/sha1.h>
@@ -808,8 +808,7 @@
        if (encini) {
                /* get an IV, network byte order */
 #ifdef __NetBSD__
-               rnd_extract_data(ses->ses_iv,
-                   sizeof(ses->ses_iv), RND_EXTRACT_ANY);
+               cprng_fast(ses->ses_iv, sizeof(ses->ses_iv));
 #else
                get_random_bytes(ses->ses_iv, sizeof(ses->ses_iv));
 #endif
Index: sys/dev/pci/ixgbe/ixgbe.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/ixgbe/ixgbe.c,v
retrieving revision 1.1
diff -u -b -r1.1 ixgbe.c
--- sys/dev/pci/ixgbe/ixgbe.c   12 Aug 2011 21:55:29 -0000      1.1
+++ sys/dev/pci/ixgbe/ixgbe.c   21 Oct 2011 20:31:18 -0000
@@ -4160,7 +4160,7 @@
                reta = 0;
 
                /* set up random bits */
-               arc4randbytes(&r, sizeof(r));
+               cprng_fast(&r, sizeof(r));
 
                /* Set up the redirection table */
                for (i = 0, j = 0; i < 128; i++, j++) {
Index: sys/dev/pcmcia/if_xivar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pcmcia/if_xivar.h,v
retrieving revision 1.6
diff -u -b -r1.6 if_xivar.h
--- sys/dev/pcmcia/if_xivar.h   6 Dec 2009 23:05:39 -0000       1.6
+++ sys/dev/pcmcia/if_xivar.h   21 Oct 2011 20:31:18 -0000
@@ -45,7 +45,7 @@
        u_int8_t        sc_rev;                 /* Chip revision */
 
 #if NRND > 0
-       rndsource_element_t     sc_rnd_source;
+       krndsource_t    sc_rnd_source;
 #endif
 };
 
Index: sys/dev/scsipi/cdvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/cdvar.h,v
retrieving revision 1.29
diff -u -b -r1.29 cdvar.h
--- sys/dev/scsipi/cdvar.h      19 Oct 2009 18:41:16 -0000      1.29
+++ sys/dev/scsipi/cdvar.h      21 Oct 2011 20:31:18 -0000
@@ -48,6 +48,6 @@
        struct callout sc_callout;
 
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
 };
Index: sys/dev/scsipi/sdvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/sdvar.h,v
retrieving revision 1.32
diff -u -b -r1.32 sdvar.h
--- sys/dev/scsipi/sdvar.h      10 Apr 2009 17:36:42 -0000      1.32
+++ sys/dev/scsipi/sdvar.h      21 Oct 2011 20:31:18 -0000
@@ -92,7 +92,7 @@
        char name[16]; /* product name, for default disklabel */
 
 #if NRND > 0
-       rndsource_element_t rnd_source;
+       krndsource_t rnd_source;
 #endif
 };
 
Index: sys/dev/scsipi/stvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/stvar.h,v
retrieving revision 1.21
diff -u -b -r1.21 stvar.h
--- sys/dev/scsipi/stvar.h      6 Dec 2009 22:48:17 -0000       1.21
+++ sys/dev/scsipi/stvar.h      21 Oct 2011 20:31:18 -0000
@@ -147,7 +147,7 @@
        struct io_stats *stats;         /* statistics for the drive */
 
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
 };
 
Index: sys/dev/usb/if_auereg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/if_auereg.h,v
retrieving revision 1.23
diff -u -b -r1.23 if_auereg.h
--- sys/dev/usb/if_auereg.h     4 Sep 2009 18:10:08 -0000       1.23
+++ sys/dev/usb/if_auereg.h     21 Oct 2011 20:31:18 -0000
@@ -229,7 +229,7 @@
        struct ethercom         aue_ec;
        struct mii_data         aue_mii;
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
        struct lwp              *aue_thread;
        int                     aue_closing;
Index: sys/dev/usb/if_axereg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/if_axereg.h,v
retrieving revision 1.12
diff -u -b -r1.12 if_axereg.h
--- sys/dev/usb/if_axereg.h     14 Aug 2010 10:47:57 -0000      1.12
+++ sys/dev/usb/if_axereg.h     21 Oct 2011 20:31:18 -0000
@@ -200,7 +200,7 @@
        struct ethercom         axe_ec;
        struct mii_data         axe_mii;
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
        usbd_device_handle      axe_udev;
        usbd_interface_handle   axe_iface;
Index: sys/dev/usb/if_cdcereg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/if_cdcereg.h,v
retrieving revision 1.5
diff -u -b -r1.5 if_cdcereg.h
--- sys/dev/usb/if_cdcereg.h    4 Sep 2009 18:10:08 -0000       1.5
+++ sys/dev/usb/if_cdcereg.h    21 Oct 2011 20:31:18 -0000
@@ -69,7 +69,7 @@
        device_t cdce_dev;
        struct ethercom          cdce_ec;
 #if NRND > 0
-       rndsource_element_t      rnd_source;
+       krndsource_t     rnd_source;
 #endif
 #define GET_IFP(sc) (&(sc)->cdce_ec.ec_if)
        usbd_device_handle       cdce_udev;
Index: sys/dev/usb/if_cuereg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/if_cuereg.h,v
retrieving revision 1.16
diff -u -b -r1.16 if_cuereg.h
--- sys/dev/usb/if_cuereg.h     4 Sep 2009 18:10:08 -0000       1.16
+++ sys/dev/usb/if_cuereg.h     21 Oct 2011 20:31:18 -0000
@@ -169,7 +169,7 @@
 
        struct ethercom         cue_ec;
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
 #define GET_IFP(sc) (&(sc)->cue_ec.ec_if)
 
Index: sys/dev/usb/if_kuereg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/if_kuereg.h,v
retrieving revision 1.16
diff -u -b -r1.16 if_kuereg.h
--- sys/dev/usb/if_kuereg.h     3 Nov 2010 22:30:50 -0000       1.16
+++ sys/dev/usb/if_kuereg.h     21 Oct 2011 20:31:18 -0000
@@ -163,7 +163,7 @@
 
        struct ethercom         kue_ec;
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
 #define GET_IFP(sc) (&(sc)->kue_ec.ec_if)
 
Index: sys/dev/usb/if_udavreg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/if_udavreg.h,v
retrieving revision 1.6
diff -u -b -r1.6 if_udavreg.h
--- sys/dev/usb/if_udavreg.h    3 Nov 2010 22:30:50 -0000       1.6
+++ sys/dev/usb/if_udavreg.h    21 Oct 2011 20:31:18 -0000
@@ -190,7 +190,7 @@
        int                     sc_link;
 #define        sc_media udav_mii.mii_media
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
        struct udav_cdata       sc_cdata;
 
Index: sys/dev/usb/if_upl.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/if_upl.c,v
retrieving revision 1.38
diff -u -b -r1.38 if_upl.c
--- sys/dev/usb/if_upl.c        3 Nov 2010 22:28:31 -0000       1.38
+++ sys/dev/usb/if_upl.c        21 Oct 2011 20:31:18 -0000
@@ -135,7 +135,7 @@
 
        struct ifnet            sc_if;
 #if NRND > 0
-       rndsource_element_t     sc_rnd_source;
+       krndsource_t    sc_rnd_source;
 #endif
 
        struct callout          sc_stat_ch;
Index: sys/dev/usb/if_urlreg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/if_urlreg.h,v
retrieving revision 1.6
diff -u -b -r1.6 if_urlreg.h
--- sys/dev/usb/if_urlreg.h     3 Nov 2010 22:30:50 -0000       1.6
+++ sys/dev/usb/if_urlreg.h     21 Oct 2011 20:31:18 -0000
@@ -176,7 +176,7 @@
        int                     sc_link;
 #define        sc_media url_mii.mii_media
 #if NRND > 0
-       rndsource_element_t     rnd_source;
+       krndsource_t    rnd_source;
 #endif
        struct url_cdata        sc_cdata;
 
Index: sys/dev/usb/ucom.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/ucom.c,v
retrieving revision 1.87
diff -u -b -r1.87 ucom.c
--- sys/dev/usb/ucom.c  24 Apr 2011 16:27:01 -0000      1.87
+++ sys/dev/usb/ucom.c  21 Oct 2011 20:31:19 -0000
@@ -147,7 +147,7 @@
        u_char                  sc_dying;       /* disconnecting */
 
 #if defined(__NetBSD__) && NRND > 0
-       rndsource_element_t     sc_rndsource;   /* random source */
+       krndsource_t    sc_rndsource;   /* random source */
 #endif
 };
 
Index: sys/dev/usb/uhidev.h
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/uhidev.h,v
retrieving revision 1.10
diff -u -b -r1.10 uhidev.h
--- sys/dev/usb/uhidev.h        3 Nov 2010 22:34:24 -0000       1.10
+++ sys/dev/usb/uhidev.h        21 Oct 2011 20:31:19 -0000
@@ -68,7 +68,7 @@
 #define        UHIDEV_OPEN     0x01    /* device is open */
        void (*sc_intr)(struct uhidev *, void *, u_int);
 #if NRND > 0
-        rndsource_element_t     rnd_source;
+        krndsource_t     rnd_source;
 #endif
 };
 
Index: sys/dist/pf/net/pf.c
===================================================================
RCS file: /cvsroot/src/sys/dist/pf/net/pf.c,v
retrieving revision 1.66
diff -u -b -r1.66 pf.c
--- sys/dist/pf/net/pf.c        29 Aug 2011 09:50:04 -0000      1.66
+++ sys/dist/pf/net/pf.c        21 Oct 2011 20:31:20 -0000
@@ -93,7 +93,7 @@
 #ifndef __NetBSD__
 #include <dev/rndvar.h>
 #else
-#include <sys/rnd.h>
+#include <sys/cprng.h>
 #endif /* __NetBSD__ */
 
 #include <net/pfvar.h>
@@ -2321,29 +2321,30 @@
                        switch (af) {
 #ifdef INET
                        case AF_INET:
-                               rpool->counter.addr32[0] = htonl(arc4random());
+                               rpool->counter.addr32[0] =
+                                   htonl(cprng_fast32());
                                break;
 #endif /* INET */
 #ifdef INET6
                        case AF_INET6:
                                if (rmask->addr32[3] != 0xffffffff)
                                        rpool->counter.addr32[3] =
-                                           htonl(arc4random());
+                                           htonl(cprng_fast32());
                                else
                                        break;
                                if (rmask->addr32[2] != 0xffffffff)
                                        rpool->counter.addr32[2] =
-                                           htonl(arc4random());
+                                           htonl(cprng_fast32());
                                else
                                        break;
                                if (rmask->addr32[1] != 0xffffffff)
                                        rpool->counter.addr32[1] =
-                                           htonl(arc4random());
+                                           htonl(cprng_fast32());
                                else
                                        break;
                                if (rmask->addr32[0] != 0xffffffff)
                                        rpool->counter.addr32[0] =
-                                           htonl(arc4random());
+                                           htonl(cprng_fast32());
                                break;
 #endif /* INET6 */
                        }
@@ -2476,7 +2477,7 @@
                                high = tmp;
                        }
                        /* low < high */
-                       cut = htonl(arc4random()) % (1 + high - low) + low;
+                       cut = htonl(cprng_fast32()) % (1 + high - low) + low;
                        /* low <= cut <= high */
                        for (tmp = cut; tmp <= high; ++(tmp)) {
                                key.gwy.port = htons(tmp);
@@ -3305,7 +3306,7 @@
                    !pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
                    pd->lookup.gid))
                        r = TAILQ_NEXT(r, entries);
-               else if (r->prob && r->prob <= arc4random())
+               else if (r->prob && r->prob <= cprng_fast32())
                        r = TAILQ_NEXT(r, entries);
                else if (r->match_tag && !pf_match_tag(m, r, &tag))
                        r = TAILQ_NEXT(r, entries);
@@ -3710,7 +3711,7 @@
                                        sport = th->th_dport;
                                }
                        }
-                       s->src.seqhi = htonl(arc4random());
+                       s->src.seqhi = htonl(cprng_fast32());
                        /* Find mss option */
                        mss = pf_get_mss(m, off, th->th_off, af);
                        mss = pf_calc_mss(saddr, af, mss);
@@ -3767,7 +3768,7 @@
                    r->flagset || r->type || r->code ||
                    r->os_fingerprint != PF_OSFP_ANY)
                        r = TAILQ_NEXT(r, entries);
-               else if (r->prob && r->prob <= arc4random())
+               else if (r->prob && r->prob <= cprng_fast32())
                        r = TAILQ_NEXT(r, entries);
                else if (r->match_tag && !pf_match_tag(m, r, &tag))
                        r = TAILQ_NEXT(r, entries);
@@ -3895,7 +3896,7 @@
                        }
                        (*state)->src.max_win = MAX(ntohs(th->th_win), 1);
                        if ((*state)->dst.seqhi == 1)
-                               (*state)->dst.seqhi = htonl(arc4random());
+                               (*state)->dst.seqhi = htonl(cprng_fast32());
                        pf_send_tcp((*state)->rule.ptr, pd->af, &psrc->addr,
                            &pdst->addr, psrc->port, pdst->port,
                            (*state)->dst.seqhi, 0, TH_SYN, 0,
Index: sys/dist/pf/netinet/tcp_rndiss.c
===================================================================
RCS file: /cvsroot/src/sys/dist/pf/netinet/tcp_rndiss.c,v
retrieving revision 1.2
diff -u -b -r1.2 tcp_rndiss.c
--- sys/dist/pf/netinet/tcp_rndiss.c    18 Jun 2008 09:06:27 -0000      1.2
+++ sys/dist/pf/netinet/tcp_rndiss.c    21 Oct 2011 20:31:20 -0000
@@ -72,7 +72,7 @@
 __KERNEL_RCSID(0, "$NetBSD: tcp_rndiss.c,v 1.2 2008/06/18 09:06:27 yamt Exp 
$");
 
 #include <sys/param.h>
-#include <sys/rnd.h>
+#include <sys/cprng.h>
 
 #include <netinet/tcp.h>
 #include <netinet/tcp_seq.h>
@@ -104,8 +104,7 @@
 void
 tcp_rndiss_init(void)
 {
-       rnd_extract_data(tcp_rndiss_sbox, sizeof(tcp_rndiss_sbox),
-           RND_EXTRACT_ANY);
+       cprng_strong(kern_cprng, tcp_rndiss_sbox, sizeof(tcp_rndiss_sbox));
 
        tcp_rndiss_reseed = time_second + TCP_RNDISS_OUT;
        tcp_rndiss_msb = tcp_rndiss_msb == 0x8000 ? 0 : 0x8000;
@@ -121,5 +120,5 @@
 
        /* (arc4random() & 0x7fff) ensures a 32768 byte gap between ISS */
        return ((tcp_rndiss_encrypt(tcp_rndiss_cnt++) | tcp_rndiss_msb) <<16) |
-               (arc4random() & 0x7fff);
+               (cprng_fast32() & 0x7fff);
 }
Index: sys/fs/tmpfs/tmpfs_subr.c
===================================================================
RCS file: /cvsroot/src/sys/fs/tmpfs/tmpfs_subr.c,v
retrieving revision 1.77
diff -u -b -r1.77 tmpfs_subr.c
--- sys/fs/tmpfs/tmpfs_subr.c   27 Aug 2011 15:32:28 -0000      1.77
+++ sys/fs/tmpfs/tmpfs_subr.c   21 Oct 2011 20:31:20 -0000
@@ -124,7 +124,7 @@
         * for applications that do not understand 64-bit ino_t.
         */
        nnode->tn_id = (ino_t)((uintptr_t)nnode / sizeof(*nnode));
-       nnode->tn_gen = TMPFS_NODE_GEN_MASK & arc4random();
+       nnode->tn_gen = TMPFS_NODE_GEN_MASK & random();
 
        /* Generic initialization. */
        nnode->tn_type = type;
Index: sys/kern/exec_elf.c
===================================================================
RCS file: /cvsroot/src/sys/kern/exec_elf.c,v
retrieving revision 1.32
diff -u -b -r1.32 exec_elf.c
--- sys/kern/exec_elf.c 27 Aug 2011 17:53:21 -0000      1.32
+++ sys/kern/exec_elf.c 21 Oct 2011 20:31:21 -0000
@@ -77,6 +77,7 @@
 #include <sys/stat.h>
 #include <sys/kauth.h>
 #include <sys/bitops.h>
+#include <sys/cprng.h>
 
 #include <sys/cpu.h>
 #include <machine/reg.h>
@@ -134,7 +135,7 @@
 
                pax_align = align;
 
-               r = arc4random();
+               r = cprng_fast32();
 
                if (pax_align == 0)
                        pax_align = PGSHIFT;
Index: sys/kern/init_main.c
===================================================================
RCS file: /cvsroot/src/sys/kern/init_main.c,v
retrieving revision 1.436
diff -u -b -r1.436 init_main.c
--- sys/kern/init_main.c        28 Sep 2011 15:52:47 -0000      1.436
+++ sys/kern/init_main.c        21 Oct 2011 20:31:21 -0000
@@ -186,9 +186,7 @@
 #endif
 #include <sys/domain.h>
 #include <sys/namei.h>
-#if NRND > 0
 #include <sys/rnd.h>
-#endif
 #include <sys/pipe.h>
 #if NVERIEXEC > 0
 #include <sys/verified_exec.h>
@@ -204,6 +202,7 @@
 #ifdef PTRACE
 #include <sys/ptrace.h>
 #endif /* PTRACE */
+#include <sys/cprng.h>
 
 #include <sys/syscall.h>
 #include <sys/syscallargs.h>
@@ -260,6 +259,8 @@
 
 int    start_init_exec;                /* semaphore for start_init() */
 
+cprng_strong_t *kern_cprng;
+
 static void check_console(struct lwp *l);
 static void start_init(void *);
 static void configure(void);
@@ -375,9 +376,9 @@
        /*
         * The following things must be done before autoconfiguration.
         */
-#if NRND > 0
-       rnd_init();             /* initialize random number generator */
-#endif
+       rnd_init();             /* initialize entropy pool */
+
+       cprng_init();           /* initialize cryptographic PRNG */
 
        /* Initialize process and pgrp structures. */
 #ifdef KERN_SA
@@ -501,6 +502,9 @@
        /* Initialize the disk wedge subsystem. */
        dkwedge_init();
 
+       /* Initialize the kernel strong PRNG. */
+       kern_cprng = cprng_strong_create("kernel_cprng", IPL_VM);
+                                        
        /* Initialize interfaces. */
        ifinit1();
 
@@ -509,7 +513,6 @@
        /* Initialize sockets thread(s) */
        soinit1();
 
-
        /* Configure the system hardware.  This will enable interrupts. */
        configure();
 
Index: sys/kern/init_sysctl.c
===================================================================
RCS file: /cvsroot/src/sys/kern/init_sysctl.c,v
retrieving revision 1.183
diff -u -b -r1.183 init_sysctl.c
--- sys/kern/init_sysctl.c      30 Aug 2011 12:39:59 -0000      1.183
+++ sys/kern/init_sysctl.c      21 Oct 2011 20:31:21 -0000
@@ -38,7 +38,6 @@
 #include "opt_sa.h"
 #include "opt_posix.h"
 #include "pty.h"
-#include "rnd.h"
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -49,7 +48,7 @@
 #include <sys/kernel.h>
 #include <sys/unistd.h>
 #include <sys/disklabel.h>
-#include <sys/rnd.h>
+#include <sys/cprng.h>
 #include <sys/vnode.h>
 #include <sys/mount.h>
 #include <sys/namei.h>
@@ -1395,12 +1394,9 @@
 static int
 sysctl_kern_urnd(SYSCTLFN_ARGS)
 {
-#if NRND > 0
        int v, rv;
 
-       KERNEL_LOCK(1, NULL);
-       rv = rnd_extract_data(&v, sizeof(v), RND_EXTRACT_ANY);
-       KERNEL_UNLOCK_ONE(NULL);
+       rv = cprng_strong(sysctl_prng, &v, sizeof(v));
        if (rv == sizeof(v)) {
                struct sysctlnode node = *rnode;
                node.sysctl_data = &v;
@@ -1408,9 +1404,6 @@
        }
        else
                return (EIO);   /*XXX*/
-#else
-       return (EOPNOTSUPP);
-#endif
 }
 
 /*
@@ -1420,7 +1413,6 @@
 static int
 sysctl_kern_arnd(SYSCTLFN_ARGS)
 {
-#if NRND > 0
        int error;
        void *v;
        struct sysctlnode node = *rnode;
@@ -1431,15 +1423,12 @@
                return E2BIG;
 
        v = kmem_alloc(*oldlenp, KM_SLEEP);
-       arc4randbytes(v, *oldlenp);
+       cprng_fast(v, *oldlenp);
        node.sysctl_data = v;
        node.sysctl_size = *oldlenp;
        error = sysctl_lookup(SYSCTLFN_CALL(&node));
        kmem_free(v, *oldlenp);
        return error;
-#else
-       return (EOPNOTSUPP);
-#endif
 }
 /*
  * sysctl helper routine to do kern.lwp.* work.
Index: sys/kern/kern_exec.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_exec.c,v
retrieving revision 1.329
diff -u -b -r1.329 kern_exec.c
--- sys/kern/kern_exec.c        16 Sep 2011 21:02:28 -0000      1.329
+++ sys/kern/kern_exec.c        21 Oct 2011 20:31:21 -0000
@@ -103,6 +103,7 @@
 #include <sys/verified_exec.h>
 #endif /* NVERIEXEC > 0 */
 #include <sys/sdt.h>
+#include <sys/cprng.h>
 
 #include <uvm/uvm_extern.h>
 
@@ -780,7 +781,7 @@
 
 #ifdef PAX_ASLR
        if (pax_aslr_active(l))
-               len += (arc4random() % PAGE_SIZE);
+               len += (cprng_fast32() % PAGE_SIZE);
 #endif /* PAX_ASLR */
 
 #ifdef STACKALIGN      /* arm, etc. */
Index: sys/kern/kern_pax.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_pax.c,v
retrieving revision 1.25
diff -u -b -r1.25 kern_pax.c
--- sys/kern/kern_pax.c 24 Apr 2011 18:46:22 -0000      1.25
+++ sys/kern/kern_pax.c 21 Oct 2011 20:31:21 -0000
@@ -43,6 +43,7 @@
 #include <sys/vnode.h>
 #include <sys/queue.h>
 #include <sys/kauth.h>
+#include <sys/cprng.h>
 
 #ifdef PAX_ASLR
 #include <sys/mman.h>
@@ -310,7 +311,7 @@
        if (!pax_aslr_active(l))
                return;
 
-       vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(arc4random(),
+       vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(cprng_fast32(),
            PAX_ASLR_DELTA_MMAP_LSB, PAX_ASLR_DELTA_MMAP_LEN);
 }
 
@@ -344,7 +345,7 @@
 pax_aslr_stack(struct lwp *l, struct exec_package *epp, u_long *max_stack_size)
 {
        if (pax_aslr_active(l)) {
-               u_long d =  PAX_ASLR_DELTA(arc4random(),
+               u_long d =  PAX_ASLR_DELTA(cprng_fast32(),
                    PAX_ASLR_DELTA_STACK_LSB,
                    PAX_ASLR_DELTA_STACK_LEN);
 #ifdef PAX_ASLR_DEBUG
Index: sys/kern/kern_ssp.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_ssp.c,v
retrieving revision 1.5
diff -u -b -r1.5 kern_ssp.c
--- sys/kern/kern_ssp.c 1 Feb 2010 16:14:58 -0000       1.5
+++ sys/kern/kern_ssp.c 21 Oct 2011 20:31:21 -0000
@@ -32,6 +32,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/intr.h>
+#include <sys/cprng.h>
 
 #if defined(__SSP__) || defined(__SSP_ALL__)
 long __stack_chk_guard[8] = {0, 0, 0, 0, 0, 0, 0, 0};
@@ -57,7 +58,7 @@
        size_t i;
        long guard[__arraycount(__stack_chk_guard)];
 
-       arc4randbytes(guard, sizeof(guard));
+       cprng_fast(guard, sizeof(guard));
        s = splhigh();
        for (i = 0; i < __arraycount(guard); i++)
                __stack_chk_guard[i] = guard[i];
Index: sys/kern/kern_sysctl.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_sysctl.c,v
retrieving revision 1.232
diff -u -b -r1.232 kern_sysctl.c
--- sys/kern/kern_sysctl.c      5 Oct 2011 13:24:09 -0000       1.232
+++ sys/kern/kern_sysctl.c      21 Oct 2011 20:31:22 -0000
@@ -84,6 +84,7 @@
 #include <sys/syscallargs.h>
 #include <sys/kauth.h>
 #include <sys/ktrace.h>
+#include <sys/cprng.h>
 
 #define        MAXDESCLEN      1024
 MALLOC_DEFINE(M_SYSCTLNODE, "sysctlnode", "sysctl node structures");
@@ -158,6 +159,8 @@
 #endif
 char defcorename[MAXPATHLEN] = DEFCORENAME;
 
+cprng_strong_t *sysctl_prng;
+
 /*
  * ********************************************************************
  * Section 0: Some simple glue
@@ -245,12 +248,15 @@
  * trees that claim to be readonly at the root now are, and if
  * the main tree is readonly, *everything* is.
  *
+ * Also starts up the PRNG used for the "random" sysctl: it's
+ * better to start it later than sooner.
+ *
  * Call this at the end of kernel init.
  */
 void
 sysctl_finalize(void)
 {
-
+        sysctl_prng = cprng_strong_create("sysctl", IPL_VM);
        sysctl_root.sysctl_flags |= CTLFLAG_PERMANENT;
 }
 
Index: sys/kern/kern_uuid.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_uuid.c,v
retrieving revision 1.17
diff -u -b -r1.17 kern_uuid.c
--- sys/kern/kern_uuid.c        4 May 2010 19:23:56 -0000       1.17
+++ sys/kern/kern_uuid.c        21 Oct 2011 20:31:22 -0000
@@ -44,6 +44,7 @@
 #include <sys/mount.h>
 #include <sys/syscallargs.h>
 #include <sys/uio.h>
+#include <sys/cprng.h>
 
 #include <net/if.h>
 #include <net/if_dl.h>
@@ -126,7 +127,7 @@
        splx(s);
 
        for (i = 0; i < (UUID_NODE_LEN>>1); i++)
-               node[i] = (uint16_t)arc4random();
+               node[i] = (uint16_t)cprng_fast32();
        *((uint8_t*)node) |= 0x01;
 }
 
@@ -165,7 +166,7 @@
        if (uuid_last.time.ll == 0LL || uuid_last.node[0] != uuid->node[0] ||
            uuid_last.node[1] != uuid->node[1] ||
            uuid_last.node[2] != uuid->node[2])
-               uuid->seq = (uint16_t)arc4random() & 0x3fff;
+               uuid->seq = (uint16_t)cprng_fast32() & 0x3fff;
        else if (uuid_last.time.ll >= xtime)
                uuid->seq = (uuid_last.seq + 1) & 0x3fff;
        else
Index: sys/kern/subr_cprng.c
===================================================================
RCS file: sys/kern/subr_cprng.c
diff -N sys/kern/subr_cprng.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sys/kern/subr_cprng.c       21 Oct 2011 20:31:22 -0000
@@ -0,0 +1,178 @@
+/*     $NetBSD: $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Thor Lancelot Simon.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/kmem.h>
+#include <sys/mutex.h>
+#include <sys/rngtest.h>
+#include <sys/rnd.h>
+
+#include <machine/cpu_counter.h>
+
+#include <sys/cprng.h>
+
+void
+cprng_init(void)
+{
+       nist_ctr_initialize();
+}
+
+static inline uint32_t
+cprng_counter(void)
+{
+       struct timeval tv;
+
+#if defined(__HAVE_CPU_COUNTER)
+       if (cpu_hascounter())
+               return cpu_counter32();
+#endif
+       if (__predict_false(cold)) {
+               /* microtime unsafe if clock not running yet */
+               return 0;
+       }
+       return (tv.tv_sec * 1000000 + tv.tv_usec);
+}
+
+static void cprng_strong_reseed(void *arg)
+{
+       cprng_strong_t *c = arg;
+       uint8_t key[NIST_BLOCK_KEYLEN_BYTES];
+       uint32_t cc = cprng_counter();;
+
+       mutex_enter(&c->mtx);
+       if (c->reseed.len != sizeof(key)) {
+               panic("cprng_strong_reseed: bad entropy length %d "
+                     " (expected %d)", (int)c->reseed.len, (int)sizeof(key));
+       }
+       if (nist_ctr_drbg_reseed(&c->drbg, c->reseed.data, c->reseed.len,
+                                &cc, sizeof(cc))) {
+               panic("cprng %s: nist_ctr_drbg_reseed failed.", c->name);
+       }
+       c->reseed_pending = 0;
+       mutex_exit(&c->mtx);
+}
+
+cprng_strong_t *cprng_strong_create(const char *const name, int ipl)
+{
+       cprng_strong_t *c;
+       uint8_t key[NIST_BLOCK_KEYLEN_BYTES];
+       int r;
+       uint32_t cc;
+
+       c = kmem_alloc(sizeof(*c), KM_NOSLEEP);
+       if (c == NULL) {
+               return NULL;
+       }
+       strlcpy(c->name, name, sizeof(c->name));
+       c->reseed.cb = cprng_strong_reseed;
+       c->reseed.arg = c;
+       strlcpy(c->reseed.name, name, sizeof(c->reseed.name));
+
+       mutex_init(&c->mtx, MUTEX_DEFAULT, ipl);
+       mutex_enter(&c->mtx);
+       r = rnd_extract_data(key, sizeof(key), RND_EXTRACT_GOOD);
+       if (r != sizeof(key)) {
+               printf("cprng %s: WARNING insufficient "
+                      "entropy at creation.\n", name);
+               rnd_extract_data(key + r, sizeof(key - r), RND_EXTRACT_ANY);
+
+               /* Ask for more. */
+               c->reseed.len = sizeof(key);
+               rndsink_attach(&c->reseed);
+       }
+               
+       if (nist_ctr_drbg_instantiate(&c->drbg, key, sizeof(key),
+                                     &cc, sizeof(cc), name, strlen(name))) {
+               panic("cprng %s: instantiation failed.", name);
+       }
+       mutex_exit(&c->mtx);
+       return c;
+}
+
+
+size_t cprng_strong(cprng_strong_t *c, void *p, size_t len)
+{
+       uint32_t cc = cprng_counter();
+
+       mutex_enter(&c->mtx);
+
+       if (nist_ctr_drbg_generate(&c->drbg, p, len, &cc, sizeof(cc))) {
+               panic("cprng %s: nist_ctr_drbg_generate failed!", c->name);
+       }
+
+       /*
+        * If the generator has just been keyed, perform
+        * the statistical RNG test.
+        */
+       if (__predict_false(c->drbg.reseed_counter = 1)) {
+               rngtest_t rt;
+
+               if (nist_ctr_drbg_generate(&c->drbg, rt.rt_b,
+                   sizeof(rt.rt_b), NULL, 0)) {
+                       panic("cprng %s: nist_ctr_drbg_generate failed!",
+                             c->name);
+               }
+               if (rngtest(&rt)) {
+                       panic("cprng %s: failed statistical RNG test.",
+                             c->name);
+               }
+
+               memset(&rt, 0, sizeof(rt));
+       }
+
+       if (__predict_false(c->drbg.reseed_counter >
+                           (NIST_CTR_DRBG_RESEED_INTERVAL / 2))) {
+               if (!(c->reseed_pending)) {
+                       c->reseed.len = NIST_BLOCK_KEYLEN_BYTES;
+                       rndsink_attach(&c->reseed);
+               }
+       }
+
+       mutex_exit(&c->mtx);
+       return len;
+}
+
+void cprng_strong_destroy(cprng_strong_t *c)
+{
+       mutex_enter(&c->mtx);
+       if (c->reseed_pending) {
+               rndsink_detach(&c->reseed);
+       }
+       mutex_exit(&c->mtx);
+       mutex_destroy(&c->mtx);
+       nist_ctr_drbg_destroy(&c->drbg);
+       memset(c, 0, sizeof(*c));
+       kmem_free(c, sizeof(*c));
+}
Index: sys/kern/subr_rngtest.c
===================================================================
RCS file: sys/kern/subr_rngtest.c
diff -N sys/kern/subr_rngtest.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sys/kern/subr_rngtest.c     21 Oct 2011 20:31:22 -0000
@@ -0,0 +1,269 @@
+/*     $NetBSD: $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Thor Lancelot Simon.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* fips140.c   1.5 (Qualcomm) 02/09/02 */
+/*
+This software is free for commercial and non-commercial use
+subject to the following conditions.
+
+Copyright remains vested in QUALCOMM Incorporated, and Copyright
+notices in the code are not to be removed.  If this package is used in
+a product, QUALCOMM should be given attribution as the author this
+software.  This can be in the form of a textual message at program
+startup or in documentation (online or textual) provided with the
+package.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the copyright notice,
+   this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the
+   distribution.
+
+3. All advertising materials mentioning features or use of this
+   software must display the following acknowledgement:  This product
+   includes software developed by QUALCOMM Incorporated.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+The license and distribution terms for any publically available version
+or derivative of this code cannot be changed, that is, this code cannot
+simply be copied and put under another distribution license including
+the GNU Public License.
+*/
+
+/* Run FIPS 140 statistical tests on a file */
+
+/* written by Greg Rose, Copyright C 2000 QUALCOMM Incorporated */
+
+/*
+ * Modified for in-kernel use (API adjustments, conversion from
+ * floating to fixed-point chi-sq computation) by Thor Lancelot
+ * Simon.
+ *
+ * A comment on appropriate use of this test and the infamous FIPS 140
+ * "continuous output test" (COT):  Both tests are very appropriate for
+ * software interfaces to hardware implementations, and will quickly tell
+ * you if any number of very bad things have happened to your RNG: perhaps
+ * it has come disconnected from the rest of the system, somehow, and you
+ * are getting only unconditioned bus noise (read: clock edges from the
+ * loudest thing in your system).  Perhaps it has ceased to latch a shift
+ * register and is feeding you the same data over and over again.  Perhaps
+ * it is not really random at all but was sold to you as such.  Perhaps it
+ * is not actually *there* (Intel chipset RNG anyone?) but claims to be,
+ * and is feeding you 01010101 on every register read.
+ *
+ * However, when applied to software RNGs, the situation is quite different.
+ * Most software RNGs use a modern hash function or cipher as an output
+ * stage.  The resulting bitstream assuredly *should* pass both the
+ * "continuous output" (no two consecutive samples identical) and
+ * statistical tests: if it does not, the cryptographic primitive or its
+ * implementation is terribly broken.
+ *
+ * There is still value to this test: it will tell you if you inadvertently
+ * terribly break your implementation of the software RNG.  Which is a thing
+ * that has in fact happened from time to time, even to the careful (or
+ * paranoid).  But it will not tell you if there is a problem with the
+ * _input_ to that final cryptographic primitive -- the bits that are hashed
+ * or the key to the cipher -- and if an adversary can find one, you're
+ * still toast.
+ *
+ * The situation is -- sadly -- similar with hardware RNGs that are
+ * certified to one of the standards such as X9.31 or SP800-90.  In these
+ * cases the hardware vendor has hidden the actual random bitstream behind
+ * a hardware cipher/hash implementation that should, indeed, produce good
+ * quality random numbers that pass will pass this test -- whether the
+ * underlying bitstream is trustworthy or not.
+ *
+ * However, this test (and the COT) will still probably tell you if the
+ * thing fell off the bus, etc.  Which is a thing that has in fact
+ * happened from time to time, even to the fully certified...
+ *
+ * This module does not (yet?) implement the Continuous Output Test.  When
+ * I call that test "infamous", it's because it obviously reduces the
+ * backtracking resistance of any implementation that includes it -- the
+ * implementation has to store the entire previous RNG output in order to
+ * perform the required comparison; not just periodically but all the time
+ * when operating at all.  Nonetheless, it has obvious value for
+ * hardware implementations where it will quickly and surely detect a
+ * severe failure; but as of this writing several of the latest comments
+ * on SP800-90 recommend removing any requirement for the COT and my
+ * personal tendency is to agree.  It's easy to add if you really need it.
+ * 
+ */
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/rngtest.h>
+
+int    bitnum = 0;
+
+const int minrun[7] = { 0, 2315, 1114, 527, 240, 103, 103 };
+const int maxrun[7] = { 0, 2685, 1386, 723, 384, 209, 209 };
+#define LONGRUN        26
+#define MINONES 9725
+#define MAXONES 10275
+#define MINPOKE 2.16
+#define MAXPOKE 46.17
+#define PRECISION 100000
+
+const int longrun = LONGRUN;
+const int minones = MINONES;
+const int maxones = MAXONES;
+const long long minpoke = (MINPOKE * PRECISION);
+const long long maxpoke = (MAXPOKE * PRECISION);
+
+/* Population count of 1's in a byte */
+const unsigned char Popcount[] = {
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+};
+
+/* end of run */
+static void
+endrun(rngtest_t *const rc, const int last, int run)
+{
+    if (run >= longrun) {
+       printf("Kernel RNG \"%s\" long run test FAILURE: "
+              "Run of %d %ds found\n", rc->rt_name, run, last);
+       ++rc->rt_nerrs;
+    }
+    if (run > 6)
+       run = 6;
+    ++rc->rt_runs[last][run];
+}
+
+int
+rngtest(rngtest_t *const rc)
+{
+    int                i;
+    uint8_t *  p;
+    int                c;
+    long long  X;
+    int                last;
+    int                run;
+
+    /* Enforce sanity for most members of the context */
+    memset(rc->rt_poker, 0, sizeof(rc->rt_poker));
+    memset(rc->rt_runs, 0, sizeof(rc->rt_runs));
+    rc->rt_nerrs = 0;
+    rc->rt_name[sizeof(rc->rt_name) - 1] = '\0';
+
+    /* monobit test */
+    for (p = rc->rt_b, c = 0; p < &rc->rt_b[sizeof rc->rt_b]; ++p)
+       c += Popcount[*p];
+    if (c <= minones || maxones <= c) {
+       printf("Kernel RNG \"%s\" monobit test FAILURE: %d ones\n",
+              rc->rt_name,  c);
+       ++rc->rt_nerrs;
+    }
+    
+    /* poker test */
+    for (p = rc->rt_b; p < &rc->rt_b[sizeof rc->rt_b]; ++p) {
+       ++rc->rt_poker[*p & 0xF];
+       ++rc->rt_poker[(*p >> 4) & 0xF];
+    }
+    for (X = i = 0; i < 16; ++i) {
+       X += rc->rt_poker[i] * rc->rt_poker[i];
+    }
+    X *= PRECISION;
+    X = 16 * X / 5000 - 5000 * PRECISION;
+    if (X <= minpoke || maxpoke <= X) {
+       printf("Kernel RNG \"%s\" poker test failure: "
+              "parameter X = %lld.%lld\n", rc->rt_name,
+               (X / PRECISION), (X % PRECISION));
+       ++rc->rt_nerrs;
+    }
+
+    /* runs test */
+    last = (rc->rt_b[0] >> 7) & 1;
+    run = 0;
+    for (p = rc->rt_b; p < &rc->rt_b[sizeof rc->rt_b]; ++p) {
+       c = *p;
+       for (i = 7; i >= 0; --i) {
+           if (((c >> i) & 1) != last) {
+               endrun(rc, last, run);
+               run = 0;
+               last = (c >> i) & 1;
+           }
+           ++run;
+       }
+    }
+    endrun(rc, last, run);
+
+    for (run = 1; run <= 6; ++run) {
+       for (last = 0; last <= 1; ++last) {
+           if (rc->rt_runs[last][run] <= minrun[run]) {
+               printf("Kernel RNG \"%s\" runs test FAILURE: "
+                   "too few runs of %d %ds (%d < %d)\n", rc->rt_name,
+                   run, last, rc->rt_runs[last][run], minrun[run]);
+               ++rc->rt_nerrs;
+           }
+           else if (rc->rt_runs[last][run] >= maxrun[run]) {
+               printf("Kernel RNG \"%s\" runs test FAILURE: "
+                      "too many runs of %d %ds (%d > %d)\n", rc->rt_name,
+                      run, last, rc->rt_runs[last][run], maxrun[run]);
+               ++rc->rt_nerrs;
+           }
+       }
+    }
+    memset(rc->rt_b, 0, sizeof(rc->rt_b));
+    return rc->rt_nerrs;
+}
Index: sys/lib/libkern/arc4random.c
===================================================================
RCS file: /cvsroot/src/sys/lib/libkern/arc4random.c,v
retrieving revision 1.21
diff -u -b -r1.21 arc4random.c
--- sys/lib/libkern/arc4random.c        18 Jan 2010 20:54:54 -0000      1.21
+++ sys/lib/libkern/arc4random.c        21 Oct 2011 20:31:22 -0000
@@ -1,7 +1,7 @@
 /*     $NetBSD: arc4random.c,v 1.21 2010/01/18 20:54:54 joerg Exp $    */
 
 /*-
- * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * Copyright (c) 2002, 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -57,15 +57,42 @@
 #endif
 #include <sys/systm.h>
 
+#ifdef _KERNEL
+#include <sys/mutex.h>
+#include <sys/rngtest.h>
+#else
+#define mutex_spin_enter(x) ;
+#define mutex_spin_exit(x) ;
+#define mutex_init(x, y, z) ;
+#endif
+
 #include <lib/libkern/libkern.h>
 
 #if NRND > 0
 #include <sys/rnd.h>
+
+rndsink_t      rs;
+
 #endif
 
-#define        ARC4_MAXRUNS 16384
+/*
+ * The best known attack that distinguishes RC4 output from a random
+ * bitstream requires 2^25 bytes.  (see Paul and Preneel, Analysis of
+ * Non-fortuitous Predictive States of the RC4 Keystream Generator.
+ * INDOCRYPT 2003, pp52 – 67).
+ *
+ * However, we discard the first 1024 bytes of output, avoiding the
+ * biases detected in this paper.  The best current attack that
+ * can distinguish this "RC4[drop]" output seems to be Fleuhrer &
+ * McGrew's attack which requires 2^30.6 bytes of output:
+ * Fluhrer and McGrew, Statistical Analysis of the Alleged RC4
+ * Keystream Generator. FSE 2000, pp19 – 30
+ *
+ * We rekey at 2^24 bytes.
+ */
+#define        ARC4_MAXBYTES           (16 * 1024 * 1024)
 #define        ARC4_RESEED_SECONDS 300
-#define        ARC4_KEYBYTES 32 /* 256 bit key */
+#define        ARC4_KEYBYTES           16 /* 128 bit key */
 
 #ifdef _STANDALONE
 #define        time_uptime     1       /* XXX ugly! */
@@ -73,11 +100,17 @@
 
 static u_int8_t arc4_i, arc4_j;
 static int arc4_initialized = 0;
-static int arc4_numruns = 0;
+static int arc4_numbytes = 0;
 static u_int8_t arc4_sbox[256];
 static time_t arc4_nextreseed;
 
+#ifdef _KERNEL
+kmutex_t       arc4_mtx;
+#endif
+
 static inline u_int8_t arc4_randbyte(void);
+static inline void arc4randbytes_unlocked(void *, size_t);
+
 
 static inline void
 arc4_swap(u_int8_t *a, u_int8_t *b)
@@ -93,55 +126,70 @@
  * Stir our S-box.
  */
 static void
-arc4_randrekey(void)
+arc4_randrekey(void *arg)
 {
        u_int8_t key[256];
-       static int cur_keybytes;
-       int n, byteswanted;
+       int n, ask_for_more = 0;
+#ifdef _KERNEL
+       rngtest_t rt;
+#endif
 #if NRND > 0
+       static int callback_pending;
        int r;
 #endif
 
-       if(!arc4_initialized)
-               /* The first time through, we must take what we can get */
-               byteswanted = 0;
-       else
-               /* Don't rekey with less entropy than we already have */
-               byteswanted = cur_keybytes;
-
+       mutex_spin_enter(&arc4_mtx);
 #if NRND > 0   /* XXX without rnd, we will key from the stack, ouch! */
-       r = rnd_extract_data(key, ARC4_KEYBYTES, RND_EXTRACT_GOOD);
+       if (!arc4_initialized) {
+               KASSERT(arg == NULL);
+               /*
+                * The first time through, we must take what we can get,
+                * so schedule ourselves for callback no matter what.
+                */
+               r = rnd_extract_data(key, ARC4_KEYBYTES, RND_EXTRACT_ANY);
+               ask_for_more = 1;
+               goto got_entropy;
+       }
 
+       KASSERT(arg == NULL || (arg == &rs && callback_pending == 1));
+       if (arg == NULL) {
+               r = rnd_extract_data(key, ARC4_KEYBYTES, RND_EXTRACT_GOOD);
        if (r < ARC4_KEYBYTES) {
-               if (r >= byteswanted) {
-                       (void)rnd_extract_data(key + r,
-                                              ARC4_KEYBYTES - r,
-                                              RND_EXTRACT_ANY);
+                       ask_for_more = 1;
+               }
                } else {
-                       /* don't replace a good key with a bad one! */
-                       arc4_nextreseed = time_uptime + ARC4_RESEED_SECONDS;
-                       arc4_numruns = 0;
-                       /* we should just ask rnd(4) to rekey us when
-                          it can, but for now, we'll just try later. */
-                       return;
+               callback_pending = 0;
+               ask_for_more = 0;
+               if (rs.len != ARC4_KEYBYTES) {
+                       panic("arc4_randrekey: rekey callback bad length");
                }
+               memcpy(key, rs.data, rs.len);
        }
 
-       cur_keybytes = r;
-
+got_entropy:
+       if (ask_for_more) {
+               KASSERT(!callback_pending);
+               callback_pending = 1;
+               strlcpy(rs.name, "arc4random", sizeof(rs.name));
+               rs.cb = arc4_randrekey;
+               rs.arg = &rs;
+               rs.len = ARC4_KEYBYTES;
+               rndsink_attach(&rs);
+       }
+#endif
+       /*
+        * If it's the first time, or we got a good key, actually rekey.
+        */
+       if (!ask_for_more || !arc4_initialized) {
        for (n = ARC4_KEYBYTES; n < sizeof(key); n++)
                        key[n] = key[n % ARC4_KEYBYTES];
-#endif
+
        for (n = 0; n < 256; n++) {
                arc4_j = (arc4_j + arc4_sbox[n] + key[n]) % 256;
                arc4_swap(&arc4_sbox[n], &arc4_sbox[arc4_j]);
        }
        arc4_i = arc4_j;
 
-       /* Reset for next reseed cycle. */
-       arc4_nextreseed = time_uptime + ARC4_RESEED_SECONDS;
-       arc4_numruns = 0;
-
        /*
         * Throw away the first N words of output, as suggested in the
         * paper "Weaknesses in the Key Scheduling Algorithm of RC4"
@@ -149,6 +197,26 @@
         */
        for (n = 0; n < 256 * 4; n++)
                arc4_randbyte();
+
+               /* Reset for next reseed cycle. */
+               arc4_nextreseed = time_uptime + ARC4_RESEED_SECONDS;
+               arc4_numbytes = 0;
+#ifdef _KERNEL
+               /*
+                * Perform the FIPS 140-2 statistical RNG test; warn if our
+                * output has such poor quality as to fail the test.
+                */
+               arc4randbytes_unlocked(rt.rt_b, sizeof(rt.rt_b));
+               strlcpy(rt.rt_name, "arc4random", sizeof(rt.rt_name));
+               if (rngtest(&rt)) {
+                       /* rngtest will scream to the console. */
+                       arc4_nextreseed = time_uptime;
+                       arc4_numbytes = ARC4_MAXBYTES;
+                       /* XXX should keep old context around, *NOT* use new */
+               }
+#endif
+       }
+       mutex_spin_exit(&arc4_mtx);
 }
 
 /*
@@ -159,11 +227,12 @@
 {
        int n;
 
+       mutex_init(&arc4_mtx, MUTEX_DEFAULT, IPL_VM);
        arc4_i = arc4_j = 0;
        for (n = 0; n < 256; n++)
                arc4_sbox[n] = (u_int8_t) n;
 
-       arc4_randrekey();
+       arc4_randrekey(NULL);
        arc4_initialized = 1;
 }
 
@@ -187,40 +256,40 @@
 u_int32_t
 arc4random(void)
 {
-       u_int32_t ret;
-       int i;
+    int ret;
+    u_int8_t *retc;
 
-       /* Initialize array if needed. */
-       if (!arc4_initialized)
-               arc4_init();
+    retc = (u_int8_t *)&ret;
 
-       if ((++arc4_numruns > ARC4_MAXRUNS) ||
-           (time_uptime > arc4_nextreseed)) {
-               arc4_randrekey();
-       }
+    arc4randbytes(retc, sizeof(u_int32_t));
+    return ret;
+}
+
+static inline void
+arc4randbytes_unlocked(void *p, size_t len)
+{
+       u_int8_t *buf = (u_int8_t *)p;
+       size_t i;
 
-       for (i = 0, ret = 0; i <= 24; ret |= arc4_randbyte() << i, i += 8)
+       for (i = 0; i < len; buf[i] = arc4_randbyte(), i++)
                continue;
-       return ret;
 }
 
 void
 arc4randbytes(void *p, size_t len)
 {
-       u_int8_t *buf;
-       size_t i;
-
        /* Initialize array if needed. */
-       if (!arc4_initialized)
+       if (!arc4_initialized) {
                arc4_init();
-
-       buf = (u_int8_t *)p;
-
-       for (i = 0; i < len; buf[i] = arc4_randbyte(), i++)
-               continue;
-       arc4_numruns += len / sizeof(u_int32_t);
-       if ((arc4_numruns > ARC4_MAXRUNS) ||
+                /* avoid conditionalizing locking */
+               return arc4randbytes_unlocked(p, len);
+       }
+       mutex_spin_enter(&arc4_mtx);
+       arc4randbytes_unlocked(p, len);
+       arc4_numbytes += len;
+       mutex_spin_exit(&arc4_mtx);
+       if ((arc4_numbytes > ARC4_MAXBYTES) ||
            (time_uptime > arc4_nextreseed)) {
-               arc4_randrekey();
+               arc4_randrekey(NULL);
        }
 }
Index: sys/net/if_bridge.c
===================================================================
RCS file: /cvsroot/src/sys/net/if_bridge.c,v
retrieving revision 1.73
diff -u -b -r1.73 if_bridge.c
--- sys/net/if_bridge.c 23 May 2011 21:52:54 -0000      1.73
+++ sys/net/if_bridge.c 21 Oct 2011 20:31:22 -0000
@@ -100,6 +100,7 @@
 #include <sys/pool.h>
 #include <sys/kauth.h>
 #include <sys/cpu.h>
+#include <sys/cprng.h>
 
 #include <net/bpf.h>
 #include <net/if.h>
@@ -1848,7 +1849,7 @@
        for (i = 0; i < BRIDGE_RTHASH_SIZE; i++)
                LIST_INIT(&sc->sc_rthash[i]);
 
-       sc->sc_rthash_key = arc4random();
+       sc->sc_rthash_key = cprng_fast32();
 
        LIST_INIT(&sc->sc_rtlist);
 
Index: sys/net/if_spppsubr.c
===================================================================
RCS file: /cvsroot/src/sys/net/if_spppsubr.c,v
retrieving revision 1.122
diff -u -b -r1.122 if_spppsubr.c
--- sys/net/if_spppsubr.c       5 Sep 2011 12:19:09 -0000       1.122
+++ sys/net/if_spppsubr.c       21 Oct 2011 20:31:23 -0000
@@ -66,6 +66,7 @@
 #include <sys/md5.h>
 #include <sys/inttypes.h>
 #include <sys/kauth.h>
+#include <sys/cprng.h>
 
 #include <net/if.h>
 #include <net/netisr.h>
@@ -1203,7 +1204,7 @@
                        ++sp->pp_loopcnt;
 
                        /* Generate new local sequence number */
-                       sp->pp_seq[IDX_LCP] = arc4random();
+                       sp->pp_seq[IDX_LCP] = cprng_fast32();
                        break;
                }
                sp->pp_loopcnt = 0;
@@ -2482,7 +2483,7 @@
                                if (magic == ~sp->lcp.magic) {
                                        if (debug)
                                                addlog(" magic glitch");
-                                       sp->lcp.magic = arc4random();
+                                       sp->lcp.magic = cprng_fast32();
                                } else {
                                        sp->lcp.magic = magic;
                                        if (debug)
@@ -2666,7 +2667,7 @@
 
        if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) {
                if (! sp->lcp.magic)
-                       sp->lcp.magic = arc4random();
+                       sp->lcp.magic = cprng_fast32();
                opt[i++] = LCP_OPT_MAGIC;
                opt[i++] = 6;
                opt[i++] = sp->lcp.magic >> 24;
@@ -4230,7 +4231,7 @@
                 * Compute the re-challenge timeout.  This will yield
                 * a number between 300 and 810 seconds.
                 */
-               i = 300 + ((unsigned)(arc4random() & 0xff00) >> 7);
+               i = 300 + ((unsigned)(cprng_fast32() & 0xff00) >> 7);
 
                callout_reset(&sp->ch[IDX_CHAP], i * hz, chap.TO, sp);
        }
@@ -4287,7 +4288,7 @@
 sppp_chap_scr(struct sppp *sp)
 {
        uint32_t *ch;
-       u_char clen;
+       u_char clen = 4 * sizeof(uint32_t);
 
        if (sp->myauth.name == NULL) {
            /* can't do anything useful */
@@ -4298,11 +4299,7 @@
 
        /* Compute random challenge. */
        ch = (uint32_t *)sp->myauth.challenge;
-       ch[0] = arc4random();
-       ch[1] = arc4random();
-       ch[2] = arc4random();
-       ch[3] = arc4random();
-       clen = 16;      /* 4 * sizeof(uint32_t) */
+       cprng_strong(kern_cprng, ch, clen);
 
        sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP];
 
Index: sys/net/npf/npf_nat.c
===================================================================
RCS file: /cvsroot/src/sys/net/npf/npf_nat.c,v
retrieving revision 1.6
diff -u -b -r1.6 npf_nat.c
--- sys/net/npf/npf_nat.c       2 Feb 2011 02:20:25 -0000       1.6
+++ sys/net/npf/npf_nat.c       21 Oct 2011 20:31:23 -0000
@@ -87,6 +87,8 @@
 #include <sys/kmem.h>
 #include <sys/mutex.h>
 #include <sys/pool.h>
+#include <sys/cprng.h>
+
 #include <net/pfil.h>
 #include <netinet/in.h>
 
@@ -319,7 +321,7 @@
        u_int n = PORTMAP_SIZE, idx, bit;
        uint32_t map, nmap;
 
-       idx = arc4random() % PORTMAP_SIZE;
+       idx = cprng_fast32() % PORTMAP_SIZE;
        for (;;) {
                KASSERT(idx < PORTMAP_SIZE);
                map = pm->p_bitmap[idx];
Index: sys/net80211/ieee80211_netbsd.c
===================================================================
RCS file: /cvsroot/src/sys/net80211/ieee80211_netbsd.c,v
retrieving revision 1.19
diff -u -b -r1.19 ieee80211_netbsd.c
--- sys/net80211/ieee80211_netbsd.c     7 Oct 2011 16:51:45 -0000       1.19
+++ sys/net80211/ieee80211_netbsd.c     21 Oct 2011 20:31:23 -0000
@@ -46,6 +46,8 @@
 
 #include <sys/socket.h>
 
+#include <sys/cprng.h>
+
 #include <net/if.h>
 #include <net/if_media.h>
 #include <net/if_ether.h>
@@ -640,14 +642,7 @@
 void
 get_random_bytes(void *p, size_t n)
 {
-       u_int8_t *dp = p;
-
-       while (n > 0) {
-               u_int32_t v = arc4random();
-               size_t nb = n > sizeof(u_int32_t) ? sizeof(u_int32_t) : n;
-               (void)memcpy(dp, &v, nb);
-               dp += sizeof(u_int32_t), n -= nb;
-       }
+       cprng_fast(p, n);
 }
 
 void
Index: sys/netinet/in.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/in.c,v
retrieving revision 1.139
diff -u -b -r1.139 in.c
--- sys/netinet/in.c    19 Oct 2011 01:52:22 -0000      1.139
+++ sys/netinet/in.c    21 Oct 2011 20:31:23 -0000
@@ -110,6 +110,8 @@
 #include <sys/syslog.h>
 #include <sys/kauth.h>
 
+#include <sys/cprng.h>
+
 #include <net/if.h>
 #include <net/route.h>
 
@@ -403,7 +405,7 @@
                                ia->ia_broadaddr.sin_family = AF_INET;
                        }
                        ia->ia_ifp = ifp;
-                       ia->ia_idsalt = arc4random() % 65535;
+                       ia->ia_idsalt = cprng_fast32() % 65535;
                        LIST_INIT(&ia->ia_multiaddrs);
                        newifaddr = 1;
                }
Index: sys/netinet/ip_carp.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_carp.c,v
retrieving revision 1.46
diff -u -b -r1.46 ip_carp.c
--- sys/netinet/ip_carp.c       19 Oct 2011 01:52:22 -0000      1.46
+++ sys/netinet/ip_carp.c       21 Oct 2011 20:31:23 -0000
@@ -55,6 +55,7 @@
 #include <sys/ucred.h>
 #include <sys/syslog.h>
 #include <sys/acct.h>
+#include <sys/cprng.h>
 
 #include <sys/cpu.h>
 
@@ -877,9 +878,7 @@
 {
        if (sc->sc_init_counter) {
                /* this could also be seconds since unix epoch */
-               sc->sc_counter = arc4random();
-               sc->sc_counter = sc->sc_counter << 32;
-               sc->sc_counter += arc4random();
+               sc->sc_counter = cprng_fast64();
        } else
                sc->sc_counter++;
 
Index: sys/netinet/ip_id.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_id.c,v
retrieving revision 1.14
diff -u -b -r1.14 ip_id.c
--- sys/netinet/ip_id.c 5 Nov 2010 01:35:57 -0000       1.14
+++ sys/netinet/ip_id.c 21 Oct 2011 20:31:24 -0000
@@ -35,6 +35,7 @@
 #include <sys/param.h>
 #include <sys/kmem.h>
 #include <sys/mutex.h>
+#include <sys/cprng.h>
 
 #include <net/if.h>
 #include <netinet/in.h>
@@ -54,7 +55,7 @@
 static inline uint32_t
 ipid_random(void)
 {
-       return arc4random();
+       return cprng_fast32();
 }
 
 /*
Index: sys/netinet/rfc6056.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/rfc6056.c,v
retrieving revision 1.3
diff -u -b -r1.3 rfc6056.c
--- sys/netinet/rfc6056.c       25 Sep 2011 11:54:28 -0000      1.3
+++ sys/netinet/rfc6056.c       21 Oct 2011 20:31:24 -0000
@@ -39,6 +39,7 @@
 #include <sys/uidinfo.h>
 #include <sys/domain.h>
 #include <sys/md5.h>
+#include <sys/cprng.h>
 
 #include <net/if.h>
 #include <net/route.h>
@@ -427,7 +428,7 @@
 
        DPRINTF("num_ephemeral: %u\n", num_ephemeral);
 
-       *next_ephemeral = mymin + (arc4random() % num_ephemeral);
+       *next_ephemeral = mymin + (cprng_fast32() % num_ephemeral);
 
        DPRINTF("next_ephemeral initially: %u\n", *next_ephemeral);
 
@@ -480,7 +481,7 @@
        num_ephemeral = mymax - mymin + 1;
 
        DPRINTF("num_ephemeral: %u\n", num_ephemeral);
-       *next_ephemeral = mymin + (arc4random() % num_ephemeral);
+       *next_ephemeral = mymin + (cprng_fast32() % num_ephemeral);
 
        DPRINTF("next_ephemeral initially: %u\n", *next_ephemeral);
 
@@ -493,7 +494,7 @@
                        return 0;
                }
                *next_ephemeral = mymin +
-                   (arc4random() % num_ephemeral);
+                   (cprng_fast32() % num_ephemeral);
 
                count--;
 
@@ -516,10 +517,7 @@
        uint32_t offset;
        uint16_t soffset[2];
 
-       secret_f[0] = arc4random();
-       secret_f[1] = arc4random();
-       secret_f[2] = arc4random();
-       secret_f[3] = arc4random();
+       cprng_fast(secret_f, sizeof(secret_f));
 
        MD5Init(&f_ctx);
        switch (inp_hdr->inph_af) {
@@ -732,7 +730,7 @@
                return error;
 
        if (*next_ephemeral == 0)
-               *next_ephemeral = arc4random() & 0xffff;
+               *next_ephemeral = cprng_fast32() & 0xffff;
 
        /* Ephemeral port selection function */
        num_ephemeral = mymax - mymin + 1;
@@ -740,7 +738,7 @@
        count = num_ephemeral;
        do {
                *next_ephemeral = *next_ephemeral +
-                   (arc4random() % N) + 1;
+                   (cprng_fast32() % N) + 1;
                myport = mymin +
                    (*next_ephemeral % num_ephemeral);
 
Index: sys/netinet/tcp_input.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_input.c,v
retrieving revision 1.316
diff -u -b -r1.316 tcp_input.c
--- sys/netinet/tcp_input.c     31 Aug 2011 18:31:03 -0000      1.316
+++ sys/netinet/tcp_input.c     21 Oct 2011 20:31:24 -0000
@@ -171,6 +171,7 @@
 #include <sys/md5.h>
 #endif
 #include <sys/lwp.h> /* for lwp0 */
+#include <sys/cprng.h>
 
 #include <net/if.h>
 #include <net/route.h>
@@ -3711,8 +3712,8 @@
         * the hash secrets.
         */
        if (syn_cache_count == 0) {
-               syn_hash1 = arc4random();
-               syn_hash2 = arc4random();
+               syn_hash1 = cprng_fast32();
+               syn_hash2 = cprng_fast32();
        }
 
        SYN_HASHALL(sc->sc_hash, &sc->sc_src.sa, &sc->sc_dst.sa);
Index: sys/netinet/tcp_subr.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_subr.c,v
retrieving revision 1.241
diff -u -b -r1.241 tcp_subr.c
--- sys/netinet/tcp_subr.c      3 May 2011 18:28:45 -0000       1.241
+++ sys/netinet/tcp_subr.c      21 Oct 2011 20:31:25 -0000
@@ -98,7 +98,6 @@
 #include "opt_tcp_compat_42.h"
 #include "opt_inet_csum.h"
 #include "opt_mbuftrace.h"
-#include "rnd.h"
 
 #include <sys/param.h>
 #include <sys/proc.h>
@@ -111,10 +110,8 @@
 #include <sys/errno.h>
 #include <sys/kernel.h>
 #include <sys/pool.h>
-#if NRND > 0
 #include <sys/md5.h>
-#include <sys/rnd.h>
-#endif
+#include <sys/cprng.h>
 
 #include <net/route.h>
 #include <net/if.h>
@@ -174,9 +171,7 @@
 int    tcp_minmss = TCP_MINMSS;
 int    tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
 int    tcp_do_rfc1323 = 1;     /* window scaling / timestamps (obsolete) */
-#if NRND > 0
 int    tcp_do_rfc1948 = 0;     /* ISS by cryptographic hash */
-#endif
 int    tcp_do_sack = 1;        /* selective acknowledgement */
 int    tcp_do_win_scale = 1;   /* RFC1323 window scaling */
 int    tcp_do_timestamps = 1;  /* RFC1323 timestamps */
@@ -2178,9 +2173,7 @@
 }
 
 tcp_seq         tcp_iss_seq = 0;       /* tcp initial seq # */
-#if NRND > 0
 u_int8_t tcp_iss_secret[16];   /* 128 bits; should be plenty */
-#endif
 
 /*
  * Get a new sequence value given a tcp control block
@@ -2218,7 +2211,6 @@
 {
        tcp_seq tcp_iss;
 
-#if NRND > 0
        static bool tcp_iss_gotten_secret;
 
        /*
@@ -2226,8 +2218,8 @@
         * hash secret.
         */
        if (tcp_iss_gotten_secret == false) {
-               rnd_extract_data(tcp_iss_secret, sizeof(tcp_iss_secret),
-                   RND_EXTRACT_ANY);
+               cprng_strong(kern_cprng,
+                            tcp_iss_secret, sizeof(tcp_iss_secret));
                tcp_iss_gotten_secret = true;
        }
 
@@ -2268,17 +2260,11 @@
 #ifdef TCPISS_DEBUG
                printf("new ISS 0x%08x\n", tcp_iss);
 #endif
-       } else
-#endif /* NRND > 0 */
-       {
+       } else {
                /*
                 * Randomize.
                 */
-#if NRND > 0
-               rnd_extract_data(&tcp_iss, sizeof(tcp_iss), RND_EXTRACT_ANY);
-#else
-               tcp_iss = arc4random();
-#endif
+               tcp_iss = cprng_fast32();
 
                /*
                 * If we were asked to add some amount to a known value,
Index: sys/netinet6/files.ipsec
===================================================================
RCS file: /cvsroot/src/sys/netinet6/files.ipsec,v
retrieving revision 1.5
diff -u -b -r1.5 files.ipsec
--- sys/netinet6/files.ipsec    27 Oct 2006 21:20:48 -0000      1.5
+++ sys/netinet6/files.ipsec    21 Oct 2011 20:31:25 -0000
@@ -1,7 +1,7 @@
 #      $NetBSD: files.ipsec,v 1.5 2006/10/27 21:20:48 christos Exp $
 
-defflag opt_ipsec.h            IPSEC: rijndael
-defflag opt_ipsec.h            IPSEC_ESP: des, blowfish, cast128, rijndael
+defflag opt_ipsec.h            IPSEC
+defflag opt_ipsec.h            IPSEC_ESP: des, blowfish, cast128
 defflag opt_ipsec.h            IPSEC_NAT_T
 
 file   netinet6/ah_aesxcbcmac.c        ipsec
Index: sys/netinet6/in6.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/in6.c,v
retrieving revision 1.158
diff -u -b -r1.158 in6.c
--- sys/netinet6/in6.c  19 Oct 2011 01:53:07 -0000      1.158
+++ sys/netinet6/in6.c  21 Oct 2011 20:31:25 -0000
@@ -81,6 +81,7 @@
 #include <sys/kernel.h>
 #include <sys/syslog.h>
 #include <sys/kauth.h>
+#include <sys/cprng.h>
 
 #include <net/if.h>
 #include <net/if_types.h>
@@ -1119,7 +1120,7 @@
                         * avoid report collision.
                         * [draft-ietf-ipv6-rfc2462bis-02.txt]
                         */
-                       dad_delay = arc4random() %
+                       dad_delay = cprng_fast32() %
                            (MAX_RTR_SOLICITATION_DELAY * hz);
                }
 
@@ -1210,7 +1211,7 @@
                         * The spec doesn't say anything about delay for this
                         * group, but the same logic should apply.
                         */
-                       dad_delay = arc4random() %
+                       dad_delay = cprng_fast32() %
                            (MAX_RTR_SOLICITATION_DELAY * hz);
                }
                if (in6_nigroup(ifp, hostname, hostnamelen, &mltaddr) != 0)
@@ -1318,7 +1319,7 @@
                                dad_delay = 0;
                        else {
                                dad_delay =
-                                   (arc4random() % (maxdelay - mindelay)) +
+                                   (cprng_fast32() % (maxdelay - mindelay)) +
                                    mindelay;
                        }
                }
@@ -2157,7 +2158,8 @@
                         * case, but we impose delays just in case.
                         */
                        nd6_dad_start(ifa,
-                           arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz));
+                           cprng_fast32() %
+                               (MAX_RTR_SOLICITATION_DELAY * hz));
                }
        }
 
Index: sys/netinet6/in6_ifattach.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/in6_ifattach.c,v
retrieving revision 1.85
diff -u -b -r1.85 in6_ifattach.c
--- sys/netinet6/in6_ifattach.c 19 Sep 2009 13:11:02 -0000      1.85
+++ sys/netinet6/in6_ifattach.c 21 Oct 2011 20:31:25 -0000
@@ -43,6 +43,7 @@
 #include <sys/syslog.h>
 #include <sys/md5.h>
 #include <sys/socketvar.h>
+#include <sys/cprng.h>
 
 #include <net/if.h>
 #include <net/if_dl.h>
@@ -194,7 +195,7 @@
                int i;
 
                for (i = 0; i < 2; i++) {
-                       val32 = arc4random();
+                       val32 = cprng_fast32();
                        memcpy(seed + sizeof(val32) * i, &val32, sizeof(val32));
                }
        } else
Index: sys/netinet6/ip6_id.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/ip6_id.c,v
retrieving revision 1.16
diff -u -b -r1.16 ip6_id.c
--- sys/netinet6/ip6_id.c       30 Aug 2006 17:11:53 -0000      1.16
+++ sys/netinet6/ip6_id.c       21 Oct 2011 20:31:25 -0000
@@ -85,6 +85,8 @@
 __KERNEL_RCSID(0, "$NetBSD: ip6_id.c,v 1.16 2006/08/30 17:11:53 christos Exp 
$");
 
 #include <sys/param.h>
+#include <sys/cprng.h>
+
 #include <lib/libkern/libkern.h>
 
 #include <net/if.h>
@@ -175,20 +177,20 @@
        u_int32_t j, i;
        int noprime = 1;
 
-       p->ru_x = arc4random() % p->ru_m;
+       p->ru_x = cprng_fast32() % p->ru_m;
 
        /* (bits - 1) bits of random seed */
-       p->ru_seed = arc4random() & (~0U >> (32 - p->ru_bits + 1));
-       p->ru_seed2 = arc4random() & (~0U >> (32 - p->ru_bits + 1));
+       p->ru_seed = cprng_fast32() & (~0U >> (32 - p->ru_bits + 1));
+       p->ru_seed2 = cprng_fast32() & (~0U >> (32 - p->ru_bits + 1));
 
        /* Determine the LCG we use */
-       p->ru_b = (arc4random() & (~0U >> (32 - p->ru_bits))) | 1;
+       p->ru_b = (cprng_fast32() & (~0U >> (32 - p->ru_bits))) | 1;
        p->ru_a = pmod(p->ru_agen,
-           (arc4random() & (~0U >> (32 - p->ru_bits))) & (~1U), p->ru_m);
+           (cprng_fast32() & (~0U >> (32 - p->ru_bits))) & (~1U), p->ru_m);
        while (p->ru_b % 3 == 0)
                p->ru_b += 2;
 
-       j = arc4random() % p->ru_n;
+       j = cprng_fast32() % p->ru_n;
 
        /*
         * Do a fast gcd(j, RU_N - 1), so we can find a j with
@@ -222,7 +224,7 @@
                initid(p);
 
        /* Skip a random number of ids */
-       n = arc4random() & 0x3;
+       n = cprng_fast32() & 0x3;
        if (p->ru_counter + n >= p->ru_max)
                initid(p);
 
Index: sys/netinet6/ip6_input.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.132
diff -u -b -r1.132 ip6_input.c
--- sys/netinet6/ip6_input.c    1 Jun 2011 22:59:44 -0000       1.132
+++ sys/netinet6/ip6_input.c    21 Oct 2011 20:31:25 -0000
@@ -85,6 +85,7 @@
 #include <sys/syslog.h>
 #include <sys/proc.h>
 #include <sys/sysctl.h>
+#include <sys/cprng.h>
 
 #include <net/if.h>
 #include <net/if_types.h>
@@ -190,7 +191,7 @@
        addrsel_policy_init();
        nd6_init();
        frag6_init();
-       ip6_desync_factor = arc4random() % MAX_TEMP_DESYNC_FACTOR;
+       ip6_desync_factor = cprng_fast32() % MAX_TEMP_DESYNC_FACTOR;
 
        ip6_init2((void *)0);
 #ifdef GATEWAY
Index: sys/netinet6/mld6.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/mld6.c,v
retrieving revision 1.54
diff -u -b -r1.54 mld6.c
--- sys/netinet6/mld6.c 19 Oct 2011 01:53:07 -0000      1.54
+++ sys/netinet6/mld6.c 21 Oct 2011 20:31:26 -0000
@@ -116,6 +116,7 @@
 #include <sys/sysctl.h>
 #include <sys/kernel.h>
 #include <sys/callout.h>
+#include <sys/cprng.h>
 
 #include <net/if.h>
 
@@ -289,7 +290,7 @@
                in6m->in6m_state = MLD_OTHERLISTENER;
        } else {
                mld_sendpkt(in6m, MLD_LISTENER_REPORT, NULL);
-               in6m->in6m_timer = arc4random() %
+               in6m->in6m_timer = cprng_fast32() %
                    (MLD_UNSOLICITED_REPORT_INTERVAL * hz);
                in6m->in6m_state = MLD_IREPORTEDLAST;
 
@@ -443,7 +444,7 @@
                        } else if (in6m->in6m_timer == IN6M_TIMER_UNDEF ||
                            mld_timerresid(in6m) > timer) {
                                in6m->in6m_timer =
-                                  1 + (arc4random() % timer) * hz / 1000;
+                                  1 + (cprng_fast32() % timer) * hz / 1000;
                                mld_starttimer(in6m);
                        }
                }
Index: sys/netinet6/mld6_var.h
===================================================================
RCS file: /cvsroot/src/sys/netinet6/mld6_var.h,v
retrieving revision 1.9
diff -u -b -r1.9 mld6_var.h
--- sys/netinet6/mld6_var.h     1 Nov 2007 20:33:58 -0000       1.9
+++ sys/netinet6/mld6_var.h     21 Oct 2011 20:31:26 -0000
@@ -35,7 +35,7 @@
 
 #ifdef _KERNEL
 
-#define MLD_RANDOM_DELAY(X)    (arc4random() % (X) + 1)
+#define MLD_RANDOM_DELAY(X)    (cprng_fast32() % (X) + 1)
 
 /*
  * States for MLD stop-listening processing
Index: sys/netinet6/nd6.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/nd6.c,v
retrieving revision 1.136
diff -u -b -r1.136 nd6.c
--- sys/netinet6/nd6.c  15 Jul 2010 19:15:30 -0000      1.136
+++ sys/netinet6/nd6.c  21 Oct 2011 20:31:26 -0000
@@ -50,6 +50,7 @@
 #include <sys/ioctl.h>
 #include <sys/syslog.h>
 #include <sys/queue.h>
+#include <sys/cprng.h>
 
 #include <net/if.h>
 #include <net/if_dl.h>
Index: sys/netinet6/nd6.h
===================================================================
RCS file: /cvsroot/src/sys/netinet6/nd6.h,v
retrieving revision 1.54
diff -u -b -r1.54 nd6.h
--- sys/netinet6/nd6.h  24 May 2011 18:07:11 -0000      1.54
+++ sys/netinet6/nd6.h  21 Oct 2011 20:31:26 -0000
@@ -260,7 +260,7 @@
 #define TEMPADDR_REGEN_ADVANCE         5       /* sec */
 #define MAX_TEMP_DESYNC_FACTOR         600     /* 10 min */
 #define ND_COMPUTE_RTIME(x) \
-               (((MIN_RANDOM_FACTOR * (x >> 10)) + (arc4random() & \
+               (((MIN_RANDOM_FACTOR * (x >> 10)) + (cprng_fast32() & \
                ((MAX_RANDOM_FACTOR - MIN_RANDOM_FACTOR) * (x >> 10)))) /1000)
 
 TAILQ_HEAD(nd_drhead, nd_defrouter);
Index: sys/netinet6/nd6_rtr.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/nd6_rtr.c,v
retrieving revision 1.81
diff -u -b -r1.81 nd6_rtr.c
--- sys/netinet6/nd6_rtr.c      24 May 2011 18:07:11 -0000      1.81
+++ sys/netinet6/nd6_rtr.c      21 Oct 2011 20:31:27 -0000
@@ -44,6 +44,7 @@
 #include <sys/errno.h>
 #include <sys/ioctl.h>
 #include <sys/syslog.h>
+#include <sys/cprng.h>
 
 #include <net/if.h>
 #include <net/if_types.h>
Index: sys/netkey/key.c
===================================================================
RCS file: /cvsroot/src/sys/netkey/key.c,v
retrieving revision 1.179
diff -u -b -r1.179 key.c
--- sys/netkey/key.c    17 Jul 2011 20:54:54 -0000      1.179
+++ sys/netkey/key.c    21 Oct 2011 20:31:27 -0000
@@ -96,10 +96,7 @@
 
 #include <miscfs/kernfs/kernfs.h>
 
-#include "rnd.h"
-#if NRND > 0
-#include <sys/rnd.h>
-#endif
+#include <sys/cprng.h>
 
 #include <net/net_osdep.h>
 
@@ -4975,20 +4972,7 @@
 void
 key_randomfill(void *p, size_t l)
 {
-#if NRND == 0
-       static int warn = 1;
-#endif
-
-       arc4randbytes(p, l);
-
-#if NRND == 0
-       /* the arc4 generator is keyed with junk. */
-       if (warn) {
-               printf("WARNING: pseudo-random number generator "
-                   "used for IPsec processing\n");
-               warn = 0;
-       }
-#endif
+       cprng_fast(p, l);
 }
 
 /*
Index: sys/nfs/nfs_subs.c
===================================================================
RCS file: /cvsroot/src/sys/nfs/nfs_subs.c,v
retrieving revision 1.221
diff -u -b -r1.221 nfs_subs.c
--- sys/nfs/nfs_subs.c  12 Jun 2011 03:35:59 -0000      1.221
+++ sys/nfs/nfs_subs.c  21 Oct 2011 20:31:28 -0000
@@ -98,6 +98,7 @@
 #include <sys/once.h>
 #include <sys/kauth.h>
 #include <sys/atomic.h>
+#include <sys/cprng.h>
 
 #include <uvm/uvm.h>
 
@@ -1488,7 +1489,7 @@
        nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
        if (nfs_ticks < 1)
                nfs_ticks = 1;
-       nfs_xid = arc4random();
+       nfs_xid = cprng_fast32();
        nfsdreq_init();
 
        /*
Index: sys/opencrypto/files.opencrypto
===================================================================
RCS file: /cvsroot/src/sys/opencrypto/files.opencrypto,v
retrieving revision 1.24
diff -u -b -r1.24 files.opencrypto
--- sys/opencrypto/files.opencrypto     26 May 2011 21:50:03 -0000      1.24
+++ sys/opencrypto/files.opencrypto     21 Oct 2011 20:31:28 -0000
@@ -15,7 +15,7 @@
 # Pseudo-device that provides software implementations of various cryptographic
 # algorithms.
 defpseudo swcrypto: opencrypto,
-               blowfish, des, cast128, rijndael, skipjack, camellia
+               blowfish, des, cast128, skipjack, camellia
 file   opencrypto/cryptosoft.c         swcrypto
 file   opencrypto/deflate.c            swcrypto        # wrapper around zlib
 file   opencrypto/aesxcbcmac.c         swcrypto
Index: sys/rump/dev/lib/librnd/Makefile
===================================================================
RCS file: /cvsroot/src/sys/rump/dev/lib/librnd/Makefile,v
retrieving revision 1.2
diff -u -b -r1.2 Makefile
--- sys/rump/dev/lib/librnd/Makefile    16 Feb 2010 20:42:45 -0000      1.2
+++ sys/rump/dev/lib/librnd/Makefile    21 Oct 2011 20:31:28 -0000
@@ -5,7 +5,7 @@
 
 LIB=   rumpdev_rnd
 
-SRCS=   rnd.c rndpool.c
+#SRCS=   rnd.c rndpool.c
 
 SRCS+= component.c
 
Index: sys/rump/librump/rumpkern/Makefile.rumpkern
===================================================================
RCS file: /cvsroot/src/sys/rump/librump/rumpkern/Makefile.rumpkern,v
retrieving revision 1.110
diff -u -b -r1.110 Makefile.rumpkern
--- sys/rump/librump/rumpkern/Makefile.rumpkern 12 Jun 2011 06:36:38 -0000      
1.110
+++ sys/rump/librump/rumpkern/Makefile.rumpkern 21 Oct 2011 20:31:28 -0000
@@ -20,7 +20,7 @@
 # 
 SRCS=  rump.c rumpcopy.c emul.c intr.c lwproc.c klock.c        \
        kobj_rename.c ltsleep.c memalloc.c scheduler.c          \
-       signals.c sleepq.c threads.c vm.c
+       signals.c sleepq.c threads.c vm.c cprng_stub.c
 
 # Multiprocessor or uniprocessor locking.  TODO: select right
 # locking at runtime.
@@ -94,6 +94,7 @@
        subr_lwp_specificdata.c \
        subr_once.c             \
        subr_prf.c              \
+       subr_rngtest.c          \
        subr_specificdata.c     \
        subr_time.c             \
        subr_workqueue.c        \
Index: sys/rump/librump/rumpkern/cprng_stub.c
===================================================================
RCS file: sys/rump/librump/rumpkern/cprng_stub.c
diff -N sys/rump/librump/rumpkern/cprng_stub.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sys/rump/librump/rumpkern/cprng_stub.c      21 Oct 2011 20:31:28 -0000
@@ -0,0 +1,89 @@
+/*     $NetBSD: $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Thor Lancelot Simon.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/kmem.h>
+#include <sys/mutex.h>
+#include <sys/rngtest.h>
+
+#include <machine/cpu_counter.h>
+
+#include <sys/cprng.h>
+
+/*
+ * This is all stubbed out because of rump build dependency issues I
+ * cannot fix.  One is more-or-less caused by the longstanding bogosity
+ * that sys/dev/rnd.c implements *both* the in-kernel interface *and*
+ * the pseudodevice.  The other, by the fact that I am not smart enough
+ * to understand how to deal with code in rumpkern that depends on code
+ * that lives in sys/crypto.  Sigh.
+ */
+
+cprng_strong_t *kern_cprng = NULL;
+
+void
+cprng_init(void)
+{
+       return;
+}
+
+cprng_strong_t *cprng_strong_create(const char *const name, int ipl)
+{
+       cprng_strong_t *c;
+
+       c = kmem_alloc(sizeof(*c), KM_NOSLEEP);
+       if (c == NULL) {
+               return NULL;
+       }
+       strlcpy(c->name, name, sizeof(c->name));
+       mutex_init(&c->mtx, MUTEX_DEFAULT, ipl);
+       return c;
+}
+
+
+size_t cprng_strong(cprng_strong_t *c, void *p, size_t len)
+{
+       mutex_enter(&c->mtx);
+       cprng_fast(p, len);             /* XXX! */
+       mutex_exit(&c->mtx);
+       return len;
+}
+
+void cprng_strong_destroy(cprng_strong_t *c)
+{
+       mutex_destroy(&c->mtx);
+       memset(c, 0, sizeof(*c));
+       kmem_free(c, sizeof(*c));
+}
Index: sys/rump/librump/rumpkern/rump.c
===================================================================
RCS file: /cvsroot/src/sys/rump/librump/rumpkern/rump.c,v
retrieving revision 1.234
diff -u -b -r1.234 rump.c
--- sys/rump/librump/rumpkern/rump.c    22 Mar 2011 15:16:23 -0000      1.234
+++ sys/rump/librump/rumpkern/rump.c    21 Oct 2011 20:31:28 -0000
@@ -69,6 +69,7 @@
 #include <sys/vmem.h>
 #include <sys/xcall.h>
 #include <sys/simplelock.h>
+#include <sys/cprng.h>
 
 #include <rump/rumpuser.h>
 
@@ -288,7 +289,7 @@
         * implementation.
         */
        messthestack();
-       arc4random();
+       cprng_fast32();
 
        if (rump_version != RUMP_VERSION) {
                printf("rump version mismatch, %d vs. %d\n",
Index: sys/rump/librump/rumpvfs/rumpblk.c
===================================================================
RCS file: /cvsroot/src/sys/rump/librump/rumpvfs/rumpblk.c,v
retrieving revision 1.46
diff -u -b -r1.46 rumpblk.c
--- sys/rump/librump/rumpvfs/rumpblk.c  3 Feb 2011 22:16:11 -0000       1.46
+++ sys/rump/librump/rumpvfs/rumpblk.c  21 Oct 2011 20:31:28 -0000
@@ -65,6 +65,7 @@
 #include <sys/malloc.h>
 #include <sys/queue.h>
 #include <sys/stat.h>
+#include <sys/cprng.h>
 
 #include <rump/rumpuser.h>
 
@@ -326,7 +327,7 @@
                    &error) == 0) {
                        randstate = strtoul(buf, NULL, 10);
                } else {
-                       randstate = arc4random();
+                       randstate = cprng_fast32();
                }
                printf("rumpblk: FAULT INJECTION ACTIVE! fail %d/%d. "
                    "seed %u\n", blkfail, BLKFAIL_MAX, randstate);
Index: sys/rump/net/lib/libshmif/if_shmem.c
===================================================================
RCS file: /cvsroot/src/sys/rump/net/lib/libshmif/if_shmem.c,v
retrieving revision 1.43
diff -u -b -r1.43 if_shmem.c
--- sys/rump/net/lib/libshmif/if_shmem.c        2 Sep 2011 22:25:08 -0000       
1.43
+++ sys/rump/net/lib/libshmif/if_shmem.c        21 Oct 2011 20:31:28 -0000
@@ -37,6 +37,7 @@
 #include <sys/kthread.h>
 #include <sys/lock.h>
 #include <sys/vmem.h>
+#include <sys/cprng.h>
 
 #include <net/bpf.h>
 #include <net/if.h>
@@ -152,7 +153,7 @@
        uint32_t randnum;
        int error;
 
-       randnum = arc4random();
+       randnum = cprng_fast32();
        memcpy(&enaddr[2], &randnum, sizeof(randnum));
 
        sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
Index: sys/rump/net/lib/libvirtif/if_virt.c
===================================================================
RCS file: /cvsroot/src/sys/rump/net/lib/libvirtif/if_virt.c,v
retrieving revision 1.24
diff -u -b -r1.24 if_virt.c
--- sys/rump/net/lib/libvirtif/if_virt.c        7 Aug 2011 14:03:16 -0000       
1.24
+++ sys/rump/net/lib/libvirtif/if_virt.c        21 Oct 2011 20:31:28 -0000
@@ -38,6 +38,7 @@
 #include <sys/poll.h>
 #include <sys/sockio.h>
 #include <sys/socketvar.h>
+#include <sys/cprng.h>
 
 #include <net/bpf.h>
 #include <net/if.h>
@@ -102,7 +103,7 @@
                    num, error);
                return error;
        }
-       enaddr[2] = arc4random() & 0xff;
+       enaddr[2] = cprng_fast32() & 0xff;
        enaddr[5] = num;
 
        sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
@@ -370,8 +371,8 @@
        struct ethercom *ec;
        uint8_t enaddr[ETHER_ADDR_LEN] = { 0xb2, 0x0a, 0x00, 0x0b, 0x0e, 0x01 };
 
-       enaddr[2] = arc4random() & 0xff;
-       enaddr[5] = arc4random() & 0xff;
+       enaddr[2] = cprng_fast32() & 0xff;
+       enaddr[5] = cprng_fast32() & 0xff;
 
        ec = kmem_zalloc(sizeof(*ec), KM_SLEEP);
 
Index: sys/sys/cprng.h
===================================================================
RCS file: sys/sys/cprng.h
diff -N sys/sys/cprng.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sys/sys/cprng.h     21 Oct 2011 20:31:28 -0000
@@ -0,0 +1,94 @@
+/*     $NetBSD: $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Thor Lancelot Simon.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _CPRNG_H
+#define _CPRNG_H
+
+#include <sys/types.h>
+#include <lib/libkern/libkern.h>
+#include <sys/rnd.h>
+#include <crypto/nist_ctr_drbg/nist_ctr_drbg.h>
+
+static inline size_t
+cprng_fast(void *p, size_t len)
+{
+       arc4randbytes(p, len);
+       return len;
+}
+
+static inline uint32_t
+cprng_fast32(void)
+{
+       return arc4random();
+}
+
+static inline uint64_t
+cprng_fast64(void)
+{
+       uint64_t r;
+       arc4randbytes(&r, sizeof(r));
+       return r;
+}
+
+typedef struct _cprng_strong {
+       kmutex_t      mtx;
+       NIST_CTR_DRBG drbg;
+       char          name[16];
+       int           reseed_pending;
+       rndsink_t     reseed;
+} cprng_strong_t;
+
+cprng_strong_t *cprng_strong_create(const char *const, int);
+
+size_t cprng_strong(cprng_strong_t *, void *, size_t);
+
+void cprng_strong_destroy(cprng_strong_t *);
+
+extern cprng_strong_t *        kern_cprng;
+
+static inline uint32_t
+cprng_strong32(void)
+{
+       uint32_t r;
+       cprng_strong(kern_cprng, &r, sizeof(r));
+        return r;
+}
+
+static inline uint64_t
+cprng_strong64(void)
+{
+        uint64_t r;
+       cprng_strong(kern_cprng, &r, sizeof(r));
+        return r;
+}
+
+void cprng_init(void);
+
+#endif
Index: sys/sys/queue.h
===================================================================
RCS file: /cvsroot/src/sys/sys/queue.h,v
retrieving revision 1.52
diff -u -b -r1.52 queue.h
--- sys/sys/queue.h     20 Apr 2009 09:56:08 -0000      1.52
+++ sys/sys/queue.h     21 Oct 2011 20:31:28 -0000
@@ -166,6 +166,10 @@
                (var);                                                  \
                (var) = ((var)->field.le_next))
 
+#define        LIST_FOREACH_SAFE(var, head, field, tvar)                       
\
+       for ((var) = LIST_FIRST((head));                                \
+               (var) && ((tvar) = LIST_NEXT((var), field), 1);         \
+               (var) = (tvar))
 /*
  * List access methods.
  */
Index: sys/sys/rnd.h
===================================================================
RCS file: /cvsroot/src/sys/sys/rnd.h,v
retrieving revision 1.21
diff -u -b -r1.21 rnd.h
--- sys/sys/rnd.h       28 Apr 2008 20:24:11 -0000      1.21
+++ sys/sys/rnd.h       21 Oct 2011 20:31:28 -0000
@@ -43,6 +43,10 @@
 #include <sys/queue.h>
 #endif
 
+#ifdef _KERNEL
+#include <sys/rngtest.h>
+#endif
+
 #define        RND_DEV_RANDOM  0       /* minor devices for random and kinda 
random */
 #define        RND_DEV_URANDOM 1
 
@@ -82,26 +86,14 @@
        uint32_t        generated;
 } rndpoolstat_t;
 
-
-typedef struct {
-       uint32_t        cursor;         /* current add point in the pool */
-       uint32_t        rotate;         /* how many bits to rotate by */
-       rndpoolstat_t   stats;          /* current statistics */
-       uint32_t        pool[RND_POOLWORDS]; /* random pool data */
-} rndpool_t;
-
+/* Sanitized random source view for userspace */
 typedef struct {
        char            name[16];       /* device name */
-       uint32_t        last_time;      /* last time recorded */
-       uint32_t        last_delta;     /* last delta value */
-       uint32_t        last_delta2;    /* last delta2 value */
        uint32_t        total;          /* entropy from this source */
        uint32_t        type;           /* type */
        uint32_t        flags;          /* flags */
-       void            *state;         /* state informaiton */
 } rndsource_t;
 
-
 /*
  * Flags to control the source.  Low byte is type, upper bits are flags.
  */
@@ -118,12 +110,36 @@
 #define        RND_TYPE_MAX            5       /* last type id used */
 
 #ifdef _KERNEL
-typedef struct __rndsource_element rndsource_element_t;
 
-struct __rndsource_element {
-       LIST_ENTRY(__rndsource_element) list; /* the linked list */
-       rndsource_t     data;           /* the actual data */
-};
+typedef struct krndsource {
+       LIST_ENTRY(krndsource) list;    /* the linked list */
+        char            name[16];       /* device name */
+        uint32_t        last_time;      /* last time recorded */
+        uint32_t        last_delta;     /* last delta value */
+        uint32_t        last_delta2;    /* last delta2 value */
+        uint32_t        total;          /* entropy from this source */
+        uint32_t        type;           /* type */
+        uint32_t        flags;          /* flags */
+        void            *state;         /* state informaiton */
+        size_t          test_cnt;       /* how much test data accumulated? */
+        rngtest_t      *test;          /* test data for RNG type sources */
+} krndsource_t;
+
+typedef struct rndsink {
+        TAILQ_ENTRY(rndsink) tailq;     /* the queue */
+        void            (*cb)(void *);  /* callback function when ready */
+        void            *arg;           /* callback function argument */
+        char            name[16];       /* sink name */
+        size_t          len;            /* how many bytes wanted/supplied */
+        uint8_t         data[64];       /* random data returned here */
+} rndsink_t;
+
+typedef struct {
+        uint32_t        cursor;         /* current add point in the pool */
+        uint32_t        rotate;         /* how many bits to rotate by */
+        rndpoolstat_t   stats;          /* current statistics */
+        uint32_t        pool[RND_POOLWORDS]; /* random pool data */
+} rndpool_t;
 
 /*
  * Used by rnd_extract_data() and rndpool_extract_data() to describe how
@@ -134,7 +150,7 @@
                                      (short read ok) */
 
 #define RND_ENABLED(rp) \
-        (((rp)->data.flags & RND_FLAG_NO_COLLECT) == 0)
+        (((rp)->flags & RND_FLAG_NO_COLLECT) == 0)
 
 void           rndpool_init(rndpool_t *);
 void           rndpool_init_global(void);
@@ -148,13 +164,16 @@
                    uint32_t);
 
 void           rnd_init(void);
-void           rnd_add_uint32(rndsource_element_t *, uint32_t);
-void           rnd_add_data(rndsource_element_t *, void *, uint32_t,
+void           rnd_add_uint32(krndsource_t *, uint32_t);
+void           rnd_add_data(krndsource_t *, void *, uint32_t,
                    uint32_t);
 uint32_t       rnd_extract_data(void *, uint32_t, uint32_t);
-void           rnd_attach_source(rndsource_element_t *, const char *,
+void           rnd_attach_source(krndsource_t *, const char *,
                    uint32_t, uint32_t);
-void           rnd_detach_source(rndsource_element_t *);
+void           rnd_detach_source(krndsource_t *);
+
+void           rndsink_attach(rndsink_t *);
+void           rndsink_detach(rndsink_t *);
 
 #endif /* _KERNEL */
 
Index: sys/sys/rngtest.h
===================================================================
RCS file: sys/sys/rngtest.h
diff -N sys/sys/rngtest.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sys/sys/rngtest.h   21 Oct 2011 20:31:28 -0000
@@ -0,0 +1,49 @@
+/*     $NetBSD: $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Thor Lancelot Simon.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _RNGTEST_H
+#define _RNGTEST_H
+
+#include <sys/types.h>
+
+#define FIPS140_RNG_TEST_BITS 20000
+#define FIPS140_RNG_TEST_BYTES (FIPS140_RNG_TEST_BITS / NBBY)
+
+typedef struct {
+       uint8_t rt_b[FIPS140_RNG_TEST_BYTES];
+       int     rt_poker[16];
+       int     rt_runs[2][7];
+       int     rt_nerrs;
+       char    rt_name[16];
+} rngtest_t;
+
+int rngtest(rngtest_t *const);
+
+#endif
Index: sys/sys/sysctl.h
===================================================================
RCS file: /cvsroot/src/sys/sys/sysctl.h,v
retrieving revision 1.196
diff -u -b -r1.196 sysctl.h
--- sys/sys/sysctl.h    12 Oct 2011 23:04:22 -0000      1.196
+++ sys/sys/sysctl.h    21 Oct 2011 20:31:29 -0000
@@ -56,6 +56,10 @@
 #include <stdbool.h>
 #endif
 
+#ifdef _KERNEL
+#include <sys/cprng.h>
+#endif
+
 /*
  * Definitions for sysctl call.  The sysctl call uses a hierarchical name
  * for objects that can be examined or modified.  The name is expressed as
@@ -1208,6 +1212,8 @@
 
 extern const u_int sysctl_lwpflagmap[];
 
+extern cprng_strong_t *sysctl_prng;
+
 #else  /* !_KERNEL */
 #include <sys/cdefs.h>
 
Index: sys/ufs/ffs/ffs_appleufs.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ffs/ffs_appleufs.c,v
retrieving revision 1.11
diff -u -b -r1.11 ffs_appleufs.c
--- sys/ufs/ffs/ffs_appleufs.c  22 Jun 2011 04:01:33 -0000      1.11
+++ sys/ufs/ffs/ffs_appleufs.c  21 Oct 2011 20:31:30 -0000
@@ -33,6 +33,7 @@
 #if defined(_KERNEL)
 #include <sys/kernel.h>
 #include <sys/systm.h>
+#include <sys/cprng.h>
 #endif
 
 #include <ufs/ufs/dinode.h>
@@ -136,9 +137,7 @@
        }
        if (uuid == 0) {
 #if defined(_KERNEL) && !defined(STANDALONE)
-               uuid = arc4random();
-               uuid <<= 32;
-               uuid |= arc4random();
+               uuid = cprng_fast64();
 #endif
        }
        namelen = strlen(name);


Home | Main Index | Thread Index | Old Index