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