1 /* 2 * rand - generate random bytes 3 * 4 * Copyright(c) 2016 Glenn Strauss gstrauss()gluelogic.com All rights reserved 5 * License: BSD 3-clause (same as lighttpd) 6 */ 7 #include "first.h" 8 9 #include "rand.h" 10 #include "buffer.h" 11 #include "fdevent.h" 12 #include "safe_memclear.h" 13 14 #include <sys/types.h> 15 #include <sys/stat.h> 16 #include <errno.h> 17 #include <fcntl.h> 18 #include <stdlib.h> 19 #include <string.h> 20 #include <time.h> 21 #include <unistd.h> 22 23 #include "sys-crypto.h" /* USE_LIB_CRYPTO */ 24 #ifdef USE_NETTLE_CRYPTO 25 #undef USE_MBEDTLS_CRYPTO 26 #undef USE_WOLFSSL_CRYPTO 27 #undef USE_OPENSSL_CRYPTO 28 #undef USE_GNUTLS_CRYPTO 29 #include <nettle/knuth-lfib.h> 30 #include <nettle/arcfour.h> 31 #include <nettle/yarrow.h> 32 #endif 33 #ifdef USE_MBEDTLS_CRYPTO 34 #undef USE_WOLFSSL_CRYPTO 35 #undef USE_OPENSSL_CRYPTO 36 #undef USE_GNUTLS_CRYPTO 37 #include <mbedtls/ctr_drbg.h> 38 #include <mbedtls/entropy.h> 39 #endif 40 #ifdef USE_WOLFSSL_CRYPTO 41 #undef USE_OPENSSL_CRYPTO 42 #undef USE_GNUTLS_CRYPTO 43 #include <wolfssl/wolfcrypt/random.h> 44 #endif 45 #ifdef USE_OPENSSL_CRYPTO 46 #undef USE_GNUTLS_CRYPTO 47 #include <openssl/opensslv.h> /* OPENSSL_VERSION_NUMBER */ 48 #include <openssl/rand.h> 49 #endif 50 #ifdef USE_GNUTLS_CRYPTO 51 #include <gnutls/crypto.h> 52 #endif 53 #ifdef HAVE_GETENTROPY 54 #include <sys/random.h> 55 #endif 56 #ifdef HAVE_LINUX_RANDOM_H 57 #include <sys/syscall.h> 58 #include <linux/random.h> 59 #endif 60 #ifdef RNDGETENTCNT 61 #include <sys/ioctl.h> 62 #endif 63 64 /* Take some reasonable steps to attempt to *seed* random number generators with 65 * cryptographically random data. Some of these initialization routines may 66 * block, and are intended to be called only at startup in lighttpd, or 67 * immediately after fork() to start lighttpd workers. 68 * 69 * Update: li_rand_init() is now deferred until first use so that installations 70 * that do not use modules which use these routines do need to potentially block 71 * at startup. Current use by core lighttpd modules is in mod_auth HTTP Digest 72 * auth and in mod_usertrack. Deferring collection of random data until first 73 * use may allow sufficient entropy to be collected by kernel before first use, 74 * helping reduce or avoid situations in low-entropy-generating embedded devices 75 * which might otherwise block lighttpd for minutes at device startup. 76 * Further discussion in https://redmine.lighttpd.net/boards/2/topics/6981 77 * 78 * Note: results from li_rand_pseudo_bytes() are not necessarily 79 * cryptographically random and must not be used for purposes such 80 * as key generation which require cryptographic randomness. 81 * 82 * https://wiki.openssl.org/index.php/Random_Numbers 83 * https://wiki.openssl.org/index.php/Random_fork-safety 84 * 85 * openssl random number generators are not thread-safe by default 86 * https://wiki.openssl.org/index.php/Manual:Threads(3) 87 * 88 * RFE: add more paranoid checks from the following to improve confidence: 89 * http://insanecoding.blogspot.co.uk/2014/05/a-good-idea-with-bad-usage-devurandom.html 90 * RFE: retry on EINTR 91 * RFE: check RAND_status() 92 */ 93 94 static int li_getentropy (void *buf, size_t buflen) 95 { 96 #ifdef HAVE_GETENTROPY 97 return getentropy(buf, buflen); 98 #else 99 /*(see NOTES section in 'man getrandom' on Linux)*/ 100 #if defined(HAVE_GETRANDOM) || defined(SYS_getrandom) 101 if (buflen <= 256) { 102 #ifdef HAVE_GETRANDOM /*(not implemented in glibc yet)*/ 103 int num = getrandom(buf, buflen, 0); 104 #elif defined(SYS_getrandom) 105 /* https://lwn.net/Articles/605828/ */ 106 /* https://bbs.archlinux.org/viewtopic.php?id=200039 */ 107 int num = (int)syscall(SYS_getrandom, buf, buflen, 0); 108 #endif 109 if (num == (int)buflen) return 0; 110 if (num < 0) return num; /* -1 */ 111 } 112 #else 113 UNUSED(buf); 114 UNUSED(buflen); 115 #endif 116 errno = EIO; 117 return -1; 118 #endif 119 } 120 121 static int li_rand_device_bytes (unsigned char *buf, int num) 122 { 123 /* randomness from these devices is cryptographically strong, 124 * unless /dev/urandom is low on entropy */ 125 126 static const char * const devices[] = { 127 #ifdef __OpenBSD__ 128 "/dev/arandom", 129 #endif 130 "/dev/urandom", 131 "/dev/random" 132 }; 133 134 /* device files might not be available in chroot environment, 135 * so prefer syscall, if available */ 136 if (0 == li_getentropy(buf, (size_t)num)) return 1; 137 138 for (unsigned int u = 0; u < sizeof(devices)/sizeof(devices[0]); ++u) { 139 /*(some systems might have symlink to another device; omit O_NOFOLLOW)*/ 140 int fd = fdevent_open_cloexec(devices[u], 0, O_RDONLY, 0); 141 if (fd >= 0) { 142 ssize_t rd = 0; 143 #ifdef RNDGETENTCNT 144 int entropy; 145 if (0 == ioctl(fd, (unsigned long)(RNDGETENTCNT), &entropy) 146 && entropy >= num*8) 147 #endif 148 rd = read(fd, buf, (size_t)num); 149 close(fd); 150 if (rd == num) { 151 return 1; 152 } 153 } 154 } 155 156 return 0; 157 } 158 159 static int li_rand_inited; 160 static unsigned short xsubi[3]; 161 #ifdef USE_MBEDTLS_CRYPTO 162 #ifdef MBEDTLS_ENTROPY_C 163 static mbedtls_entropy_context entropy; 164 #ifdef MBEDTLS_CTR_DRBG_C 165 static mbedtls_ctr_drbg_context ctr_drbg; 166 #endif 167 #endif 168 #endif 169 #ifdef USE_WOLFSSL_CRYPTO 170 static WC_RNG wolf_globalRNG; 171 #endif 172 #ifdef USE_NETTLE_CRYPTO 173 static struct knuth_lfib_ctx knuth_lfib_ctx; 174 static struct arcfour_ctx arcfour_ctx; 175 static struct yarrow256_ctx yarrow256_ctx; 176 #endif 177 178 #ifdef USE_NETTLE_CRYPTO 179 /* adapted from Nettle documentation arcfour_set_key_hashed() in nettle.pdf */ 180 /* A more robust key setup function for ARCFOUR */ 181 static void 182 li_arcfour_init_random_key_hashed(struct arcfour_ctx *ctx) 183 { 184 uint8_t key[ARCFOUR_KEY_SIZE]; 185 const size_t length = sizeof(key); 186 if (1 != li_rand_device_bytes(key, (int)sizeof(key))) { 187 log_failed_assert(__FILE__, __LINE__, 188 "gathering entropy for arcfour seed failed"); 189 } 190 memset(ctx, 0, sizeof(*ctx)); 191 192 struct sha256_ctx hash; 193 uint8_t digest[SHA256_DIGEST_SIZE]; 194 uint8_t buf[0x200]; 195 memset(buf, 0, sizeof(buf)); 196 sha256_init(&hash); 197 sha256_update(&hash, length, key); 198 sha256_digest(&hash, SHA256_DIGEST_SIZE, digest); 199 nettle_arcfour_set_key(ctx, SHA256_DIGEST_SIZE, digest); 200 nettle_arcfour_crypt(ctx, sizeof(buf), buf, buf); 201 nettle_arcfour_crypt(ctx, sizeof(buf), buf, buf); 202 nettle_arcfour_crypt(ctx, sizeof(buf), buf, buf); 203 } 204 #endif 205 206 __attribute_cold__ 207 static void li_rand_init (void) 208 { 209 /* (intended to be called at init and after fork() in order to re-seed PRNG 210 * so that forked children, grandchildren, etc do not share PRNG seed) 211 * https://github.com/ramsey/uuid/issues/80 212 * https://www.agwa.name/blog/post/libressls_prng_is_unsafe_on_linux 213 * (issue in early version of libressl has since been fixed) 214 * https://github.com/libressl-portable/portable/commit/32d9eeeecf4e951e1566d5f4a42b36ea37b60f35 215 */ 216 unsigned int u; 217 li_rand_inited = 1; 218 if (1 == li_rand_device_bytes((unsigned char *)xsubi, (int)sizeof(xsubi))) { 219 u = ((unsigned int)xsubi[0] << 16) | xsubi[1]; 220 } 221 else { 222 #ifdef HAVE_ARC4RANDOM_BUF 223 u = arc4random(); 224 arc4random_buf(xsubi, sizeof(xsubi)); 225 #elif defined(__COVERITY__) 226 /* Coverity Scan ignores(?) annotation below, 227 * so hide fallback path from Coverity Scan */ 228 u = (unsigned int)(time(NULL) ^ getpid()); 229 #else 230 /* NOTE: not cryptographically random !!! */ 231 srand((unsigned int)(time(NULL) ^ getpid())); 232 for (u = 0; u < sizeof(unsigned short); ++u) 233 /* coverity[dont_call : FALSE] */ 234 xsubi[u] = (unsigned short)(rand() & 0xFFFF); 235 u = ((unsigned int)xsubi[0] << 16) | xsubi[1]; 236 #endif 237 } 238 srand(u); /*(initialize just in case rand() used elsewhere)*/ 239 #ifdef HAVE_SRANDOM 240 srandom(u); /*(initialize just in case random() used elsewhere)*/ 241 #endif 242 #ifdef USE_NETTLE_CRYPTO 243 nettle_knuth_lfib_init(&knuth_lfib_ctx, u); 244 nettle_yarrow256_init(&yarrow256_ctx, 0, NULL); 245 li_arcfour_init_random_key_hashed(&arcfour_ctx); 246 #endif 247 #ifdef USE_WOLFSSL_CRYPTO 248 /* xsubi[] is small, so use wc_InitRng() instead of wc_InitRngNonce() 249 * to get default behavior of a larger internally-generated nonce */ 250 if (0 != wolfCrypt_Init() || 0 != wc_InitRng(&wolf_globalRNG)) 251 log_failed_assert(__FILE__, __LINE__, 252 "wolfCrypt_Init or wc_InitRng() failed"); 253 #endif 254 #ifdef USE_OPENSSL_CRYPTO 255 RAND_poll(); 256 RAND_seed(xsubi, (int)sizeof(xsubi)); 257 #endif 258 #ifdef USE_MBEDTLS_CRYPTO 259 #ifdef MBEDTLS_ENTROPY_C 260 mbedtls_entropy_init(&entropy); 261 #ifdef MBEDTLS_CTR_DRBG_C 262 mbedtls_ctr_drbg_init(&ctr_drbg); 263 int rc = 264 mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, 265 (unsigned char *)xsubi, sizeof(xsubi)); 266 if (0 != rc) /*(not expecting built-in entropy function to fail)*/ 267 log_failed_assert(__FILE__, __LINE__, "mbedtls_ctr_drbg_seed() failed"); 268 #endif 269 #endif 270 #endif 271 } 272 273 void li_rand_reseed (void) 274 { 275 #ifdef USE_GNUTLS_CRYPTO 276 gnutls_rnd_refresh(); 277 return; 278 #endif 279 #ifdef USE_WOLFSSL_CRYPTO 280 if (li_rand_inited) { 281 #if 0 /*(wc_RNG_DRBG_Reseed() is not part of public API)*/ 282 /*(XXX: might use stack to procure larger seed; 283 * xsubi[] is short (6 bytes)) */ 284 if (1 == li_rand_device_bytes((unsigned char *)xsubi, 285 (int)sizeof(xsubi))) { 286 if (0 != wc_RNG_DRBG_Reseed(&wolf_globalRNG, 287 (const byte *)xsubi, 288 (word32)sizeof(xsubi))) 289 /*(not expecting this to fail)*/ 290 log_failed_assert(__FILE__, __LINE__, 291 "wc_RNG_DRBG_Reseed() failed"); 292 } 293 #else 294 wc_FreeRng(&wolf_globalRNG); 295 if (0 != wc_InitRng(&wolf_globalRNG)) 296 log_failed_assert(__FILE__, __LINE__, "wc_InitRng() failed"); 297 #endif 298 return; 299 } 300 #endif 301 #ifdef USE_MBEDTLS_CRYPTO 302 if (li_rand_inited) { 303 #ifdef MBEDTLS_ENTROPY_C 304 #ifdef MBEDTLS_CTR_DRBG_C 305 mbedtls_ctr_drbg_free(&ctr_drbg); 306 #endif 307 mbedtls_entropy_free(&entropy); 308 #endif 309 } 310 #endif 311 if (li_rand_inited) li_rand_init(); 312 } 313 314 int li_rand_pseudo (void) 315 { 316 #ifdef USE_GNUTLS_CRYPTO 317 int i; 318 if (0 == gnutls_rnd(GNUTLS_RND_NONCE, &i, sizeof(i))) return i; 319 #endif 320 if (!li_rand_inited) li_rand_init(); 321 /* randomness *is not* cryptographically strong */ 322 /* (attempt to use better mechanisms to replace the more portable rand()) */ 323 #ifdef USE_OPENSSL_CRYPTO /* (openssl 1.1.0 deprecates RAND_pseudo_bytes()) */ 324 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 325 int i; 326 if (-1 != RAND_pseudo_bytes((unsigned char *)&i, sizeof(i))) return i; 327 #endif 328 #endif 329 #ifdef USE_WOLFSSL_CRYPTO 330 /* RAND_pseudo_bytes() in WolfSSL is equivalent to RAND_bytes() */ 331 int i; 332 if (0 == wc_RNG_GenerateBlock(&wolf_globalRNG,(byte *)&i,(word32)sizeof(i))) 333 return i; 334 #endif 335 #ifdef USE_NETTLE_CRYPTO 336 int i = (int)nettle_knuth_lfib_get(&knuth_lfib_ctx); 337 nettle_arcfour_crypt(&arcfour_ctx, sizeof(i), (uint8_t *)&i, (uint8_t *)&i); 338 if (i) return i; /*(cond to avoid compiler warning for code after return)*/ 339 #endif 340 #ifdef USE_MBEDTLS_CRYPTO 341 #ifdef MBEDTLS_CTR_DRBG_C 342 int i; 343 if (0 == mbedtls_ctr_drbg_random(&ctr_drbg, (unsigned char *)&i, sizeof(i))) 344 return i; 345 #endif 346 #endif 347 #ifdef HAVE_ARC4RANDOM_BUF 348 return (int)arc4random(); 349 #elif defined(__COVERITY__) 350 /* li_rand_pseudo() is not intended for cryptographic use */ 351 /* Coverity Scan ignores(?) annotation below, 352 * so hide fallback paths from Coverity Scan */ 353 return (int)(time(NULL) ^ getpid()); 354 #elif defined(HAVE_SRANDOM) 355 /* coverity[dont_call : FALSE] */ 356 return (int)random(); 357 #elif defined(HAVE_JRAND48) 358 /*(FYI: jrand48() reentrant, but use of file-scoped static xsubi[] is not)*/ 359 /* coverity[dont_call : FALSE] */ 360 return (int)jrand48(xsubi); 361 #else 362 /* coverity[dont_call : FALSE] */ 363 return rand(); 364 #endif 365 } 366 367 void li_rand_pseudo_bytes (unsigned char *buf, int num) 368 { 369 #ifdef USE_GNUTLS_CRYPTO 370 if (0 == gnutls_rnd(GNUTLS_RND_NONCE, buf, (size_t)num)) return; 371 #endif 372 if (!li_rand_inited) li_rand_init(); 373 #ifdef USE_MBEDTLS_CRYPTO 374 #ifdef MBEDTLS_CTR_DRBG_C 375 if (0 == mbedtls_ctr_drbg_random(&ctr_drbg, buf, (size_t)num)) return; 376 #endif 377 #endif 378 #ifdef USE_WOLFSSL_CRYPTO 379 /* RAND_pseudo_bytes() in WolfSSL is equivalent to RAND_bytes() */ 380 if (0 == wc_RNG_GenerateBlock(&wolf_globalRNG, (byte *)buf, (word32)num)) 381 return; 382 #endif 383 for (int i = 0; i < num; ++i) 384 buf[i] = li_rand_pseudo() & 0xFF; 385 } 386 387 int li_rand_bytes (unsigned char *buf, int num) 388 { 389 #ifdef USE_GNUTLS_CRYPTO /* should use GNUTLS_RND_KEY for long-term keys */ 390 if (0 == gnutls_rnd(GNUTLS_RND_RANDOM, buf, (size_t)num)) return 1; 391 #endif 392 #ifdef USE_NETTLE_CRYPTO 393 #if 0 /* not implemented: periodic nettle_yarrow256_update() and reseed */ 394 if (!nettle_yarrow256_is_seeded(&yarrow256_ctx)) { 395 uint8_t seed_file[YARROW256_SEED_FILE_SIZE]; 396 if (1 == li_rand_device_bytes((unsigned char *)seed_file, 397 (int)sizeof(seed_file))) { 398 nettle_yarrow256_seed(&yarrow256_ctx, sizeof(seed_file), seed_file); 399 } 400 } 401 if (nettle_yarrow256_is_seeded(&yarrow256_ctx)) { 402 nettle_yarrow256_random(&yarrow256_ctx, (size_t)num, (uint8_t *)buf); 403 return 1; 404 } 405 #endif 406 #endif 407 #ifdef USE_OPENSSL_CRYPTO 408 int rc = RAND_bytes(buf, num); 409 if (-1 != rc) { 410 return rc; 411 } 412 #endif 413 #ifdef USE_WOLFSSL_CRYPTO 414 if (0 == wc_RNG_GenerateBlock(&wolf_globalRNG, (byte *)buf, (word32)num)) { 415 return 1; 416 } 417 #endif 418 #ifdef USE_MBEDTLS_CRYPTO 419 #ifdef MBEDTLS_ENTROPY_C 420 /*(each call <= MBEDTLS_ENTROPY_BLOCK_SIZE; could implement loop here)*/ 421 if (num <= MBEDTLS_ENTROPY_BLOCK_SIZE 422 && 0 == mbedtls_entropy_func(&entropy, buf, (size_t)num)) { 423 return 1; 424 } 425 #endif 426 #endif 427 if (1 == li_rand_device_bytes(buf, num)) { 428 return 1; 429 } 430 else { 431 /* NOTE: not cryptographically random !!! */ 432 li_rand_pseudo_bytes(buf, num); 433 /*(openssl RAND_pseudo_bytes rc for non-cryptographically random data)*/ 434 return 0; 435 } 436 } 437 438 void li_rand_cleanup (void) 439 { 440 #ifdef USE_WOLFSSL_CRYPTO 441 if (li_rand_inited) { 442 wc_FreeRng(&wolf_globalRNG); 443 wolfCrypt_Cleanup(); 444 li_rand_inited = 0; 445 } 446 #endif 447 #ifdef USE_OPENSSL_CRYPTO 448 #if OPENSSL_VERSION_NUMBER < 0x10100000L 449 RAND_cleanup(); 450 #endif 451 #endif 452 #ifdef USE_MBEDTLS_CRYPTO 453 #ifdef MBEDTLS_ENTROPY_C 454 #ifdef MBEDTLS_CTR_DRBG_C 455 mbedtls_ctr_drbg_free(&ctr_drbg); 456 #endif 457 mbedtls_entropy_free(&entropy); 458 #endif 459 #endif 460 safe_memclear(xsubi, sizeof(xsubi)); 461 } 462