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