apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Justin Erenkrantz <jerenkra...@ebuilt.com>
Subject [PATCH] Add EGD-compatible random support
Date Sat, 05 Jan 2002 00:53:40 GMT
This patch adds EGD-gathering support to apr_generate_random_bytes.
At this time, you just specify the EGD socket at configure-time
FWIW, I used --with-egd=/home/jerenkrantz/.entropy and started 
PRNGd with "prngd /home/jerenkrantz/.entropy" and ran the testrand
I added to apr/test/.

Ideally, I'd like to add an apr_generate_random_bytes_setup function
that takes in a path name that will configure the random device 
(you'd have to know what random device is being used APR, but it'd 
be useful).  This will be even more useful if/when we add an internal
entropy gatherer that will need a config file.  We can have 
compiled-in defaults (see DEFAULT_EGD_SOCKET), but I'd like the
application be able to override these choices.  -- justin

P.S. It'd be nice if apr_generate_random_bytes took in a pool...

Index: acconfig.h
===================================================================
RCS file: /home/cvs/apr/acconfig.h,v
retrieving revision 1.53
diff -u -r1.53 acconfig.h
--- acconfig.h	29 Nov 2001 00:34:27 -0000	1.53
+++ acconfig.h	5 Jan 2002 00:42:32 -0000
@@ -10,6 +10,8 @@
 #undef HAVE_CODESET
 #undef HAVE_PTHREAD_PROCESS_SHARED
 #undef DEV_RANDOM
+#undef HAVE_EGD
+#undef EGD_DEFAULT_SOCKET
 #undef HAVE_TRUERAND
 #undef HAVE_POLLIN
 #undef HAVE_isascii
Index: configure.in
===================================================================
RCS file: /home/cvs/apr/configure.in,v
retrieving revision 1.392
diff -u -r1.392 configure.in
--- configure.in	2 Jan 2002 09:12:37 -0000	1.392
+++ configure.in	5 Jan 2002 00:42:32 -0000
@@ -1186,19 +1188,32 @@
     AC_MSG_RESULT(/dev/urandom)
     rand="1"
 else
-    AC_MSG_RESULT(not found);
-
     case $host in
         # we have built in support for OS/2
         *-os2*)
+            AC_MSG_RESULT([Using OS/2 builtin random])
             rand="1"
             ;;
-        # no other choice, try for truerand
         *)
-            if test "$ac_cv_lib_truerand_main" = "yes"; then
+            AC_ARG_WITH(egd, 
+              [  --with-egd=<path>   use egd-compatible socket],
+              [ if test "$withval" = "yes"; then
+                  AC_ERROR([You must specify a default EGD socket path.])
+                fi
+                AC_DEFINE(HAVE_EGD)
+                AC_DEFINE_UNQUOTED(EGD_DEFAULT_SOCKET, [$withval])
+                AC_MSG_RESULT(EGD-compatible daemon)
                 rand="1"
-            else
+              ])
+            if test "$rand" != "1"; then
+              if test "$ac_cv_lib_truerand_main" = "yes"; then
+                AC_DEFINE(HAVE_TRUERAND)
+                AC_MSG_RESULT(truerand)
+                rand="1"
+              else
+                AC_MSG_RESULT(not found)
                 rand="0"
+              fi
             fi
             ;;
     esac
Index: misc/unix/rand.c
===================================================================
RCS file: /home/cvs/apr/misc/unix/rand.c,v
retrieving revision 1.7
diff -u -r1.7 rand.c
--- misc/unix/rand.c	10 Aug 2001 21:04:47 -0000	1.7
+++ misc/unix/rand.c	5 Jan 2002 00:42:33 -0000
@@ -62,13 +62,14 @@
 
 #if APR_HAS_RANDOM
 
+/* This tells the preprocessor to put quotes around the value. */
 #define	XSTR(x)	#x
 #define	STR(x)	XSTR(x)
 
 APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char *buf, 
                                                     int length) 
 {
-#ifdef	DEV_RANDOM
+#ifdef DEV_RANDOM
 
     int rnd;
     size_t got, tot;
@@ -89,7 +90,79 @@
     for (idx=0; idx<length; idx++)
 	buf[idx] = randbyte();
 
-#else  /* use truerand */
+#elif defined(HAVE_EGD)
+    /* use EGD-compatible socket daemon (such as EGD or PRNGd).
+     * message format:
+     * 0x00 (get entropy level)
+     *   0xMM (msb) 0xmm 0xll 0xLL (lsb)
+     * 0x01 (read entropy nonblocking) 0xNN (bytes requested)
+     *   0xMM (bytes granted) MM bytes
+     * 0x02 (read entropy blocking) 0xNN (bytes desired)
+     *   [block] NN bytes
+     * 0x03 (write entropy) 0xMM 0xLL (bits of entropy) 0xNN (bytes of data) 
+     *      NN bytes
+     * (no response - write only) 
+     * 0x04 (report PID)
+     *   0xMM (length of PID string, not null-terminated) MM chars
+     */
+    apr_status_t rv;
+    apr_socket_t *egd_socket;
+    apr_sockaddr_t *egd_sockaddr;
+    apr_pool_t *pool;
+    apr_size_t req_expected, resp_expected;
+    unsigned char req[2], resp[255];
+    char *curbuf = buf;
+
+    apr_pool_create(&pool, NULL);
+    apr_socket_create(&egd_socket, APR_UNIX, SOCK_STREAM, pool);
+
+    apr_socket_addr_get(&egd_sockaddr, APR_LOCAL, egd_socket);
+  
+    /* We need to be able to set this via APR. */ 
+    memcpy(egd_sockaddr->sa.sunix.sun_path, STR(EGD_DEFAULT_SOCKET), 
+           strlen(STR(EGD_DEFAULT_SOCKET)));
+
+    rv = apr_connect(egd_socket, egd_sockaddr);
+    if (rv != APR_SUCCESS) {
+        apr_pool_destroy(pool);
+        return rv;
+    }
+   
+    /* EGD can only take 255 bytes (2 bytes) of data.  Silly.  */ 
+    while (length > 0) {
+        req[0] = 2; /* We'll block for now. */
+        req[1] = length > 255 ? 255: length;
+
+        req_expected = 2;
+        rv = apr_send(egd_socket, req, &req_expected);
+        if (rv != APR_SUCCESS) {
+            apr_shutdown(egd_socket, APR_SHUTDOWN_READWRITE);
+            apr_pool_destroy(pool);
+            return rv;
+        }
+
+        if (req_expected != 2) {
+            apr_shutdown(egd_socket, APR_SHUTDOWN_READWRITE);
+            apr_pool_destroy(pool);
+            return APR_EGENERAL;  /* Try again. */
+        }
+
+        resp_expected = req[1];
+        rv = apr_recv(egd_socket, resp, &resp_expected);
+        if (rv != APR_SUCCESS) {
+            apr_shutdown(egd_socket, APR_SHUTDOWN_READWRITE);
+            apr_pool_destroy(pool);
+            return rv;
+        }
+        memcpy(curbuf, resp, resp_expected);
+        curbuf += resp_expected;
+        length -= resp_expected;
+    }
+
+    apr_shutdown(egd_socket, APR_SHUTDOWN_READWRITE);
+    apr_pool_destroy(pool);
+    
+#elif defined(HAVE_TRUERAND) /* use truerand */
 
     extern int randbyte(void);	/* from the truerand library */
     unsigned int idx;


Mime
View raw message