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