]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/rand/rand_unix.c
Add missing cipher aliases to openssl(1)
[thirdparty/openssl.git] / crypto / rand / rand_unix.c
CommitLineData
b1322259 1/*
0d664759 2 * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
0c61e299 3 *
b1322259
RS
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
0c61e299 8 */
b1322259 9
a0e53000
AP
10#ifndef _GNU_SOURCE
11# define _GNU_SOURCE
12#endif
da0616cd 13#include "e_os.h"
07016a8a 14#include <stdio.h>
b39fc560 15#include "internal/cryptlib.h"
0c61e299
RL
16#include <openssl/rand.h>
17#include "rand_lcl.h"
6decf943 18#include "internal/rand_int.h"
8389ec4b 19#include <stdio.h>
cf0891b8 20#include "internal/dso.h"
14879629
KR
21#if defined(__linux)
22# include <sys/syscall.h>
23#endif
24#if defined(__FreeBSD__)
25# include <sys/types.h>
26# include <sys/sysctl.h>
27# include <sys/param.h>
28#endif
8f576627 29#if defined(__OpenBSD__) || defined(__NetBSD__)
14879629
KR
30# include <sys/param.h>
31#endif
748eb991
DMSP
32
33#if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__)
5bc6bcf8 34# include <sys/types.h>
c7504aeb
P
35# include <sys/stat.h>
36# include <fcntl.h>
5bc6bcf8
DMSP
37# include <unistd.h>
38# include <sys/time.h>
39
40static uint64_t get_time_stamp(void);
41static uint64_t get_timer_bits(void);
42
43/* Macro to convert two thirty two bit values into a sixty four bit one */
44# define TWO32TO64(a, b) ((((uint64_t)(a)) << 32) + (b))
45
46/*
47 * Check for the existence and support of POSIX timers. The standard
48 * says that the _POSIX_TIMERS macro will have a positive value if they
49 * are available.
50 *
51 * However, we want an additional constraint: that the timer support does
52 * not require an extra library dependency. Early versions of glibc
53 * require -lrt to be specified on the link line to access the timers,
54 * so this needs to be checked for.
55 *
56 * It is worse because some libraries define __GLIBC__ but don't
57 * support the version testing macro (e.g. uClibc). This means
58 * an extra check is needed.
59 *
60 * The final condition is:
61 * "have posix timers and either not glibc or glibc without -lrt"
62 *
63 * The nested #if sequences are required to avoid using a parameterised
64 * macro that might be undefined.
65 */
66# undef OSSL_POSIX_TIMER_OKAY
67# if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0
68# if defined(__GLIBC__)
69# if defined(__GLIBC_PREREQ)
70# if __GLIBC_PREREQ(2, 17)
71# define OSSL_POSIX_TIMER_OKAY
72# endif
73# endif
74# else
75# define OSSL_POSIX_TIMER_OKAY
76# endif
77# endif
748eb991 78#endif /* defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) */
0c61e299 79
c16de9d8 80#if (defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)) && \
8389ec4b 81 !defined(OPENSSL_RAND_SEED_NONE)
c16de9d8
DMSP
82# error "UEFI and VXWorks only support seeding NONE"
83#endif
84
85#if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) \
86 || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_VXWORKS) \
87 || defined(OPENSSL_SYS_UEFI))
0f113f3e 88
9b5f1c8f
DMSP
89static ssize_t syscall_random(void *buf, size_t buflen);
90
0f113f3e
MC
91# if defined(OPENSSL_SYS_VOS)
92
8389ec4b
RS
93# ifndef OPENSSL_RAND_SEED_OS
94# error "Unsupported seeding method configured; must be os"
95# endif
96
97# if defined(OPENSSL_SYS_VOS_HPPA) && defined(OPENSSL_SYS_VOS_IA32)
98# error "Unsupported HP-PA and IA32 at the same time."
99# endif
100# if !defined(OPENSSL_SYS_VOS_HPPA) && !defined(OPENSSL_SYS_VOS_IA32)
101# error "Must have one of HP-PA or IA32"
102# endif
103
0f113f3e
MC
104/*
105 * The following algorithm repeatedly samples the real-time clock (RTC) to
106 * generate a sequence of unpredictable data. The algorithm relies upon the
107 * uneven execution speed of the code (due to factors such as cache misses,
108 * interrupts, bus activity, and scheduling) and upon the rather large
109 * relative difference between the speed of the clock and the rate at which
75e2c877
RS
110 * it can be read. If it is ported to an environment where execution speed
111 * is more constant or where the RTC ticks at a much slower rate, or the
112 * clock can be read with fewer instructions, it is likely that the results
113 * would be far more predictable. This should only be used for legacy
114 * platforms.
0f113f3e 115 *
c16de9d8 116 * As a precaution, we assume only 2 bits of entropy per byte.
0f113f3e 117 */
6decf943 118size_t rand_pool_acquire_entropy(RAND_POOL *pool)
cc7399e7 119{
0f113f3e 120 short int code;
0f113f3e 121 int i, k;
c16de9d8 122 size_t bytes_needed;
0f113f3e
MC
123 struct timespec ts;
124 unsigned char v;
0f113f3e
MC
125# ifdef OPENSSL_SYS_VOS_HPPA
126 long duration;
127 extern void s$sleep(long *_duration, short int *_code);
128# else
0f113f3e
MC
129 long long duration;
130 extern void s$sleep2(long long *_duration, short int *_code);
8389ec4b 131# endif
0f113f3e 132
6ebb49f3 133 bytes_needed = rand_pool_bytes_needed(pool, 4 /*entropy_factor*/);
c16de9d8
DMSP
134
135 for (i = 0; i < bytes_needed; i++) {
0f113f3e
MC
136 /*
137 * burn some cpu; hope for interrupts, cache collisions, bus
138 * interference, etc.
139 */
140 for (k = 0; k < 99; k++)
141 ts.tv_nsec = random();
142
143# ifdef OPENSSL_SYS_VOS_HPPA
144 /* sleep for 1/1024 of a second (976 us). */
145 duration = 1;
146 s$sleep(&duration, &code);
147# else
0f113f3e
MC
148 /* sleep for 1/65536 of a second (15 us). */
149 duration = 1;
150 s$sleep2(&duration, &code);
8389ec4b 151# endif
0f113f3e 152
8389ec4b 153 /* Get wall clock time, take 8 bits. */
0f113f3e 154 clock_gettime(CLOCK_REALTIME, &ts);
8389ec4b 155 v = (unsigned char)(ts.tv_nsec & 0xFF);
6decf943 156 rand_pool_add(pool, arg, &v, sizeof(v) , 2);
0f113f3e 157 }
6decf943 158 return rand_pool_entropy_available(pool);
cc7399e7 159}
8389ec4b 160
c7504aeb
P
161void rand_pool_cleanup(void)
162{
163}
164
165void rand_pool_keep_random_devices_open(int keep)
166{
167}
168
810ef917 169# else
8389ec4b
RS
170
171# if defined(OPENSSL_RAND_SEED_EGD) && \
172 (defined(OPENSSL_NO_EGD) || !defined(DEVRANDOM_EGD))
173# error "Seeding uses EGD but EGD is turned off or no device given"
0f113f3e
MC
174# endif
175
8389ec4b
RS
176# if defined(OPENSSL_RAND_SEED_DEVRANDOM) && !defined(DEVRANDOM)
177# error "Seeding uses urandom but DEVRANDOM is not configured"
178# endif
0f113f3e 179
8389ec4b 180# if defined(OPENSSL_RAND_SEED_OS)
72960279 181# if !defined(DEVRANDOM)
8389ec4b 182# error "OS seeding requires DEVRANDOM to be configured"
0f113f3e 183# endif
14879629 184# define OPENSSL_RAND_SEED_GETRANDOM
72960279 185# define OPENSSL_RAND_SEED_DEVRANDOM
8389ec4b 186# endif
0f113f3e 187
8389ec4b
RS
188# if defined(OPENSSL_RAND_SEED_LIBRANDOM)
189# error "librandom not (yet) supported"
190# endif
0f113f3e 191
8f576627 192# if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
14879629
KR
193/*
194 * sysctl_random(): Use sysctl() to read a random number from the kernel
9b5f1c8f 195 * Returns the number of bytes returned in buf on success, -1 on failure.
14879629 196 */
9b5f1c8f 197static ssize_t sysctl_random(char *buf, size_t buflen)
14879629
KR
198{
199 int mib[2];
200 size_t done = 0;
201 size_t len;
202
9b5f1c8f
DMSP
203 /*
204 * Note: sign conversion between size_t and ssize_t is safe even
205 * without a range check, see comment in syscall_random()
206 */
207
14879629 208 /*
8f576627
KR
209 * On FreeBSD old implementations returned longs, newer versions support
210 * variable sizes up to 256 byte. The code below would not work properly
211 * when the sysctl returns long and we want to request something not a
212 * multiple of longs, which should never be the case.
14879629 213 */
9b5f1c8f
DMSP
214 if (!ossl_assert(buflen % sizeof(long) == 0)) {
215 errno = EINVAL;
216 return -1;
217 }
14879629 218
8f576627
KR
219 /*
220 * On NetBSD before 4.0 KERN_ARND was an alias for KERN_URND, and only
221 * filled in an int, leaving the rest uninitialized. Since NetBSD 4.0
222 * it returns a variable number of bytes with the current version supporting
223 * up to 256 bytes.
224 * Just return an error on older NetBSD versions.
225 */
226#if defined(__NetBSD__) && __NetBSD_Version__ < 400000000
9b5f1c8f
DMSP
227 errno = ENOSYS;
228 return -1;
8f576627
KR
229#endif
230
14879629
KR
231 mib[0] = CTL_KERN;
232 mib[1] = KERN_ARND;
233
234 do {
235 len = buflen;
236 if (sysctl(mib, 2, buf, &len, NULL, 0) == -1)
9b5f1c8f 237 return done > 0 ? done : -1;
14879629
KR
238 done += len;
239 buf += len;
240 buflen -= len;
241 } while (buflen > 0);
242
243 return done;
244}
245# endif
246
247/*
248 * syscall_random(): Try to get random data using a system call
9b5f1c8f 249 * returns the number of bytes returned in buf, or < 0 on error.
14879629 250 */
9b5f1c8f 251static ssize_t syscall_random(void *buf, size_t buflen)
14879629 252{
9b5f1c8f
DMSP
253 /*
254 * Note: 'buflen' equals the size of the buffer which is used by the
255 * get_entropy() callback of the RAND_DRBG. It is roughly bounded by
256 *
257 * 2 * DRBG_MINMAX_FACTOR * (RAND_DRBG_STRENGTH / 8) = 2^13
258 *
259 * which is way below the OSSL_SSIZE_MAX limit. Therefore sign conversion
260 * between size_t and ssize_t is safe even without a range check.
261 */
262
cf0891b8
KR
263 /*
264 * Do runtime detection to find getentropy().
265 *
cf0891b8
KR
266 * Known OSs that should support this:
267 * - Darwin since 16 (OSX 10.12, IOS 10.0).
268 * - Solaris since 11.3
269 * - OpenBSD since 5.6
270 * - Linux since 3.17 with glibc 2.25
271 * - FreeBSD since 12.0 (1200061)
272 */
8d58f017 273# if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux)
9b5f1c8f 274 extern int getentropy(void *buffer, size_t length) __attribute__((weak));
913cebc8
AP
275
276 if (getentropy != NULL)
9b5f1c8f 277 return getentropy(buf, buflen) == 0 ? (ssize_t)buflen : -1;
913cebc8
AP
278# else
279 union {
280 void *p;
281 int (*f)(void *buffer, size_t length);
282 } p_getentropy;
283
284 /*
285 * We could cache the result of the lookup, but we normally don't
286 * call this function often.
287 */
46ceca3c 288 ERR_set_mark();
cf0891b8 289 p_getentropy.p = DSO_global_lookup("getentropy");
46ceca3c 290 ERR_pop_to_mark();
cf0891b8 291 if (p_getentropy.p != NULL)
9b5f1c8f 292 return p_getentropy.f(buf, buflen) == 0 ? (ssize_t)buflen : -1;
913cebc8 293# endif
cf0891b8 294
cf0891b8 295 /* Linux supports this since version 3.17 */
14879629 296# if defined(__linux) && defined(SYS_getrandom)
9b5f1c8f
DMSP
297 return syscall(SYS_getrandom, buf, buflen, 0);
298# elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
299 return sysctl_random(buf, buflen);
300# else
301 errno = ENOSYS;
14879629 302 return -1;
9b5f1c8f 303# endif
14879629
KR
304}
305
c7504aeb
P
306#if !defined(OPENSSL_RAND_SEED_NONE) && defined(OPENSSL_RAND_SEED_DEVRANDOM)
307static const char *random_device_paths[] = { DEVRANDOM };
308static struct random_device {
309 int fd;
310 dev_t dev;
311 ino_t ino;
312 mode_t mode;
313 dev_t rdev;
314} random_devices[OSSL_NELEM(random_device_paths)];
315static int keep_random_devices_open = 1;
316
317/*
318 * Verify that the file descriptor associated with the random source is
319 * still valid. The rationale for doing this is the fact that it is not
320 * uncommon for daemons to close all open file handles when daemonizing.
321 * So the handle might have been closed or even reused for opening
322 * another file.
323 */
324static int check_random_device(struct random_device * rd)
325{
326 struct stat st;
327
328 return rd->fd != -1
329 && fstat(rd->fd, &st) != -1
330 && rd->dev == st.st_dev
331 && rd->ino == st.st_ino
332 && ((rd->mode ^ st.st_mode) & ~(S_IRWXU | S_IRWXG | S_IRWXO)) == 0
333 && rd->rdev == st.st_rdev;
334}
335
336/*
337 * Open a random device if required and return its file descriptor or -1 on error
338 */
339static int get_random_device(size_t n)
340{
341 struct stat st;
342 struct random_device * rd = &random_devices[n];
343
344 /* reuse existing file descriptor if it is (still) valid */
345 if (check_random_device(rd))
346 return rd->fd;
347
348 /* open the random device ... */
349 if ((rd->fd = open(random_device_paths[n], O_RDONLY)) == -1)
350 return rd->fd;
351
352 /* ... and cache its relevant stat(2) data */
353 if (fstat(rd->fd, &st) != -1) {
354 rd->dev = st.st_dev;
355 rd->ino = st.st_ino;
356 rd->mode = st.st_mode;
357 rd->rdev = st.st_rdev;
358 } else {
359 close(rd->fd);
360 rd->fd = -1;
361 }
362
363 return rd->fd;
364}
365
366/*
367 * Close a random device making sure it is a random device
368 */
369static void close_random_device(size_t n)
370{
371 struct random_device * rd = &random_devices[n];
372
373 if (check_random_device(rd))
374 close(rd->fd);
375 rd->fd = -1;
376}
377
378static void open_random_devices(void)
379{
380 size_t i;
381
382 for (i = 0; i < OSSL_NELEM(random_devices); i++)
383 (void)get_random_device(i);
384}
385
386int rand_pool_init(void)
387{
388 size_t i;
389
390 for (i = 0; i < OSSL_NELEM(random_devices); i++)
391 random_devices[i].fd = -1;
392 open_random_devices();
393 return 1;
394}
395
396void rand_pool_cleanup(void)
397{
398 size_t i;
399
400 for (i = 0; i < OSSL_NELEM(random_devices); i++)
401 close_random_device(i);
402}
403
404void rand_pool_keep_random_devices_open(int keep)
405{
406 if (keep)
407 open_random_devices();
408 else
409 rand_pool_cleanup();
410 keep_random_devices_open = keep;
411}
412
413# else /* defined(OPENSSL_RAND_SEED_NONE)
414 * || !defined(OPENSSL_RAND_SEED_DEVRANDOM)
415 */
416
417int rand_pool_init(void)
418{
419 return 1;
420}
421
422void rand_pool_cleanup(void)
423{
424}
425
426void rand_pool_keep_random_devices_open(int keep)
427{
428}
429
430# endif /* !defined(OPENSSL_RAND_SEED_NONE)
431 * && defined(OPENSSL_RAND_SEED_DEVRANDOM)
432 */
433
75e2c877 434/*
c16de9d8
DMSP
435 * Try the various seeding methods in turn, exit when successful.
436 *
437 * TODO(DRBG): If more than one entropy source is available, is it
438 * preferable to stop as soon as enough entropy has been collected
439 * (as favored by @rsalz) or should one rather be defensive and add
440 * more entropy than requested and/or from different sources?
441 *
442 * Currently, the user can select multiple entropy sources in the
443 * configure step, yet in practice only the first available source
444 * will be used. A more flexible solution has been requested, but
445 * currently it is not clear how this can be achieved without
446 * overengineering the problem. There are many parameters which
447 * could be taken into account when selecting the order and amount
448 * of input from the different entropy sources (trust, quality,
449 * possibility of blocking).
75e2c877 450 */
6decf943 451size_t rand_pool_acquire_entropy(RAND_POOL *pool)
8389ec4b
RS
452{
453# ifdef OPENSSL_RAND_SEED_NONE
6decf943 454 return rand_pool_entropy_available(pool);
8389ec4b 455# else
c16de9d8
DMSP
456 size_t bytes_needed;
457 size_t entropy_available = 0;
458 unsigned char *buffer;
0f113f3e 459
75e2c877 460# ifdef OPENSSL_RAND_SEED_GETRANDOM
630ce41e
DMSP
461 {
462 ssize_t bytes;
463 /* Maximum allowed number of consecutive unsuccessful attempts */
464 int attempts = 3;
465
466 bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
467 while (bytes_needed != 0 && attempts-- > 0) {
468 buffer = rand_pool_add_begin(pool, bytes_needed);
469 bytes = syscall_random(buffer, bytes_needed);
470 if (bytes > 0) {
471 rand_pool_add_end(pool, bytes, 8 * bytes);
472 bytes_needed -= bytes;
473 attempts = 3; /* reset counter after successful attempt */
474 } else if (bytes < 0 && errno != EINTR) {
475 break;
476 }
477 }
75e2c877 478 }
630ce41e 479 entropy_available = rand_pool_entropy_available(pool);
c16de9d8
DMSP
480 if (entropy_available > 0)
481 return entropy_available;
0f113f3e
MC
482# endif
483
75e2c877 484# if defined(OPENSSL_RAND_SEED_LIBRANDOM)
8389ec4b 485 {
75e2c877 486 /* Not yet implemented. */
0f113f3e 487 }
8389ec4b 488# endif
0f113f3e 489
8389ec4b 490# ifdef OPENSSL_RAND_SEED_DEVRANDOM
6ebb49f3 491 bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
c7504aeb
P
492 {
493 size_t i;
0f113f3e 494
c7504aeb 495 for (i = 0; bytes_needed > 0 && i < OSSL_NELEM(random_device_paths); i++) {
cca99621
DMSP
496 ssize_t bytes = 0;
497 /* Maximum allowed number of consecutive unsuccessful attempts */
498 int attempts = 3;
c7504aeb
P
499 const int fd = get_random_device(i);
500
501 if (fd == -1)
8389ec4b 502 continue;
c16de9d8 503
cca99621
DMSP
504 while (bytes_needed != 0 && attempts-- > 0) {
505 buffer = rand_pool_add_begin(pool, bytes_needed);
506 bytes = read(fd, buffer, bytes_needed);
c7504aeb 507
cca99621
DMSP
508 if (bytes > 0) {
509 rand_pool_add_end(pool, bytes, 8 * bytes);
510 bytes_needed -= bytes;
511 attempts = 3; /* reset counter after successful attempt */
512 } else if (bytes < 0 && errno != EINTR) {
513 break;
514 }
8389ec4b 515 }
cca99621 516 if (bytes < 0 || !keep_random_devices_open)
c7504aeb 517 close_random_device(i);
c16de9d8 518
6ebb49f3 519 bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
8389ec4b 520 }
c7504aeb
P
521 entropy_available = rand_pool_entropy_available(pool);
522 if (entropy_available > 0)
523 return entropy_available;
0f113f3e 524 }
8389ec4b 525# endif
0f113f3e 526
75e2c877 527# ifdef OPENSSL_RAND_SEED_RDTSC
c16de9d8
DMSP
528 entropy_available = rand_acquire_entropy_from_tsc(pool);
529 if (entropy_available > 0)
530 return entropy_available;
75e2c877
RS
531# endif
532
533# ifdef OPENSSL_RAND_SEED_RDCPU
c16de9d8
DMSP
534 entropy_available = rand_acquire_entropy_from_cpu(pool);
535 if (entropy_available > 0)
536 return entropy_available;
75e2c877
RS
537# endif
538
539# ifdef OPENSSL_RAND_SEED_EGD
6ebb49f3 540 bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
c16de9d8 541 if (bytes_needed > 0) {
75e2c877
RS
542 static const char *paths[] = { DEVRANDOM_EGD, NULL };
543 int i;
0f113f3e 544
75e2c877 545 for (i = 0; paths[i] != NULL; i++) {
6decf943 546 buffer = rand_pool_add_begin(pool, bytes_needed);
c16de9d8
DMSP
547 if (buffer != NULL) {
548 size_t bytes = 0;
549 int num = RAND_query_egd_bytes(paths[i],
550 buffer, (int)bytes_needed);
551 if (num == (int)bytes_needed)
552 bytes = bytes_needed;
553
8e2bec9b
RL
554 rand_pool_add_end(pool, bytes, 8 * bytes);
555 entropy_available = rand_pool_entropy_available(pool);
75e2c877 556 }
c16de9d8
DMSP
557 if (entropy_available > 0)
558 return entropy_available;
8389ec4b
RS
559 }
560 }
561# endif
0f113f3e 562
6decf943 563 return rand_pool_entropy_available(pool);
0f113f3e 564# endif
0c61e299 565}
8389ec4b 566# endif
5bc6bcf8
DMSP
567#endif
568
748eb991 569#if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__)
5bc6bcf8
DMSP
570int rand_pool_add_nonce_data(RAND_POOL *pool)
571{
572 struct {
573 pid_t pid;
574 CRYPTO_THREAD_ID tid;
575 uint64_t time;
576 } data = { 0 };
577
578 /*
579 * Add process id, thread id, and a high resolution timestamp to
580 * ensure that the nonce is unique whith high probability for
581 * different process instances.
582 */
583 data.pid = getpid();
584 data.tid = CRYPTO_THREAD_get_current_id();
585 data.time = get_time_stamp();
586
587 return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
588}
589
590int rand_pool_add_additional_data(RAND_POOL *pool)
591{
592 struct {
593 CRYPTO_THREAD_ID tid;
594 uint64_t time;
595 } data = { 0 };
596
597 /*
598 * Add some noise from the thread id and a high resolution timer.
599 * The thread id adds a little randomness if the drbg is accessed
600 * concurrently (which is the case for the <master> drbg).
601 */
602 data.tid = CRYPTO_THREAD_get_current_id();
603 data.time = get_timer_bits();
604
605 return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
606}
607
608
5bc6bcf8
DMSP
609/*
610 * Get the current time with the highest possible resolution
611 *
612 * The time stamp is added to the nonce, so it is optimized for not repeating.
613 * The current time is ideal for this purpose, provided the computer's clock
614 * is synchronized.
615 */
616static uint64_t get_time_stamp(void)
617{
618# if defined(OSSL_POSIX_TIMER_OKAY)
619 {
620 struct timespec ts;
621
622 if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
623 return TWO32TO64(ts.tv_sec, ts.tv_nsec);
624 }
625# endif
626# if defined(__unix__) \
627 || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
628 {
629 struct timeval tv;
630
631 if (gettimeofday(&tv, NULL) == 0)
632 return TWO32TO64(tv.tv_sec, tv.tv_usec);
633 }
634# endif
635 return time(NULL);
636}
637
638/*
639 * Get an arbitrary timer value of the highest possible resolution
640 *
641 * The timer value is added as random noise to the additional data,
642 * which is not considered a trusted entropy sourec, so any result
643 * is acceptable.
644 */
645static uint64_t get_timer_bits(void)
646{
647 uint64_t res = OPENSSL_rdtsc();
648
649 if (res != 0)
650 return res;
651
652# if defined(__sun) || defined(__hpux)
653 return gethrtime();
654# elif defined(_AIX)
655 {
656 timebasestruct_t t;
657
658 read_wall_time(&t, TIMEBASE_SZ);
659 return TWO32TO64(t.tb_high, t.tb_low);
660 }
661# elif defined(OSSL_POSIX_TIMER_OKAY)
662 {
663 struct timespec ts;
664
665# ifdef CLOCK_BOOTTIME
666# define CLOCK_TYPE CLOCK_BOOTTIME
667# elif defined(_POSIX_MONOTONIC_CLOCK)
668# define CLOCK_TYPE CLOCK_MONOTONIC
669# else
670# define CLOCK_TYPE CLOCK_REALTIME
671# endif
672
673 if (clock_gettime(CLOCK_TYPE, &ts) == 0)
674 return TWO32TO64(ts.tv_sec, ts.tv_nsec);
675 }
676# endif
677# if defined(__unix__) \
678 || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
679 {
680 struct timeval tv;
0c61e299 681
5bc6bcf8
DMSP
682 if (gettimeofday(&tv, NULL) == 0)
683 return TWO32TO64(tv.tv_sec, tv.tv_usec);
684 }
685# endif
686 return time(NULL);
687}
748eb991 688#endif /* defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) */