xref: /lighttpd1.4/src/rand.c (revision 1eda5074)
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