apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Joe Orton <jor...@redhat.com>
Subject [PATCH] Re: apr_generate_random_bytes() blocks forever
Date Wed, 16 Apr 2003 11:58:04 GMT
On Wed, Apr 16, 2003 at 10:50:17AM +0100, David Reid wrote:
> > "David Reid" <dreid@jetnet.co.uk> writes:
> >
> > > Ben's point is more (I think) that if we say we're providing randomness
> then
> > > we should provide that.
> >
> > But a caller isn't allowed to *explicitly* ask for poor-quality,
> > non-blocking randomness?  Why not?   If the word "randomness" bothers
> > people, then let's create a new function that never uses the word:
> > apr_generate_bits_nonblocking() or something.
> >
> > Nobody is arguing that we shouldn't have a function that produces
> > high-quality randomness.  Most of the time, that's what people want.
> > But we *also* need the ability to produce very poor randomness which
> > doesn't ever block for entropy.
> 
> Why? Please provide some cases that aren't SVN specific...

The issue is the UUID code in apr-util, and it's not really SVN
specific.  Here's how I'd do it: add apr_generate_weak_random_bytes(),
which MAY use /dev/urandom if available.  Any objections to the below
patch?

(you could do this with a "non-blocking" interface which returns EAGAIN
when /dev/random runs dry.  But then the caller would have to fall back
on their pet gettimeofday()-based random byte generator, which won't be
as good as /dev/urandom, so I prefer this solution)

Index: configure.in
===================================================================
RCS file: /home/cvs/apr/configure.in,v
retrieving revision 1.525
diff -u -r1.525 configure.in
--- configure.in	15 Apr 2003 21:45:57 -0000	1.525
+++ configure.in	16 Apr 2003 11:02:12 -0000
@@ -1686,6 +1686,16 @@
   if test "$rand" = "1"; then
     AC_DEFINE_UNQUOTED(DEV_RANDOM, ["$apr_devrandom"], [Define to path of random device])
     AC_MSG_RESULT([$apr_devrandom])
+    if test "x$apr_devrandom" != "x/dev/urandom"; then
+      AC_MSG_CHECKING(for /dev/urandom)
+      # See whether an alternative interface is also available
+      if test -r /dev/urandom; then
+        AC_MSG_RESULT(yes)
+        AC_DEFINE(HAVE_DEVURANDOM, 1, [Define if /dev/urandom is available])
+      else
+        AC_MSG_RESULT(no)
+      fi
+    fi
   fi
 fi
 
Index: include/apr_general.h
===================================================================
RCS file: /home/cvs/apr/include/apr_general.h,v
retrieving revision 1.80
diff -u -r1.80 apr_general.h
--- include/apr_general.h	5 Mar 2003 21:22:26 -0000	1.80
+++ include/apr_general.h	16 Apr 2003 11:02:12 -0000
@@ -265,7 +265,8 @@
 
 /* TODO: I'm not sure this is the best place to put this prototype...*/
 /**
- * Generate random bytes.
+ * Generate random bytes of highest quality available.  This function may
+ * take some time to complete if no entropy sources are available.
  * @param buf Buffer to fill with random bytes
  * @param length Length of buffer in bytes (becomes apr_size_t in APR 1.0)
  */
@@ -275,6 +276,15 @@
 #else
 APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char * buf, 
                                                     int length);
+/** Generate weak random bytes; on some platforms, this function may
+ * be able to provide weaker quality random bytes quickly, when high
+ * quality random bytes are not available.  On other platforms it will
+ * be equivalent to apr_generate_random_bytes.
+ * @param buf Buffer to fill with random bytes
+ * @param length Length of buffer in bytes (becomes apr_size_t in APR 1.0)
+ */
+APR_DECLARE(apr_status_t) apr_generate_weak_random_bytes(unsigned char * buf,
+                                                         int length);
 #endif
 
 #endif
Index: misc/unix/rand.c
===================================================================
RCS file: /home/cvs/apr/misc/unix/rand.c,v
retrieving revision 1.21
diff -u -r1.21 rand.c
--- misc/unix/rand.c	13 Jan 2003 18:23:09 -0000	1.21
+++ misc/unix/rand.c	16 Apr 2003 11:02:12 -0000
@@ -80,15 +80,10 @@
 
 #if APR_HAS_RANDOM
 
-APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char *buf, 
-#ifdef APR_ENABLE_FOR_1_0
-                                                    apr_size_t length)
-#else
-                                                    int length)
-#endif
-{
 #ifdef DEV_RANDOM
-
+/* FIXME: use size_t length for 1.0 */
+static apr_ssize_t read_random(const char *device, char *buf, int length)
+{
     int fd = -1;
 
     /* On BSD/OS 4.1, /dev/random gives out 8 bytes at a time, then
@@ -98,7 +93,7 @@
         apr_ssize_t rc;
 
         if (fd == -1)
-            if ((fd = open(DEV_RANDOM, O_RDONLY)) == -1)
+            if ((fd = open(device, O_RDONLY)) == -1)
                 return errno;
         
         rc = read(fd, buf, length);
@@ -118,6 +113,28 @@
     } while (length > 0);
     
     close(fd);
+
+    return APR_SUCCESS;
+}
+#endif
+
+/* FIXME: use size_t length for 1.0 */
+APR_DECLARE(apr_status_t) apr_generate_weak_random_bytes(unsigned char *buf, 
+                                                         int length)
+{
+#if defined(HAVE_DEVURANDOM)
+    return read_random("/dev/urandom", buf, length);
+#else
+    return apr_generate_random_bytes(buf, length);
+#endif
+}
+
+/* FIXME: use size_t length for 1.0 */
+APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char *buf, 
+                                                    int length)
+{
+#ifdef DEV_RANDOM
+    return read_random(DEV_RANDOM, buf, length);
 #elif defined(OS2)
     static UCHAR randbyte();
     unsigned int idx;
@@ -125,6 +142,7 @@
     for (idx=0; idx<length; idx++)
 	buf[idx] = randbyte();
 
+    return APR_SUCCESS;
 #elif defined(HAVE_EGD)
     /* use EGD-compatible socket daemon (such as EGD or PRNGd).
      * message format:
@@ -221,6 +239,7 @@
         return bad_errno;
     }
 
+    return APR_SUCCESS;
 #elif defined(HAVE_TRUERAND) /* use truerand */
 
     extern int randbyte(void);	/* from the truerand library */
@@ -232,9 +251,8 @@
     for (idx=0; idx<length; idx++)
 	buf[idx] = (unsigned char) randbyte();
 
-#endif	/* DEV_RANDOM */
-
     return APR_SUCCESS;
+#endif	/* DEV_RANDOM */
 }
 
 #undef	STR
Index: test/testrand.c
===================================================================
RCS file: /home/cvs/apr/test/testrand.c,v
retrieving revision 1.10
diff -u -r1.10 testrand.c
--- test/testrand.c	1 Jan 2003 00:01:56 -0000	1.10
+++ test/testrand.c	16 Apr 2003 11:02:12 -0000
@@ -71,7 +71,7 @@
      * what it is right now.
      */
     for (i = 1; i <= 8; i++) {
-        rv = apr_generate_random_bytes(c, i * 255);
+        rv = apr_generate_weak_random_bytes(c, i * 255);
         apr_assert_success(tc, "apr_generate_random_bytes failed", rv);
     }
 #endif

Mime
View raw message