/src/ntpsec/libntp/ntp_random.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright the NTPsec project contributors |
3 | | * SPDX-License-Identifier: BSD-2-Clause |
4 | | */ |
5 | | |
6 | | #include <stdint.h> |
7 | | #include <string.h> |
8 | | |
9 | | #include <openssl/opensslv.h> |
10 | | #include <openssl/rand.h> |
11 | | |
12 | | #include "config.h" |
13 | | #include "ntp.h" |
14 | | #include "ntp_stdlib.h" |
15 | | #include "ntp_syslog.h" |
16 | | |
17 | | #ifndef PRAND_BUF_LEN |
18 | 0 | #define PRAND_BUF_LEN 4096l |
19 | | #endif |
20 | | static uint8_t prand_buffer[PRAND_BUF_LEN]; |
21 | | static size_t prand_burned = PRAND_BUF_LEN; |
22 | | |
23 | | /* NB: RAND_bytes comes from OpenSSL |
24 | | * Starting in version 1.1.1, it reseeds itself occasionally. |
25 | | * That may need access to /dev/urandom which may be blocked by chroot jails. |
26 | | * getrandom(2) is used when available. It was added to Linux kernel 3.17 |
27 | | * so this won't be a problem on newer Linux systems. |
28 | | */ |
29 | | |
30 | | /* Use psuedorandom pool to get entropy from */ |
31 | 0 | static void ntp_pool_rand_fill(uint8_t *buf, int num) { |
32 | 0 | if (0 > num) { |
33 | 0 | return; |
34 | 0 | } |
35 | 0 | if (1 != RAND_bytes(buf, num)) { |
36 | 0 | msyslog(LOG_ERR, "ERR: RAND_bytes failed"); |
37 | 0 | exit(1); |
38 | 0 | } |
39 | 0 | } |
40 | | |
41 | 0 | void ntp_RAND_bytes(unsigned char *buf, int num) { |
42 | 0 | if (0 >= num) { |
43 | 0 | return; |
44 | 0 | } |
45 | 0 | if (PRAND_BUF_LEN <= num) { // This should never happen |
46 | 0 | return ntp_pool_rand_fill(buf, num); |
47 | 0 | } |
48 | 0 | if (PRAND_BUF_LEN < num + prand_burned) { |
49 | 0 | ntp_pool_rand_fill(prand_buffer, prand_burned); |
50 | 0 | prand_burned = 0; |
51 | 0 | } |
52 | 0 | memcpy(buf, prand_buffer + prand_burned, num); |
53 | 0 | prand_burned += num; |
54 | 0 | } |
55 | | |
56 | 0 | void ntp_RAND_priv_bytes(unsigned char *buf, int num) { |
57 | 0 | int err; |
58 | 0 | #if (OPENSSL_VERSION_NUMBER > 0x1010100fL) && !defined(LIBRESSL_VERSION_NUMBER) |
59 | 0 | err = RAND_priv_bytes(buf, num); |
60 | | #else |
61 | | err = RAND_bytes(buf, num); |
62 | | #endif |
63 | 0 | if (1 != err) { |
64 | 0 | msyslog(LOG_ERR, "ERR: RAND_priv_bytes failed"); |
65 | 0 | exit(1); |
66 | 0 | } |
67 | 0 | } |
68 | | |
69 | | /* Return four byes of entropy. This differs from the ~31bits from random() */ |
70 | | |
71 | 0 | uint32_t ntp_random(void) { |
72 | 0 | uint32_t ret; |
73 | 0 | ntp_RAND_bytes((uint8_t*)&ret, sizeof(ret)); |
74 | 0 | return ret; |
75 | 0 | } |