From de02ec27673108e4b1e92883171ee8c3092a6e54 Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Sat, 27 Dec 2003 16:02:22 +0000 Subject: Check if a random "file" is really a device file, and treat it specially if it is. Add a few OpenBSD-specific cases. This is part of a large change submitted by Markus Friedl --- crypto/rand/rand_unix.c | 19 ++++++++++++++ crypto/rand/randfile.c | 67 +++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 75 insertions(+), 11 deletions(-) diff --git a/crypto/rand/rand_unix.c b/crypto/rand/rand_unix.c index 8b4c483312..ef80201212 100644 --- a/crypto/rand/rand_unix.c +++ b/crypto/rand/rand_unix.c @@ -125,6 +125,24 @@ #include #include +#ifdef __OpenBSD__ +int RAND_poll(void) +{ + u_int32_t rnd = 0, i; + unsigned char buf[ENTROPY_NEEDED]; + + for (i = 0; i < sizeof(buf); i++) { + if (i % 4 == 0) + rnd = arc4random(); + buf[i] = rnd; + rnd >>= 8; + } + RAND_add(buf, sizeof(buf), ENTROPY_NEEDED); + memset(buf, 0, sizeof(buf)); + + return 1; +} +#else int RAND_poll(void) { unsigned long l; @@ -236,6 +254,7 @@ int RAND_poll(void) #endif } +#endif #endif #if defined(OPENSSL_SYS_VXWORKS) diff --git a/crypto/rand/randfile.c b/crypto/rand/randfile.c index 41574768ab..f1f250c5bf 100644 --- a/crypto/rand/randfile.c +++ b/crypto/rand/randfile.c @@ -56,6 +56,9 @@ * [including the GNU Public Licence.] */ +/* We need to define this to get macros like S_IFBLK and S_IFCHR */ +#define _XOPEN_SOURCE 1 + #include #include #include @@ -64,6 +67,7 @@ #include "e_os.h" #include #include +#include #ifdef OPENSSL_SYS_VMS #include @@ -106,6 +110,14 @@ int RAND_load_file(const char *file, long bytes) in=fopen(file,"rb"); if (in == NULL) goto err; + if (sb.st_mode & (S_IFBLK | S_IFCHR)) { + /* this file is a device. we don't want read an infinite number + * of bytes from a random device, nor do we want to use buffered + * I/O because we will waste system entropy. + */ + bytes = (bytes == -1) ? 2048 : bytes; /* ok, is 2048 enough? */ + setvbuf(in, NULL, _IONBF, 0); /* don't do buffered reads */ + } for (;;) { if (bytes > 0) @@ -135,7 +147,20 @@ int RAND_write_file(const char *file) int i,ret=0,rand_err=0; FILE *out = NULL; int n; + struct stat sb; + i=stat(file,&sb); + if (i != -1) { + if (sb.st_mode & (S_IFBLK | S_IFCHR)) { + /* this file is a device. we don't write back to it. + * we "succeed" on the assumption this is some sort + * of random device. Otherwise attempting to write to + * and chmod the device causes problems. + */ + return(1); + } + } + #if defined(O_CREAT) && !defined(OPENSSL_SYS_WIN32) /* For some reason Win32 can't write to files created this way */ @@ -197,16 +222,17 @@ err: const char *RAND_file_name(char *buf, size_t size) { char *s=NULL; - char *ret=NULL; + int ok = 0; +#ifdef __OpenBSD__ + struct stat sb; +#endif if (OPENSSL_issetugid() == 0) s=getenv("RANDFILE"); - if (s != NULL) + if (s != NULL && *s && strlen(s) + 1 < size) { - if(strlen(s) >= size) + if (BUF_strlcpy(buf,s,size) >= size) return NULL; - strcpy(buf,s); - ret=buf; } else { @@ -218,17 +244,36 @@ const char *RAND_file_name(char *buf, size_t size) s = DEFAULT_HOME; } #endif - if (s != NULL && (strlen(s)+strlen(RFILE)+2 < size)) + if (s && *s && strlen(s)+strlen(RFILE)+2 < size) { - strcpy(buf,s); + BUF_strlcpy(buf,s,size); #ifndef OPENSSL_SYS_VMS - strcat(buf,"/"); + BUF_strlcat(buf,"/",size); #endif - strcat(buf,RFILE); - ret=buf; + BUF_strlcat(buf,RFILE,size); + ok = 1; } else buf[0] = '\0'; /* no file name */ } - return(ret); + +#ifdef __OpenBSD__ + /* given that all random loads just fail if the file can't be + * seen on a stat, we stat the file we're returning, if it + * fails, use /dev/arandom instead. this allows the user to + * use their own source for good random data, but defaults + * to something hopefully decent if that isn't available. + */ + + if (!ok) + if (BUF_strlcpy(buf,"/dev/arandom",size) >= size) { + return(NULL); + } + if (stat(buf,&sb) == -1) + if (BUF_strlcpy(buf,"/dev/arandom",size) >= size) { + return(NULL); + } + +#endif + return(buf); } -- cgit v1.2.3