svn commit: r267380 - stable/8/lib/libc/gen

Xin LI delphij at FreeBSD.org
Thu Jun 12 00:19:06 UTC 2014


Author: delphij
Date: Thu Jun 12 00:19:05 2014
New Revision: 267380
URL: http://svnweb.freebsd.org/changeset/base/267380

Log:
  MFC r227519, r227520:
  
  r227519 (das)
  
  Sync the style, comments, and variable names of arc4random.c with
  OpenBSD's version (r1.22).  No functional changes, as verified with
  md5.
  
  r227520 (das)
  
  Further reduce diffs with OpenBSD's arc4random.  The main functional
  change here is to ensure that when a process forks after arc4random
  is seeded, the parent and child don't observe the same random sequence.
  OpenBSD's fix introduces some additional overhead in the form of a
  getpid() call.
  
  The only significant remaining difference between our arc4random and
  OpenBSD's is in how we seed the generator in arc4_stir().

Modified:
  stable/8/lib/libc/gen/arc4random.c
Directory Properties:
  stable/8/lib/libc/   (props changed)

Modified: stable/8/lib/libc/gen/arc4random.c
==============================================================================
--- stable/8/lib/libc/gen/arc4random.c	Thu Jun 12 00:15:07 2014	(r267379)
+++ stable/8/lib/libc/gen/arc4random.c	Thu Jun 12 00:19:05 2014	(r267380)
@@ -1,3 +1,5 @@
+/*	$OpenBSD: arc4random.c,v 1.22 2010/12/22 08:23:42 otto Exp $	*/
+
 /*
  * Copyright (c) 1996, David Mazieres <dm at uun.org>
  * Copyright (c) 2008, Damien Miller <djm at openbsd.org>
@@ -24,11 +26,6 @@
  * which is a trade secret).  The same algorithm is used as a stream
  * cipher called "arcfour" in Tatu Ylonen's ssh package.
  *
- * Here the stream cipher has been modified always to include the time
- * when initializing the state.  That makes it impossible to
- * regenerate the same random sequence twice, so this can't be used
- * for encryption, but will generate good random numbers.
- *
  * RC4 is a registered trademark of RSA Laboratories.
  */
 
@@ -36,16 +33,24 @@
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
-#include <sys/types.h>
-#include <sys/time.h>
-#include <stdlib.h>
 #include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
 #include <unistd.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
 #include <pthread.h>
 
 #include "libc_private.h"
 #include "un-namespace.h"
 
+#ifdef __GNUC__
+#define inline __inline
+#else				/* !__GNUC__ */
+#define inline
+#endif				/* !__GNUC__ */
+
 struct arc4_stream {
 	u_int8_t i;
 	u_int8_t j;
@@ -55,22 +60,22 @@ struct arc4_stream {
 static pthread_mutex_t	arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
 
 #define	RANDOMDEV	"/dev/random"
-#define KEYSIZE		128
-#define	THREAD_LOCK()						\
+#define	KEYSIZE		128
+#define	_ARC4_LOCK()						\
 	do {							\
 		if (__isthreaded)				\
 			_pthread_mutex_lock(&arc4random_mtx);	\
 	} while (0)
 
-#define	THREAD_UNLOCK()						\
+#define	_ARC4_UNLOCK()						\
 	do {							\
 		if (__isthreaded)				\
 			_pthread_mutex_unlock(&arc4random_mtx);	\
 	} while (0)
 
-static struct arc4_stream rs;
 static int rs_initialized;
-static int rs_stired;
+static struct arc4_stream rs;
+static pid_t arc4_stir_pid;
 static int arc4_count;
 
 static inline u_int8_t arc4_getbyte(void);
@@ -107,20 +112,24 @@ arc4_addrandom(u_char *dat, int datlen)
 static void
 arc4_stir(void)
 {
-	int done, fd, n;
+	int done, fd, i;
 	struct {
 		struct timeval	tv;
-		pid_t 		pid;
-		u_int8_t 	rnd[KEYSIZE];
+		pid_t		pid;
+		u_char	 	rnd[KEYSIZE];
 	} rdat;
 
+	if (!rs_initialized) {
+		arc4_init();
+		rs_initialized = 1;
+	}
 	fd = _open(RANDOMDEV, O_RDONLY, 0);
 	done = 0;
 	if (fd >= 0) {
 		if (_read(fd, &rdat, KEYSIZE) == KEYSIZE)
 			done = 1;
 		(void)_close(fd);
-	} 
+	}
 	if (!done) {
 		(void)gettimeofday(&rdat.tv, NULL);
 		rdat.pid = getpid();
@@ -130,17 +139,26 @@ arc4_stir(void)
 	arc4_addrandom((u_char *)&rdat, KEYSIZE);
 
 	/*
-	 * Throw away the first N bytes of output, as suggested in the
-	 * paper "Weaknesses in the Key Scheduling Algorithm of RC4"
-	 * by Fluher, Mantin, and Shamir.  N=1024 is based on
-	 * suggestions in the paper "(Not So) Random Shuffles of RC4"
-	 * by Ilya Mironov.
+	 * Discard early keystream, as per recommendations in:
+	 * "(Not So) Random Shuffles of RC4" by Ilya Mironov.
 	 */
-	for (n = 0; n < 1024; n++)
-		(void) arc4_getbyte();
+	for (i = 0; i < 1024; i++)
+		(void)arc4_getbyte();
 	arc4_count = 1600000;
 }
 
+static void
+arc4_stir_if_needed(void)
+{
+	pid_t pid = getpid();
+
+	if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != pid)
+	{
+		arc4_stir_pid = pid;
+		arc4_stir();
+	}
+}
+
 static inline u_int8_t
 arc4_getbyte(void)
 {
@@ -152,7 +170,6 @@ arc4_getbyte(void)
 	sj = rs.s[rs.j];
 	rs.s[rs.i] = sj;
 	rs.s[rs.j] = si;
-
 	return (rs.s[(si + sj) & 0xff]);
 }
 
@@ -160,81 +177,55 @@ static inline u_int32_t
 arc4_getword(void)
 {
 	u_int32_t val;
-
 	val = arc4_getbyte() << 24;
 	val |= arc4_getbyte() << 16;
 	val |= arc4_getbyte() << 8;
 	val |= arc4_getbyte();
-
-	return (val);
-}
-
-static void
-arc4_check_init(void)
-{
-	if (!rs_initialized) {
-		arc4_init();
-		rs_initialized = 1;
-	}
-}
-
-static inline void
-arc4_check_stir(void)
-{
-	if (!rs_stired || arc4_count <= 0) {
-		arc4_stir();
-		rs_stired = 1;
-	}
+	return val;
 }
 
 void
 arc4random_stir(void)
 {
-	THREAD_LOCK();
-	arc4_check_init();
+	_ARC4_LOCK();
 	arc4_stir();
-	rs_stired = 1;
-	THREAD_UNLOCK();
+	_ARC4_UNLOCK();
 }
 
 void
 arc4random_addrandom(u_char *dat, int datlen)
 {
-	THREAD_LOCK();
-	arc4_check_init();
-	arc4_check_stir();
+	_ARC4_LOCK();
+	if (!rs_initialized)
+		arc4_stir();
 	arc4_addrandom(dat, datlen);
-	THREAD_UNLOCK();
+	_ARC4_UNLOCK();
 }
 
 u_int32_t
 arc4random(void)
 {
-	u_int32_t rnd;
-
-	THREAD_LOCK();
-	arc4_check_init();
-	arc4_check_stir();
-	rnd = arc4_getword();
+	u_int32_t val;
+	_ARC4_LOCK();
 	arc4_count -= 4;
-	THREAD_UNLOCK();
-
-	return (rnd);
+	arc4_stir_if_needed();
+	val = arc4_getword();
+	_ARC4_UNLOCK();
+	return val;
 }
 
 void
 arc4random_buf(void *_buf, size_t n)
 {
 	u_char *buf = (u_char *)_buf;
-
-	THREAD_LOCK();
-	arc4_check_init();
+	_ARC4_LOCK();
+	arc4_stir_if_needed();
 	while (n--) {
-		arc4_check_stir();
+		if (--arc4_count <= 0)
+			arc4_stir();
 		buf[n] = arc4_getbyte();
-		arc4_count--;
 	}
-	THREAD_UNLOCK();
+	_ARC4_UNLOCK();
 }
 
 /*
@@ -253,7 +244,7 @@ arc4random_uniform(u_int32_t upper_bound
 	u_int32_t r, min;
 
 	if (upper_bound < 2)
-		return (0);
+		return 0;
 
 #if (ULONG_MAX > 0xffffffffUL)
 	min = 0x100000000UL % upper_bound;
@@ -279,7 +270,7 @@ arc4random_uniform(u_int32_t upper_bound
 			break;
 	}
 
-	return (r % upper_bound);
+	return r % upper_bound;
 }
 
 #if 0


More information about the svn-src-all mailing list