Path: blob/main/crypto/openssl/providers/implementations/rands/seeding/rand_unix.c
108736 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) && (defined(OPENSSL_NO_EGD) || !defined(DEVRANDOM_EGD))197#error "Seeding uses EGD but EGD is turned off or no device given"198#endif199200#if defined(OPENSSL_RAND_SEED_DEVRANDOM) && !defined(DEVRANDOM)201#error "Seeding uses urandom but DEVRANDOM is not configured"202#endif203204#if defined(OPENSSL_RAND_SEED_OS)205#if !defined(DEVRANDOM)206#error "OS seeding requires DEVRANDOM to be configured"207#endif208#define OPENSSL_RAND_SEED_GETRANDOM209#define OPENSSL_RAND_SEED_DEVRANDOM210#endif211212#if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)213/*214* sysctl_random(): Use sysctl() to read a random number from the kernel215* Returns the number of bytes returned in buf on success, -1 on failure.216*/217static ssize_t sysctl_random(char *buf, size_t buflen)218{219int mib[2];220size_t done = 0;221size_t len;222223/*224* Note: sign conversion between size_t and ssize_t is safe even225* without a range check, see comment in syscall_random()226*/227228/*229* On FreeBSD old implementations returned longs, newer versions support230* variable sizes up to 256 byte. The code below would not work properly231* when the sysctl returns long and we want to request something not a232* multiple of longs, which should never be the case.233*/234#if defined(__FreeBSD__)235if (!ossl_assert(buflen % sizeof(long) == 0)) {236errno = EINVAL;237return -1;238}239#endif240241/*242* On NetBSD before 4.0 KERN_ARND was an alias for KERN_URND, and only243* filled in an int, leaving the rest uninitialized. Since NetBSD 4.0244* it returns a variable number of bytes with the current version supporting245* up to 256 bytes.246* Just return an error on older NetBSD versions.247*/248#if defined(__NetBSD__) && __NetBSD_Version__ < 400000000249errno = ENOSYS;250return -1;251#endif252253mib[0] = CTL_KERN;254mib[1] = KERN_ARND;255256do {257len = buflen > 256 ? 256 : buflen;258if (sysctl(mib, 2, buf, &len, NULL, 0) == -1)259return done > 0 ? done : -1;260done += len;261buf += len;262buflen -= len;263} while (buflen > 0);264265return done;266}267#endif268269#if defined(OPENSSL_RAND_SEED_GETRANDOM)270271#if defined(__linux) && !defined(__NR_getrandom)272#if defined(__arm__)273#define __NR_getrandom (__NR_SYSCALL_BASE + 384)274#elif defined(__i386__)275#define __NR_getrandom 355276#elif defined(__x86_64__)277#if defined(__ILP32__)278#define __NR_getrandom (__X32_SYSCALL_BIT + 318)279#else280#define __NR_getrandom 318281#endif282#elif defined(__xtensa__)283#define __NR_getrandom 338284#elif defined(__s390__) || defined(__s390x__)285#define __NR_getrandom 349286#elif defined(__bfin__)287#define __NR_getrandom 389288#elif defined(__powerpc__)289#define __NR_getrandom 359290#elif defined(__mips__) || defined(__mips64)291#if _MIPS_SIM == _MIPS_SIM_ABI32292#define __NR_getrandom (__NR_Linux + 353)293#elif _MIPS_SIM == _MIPS_SIM_ABI64294#define __NR_getrandom (__NR_Linux + 313)295#elif _MIPS_SIM == _MIPS_SIM_NABI32296#define __NR_getrandom (__NR_Linux + 317)297#endif298#elif defined(__hppa__)299#define __NR_getrandom (__NR_Linux + 339)300#elif defined(__sparc__)301#define __NR_getrandom 347302#elif defined(__ia64__)303#define __NR_getrandom 1339304#elif defined(__alpha__)305#define __NR_getrandom 511306#elif defined(__sh__)307#if defined(__SH5__)308#define __NR_getrandom 373309#else310#define __NR_getrandom 384311#endif312#elif defined(__avr32__)313#define __NR_getrandom 317314#elif defined(__microblaze__)315#define __NR_getrandom 385316#elif defined(__m68k__)317#define __NR_getrandom 352318#elif defined(__cris__)319#define __NR_getrandom 356320#else /* generic (f.e. aarch64, loongarch, loongarch64) */321#define __NR_getrandom 278322#endif323#endif324325/*326* syscall_random(): Try to get random data using a system call327* returns the number of bytes returned in buf, or < 0 on error.328*/329static ssize_t syscall_random(void *buf, size_t buflen)330{331/*332* Note: 'buflen' equals the size of the buffer which is used by the333* get_entropy() callback of the RAND_DRBG. It is roughly bounded by334*335* 2 * RAND_POOL_FACTOR * (RAND_DRBG_STRENGTH / 8) = 2^14336*337* which is way below the OSSL_SSIZE_MAX limit. Therefore sign conversion338* between size_t and ssize_t is safe even without a range check.339*/340341/*342* Do runtime detection to find getentropy().343*344* Known OSs that should support this:345* - Darwin since 16 (OSX 10.12, IOS 10.0).346* - Solaris since 11.3347* - OpenBSD since 5.6348* - Linux since 3.17 with glibc 2.25349*350* Note: Sometimes getentropy() can be provided but not implemented351* internally. So we need to check errno for ENOSYS352*/353#if !defined(__DragonFly__) && !defined(__NetBSD__) && !defined(__FreeBSD__)354#if defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__) && !defined(__hpux)355extern int getentropy(void *buffer, size_t length) __attribute__((weak));356357if (getentropy != NULL) {358if (getentropy(buf, buflen) == 0)359return (ssize_t)buflen;360if (errno != ENOSYS)361return -1;362}363#elif defined(OPENSSL_APPLE_CRYPTO_RANDOM)364365if (CCRandomGenerateBytes(buf, buflen) == kCCSuccess)366return (ssize_t)buflen;367368return -1;369#else370union {371void *p;372int (*f)(void *buffer, size_t length);373} p_getentropy;374375/*376* We could cache the result of the lookup, but we normally don't377* call this function often.378*/379ERR_set_mark();380p_getentropy.p = DSO_global_lookup("getentropy");381ERR_pop_to_mark();382if (p_getentropy.p != NULL)383return p_getentropy.f(buf, buflen) == 0 ? (ssize_t)buflen : -1;384#endif385#endif /* !__DragonFly__ && !__NetBSD__ && !__FreeBSD__ */386387/* Linux supports this since version 3.17 */388#if defined(__linux) && defined(__NR_getrandom)389return syscall(__NR_getrandom, buf, buflen, 0);390#elif (defined(__DragonFly__) && __DragonFly_version >= 500700) \391|| (defined(__NetBSD__) && __NetBSD_Version >= 1000000000) \392|| (defined(__FreeBSD__) && __FreeBSD_version >= 1200061)393return getrandom(buf, buflen, 0);394#elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)395return sysctl_random(buf, buflen);396#elif defined(__wasi__)397if (getentropy(buf, buflen) == 0)398return (ssize_t)buflen;399return -1;400#else401errno = ENOSYS;402return -1;403#endif404}405#endif /* defined(OPENSSL_RAND_SEED_GETRANDOM) */406407#if defined(OPENSSL_RAND_SEED_DEVRANDOM)408static const char *random_device_paths[] = { DEVRANDOM };409static struct random_device {410int fd;411dev_t dev;412ino_t ino;413mode_t mode;414dev_t rdev;415} random_devices[OSSL_NELEM(random_device_paths)];416static int keep_random_devices_open = 1;417418#if defined(__linux) && defined(DEVRANDOM_WAIT) \419&& defined(OPENSSL_RAND_SEED_GETRANDOM)420static void *shm_addr;421422static void cleanup_shm(void)423{424shmdt(shm_addr);425}426427/*428* Ensure that the system randomness source has been adequately seeded.429* This is done by having the first start of libcrypto, wait until the device430* /dev/random becomes able to supply a byte of entropy. Subsequent starts431* of the library and later reseedings do not need to do this.432*/433static int wait_random_seeded(void)434{435static int seeded = OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID < 0;436static const int kernel_version[] = { DEVRANDOM_SAFE_KERNEL };437int kernel[2];438int shm_id, fd, r;439char c, *p;440struct utsname un;441fd_set fds;442443if (!seeded) {444/* See if anything has created the global seeded indication */445if ((shm_id = shmget(OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID, 1, 0)) == -1) {446/*447* Check the kernel's version and fail if it is too recent.448*449* Linux kernels from 4.8 onwards do not guarantee that450* /dev/urandom is properly seeded when /dev/random becomes451* readable. However, such kernels support the getentropy(2)452* system call and this should always succeed which renders453* this alternative but essentially identical source moot.454*/455if (uname(&un) == 0) {456kernel[0] = atoi(un.release);457p = strchr(un.release, '.');458kernel[1] = p == NULL ? 0 : atoi(p + 1);459if (kernel[0] > kernel_version[0]460|| (kernel[0] == kernel_version[0]461&& kernel[1] >= kernel_version[1])) {462return 0;463}464}465/* Open /dev/random and wait for it to be readable */466if ((fd = open(DEVRANDOM_WAIT, O_RDONLY)) != -1) {467if (DEVRANDM_WAIT_USE_SELECT && fd < FD_SETSIZE) {468FD_ZERO(&fds);469FD_SET(fd, &fds);470while ((r = select(fd + 1, &fds, NULL, NULL, NULL)) < 0471&& errno == EINTR)472;473} else {474while ((r = read(fd, &c, 1)) < 0 && errno == EINTR)475;476}477close(fd);478if (r == 1) {479seeded = 1;480/* Create the shared memory indicator */481shm_id = shmget(OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID, 1,482IPC_CREAT | S_IRUSR | S_IRGRP | S_IROTH);483}484}485}486if (shm_id != -1) {487seeded = 1;488/*489* Map the shared memory to prevent its premature destruction.490* If this call fails, it isn't a big problem.491*/492shm_addr = shmat(shm_id, NULL, SHM_RDONLY);493if (shm_addr != (void *)-1)494OPENSSL_atexit(&cleanup_shm);495}496}497return seeded;498}499#else /* defined __linux && DEVRANDOM_WAIT && OPENSSL_RAND_SEED_GETRANDOM */500static int wait_random_seeded(void)501{502return 1;503}504#endif505506/*507* Verify that the file descriptor associated with the random source is508* still valid. The rationale for doing this is the fact that it is not509* uncommon for daemons to close all open file handles when daemonizing.510* So the handle might have been closed or even reused for opening511* another file.512*/513static int check_random_device(struct random_device *rd)514{515struct stat st;516517return rd->fd != -1518&& fstat(rd->fd, &st) != -1519&& rd->dev == st.st_dev520&& rd->ino == st.st_ino521&& ((rd->mode ^ st.st_mode) & ~(S_IRWXU | S_IRWXG | S_IRWXO)) == 0522&& rd->rdev == st.st_rdev;523}524525/*526* Open a random device if required and return its file descriptor or -1 on error527*/528static int get_random_device(size_t n)529{530struct stat st;531struct random_device *rd = &random_devices[n];532533/* reuse existing file descriptor if it is (still) valid */534if (check_random_device(rd))535return rd->fd;536537/* open the random device ... */538if ((rd->fd = open(random_device_paths[n], O_RDONLY)) == -1)539return rd->fd;540541/* ... and cache its relevant stat(2) data */542if (fstat(rd->fd, &st) != -1) {543rd->dev = st.st_dev;544rd->ino = st.st_ino;545rd->mode = st.st_mode;546rd->rdev = st.st_rdev;547} else {548close(rd->fd);549rd->fd = -1;550}551552return rd->fd;553}554555/*556* Close a random device making sure it is a random device557*/558static void close_random_device(size_t n)559{560struct random_device *rd = &random_devices[n];561562if (check_random_device(rd))563close(rd->fd);564rd->fd = -1;565}566567int ossl_rand_pool_init(void)568{569size_t i;570571for (i = 0; i < OSSL_NELEM(random_devices); i++)572random_devices[i].fd = -1;573574return 1;575}576577void ossl_rand_pool_cleanup(void)578{579size_t i;580581for (i = 0; i < OSSL_NELEM(random_devices); i++)582close_random_device(i);583}584585void ossl_rand_pool_keep_random_devices_open(int keep)586{587if (!keep)588ossl_rand_pool_cleanup();589590keep_random_devices_open = keep;591}592593#else /* !defined(OPENSSL_RAND_SEED_DEVRANDOM) */594595int ossl_rand_pool_init(void)596{597return 1;598}599600void ossl_rand_pool_cleanup(void)601{602}603604void ossl_rand_pool_keep_random_devices_open(int keep)605{606}607608#endif /* defined(OPENSSL_RAND_SEED_DEVRANDOM) */609610/*611* Try the various seeding methods in turn, exit when successful.612*613* If more than one entropy source is available, is it614* preferable to stop as soon as enough entropy has been collected615* (as favored by @rsalz) or should one rather be defensive and add616* more entropy than requested and/or from different sources?617*618* Currently, the user can select multiple entropy sources in the619* configure step, yet in practice only the first available source620* will be used. A more flexible solution has been requested, but621* currently it is not clear how this can be achieved without622* overengineering the problem. There are many parameters which623* could be taken into account when selecting the order and amount624* of input from the different entropy sources (trust, quality,625* possibility of blocking).626*/627size_t ossl_pool_acquire_entropy(RAND_POOL *pool)628{629#if defined(OPENSSL_RAND_SEED_NONE)630return ossl_rand_pool_entropy_available(pool);631#else632size_t entropy_available = 0;633634(void)entropy_available; /* avoid compiler warning */635636#if defined(OPENSSL_RAND_SEED_GETRANDOM)637{638size_t bytes_needed;639unsigned char *buffer;640ssize_t bytes;641/* Maximum allowed number of consecutive unsuccessful attempts */642int attempts = 3;643644bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);645while (bytes_needed != 0 && attempts-- > 0) {646buffer = ossl_rand_pool_add_begin(pool, bytes_needed);647bytes = syscall_random(buffer, bytes_needed);648if (bytes > 0) {649ossl_rand_pool_add_end(pool, bytes, 8 * bytes);650bytes_needed -= bytes;651attempts = 3; /* reset counter after successful attempt */652} else if (bytes < 0 && errno != EINTR) {653break;654}655}656}657entropy_available = ossl_rand_pool_entropy_available(pool);658if (entropy_available > 0)659return entropy_available;660#endif661662#if defined(OPENSSL_RAND_SEED_DEVRANDOM)663if (wait_random_seeded()) {664size_t bytes_needed;665unsigned char *buffer;666size_t i;667668bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);669for (i = 0; bytes_needed > 0 && i < OSSL_NELEM(random_device_paths);670i++) {671ssize_t bytes = 0;672/* Maximum number of consecutive unsuccessful attempts */673int attempts = 3;674const int fd = get_random_device(i);675676if (fd == -1)677continue;678679while (bytes_needed != 0 && attempts-- > 0) {680buffer = ossl_rand_pool_add_begin(pool, bytes_needed);681bytes = read(fd, buffer, bytes_needed);682683if (bytes > 0) {684ossl_rand_pool_add_end(pool, bytes, 8 * bytes);685bytes_needed -= bytes;686attempts = 3; /* reset counter on successful attempt */687} else if (bytes < 0 && errno != EINTR) {688break;689}690}691if (bytes < 0 || !keep_random_devices_open)692close_random_device(i);693694bytes_needed = ossl_rand_pool_bytes_needed(pool, 1);695}696entropy_available = ossl_rand_pool_entropy_available(pool);697if (entropy_available > 0)698return entropy_available;699}700#endif701702#if defined(OPENSSL_RAND_SEED_RDTSC)703entropy_available = ossl_prov_acquire_entropy_from_tsc(pool);704if (entropy_available > 0)705return entropy_available;706#endif707708#if defined(OPENSSL_RAND_SEED_RDCPU)709entropy_available = ossl_prov_acquire_entropy_from_cpu(pool);710if (entropy_available > 0)711return entropy_available;712#endif713714#if defined(OPENSSL_RAND_SEED_EGD)715{716static const char *paths[] = { DEVRANDOM_EGD, NULL };717size_t bytes_needed;718unsigned char *buffer;719int i;720721bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);722for (i = 0; bytes_needed > 0 && paths[i] != NULL; i++) {723size_t bytes = 0;724int num;725726buffer = ossl_rand_pool_add_begin(pool, bytes_needed);727num = RAND_query_egd_bytes(paths[i],728buffer, (int)bytes_needed);729if (num == (int)bytes_needed)730bytes = bytes_needed;731732ossl_rand_pool_add_end(pool, bytes, 8 * bytes);733bytes_needed = ossl_rand_pool_bytes_needed(pool, 1);734}735entropy_available = ossl_rand_pool_entropy_available(pool);736if (entropy_available > 0)737return entropy_available;738}739#endif740741return ossl_rand_pool_entropy_available(pool);742#endif743}744#endif745#endif746747#if (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS)) \748|| defined(__DJGPP__)749int ossl_pool_add_nonce_data(RAND_POOL *pool)750{751struct {752pid_t pid;753CRYPTO_THREAD_ID tid;754uint64_t time;755} data;756757/* Erase the entire structure including any padding */758memset(&data, 0, sizeof(data));759760/*761* Add process id, thread id, and a high resolution timestamp to762* ensure that the nonce is unique with high probability for763* different process instances.764*/765data.pid = getpid();766data.tid = CRYPTO_THREAD_get_current_id();767data.time = get_time_stamp();768769return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);770}771772/*773* Get the current time with the highest possible resolution774*775* The time stamp is added to the nonce, so it is optimized for not repeating.776* The current time is ideal for this purpose, provided the computer's clock777* is synchronized.778*/779static uint64_t get_time_stamp(void)780{781#if defined(OSSL_POSIX_TIMER_OKAY)782{783struct timespec ts;784785if (clock_gettime(CLOCK_REALTIME, &ts) == 0)786return TWO32TO64(ts.tv_sec, ts.tv_nsec);787}788#endif789#if defined(__unix__) \790|| (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)791{792struct timeval tv;793794if (gettimeofday(&tv, NULL) == 0)795return TWO32TO64(tv.tv_sec, tv.tv_usec);796}797#endif798return time(NULL);799}800801#endif /* (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS)) \802|| defined(__DJGPP__) */803804805