[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