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