? rnd2.diff
? arch/amd64/conf/NEWRND
? dev/.rndpseudo.c.swp
? dev/pci/.hifn7751.c.swp
? opencrypto/.cryptodev.c.swp
? opencrypto/.cryptodev.h.swp
Index: 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
--- altq/altq_blue.c	4 Mar 2007 05:59:00 -0000	1.22
+++ altq/altq_blue.c	31 Oct 2011 04:29:06 -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: 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
--- altq/altq_cdnr.c	4 Mar 2007 05:59:01 -0000	1.19
+++ altq/altq_cdnr.c	31 Oct 2011 04:29:06 -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: 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
--- altq/altq_red.c	18 Jun 2008 09:06:27 -0000	1.28
+++ altq/altq_red.c	31 Oct 2011 04:29:06 -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: 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
--- altq/altq_rmclass.c	15 Jul 2008 16:18:08 -0000	1.21
+++ altq/altq_rmclass.c	31 Oct 2011 04:29:07 -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: 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
--- arch/acorn26/ioc/arckbd.c	19 Jul 2011 16:05:10 -0000	1.20
+++ arch/acorn26/ioc/arckbd.c	31 Oct 2011 04:29:07 -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: 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
--- arch/arm/at91/at91dbguvar.h	23 Oct 2009 06:53:13 -0000	1.3
+++ arch/arm/at91/at91dbguvar.h	31 Oct 2011 04:29:07 -0000
@@ -82,7 +82,7 @@
 
 	int			enabled;
 #if NRND > 0 && defined(RND_COM)
-	rndsource_element_t  rnd_source;
+	krndsource_t  rnd_source;
 #endif
 };
 
Index: 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
--- arch/arm/at91/at91usartvar.h	23 Oct 2009 06:53:13 -0000	1.3
+++ arch/arm/at91/at91usartvar.h	31 Oct 2011 04:29:07 -0000
@@ -86,7 +86,7 @@
 
 	int			enabled;
 #if NRND > 0 && defined(RND_COM)
-	rndsource_element_t  rnd_source;
+	krndsource_t  rnd_source;
 #endif
 };
 
Index: 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
--- arch/arm/ep93xx/epcomvar.h	23 Oct 2009 00:39:30 -0000	1.4
+++ arch/arm/ep93xx/epcomvar.h	31 Oct 2011 04:29:07 -0000
@@ -83,7 +83,7 @@
 
 	int			enabled;
 #if NRND > 0 && defined(RND_COM)
-	rndsource_element_t  rnd_source;
+	krndsource_t  rnd_source;
 #endif
 };
 
Index: 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
--- arch/arm/s3c2xx0/sscom_var.h	1 Jul 2011 20:31:39 -0000	1.8
+++ arch/arm/s3c2xx0/sscom_var.h	31 Oct 2011 04:29:07 -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: 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
--- arch/arm/sa11x0/sa1111_kbc.c	13 Mar 2010 11:13:31 -0000	1.12
+++ arch/arm/sa11x0/sa1111_kbc.c	31 Oct 2011 04:29:07 -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: 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
--- arch/arm/xscale/ixp425_if_npe.c	1 Jul 2011 20:32:51 -0000	1.20
+++ arch/arm/xscale/ixp425_if_npe.c	31 Oct 2011 04:29:08 -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: 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
--- arch/emips/ebus/ace_ebus.c	18 Jun 2011 17:47:20 -0000	1.2
+++ arch/emips/ebus/ace_ebus.c	31 Oct 2011 04:29:09 -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: 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
--- arch/emips/ebus/flash_ebus.c	12 Jun 2011 03:29:33 -0000	1.2
+++ arch/emips/ebus/flash_ebus.c	31 Oct 2011 04:29:09 -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: 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
--- arch/emips/ebus/if_le_ebus.c	12 Jun 2011 14:31:31 -0000	1.2
+++ arch/emips/ebus/if_le_ebus.c	31 Oct 2011 04:29:09 -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: 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
--- arch/evbarm/dev/plcomvar.h	5 Jan 2008 12:40:34 -0000	1.6
+++ arch/evbarm/dev/plcomvar.h	31 Oct 2011 04:29:10 -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: 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
--- arch/hp300/dev/rdvar.h	8 Feb 2011 20:20:13 -0000	1.20
+++ arch/hp300/dev/rdvar.h	31 Oct 2011 04:29:10 -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: 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
--- arch/hp700/gsc/harmonyvar.h	25 Apr 2008 08:17:52 -0000	1.4
+++ arch/hp700/gsc/harmonyvar.h	31 Oct 2011 04:29:10 -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: 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
--- arch/i386/pci/glxsb.c	16 May 2009 16:52:03 -0000	1.9
+++ arch/i386/pci/glxsb.c	31 Oct 2011 04:29:10 -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: 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
--- arch/macppc/dev/if_gm.c	18 Jun 2011 08:08:28 -0000	1.39
+++ arch/macppc/dev/if_gm.c	31 Oct 2011 04:29:11 -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: 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
--- arch/mips/alchemy/dev/if_aumac.c	10 Jul 2011 23:13:23 -0000	1.31
+++ arch/mips/alchemy/dev/if_aumac.c	31 Oct 2011 04:29:11 -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: 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
--- arch/mips/atheros/dev/aevar.h	28 Apr 2008 20:23:28 -0000	1.3
+++ arch/mips/atheros/dev/aevar.h	31 Oct 2011 04:29:11 -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: 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
--- arch/mips/sibyte/dev/sbscnvar.h	1 Feb 2011 03:16:54 -0000	1.4
+++ arch/mips/sibyte/dev/sbscnvar.h	31 Oct 2011 04:29:11 -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: 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
--- arch/next68k/dev/mb8795var.h	24 Apr 2010 19:58:13 -0000	1.11
+++ arch/next68k/dev/mb8795var.h	31 Oct 2011 04:29:11 -0000
@@ -72,7 +72,7 @@
 	struct ifmedia sc_media;
 
 #if NRND > 0
-	rndsource_element_t     rnd_source;
+	krndsource_t     rnd_source;
 #endif /* NRND */
 
 };
Index: 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
--- arch/sgimips/hpc/sqvar.h	25 Jan 2011 13:12:39 -0000	1.12
+++ arch/sgimips/hpc/sqvar.h	31 Oct 2011 04:29:12 -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: 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
--- arch/sgimips/mace/if_mec.c	1 Jul 2011 18:53:47 -0000	1.46
+++ arch/sgimips/mace/if_mec.c	31 Oct 2011 04:29:12 -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: 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
--- arch/sun2/dev/if_ec.c	5 Apr 2010 07:19:32 -0000	1.18
+++ arch/sun2/dev/if_ec.c	31 Oct 2011 04:29:12 -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: 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
--- arch/x68k/dev/fd.c	10 Apr 2011 15:23:06 -0000	1.94
+++ arch/x68k/dev/fd.c	31 Oct 2011 04:29:12 -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: 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
--- arch/x86/include/via_padlock.h	19 Feb 2011 13:52:28 -0000	1.6
+++ arch/x86/include/via_padlock.h	31 Oct 2011 04:29:12 -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: 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
--- arch/x86/pci/fwhrng.c	1 Jul 2011 18:22:08 -0000	1.3
+++ arch/x86/pci/fwhrng.c	31 Oct 2011 04:29:12 -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: 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
--- arch/x86/x86/via_padlock.c	24 May 2011 18:59:21 -0000	1.15
+++ arch/x86/x86/via_padlock.c	31 Oct 2011 04:29:12 -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: 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
--- arch/xen/include/xbdvar.h	23 Oct 2009 02:32:33 -0000	1.12
+++ arch/xen/include/xbdvar.h	31 Oct 2011 04:29:12 -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: 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
--- arch/xen/xen/if_xennet_xenbus.c	26 Sep 2011 21:44:09 -0000	1.53
+++ arch/xen/xen/if_xennet_xenbus.c	31 Oct 2011 04:29:13 -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: 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
--- arch/xen/xen/xbd_xenbus.c	20 Sep 2011 00:12:24 -0000	1.48
+++ arch/xen/xen/xbd_xenbus.c	31 Oct 2011 04:29:13 -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: conf/files
===================================================================
RCS file: /cvsroot/src/sys/conf/files,v
retrieving revision 1.1029
diff -u -b -r1.1029 files
--- conf/files	15 Oct 2011 00:23:08 -0000	1.1029
+++ conf/files	31 Oct 2011 04:29:13 -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: crypto/nist_ctr_drbg/files.nist_ctr_drbg
===================================================================
RCS file: crypto/nist_ctr_drbg/files.nist_ctr_drbg
diff -N crypto/nist_ctr_drbg/files.nist_ctr_drbg
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ crypto/nist_ctr_drbg/files.nist_ctr_drbg	31 Oct 2011 04:29:13 -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: crypto/nist_ctr_drbg/nist_ctr_aes_rijndael.h
===================================================================
RCS file: crypto/nist_ctr_drbg/nist_ctr_aes_rijndael.h
diff -N crypto/nist_ctr_drbg/nist_ctr_aes_rijndael.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ crypto/nist_ctr_drbg/nist_ctr_aes_rijndael.h	31 Oct 2011 04:29:13 -0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2007 Henric Jungheim <software@henric.info>
+ *
+ * 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: crypto/nist_ctr_drbg/nist_ctr_drbg.c
===================================================================
RCS file: crypto/nist_ctr_drbg/nist_ctr_drbg.c
diff -N crypto/nist_ctr_drbg/nist_ctr_drbg.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ crypto/nist_ctr_drbg/nist_ctr_drbg.c	31 Oct 2011 04:29:13 -0000
@@ -0,0 +1,598 @@
+/*
+ * Copyright (c) 2007 Henric Jungheim <software@henric.info>
+ *
+ * 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: crypto/nist_ctr_drbg/nist_ctr_drbg.h
===================================================================
RCS file: crypto/nist_ctr_drbg/nist_ctr_drbg.h
diff -N crypto/nist_ctr_drbg/nist_ctr_drbg.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ crypto/nist_ctr_drbg/nist_ctr_drbg.h	31 Oct 2011 04:29:13 -0000
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2007 Henric Jungheim <software@henric.info>
+ *
+ * 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: crypto/nist_ctr_drbg/nist_ctr_drbg_aes128.h
===================================================================
RCS file: crypto/nist_ctr_drbg/nist_ctr_drbg_aes128.h
diff -N crypto/nist_ctr_drbg/nist_ctr_drbg_aes128.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ crypto/nist_ctr_drbg/nist_ctr_drbg_aes128.h	31 Oct 2011 04:29:13 -0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007 Henric Jungheim <software@henric.info>
+ *
+ * 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: crypto/nist_ctr_drbg/nist_ctr_drbg_aes256.h
===================================================================
RCS file: crypto/nist_ctr_drbg/nist_ctr_drbg_aes256.h
diff -N crypto/nist_ctr_drbg/nist_ctr_drbg_aes256.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ crypto/nist_ctr_drbg/nist_ctr_drbg_aes256.h	31 Oct 2011 04:29:13 -0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007 Henric Jungheim <software@henric.info>
+ *
+ * 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: crypto/nist_ctr_drbg/nist_ctr_drbg_config.h
===================================================================
RCS file: crypto/nist_ctr_drbg/nist_ctr_drbg_config.h
diff -N crypto/nist_ctr_drbg/nist_ctr_drbg_config.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ crypto/nist_ctr_drbg/nist_ctr_drbg_config.h	31 Oct 2011 04:29:13 -0000
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2007 Henric Jungheim <software@henric.info>
+ *
+ * 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: 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
--- crypto/rijndael/files.rijndael	11 Dec 2005 12:20:52 -0000	1.5
+++ crypto/rijndael/files.rijndael	31 Oct 2011 04:29:13 -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: dev/ldvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ldvar.h,v
retrieving revision 1.18
diff -u -b -r1.18 ldvar.h
--- dev/ldvar.h	20 Sep 2010 06:54:06 -0000	1.18
+++ dev/ldvar.h	31 Oct 2011 04:29:13 -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: dev/rnd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/rnd.c,v
retrieving revision 1.82
diff -u -b -r1.82 rnd.c
--- dev/rnd.c	11 Oct 2011 23:55:30 -0000	1.82
+++ dev/rnd.c	31 Oct 2011 04:29:14 -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,23 @@
 		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\""
+		       " (cb %p, arg %p).\n",
+		       (int)sink->len, sink->name, sink->cb, sink->arg);
+#endif
+		sink->cb(sink->arg);
+		TAILQ_REMOVE(&sunk, sink, tailq);
+	}
 }
 
 /*
@@ -218,7 +276,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;
 
@@ -287,7 +345,9 @@
 
 	/* mix in another counter */
 	c = rnd_counter();
+	mutex_enter(&rndpool_mtx);
 	rndpool_add_data(&rnd_pool, &c, sizeof(u_int32_t), 1);
+	mutex_exit(&rndpool_mtx);
 }
 
 /*
@@ -315,6 +375,7 @@
 
 	LIST_INIT(&rnd_sources);
 	SIMPLEQ_INIT(&rnd_samples);
+	TAILQ_INIT(&rnd_sinks);
 	selinit(&rnd_selq);
 
 	rndpool_init(&rnd_pool);
@@ -327,9 +388,11 @@
 	 * XXX more things to add would be nice.
 	 */
 	if (c) {
+		mutex_enter(&rndpool_mtx);
 		rndpool_add_data(&rnd_pool, &c, sizeof(u_int32_t), 1);
 		c = rnd_counter();
 		rndpool_add_data(&rnd_pool, &c, sizeof(u_int32_t), 1);
+		mutex_exit(&rndpool_mtx);
 	}
 
 	rnd_ready = 1;
@@ -470,11 +533,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 +625,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 +637,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 +651,15 @@
 		 * 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,
+				    MIN(sizeof(kr->name),
+					sizeof(*rstnm))) == 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 +672,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 +693,16 @@
 		/*
 		 * 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,
+				    MIN(sizeof(kr->name),
+                                        sizeof(rctl->name))) == 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 +832,7 @@
 }
 
 static rnd_sample_t *
-rnd_sample_allocate(rndsource_t *source)
+rnd_sample_allocate(krndsource_t *source)
 {
 	rnd_sample_t *c;
 
@@ -782,7 +851,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;
 
@@ -800,7 +869,7 @@
 static void
 rnd_sample_free(rnd_sample_t *c)
 {
-	memset(c, 0, sizeof(rnd_sample_t));
+	memset(c, 0, sizeof(*c));
 	pool_put(&rnd_mempool, c);
 }
 
@@ -808,7 +877,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 +886,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 +899,27 @@
 	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->data.state = rnd_sample_allocate(&rs->data);
+	rs->type = type;
+	rs->flags = flags;
 
+	rs->state = rnd_sample_allocate(rs);
+
+	mutex_enter(&rndpool_mtx);
 	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)
@@ -854,28 +935,30 @@
 	 * XXX Bogus, but harder to guess than zeros.
 	 */
 	rndpool_add_data(&rnd_pool, &ts, sizeof(u_int32_t), 1);
+	mutex_exit(&rndpool_mtx);
 }
 
 /*
  * 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 +971,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 +982,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;
+	u_int32_t entropy = 0;
 
-
-	rst = &rs->data;
-
-	if (rst->flags & RND_FLAG_NO_COLLECT)
+	if (rs->flags & RND_FLAG_NO_COLLECT)
 		return;
 
 	/*
@@ -918,134 +997,263 @@
 	ts = rnd_counter();
 
 	/*
-	 * If the sample buffer is NULL, try to allocate one here.  If this
-	 * fails, drop this sample.
+	 * If we are estimating entropy on this source,
+	 * calculate differentials.
 	 */
-	state = rst->state;
-	if (state == NULL) {
-		state = rnd_sample_allocate_isr(rst);
-		if (state == NULL)
+
+	if ((rs->flags & RND_FLAG_NO_ESTIMATE) == 0) {
+		entropy = rnd_estimate_entropy(rs, ts);
+	}
+
+	rnd_add_data(rs, &val, sizeof(val), entropy);
+}
+
+void
+rnd_add_data(krndsource_t *rs, const void *const data, u_int32_t len,
+    u_int32_t entropy)
+{
+	rnd_sample_t *state = NULL;
+	uint32_t ts;
+	const uint32_t *dint = data;
+	int todo, done, filled = 0;
+	SIMPLEQ_HEAD(, _rnd_sample_t) tmp_samples =
+	    		SIMPLEQ_HEAD_INITIALIZER(tmp_samples);
+
+	if (rs->flags & RND_FLAG_NO_COLLECT) {
 			return;
-		rst->state = state;
 	}
 
 	/*
-	 * If we are estimating entropy on this source,
-	 * calculate differentials.
+         * Sample the counter as soon as possible to avoid entropy
+         * overestimation.
 	 */
+        ts = rnd_counter();
 
-	if ((rst->flags & RND_FLAG_NO_ESTIMATE) == 0)
-		state->entropy += rnd_estimate_entropy(rst, ts);
+	/*
+	 * Loop over data packaging it into sample buffers.
+	 * If a sample buffer allocation fails, drop all data.
+	 */
+	todo = len / sizeof(*dint);
+	for (done = 0; done < todo ; done++) {
+		state = rs->state;
+		if (state == NULL) {
+			state = rnd_sample_allocate_isr(rs);
+			if (__predict_false(state == NULL)) {
+				break;
+			}
+			rs->state = state;
+		}
 
 	state->ts[state->cursor] = ts;
-	state->values[state->cursor] = val;
+		state->values[state->cursor] = dint[done];
 	state->cursor++;
 
+		if (state->cursor == RND_SAMPLE_COUNT) {
+			SIMPLEQ_INSERT_HEAD(&tmp_samples, state, next);
+			filled++;
+			rs->state = NULL;
+		}
+	}
+
+	if (__predict_false(state == NULL)) {
+		while ((state = SIMPLEQ_FIRST(&tmp_samples))) {
+			SIMPLEQ_REMOVE_HEAD(&tmp_samples, next);
+			rnd_sample_free(state);
+		}
+		return;
+	}
+
 	/*
-	 * If the state arrays are not full, we're done.
+	 * Claim all the entropy on the last one we send to
+	 * the pool, so we don't rely on it being evenly distributed
+	 * in the supplied data.
+	 *
+	 * XXX The rndpool code must accept samples with more
+	 * XXX claimed entropy than bits for this to work right.
 	 */
-	if (state->cursor < RND_SAMPLE_COUNT)
-		return;
+	state->entropy += entropy;
+	rs->total += entropy;
 
 	/*
-	 * State arrays are full.  Queue this chunk on the processing queue.
+	 * If we didn't finish any sample buffers, we're done.
 	 */
-	mutex_enter(&rnd_mtx);
+	if (!filled) {
+		return;
+	}
+
+	mutex_spin_enter(&rnd_mtx);
+	while ((state = SIMPLEQ_FIRST(&tmp_samples))) {
+		SIMPLEQ_REMOVE_HEAD(&tmp_samples, next);
 	SIMPLEQ_INSERT_HEAD(&rnd_samples, state, next);
-	rst->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! */
+		return;
+	} else {
 	if (rnd_timeout_pending == 0) {
 		rnd_timeout_pending = 1;
-		callout_reset(&rnd_callout, 1, rnd_timeout, NULL);
+			callout_reset(&rnd_callout, 1,
+				      rnd_timeout, NULL);
 	}
-	mutex_exit(&rnd_mtx);
-
-	/*
-	 * To get here we have to have queued the state up, and therefore
-	 * we need a new state buffer.  If we can, allocate one now;
-	 * 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);
+	}
+	mutex_spin_exit(&rnd_mtx);
 }
 
-void
-rnd_add_data(rndsource_element_t *rs, void *data, u_int32_t len,
-    u_int32_t entropy)
+static int
+rnd_hwrng_test(rnd_sample_t *sample)
 {
-	rndsource_t *rst;
+	krndsource_t *source = sample->source;
+	size_t cmplen;
+	uint8_t *v1, *v2;
+	size_t resid, totest;
 
-	/* Mix in the random data directly into the pool. */
-	rndpool_add_data(&rnd_pool, data, len, entropy);
+	KASSERT(source->type = RND_TYPE_RNG);
 
-	if (rs != NULL) {
-		rst = &rs->data;
-		rst->total += entropy;
+	/*
+	 * 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 ((rst->flags & RND_FLAG_NO_ESTIMATE) == 0)
-			/* Estimate entropy using timing information */
-			rnd_add_uint32(rs, *(u_int8_t *)data);
+	if (__predict_false(memcmp(v1, v2, cmplen))) {
+		printf("rnd: source \"%s\" failed continuous-output test.",
+		       source->name);
+		return 1;
 	}
 
-	/* Wake up any potential readers since we've just added some data. */
-	rnd_wakeup_readers();
+	/*
+	 * 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 +1261,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 +1288,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 +1337,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: 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
--- dev/ata/wdvar.h	17 Dec 2009 21:03:10 -0000	1.38
+++ dev/ata/wdvar.h	31 Oct 2011 04:29:14 -0000
@@ -67,7 +67,7 @@
 	u_int sc_bscount;
 #endif
 #if NRND > 0
-	rndsource_element_t	rnd_source;
+	krndsource_t	rnd_source;
 #endif
 };
 
Index: 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
--- dev/gpib/rd.c	8 Feb 2011 20:20:27 -0000	1.28
+++ dev/gpib/rd.c	31 Oct 2011 04:29:14 -0000
@@ -143,7 +143,7 @@
 	struct	callout sc_restart_ch;
 
 #if NRND > 0
-	rndsource_element_t rnd_source;
+	krndsource_t rnd_source;
 #endif
 };
 
Index: 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
--- dev/ic/comvar.h	13 Nov 2010 15:35:50 -0000	1.71
+++ dev/ic/comvar.h	31 Oct 2011 04:29:14 -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: 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
--- dev/ic/cs89x0var.h	22 Sep 2009 14:55:19 -0000	1.14
+++ dev/ic/cs89x0var.h	31 Oct 2011 04:29:14 -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: 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
--- dev/ic/dp8390var.h	12 May 2009 14:25:17 -0000	1.30
+++ dev/ic/dp8390var.h	31 Oct 2011 04:29:14 -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: 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
--- dev/ic/elink3var.h	5 Sep 2009 12:30:59 -0000	1.36
+++ dev/ic/elink3var.h	31 Oct 2011 04:29:14 -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: 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
--- dev/ic/elinkxlvar.h	22 Mar 2010 23:03:30 -0000	1.22
+++ dev/ic/elinkxlvar.h	31 Oct 2011 04:29:14 -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: 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
--- dev/ic/gemvar.h	24 Feb 2010 22:37:58 -0000	1.21
+++ dev/ic/gemvar.h	31 Oct 2011 04:29:14 -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: 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
--- dev/ic/hmevar.h	18 Sep 2009 12:40:15 -0000	1.21
+++ dev/ic/hmevar.h	31 Oct 2011 04:29:14 -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: 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
--- dev/ic/i82557var.h	25 Feb 2010 23:40:39 -0000	1.48
+++ dev/ic/i82557var.h	31 Oct 2011 04:29:14 -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: 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
--- dev/ic/lan9118var.h	28 Nov 2009 08:44:00 -0000	1.2
+++ dev/ic/lan9118var.h	31 Oct 2011 04:29:14 -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: 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
--- dev/ic/lancevar.h	4 Sep 2009 16:21:24 -0000	1.13
+++ dev/ic/lancevar.h	31 Oct 2011 04:29:14 -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: 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
--- dev/ic/lemacvar.h	11 Dec 2005 12:21:27 -0000	1.9
+++ dev/ic/lemacvar.h	31 Oct 2011 04:29:14 -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: 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
--- dev/ic/mb86950var.h	12 May 2009 14:25:17 -0000	1.5
+++ dev/ic/mb86950var.h	31 Oct 2011 04:29:14 -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: 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
--- dev/ic/mb86960var.h	12 May 2009 14:25:17 -0000	1.37
+++ dev/ic/mb86960var.h	31 Oct 2011 04:29:14 -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: 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
--- dev/ic/mtd803var.h	28 Apr 2008 20:23:50 -0000	1.6
+++ dev/ic/mtd803var.h	31 Oct 2011 04:29:14 -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: 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
--- dev/ic/pckbc.c	8 Aug 2010 09:33:05 -0000	1.51
+++ dev/ic/pckbc.c	31 Oct 2011 04:29:14 -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: 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
--- dev/ic/rtl81x9var.h	27 Jul 2010 21:02:00 -0000	1.50
+++ dev/ic/rtl81x9var.h	31 Oct 2011 04:29:14 -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: 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
--- dev/ic/seeq8005var.h	7 Nov 2001 20:01:58 -0000	1.5
+++ dev/ic/seeq8005var.h	31 Oct 2011 04:29:14 -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: 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
--- dev/ic/smc91cxxvar.h	12 May 2009 14:25:18 -0000	1.16
+++ dev/ic/smc91cxxvar.h	31 Oct 2011 04:29:14 -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: 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
--- dev/ic/tulipvar.h	9 Jul 2011 23:18:05 -0000	1.65
+++ dev/ic/tulipvar.h	31 Oct 2011 04:29:15 -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: 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
--- dev/isa/fdvar.h	28 Apr 2008 20:23:52 -0000	1.6
+++ dev/isa/fdvar.h	31 Oct 2011 04:29:15 -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: 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
--- dev/isa/if_eg.c	5 Apr 2010 07:20:24 -0000	1.82
+++ dev/isa/if_eg.c	31 Oct 2011 04:29:15 -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: 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
--- dev/isa/if_el.c	5 Apr 2010 07:20:24 -0000	1.86
+++ dev/isa/if_el.c	31 Oct 2011 04:29:15 -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: 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
--- dev/isa/if_iy.c	5 Apr 2010 07:20:24 -0000	1.88
+++ dev/isa/if_iy.c	31 Oct 2011 04:29:15 -0000
@@ -129,7 +129,7 @@
 #endif
 
 #if NRND > 0
-	rndsource_element_t rnd_source;
+	krndsource_t rnd_source;
 #endif
 };
 
Index: 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
--- dev/marvell/if_gfevar.h	28 Apr 2010 13:51:56 -0000	1.10
+++ dev/marvell/if_gfevar.h	31 Oct 2011 04:29:15 -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: 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
--- dev/marvell/if_mvgbe.c	6 Sep 2011 19:38:23 -0000	1.13
+++ dev/marvell/if_mvgbe.c	31 Oct 2011 04:29:15 -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: 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
--- dev/mca/edvar.h	4 May 2008 13:11:14 -0000	1.13
+++ dev/mca/edvar.h	31 Oct 2011 04:29:15 -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: 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
--- dev/pci/amdpmvar.h	28 Apr 2008 20:23:54 -0000	1.6
+++ dev/pci/amdpmvar.h	31 Oct 2011 04:29:16 -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: 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
--- dev/pci/hifn7751.c	13 Nov 2010 13:52:05 -0000	1.46
+++ dev/pci/hifn7751.c	31 Oct 2011 04:29:16 -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: 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
--- dev/pci/hifn7751var.h	11 Dec 2005 12:22:49 -0000	1.7
+++ dev/pci/hifn7751var.h	31 Oct 2011 04:29:16 -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: 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
--- dev/pci/if_bce.c	13 Nov 2010 13:52:05 -0000	1.33
+++ dev/pci/if_bce.c	31 Oct 2011 04:29:16 -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: 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
--- dev/pci/if_bgevar.h	18 May 2011 01:02:43 -0000	1.7
+++ dev/pci/if_bgevar.h	31 Oct 2011 04:29:16 -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: 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
--- dev/pci/if_casvar.h	18 Jan 2010 18:09:22 -0000	1.2
+++ dev/pci/if_casvar.h	31 Oct 2011 04:29:16 -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: 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
--- dev/pci/if_devar.h	5 Apr 2010 07:20:25 -0000	1.55
+++ dev/pci/if_devar.h	31 Oct 2011 04:29:17 -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: 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
--- dev/pci/if_dge.c	13 Nov 2010 13:52:06 -0000	1.31
+++ dev/pci/if_dge.c	31 Oct 2011 04:29:17 -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: 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
--- dev/pci/if_iwi.c	23 May 2011 15:37:36 -0000	1.87
+++ dev/pci/if_iwi.c	31 Oct 2011 04:29:17 -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: 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
--- dev/pci/if_jme.c	30 Mar 2011 18:11:37 -0000	1.17
+++ dev/pci/if_jme.c	31 Oct 2011 04:29:17 -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: 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
--- dev/pci/if_mskvar.h	24 Dec 2009 18:27:32 -0000	1.8
+++ dev/pci/if_mskvar.h	31 Oct 2011 04:29:17 -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: 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
--- dev/pci/if_pcn.c	13 Nov 2010 13:52:06 -0000	1.52
+++ dev/pci/if_pcn.c	31 Oct 2011 04:29:18 -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: 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
--- dev/pci/if_sip.c	15 Oct 2011 19:50:20 -0000	1.150
+++ dev/pci/if_sip.c	31 Oct 2011 04:29:19 -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: 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
--- dev/pci/if_skvar.h	8 Sep 2008 21:20:03 -0000	1.15
+++ dev/pci/if_skvar.h	31 Oct 2011 04:29:19 -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: 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
--- dev/pci/if_tlvar.h	19 Oct 2009 18:41:15 -0000	1.14
+++ dev/pci/if_tlvar.h	31 Oct 2011 04:29:19 -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: 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
--- dev/pci/if_vr.c	16 Dec 2010 17:07:44 -0000	1.107
+++ dev/pci/if_vr.c	31 Oct 2011 04:29:19 -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: 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
--- dev/pci/if_vtevar.h	26 Jan 2011 18:48:13 -0000	1.1
+++ dev/pci/if_vtevar.h	31 Oct 2011 04:29:19 -0000
@@ -139,7 +139,7 @@
 	int			vte_int_tx_mod;
 
 #if NRND > 0
-	rndsource_element_t	rnd_source;
+	krndsource_t	rnd_source;
 #endif
 };
 
Index: 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
--- dev/pci/if_wm.c	1 Jul 2011 07:45:39 -0000	1.223
+++ dev/pci/if_wm.c	31 Oct 2011 04:29:20 -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: 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
--- dev/pci/ubsec.c	13 Nov 2010 13:52:09 -0000	1.25
+++ dev/pci/ubsec.c	31 Oct 2011 04:29:20 -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: 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
--- dev/pci/ixgbe/ixgbe.c	12 Aug 2011 21:55:29 -0000	1.1
+++ dev/pci/ixgbe/ixgbe.c	31 Oct 2011 04:29:21 -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: 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
--- dev/pcmcia/if_xivar.h	6 Dec 2009 23:05:39 -0000	1.6
+++ dev/pcmcia/if_xivar.h	31 Oct 2011 04:29:21 -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: 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
--- dev/scsipi/cdvar.h	19 Oct 2009 18:41:16 -0000	1.29
+++ dev/scsipi/cdvar.h	31 Oct 2011 04:29:21 -0000
@@ -48,6 +48,6 @@
 	struct callout sc_callout;
 
 #if NRND > 0
-	rndsource_element_t	rnd_source;
+	krndsource_t	rnd_source;
 #endif
 };
Index: 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
--- dev/scsipi/sdvar.h	10 Apr 2009 17:36:42 -0000	1.32
+++ dev/scsipi/sdvar.h	31 Oct 2011 04:29:21 -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: 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
--- dev/scsipi/stvar.h	6 Dec 2009 22:48:17 -0000	1.21
+++ dev/scsipi/stvar.h	31 Oct 2011 04:29:21 -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: 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
--- dev/usb/if_auereg.h	4 Sep 2009 18:10:08 -0000	1.23
+++ dev/usb/if_auereg.h	31 Oct 2011 04:29:21 -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: 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
--- dev/usb/if_axereg.h	14 Aug 2010 10:47:57 -0000	1.12
+++ dev/usb/if_axereg.h	31 Oct 2011 04:29:21 -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: 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
--- dev/usb/if_cdcereg.h	4 Sep 2009 18:10:08 -0000	1.5
+++ dev/usb/if_cdcereg.h	31 Oct 2011 04:29:21 -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: 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
--- dev/usb/if_cuereg.h	4 Sep 2009 18:10:08 -0000	1.16
+++ dev/usb/if_cuereg.h	31 Oct 2011 04:29:21 -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: 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
--- dev/usb/if_kuereg.h	3 Nov 2010 22:30:50 -0000	1.16
+++ dev/usb/if_kuereg.h	31 Oct 2011 04:29:21 -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: 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
--- dev/usb/if_udavreg.h	3 Nov 2010 22:30:50 -0000	1.6
+++ dev/usb/if_udavreg.h	31 Oct 2011 04:29:21 -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: 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
--- dev/usb/if_upl.c	3 Nov 2010 22:28:31 -0000	1.38
+++ dev/usb/if_upl.c	31 Oct 2011 04:29:21 -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: 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
--- dev/usb/if_urlreg.h	3 Nov 2010 22:30:50 -0000	1.6
+++ dev/usb/if_urlreg.h	31 Oct 2011 04:29:21 -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: 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
--- dev/usb/ucom.c	24 Apr 2011 16:27:01 -0000	1.87
+++ dev/usb/ucom.c	31 Oct 2011 04:29:22 -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: 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
--- dev/usb/uhidev.h	3 Nov 2010 22:34:24 -0000	1.10
+++ dev/usb/uhidev.h	31 Oct 2011 04:29:22 -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: 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
--- dist/pf/net/pf.c	29 Aug 2011 09:50:04 -0000	1.66
+++ dist/pf/net/pf.c	31 Oct 2011 04:29:22 -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: 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
--- dist/pf/netinet/tcp_rndiss.c	18 Jun 2008 09:06:27 -0000	1.2
+++ dist/pf/netinet/tcp_rndiss.c	31 Oct 2011 04:29:22 -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: 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
--- fs/tmpfs/tmpfs_subr.c	27 Aug 2011 15:32:28 -0000	1.77
+++ fs/tmpfs/tmpfs_subr.c	31 Oct 2011 04:29:23 -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: 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
--- kern/exec_elf.c	27 Aug 2011 17:53:21 -0000	1.32
+++ kern/exec_elf.c	31 Oct 2011 04:29:23 -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: 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
--- kern/init_main.c	28 Sep 2011 15:52:47 -0000	1.436
+++ kern/init_main.c	31 Oct 2011 04:29:23 -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: 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
--- kern/init_sysctl.c	30 Aug 2011 12:39:59 -0000	1.183
+++ kern/init_sysctl.c	31 Oct 2011 04:29:23 -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: 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
--- kern/kern_exec.c	16 Sep 2011 21:02:28 -0000	1.329
+++ kern/kern_exec.c	31 Oct 2011 04:29:24 -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: 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
--- kern/kern_pax.c	24 Apr 2011 18:46:22 -0000	1.25
+++ kern/kern_pax.c	31 Oct 2011 04:29:24 -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: 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
--- kern/kern_ssp.c	1 Feb 2010 16:14:58 -0000	1.5
+++ kern/kern_ssp.c	31 Oct 2011 04:29:24 -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: 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
--- kern/kern_sysctl.c	5 Oct 2011 13:24:09 -0000	1.232
+++ kern/kern_sysctl.c	31 Oct 2011 04:29:24 -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_NONE);
 	sysctl_root.sysctl_flags |= CTLFLAG_PERMANENT;
 }
 
Index: 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
--- kern/kern_uuid.c	4 May 2010 19:23:56 -0000	1.17
+++ kern/kern_uuid.c	31 Oct 2011 04:29:24 -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: kern/subr_cprng.c
===================================================================
RCS file: kern/subr_cprng.c
diff -N kern/subr_cprng.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ kern/subr_cprng.c	31 Oct 2011 04:29:24 -0000
@@ -0,0 +1,186 @@
+/*	$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;
+	}
+	microtime(&tv);
+	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, getmore = 0;;
+	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);
+	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);
+		getmore++;
+	}
+		
+	if (nist_ctr_drbg_instantiate(&c->drbg, key, sizeof(key),
+				      &cc, sizeof(cc), name, strlen(name))) {
+		panic("cprng %s: instantiation failed.", name);
+	}
+
+	if (getmore) {
+		/* Ask for more. */
+		c->reseed.len = sizeof(key);
+		rndsink_attach(&c->reseed);
+	}
+	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;
+
+		strncpy(rt.rt_name, c->name, sizeof(rt.rt_name));
+
+		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: kern/subr_rngtest.c
===================================================================
RCS file: kern/subr_rngtest.c
diff -N kern/subr_rngtest.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ kern/subr_rngtest.c	31 Oct 2011 04:29:24 -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: 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
--- lib/libkern/arc4random.c	18 Jan 2010 20:54:54 -0000	1.21
+++ lib/libkern/arc4random.c	31 Oct 2011 04:29:24 -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,73 @@
  * 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;
-
 #if NRND > 0	/* XXX without rnd, we will key from the stack, ouch! */
-	r = rnd_extract_data(key, ARC4_KEYBYTES, RND_EXTRACT_GOOD);
+	/*
+	 * The first time through, we must take what we can get,
+	 * so schedule ourselves for callback no matter what.
+	 */
+	if (!arc4_initialized) {
+		ask_for_more = 1;
+		r = rnd_extract_data(key, ARC4_KEYBYTES, RND_EXTRACT_ANY);
+		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;
+		ask_for_more = 0;
+		if (rs.len != ARC4_KEYBYTES) {
+			panic("arc4_randrekey: rekey callback bad length");
 		}
+		memcpy(key, rs.data, rs.len);
 	}
+#endif
 
-	cur_keybytes = r;
+got_entropy:
+	if (__predict_true(arc4_initialized)) {
+		mutex_spin_enter(&arc4_mtx);
+	}
+	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);
+	} else {
+		callback_pending = 0;
+	}
 
+	/*
+	 * 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 +200,28 @@
 	 */
 	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
+	}
+	if (__predict_true(arc4_initialized)) {
+		mutex_spin_exit(&arc4_mtx);
+	}
 }
 
 /*
@@ -159,11 +232,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 +261,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: 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
--- net/if_bridge.c	23 May 2011 21:52:54 -0000	1.73
+++ net/if_bridge.c	31 Oct 2011 04:29:25 -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: net/if_spppsubr.c
===================================================================
RCS file: /cvsroot/src/sys/net/if_spppsubr.c,v
retrieving revision 1.123
diff -u -b -r1.123 if_spppsubr.c
--- net/if_spppsubr.c	28 Oct 2011 22:08:14 -0000	1.123
+++ net/if_spppsubr.c	31 Oct 2011 04:29:25 -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>
@@ -1202,7 +1203,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;
@@ -2481,7 +2482,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)
@@ -2665,7 +2666,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;
@@ -4229,7 +4230,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);
 	}
@@ -4286,7 +4287,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 */
@@ -4297,11 +4298,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: 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
--- net/npf/npf_nat.c	2 Feb 2011 02:20:25 -0000	1.6
+++ net/npf/npf_nat.c	31 Oct 2011 04:29:25 -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: 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
--- net80211/ieee80211_netbsd.c	7 Oct 2011 16:51:45 -0000	1.19
+++ net80211/ieee80211_netbsd.c	31 Oct 2011 04:29:25 -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: netinet/in.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/in.c,v
retrieving revision 1.140
diff -u -b -r1.140 in.c
--- netinet/in.c	28 Oct 2011 22:23:54 -0000	1.140
+++ netinet/in.c	31 Oct 2011 04:29:26 -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>
 
@@ -401,7 +403,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: 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
--- netinet/ip_carp.c	19 Oct 2011 01:52:22 -0000	1.46
+++ netinet/ip_carp.c	31 Oct 2011 04:29:26 -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: 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
--- netinet/ip_id.c	5 Nov 2010 01:35:57 -0000	1.14
+++ netinet/ip_id.c	31 Oct 2011 04:29:26 -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: netinet/rfc6056.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/rfc6056.c,v
retrieving revision 1.3
diff -u -b -r1.3 rfc6056.c
--- netinet/rfc6056.c	25 Sep 2011 11:54:28 -0000	1.3
+++ netinet/rfc6056.c	31 Oct 2011 04:29:26 -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: 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
--- netinet/tcp_input.c	31 Aug 2011 18:31:03 -0000	1.316
+++ netinet/tcp_input.c	31 Oct 2011 04:29:27 -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: 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
--- netinet/tcp_subr.c	3 May 2011 18:28:45 -0000	1.241
+++ netinet/tcp_subr.c	31 Oct 2011 04:29:27 -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: netinet6/files.ipsec
===================================================================
RCS file: /cvsroot/src/sys/netinet6/files.ipsec,v
retrieving revision 1.5
diff -u -b -r1.5 files.ipsec
--- netinet6/files.ipsec	27 Oct 2006 21:20:48 -0000	1.5
+++ netinet6/files.ipsec	31 Oct 2011 04:29:27 -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: netinet6/in6.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/in6.c,v
retrieving revision 1.158
diff -u -b -r1.158 in6.c
--- netinet6/in6.c	19 Oct 2011 01:53:07 -0000	1.158
+++ netinet6/in6.c	31 Oct 2011 04:29:27 -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: 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
--- netinet6/in6_ifattach.c	19 Sep 2009 13:11:02 -0000	1.85
+++ netinet6/in6_ifattach.c	31 Oct 2011 04:29:28 -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>
@@ -177,7 +178,6 @@
 {
 	MD5_CTX ctxt;
 	u_int8_t seed[16], digest[16], nullbuf[8];
-	u_int32_t val32;
 	/*
 	 * interface ID for subnet anycast addresses.
 	 * XXX: we assume the unicast address range that requires IDs
@@ -191,12 +191,7 @@
 	/* If there's no hisotry, start with a random seed. */
 	memset(nullbuf, 0, sizeof(nullbuf));
 	if (memcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) {
-		int i;
-
-		for (i = 0; i < 2; i++) {
-			val32 = arc4random();
-			memcpy(seed + sizeof(val32) * i, &val32, sizeof(val32));
-		}
+		cprng_fast(seed, sizeof(seed));
 	} else
 		memcpy(seed, seed0, 8);
 
Index: 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
--- netinet6/ip6_id.c	30 Aug 2006 17:11:53 -0000	1.16
+++ netinet6/ip6_id.c	31 Oct 2011 04:29:28 -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: 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
--- netinet6/ip6_input.c	1 Jun 2011 22:59:44 -0000	1.132
+++ netinet6/ip6_input.c	31 Oct 2011 04:29:28 -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: netinet6/mld6.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/mld6.c,v
retrieving revision 1.54
diff -u -b -r1.54 mld6.c
--- netinet6/mld6.c	19 Oct 2011 01:53:07 -0000	1.54
+++ netinet6/mld6.c	31 Oct 2011 04:29:28 -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: 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
--- netinet6/mld6_var.h	1 Nov 2007 20:33:58 -0000	1.9
+++ netinet6/mld6_var.h	31 Oct 2011 04:29:28 -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: netinet6/nd6.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/nd6.c,v
retrieving revision 1.136
diff -u -b -r1.136 nd6.c
--- netinet6/nd6.c	15 Jul 2010 19:15:30 -0000	1.136
+++ netinet6/nd6.c	31 Oct 2011 04:29:29 -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: netinet6/nd6.h
===================================================================
RCS file: /cvsroot/src/sys/netinet6/nd6.h,v
retrieving revision 1.54
diff -u -b -r1.54 nd6.h
--- netinet6/nd6.h	24 May 2011 18:07:11 -0000	1.54
+++ netinet6/nd6.h	31 Oct 2011 04:29:29 -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: 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
--- netinet6/nd6_rtr.c	24 May 2011 18:07:11 -0000	1.81
+++ netinet6/nd6_rtr.c	31 Oct 2011 04:29:29 -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: netkey/key.c
===================================================================
RCS file: /cvsroot/src/sys/netkey/key.c,v
retrieving revision 1.179
diff -u -b -r1.179 key.c
--- netkey/key.c	17 Jul 2011 20:54:54 -0000	1.179
+++ netkey/key.c	31 Oct 2011 04:29:30 -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: 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
--- nfs/nfs_subs.c	12 Jun 2011 03:35:59 -0000	1.221
+++ nfs/nfs_subs.c	31 Oct 2011 04:29:30 -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: opencrypto/files.opencrypto
===================================================================
RCS file: /cvsroot/src/sys/opencrypto/files.opencrypto,v
retrieving revision 1.24
diff -u -b -r1.24 files.opencrypto
--- opencrypto/files.opencrypto	26 May 2011 21:50:03 -0000	1.24
+++ opencrypto/files.opencrypto	31 Oct 2011 04:29:30 -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: 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
--- rump/dev/lib/librnd/Makefile	16 Feb 2010 20:42:45 -0000	1.2
+++ rump/dev/lib/librnd/Makefile	31 Oct 2011 04:29:30 -0000
@@ -5,7 +5,7 @@
 
 LIB=	rumpdev_rnd
 
-SRCS=   rnd.c rndpool.c
+#SRCS=   rnd.c rndpool.c
 
 SRCS+=	component.c
 
Index: 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
--- rump/librump/rumpkern/Makefile.rumpkern	12 Jun 2011 06:36:38 -0000	1.110
+++ rump/librump/rumpkern/Makefile.rumpkern	31 Oct 2011 04:29:30 -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: rump/librump/rumpkern/cprng_stub.c
===================================================================
RCS file: rump/librump/rumpkern/cprng_stub.c
diff -N rump/librump/rumpkern/cprng_stub.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ rump/librump/rumpkern/cprng_stub.c	31 Oct 2011 04:29:30 -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: 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
--- rump/librump/rumpkern/rump.c	22 Mar 2011 15:16:23 -0000	1.234
+++ rump/librump/rumpkern/rump.c	31 Oct 2011 04:29:30 -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: 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
--- rump/librump/rumpvfs/rumpblk.c	3 Feb 2011 22:16:11 -0000	1.46
+++ rump/librump/rumpvfs/rumpblk.c	31 Oct 2011 04:29:31 -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: 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
--- rump/net/lib/libshmif/if_shmem.c	2 Sep 2011 22:25:08 -0000	1.43
+++ rump/net/lib/libshmif/if_shmem.c	31 Oct 2011 04:29:31 -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: 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
--- rump/net/lib/libvirtif/if_virt.c	7 Aug 2011 14:03:16 -0000	1.24
+++ rump/net/lib/libvirtif/if_virt.c	31 Oct 2011 04:29:31 -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/cprng.h
===================================================================
RCS file: sys/cprng.h
diff -N sys/cprng.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/cprng.h	31 Oct 2011 04:29:31 -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/queue.h
===================================================================
RCS file: /cvsroot/src/sys/sys/queue.h,v
retrieving revision 1.52
diff -u -b -r1.52 queue.h
--- sys/queue.h	20 Apr 2009 09:56:08 -0000	1.52
+++ sys/queue.h	31 Oct 2011 04:29:31 -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/rnd.h
===================================================================
RCS file: /cvsroot/src/sys/sys/rnd.h,v
retrieving revision 1.21
diff -u -b -r1.21 rnd.h
--- sys/rnd.h	28 Apr 2008 20:24:11 -0000	1.21
+++ sys/rnd.h	31 Oct 2011 04:29:31 -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);
@@ -144,17 +160,18 @@
 uint32_t	*rndpool_get_pool(rndpool_t *);
 uint32_t	rndpool_get_poolsize(void);
 void		rndpool_add_data(rndpool_t *, void *, uint32_t, uint32_t);
-uint32_t	rndpool_extract_data(rndpool_t *, void *, uint32_t,
-		    uint32_t);
-
+uint32_t	rndpool_extract_data(rndpool_t *, void *, uint32_t, 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 *, const void *const, 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/rngtest.h
===================================================================
RCS file: sys/rngtest.h
diff -N sys/rngtest.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/rngtest.h	31 Oct 2011 04:29:31 -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/sysctl.h
===================================================================
RCS file: /cvsroot/src/sys/sys/sysctl.h,v
retrieving revision 1.197
diff -u -b -r1.197 sysctl.h
--- sys/sysctl.h	21 Oct 2011 02:07:07 -0000	1.197
+++ sys/sysctl.h	31 Oct 2011 04:29:31 -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: 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
--- ufs/ffs/ffs_appleufs.c	22 Jun 2011 04:01:33 -0000	1.11
+++ ufs/ffs/ffs_appleufs.c	31 Oct 2011 04:29:31 -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);
