Module Name:    src
Committed By:   tls
Date:           Thu Jun 13 19:18:00 UTC 2013

Modified Files:
        src/sys/kern: kern_rndpool.c

Log Message:
Correct use of entropy estimate when data are extracted from the pool.

The "threshold" value was being inappropriately used to limit how many
bytes could be output even after the estimator said enough bytes had
been put in to meet our minimum security guarantee.

This fixes a panic observed with the automatic test harness and by
msaitoh, where it was not possible to extract the full estimate's worth
of bytes even holding the pool lock across the estimate and extract
calls.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/kern/kern_rndpool.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/kern_rndpool.c
diff -u src/sys/kern/kern_rndpool.c:1.3 src/sys/kern/kern_rndpool.c:1.4
--- src/sys/kern/kern_rndpool.c:1.3	Thu Jun 13 00:55:01 2013
+++ src/sys/kern/kern_rndpool.c	Thu Jun 13 19:18:00 2013
@@ -1,4 +1,4 @@
-/*      $NetBSD: kern_rndpool.c,v 1.3 2013/06/13 00:55:01 tls Exp $        */
+/*      $NetBSD: kern_rndpool.c,v 1.4 2013/06/13 19:18:00 tls Exp $        */
 
 /*-
  * Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_rndpool.c,v 1.3 2013/06/13 00:55:01 tls Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_rndpool.c,v 1.4 2013/06/13 19:18:00 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -57,6 +57,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_rndpool
 int rnd_full = 0;			/* Flag: is the pool full? */
 int rnd_filled = 0;			/* Count: how many times filled? */
 int rnd_empty = 1;			/* Flag: is the pool empty? */
+extern int	rnd_initial_entropy;	/* Have ever hit the "threshold" */
 
 static inline void rndpool_add_one_word(rndpool_t *, u_int32_t);
 
@@ -235,8 +236,11 @@ rndpool_add_data(rndpool_t *rp, void *p,
  * the hash are xored together before being returned.
  *
  * Honor the request from the caller to only return good data, any data,
- * etc.  Note that we must have at least 64 bits of entropy in the pool
- * before we return anything in the high-quality modes.
+ * etc.
+ *
+ * For the "high-quality" mode, we must have as much data as the caller
+ * requests, and at some point we must have had at least the "threshold"
+ * amount of entropy in the pool.
  */
 u_int32_t
 rndpool_extract_data(rndpool_t *rp, void *p, u_int32_t len, u_int32_t mode)
@@ -246,7 +250,6 @@ rndpool_extract_data(rndpool_t *rp, void
 	u_char digest[SHA1_DIGEST_LENGTH];
 	u_int32_t remain, deltae, count;
 	u_int8_t *buf;
-	int good;
 
 	buf = p;
 	remain = len;
@@ -255,14 +258,10 @@ rndpool_extract_data(rndpool_t *rp, void
 		rnd_full = 0;
 	}
 
-	if (mode == RND_EXTRACT_ANY)
-		good = 1;
-	else
-		good = (rp->stats.curentropy >= (8 * RND_ENTROPY_THRESHOLD));
-
 	KASSERT(RND_ENTROPY_THRESHOLD * 2 <= sizeof(digest));
 
-	while (good && (remain != 0)) {
+	while (remain != 0 && ! (mode == RND_EXTRACT_GOOD &&
+				 remain > rp->stats.curentropy * 8)) {
 		/*
 		 * While bytes are requested, compute the hash of the pool,
 		 * and then "fold" the hash in half with XOR, keeping the
@@ -289,6 +288,7 @@ rndpool_extract_data(rndpool_t *rp, void
 			rndpool_add_one_word(rp, word);
 		}
 
+		/* XXX careful, here the THRESHOLD just controls folding */
 		count = min(remain, RND_ENTROPY_THRESHOLD);
 
 		for (i = 0; i < count; i++)
@@ -306,9 +306,6 @@ rndpool_extract_data(rndpool_t *rp, void
 		if (rp->stats.curentropy == 0)
 			rp->stats.generated += (count * 8) - deltae;
 
-		if (mode == RND_EXTRACT_GOOD)
-			good = (rp->stats.curentropy >=
-			    (8 * RND_ENTROPY_THRESHOLD));
 	}
 
 	memset(&hash, 0, sizeof(hash));

Reply via email to