1*b077aed3SPierre Pronchery /*
2*b077aed3SPierre Pronchery  * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
3*b077aed3SPierre Pronchery  *
4*b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5*b077aed3SPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6*b077aed3SPierre Pronchery  * in the file LICENSE in the source distribution or at
7*b077aed3SPierre Pronchery  * https://www.openssl.org/source/license.html
8*b077aed3SPierre Pronchery  */
9*b077aed3SPierre Pronchery 
10*b077aed3SPierre Pronchery #ifndef _GNU_SOURCE
11*b077aed3SPierre Pronchery # define _GNU_SOURCE
12*b077aed3SPierre Pronchery #endif
13*b077aed3SPierre Pronchery #include "../e_os.h"
14*b077aed3SPierre Pronchery #include <stdio.h>
15*b077aed3SPierre Pronchery #include "internal/cryptlib.h"
16*b077aed3SPierre Pronchery #include <openssl/rand.h>
17*b077aed3SPierre Pronchery #include <openssl/crypto.h>
18*b077aed3SPierre Pronchery #include "crypto/rand_pool.h"
19*b077aed3SPierre Pronchery #include "crypto/rand.h"
20*b077aed3SPierre Pronchery #include <stdio.h>
21*b077aed3SPierre Pronchery #include "internal/dso.h"
22*b077aed3SPierre Pronchery #include "prov/seeding.h"
23*b077aed3SPierre Pronchery 
24*b077aed3SPierre Pronchery #ifdef __linux
25*b077aed3SPierre Pronchery # include <sys/syscall.h>
26*b077aed3SPierre Pronchery # ifdef DEVRANDOM_WAIT
27*b077aed3SPierre Pronchery #  include <sys/shm.h>
28*b077aed3SPierre Pronchery #  include <sys/utsname.h>
29*b077aed3SPierre Pronchery # endif
30*b077aed3SPierre Pronchery #endif
31*b077aed3SPierre Pronchery #if (defined(__FreeBSD__) || defined(__NetBSD__)) && !defined(OPENSSL_SYS_UEFI)
32*b077aed3SPierre Pronchery # include <sys/types.h>
33*b077aed3SPierre Pronchery # include <sys/sysctl.h>
34*b077aed3SPierre Pronchery # include <sys/param.h>
35*b077aed3SPierre Pronchery #endif
36*b077aed3SPierre Pronchery #if defined(__OpenBSD__)
37*b077aed3SPierre Pronchery # include <sys/param.h>
38*b077aed3SPierre Pronchery #endif
39*b077aed3SPierre Pronchery #if defined(__DragonFly__)
40*b077aed3SPierre Pronchery # include <sys/param.h>
41*b077aed3SPierre Pronchery # include <sys/random.h>
42*b077aed3SPierre Pronchery #endif
43*b077aed3SPierre Pronchery 
44*b077aed3SPierre Pronchery #if (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS)) \
45*b077aed3SPierre Pronchery      || defined(__DJGPP__)
46*b077aed3SPierre Pronchery # include <sys/types.h>
47*b077aed3SPierre Pronchery # include <sys/stat.h>
48*b077aed3SPierre Pronchery # include <fcntl.h>
49*b077aed3SPierre Pronchery # include <unistd.h>
50*b077aed3SPierre Pronchery # include <sys/time.h>
51*b077aed3SPierre Pronchery 
52*b077aed3SPierre Pronchery static uint64_t get_time_stamp(void);
53*b077aed3SPierre Pronchery static uint64_t get_timer_bits(void);
54*b077aed3SPierre Pronchery 
55*b077aed3SPierre Pronchery /* Macro to convert two thirty two bit values into a sixty four bit one */
56*b077aed3SPierre Pronchery # define TWO32TO64(a, b) ((((uint64_t)(a)) << 32) + (b))
57*b077aed3SPierre Pronchery 
58*b077aed3SPierre Pronchery /*
59*b077aed3SPierre Pronchery  * Check for the existence and support of POSIX timers.  The standard
60*b077aed3SPierre Pronchery  * says that the _POSIX_TIMERS macro will have a positive value if they
61*b077aed3SPierre Pronchery  * are available.
62*b077aed3SPierre Pronchery  *
63*b077aed3SPierre Pronchery  * However, we want an additional constraint: that the timer support does
64*b077aed3SPierre Pronchery  * not require an extra library dependency.  Early versions of glibc
65*b077aed3SPierre Pronchery  * require -lrt to be specified on the link line to access the timers,
66*b077aed3SPierre Pronchery  * so this needs to be checked for.
67*b077aed3SPierre Pronchery  *
68*b077aed3SPierre Pronchery  * It is worse because some libraries define __GLIBC__ but don't
69*b077aed3SPierre Pronchery  * support the version testing macro (e.g. uClibc).  This means
70*b077aed3SPierre Pronchery  * an extra check is needed.
71*b077aed3SPierre Pronchery  *
72*b077aed3SPierre Pronchery  * The final condition is:
73*b077aed3SPierre Pronchery  *      "have posix timers and either not glibc or glibc without -lrt"
74*b077aed3SPierre Pronchery  *
75*b077aed3SPierre Pronchery  * The nested #if sequences are required to avoid using a parameterised
76*b077aed3SPierre Pronchery  * macro that might be undefined.
77*b077aed3SPierre Pronchery  */
78*b077aed3SPierre Pronchery # undef OSSL_POSIX_TIMER_OKAY
79*b077aed3SPierre Pronchery /* On some systems, _POSIX_TIMERS is defined but empty.
80*b077aed3SPierre Pronchery  * Subtracting by 0 when comparing avoids an error in this case. */
81*b077aed3SPierre Pronchery # if defined(_POSIX_TIMERS) && _POSIX_TIMERS -0 > 0
82*b077aed3SPierre Pronchery #  if defined(__GLIBC__)
83*b077aed3SPierre Pronchery #   if defined(__GLIBC_PREREQ)
84*b077aed3SPierre Pronchery #    if __GLIBC_PREREQ(2, 17)
85*b077aed3SPierre Pronchery #     define OSSL_POSIX_TIMER_OKAY
86*b077aed3SPierre Pronchery #    endif
87*b077aed3SPierre Pronchery #   endif
88*b077aed3SPierre Pronchery #  else
89*b077aed3SPierre Pronchery #   define OSSL_POSIX_TIMER_OKAY
90*b077aed3SPierre Pronchery #  endif
91*b077aed3SPierre Pronchery # endif
92*b077aed3SPierre Pronchery #endif /* (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS))
93*b077aed3SPierre Pronchery           || defined(__DJGPP__) */
94*b077aed3SPierre Pronchery 
95*b077aed3SPierre Pronchery #if defined(OPENSSL_RAND_SEED_NONE)
96*b077aed3SPierre Pronchery /* none means none. this simplifies the following logic */
97*b077aed3SPierre Pronchery # undef OPENSSL_RAND_SEED_OS
98*b077aed3SPierre Pronchery # undef OPENSSL_RAND_SEED_GETRANDOM
99*b077aed3SPierre Pronchery # undef OPENSSL_RAND_SEED_LIBRANDOM
100*b077aed3SPierre Pronchery # undef OPENSSL_RAND_SEED_DEVRANDOM
101*b077aed3SPierre Pronchery # undef OPENSSL_RAND_SEED_RDTSC
102*b077aed3SPierre Pronchery # undef OPENSSL_RAND_SEED_RDCPU
103*b077aed3SPierre Pronchery # undef OPENSSL_RAND_SEED_EGD
104*b077aed3SPierre Pronchery #endif
105*b077aed3SPierre Pronchery 
106*b077aed3SPierre Pronchery #if defined(OPENSSL_SYS_UEFI) && !defined(OPENSSL_RAND_SEED_NONE)
107*b077aed3SPierre Pronchery # error "UEFI only supports seeding NONE"
108*b077aed3SPierre Pronchery #endif
109*b077aed3SPierre Pronchery 
110*b077aed3SPierre Pronchery #if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) \
111*b077aed3SPierre Pronchery     || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_VXWORKS) \
112*b077aed3SPierre Pronchery     || defined(OPENSSL_SYS_UEFI))
113*b077aed3SPierre Pronchery 
114*b077aed3SPierre Pronchery # if defined(OPENSSL_SYS_VOS)
115*b077aed3SPierre Pronchery 
116*b077aed3SPierre Pronchery #  ifndef OPENSSL_RAND_SEED_OS
117*b077aed3SPierre Pronchery #   error "Unsupported seeding method configured; must be os"
118*b077aed3SPierre Pronchery #  endif
119*b077aed3SPierre Pronchery 
120*b077aed3SPierre Pronchery #  if defined(OPENSSL_SYS_VOS_HPPA) && defined(OPENSSL_SYS_VOS_IA32)
121*b077aed3SPierre Pronchery #   error "Unsupported HP-PA and IA32 at the same time."
122*b077aed3SPierre Pronchery #  endif
123*b077aed3SPierre Pronchery #  if !defined(OPENSSL_SYS_VOS_HPPA) && !defined(OPENSSL_SYS_VOS_IA32)
124*b077aed3SPierre Pronchery #   error "Must have one of HP-PA or IA32"
125*b077aed3SPierre Pronchery #  endif
126*b077aed3SPierre Pronchery 
127*b077aed3SPierre Pronchery /*
128*b077aed3SPierre Pronchery  * The following algorithm repeatedly samples the real-time clock (RTC) to
129*b077aed3SPierre Pronchery  * generate a sequence of unpredictable data.  The algorithm relies upon the
130*b077aed3SPierre Pronchery  * uneven execution speed of the code (due to factors such as cache misses,
131*b077aed3SPierre Pronchery  * interrupts, bus activity, and scheduling) and upon the rather large
132*b077aed3SPierre Pronchery  * relative difference between the speed of the clock and the rate at which
133*b077aed3SPierre Pronchery  * it can be read.  If it is ported to an environment where execution speed
134*b077aed3SPierre Pronchery  * is more constant or where the RTC ticks at a much slower rate, or the
135*b077aed3SPierre Pronchery  * clock can be read with fewer instructions, it is likely that the results
136*b077aed3SPierre Pronchery  * would be far more predictable.  This should only be used for legacy
137*b077aed3SPierre Pronchery  * platforms.
138*b077aed3SPierre Pronchery  *
139*b077aed3SPierre Pronchery  * As a precaution, we assume only 2 bits of entropy per byte.
140*b077aed3SPierre Pronchery  */
ossl_pool_acquire_entropy(RAND_POOL * pool)141*b077aed3SPierre Pronchery size_t ossl_pool_acquire_entropy(RAND_POOL *pool)
142*b077aed3SPierre Pronchery {
143*b077aed3SPierre Pronchery     short int code;
144*b077aed3SPierre Pronchery     int i, k;
145*b077aed3SPierre Pronchery     size_t bytes_needed;
146*b077aed3SPierre Pronchery     struct timespec ts;
147*b077aed3SPierre Pronchery     unsigned char v;
148*b077aed3SPierre Pronchery #  ifdef OPENSSL_SYS_VOS_HPPA
149*b077aed3SPierre Pronchery     long duration;
150*b077aed3SPierre Pronchery     extern void s$sleep(long *_duration, short int *_code);
151*b077aed3SPierre Pronchery #  else
152*b077aed3SPierre Pronchery     long long duration;
153*b077aed3SPierre Pronchery     extern void s$sleep2(long long *_duration, short int *_code);
154*b077aed3SPierre Pronchery #  endif
155*b077aed3SPierre Pronchery 
156*b077aed3SPierre Pronchery     bytes_needed = ossl_rand_pool_bytes_needed(pool, 4 /*entropy_factor*/);
157*b077aed3SPierre Pronchery 
158*b077aed3SPierre Pronchery     for (i = 0; i < bytes_needed; i++) {
159*b077aed3SPierre Pronchery         /*
160*b077aed3SPierre Pronchery          * burn some cpu; hope for interrupts, cache collisions, bus
161*b077aed3SPierre Pronchery          * interference, etc.
162*b077aed3SPierre Pronchery          */
163*b077aed3SPierre Pronchery         for (k = 0; k < 99; k++)
164*b077aed3SPierre Pronchery             ts.tv_nsec = random();
165*b077aed3SPierre Pronchery 
166*b077aed3SPierre Pronchery #  ifdef OPENSSL_SYS_VOS_HPPA
167*b077aed3SPierre Pronchery         /* sleep for 1/1024 of a second (976 us).  */
168*b077aed3SPierre Pronchery         duration = 1;
169*b077aed3SPierre Pronchery         s$sleep(&duration, &code);
170*b077aed3SPierre Pronchery #  else
171*b077aed3SPierre Pronchery         /* sleep for 1/65536 of a second (15 us).  */
172*b077aed3SPierre Pronchery         duration = 1;
173*b077aed3SPierre Pronchery         s$sleep2(&duration, &code);
174*b077aed3SPierre Pronchery #  endif
175*b077aed3SPierre Pronchery 
176*b077aed3SPierre Pronchery         /* Get wall clock time, take 8 bits. */
177*b077aed3SPierre Pronchery         clock_gettime(CLOCK_REALTIME, &ts);
178*b077aed3SPierre Pronchery         v = (unsigned char)(ts.tv_nsec & 0xFF);
179*b077aed3SPierre Pronchery         ossl_rand_pool_add(pool, arg, &v, sizeof(v) , 2);
180*b077aed3SPierre Pronchery     }
181*b077aed3SPierre Pronchery     return ossl_rand_pool_entropy_available(pool);
182*b077aed3SPierre Pronchery }
183*b077aed3SPierre Pronchery 
ossl_rand_pool_cleanup(void)184*b077aed3SPierre Pronchery void ossl_rand_pool_cleanup(void)
185*b077aed3SPierre Pronchery {
186*b077aed3SPierre Pronchery }
187*b077aed3SPierre Pronchery 
ossl_rand_pool_keep_random_devices_open(int keep)188*b077aed3SPierre Pronchery void ossl_rand_pool_keep_random_devices_open(int keep)
189*b077aed3SPierre Pronchery {
190*b077aed3SPierre Pronchery }
191*b077aed3SPierre Pronchery 
192*b077aed3SPierre Pronchery # else
193*b077aed3SPierre Pronchery 
194*b077aed3SPierre Pronchery #  if defined(OPENSSL_RAND_SEED_EGD) && \
195*b077aed3SPierre Pronchery         (defined(OPENSSL_NO_EGD) || !defined(DEVRANDOM_EGD))
196*b077aed3SPierre Pronchery #   error "Seeding uses EGD but EGD is turned off or no device given"
197*b077aed3SPierre Pronchery #  endif
198*b077aed3SPierre Pronchery 
199*b077aed3SPierre Pronchery #  if defined(OPENSSL_RAND_SEED_DEVRANDOM) && !defined(DEVRANDOM)
200*b077aed3SPierre Pronchery #   error "Seeding uses urandom but DEVRANDOM is not configured"
201*b077aed3SPierre Pronchery #  endif
202*b077aed3SPierre Pronchery 
203*b077aed3SPierre Pronchery #  if defined(OPENSSL_RAND_SEED_OS)
204*b077aed3SPierre Pronchery #   if !defined(DEVRANDOM)
205*b077aed3SPierre Pronchery #    error "OS seeding requires DEVRANDOM to be configured"
206*b077aed3SPierre Pronchery #   endif
207*b077aed3SPierre Pronchery #   define OPENSSL_RAND_SEED_GETRANDOM
208*b077aed3SPierre Pronchery #   define OPENSSL_RAND_SEED_DEVRANDOM
209*b077aed3SPierre Pronchery #  endif
210*b077aed3SPierre Pronchery 
211*b077aed3SPierre Pronchery #  if defined(OPENSSL_RAND_SEED_LIBRANDOM)
212*b077aed3SPierre Pronchery #   error "librandom not (yet) supported"
213*b077aed3SPierre Pronchery #  endif
214*b077aed3SPierre Pronchery 
215*b077aed3SPierre Pronchery #  if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
216*b077aed3SPierre Pronchery /*
217*b077aed3SPierre Pronchery  * sysctl_random(): Use sysctl() to read a random number from the kernel
218*b077aed3SPierre Pronchery  * Returns the number of bytes returned in buf on success, -1 on failure.
219*b077aed3SPierre Pronchery  */
sysctl_random(char * buf,size_t buflen)220*b077aed3SPierre Pronchery static ssize_t sysctl_random(char *buf, size_t buflen)
221*b077aed3SPierre Pronchery {
222*b077aed3SPierre Pronchery     int mib[2];
223*b077aed3SPierre Pronchery     size_t done = 0;
224*b077aed3SPierre Pronchery     size_t len;
225*b077aed3SPierre Pronchery 
226*b077aed3SPierre Pronchery     /*
227*b077aed3SPierre Pronchery      * Note: sign conversion between size_t and ssize_t is safe even
228*b077aed3SPierre Pronchery      * without a range check, see comment in syscall_random()
229*b077aed3SPierre Pronchery      */
230*b077aed3SPierre Pronchery 
231*b077aed3SPierre Pronchery     /*
232*b077aed3SPierre Pronchery      * On FreeBSD old implementations returned longs, newer versions support
233*b077aed3SPierre Pronchery      * variable sizes up to 256 byte. The code below would not work properly
234*b077aed3SPierre Pronchery      * when the sysctl returns long and we want to request something not a
235*b077aed3SPierre Pronchery      * multiple of longs, which should never be the case.
236*b077aed3SPierre Pronchery      */
237*b077aed3SPierre Pronchery #if   defined(__FreeBSD__)
238*b077aed3SPierre Pronchery     if (!ossl_assert(buflen % sizeof(long) == 0)) {
239*b077aed3SPierre Pronchery         errno = EINVAL;
240*b077aed3SPierre Pronchery         return -1;
241*b077aed3SPierre Pronchery     }
242*b077aed3SPierre Pronchery #endif
243*b077aed3SPierre Pronchery 
244*b077aed3SPierre Pronchery     /*
245*b077aed3SPierre Pronchery      * On NetBSD before 4.0 KERN_ARND was an alias for KERN_URND, and only
246*b077aed3SPierre Pronchery      * filled in an int, leaving the rest uninitialized. Since NetBSD 4.0
247*b077aed3SPierre Pronchery      * it returns a variable number of bytes with the current version supporting
248*b077aed3SPierre Pronchery      * up to 256 bytes.
249*b077aed3SPierre Pronchery      * Just return an error on older NetBSD versions.
250*b077aed3SPierre Pronchery      */
251*b077aed3SPierre Pronchery #if   defined(__NetBSD__) && __NetBSD_Version__ < 400000000
252*b077aed3SPierre Pronchery     errno = ENOSYS;
253*b077aed3SPierre Pronchery     return -1;
254*b077aed3SPierre Pronchery #endif
255*b077aed3SPierre Pronchery 
256*b077aed3SPierre Pronchery     mib[0] = CTL_KERN;
257*b077aed3SPierre Pronchery     mib[1] = KERN_ARND;
258*b077aed3SPierre Pronchery 
259*b077aed3SPierre Pronchery     do {
260*b077aed3SPierre Pronchery         len = buflen > 256 ? 256 : buflen;
261*b077aed3SPierre Pronchery         if (sysctl(mib, 2, buf, &len, NULL, 0) == -1)
262*b077aed3SPierre Pronchery             return done > 0 ? done : -1;
263*b077aed3SPierre Pronchery         done += len;
264*b077aed3SPierre Pronchery         buf += len;
265*b077aed3SPierre Pronchery         buflen -= len;
266*b077aed3SPierre Pronchery     } while (buflen > 0);
267*b077aed3SPierre Pronchery 
268*b077aed3SPierre Pronchery     return done;
269*b077aed3SPierre Pronchery }
270*b077aed3SPierre Pronchery #  endif
271*b077aed3SPierre Pronchery 
272*b077aed3SPierre Pronchery #  if defined(OPENSSL_RAND_SEED_GETRANDOM)
273*b077aed3SPierre Pronchery 
274*b077aed3SPierre Pronchery #   if defined(__linux) && !defined(__NR_getrandom)
275*b077aed3SPierre Pronchery #    if defined(__arm__)
276*b077aed3SPierre Pronchery #     define __NR_getrandom    (__NR_SYSCALL_BASE+384)
277*b077aed3SPierre Pronchery #    elif defined(__i386__)
278*b077aed3SPierre Pronchery #     define __NR_getrandom    355
279*b077aed3SPierre Pronchery #    elif defined(__x86_64__)
280*b077aed3SPierre Pronchery #     if defined(__ILP32__)
281*b077aed3SPierre Pronchery #      define __NR_getrandom   (__X32_SYSCALL_BIT + 318)
282*b077aed3SPierre Pronchery #     else
283*b077aed3SPierre Pronchery #      define __NR_getrandom   318
284*b077aed3SPierre Pronchery #     endif
285*b077aed3SPierre Pronchery #    elif defined(__xtensa__)
286*b077aed3SPierre Pronchery #     define __NR_getrandom    338
287*b077aed3SPierre Pronchery #    elif defined(__s390__) || defined(__s390x__)
288*b077aed3SPierre Pronchery #     define __NR_getrandom    349
289*b077aed3SPierre Pronchery #    elif defined(__bfin__)
290*b077aed3SPierre Pronchery #     define __NR_getrandom    389
291*b077aed3SPierre Pronchery #    elif defined(__powerpc__)
292*b077aed3SPierre Pronchery #     define __NR_getrandom    359
293*b077aed3SPierre Pronchery #    elif defined(__mips__) || defined(__mips64)
294*b077aed3SPierre Pronchery #     if _MIPS_SIM == _MIPS_SIM_ABI32
295*b077aed3SPierre Pronchery #      define __NR_getrandom   (__NR_Linux + 353)
296*b077aed3SPierre Pronchery #     elif _MIPS_SIM == _MIPS_SIM_ABI64
297*b077aed3SPierre Pronchery #      define __NR_getrandom   (__NR_Linux + 313)
298*b077aed3SPierre Pronchery #     elif _MIPS_SIM == _MIPS_SIM_NABI32
299*b077aed3SPierre Pronchery #      define __NR_getrandom   (__NR_Linux + 317)
300*b077aed3SPierre Pronchery #     endif
301*b077aed3SPierre Pronchery #    elif defined(__hppa__)
302*b077aed3SPierre Pronchery #     define __NR_getrandom    (__NR_Linux + 339)
303*b077aed3SPierre Pronchery #    elif defined(__sparc__)
304*b077aed3SPierre Pronchery #     define __NR_getrandom    347
305*b077aed3SPierre Pronchery #    elif defined(__ia64__)
306*b077aed3SPierre Pronchery #     define __NR_getrandom    1339
307*b077aed3SPierre Pronchery #    elif defined(__alpha__)
308*b077aed3SPierre Pronchery #     define __NR_getrandom    511
309*b077aed3SPierre Pronchery #    elif defined(__sh__)
310*b077aed3SPierre Pronchery #     if defined(__SH5__)
311*b077aed3SPierre Pronchery #      define __NR_getrandom   373
312*b077aed3SPierre Pronchery #     else
313*b077aed3SPierre Pronchery #      define __NR_getrandom   384
314*b077aed3SPierre Pronchery #     endif
315*b077aed3SPierre Pronchery #    elif defined(__avr32__)
316*b077aed3SPierre Pronchery #     define __NR_getrandom    317
317*b077aed3SPierre Pronchery #    elif defined(__microblaze__)
318*b077aed3SPierre Pronchery #     define __NR_getrandom    385
319*b077aed3SPierre Pronchery #    elif defined(__m68k__)
320*b077aed3SPierre Pronchery #     define __NR_getrandom    352
321*b077aed3SPierre Pronchery #    elif defined(__cris__)
322*b077aed3SPierre Pronchery #     define __NR_getrandom    356
323*b077aed3SPierre Pronchery #    elif defined(__aarch64__)
324*b077aed3SPierre Pronchery #     define __NR_getrandom    278
325*b077aed3SPierre Pronchery #    else /* generic */
326*b077aed3SPierre Pronchery #     define __NR_getrandom    278
327*b077aed3SPierre Pronchery #    endif
328*b077aed3SPierre Pronchery #   endif
329*b077aed3SPierre Pronchery 
330*b077aed3SPierre Pronchery /*
331*b077aed3SPierre Pronchery  * syscall_random(): Try to get random data using a system call
332*b077aed3SPierre Pronchery  * returns the number of bytes returned in buf, or < 0 on error.
333*b077aed3SPierre Pronchery  */
syscall_random(void * buf,size_t buflen)334*b077aed3SPierre Pronchery static ssize_t syscall_random(void *buf, size_t buflen)
335*b077aed3SPierre Pronchery {
336*b077aed3SPierre Pronchery     /*
337*b077aed3SPierre Pronchery      * Note: 'buflen' equals the size of the buffer which is used by the
338*b077aed3SPierre Pronchery      * get_entropy() callback of the RAND_DRBG. It is roughly bounded by
339*b077aed3SPierre Pronchery      *
340*b077aed3SPierre Pronchery      *   2 * RAND_POOL_FACTOR * (RAND_DRBG_STRENGTH / 8) = 2^14
341*b077aed3SPierre Pronchery      *
342*b077aed3SPierre Pronchery      * which is way below the OSSL_SSIZE_MAX limit. Therefore sign conversion
343*b077aed3SPierre Pronchery      * between size_t and ssize_t is safe even without a range check.
344*b077aed3SPierre Pronchery      */
345*b077aed3SPierre Pronchery 
346*b077aed3SPierre Pronchery     /*
347*b077aed3SPierre Pronchery      * Do runtime detection to find getentropy().
348*b077aed3SPierre Pronchery      *
349*b077aed3SPierre Pronchery      * Known OSs that should support this:
350*b077aed3SPierre Pronchery      * - Darwin since 16 (OSX 10.12, IOS 10.0).
351*b077aed3SPierre Pronchery      * - Solaris since 11.3
352*b077aed3SPierre Pronchery      * - OpenBSD since 5.6
353*b077aed3SPierre Pronchery      * - Linux since 3.17 with glibc 2.25
354*b077aed3SPierre Pronchery      * - FreeBSD since 12.0 (1200061)
355*b077aed3SPierre Pronchery      *
356*b077aed3SPierre Pronchery      * Note: Sometimes getentropy() can be provided but not implemented
357*b077aed3SPierre Pronchery      * internally. So we need to check errno for ENOSYS
358*b077aed3SPierre Pronchery      */
359*b077aed3SPierre Pronchery #  if !defined(__DragonFly__) && !defined(__NetBSD__)
360*b077aed3SPierre Pronchery #    if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux)
361*b077aed3SPierre Pronchery     extern int getentropy(void *buffer, size_t length) __attribute__((weak));
362*b077aed3SPierre Pronchery 
363*b077aed3SPierre Pronchery     if (getentropy != NULL) {
364*b077aed3SPierre Pronchery         if (getentropy(buf, buflen) == 0)
365*b077aed3SPierre Pronchery             return (ssize_t)buflen;
366*b077aed3SPierre Pronchery         if (errno != ENOSYS)
367*b077aed3SPierre Pronchery             return -1;
368*b077aed3SPierre Pronchery     }
369*b077aed3SPierre Pronchery #    elif defined(OPENSSL_APPLE_CRYPTO_RANDOM)
370*b077aed3SPierre Pronchery 
371*b077aed3SPierre Pronchery     if (CCRandomGenerateBytes(buf, buflen) == kCCSuccess)
372*b077aed3SPierre Pronchery 	    return (ssize_t)buflen;
373*b077aed3SPierre Pronchery 
374*b077aed3SPierre Pronchery     return -1;
375*b077aed3SPierre Pronchery #    else
376*b077aed3SPierre Pronchery     union {
377*b077aed3SPierre Pronchery         void *p;
378*b077aed3SPierre Pronchery         int (*f)(void *buffer, size_t length);
379*b077aed3SPierre Pronchery     } p_getentropy;
380*b077aed3SPierre Pronchery 
381*b077aed3SPierre Pronchery     /*
382*b077aed3SPierre Pronchery      * We could cache the result of the lookup, but we normally don't
383*b077aed3SPierre Pronchery      * call this function often.
384*b077aed3SPierre Pronchery      */
385*b077aed3SPierre Pronchery     ERR_set_mark();
386*b077aed3SPierre Pronchery     p_getentropy.p = DSO_global_lookup("getentropy");
387*b077aed3SPierre Pronchery     ERR_pop_to_mark();
388*b077aed3SPierre Pronchery     if (p_getentropy.p != NULL)
389*b077aed3SPierre Pronchery         return p_getentropy.f(buf, buflen) == 0 ? (ssize_t)buflen : -1;
390*b077aed3SPierre Pronchery #    endif
391*b077aed3SPierre Pronchery #  endif /* !__DragonFly__ */
392*b077aed3SPierre Pronchery 
393*b077aed3SPierre Pronchery     /* Linux supports this since version 3.17 */
394*b077aed3SPierre Pronchery #  if defined(__linux) && defined(__NR_getrandom)
395*b077aed3SPierre Pronchery     return syscall(__NR_getrandom, buf, buflen, 0);
396*b077aed3SPierre Pronchery #  elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
397*b077aed3SPierre Pronchery     return sysctl_random(buf, buflen);
398*b077aed3SPierre Pronchery #  elif (defined(__DragonFly__)  && __DragonFly_version >= 500700) \
399*b077aed3SPierre Pronchery      || (defined(__NetBSD__) && __NetBSD_Version >= 1000000000)
400*b077aed3SPierre Pronchery     return getrandom(buf, buflen, 0);
401*b077aed3SPierre Pronchery #  else
402*b077aed3SPierre Pronchery     errno = ENOSYS;
403*b077aed3SPierre Pronchery     return -1;
404*b077aed3SPierre Pronchery #  endif
405*b077aed3SPierre Pronchery }
406*b077aed3SPierre Pronchery #  endif    /* defined(OPENSSL_RAND_SEED_GETRANDOM) */
407*b077aed3SPierre Pronchery 
408*b077aed3SPierre Pronchery #  if defined(OPENSSL_RAND_SEED_DEVRANDOM)
409*b077aed3SPierre Pronchery static const char *random_device_paths[] = { DEVRANDOM };
410*b077aed3SPierre Pronchery static struct random_device {
411*b077aed3SPierre Pronchery     int fd;
412*b077aed3SPierre Pronchery     dev_t dev;
413*b077aed3SPierre Pronchery     ino_t ino;
414*b077aed3SPierre Pronchery     mode_t mode;
415*b077aed3SPierre Pronchery     dev_t rdev;
416*b077aed3SPierre Pronchery } random_devices[OSSL_NELEM(random_device_paths)];
417*b077aed3SPierre Pronchery static int keep_random_devices_open = 1;
418*b077aed3SPierre Pronchery 
419*b077aed3SPierre Pronchery #   if defined(__linux) && defined(DEVRANDOM_WAIT) \
420*b077aed3SPierre Pronchery        && defined(OPENSSL_RAND_SEED_GETRANDOM)
421*b077aed3SPierre Pronchery static void *shm_addr;
422*b077aed3SPierre Pronchery 
cleanup_shm(void)423*b077aed3SPierre Pronchery static void cleanup_shm(void)
424*b077aed3SPierre Pronchery {
425*b077aed3SPierre Pronchery     shmdt(shm_addr);
426*b077aed3SPierre Pronchery }
427*b077aed3SPierre Pronchery 
428*b077aed3SPierre Pronchery /*
429*b077aed3SPierre Pronchery  * Ensure that the system randomness source has been adequately seeded.
430*b077aed3SPierre Pronchery  * This is done by having the first start of libcrypto, wait until the device
431*b077aed3SPierre Pronchery  * /dev/random becomes able to supply a byte of entropy.  Subsequent starts
432*b077aed3SPierre Pronchery  * of the library and later reseedings do not need to do this.
433*b077aed3SPierre Pronchery  */
wait_random_seeded(void)434*b077aed3SPierre Pronchery static int wait_random_seeded(void)
435*b077aed3SPierre Pronchery {
436*b077aed3SPierre Pronchery     static int seeded = OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID < 0;
437*b077aed3SPierre Pronchery     static const int kernel_version[] = { DEVRANDOM_SAFE_KERNEL };
438*b077aed3SPierre Pronchery     int kernel[2];
439*b077aed3SPierre Pronchery     int shm_id, fd, r;
440*b077aed3SPierre Pronchery     char c, *p;
441*b077aed3SPierre Pronchery     struct utsname un;
442*b077aed3SPierre Pronchery     fd_set fds;
443*b077aed3SPierre Pronchery 
444*b077aed3SPierre Pronchery     if (!seeded) {
445*b077aed3SPierre Pronchery         /* See if anything has created the global seeded indication */
446*b077aed3SPierre Pronchery         if ((shm_id = shmget(OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID, 1, 0)) == -1) {
447*b077aed3SPierre Pronchery             /*
448*b077aed3SPierre Pronchery              * Check the kernel's version and fail if it is too recent.
449*b077aed3SPierre Pronchery              *
450*b077aed3SPierre Pronchery              * Linux kernels from 4.8 onwards do not guarantee that
451*b077aed3SPierre Pronchery              * /dev/urandom is properly seeded when /dev/random becomes
452*b077aed3SPierre Pronchery              * readable.  However, such kernels support the getentropy(2)
453*b077aed3SPierre Pronchery              * system call and this should always succeed which renders
454*b077aed3SPierre Pronchery              * this alternative but essentially identical source moot.
455*b077aed3SPierre Pronchery              */
456*b077aed3SPierre Pronchery             if (uname(&un) == 0) {
457*b077aed3SPierre Pronchery                 kernel[0] = atoi(un.release);
458*b077aed3SPierre Pronchery                 p = strchr(un.release, '.');
459*b077aed3SPierre Pronchery                 kernel[1] = p == NULL ? 0 : atoi(p + 1);
460*b077aed3SPierre Pronchery                 if (kernel[0] > kernel_version[0]
461*b077aed3SPierre Pronchery                     || (kernel[0] == kernel_version[0]
462*b077aed3SPierre Pronchery                         && kernel[1] >= kernel_version[1])) {
463*b077aed3SPierre Pronchery                     return 0;
464*b077aed3SPierre Pronchery                 }
465*b077aed3SPierre Pronchery             }
466*b077aed3SPierre Pronchery             /* Open /dev/random and wait for it to be readable */
467*b077aed3SPierre Pronchery             if ((fd = open(DEVRANDOM_WAIT, O_RDONLY)) != -1) {
468*b077aed3SPierre Pronchery                 if (DEVRANDM_WAIT_USE_SELECT && fd < FD_SETSIZE) {
469*b077aed3SPierre Pronchery                     FD_ZERO(&fds);
470*b077aed3SPierre Pronchery                     FD_SET(fd, &fds);
471*b077aed3SPierre Pronchery                     while ((r = select(fd + 1, &fds, NULL, NULL, NULL)) < 0
472*b077aed3SPierre Pronchery                            && errno == EINTR);
473*b077aed3SPierre Pronchery                 } else {
474*b077aed3SPierre Pronchery                     while ((r = read(fd, &c, 1)) < 0 && errno == EINTR);
475*b077aed3SPierre Pronchery                 }
476*b077aed3SPierre Pronchery                 close(fd);
477*b077aed3SPierre Pronchery                 if (r == 1) {
478*b077aed3SPierre Pronchery                     seeded = 1;
479*b077aed3SPierre Pronchery                     /* Create the shared memory indicator */
480*b077aed3SPierre Pronchery                     shm_id = shmget(OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID, 1,
481*b077aed3SPierre Pronchery                                     IPC_CREAT | S_IRUSR | S_IRGRP | S_IROTH);
482*b077aed3SPierre Pronchery                 }
483*b077aed3SPierre Pronchery             }
484*b077aed3SPierre Pronchery         }
485*b077aed3SPierre Pronchery         if (shm_id != -1) {
486*b077aed3SPierre Pronchery             seeded = 1;
487*b077aed3SPierre Pronchery             /*
488*b077aed3SPierre Pronchery              * Map the shared memory to prevent its premature destruction.
489*b077aed3SPierre Pronchery              * If this call fails, it isn't a big problem.
490*b077aed3SPierre Pronchery              */
491*b077aed3SPierre Pronchery             shm_addr = shmat(shm_id, NULL, SHM_RDONLY);
492*b077aed3SPierre Pronchery             if (shm_addr != (void *)-1)
493*b077aed3SPierre Pronchery                 OPENSSL_atexit(&cleanup_shm);
494*b077aed3SPierre Pronchery         }
495*b077aed3SPierre Pronchery     }
496*b077aed3SPierre Pronchery     return seeded;
497*b077aed3SPierre Pronchery }
498*b077aed3SPierre Pronchery #   else /* defined __linux && DEVRANDOM_WAIT && OPENSSL_RAND_SEED_GETRANDOM */
wait_random_seeded(void)499*b077aed3SPierre Pronchery static int wait_random_seeded(void)
500*b077aed3SPierre Pronchery {
501*b077aed3SPierre Pronchery     return 1;
502*b077aed3SPierre Pronchery }
503*b077aed3SPierre Pronchery #   endif
504*b077aed3SPierre Pronchery 
505*b077aed3SPierre Pronchery /*
506*b077aed3SPierre Pronchery  * Verify that the file descriptor associated with the random source is
507*b077aed3SPierre Pronchery  * still valid. The rationale for doing this is the fact that it is not
508*b077aed3SPierre Pronchery  * uncommon for daemons to close all open file handles when daemonizing.
509*b077aed3SPierre Pronchery  * So the handle might have been closed or even reused for opening
510*b077aed3SPierre Pronchery  * another file.
511*b077aed3SPierre Pronchery  */
check_random_device(struct random_device * rd)512*b077aed3SPierre Pronchery static int check_random_device(struct random_device * rd)
513*b077aed3SPierre Pronchery {
514*b077aed3SPierre Pronchery     struct stat st;
515*b077aed3SPierre Pronchery 
516*b077aed3SPierre Pronchery     return rd->fd != -1
517*b077aed3SPierre Pronchery            && fstat(rd->fd, &st) != -1
518*b077aed3SPierre Pronchery            && rd->dev == st.st_dev
519*b077aed3SPierre Pronchery            && rd->ino == st.st_ino
520*b077aed3SPierre Pronchery            && ((rd->mode ^ st.st_mode) & ~(S_IRWXU | S_IRWXG | S_IRWXO)) == 0
521*b077aed3SPierre Pronchery            && rd->rdev == st.st_rdev;
522*b077aed3SPierre Pronchery }
523*b077aed3SPierre Pronchery 
524*b077aed3SPierre Pronchery /*
525*b077aed3SPierre Pronchery  * Open a random device if required and return its file descriptor or -1 on error
526*b077aed3SPierre Pronchery  */
get_random_device(size_t n)527*b077aed3SPierre Pronchery static int get_random_device(size_t n)
528*b077aed3SPierre Pronchery {
529*b077aed3SPierre Pronchery     struct stat st;
530*b077aed3SPierre Pronchery     struct random_device * rd = &random_devices[n];
531*b077aed3SPierre Pronchery 
532*b077aed3SPierre Pronchery     /* reuse existing file descriptor if it is (still) valid */
533*b077aed3SPierre Pronchery     if (check_random_device(rd))
534*b077aed3SPierre Pronchery         return rd->fd;
535*b077aed3SPierre Pronchery 
536*b077aed3SPierre Pronchery     /* open the random device ... */
537*b077aed3SPierre Pronchery     if ((rd->fd = open(random_device_paths[n], O_RDONLY)) == -1)
538*b077aed3SPierre Pronchery         return rd->fd;
539*b077aed3SPierre Pronchery 
540*b077aed3SPierre Pronchery     /* ... and cache its relevant stat(2) data */
541*b077aed3SPierre Pronchery     if (fstat(rd->fd, &st) != -1) {
542*b077aed3SPierre Pronchery         rd->dev = st.st_dev;
543*b077aed3SPierre Pronchery         rd->ino = st.st_ino;
544*b077aed3SPierre Pronchery         rd->mode = st.st_mode;
545*b077aed3SPierre Pronchery         rd->rdev = st.st_rdev;
546*b077aed3SPierre Pronchery     } else {
547*b077aed3SPierre Pronchery         close(rd->fd);
548*b077aed3SPierre Pronchery         rd->fd = -1;
549*b077aed3SPierre Pronchery     }
550*b077aed3SPierre Pronchery 
551*b077aed3SPierre Pronchery     return rd->fd;
552*b077aed3SPierre Pronchery }
553*b077aed3SPierre Pronchery 
554*b077aed3SPierre Pronchery /*
555*b077aed3SPierre Pronchery  * Close a random device making sure it is a random device
556*b077aed3SPierre Pronchery  */
close_random_device(size_t n)557*b077aed3SPierre Pronchery static void close_random_device(size_t n)
558*b077aed3SPierre Pronchery {
559*b077aed3SPierre Pronchery     struct random_device * rd = &random_devices[n];
560*b077aed3SPierre Pronchery 
561*b077aed3SPierre Pronchery     if (check_random_device(rd))
562*b077aed3SPierre Pronchery         close(rd->fd);
563*b077aed3SPierre Pronchery     rd->fd = -1;
564*b077aed3SPierre Pronchery }
565*b077aed3SPierre Pronchery 
ossl_rand_pool_init(void)566*b077aed3SPierre Pronchery int ossl_rand_pool_init(void)
567*b077aed3SPierre Pronchery {
568*b077aed3SPierre Pronchery     size_t i;
569*b077aed3SPierre Pronchery 
570*b077aed3SPierre Pronchery     for (i = 0; i < OSSL_NELEM(random_devices); i++)
571*b077aed3SPierre Pronchery         random_devices[i].fd = -1;
572*b077aed3SPierre Pronchery 
573*b077aed3SPierre Pronchery     return 1;
574*b077aed3SPierre Pronchery }
575*b077aed3SPierre Pronchery 
ossl_rand_pool_cleanup(void)576*b077aed3SPierre Pronchery void ossl_rand_pool_cleanup(void)
577*b077aed3SPierre Pronchery {
578*b077aed3SPierre Pronchery     size_t i;
579*b077aed3SPierre Pronchery 
580*b077aed3SPierre Pronchery     for (i = 0; i < OSSL_NELEM(random_devices); i++)
581*b077aed3SPierre Pronchery         close_random_device(i);
582*b077aed3SPierre Pronchery }
583*b077aed3SPierre Pronchery 
ossl_rand_pool_keep_random_devices_open(int keep)584*b077aed3SPierre Pronchery void ossl_rand_pool_keep_random_devices_open(int keep)
585*b077aed3SPierre Pronchery {
586*b077aed3SPierre Pronchery     if (!keep)
587*b077aed3SPierre Pronchery         ossl_rand_pool_cleanup();
588*b077aed3SPierre Pronchery 
589*b077aed3SPierre Pronchery     keep_random_devices_open = keep;
590*b077aed3SPierre Pronchery }
591*b077aed3SPierre Pronchery 
592*b077aed3SPierre Pronchery #  else     /* !defined(OPENSSL_RAND_SEED_DEVRANDOM) */
593*b077aed3SPierre Pronchery 
ossl_rand_pool_init(void)594*b077aed3SPierre Pronchery int ossl_rand_pool_init(void)
595*b077aed3SPierre Pronchery {
596*b077aed3SPierre Pronchery     return 1;
597*b077aed3SPierre Pronchery }
598*b077aed3SPierre Pronchery 
ossl_rand_pool_cleanup(void)599*b077aed3SPierre Pronchery void ossl_rand_pool_cleanup(void)
600*b077aed3SPierre Pronchery {
601*b077aed3SPierre Pronchery }
602*b077aed3SPierre Pronchery 
ossl_rand_pool_keep_random_devices_open(int keep)603*b077aed3SPierre Pronchery void ossl_rand_pool_keep_random_devices_open(int keep)
604*b077aed3SPierre Pronchery {
605*b077aed3SPierre Pronchery }
606*b077aed3SPierre Pronchery 
607*b077aed3SPierre Pronchery #  endif    /* defined(OPENSSL_RAND_SEED_DEVRANDOM) */
608*b077aed3SPierre Pronchery 
609*b077aed3SPierre Pronchery /*
610*b077aed3SPierre Pronchery  * Try the various seeding methods in turn, exit when successful.
611*b077aed3SPierre Pronchery  *
612*b077aed3SPierre Pronchery  * If more than one entropy source is available, is it
613*b077aed3SPierre Pronchery  * preferable to stop as soon as enough entropy has been collected
614*b077aed3SPierre Pronchery  * (as favored by @rsalz) or should one rather be defensive and add
615*b077aed3SPierre Pronchery  * more entropy than requested and/or from different sources?
616*b077aed3SPierre Pronchery  *
617*b077aed3SPierre Pronchery  * Currently, the user can select multiple entropy sources in the
618*b077aed3SPierre Pronchery  * configure step, yet in practice only the first available source
619*b077aed3SPierre Pronchery  * will be used. A more flexible solution has been requested, but
620*b077aed3SPierre Pronchery  * currently it is not clear how this can be achieved without
621*b077aed3SPierre Pronchery  * overengineering the problem. There are many parameters which
622*b077aed3SPierre Pronchery  * could be taken into account when selecting the order and amount
623*b077aed3SPierre Pronchery  * of input from the different entropy sources (trust, quality,
624*b077aed3SPierre Pronchery  * possibility of blocking).
625*b077aed3SPierre Pronchery  */
ossl_pool_acquire_entropy(RAND_POOL * pool)626*b077aed3SPierre Pronchery size_t ossl_pool_acquire_entropy(RAND_POOL *pool)
627*b077aed3SPierre Pronchery {
628*b077aed3SPierre Pronchery #  if defined(OPENSSL_RAND_SEED_NONE)
629*b077aed3SPierre Pronchery     return ossl_rand_pool_entropy_available(pool);
630*b077aed3SPierre Pronchery #  else
631*b077aed3SPierre Pronchery     size_t entropy_available = 0;
632*b077aed3SPierre Pronchery 
633*b077aed3SPierre Pronchery     (void)entropy_available;    /* avoid compiler warning */
634*b077aed3SPierre Pronchery 
635*b077aed3SPierre Pronchery #   if defined(OPENSSL_RAND_SEED_GETRANDOM)
636*b077aed3SPierre Pronchery     {
637*b077aed3SPierre Pronchery         size_t bytes_needed;
638*b077aed3SPierre Pronchery         unsigned char *buffer;
639*b077aed3SPierre Pronchery         ssize_t bytes;
640*b077aed3SPierre Pronchery         /* Maximum allowed number of consecutive unsuccessful attempts */
641*b077aed3SPierre Pronchery         int attempts = 3;
642*b077aed3SPierre Pronchery 
643*b077aed3SPierre Pronchery         bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
644*b077aed3SPierre Pronchery         while (bytes_needed != 0 && attempts-- > 0) {
645*b077aed3SPierre Pronchery             buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
646*b077aed3SPierre Pronchery             bytes = syscall_random(buffer, bytes_needed);
647*b077aed3SPierre Pronchery             if (bytes > 0) {
648*b077aed3SPierre Pronchery                 ossl_rand_pool_add_end(pool, bytes, 8 * bytes);
649*b077aed3SPierre Pronchery                 bytes_needed -= bytes;
650*b077aed3SPierre Pronchery                 attempts = 3; /* reset counter after successful attempt */
651*b077aed3SPierre Pronchery             } else if (bytes < 0 && errno != EINTR) {
652*b077aed3SPierre Pronchery                 break;
653*b077aed3SPierre Pronchery             }
654*b077aed3SPierre Pronchery         }
655*b077aed3SPierre Pronchery     }
656*b077aed3SPierre Pronchery     entropy_available = ossl_rand_pool_entropy_available(pool);
657*b077aed3SPierre Pronchery     if (entropy_available > 0)
658*b077aed3SPierre Pronchery         return entropy_available;
659*b077aed3SPierre Pronchery #   endif
660*b077aed3SPierre Pronchery 
661*b077aed3SPierre Pronchery #   if defined(OPENSSL_RAND_SEED_LIBRANDOM)
662*b077aed3SPierre Pronchery     {
663*b077aed3SPierre Pronchery         /* Not yet implemented. */
664*b077aed3SPierre Pronchery     }
665*b077aed3SPierre Pronchery #   endif
666*b077aed3SPierre Pronchery 
667*b077aed3SPierre Pronchery #   if defined(OPENSSL_RAND_SEED_DEVRANDOM)
668*b077aed3SPierre Pronchery     if (wait_random_seeded()) {
669*b077aed3SPierre Pronchery         size_t bytes_needed;
670*b077aed3SPierre Pronchery         unsigned char *buffer;
671*b077aed3SPierre Pronchery         size_t i;
672*b077aed3SPierre Pronchery 
673*b077aed3SPierre Pronchery         bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
674*b077aed3SPierre Pronchery         for (i = 0; bytes_needed > 0 && i < OSSL_NELEM(random_device_paths);
675*b077aed3SPierre Pronchery              i++) {
676*b077aed3SPierre Pronchery             ssize_t bytes = 0;
677*b077aed3SPierre Pronchery             /* Maximum number of consecutive unsuccessful attempts */
678*b077aed3SPierre Pronchery             int attempts = 3;
679*b077aed3SPierre Pronchery             const int fd = get_random_device(i);
680*b077aed3SPierre Pronchery 
681*b077aed3SPierre Pronchery             if (fd == -1)
682*b077aed3SPierre Pronchery                 continue;
683*b077aed3SPierre Pronchery 
684*b077aed3SPierre Pronchery             while (bytes_needed != 0 && attempts-- > 0) {
685*b077aed3SPierre Pronchery                 buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
686*b077aed3SPierre Pronchery                 bytes = read(fd, buffer, bytes_needed);
687*b077aed3SPierre Pronchery 
688*b077aed3SPierre Pronchery                 if (bytes > 0) {
689*b077aed3SPierre Pronchery                     ossl_rand_pool_add_end(pool, bytes, 8 * bytes);
690*b077aed3SPierre Pronchery                     bytes_needed -= bytes;
691*b077aed3SPierre Pronchery                     attempts = 3; /* reset counter on successful attempt */
692*b077aed3SPierre Pronchery                 } else if (bytes < 0 && errno != EINTR) {
693*b077aed3SPierre Pronchery                     break;
694*b077aed3SPierre Pronchery                 }
695*b077aed3SPierre Pronchery             }
696*b077aed3SPierre Pronchery             if (bytes < 0 || !keep_random_devices_open)
697*b077aed3SPierre Pronchery                 close_random_device(i);
698*b077aed3SPierre Pronchery 
699*b077aed3SPierre Pronchery             bytes_needed = ossl_rand_pool_bytes_needed(pool, 1);
700*b077aed3SPierre Pronchery         }
701*b077aed3SPierre Pronchery         entropy_available = ossl_rand_pool_entropy_available(pool);
702*b077aed3SPierre Pronchery         if (entropy_available > 0)
703*b077aed3SPierre Pronchery             return entropy_available;
704*b077aed3SPierre Pronchery     }
705*b077aed3SPierre Pronchery #   endif
706*b077aed3SPierre Pronchery 
707*b077aed3SPierre Pronchery #   if defined(OPENSSL_RAND_SEED_RDTSC)
708*b077aed3SPierre Pronchery     entropy_available = ossl_prov_acquire_entropy_from_tsc(pool);
709*b077aed3SPierre Pronchery     if (entropy_available > 0)
710*b077aed3SPierre Pronchery         return entropy_available;
711*b077aed3SPierre Pronchery #   endif
712*b077aed3SPierre Pronchery 
713*b077aed3SPierre Pronchery #   if defined(OPENSSL_RAND_SEED_RDCPU)
714*b077aed3SPierre Pronchery     entropy_available = ossl_prov_acquire_entropy_from_cpu(pool);
715*b077aed3SPierre Pronchery     if (entropy_available > 0)
716*b077aed3SPierre Pronchery         return entropy_available;
717*b077aed3SPierre Pronchery #   endif
718*b077aed3SPierre Pronchery 
719*b077aed3SPierre Pronchery #   if defined(OPENSSL_RAND_SEED_EGD)
720*b077aed3SPierre Pronchery     {
721*b077aed3SPierre Pronchery         static const char *paths[] = { DEVRANDOM_EGD, NULL };
722*b077aed3SPierre Pronchery         size_t bytes_needed;
723*b077aed3SPierre Pronchery         unsigned char *buffer;
724*b077aed3SPierre Pronchery         int i;
725*b077aed3SPierre Pronchery 
726*b077aed3SPierre Pronchery         bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
727*b077aed3SPierre Pronchery         for (i = 0; bytes_needed > 0 && paths[i] != NULL; i++) {
728*b077aed3SPierre Pronchery             size_t bytes = 0;
729*b077aed3SPierre Pronchery             int num;
730*b077aed3SPierre Pronchery 
731*b077aed3SPierre Pronchery             buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
732*b077aed3SPierre Pronchery             num = RAND_query_egd_bytes(paths[i],
733*b077aed3SPierre Pronchery                                        buffer, (int)bytes_needed);
734*b077aed3SPierre Pronchery             if (num == (int)bytes_needed)
735*b077aed3SPierre Pronchery                 bytes = bytes_needed;
736*b077aed3SPierre Pronchery 
737*b077aed3SPierre Pronchery             ossl_rand_pool_add_end(pool, bytes, 8 * bytes);
738*b077aed3SPierre Pronchery             bytes_needed = ossl_rand_pool_bytes_needed(pool, 1);
739*b077aed3SPierre Pronchery         }
740*b077aed3SPierre Pronchery         entropy_available = ossl_rand_pool_entropy_available(pool);
741*b077aed3SPierre Pronchery         if (entropy_available > 0)
742*b077aed3SPierre Pronchery             return entropy_available;
743*b077aed3SPierre Pronchery     }
744*b077aed3SPierre Pronchery #   endif
745*b077aed3SPierre Pronchery 
746*b077aed3SPierre Pronchery     return ossl_rand_pool_entropy_available(pool);
747*b077aed3SPierre Pronchery #  endif
748*b077aed3SPierre Pronchery }
749*b077aed3SPierre Pronchery # endif
750*b077aed3SPierre Pronchery #endif
751*b077aed3SPierre Pronchery 
752*b077aed3SPierre Pronchery #if (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS)) \
753*b077aed3SPierre Pronchery      || defined(__DJGPP__)
ossl_pool_add_nonce_data(RAND_POOL * pool)754*b077aed3SPierre Pronchery int ossl_pool_add_nonce_data(RAND_POOL *pool)
755*b077aed3SPierre Pronchery {
756*b077aed3SPierre Pronchery     struct {
757*b077aed3SPierre Pronchery         pid_t pid;
758*b077aed3SPierre Pronchery         CRYPTO_THREAD_ID tid;
759*b077aed3SPierre Pronchery         uint64_t time;
760*b077aed3SPierre Pronchery     } data;
761*b077aed3SPierre Pronchery 
762*b077aed3SPierre Pronchery     /* Erase the entire structure including any padding */
763*b077aed3SPierre Pronchery     memset(&data, 0, sizeof(data));
764*b077aed3SPierre Pronchery 
765*b077aed3SPierre Pronchery     /*
766*b077aed3SPierre Pronchery      * Add process id, thread id, and a high resolution timestamp to
767*b077aed3SPierre Pronchery      * ensure that the nonce is unique with high probability for
768*b077aed3SPierre Pronchery      * different process instances.
769*b077aed3SPierre Pronchery      */
770*b077aed3SPierre Pronchery     data.pid = getpid();
771*b077aed3SPierre Pronchery     data.tid = CRYPTO_THREAD_get_current_id();
772*b077aed3SPierre Pronchery     data.time = get_time_stamp();
773*b077aed3SPierre Pronchery 
774*b077aed3SPierre Pronchery     return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
775*b077aed3SPierre Pronchery }
776*b077aed3SPierre Pronchery 
ossl_rand_pool_add_additional_data(RAND_POOL * pool)777*b077aed3SPierre Pronchery int ossl_rand_pool_add_additional_data(RAND_POOL *pool)
778*b077aed3SPierre Pronchery {
779*b077aed3SPierre Pronchery     struct {
780*b077aed3SPierre Pronchery         int fork_id;
781*b077aed3SPierre Pronchery         CRYPTO_THREAD_ID tid;
782*b077aed3SPierre Pronchery         uint64_t time;
783*b077aed3SPierre Pronchery     } data;
784*b077aed3SPierre Pronchery 
785*b077aed3SPierre Pronchery     /* Erase the entire structure including any padding */
786*b077aed3SPierre Pronchery     memset(&data, 0, sizeof(data));
787*b077aed3SPierre Pronchery 
788*b077aed3SPierre Pronchery     /*
789*b077aed3SPierre Pronchery      * Add some noise from the thread id and a high resolution timer.
790*b077aed3SPierre Pronchery      * The fork_id adds some extra fork-safety.
791*b077aed3SPierre Pronchery      * The thread id adds a little randomness if the drbg is accessed
792*b077aed3SPierre Pronchery      * concurrently (which is the case for the <master> drbg).
793*b077aed3SPierre Pronchery      */
794*b077aed3SPierre Pronchery     data.fork_id = openssl_get_fork_id();
795*b077aed3SPierre Pronchery     data.tid = CRYPTO_THREAD_get_current_id();
796*b077aed3SPierre Pronchery     data.time = get_timer_bits();
797*b077aed3SPierre Pronchery 
798*b077aed3SPierre Pronchery     return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
799*b077aed3SPierre Pronchery }
800*b077aed3SPierre Pronchery 
801*b077aed3SPierre Pronchery 
802*b077aed3SPierre Pronchery /*
803*b077aed3SPierre Pronchery  * Get the current time with the highest possible resolution
804*b077aed3SPierre Pronchery  *
805*b077aed3SPierre Pronchery  * The time stamp is added to the nonce, so it is optimized for not repeating.
806*b077aed3SPierre Pronchery  * The current time is ideal for this purpose, provided the computer's clock
807*b077aed3SPierre Pronchery  * is synchronized.
808*b077aed3SPierre Pronchery  */
get_time_stamp(void)809*b077aed3SPierre Pronchery static uint64_t get_time_stamp(void)
810*b077aed3SPierre Pronchery {
811*b077aed3SPierre Pronchery # if defined(OSSL_POSIX_TIMER_OKAY)
812*b077aed3SPierre Pronchery     {
813*b077aed3SPierre Pronchery         struct timespec ts;
814*b077aed3SPierre Pronchery 
815*b077aed3SPierre Pronchery         if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
816*b077aed3SPierre Pronchery             return TWO32TO64(ts.tv_sec, ts.tv_nsec);
817*b077aed3SPierre Pronchery     }
818*b077aed3SPierre Pronchery # endif
819*b077aed3SPierre Pronchery # if defined(__unix__) \
820*b077aed3SPierre Pronchery      || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
821*b077aed3SPierre Pronchery     {
822*b077aed3SPierre Pronchery         struct timeval tv;
823*b077aed3SPierre Pronchery 
824*b077aed3SPierre Pronchery         if (gettimeofday(&tv, NULL) == 0)
825*b077aed3SPierre Pronchery             return TWO32TO64(tv.tv_sec, tv.tv_usec);
826*b077aed3SPierre Pronchery     }
827*b077aed3SPierre Pronchery # endif
828*b077aed3SPierre Pronchery     return time(NULL);
829*b077aed3SPierre Pronchery }
830*b077aed3SPierre Pronchery 
831*b077aed3SPierre Pronchery /*
832*b077aed3SPierre Pronchery  * Get an arbitrary timer value of the highest possible resolution
833*b077aed3SPierre Pronchery  *
834*b077aed3SPierre Pronchery  * The timer value is added as random noise to the additional data,
835*b077aed3SPierre Pronchery  * which is not considered a trusted entropy sourec, so any result
836*b077aed3SPierre Pronchery  * is acceptable.
837*b077aed3SPierre Pronchery  */
get_timer_bits(void)838*b077aed3SPierre Pronchery static uint64_t get_timer_bits(void)
839*b077aed3SPierre Pronchery {
840*b077aed3SPierre Pronchery     uint64_t res = OPENSSL_rdtsc();
841*b077aed3SPierre Pronchery 
842*b077aed3SPierre Pronchery     if (res != 0)
843*b077aed3SPierre Pronchery         return res;
844*b077aed3SPierre Pronchery 
845*b077aed3SPierre Pronchery # if defined(__sun) || defined(__hpux)
846*b077aed3SPierre Pronchery     return gethrtime();
847*b077aed3SPierre Pronchery # elif defined(_AIX)
848*b077aed3SPierre Pronchery     {
849*b077aed3SPierre Pronchery         timebasestruct_t t;
850*b077aed3SPierre Pronchery 
851*b077aed3SPierre Pronchery         read_wall_time(&t, TIMEBASE_SZ);
852*b077aed3SPierre Pronchery         return TWO32TO64(t.tb_high, t.tb_low);
853*b077aed3SPierre Pronchery     }
854*b077aed3SPierre Pronchery # elif defined(OSSL_POSIX_TIMER_OKAY)
855*b077aed3SPierre Pronchery     {
856*b077aed3SPierre Pronchery         struct timespec ts;
857*b077aed3SPierre Pronchery 
858*b077aed3SPierre Pronchery #  ifdef CLOCK_BOOTTIME
859*b077aed3SPierre Pronchery #   define CLOCK_TYPE CLOCK_BOOTTIME
860*b077aed3SPierre Pronchery #  elif defined(_POSIX_MONOTONIC_CLOCK)
861*b077aed3SPierre Pronchery #   define CLOCK_TYPE CLOCK_MONOTONIC
862*b077aed3SPierre Pronchery #  else
863*b077aed3SPierre Pronchery #   define CLOCK_TYPE CLOCK_REALTIME
864*b077aed3SPierre Pronchery #  endif
865*b077aed3SPierre Pronchery 
866*b077aed3SPierre Pronchery         if (clock_gettime(CLOCK_TYPE, &ts) == 0)
867*b077aed3SPierre Pronchery             return TWO32TO64(ts.tv_sec, ts.tv_nsec);
868*b077aed3SPierre Pronchery     }
869*b077aed3SPierre Pronchery # endif
870*b077aed3SPierre Pronchery # if defined(__unix__) \
871*b077aed3SPierre Pronchery      || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
872*b077aed3SPierre Pronchery     {
873*b077aed3SPierre Pronchery         struct timeval tv;
874*b077aed3SPierre Pronchery 
875*b077aed3SPierre Pronchery         if (gettimeofday(&tv, NULL) == 0)
876*b077aed3SPierre Pronchery             return TWO32TO64(tv.tv_sec, tv.tv_usec);
877*b077aed3SPierre Pronchery     }
878*b077aed3SPierre Pronchery # endif
879*b077aed3SPierre Pronchery     return time(NULL);
880*b077aed3SPierre Pronchery }
881*b077aed3SPierre Pronchery #endif /* (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS))
882*b077aed3SPierre Pronchery           || defined(__DJGPP__) */
883