1 #include "first.h" 2 3 #include "rand.h" 4 #include "fdevent.h" 5 #include "safe_memclear.h" 6 7 #include <sys/types.h> 8 #include <sys/stat.h> 9 #include <errno.h> 10 #include <fcntl.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <time.h> 14 #include <unistd.h> 15 16 #include "sys-crypto.h" 17 #ifdef USE_OPENSSL_CRYPTO 18 #include <openssl/opensslv.h> /* OPENSSL_VERSION_NUMBER */ 19 #include <openssl/rand.h> 20 #endif 21 #ifdef HAVE_GETENTROPY 22 #include <sys/random.h> 23 #endif 24 #ifdef HAVE_LINUX_RANDOM_H 25 #include <sys/syscall.h> 26 #include <linux/random.h> 27 #endif 28 #ifdef RNDGETENTCNT 29 #include <sys/ioctl.h> 30 #endif 31 32 /* Take some reasonable steps to attempt to *seed* random number generators with 33 * cryptographically random data. Some of these initialization routines may 34 * block, and are intended to be called only at startup in lighttpd, or 35 * immediately after fork() to start lighttpd workers. 36 * 37 * Update: li_rand_init() is now deferred until first use so that installations 38 * that do not use modules which use these routines do need to potentially block 39 * at startup. Current use by core lighttpd modules is in mod_auth HTTP Digest 40 * auth and in mod_usertrack. Deferring collection of random data until first 41 * use may allow sufficient entropy to be collected by kernel before first use, 42 * helping reduce or avoid situations in low-entropy-generating embedded devices 43 * which might otherwise block lighttpd for minutes at device startup. 44 * Further discussion in https://redmine.lighttpd.net/boards/2/topics/6981 45 * 46 * Note: results from li_rand_pseudo_bytes() are not necessarily 47 * cryptographically random and must not be used for purposes such 48 * as key generation which require cryptographic randomness. 49 * 50 * https://wiki.openssl.org/index.php/Random_Numbers 51 * https://wiki.openssl.org/index.php/Random_fork-safety 52 * 53 * openssl random number generators are not thread-safe by default 54 * https://wiki.openssl.org/index.php/Manual:Threads(3) 55 * 56 * RFE: add more paranoid checks from the following to improve confidence: 57 * http://insanecoding.blogspot.co.uk/2014/05/a-good-idea-with-bad-usage-devurandom.html 58 * RFE: retry on EINTR 59 * RFE: check RAND_status() 60 */ 61 62 static int li_getentropy (void *buf, size_t buflen) 63 { 64 #ifdef HAVE_GETENTROPY 65 return getentropy(buf, buflen); 66 #else 67 /*(see NOTES section in 'man getrandom' on Linux)*/ 68 #if defined(HAVE_GETRANDOM) || defined(SYS_getrandom) 69 if (buflen <= 256) { 70 #ifdef HAVE_GETRANDOM /*(not implemented in glibc yet)*/ 71 int num = getrandom(buf, buflen, 0); 72 #elif defined(SYS_getrandom) 73 /* https://lwn.net/Articles/605828/ */ 74 /* https://bbs.archlinux.org/viewtopic.php?id=200039 */ 75 int num = (int)syscall(SYS_getrandom, buf, buflen, 0); 76 #endif 77 if (num == (int)buflen) return 0; 78 if (num < 0) return num; /* -1 */ 79 } 80 #else 81 UNUSED(buf); 82 UNUSED(buflen); 83 #endif 84 errno = EIO; 85 return -1; 86 #endif 87 } 88 89 static int li_rand_device_bytes (unsigned char *buf, int num) 90 { 91 /* randomness from these devices is cryptographically strong, 92 * unless /dev/urandom is low on entropy */ 93 94 static const char * const devices[] = { 95 #ifdef __OpenBSD__ 96 "/dev/arandom", 97 #endif 98 "/dev/urandom", 99 "/dev/random" 100 }; 101 102 /* device files might not be available in chroot environment, 103 * so prefer syscall, if available */ 104 if (0 == li_getentropy(buf, (size_t)num)) return 1; 105 106 for (unsigned int u = 0; u < sizeof(devices)/sizeof(devices[0]); ++u) { 107 /*(some systems might have symlink to another device; omit O_NOFOLLOW)*/ 108 int fd = fdevent_open_cloexec(devices[u], 0, O_RDONLY, 0); 109 if (fd >= 0) { 110 ssize_t rd = 0; 111 #ifdef RNDGETENTCNT 112 int entropy; 113 if (0 == ioctl(fd, (unsigned long)(RNDGETENTCNT), &entropy) 114 && entropy >= num*8) 115 #endif 116 rd = read(fd, buf, (size_t)num); 117 close(fd); 118 if (rd == num) { 119 return 1; 120 } 121 } 122 } 123 124 return 0; 125 } 126 127 static int li_rand_inited; 128 static unsigned short xsubi[3]; 129 130 static void li_rand_init (void) 131 { 132 /* (intended to be called at init and after fork() in order to re-seed PRNG 133 * so that forked children, grandchildren, etc do not share PRNG seed) 134 * https://github.com/ramsey/uuid/issues/80 135 * https://www.agwa.name/blog/post/libressls_prng_is_unsafe_on_linux 136 * (issue in early version of libressl has since been fixed) 137 * https://github.com/libressl-portable/portable/commit/32d9eeeecf4e951e1566d5f4a42b36ea37b60f35 138 */ 139 unsigned int u; 140 li_rand_inited = 1; 141 if (1 == li_rand_device_bytes((unsigned char *)xsubi, (int)sizeof(xsubi))) { 142 u = ((unsigned int)xsubi[0] << 16) | xsubi[1]; 143 } 144 else { 145 #ifdef HAVE_ARC4RANDOM_BUF 146 u = arc4random(); 147 arc4random_buf(xsubi, sizeof(xsubi)); 148 #else 149 /* NOTE: not cryptographically random !!! */ 150 srand((unsigned int)(time(NULL) ^ getpid())); 151 for (u = 0; u < sizeof(unsigned short); ++u) 152 /* coverity[dont_call : FALSE] */ 153 xsubi[u] = (unsigned short)(rand() & 0xFFFF); 154 u = ((unsigned int)xsubi[0] << 16) | xsubi[1]; 155 #endif 156 } 157 srand(u); /*(initialize just in case rand() used elsewhere)*/ 158 #ifdef HAVE_SRANDOM 159 srandom(u); /*(initialize just in case random() used elsewhere)*/ 160 #endif 161 #ifdef USE_OPENSSL_CRYPTO 162 RAND_poll(); 163 RAND_seed(xsubi, (int)sizeof(xsubi)); 164 #endif 165 } 166 167 void li_rand_reseed (void) 168 { 169 if (li_rand_inited) li_rand_init(); 170 } 171 172 int li_rand_pseudo (void) 173 { 174 /* randomness *is not* cryptographically strong */ 175 /* (attempt to use better mechanisms to replace the more portable rand()) */ 176 #ifdef USE_OPENSSL_CRYPTO /* (openssl 1.1.0 deprecates RAND_pseudo_bytes()) */ 177 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 178 int i; 179 if (-1 != RAND_pseudo_bytes((unsigned char *)&i, sizeof(i))) return i; 180 #endif 181 #endif 182 if (!li_rand_inited) li_rand_init(); 183 #ifdef HAVE_ARC4RANDOM_BUF 184 return (int)arc4random(); 185 #elif defined(HAVE_SRANDOM) 186 /* coverity[dont_call : FALSE] */ 187 return (int)random(); 188 #elif defined(HAVE_JRAND48) 189 /*(FYI: jrand48() reentrant, but use of file-scoped static xsubi[] is not)*/ 190 /* coverity[dont_call : FALSE] */ 191 return (int)jrand48(xsubi); 192 #else 193 /* coverity[dont_call : FALSE] */ 194 return rand(); 195 #endif 196 } 197 198 void li_rand_pseudo_bytes (unsigned char *buf, int num) 199 { 200 for (int i = 0; i < num; ++i) 201 buf[i] = li_rand_pseudo() & 0xFF; 202 } 203 204 int li_rand_bytes (unsigned char *buf, int num) 205 { 206 #ifdef USE_OPENSSL_CRYPTO 207 int rc = RAND_bytes(buf, num); 208 if (-1 != rc) { 209 return rc; 210 } 211 #endif 212 if (1 == li_rand_device_bytes(buf, num)) { 213 return 1; 214 } 215 else { 216 /* NOTE: not cryptographically random !!! */ 217 li_rand_pseudo_bytes(buf, num); 218 /*(openssl RAND_pseudo_bytes rc for non-cryptographically random data)*/ 219 return 0; 220 } 221 } 222 223 void li_rand_cleanup (void) 224 { 225 #ifdef USE_OPENSSL_CRYPTO 226 #if OPENSSL_VERSION_NUMBER < 0x10100000L 227 RAND_cleanup(); 228 #endif 229 #endif 230 safe_memclear(xsubi, sizeof(xsubi)); 231 } 232