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