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