6 #include "safe_memclear.h"
17 #include "sys-crypto.h"
18 #ifdef USE_OPENSSL_CRYPTO
19 #include <openssl/opensslv.h> /* OPENSSL_VERSION_NUMBER */
20 #include <openssl/rand.h>
22 #ifdef HAVE_GETENTROPY
23 #include <sys/random.h>
25 #ifdef HAVE_LINUX_RANDOM_H
26 #include <sys/syscall.h>
27 #include <linux/random.h>
30 #include <sys/ioctl.h>
33 /* Take some reasonable steps to attempt to *seed* random number generators with
34 * cryptographically random data. Some of these initialization routines may
35 * block, and are intended to be called only at startup in lighttpd, or
36 * immediately after fork() to start lighttpd workers.
38 * Update: li_rand_init() is now deferred until first use so that installations
39 * that do not use modules which use these routines do need to potentially block
40 * at startup. Current use by core lighttpd modules is in mod_auth HTTP Digest
41 * auth and in mod_usertrack. Deferring collection of random data until first
42 * use may allow sufficient entropy to be collected by kernel before first use,
43 * helping reduce or avoid situations in low-entropy-generating embedded devices
44 * which might otherwise block lighttpd for minutes at device startup.
45 * Further discussion in https://redmine.lighttpd.net/boards/2/topics/6981
47 * Note: results from li_rand_pseudo_bytes() are not necessarily
48 * cryptographically random and must not be used for purposes such
49 * as key generation which require cryptographic randomness.
51 * https://wiki.openssl.org/index.php/Random_Numbers
52 * https://wiki.openssl.org/index.php/Random_fork-safety
54 * openssl random number generators are not thread-safe by default
55 * https://wiki.openssl.org/index.php/Manual:Threads(3)
57 * RFE: add more paranoid checks from the following to improve confidence:
58 * http://insanecoding.blogspot.co.uk/2014/05/a-good-idea-with-bad-usage-devurandom.html
60 * RFE: check RAND_status()
63 static int li_getentropy (void *buf
, size_t buflen
)
65 #ifdef HAVE_GETENTROPY
66 return getentropy(buf
, buflen
);
68 /*(see NOTES section in 'man getrandom' on Linux)*/
69 #if defined(HAVE_GETRANDOM) || defined(SYS_getrandom)
71 #ifdef HAVE_GETRANDOM /*(not implemented in glibc yet)*/
72 int num
= getrandom(buf
, buflen
, 0);
73 #elif defined(SYS_getrandom)
74 /* https://lwn.net/Articles/605828/ */
75 /* https://bbs.archlinux.org/viewtopic.php?id=200039 */
76 int num
= (int)syscall(SYS_getrandom
, buf
, buflen
, 0);
78 if (num
== (int)buflen
) return 0;
79 if (num
< 0) return num
; /* -1 */
90 static int li_rand_device_bytes (unsigned char *buf
, int num
)
92 /* randomness from these devices is cryptographically strong,
93 * unless /dev/urandom is low on entropy */
95 static const char * const devices
[] = {
103 /* device files might not be available in chroot environment,
104 * so prefer syscall, if available */
105 if (0 == li_getentropy(buf
, (size_t)num
)) return 1;
107 for (unsigned int u
= 0; u
< sizeof(devices
)/sizeof(devices
[0]); ++u
) {
108 /*(some systems might have symlink to another device; omit O_NOFOLLOW)*/
109 int fd
= fdevent_open_cloexec(devices
[u
], 0, O_RDONLY
, 0);
114 if (0 == ioctl(fd
, (unsigned long)(RNDGETENTCNT
), &entropy
)
117 rd
= read(fd
, buf
, (size_t)num
);
128 static int li_rand_inited
;
129 static unsigned short xsubi
[3];
131 static void li_rand_init (void)
133 /* (intended to be called at init and after fork() in order to re-seed PRNG
134 * so that forked children, grandchildren, etc do not share PRNG seed)
135 * https://github.com/ramsey/uuid/issues/80
136 * https://www.agwa.name/blog/post/libressls_prng_is_unsafe_on_linux
137 * (issue in early version of libressl has since been fixed)
138 * https://github.com/libressl-portable/portable/commit/32d9eeeecf4e951e1566d5f4a42b36ea37b60f35
142 if (1 == li_rand_device_bytes((unsigned char *)xsubi
, (int)sizeof(xsubi
))) {
143 u
= ((unsigned int)xsubi
[0] << 16) | xsubi
[1];
146 #ifdef HAVE_ARC4RANDOM_BUF
148 arc4random_buf(xsubi
, sizeof(xsubi
));
150 /* NOTE: not cryptographically random !!! */
151 srand((unsigned int)(time(NULL
) ^ getpid()));
152 for (u
= 0; u
< sizeof(unsigned short); ++u
)
153 /* coverity[dont_call : FALSE] */
154 xsubi
[u
] = (unsigned short)(rand() & 0xFFFF);
155 u
= ((unsigned int)xsubi
[0] << 16) | xsubi
[1];
158 srand(u
); /*(initialize just in case rand() used elsewhere)*/
160 srandom(u
); /*(initialize just in case random() used elsewhere)*/
162 #ifdef USE_OPENSSL_CRYPTO
164 RAND_seed(xsubi
, (int)sizeof(xsubi
));
168 void li_rand_reseed (void)
170 if (li_rand_inited
) li_rand_init();
173 int li_rand_pseudo (void)
175 /* randomness *is not* cryptographically strong */
176 /* (attempt to use better mechanisms to replace the more portable rand()) */
177 #ifdef USE_OPENSSL_CRYPTO /* (openssl 1.1.0 deprecates RAND_pseudo_bytes()) */
178 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
180 if (-1 != RAND_pseudo_bytes((unsigned char *)&i
, sizeof(i
))) return i
;
183 if (!li_rand_inited
) li_rand_init();
184 #ifdef HAVE_ARC4RANDOM_BUF
185 return (int)arc4random();
186 #elif defined(HAVE_SRANDOM)
187 /* coverity[dont_call : FALSE] */
188 return (int)random();
189 #elif defined(HAVE_JRAND48)
190 /*(FYI: jrand48() reentrant, but use of file-scoped static xsubi[] is not)*/
191 /* coverity[dont_call : FALSE] */
192 return (int)jrand48(xsubi
);
194 /* coverity[dont_call : FALSE] */
199 void li_rand_pseudo_bytes (unsigned char *buf
, int num
)
201 for (int i
= 0; i
< num
; ++i
)
202 buf
[i
] = li_rand_pseudo() & 0xFF;
205 int li_rand_bytes (unsigned char *buf
, int num
)
207 #ifdef USE_OPENSSL_CRYPTO
208 int rc
= RAND_bytes(buf
, num
);
213 if (1 == li_rand_device_bytes(buf
, num
)) {
217 /* NOTE: not cryptographically random !!! */
218 li_rand_pseudo_bytes(buf
, num
);
219 /*(openssl RAND_pseudo_bytes rc for non-cryptographically random data)*/
224 void li_rand_cleanup (void)
226 #ifdef USE_OPENSSL_CRYPTO
227 #if OPENSSL_VERSION_NUMBER < 0x10100000L
231 safe_memclear(xsubi
, sizeof(xsubi
));