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