Module Name:    src
Committed By:   tls
Date:           Sun Mar  4 00:36:43 UTC 2012

Modified Files:
        src/lib/libc/gen: arc4random.c

Log Message:
Fix bug in previous: don't reinitialize on every call!  Fix arc4random_buf so 
it actually ever initializes -- a security problem with revisions 1.9 and 1.10.


To generate a diff of this commit:
cvs rdiff -u -r1.11 -r1.12 src/lib/libc/gen/arc4random.c

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

Modified files:

Index: src/lib/libc/gen/arc4random.c
diff -u src/lib/libc/gen/arc4random.c:1.11 src/lib/libc/gen/arc4random.c:1.12
--- src/lib/libc/gen/arc4random.c:1.11	Mon Feb 27 04:25:12 2012
+++ src/lib/libc/gen/arc4random.c	Sun Mar  4 00:36:43 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: arc4random.c,v 1.11 2012/02/27 04:25:12 tls Exp $	*/
+/*	$NetBSD: arc4random.c,v 1.12 2012/03/04 00:36:43 tls Exp $	*/
 /*	$OpenBSD: arc4random.c,v 1.6 2001/06/05 05:05:38 pvalchev Exp $	*/
 
 /*
@@ -27,7 +27,7 @@
 
 #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: arc4random.c,v 1.11 2012/02/27 04:25:12 tls Exp $");
+__RCSID("$NetBSD: arc4random.c,v 1.12 2012/03/04 00:36:43 tls Exp $");
 #endif /* LIBC_SCCS and not lint */
 
 #include "namespace.h"
@@ -46,12 +46,12 @@ __weak_alias(arc4random,_arc4random)
 
 struct arc4_stream {
 	mutex_t mtx;
+	int initialized;
 	uint8_t i;
 	uint8_t j;
 	uint8_t s[256];
 };
 
-static int rs_initialized;
 /* XXX lint explodes with an internal error if only mtx is initialized! */
 static struct arc4_stream rs = { .i = 0, .mtx = MUTEX_INITIALIZER };
 
@@ -70,6 +70,9 @@ arc4_init(struct arc4_stream *as)
 		as->s[n] = n;
 	as->i = 0;
 	as->j = 0;
+
+	as->initialized = 1;
+	arc4_stir(as);
 }
 
 static inline void
@@ -155,11 +158,11 @@ arc4_getword(struct arc4_stream *as)
 static inline void
 _arc4random_stir_unlocked(void)
 {
-	if (!rs_initialized) {
-		arc4_init(&rs);
-		rs_initialized = 1;
+	if (__predict_false(!rs.initialized)) {
+		arc4_init(&rs);				/* stirs */
+	} else {
+		arc4_stir(&rs);
 	}
-	arc4_stir(&rs);
 }
 
 void
@@ -179,8 +182,9 @@ arc4random_stir(void)
 static inline void
 _arc4random_addrandom_unlocked(u_char *dat, int datlen)
 {
-	if (!rs_initialized)
-		arc4_stir(&rs);
+	if (__predict_false(rs.initialized)) {
+		arc4_init(&rs);
+	}
 	arc4_addrandom(&rs, dat, datlen);
 }
 
@@ -201,8 +205,9 @@ arc4random_addrandom(u_char *dat, int da
 static inline uint32_t
 _arc4random_unlocked(void)
 {
-	if (!rs_initialized)
-		arc4_stir(&rs);
+	if (__predict_false(!rs.initialized)) {
+		arc4_init(&rs);
+	}
 	return arc4_getword(&rs);
 }
 
@@ -228,6 +233,10 @@ _arc4random_buf_unlocked(void *buf, size
 	uint8_t *bp = buf;
 	uint8_t *ep = bp + len;
 
+	if (__predict_false(!rs.initialized)) {
+		arc4_init(&rs);
+	}
+
 	bp[0] = arc4_getbyte(&rs) % 3;
 	while (bp[0]--)
 		(void)arc4_getbyte(&rs);
@@ -292,8 +301,9 @@ _arc4random_uniform_unlocked(uint32_t up
 	 * number inside the range we need, so it should rarely need
 	 * to re-roll (at all).
 	 */
-	if (!rs_initialized)
-		arc4_stir(&rs);
+	if (__predict_false(!rs.initialized)) {
+		arc4_init(&rs);
+	}
 	if (arc4_getbyte(&rs) & 1)
 		(void)arc4_getbyte(&rs);
 	do

Reply via email to