Support EGD.
authorUlf Möller <ulf@openssl.org>
Thu, 24 Feb 2000 02:51:47 +0000 (02:51 +0000)
committerUlf Möller <ulf@openssl.org>
Thu, 24 Feb 2000 02:51:47 +0000 (02:51 +0000)
CHANGES
apps/app_rand.c
crypto/rand/Makefile.ssl
crypto/rand/md_rand.c
crypto/rand/rand.h
crypto/rand/rand_egd.c [new file with mode: 0644]
doc/crypto/RAND_add.pod
doc/crypto/RAND_egd.pod [new file with mode: 0644]
doc/crypto/rand.pod

diff --git a/CHANGES b/CHANGES
index 2c212fd..579707a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,12 @@
 
  Changes between 0.9.4 and 0.9.5  [xx XXX 2000]
 
+  *) Support EGD <http://www.lothar.com/tech/crypto/>.  New functions
+     RAND_egd() and RAND_status().  In the command line application,
+     the EGD socket can be specified like a seed file using RANDFILE
+     or -rand.
+     [Ulf Möller]
+
   *) Allow the string CERTIFICATE to be tolerated in PKCS#7 structures.
      Some CAs (e.g. Verisign) distribute certificates in this form.
      [Steve Henson]
index b94c853..ea35bf9 100644 (file)
 
 
 static int seeded = 0;
+static int egdsocket = 0;
 
 int app_RAND_load_file(const char *file, BIO *bio_e, int dont_warn)
        {
@@ -130,12 +131,19 @@ int app_RAND_load_file(const char *file, BIO *bio_e, int dont_warn)
 
        if (file == NULL)
                file = RAND_file_name(buffer, sizeof buffer);
+       else if (RAND_egd(file) > 0)
+               {
+               /* we try if the given filename is an EGD socket.
+                  if it is, we don't write anything back to the file. */
+               egdsocket = 1;
+               return 1;
+               }
        if (file == NULL || !RAND_load_file(file, -1))
                {
-               if (!dont_warn)
+               if (RAND_status() == 0 && !dont_warn)
                        {
                        BIO_printf(bio_e,"unable to load 'random state'\n");
-                       BIO_printf(bio_e,"What this means is that the random number generator has not been seeded\n");
+                       BIO_printf(bio_e,"This means that the random number generator has not been seeded\n");
                        BIO_printf(bio_e,"with much random data.\n");
                        if (consider_randfile) /* explanation does not apply when a file is explicitly named */
                                {
@@ -165,6 +173,7 @@ long app_RAND_load_files(char *name)
                name=p+1;
                if (*n == '\0') break;
 
+               tot+=RAND_egd(n);
                tot+=RAND_load_file(n,1024L*1024L);
                if (last) break;
                }
@@ -177,7 +186,7 @@ int app_RAND_write_file(const char *file, BIO *bio_e)
        {
        char buffer[200];
        
-       if (!seeded)
+       if (egdsocket || !seeded)
                /* If we did not manage to read the seed file,
                 * we should not write a low-entropy seed file back --
                 * it would suppress a crucial warning the next time
index 8195bf0..68ef887 100644 (file)
@@ -22,8 +22,8 @@ TEST= randtest.c
 APPS=
 
 LIB=$(TOP)/libcrypto.a
-LIBSRC=md_rand.c randfile.c rand_lib.c rand_err.c
-LIBOBJ=md_rand.o randfile.o rand_lib.o rand_err.o
+LIBSRC=md_rand.c randfile.c rand_lib.c rand_err.c rand_egd.c
+LIBOBJ=md_rand.o randfile.o rand_lib.o rand_err.o rand_egd.o
 
 SRC= $(LIBSRC)
 
index 34843d0..7943861 100644 (file)
@@ -139,6 +139,7 @@ static unsigned char state[STATE_SIZE+MD_DIGEST_LENGTH];
 static unsigned char md[MD_DIGEST_LENGTH];
 static long md_count[2]={0,0};
 static double entropy=0;
+static int initialized=0;
 
 const char *RAND_version="RAND" OPENSSL_VERSION_PTEXT;
 
@@ -295,6 +296,51 @@ static void ssleay_rand_seed(const void *buf, int num)
        ssleay_rand_add(buf, num, num);
        }
 
+static void ssleay_rand_initialize(void)
+       {
+       unsigned long l;
+#ifndef GETPID_IS_MEANINGLESS
+       pid_t curr_pid = getpid();
+#endif
+#ifdef DEVRANDOM
+       FILE *fh;
+#endif
+
+       CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+       /* put in some default random data, we need more than just this */
+#ifndef GETPID_IS_MEANINGLESS
+       l=curr_pid;
+       RAND_add(&l,sizeof(l),0);
+       l=getuid();
+       RAND_add(&l,sizeof(l),0);
+#endif
+       l=time(NULL);
+       RAND_add(&l,sizeof(l),0);
+
+#ifdef DEVRANDOM
+       /* Use a random entropy pool device. Linux and FreeBSD have
+        * this. Use /dev/urandom if you can as /dev/random will block
+        * if it runs out of random entries.  */
+
+       if ((fh = fopen(DEVRANDOM, "r")) != NULL)
+               {
+               unsigned char tmpbuf[ENTROPY_NEEDED];
+               int n;
+               
+               n=fread((unsigned char *)tmpbuf,1,ENTROPY_NEEDED,fh);
+               fclose(fh);
+               RAND_add(tmpbuf,sizeof tmpbuf,n);
+               memset(tmpbuf,0,n);
+               }
+#endif
+#ifdef PURIFY
+       memset(state,0,STATE_SIZE);
+       memset(md,0,MD_DIGEST_LENGTH);
+#endif
+       CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+       initialized=1;
+       }
+
 static int ssleay_rand_bytes(unsigned char *buf, int num)
        {
        int i,j,k,st_num,st_idx;
@@ -302,14 +348,9 @@ static int ssleay_rand_bytes(unsigned char *buf, int num)
        long md_c[2];
        unsigned char local_md[MD_DIGEST_LENGTH];
        MD_CTX m;
-       static int init=1;
-       unsigned long l;
 #ifndef GETPID_IS_MEANINGLESS
        pid_t curr_pid = getpid();
 #endif
-#ifdef DEVRANDOM
-       FILE *fh;
-#endif
 
 #ifdef PREDICT
        {
@@ -342,47 +383,8 @@ static int ssleay_rand_bytes(unsigned char *buf, int num)
 
        CRYPTO_w_lock(CRYPTO_LOCK_RAND);
 
-       if (init)
-               {
-               CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
-               /* put in some default random data, we need more than
-                * just this */
-               RAND_add(&m,sizeof(m),0);
-#ifndef GETPID_IS_MEANINGLESS
-               l=curr_pid;
-               RAND_add(&l,sizeof(l),0);
-               l=getuid();
-               RAND_add(&l,sizeof(l),0);
-#endif
-               l=time(NULL);
-               RAND_add(&l,sizeof(l),0);
-
-#ifdef DEVRANDOM
-               /* 
-                * Use a random entropy pool device.
-                * Linux 1.3.x and FreeBSD-Current has 
-                * this. Use /dev/urandom if you can
-                * as /dev/random will block if it runs out
-                * of random entries.
-                */
-               if ((fh = fopen(DEVRANDOM, "r")) != NULL)
-                       {
-                       unsigned char tmpbuf[ENTROPY_NEEDED];
-                       int n;
-
-                       n=fread((unsigned char *)tmpbuf,1,ENTROPY_NEEDED,fh);
-                       fclose(fh);
-                       RAND_add(tmpbuf,sizeof tmpbuf,n);
-                       memset(tmpbuf,0,n);
-                       }
-#endif
-#ifdef PURIFY
-               memset(state,0,STATE_SIZE);
-               memset(md,0,MD_DIGEST_LENGTH);
-#endif
-               CRYPTO_w_lock(CRYPTO_LOCK_RAND);
-               init=0;
-               }
+       if (!initialized)
+               ssleay_rand_initialize();
 
        ok = (entropy >= ENTROPY_NEEDED);
 
@@ -473,6 +475,13 @@ static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num)
        return (ret);
        }
 
+int RAND_status(void)
+       {
+       if (!initialized)
+               ssleay_rand_initialize();
+       return (entropy >= ENTROPY_NEEDED);
+       }
+
 #ifdef WINDOWS
 #include <windows.h>
 #include <openssl/rand.h>
index e5d6696..28f45ec 100644 (file)
@@ -83,6 +83,8 @@ void RAND_add(const void *buf,int num,double entropy);
 int  RAND_load_file(const char *file,long max_bytes);
 int  RAND_write_file(const char *file);
 const char *RAND_file_name(char *file,int num);
+int RAND_status(void);
+int RAND_egd(const char *path);
 #ifdef WINDOWS
 void RAND_screen(void);
 #endif
diff --git a/crypto/rand/rand_egd.c b/crypto/rand/rand_egd.c
new file mode 100644 (file)
index 0000000..802d35b
--- /dev/null
@@ -0,0 +1,108 @@
+/* crypto/rand/rand_egd.c */
+/* Written by Ulf Moeller for the OpenSSL project. */
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <openssl/rand.h>
+
+/* Query the EGD <URL: http://www.lothar.com/tech/crypto/>.
+ */
+
+#if defined(WIN32) || defined(VMS)
+int RAND_egd(const char *path)
+       {
+       return(-1);
+       }
+#else
+#include <openssl/opensslconf.h>
+#include OPENSSL_UNISTD
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#ifndef offsetof
+#  define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+int RAND_egd(const char *path)
+       {
+       int ret = -1;
+       struct sockaddr_un addr;
+       int len, num;
+       int fd = -1;
+       unsigned char buf[256];
+
+       memset(&addr, 0, sizeof(addr));
+       addr.sun_family = AF_UNIX;
+       if (strlen(path) > sizeof(addr.sun_path))
+               return (-1);
+       strcpy(addr.sun_path,path);
+       len = offsetof(struct sockaddr_un, sun_path) + strlen(path);
+       fd = socket(AF_UNIX, SOCK_STREAM, 0);
+       if (fd == -1) return (-1);
+       if (connect(fd, &addr, len) == -1) goto err;
+       buf[0] = 1;
+       buf[1] = 255;
+       write(fd, buf, 2);
+       if (read(fd, buf, 1) != 1) goto err;
+       num = read(fd, buf, 255);
+       if (num < 1) goto err;
+       RAND_seed(buf, num);
+       if (RAND_status() == 1)
+               ret = num;
+ err:
+       if (fd != -1) close(fd);
+       return(ret);
+       }
+#endif
index 927c59d..d6804e2 100644 (file)
@@ -12,6 +12,8 @@ RAND_add, RAND_seed, RAND_screen - Add entropy to the PRNG
 
  void RAND_add(const void *buf, int num, double entropy);
 
+ int  RAND_status(void);
+
  void RAND_screen(void);
 
 =head1 DESCRIPTION
@@ -46,7 +48,10 @@ used on servers that run without user interaction.
 
 =head1 RETURN VALUES
 
-These functions do not return values.
+RAND_status() returns 1 if the PRNG has been seeded with enough data,
+0 otherwise.
+
+The other functions do not return values.
 
 =head1 SEE ALSO
 
@@ -55,6 +60,7 @@ L<rand(3)|rand(3)>, L<RAND_load_file(3)|RAND_load_file(3)>, L<RAND_cleanup(3)|RA
 =head1 HISTORY
 
 RAND_seed() and RAND_screen() are available in all versions of SSLeay
-and OpenSSL. RAND_add() was added in OpenSSL 0.9.5.
+and OpenSSL. RAND_add() and RAND_status() have been added in OpenSSL
+0.9.5.
 
 =cut
diff --git a/doc/crypto/RAND_egd.pod b/doc/crypto/RAND_egd.pod
new file mode 100644 (file)
index 0000000..251b71f
--- /dev/null
@@ -0,0 +1,31 @@
+=pod
+
+=head1 NAME
+
+RAND_egd - Query entropy gathering daemon
+
+=head1 SYNOPSIS
+
+ #include <openssl/rand.h>
+
+ int RAND_egd(const char *path);
+
+=head1 DESCRIPTION
+
+RAND_egd() queries the entropy gathering daemon EGD on socket B<path>.
+
+=head1 RETURN VALUES
+
+RAND_egd() returns the number of bytes read from the daemon on
+success, and -1 if the connection failed or the daemon did not return
+enough data to fully seed the PRNG.
+
+=head1 SEE ALSO
+
+L<rand(3)|rand(3)>, L<RAND_add(3)|RAND_add(3)>, L<RAND_cleanup(3)|RAND_cleanup(3)>
+
+=head1 HISTORY
+
+RAND_egd() is available since OpenSSL 0.9.5.
+
+=cut
index 0fafe54..5104b07 100644 (file)
@@ -13,12 +13,15 @@ rand - Pseudo-random number generator
 
  void RAND_seed(const void *buf,int num);
  void RAND_add(const void *buf,int num,int entropy);
+ int  RAND_status(void);
  void RAND_screen(void);
 
  int  RAND_load_file(const char *file,long max_bytes);
  int  RAND_write_file(const char *file);
  const char *RAND_file_name(char *file,int num);
 
+ int  RAND_egd(const char *path);
+
  void RAND_set_rand_method(RAND_METHOD *meth);
  RAND_METHOD *RAND_get_rand_method(void);
  RAND_METHOD *RAND_SSLeay(void);
@@ -147,7 +150,8 @@ L<RAND_add(3)|RAND_add(3)>).
 =head1 SEE ALSO
 
 L<BN_rand(3)|BN_rand(3)>, L<RAND_add(3)|RAND_add(3)>,
-L<RAND_load_file(3)|RAND_load_file(3)>, L<RAND_bytes(3)|RAND_bytes(3)>,
+L<RAND_load_file(3)|RAND_load_file(3)>, L<RAND_egd(3)|RAND_egd(3)>,
+L<RAND_bytes(3)|RAND_bytes(3)>,
 L<RAND_set_rand_method(3)|RAND_set_rand_method(3)>,
 L<RAND_cleanup(3)|RAND_cleanup(3)>