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