[PATCH] rand.c updates from FreeBSD RELENG_5

William M. Grim wgrim at siue.edu
Wed May 12 17:29:09 PDT 2004


Matthew Dillon wrote:
    It looks pretty good.  Hiten had some minor comments about retaining
    the $ cvs tags, but that isn't something you actually need to worry
    about since either Hiten or I will add them back in when we commit
    now that we know they are missing.
    I have one comment, and that is that the use of /dev/random has
    created lots of unexpected problems in FreeBSD which they have 
    hacked around.  I think we should simply use /dev/urandom here,
    which is guarenteed not to block and will certainly produce a
    random enough seed for rand's tiny little seed.

					-Matt


I have created a new patch with your recommendations above and do not 
use /dev/random any longer.  I also retrieved the latest man page 
updates from the FreeBSD team and generated a patch out of those (they 
talk about sranddev).

Also, as per another one of your emails, I have re-added the CVS tags. 
I noticed that my earlier patch removed them.  I'm not sure how/why it 
did that, but the new patches do not do that.

I think these will work better for you.

Thanks again,
Mike
--- rand.c	2004-05-12 15:43:31.000000000 -0500
+++ rand.c.new	2004-05-12 15:42:39.000000000 -0500
@@ -32,14 +32,20 @@
  *
  * Posix rand_r function added May 1999 by Wes Peters <wes at xxxxxxxxxxxx>.
  *
- * $FreeBSD: src/lib/libc/stdlib/rand.c,v 1.2.2.1 2001/03/05 11:33:57 obrien Exp $
+ * $FreeBSD: src/lib/libc/stdlib/rand.c,v 1.15 2001/03/05 11:33:57 ache Exp $
  * $DragonFly: src/lib/libc/stdlib/rand.c,v 1.2 2003/06/17 04:26:46 dillon Exp $
- *
- * @(#)rand.c	8.1 (Berkeley) 6/14/93
  */
 
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rand.c	8.1 (Berkeley) 6/14/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+
+#include <sys/time.h>          /* for sranddev() */
 #include <sys/types.h>
+#include <fcntl.h>             /* for sranddev() */
 #include <stdlib.h>
+#include <unistd.h>            /* for sranddev() */
 
 #ifdef TEST
 #include <stdio.h>
@@ -48,7 +54,34 @@
 static int
 do_rand(unsigned long *ctx)
 {
+#ifdef  USE_WEAK_SEEDING
+/*
+ * Historic implementation compatibility.
+ * The random sequences do not vary much with the seed,
+ * even with overflowing.
+ */
 	return ((*ctx = *ctx * 1103515245 + 12345) % ((u_long)RAND_MAX + 1));
+#else   /* !USE_WEAK_SEEDING */
+/*
+ * Compute x = (7^5 * x) mod (2^31 - 1)
+ * wihout overflowing 31 bits:
+ *      (2^31 - 1) = 127773 * (7^5) + 2836
+ * From "Random number generators: good ones are hard to find",
+ * Park and Miller, Communications of the ACM, vol. 31, no. 10,
+ * October 1988, p. 1195.
+ */
+	long hi, lo, x;
+
+	/* Can't be initialized with 0, so use another value. */
+	if (*ctx == 0)
+		*ctx = 123459876;
+	hi = *ctx / 127773;
+	lo = *ctx % 127773;
+	x = 16807 * lo - 2836 * hi;
+	if (x < 0)
+		x += 0x7fffffff;
+	return ((*ctx = x) % ((u_long)RAND_MAX + 1));
+#endif  /* !USE_WEAK_SEEDING */
 }
 
 
@@ -56,8 +89,10 @@
 rand_r(unsigned int *ctx)
 {
 	u_long val = (u_long) *ctx;
-	*ctx = do_rand(&val);
-	return (int) *ctx;
+	int r = do_rand(&val);
+
+	*ctx = (unsigned int) val;
+	return (r);
 }
 
 
@@ -66,7 +101,7 @@
 int
 rand()
 {
-	return do_rand(&next);
+	return (do_rand(&next));
 }
 
 void
@@ -76,6 +111,42 @@
 	next = seed;
 }
 
+
+/*
+ * sranddev:
+ *
+ * Many programs choose the seed value in a totally predictable manner.
+ * This often causes problems.  We seed the generator using the much more
+ * secure random(4) interface.
+ *
+ * FreeBSD chooses to use /dev/random for their seed.  However, because
+ * of possible problems surrounding /dev/random, we use /dev/urandom for now,
+ * which is guaranteed not to block and will produce a "good enough" seed
+ * for us for the time being.
+ */
+void
+sranddev()
+{
+	int fd, done;
+
+	done = 0;
+	fd = _open("/dev/urandom", O_RDONLY, 0);
+	if (fd >= 0) {
+		if (_read(fd, (void *) &next, sizeof(next)) == sizeof(next))
+			done = 1;
+		_close(fd);
+	}
+
+	if (!done) {
+		struct timeval tv;
+		unsigned long junk;
+
+		gettimeofday(&tv, NULL);
+		srand((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk);
+	}
+}
+
+
 #ifdef TEST
 
 main()
--- rand.3.old	2004-05-12 15:51:12.000000000 -0500
+++ rand.3.new	2004-05-12 15:51:53.000000000 -0500
@@ -34,7 +34,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     @(#)rand.3	8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/rand.3,v 1.4.2.5 2001/12/14 18:33:58 ru Exp $
+.\" $FreeBSD: /repoman/r/ncvs/src/lib/libc/stdlib/rand.3,v 1.14 2003/09/08 19:57:15 ru Exp $
 .\" $DragonFly: src/lib/libc/stdlib/rand.3,v 1.2 2003/06/17 04:26:46 dillon Exp $
 .\"
 .Dd May 25, 1999
@@ -43,6 +43,7 @@
 .Sh NAME
 .Nm rand ,
 .Nm srand ,
+.Nm sranddev ,
 .Nm rand_r
 .Nd bad random number generator
 .Sh LIBRARY
@@ -51,6 +52,8 @@
 .In stdlib.h
 .Ft void
 .Fn srand "unsigned seed"
+.Ft void
+.Fn sranddev void
 .Ft int
 .Fn rand void
 .Ft int
@@ -67,7 +70,7 @@
 of 0 to
 .Dv RAND_MAX
 (as defined by the header file
-.Aq Pa stdlib.h ) .
+.In stdlib.h ) .
 .Pp
 The
 .Fn srand
@@ -85,14 +88,24 @@
 value is provided, the functions are automatically
 seeded with a value of 1.
 .Pp
+The
+.Fn sranddev
+function initializes a seed using the
+.Xr random 4
+random number device which returns good random numbers,
+suitable for cryptographic use.
+.Pp
+The
 .Fn rand_r
+function
 provides the same functionality as
 .Fn rand .
 A pointer to the context value
 .Fa ctx
 must be supplied by the caller.
 .Sh SEE ALSO
-.Xr random 3
+.Xr random 3 ,
+.Xr random 4
 .Sh STANDARDS
 The
 .Fn rand




More information about the Submit mailing list