]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
randread: use /dev/urandom to seed, not just getpid etc
authorPaul R. Eggert <eggert@cs.ucla.edu>
Tue, 20 Jul 2010 16:50:37 +0000 (09:50 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Tue, 20 Jul 2010 16:51:12 +0000 (09:51 -0700)
* 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
gl/lib/rand-isaac.h
gl/lib/randread.c

index 377caa6050b9487517eecf916e778fb774afe294..f73144afebdb1d653f0cdaa7b83866bd960f0193 100644 (file)
@@ -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);
 }
index 6559dc8feadc92351a3e7bc6fbdfc3623867e066..052dc9f3a89193037b7493a74ca853f60c9c24b5 100644 (file)
@@ -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
index 94b9928b2a394a5a3254d2602c26605927ad5377..a681c8dae7f559449c5c43495ae4ac23ba61ab05 100644 (file)
 #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)
 # 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;