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