Package: coreutils;
Reported by: Paul Eggert <eggert <at> CS.UCLA.EDU>
Date: Fri, 16 Jul 2010 21:18:01 UTC
Severity: normal
Tags: patch
Done: Pádraig Brady <P <at> draigBrady.com>
Bug is archived. No further changes may be made.
View this message in rfc822 format
From: Paul Eggert <eggert <at> CS.UCLA.EDU> To: Jim Meyering <jim <at> meyering.net> Cc: 6658 <at> debbugs.gnu.org Subject: bug#6658: [PATCH] randread: use /dev/urandom to seed, not just getpid etc Date: Tue, 20 Jul 2010 09:59:41 -0700
OK, I installed part (2) of the patch: it uses /dev/urandom rather than the getpid()/gettimeofday() yucky stuff, when /dev/urandom is available. One downside to this patch is that on hosts where mkstemp doesn't work and we're using our substitute, each invocation of mkstemp opens /dev/urandom, reads a few bytes, and closes it. I don't view this as a big problem, because (a) it's only for hosts with broken mkstemp and they should fix their mkstemp and (b) creating a temp file is a big-deal operation anyway and the extra overhead of opening /dev/urandom doesn't add much. I considered working around the problem anyway, but couldn't come up with a simple, clean and fast workaround under the constraint that mkstemp must be thread-safe (the current randread stuff does not allow competing threads to read from the same random source). Perhaps later, if there's interest. From 3403f96997bc6ff441696e11a892f2389891aaa7 Mon Sep 17 00:00:00 2001 From: Paul R. Eggert <eggert <at> cs.ucla.edu> Date: Tue, 20 Jul 2010 09:50:37 -0700 Subject: [PATCH] randread: use /dev/urandom to seed, not just getpid etc * gl/lib/rand-isaac.c (isaac_seed_start): New arg SEEDED. (isaac_seed): New args FD and BYTES_BOUND. Read from FD if possible. Don't bother with low-quality sources if FD has enough bytes. * gl/lib/rand-isaac.h: New size_t arg for isaac_seed. * gl/lib/randread.c: Include fcntl.h, unistd.h. (NAME_OF_NONCE_DEVICE): New #define. (nonce_device): New static var. (randread_new): Use nonce device if available. --- gl/lib/rand-isaac.c | 49 +++++++++++++++++++++++++++++++++---------------- gl/lib/rand-isaac.h | 3 ++- gl/lib/randread.c | 11 ++++++++++- 3 files changed, 45 insertions(+), 18 deletions(-) diff --git a/gl/lib/rand-isaac.c b/gl/lib/rand-isaac.c index 377caa6..f73144a 100644 --- a/gl/lib/rand-isaac.c +++ b/gl/lib/rand-isaac.c @@ -209,9 +209,10 @@ isaac_init (struct isaac_state *s, uint32_t const *seed, size_t seedsize) } #endif -/* Initialize *S to a somewhat-random value. */ +/* Initialize *S to a somewhat-random value. The first SEEDED bytes + in S->mm are already seeded with random data. */ static void -isaac_seed_start (struct isaac_state *s) +isaac_seed_start (struct isaac_state *s, size_t seeded) { static uint32_t const iv[8] = { @@ -228,11 +229,12 @@ isaac_seed_start (struct isaac_state *s) mix (iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7]); #endif - memset (s->mm, 0, sizeof s->mm); + memset ((char *) s->mm + seeded, 0, sizeof s->mm - seeded); memcpy (s->iv, iv, sizeof s->iv); /* s->c gets used for a data pointer during the seeding phase */ - s->a = s->b = s->c = 0; + s->a = s->b = 0; + s->c = seeded; } /* Add a buffer of seed material. */ @@ -279,22 +281,37 @@ isaac_seed_finish (struct isaac_state *s) #define ISAAC_SEED(s,x) isaac_seed_data (s, &(x), sizeof (x)) /* Initialize *S to a somewhat-random value; this starts seeding, - seeds with somewhat-random data, and finishes seeding. */ + seeds with somewhat-random data, and finishes seeding. If FD is + nonnegative, seed by reading at most BYTES_BOUNDS bytes from it. */ void -isaac_seed (struct isaac_state *s) +isaac_seed (struct isaac_state *s, int fd, size_t bytes_bound) { - isaac_seed_start (s); + /* Get some data from FD if available. */ + ssize_t seeded = 0; + if (0 <= fd) + { + if (sizeof s->mm < bytes_bound) + bytes_bound = sizeof s->mm; + seeded = read (fd, s->mm, bytes_bound); + if (seeded < 0) + seeded = 0; + } - { pid_t t = getpid (); ISAAC_SEED (s, t); } - { pid_t t = getppid (); ISAAC_SEED (s, t); } - { uid_t t = getuid (); ISAAC_SEED (s, t); } - { gid_t t = getgid (); ISAAC_SEED (s, t); } + isaac_seed_start (s, seeded); - { - struct timeval t; - gettimeofday (&t, NULL); - ISAAC_SEED (s, t); - } + if (seeded < sizeof s->mm) + { + { pid_t t = getpid (); ISAAC_SEED (s, t); } + { pid_t t = getppid (); ISAAC_SEED (s, t); } + { uid_t t = getuid (); ISAAC_SEED (s, t); } + { gid_t t = getgid (); ISAAC_SEED (s, t); } + + { + struct timeval t; + gettimeofday (&t, NULL); + ISAAC_SEED (s, t); + } + } isaac_seed_finish (s); } diff --git a/gl/lib/rand-isaac.h b/gl/lib/rand-isaac.h index 6559dc8..052dc9f 100644 --- a/gl/lib/rand-isaac.h +++ b/gl/lib/rand-isaac.h @@ -21,6 +21,7 @@ #ifndef RAND_ISAAC_H # define RAND_ISAAC_H +# include <stddef.h> # include <stdint.h> /* Size of the state tables to use. ISAAC_LOG should be at least 3, @@ -37,7 +38,7 @@ struct isaac_state uint32_t a, b, c; /* Extra index variables */ }; -void isaac_seed (struct isaac_state *); +void isaac_seed (struct isaac_state *, int, size_t); void isaac_refill (struct isaac_state *, uint32_t[ISAAC_WORDS]); #endif diff --git a/gl/lib/randread.c b/gl/lib/randread.c index 94b9928..a681c8d 100644 --- a/gl/lib/randread.c +++ b/gl/lib/randread.c @@ -24,12 +24,14 @@ #include <errno.h> #include <error.h> #include <exitfail.h> +#include <fcntl.h> #include <quotearg.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include "gettext.h" #define _(msgid) gettext (msgid) @@ -60,6 +62,10 @@ # define ALIGNED_POINTER(ptr, type) ((size_t) (ptr) % alignof (type) == 0) #endif +#ifndef NAME_OF_NONCE_DEVICE +#define NAME_OF_NONCE_DEVICE "/dev/urandom" +#endif + /* The maximum buffer size used for reads of random data. Using the value 2 * ISAAC_BYTES makes this the largest power of two that would not otherwise cause struct randread_source to grow. */ @@ -164,8 +170,11 @@ randread_new (char const *name, size_t bytes_bound) setvbuf (source, s->buf.c, _IOFBF, MIN (sizeof s->buf.c, bytes_bound)); else { + int nonce_device = open (NAME_OF_NONCE_DEVICE, O_RDONLY | O_BINARY); s->buf.isaac.buffered = 0; - isaac_seed (&s->buf.isaac.state); + isaac_seed (&s->buf.isaac.state, nonce_device, bytes_bound); + if (0 <= nonce_device) + close (nonce_device); } return s; -- 1.7.1
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.