rand_unix.c revision 160814
1/* crypto/rand/rand_unix.c */ 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay@cryptsoft.com). 7 * The implementation was written so as to conform with Netscapes SSL. 8 * 9 * This library is free for commercial and non-commercial use as long as 10 * the following conditions are aheared to. The following conditions 11 * apply to all code found in this distribution, be it the RC4, RSA, 12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13 * included with this distribution is covered by the same copyright terms 14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15 * 16 * Copyright remains Eric Young's, and as such any Copyright notices in 17 * the code are not to be removed. 18 * If this package is used in a product, Eric Young should be given attribution 19 * as the author of the parts of the library used. 20 * This can be in the form of a textual message at program startup or 21 * in documentation (online or textual) provided with the package. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * "This product includes cryptographic software written by 34 * Eric Young (eay@cryptsoft.com)" 35 * The word 'cryptographic' can be left out if the rouines from the library 36 * being used are not cryptographic related :-). 37 * 4. If you include any Windows specific code (or a derivative thereof) from 38 * the apps directory (application code) you must include an acknowledgement: 39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40 * 41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * The licence and distribution terms for any publically available version or 54 * derivative of this code cannot be changed. i.e. this code cannot simply be 55 * copied and put under another distribution licence 56 * [including the GNU Public Licence.] 57 */ 58/* ==================================================================== 59 * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. 60 * 61 * Redistribution and use in source and binary forms, with or without 62 * modification, are permitted provided that the following conditions 63 * are met: 64 * 65 * 1. Redistributions of source code must retain the above copyright 66 * notice, this list of conditions and the following disclaimer. 67 * 68 * 2. Redistributions in binary form must reproduce the above copyright 69 * notice, this list of conditions and the following disclaimer in 70 * the documentation and/or other materials provided with the 71 * distribution. 72 * 73 * 3. All advertising materials mentioning features or use of this 74 * software must display the following acknowledgment: 75 * "This product includes software developed by the OpenSSL Project 76 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 77 * 78 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 79 * endorse or promote products derived from this software without 80 * prior written permission. For written permission, please contact 81 * openssl-core@openssl.org. 82 * 83 * 5. Products derived from this software may not be called "OpenSSL" 84 * nor may "OpenSSL" appear in their names without prior written 85 * permission of the OpenSSL Project. 86 * 87 * 6. Redistributions of any form whatsoever must retain the following 88 * acknowledgment: 89 * "This product includes software developed by the OpenSSL Project 90 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 91 * 92 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 93 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 94 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 95 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 96 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 97 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 98 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 99 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 100 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 101 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 102 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 103 * OF THE POSSIBILITY OF SUCH DAMAGE. 104 * ==================================================================== 105 * 106 * This product includes cryptographic software written by Eric Young 107 * (eay@cryptsoft.com). This product includes software written by Tim 108 * Hudson (tjh@cryptsoft.com). 109 * 110 */ 111#include <stdio.h> 112 113#define USE_SOCKETS 114#include "e_os.h" 115#include "cryptlib.h" 116#include <openssl/rand.h> 117#include "rand_lcl.h" 118 119#if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_NETWARE)) 120 121#include <sys/types.h> 122#include <sys/time.h> 123#include <sys/times.h> 124#include <sys/stat.h> 125#include <fcntl.h> 126#include <unistd.h> 127#include <time.h> 128 129#ifdef __OpenBSD__ 130int RAND_poll(void) 131{ 132 u_int32_t rnd = 0, i; 133 unsigned char buf[ENTROPY_NEEDED]; 134 135 for (i = 0; i < sizeof(buf); i++) { 136 if (i % 4 == 0) 137 rnd = arc4random(); 138 buf[i] = rnd; 139 rnd >>= 8; 140 } 141 RAND_add(buf, sizeof(buf), ENTROPY_NEEDED); 142 memset(buf, 0, sizeof(buf)); 143 144 return 1; 145} 146#else 147int RAND_poll(void) 148{ 149 unsigned long l; 150 pid_t curr_pid = getpid(); 151#if defined(DEVRANDOM) || defined(DEVRANDOM_EGD) 152 unsigned char tmpbuf[ENTROPY_NEEDED]; 153 int n = 0; 154#endif 155#ifdef DEVRANDOM 156 static const char *randomfiles[] = { DEVRANDOM }; 157 struct stat randomstats[sizeof(randomfiles)/sizeof(randomfiles[0])]; 158 int fd; 159 size_t i; 160#endif 161#ifdef DEVRANDOM_EGD 162 static const char *egdsockets[] = { DEVRANDOM_EGD, NULL }; 163 const char **egdsocket = NULL; 164#endif 165 166#ifdef DEVRANDOM 167 memset(randomstats,0,sizeof(randomstats)); 168 /* Use a random entropy pool device. Linux, FreeBSD and OpenBSD 169 * have this. Use /dev/urandom if you can as /dev/random may block 170 * if it runs out of random entries. */ 171 172 for (i=0; i<sizeof(randomfiles)/sizeof(randomfiles[0]) && n < ENTROPY_NEEDED; i++) 173 { 174 if ((fd = open(randomfiles[i], O_RDONLY 175#ifdef O_NONBLOCK 176 |O_NONBLOCK 177#endif 178#ifdef O_BINARY 179 |O_BINARY 180#endif 181#ifdef O_NOCTTY /* If it happens to be a TTY (god forbid), do not make it 182 our controlling tty */ 183 |O_NOCTTY 184#endif 185 )) >= 0) 186 { 187 struct timeval t = { 0, 10*1000 }; /* Spend 10ms on 188 each file. */ 189 int r; 190 size_t j; 191 fd_set fset; 192 struct stat *st=&randomstats[i]; 193 194 /* Avoid using same input... Used to be O_NOFOLLOW 195 * above, but it's not universally appropriate... */ 196 if (fstat(fd,st) != 0) { close(fd); continue; } 197 for (j=0;j<i;j++) 198 { 199 if (randomstats[j].st_ino==st->st_ino && 200 randomstats[j].st_dev==st->st_dev) 201 break; 202 } 203 if (j<i) { close(fd); continue; } 204 205 do 206 { 207 FD_ZERO(&fset); 208 FD_SET(fd, &fset); 209 r = -1; 210 211 if (select(fd+1,&fset,NULL,NULL,&t) < 0) 212 t.tv_usec=0; 213 else if (FD_ISSET(fd, &fset)) 214 { 215 r=read(fd,(unsigned char *)tmpbuf+n, 216 ENTROPY_NEEDED-n); 217 if (r > 0) 218 n += r; 219 } 220 221 /* Some Unixen will update t, some 222 won't. For those who won't, give 223 up here, otherwise, we will do 224 this once again for the remaining 225 time. */ 226 if (t.tv_usec == 10*1000) 227 t.tv_usec=0; 228 } 229 while ((r > 0 || (errno == EINTR || errno == EAGAIN)) 230 && t.tv_usec != 0 && n < ENTROPY_NEEDED); 231 232 close(fd); 233 } 234 } 235#endif 236 237#ifdef DEVRANDOM_EGD 238 /* Use an EGD socket to read entropy from an EGD or PRNGD entropy 239 * collecting daemon. */ 240 241 for (egdsocket = egdsockets; *egdsocket && n < ENTROPY_NEEDED; egdsocket++) 242 { 243 int r; 244 245 r = RAND_query_egd_bytes(*egdsocket, (unsigned char *)tmpbuf+n, 246 ENTROPY_NEEDED-n); 247 if (r > 0) 248 n += r; 249 } 250#endif 251 252#if defined(DEVRANDOM) || defined(DEVRANDOM_EGD) 253 if (n > 0) 254 { 255 RAND_add(tmpbuf,sizeof tmpbuf,(double)n); 256 OPENSSL_cleanse(tmpbuf,n); 257 } 258#endif 259 260 /* put in some default random data, we need more than just this */ 261 l=curr_pid; 262 RAND_add(&l,sizeof(l),0.0); 263 l=getuid(); 264 RAND_add(&l,sizeof(l),0.0); 265 266 l=time(NULL); 267 RAND_add(&l,sizeof(l),0.0); 268 269#if defined(DEVRANDOM) || defined(DEVRANDOM_EGD) 270 return 1; 271#else 272 return 0; 273#endif 274} 275 276#endif 277#endif 278 279#if defined(OPENSSL_SYS_VXWORKS) 280int RAND_poll(void) 281{ 282 return 0; 283} 284#endif 285