Coverage Report

Created: 2025-06-13 06:58

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