Path: blob/main/crypto/openssl/providers/implementations/rands/seeding/rand_unix.c
48531 views
/*1* Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89#ifndef _GNU_SOURCE10# define _GNU_SOURCE11#endif12#include "internal/e_os.h"13#include <stdio.h>14#include "internal/cryptlib.h"15#include <openssl/rand.h>16#include <openssl/crypto.h>17#include "crypto/rand_pool.h"18#include "crypto/rand.h"19#include "internal/dso.h"20#include "internal/nelem.h"21#include "prov/seeding.h"2223#ifndef OPENSSL_SYS_UEFI24# ifdef __linux25# include <sys/syscall.h>26# ifdef DEVRANDOM_WAIT27# include <sys/shm.h>28# include <sys/utsname.h>29# endif30# endif31# if defined(__FreeBSD__) || defined(__NetBSD__)32# include <sys/types.h>33# include <sys/sysctl.h>34# include <sys/param.h>35# endif36# if defined(__FreeBSD__) && __FreeBSD_version >= 120006137# include <sys/random.h>38# endif39# if defined(__OpenBSD__)40# include <sys/param.h>41# endif42# if defined(__DragonFly__)43# include <sys/param.h>44# include <sys/random.h>45# endif46#endif4748#if (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS)) \49|| defined(__DJGPP__)50# include <sys/types.h>51# include <sys/stat.h>52# include <fcntl.h>53# include <unistd.h>54# include <sys/time.h>5556static uint64_t get_time_stamp(void);5758/* Macro to convert two thirty two bit values into a sixty four bit one */59# define TWO32TO64(a, b) ((((uint64_t)(a)) << 32) + (b))6061/*62* Check for the existence and support of POSIX timers. The standard63* says that the _POSIX_TIMERS macro will have a positive value if they64* are available.65*66* However, we want an additional constraint: that the timer support does67* not require an extra library dependency. Early versions of glibc68* require -lrt to be specified on the link line to access the timers,69* so this needs to be checked for.70*71* It is worse because some libraries define __GLIBC__ but don't72* support the version testing macro (e.g. uClibc). This means73* an extra check is needed.74*75* The final condition is:76* "have posix timers and either not glibc or glibc without -lrt"77*78* The nested #if sequences are required to avoid using a parameterised79* macro that might be undefined.80*/81# undef OSSL_POSIX_TIMER_OKAY82/* On some systems, _POSIX_TIMERS is defined but empty.83* Subtracting by 0 when comparing avoids an error in this case. */84# if defined(_POSIX_TIMERS) && _POSIX_TIMERS -0 > 085# if defined(__GLIBC__)86# if defined(__GLIBC_PREREQ)87# if __GLIBC_PREREQ(2, 17)88# define OSSL_POSIX_TIMER_OKAY89# endif90# endif91# else92# define OSSL_POSIX_TIMER_OKAY93# endif94# endif95#endif /* (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS))96|| defined(__DJGPP__) */9798#if defined(OPENSSL_RAND_SEED_NONE)99/* none means none. this simplifies the following logic */100# undef OPENSSL_RAND_SEED_OS101# undef OPENSSL_RAND_SEED_GETRANDOM102# undef OPENSSL_RAND_SEED_DEVRANDOM103# undef OPENSSL_RAND_SEED_RDTSC104# undef OPENSSL_RAND_SEED_RDCPU105# undef OPENSSL_RAND_SEED_EGD106#endif107108#if defined(OPENSSL_SYS_UEFI) && !defined(OPENSSL_RAND_SEED_NONE)109# error "UEFI only supports seeding NONE"110#endif111112#if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) \113|| defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_VXWORKS) \114|| defined(OPENSSL_SYS_UEFI))115116# if defined(OPENSSL_SYS_VOS)117118# ifndef OPENSSL_RAND_SEED_OS119# error "Unsupported seeding method configured; must be os"120# endif121122# if defined(OPENSSL_SYS_VOS_HPPA) && defined(OPENSSL_SYS_VOS_IA32)123# error "Unsupported HP-PA and IA32 at the same time."124# endif125# if !defined(OPENSSL_SYS_VOS_HPPA) && !defined(OPENSSL_SYS_VOS_IA32)126# error "Must have one of HP-PA or IA32"127# endif128129/*130* The following algorithm repeatedly samples the real-time clock (RTC) to131* generate a sequence of unpredictable data. The algorithm relies upon the132* uneven execution speed of the code (due to factors such as cache misses,133* interrupts, bus activity, and scheduling) and upon the rather large134* relative difference between the speed of the clock and the rate at which135* it can be read. If it is ported to an environment where execution speed136* is more constant or where the RTC ticks at a much slower rate, or the137* clock can be read with fewer instructions, it is likely that the results138* would be far more predictable. This should only be used for legacy139* platforms.140*141* As a precaution, we assume only 2 bits of entropy per byte.142*/143size_t ossl_pool_acquire_entropy(RAND_POOL *pool)144{145short int code;146int i, k;147size_t bytes_needed;148struct timespec ts;149unsigned char v;150# ifdef OPENSSL_SYS_VOS_HPPA151long duration;152extern void s$sleep(long *_duration, short int *_code);153# else154long long duration;155extern void s$sleep2(long long *_duration, short int *_code);156# endif157158bytes_needed = ossl_rand_pool_bytes_needed(pool, 4 /*entropy_factor*/);159160for (i = 0; i < bytes_needed; i++) {161/*162* burn some cpu; hope for interrupts, cache collisions, bus163* interference, etc.164*/165for (k = 0; k < 99; k++)166ts.tv_nsec = random();167168# ifdef OPENSSL_SYS_VOS_HPPA169/* sleep for 1/1024 of a second (976 us). */170duration = 1;171s$sleep(&duration, &code);172# else173/* sleep for 1/65536 of a second (15 us). */174duration = 1;175s$sleep2(&duration, &code);176# endif177178/* Get wall clock time, take 8 bits. */179clock_gettime(CLOCK_REALTIME, &ts);180v = (unsigned char)(ts.tv_nsec & 0xFF);181ossl_rand_pool_add(pool, arg, &v, sizeof(v), 2);182}183return ossl_rand_pool_entropy_available(pool);184}185186void ossl_rand_pool_cleanup(void)187{188}189190void ossl_rand_pool_keep_random_devices_open(int keep)191{192}193194# else195196# if defined(OPENSSL_RAND_SEED_EGD) && \197(defined(OPENSSL_NO_EGD) || !defined(DEVRANDOM_EGD))198# error "Seeding uses EGD but EGD is turned off or no device given"199# endif200201# if defined(OPENSSL_RAND_SEED_DEVRANDOM) && !defined(DEVRANDOM)202# error "Seeding uses urandom but DEVRANDOM is not configured"203# endif204205# if defined(OPENSSL_RAND_SEED_OS)206# if !defined(DEVRANDOM)207# error "OS seeding requires DEVRANDOM to be configured"208# endif209# define OPENSSL_RAND_SEED_GETRANDOM210# define OPENSSL_RAND_SEED_DEVRANDOM211# endif212213# if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)214/*215* sysctl_random(): Use sysctl() to read a random number from the kernel216* Returns the number of bytes returned in buf on success, -1 on failure.217*/218static ssize_t sysctl_random(char *buf, size_t buflen)219{220int mib[2];221size_t done = 0;222size_t len;223224/*225* Note: sign conversion between size_t and ssize_t is safe even226* without a range check, see comment in syscall_random()227*/228229/*230* On FreeBSD old implementations returned longs, newer versions support231* variable sizes up to 256 byte. The code below would not work properly232* when the sysctl returns long and we want to request something not a233* multiple of longs, which should never be the case.234*/235#if defined(__FreeBSD__)236if (!ossl_assert(buflen % sizeof(long) == 0)) {237errno = EINVAL;238return -1;239}240#endif241242/*243* On NetBSD before 4.0 KERN_ARND was an alias for KERN_URND, and only244* filled in an int, leaving the rest uninitialized. Since NetBSD 4.0245* it returns a variable number of bytes with the current version supporting246* up to 256 bytes.247* Just return an error on older NetBSD versions.248*/249#if defined(__NetBSD__) && __NetBSD_Version__ < 400000000250errno = ENOSYS;251return -1;252#endif253254mib[0] = CTL_KERN;255mib[1] = KERN_ARND;256257do {258len = buflen > 256 ? 256 : buflen;259if (sysctl(mib, 2, buf, &len, NULL, 0) == -1)260return done > 0 ? done : -1;261done += len;262buf += len;263buflen -= len;264} while (buflen > 0);265266return done;267}268# endif269270# if defined(OPENSSL_RAND_SEED_GETRANDOM)271272# if defined(__linux) && !defined(__NR_getrandom)273# if defined(__arm__)274# define __NR_getrandom (__NR_SYSCALL_BASE+384)275# elif defined(__i386__)276# define __NR_getrandom 355277# elif defined(__x86_64__)278# if defined(__ILP32__)279# define __NR_getrandom (__X32_SYSCALL_BIT + 318)280# else281# define __NR_getrandom 318282# endif283# elif defined(__xtensa__)284# define __NR_getrandom 338285# elif defined(__s390__) || defined(__s390x__)286# define __NR_getrandom 349287# elif defined(__bfin__)288# define __NR_getrandom 389289# elif defined(__powerpc__)290# define __NR_getrandom 359291# elif defined(__mips__) || defined(__mips64)292# if _MIPS_SIM == _MIPS_SIM_ABI32293# define __NR_getrandom (__NR_Linux + 353)294# elif _MIPS_SIM == _MIPS_SIM_ABI64295# define __NR_getrandom (__NR_Linux + 313)296# elif _MIPS_SIM == _MIPS_SIM_NABI32297# define __NR_getrandom (__NR_Linux + 317)298# endif299# elif defined(__hppa__)300# define __NR_getrandom (__NR_Linux + 339)301# elif defined(__sparc__)302# define __NR_getrandom 347303# elif defined(__ia64__)304# define __NR_getrandom 1339305# elif defined(__alpha__)306# define __NR_getrandom 511307# elif defined(__sh__)308# if defined(__SH5__)309# define __NR_getrandom 373310# else311# define __NR_getrandom 384312# endif313# elif defined(__avr32__)314# define __NR_getrandom 317315# elif defined(__microblaze__)316# define __NR_getrandom 385317# elif defined(__m68k__)318# define __NR_getrandom 352319# elif defined(__cris__)320# define __NR_getrandom 356321# else /* generic (f.e. aarch64, loongarch, loongarch64) */322# define __NR_getrandom 278323# endif324# endif325326/*327* syscall_random(): Try to get random data using a system call328* returns the number of bytes returned in buf, or < 0 on error.329*/330static ssize_t syscall_random(void *buf, size_t buflen)331{332/*333* Note: 'buflen' equals the size of the buffer which is used by the334* get_entropy() callback of the RAND_DRBG. It is roughly bounded by335*336* 2 * RAND_POOL_FACTOR * (RAND_DRBG_STRENGTH / 8) = 2^14337*338* which is way below the OSSL_SSIZE_MAX limit. Therefore sign conversion339* between size_t and ssize_t is safe even without a range check.340*/341342/*343* Do runtime detection to find getentropy().344*345* Known OSs that should support this:346* - Darwin since 16 (OSX 10.12, IOS 10.0).347* - Solaris since 11.3348* - OpenBSD since 5.6349* - Linux since 3.17 with glibc 2.25350*351* Note: Sometimes getentropy() can be provided but not implemented352* internally. So we need to check errno for ENOSYS353*/354# if !defined(__DragonFly__) && !defined(__NetBSD__) && !defined(__FreeBSD__)355# if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux)356extern int getentropy(void *buffer, size_t length) __attribute__((weak));357358if (getentropy != NULL) {359if (getentropy(buf, buflen) == 0)360return (ssize_t)buflen;361if (errno != ENOSYS)362return -1;363}364# elif defined(OPENSSL_APPLE_CRYPTO_RANDOM)365366if (CCRandomGenerateBytes(buf, buflen) == kCCSuccess)367return (ssize_t)buflen;368369return -1;370# else371union {372void *p;373int (*f)(void *buffer, size_t length);374} p_getentropy;375376/*377* We could cache the result of the lookup, but we normally don't378* call this function often.379*/380ERR_set_mark();381p_getentropy.p = DSO_global_lookup("getentropy");382ERR_pop_to_mark();383if (p_getentropy.p != NULL)384return p_getentropy.f(buf, buflen) == 0 ? (ssize_t)buflen : -1;385# endif386# endif /* !__DragonFly__ && !__NetBSD__ && !__FreeBSD__ */387388/* Linux supports this since version 3.17 */389# if defined(__linux) && defined(__NR_getrandom)390return syscall(__NR_getrandom, buf, buflen, 0);391# elif (defined(__DragonFly__) && __DragonFly_version >= 500700) \392|| (defined(__NetBSD__) && __NetBSD_Version >= 1000000000) \393|| (defined(__FreeBSD__) && __FreeBSD_version >= 1200061)394return getrandom(buf, buflen, 0);395# elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)396return sysctl_random(buf, buflen);397# elif defined(__wasi__)398if (getentropy(buf, buflen) == 0)399return (ssize_t)buflen;400return -1;401# else402errno = ENOSYS;403return -1;404# endif405}406# endif /* defined(OPENSSL_RAND_SEED_GETRANDOM) */407408# if defined(OPENSSL_RAND_SEED_DEVRANDOM)409static const char *random_device_paths[] = { DEVRANDOM };410static struct random_device {411int fd;412dev_t dev;413ino_t ino;414mode_t mode;415dev_t rdev;416} random_devices[OSSL_NELEM(random_device_paths)];417static int keep_random_devices_open = 1;418419# if defined(__linux) && defined(DEVRANDOM_WAIT) \420&& defined(OPENSSL_RAND_SEED_GETRANDOM)421static void *shm_addr;422423static void cleanup_shm(void)424{425shmdt(shm_addr);426}427428/*429* Ensure that the system randomness source has been adequately seeded.430* This is done by having the first start of libcrypto, wait until the device431* /dev/random becomes able to supply a byte of entropy. Subsequent starts432* of the library and later reseedings do not need to do this.433*/434static int wait_random_seeded(void)435{436static int seeded = OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID < 0;437static const int kernel_version[] = { DEVRANDOM_SAFE_KERNEL };438int kernel[2];439int shm_id, fd, r;440char c, *p;441struct utsname un;442fd_set fds;443444if (!seeded) {445/* See if anything has created the global seeded indication */446if ((shm_id = shmget(OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID, 1, 0)) == -1) {447/*448* Check the kernel's version and fail if it is too recent.449*450* Linux kernels from 4.8 onwards do not guarantee that451* /dev/urandom is properly seeded when /dev/random becomes452* readable. However, such kernels support the getentropy(2)453* system call and this should always succeed which renders454* this alternative but essentially identical source moot.455*/456if (uname(&un) == 0) {457kernel[0] = atoi(un.release);458p = strchr(un.release, '.');459kernel[1] = p == NULL ? 0 : atoi(p + 1);460if (kernel[0] > kernel_version[0]461|| (kernel[0] == kernel_version[0]462&& kernel[1] >= kernel_version[1])) {463return 0;464}465}466/* Open /dev/random and wait for it to be readable */467if ((fd = open(DEVRANDOM_WAIT, O_RDONLY)) != -1) {468if (DEVRANDM_WAIT_USE_SELECT && fd < FD_SETSIZE) {469FD_ZERO(&fds);470FD_SET(fd, &fds);471while ((r = select(fd + 1, &fds, NULL, NULL, NULL)) < 0472&& errno == EINTR);473} else {474while ((r = read(fd, &c, 1)) < 0 && errno == EINTR);475}476close(fd);477if (r == 1) {478seeded = 1;479/* Create the shared memory indicator */480shm_id = shmget(OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID, 1,481IPC_CREAT | S_IRUSR | S_IRGRP | S_IROTH);482}483}484}485if (shm_id != -1) {486seeded = 1;487/*488* Map the shared memory to prevent its premature destruction.489* If this call fails, it isn't a big problem.490*/491shm_addr = shmat(shm_id, NULL, SHM_RDONLY);492if (shm_addr != (void *)-1)493OPENSSL_atexit(&cleanup_shm);494}495}496return seeded;497}498# else /* defined __linux && DEVRANDOM_WAIT && OPENSSL_RAND_SEED_GETRANDOM */499static int wait_random_seeded(void)500{501return 1;502}503# endif504505/*506* Verify that the file descriptor associated with the random source is507* still valid. The rationale for doing this is the fact that it is not508* uncommon for daemons to close all open file handles when daemonizing.509* So the handle might have been closed or even reused for opening510* another file.511*/512static int check_random_device(struct random_device *rd)513{514struct stat st;515516return rd->fd != -1517&& fstat(rd->fd, &st) != -1518&& rd->dev == st.st_dev519&& rd->ino == st.st_ino520&& ((rd->mode ^ st.st_mode) & ~(S_IRWXU | S_IRWXG | S_IRWXO)) == 0521&& rd->rdev == st.st_rdev;522}523524/*525* Open a random device if required and return its file descriptor or -1 on error526*/527static int get_random_device(size_t n)528{529struct stat st;530struct random_device *rd = &random_devices[n];531532/* reuse existing file descriptor if it is (still) valid */533if (check_random_device(rd))534return rd->fd;535536/* open the random device ... */537if ((rd->fd = open(random_device_paths[n], O_RDONLY)) == -1)538return rd->fd;539540/* ... and cache its relevant stat(2) data */541if (fstat(rd->fd, &st) != -1) {542rd->dev = st.st_dev;543rd->ino = st.st_ino;544rd->mode = st.st_mode;545rd->rdev = st.st_rdev;546} else {547close(rd->fd);548rd->fd = -1;549}550551return rd->fd;552}553554/*555* Close a random device making sure it is a random device556*/557static void close_random_device(size_t n)558{559struct random_device *rd = &random_devices[n];560561if (check_random_device(rd))562close(rd->fd);563rd->fd = -1;564}565566int ossl_rand_pool_init(void)567{568size_t i;569570for (i = 0; i < OSSL_NELEM(random_devices); i++)571random_devices[i].fd = -1;572573return 1;574}575576void ossl_rand_pool_cleanup(void)577{578size_t i;579580for (i = 0; i < OSSL_NELEM(random_devices); i++)581close_random_device(i);582}583584void ossl_rand_pool_keep_random_devices_open(int keep)585{586if (!keep)587ossl_rand_pool_cleanup();588589keep_random_devices_open = keep;590}591592# else /* !defined(OPENSSL_RAND_SEED_DEVRANDOM) */593594int ossl_rand_pool_init(void)595{596return 1;597}598599void ossl_rand_pool_cleanup(void)600{601}602603void ossl_rand_pool_keep_random_devices_open(int keep)604{605}606607# endif /* defined(OPENSSL_RAND_SEED_DEVRANDOM) */608609/*610* Try the various seeding methods in turn, exit when successful.611*612* If more than one entropy source is available, is it613* preferable to stop as soon as enough entropy has been collected614* (as favored by @rsalz) or should one rather be defensive and add615* more entropy than requested and/or from different sources?616*617* Currently, the user can select multiple entropy sources in the618* configure step, yet in practice only the first available source619* will be used. A more flexible solution has been requested, but620* currently it is not clear how this can be achieved without621* overengineering the problem. There are many parameters which622* could be taken into account when selecting the order and amount623* of input from the different entropy sources (trust, quality,624* possibility of blocking).625*/626size_t ossl_pool_acquire_entropy(RAND_POOL *pool)627{628# if defined(OPENSSL_RAND_SEED_NONE)629return ossl_rand_pool_entropy_available(pool);630# else631size_t entropy_available = 0;632633(void)entropy_available; /* avoid compiler warning */634635# if defined(OPENSSL_RAND_SEED_GETRANDOM)636{637size_t bytes_needed;638unsigned char *buffer;639ssize_t bytes;640/* Maximum allowed number of consecutive unsuccessful attempts */641int attempts = 3;642643bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);644while (bytes_needed != 0 && attempts-- > 0) {645buffer = ossl_rand_pool_add_begin(pool, bytes_needed);646bytes = syscall_random(buffer, bytes_needed);647if (bytes > 0) {648ossl_rand_pool_add_end(pool, bytes, 8 * bytes);649bytes_needed -= bytes;650attempts = 3; /* reset counter after successful attempt */651} else if (bytes < 0 && errno != EINTR) {652break;653}654}655}656entropy_available = ossl_rand_pool_entropy_available(pool);657if (entropy_available > 0)658return entropy_available;659# endif660661# if defined(OPENSSL_RAND_SEED_DEVRANDOM)662if (wait_random_seeded()) {663size_t bytes_needed;664unsigned char *buffer;665size_t i;666667bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);668for (i = 0; bytes_needed > 0 && i < OSSL_NELEM(random_device_paths);669i++) {670ssize_t bytes = 0;671/* Maximum number of consecutive unsuccessful attempts */672int attempts = 3;673const int fd = get_random_device(i);674675if (fd == -1)676continue;677678while (bytes_needed != 0 && attempts-- > 0) {679buffer = ossl_rand_pool_add_begin(pool, bytes_needed);680bytes = read(fd, buffer, bytes_needed);681682if (bytes > 0) {683ossl_rand_pool_add_end(pool, bytes, 8 * bytes);684bytes_needed -= bytes;685attempts = 3; /* reset counter on successful attempt */686} else if (bytes < 0 && errno != EINTR) {687break;688}689}690if (bytes < 0 || !keep_random_devices_open)691close_random_device(i);692693bytes_needed = ossl_rand_pool_bytes_needed(pool, 1);694}695entropy_available = ossl_rand_pool_entropy_available(pool);696if (entropy_available > 0)697return entropy_available;698}699# endif700701# if defined(OPENSSL_RAND_SEED_RDTSC)702entropy_available = ossl_prov_acquire_entropy_from_tsc(pool);703if (entropy_available > 0)704return entropy_available;705# endif706707# if defined(OPENSSL_RAND_SEED_RDCPU)708entropy_available = ossl_prov_acquire_entropy_from_cpu(pool);709if (entropy_available > 0)710return entropy_available;711# endif712713# if defined(OPENSSL_RAND_SEED_EGD)714{715static const char *paths[] = { DEVRANDOM_EGD, NULL };716size_t bytes_needed;717unsigned char *buffer;718int i;719720bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);721for (i = 0; bytes_needed > 0 && paths[i] != NULL; i++) {722size_t bytes = 0;723int num;724725buffer = ossl_rand_pool_add_begin(pool, bytes_needed);726num = RAND_query_egd_bytes(paths[i],727buffer, (int)bytes_needed);728if (num == (int)bytes_needed)729bytes = bytes_needed;730731ossl_rand_pool_add_end(pool, bytes, 8 * bytes);732bytes_needed = ossl_rand_pool_bytes_needed(pool, 1);733}734entropy_available = ossl_rand_pool_entropy_available(pool);735if (entropy_available > 0)736return entropy_available;737}738# endif739740return ossl_rand_pool_entropy_available(pool);741# endif742}743# endif744#endif745746#if (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS)) \747|| defined(__DJGPP__)748int ossl_pool_add_nonce_data(RAND_POOL *pool)749{750struct {751pid_t pid;752CRYPTO_THREAD_ID tid;753uint64_t time;754} data;755756/* Erase the entire structure including any padding */757memset(&data, 0, sizeof(data));758759/*760* Add process id, thread id, and a high resolution timestamp to761* ensure that the nonce is unique with high probability for762* different process instances.763*/764data.pid = getpid();765data.tid = CRYPTO_THREAD_get_current_id();766data.time = get_time_stamp();767768return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);769}770771/*772* Get the current time with the highest possible resolution773*774* The time stamp is added to the nonce, so it is optimized for not repeating.775* The current time is ideal for this purpose, provided the computer's clock776* is synchronized.777*/778static uint64_t get_time_stamp(void)779{780# if defined(OSSL_POSIX_TIMER_OKAY)781{782struct timespec ts;783784if (clock_gettime(CLOCK_REALTIME, &ts) == 0)785return TWO32TO64(ts.tv_sec, ts.tv_nsec);786}787# endif788# if defined(__unix__) \789|| (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)790{791struct timeval tv;792793if (gettimeofday(&tv, NULL) == 0)794return TWO32TO64(tv.tv_sec, tv.tv_usec);795}796# endif797return time(NULL);798}799800#endif /* (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS))801|| defined(__DJGPP__) */802803804