diff --git a/CHANGES b/CHANGES index 2c212fd284080a2d2220e30c92ea36c2605fb2df..579707a241db24edf15457fa3b2e901fdfdcba19 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,12 @@ Changes between 0.9.4 and 0.9.5 [xx XXX 2000] + *) Support EGD . 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] diff --git a/apps/app_rand.c b/apps/app_rand.c index b94c85323a4ca7780cd5223d3173d9daa4c6042b..ea35bf9b1d712ae5687b51314e774379c671efd6 100644 --- a/apps/app_rand.c +++ b/apps/app_rand.c @@ -115,6 +115,7 @@ 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 diff --git a/crypto/rand/Makefile.ssl b/crypto/rand/Makefile.ssl index 8195bf090b332c2e295a774f30d7f879e6109951..68ef887902fa438822c5fc8b1be8029f3f607218 100644 --- a/crypto/rand/Makefile.ssl +++ b/crypto/rand/Makefile.ssl @@ -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) diff --git a/crypto/rand/md_rand.c b/crypto/rand/md_rand.c index 34843d04dbe32c39432edd2c4f8a79af5df57e5e..79438611f284abd48e54b000a54afb6532d3f3ef 100644 --- a/crypto/rand/md_rand.c +++ b/crypto/rand/md_rand.c @@ -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 #include diff --git a/crypto/rand/rand.h b/crypto/rand/rand.h index e5d6696cb40c56403d848f919b5aafd60ff659ff..28f45ec05269965e4a9b37819b16787016932a7d 100644 --- a/crypto/rand/rand.h +++ b/crypto/rand/rand.h @@ -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 index 0000000000000000000000000000000000000000..802d35b5c29ecb1943dd2eefb68e207e7993a534 --- /dev/null +++ b/crypto/rand/rand_egd.c @@ -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 + +/* Query the EGD . + */ + +#if defined(WIN32) || defined(VMS) +int RAND_egd(const char *path) + { + return(-1); + } +#else +#include +#include OPENSSL_UNISTD +#include +#include +#include + +#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 diff --git a/doc/crypto/RAND_add.pod b/doc/crypto/RAND_add.pod index 927c59d4c3a582b8af08068f8b11da06169b1763..d6804e2a905a9dbc7f17181c91ba7debf9417036 100644 --- a/doc/crypto/RAND_add.pod +++ b/doc/crypto/RAND_add.pod @@ -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, L, L + + int RAND_egd(const char *path); + +=head1 DESCRIPTION + +RAND_egd() queries the entropy gathering daemon EGD on socket B. + +=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, L, L + +=head1 HISTORY + +RAND_egd() is available since OpenSSL 0.9.5. + +=cut diff --git a/doc/crypto/rand.pod b/doc/crypto/rand.pod index 0fafe54dd91163251873a7e5012236372045e556..5104b070a1ade2870414cb7c63fab732f4eaa586 100644 --- a/doc/crypto/rand.pod +++ b/doc/crypto/rand.pod @@ -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). =head1 SEE ALSO L, L, -L, L, +L, L, +L, L, L