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