changeset 13908:3e3d92153ccf

995 boot message: No randomness provider enabled for /dev/random Reviewed by: Garrett D'Amore <garrett@damore.org> Reviewed by: Dan McDonald <danmcd@nexenta.com> Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com> Reviewed by: Boris Protopopov <boris.protopopov@nexenta.com> Approved by: Garrett D'Amore <garrett@damore.org>
author Gordon Ross <gwr@nexenta.com>
date Thu, 20 Dec 2012 23:45:23 -0500
parents 2adac9f6b5e6
children ee64943ff115
files usr/src/uts/common/crypto/api/kcf_random.c usr/src/uts/common/crypto/core/kcf.c usr/src/uts/common/sys/crypto/impl.h
diffstat 3 files changed, 57 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/crypto/api/kcf_random.c	Thu Dec 20 02:04:26 2012 +0000
+++ b/usr/src/uts/common/crypto/api/kcf_random.c	Thu Dec 20 23:45:23 2012 -0500
@@ -20,9 +20,7 @@
  */
 /*
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-/*
- * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -124,8 +122,14 @@
 static void rndc_addbytes(uint8_t *, size_t);
 static void rndc_getbytes(uint8_t *ptr, size_t len);
 static void rnd_handler(void *);
-static void rnd_alloc_magazines();
+static void rnd_alloc_magazines(void);
+static void rnd_fips_discard_initial(void);
+static void rnd_init2(void *);
+static void rnd_schedule_timeout(void);
 
+/*
+ * Called from kcf:_init()
+ */
 void
 kcf_rnd_init()
 {
@@ -151,9 +155,37 @@
 	rnbyte_cnt = 0;
 	findex = rindex = 0;
 	num_waiters = 0;
-	rngmech_type = KCF_MECHID(KCF_MISC_CLASS, 0);
 
 	rnd_alloc_magazines();
+
+	(void) taskq_dispatch(system_taskq, rnd_init2, NULL, TQ_SLEEP);
+}
+
+/*
+ * This is called via the system taskq, so that we can do further
+ * initializations that have to wait until the kcf module itself is
+ * done loading.  (After kcf:_init returns.)
+ */
+static void
+rnd_init2(void *unused)
+{
+
+	_NOTE(ARGUNUSED(unused));
+
+	/*
+	 * This will load a randomness provider; typically "swrand",
+	 * but could be another provider if so configured.
+	 */
+	rngmech_type = crypto_mech2id(SUN_RANDOM);
+
+	/* Update rng_prov_found etc. */
+	(void) kcf_rngprov_check();
+
+	/* FIPS 140-2 init. */
+	rnd_fips_discard_initial();
+
+	/* Start rnd_handler calls. */
+	rnd_schedule_timeout();
 }
 
 /*
@@ -786,7 +818,6 @@
 {
 	rndmag_pad_t *rmp;
 	int i;
-	uint8_t discard_buf[HASHSIZE];
 
 	rndbuf_len = roundup(rndbuf_len, HASHSIZE);
 	if (rndmag_size < rndbuf_len)
@@ -812,13 +843,26 @@
 		rmp->rm_mag.rm_eptr = buf + rndbuf_len;
 		rmp->rm_mag.rm_rptr = buf + rndbuf_len;
 		rmp->rm_mag.rm_oblocks = 1;
+	}
+}
 
+/*
+ * FIPS 140-2: the first n-bit (n > 15) block generated
+ * after power-up, initialization, or reset shall not
+ * be used, but shall be saved for comparison.
+ */
+static void
+rnd_fips_discard_initial(void)
+{
+	uint8_t discard_buf[HASHSIZE];
+	rndmag_pad_t *rmp;
+	int i;
+
+	for (i = 0; i < random_max_ncpus; i++) {
+		rmp = &rndmag[i];
+
+		/* rnd_get_bytes() will call mutex_exit(&rndpool_lock) */
 		mutex_enter(&rndpool_lock);
-		/*
-		 * FIPS 140-2: the first n-bit (n > 15) block generated
-		 * after power-up, initialization, or reset shall not
-		 * be used, but shall be saved for comparison.
-		 */
 		(void) rnd_get_bytes(discard_buf,
 		    HMAC_KEYSIZE, ALWAYS_EXTRACT);
 		bcopy(discard_buf, rmp->rm_mag.rm_previous,
@@ -835,22 +879,10 @@
 }
 
 static void
-rnd_mechid(void *notused)
-{
-	_NOTE(ARGUNUSED(notused));
-	rngmech_type = crypto_mech2id(SUN_RANDOM);
-}
-
-void
-kcf_rnd_schedule_timeout(boolean_t do_mech2id)
+rnd_schedule_timeout(void)
 {
 	clock_t ut;	/* time in microseconds */
 
-	if (do_mech2id) {
-		/* This should never fail due to TQ_SLEEP. */
-		(void) taskq_dispatch(system_taskq, rnd_mechid, NULL, TQ_SLEEP);
-	}
-
 	/*
 	 * The new timeout value is taken from the buffer of random bytes.
 	 * We're merely reading the first 32 bits from the buffer here, not
@@ -957,7 +989,7 @@
 		cv_broadcast(&rndpool_read_cv);
 	mutex_exit(&rndpool_lock);
 
-	kcf_rnd_schedule_timeout(B_FALSE);
+	rnd_schedule_timeout();
 }
 
 static void
--- a/usr/src/uts/common/crypto/core/kcf.c	Thu Dec 20 02:04:26 2012 +0000
+++ b/usr/src/uts/common/crypto/core/kcf.c	Thu Dec 20 23:45:23 2012 -0500
@@ -92,8 +92,6 @@
 	/* initialize the RNG support structures */
 	kcf_rnd_init();
 
-	kcf_rnd_schedule_timeout(B_TRUE);
-
 	return (mod_install(&modlinkage));
 }
 
--- a/usr/src/uts/common/sys/crypto/impl.h	Thu Dec 20 02:04:26 2012 +0000
+++ b/usr/src/uts/common/sys/crypto/impl.h	Thu Dec 20 23:45:23 2012 -0500
@@ -1344,7 +1344,6 @@
 extern int kcf_rnd_get_bytes(uint8_t *, size_t, boolean_t);
 extern int random_add_pseudo_entropy(uint8_t *, size_t, uint_t);
 extern void kcf_rnd_chpoll(short, int, short *, struct pollhead **);
-extern void kcf_rnd_schedule_timeout(boolean_t);
 extern int crypto_uio_data(crypto_data_t *, uchar_t *, int, cmd_type_t,
     void *, void (*update)());
 extern int crypto_mblk_data(crypto_data_t *, uchar_t *, int, cmd_type_t,