tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: [6.0_BETA] cprng xxx: WARNING insufficient entropy at creation.



On Sat, Feb 25, 2012 at 03:50:39PM -0500, Thor Lancelot Simon wrote:
> On Sat, Feb 25, 2012 at 02:08:49PM -0500, Thor Lancelot Simon wrote:
> > On Sat, Feb 25, 2012 at 07:54:41PM +0100, Martin Husemann wrote:
> > > 
> > > What I am still wondering is: is this a local setup problem, unavoidable
> > > on this hardware, or a bug in the code?
> > 
> > Well, one worthwhile question is why sshd would be opening
> > /dev/urandom over and over again rather than opening once and
> > reading many times.  If it opened it once, it would not deplete
> > your system's entropy in this manner.
> 
> It's arc4_stir() in libc, I believe.  I'll fix.

Try the following patch.  Warning -- untested.  But it should do the job.

Index: gen/arc4random.c
===================================================================
RCS file: /cvsroot/src/lib/libc/gen/arc4random.c,v
retrieving revision 1.10
diff -u -r1.10 arc4random.c
--- gen/arc4random.c    4 Feb 2011 22:07:07 -0000       1.10
+++ gen/arc4random.c    26 Feb 2012 04:51:08 -0000
@@ -31,6 +31,7 @@
 #endif /* LIBC_SCCS and not lint */
 
 #include "namespace.h"
+#include "reentrant.h"
 #include <fcntl.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -44,13 +45,15 @@
 #endif
 
 struct arc4_stream {
+       int rndfd;
+       mutex_t mtx;
        uint8_t i;
        uint8_t j;
        uint8_t s[256];
 };
 
 static int rs_initialized;
-static struct arc4_stream rs;
+static struct arc4_stream rs = { .rndfd = -1, .mtx = MUTEX_INITIALIZER };
 
 static inline void arc4_init(struct arc4_stream *);
 static inline void arc4_addrandom(struct arc4_stream *, u_char *, int);
@@ -89,21 +92,16 @@
 static void
 arc4_stir(struct arc4_stream *as)
 {
-       int     fd;
-       struct {
-               struct timeval tv;
-               u_int rnd[(128 - sizeof(struct timeval)) / sizeof(u_int)];
-       }       rdat;
+       int rdat[128 / sizeof(int)];
        int     n;
 
-       gettimeofday(&rdat.tv, NULL);
-       fd = open("/dev/urandom", O_RDONLY);
-       if (fd != -1) {
-               read(fd, rdat.rnd, sizeof(rdat.rnd));
-               close(fd);
+       if (as->rndfd == -1) {
+               as->rndfd = open("/dev/urandom", O_RDONLY);
        }
-#ifdef KERN_URND
-       else {
+       
+       if (as->rndfd != -1) {
+               read(as->rndfd, rdat, sizeof(rdat));
+       } else {
                int mib[2];
                u_int i;
                size_t len;
@@ -114,15 +112,12 @@
                mib[0] = CTL_KERN;
                mib[1] = KERN_URND;
 
-               for (i = 0; i < sizeof(rdat.rnd) / sizeof(u_int); i++) {
-                       len = sizeof(u_int);
-                       if (sysctl(mib, 2, &rdat.rnd[i], &len, NULL, 0) == -1)
-                               break;
+               for (i = 0; i < sizeof(rdat) / sizeof(int); i++) {
+                       len = sizeof(rdat[i]);
+                       if (sysctl(mib, 2, &rdat[i], &len, NULL, 0) == -1)
+                               abort();
                }
        }
-#endif
-       /* fd < 0 or failed sysctl ?  Ah, what the heck. We'll just take
-        * whatever was on the stack... */
 
        arc4_addrandom(as, (void *) &rdat, sizeof(rdat));
 
@@ -160,8 +155,8 @@
        return val;
 }
 
-void
-arc4random_stir(void)
+static inline void
+_arc4random_stir_unlocked(void)
 {
        if (!rs_initialized) {
                arc4_init(&rs);
@@ -171,23 +166,67 @@
 }
 
 void
-arc4random_addrandom(u_char *dat, int datlen)
+arc4random_stir(void)
+{
+#ifdef _REENTRANT
+       if (__isthreaded) {
+               mutex_lock(&rs.mtx);
+                _arc4random_stir_unlocked();
+               mutex_unlock(&rs.mtx);
+               return;
+        }
+#endif
+       _arc4random_stir_unlocked();
+}
+
+static inline void
+_arc4random_addrandom_unlocked(u_char *dat, int datlen)
 {
        if (!rs_initialized)
-               arc4random_stir();
+               arc4_stir(&rs);
        arc4_addrandom(&rs, dat, datlen);
 }
 
-uint32_t
-arc4random(void)
+void
+arc4random_addrandom(u_char *dat, int datlen)
+{
+#ifdef _REENTRANT
+       if (__isthreaded) {
+               mutex_lock(&rs.mtx);
+               _arc4random_addrandom_unlocked(dat, datlen);
+               mutex_unlock(&rs.mtx);
+               return;
+       }
+#endif
+       _arc4random_addrandom_unlocked(dat, datlen);
+}
+
+static inline uint32_t
+_arc4random_unlocked(void)
 {
        if (!rs_initialized)
-               arc4random_stir();
+               arc4_stir(&rs);
        return arc4_getword(&rs);
 }
 
-void
-arc4random_buf(void *buf, size_t len)
+uint32_t
+arc4random(void)
+{
+       uint32_t v;
+#ifdef _REENTRANT
+       if (__isthreaded) {
+               mutex_lock(&rs.mtx);
+               v = _arc4random_unlocked();
+               mutex_unlock(&rs.mtx);
+               return v;
+       }
+#endif
+       v = _arc4random_unlocked();
+       return v;
+}
+
+static void
+_arc4random_buf_unlocked(void *buf, size_t len)
 {
        uint8_t *bp = buf;
        uint8_t *ep = bp + len;
@@ -200,6 +239,20 @@
                *bp++ = arc4_getbyte(&rs);
 }
 
+void
+arc4random_buf(void *buf, size_t len)
+{
+#ifdef _REENTRANT
+       if (__isthreaded) {
+               mutex_lock(&rs.mtx);
+               _arc4random_buf_unlocked(buf, len);
+               mutex_unlock(&rs.mtx);
+               return;
+       } else
+#endif
+       _arc4random_buf_unlocked(buf, len);
+}
+
 /*-
  * Written by Damien Miller.
  * With simplifications by Jinmei Tatuya.
@@ -216,8 +269,8 @@
  * [2^32 % upper_bound, 2^32[ which maps back to
  * [0, upper_bound[ after reduction modulo upper_bound.
  */
-uint32_t
-arc4random_uniform(uint32_t upper_bound)
+static uint32_t
+_arc4random_uniform_unlocked(uint32_t upper_bound)
 {
        uint32_t r, min;
 
@@ -243,7 +296,7 @@
         * to re-roll (at all).
         */
        if (!rs_initialized)
-               arc4random_stir();
+               arc4_stir(&rs);
        if (arc4_getbyte(&rs) & 1)
                (void)arc4_getbyte(&rs);
        do
@@ -253,24 +306,18 @@
        return r % upper_bound;
 }
 
-
-#if 0
-/*-------- Test code for i386 --------*/
-#include <stdio.h>
-#include <machine/pctr.h>
-int
-main(int argc, char **argv)
-{
-       const int iter = 1000000;
-       int     i;
-       pctrval v;
-
-       v = rdtsc();
-       for (i = 0; i < iter; i++)
-               arc4random();
-       v = rdtsc() - v;
-       v /= iter;
-
-       printf("%qd cycles\n", v);
-}
+uint32_t
+arc4random_uniform(uint32_t upper_bound)
+{
+       uint32_t v;
+#ifdef _REENTRANT
+       if (__isthreaded) {
+               mutex_lock(&rs.mtx);
+               v = _arc4random_uniform_unlocked(upper_bound);
+               mutex_unlock(&rs.mtx);
+               return v;
+       }
 #endif
+       v = _arc4random_uniform_unlocked(upper_bound);
+       return v;
+}


Home | Main Index | Thread Index | Old Index