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