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