1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #if defined(__i386__) || defined(__x86_64__)
4 #include <cpuid.h>
5 #endif
6
7 #include <elf.h>
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <linux/random.h>
11 #include <pthread.h>
12 #include <stdbool.h>
13 #include <stdint.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/ioctl.h>
17 #include <sys/time.h>
18
19 #if HAVE_SYS_AUXV_H
20 # include <sys/auxv.h>
21 #endif
22
23 #include "alloc-util.h"
24 #include "env-util.h"
25 #include "errno-util.h"
26 #include "fd-util.h"
27 #include "fileio.h"
28 #include "io-util.h"
29 #include "missing_random.h"
30 #include "missing_syscall.h"
31 #include "parse-util.h"
32 #include "random-util.h"
33 #include "siphash24.h"
34 #include "time-util.h"
35
36 static bool srand_called = false;
37
genuine_random_bytes(void * p,size_t n,RandomFlags flags)38 int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
39 static int have_syscall = -1;
40 _cleanup_close_ int fd = -1;
41
42 /* Gathers some high-quality randomness from the kernel. This call won't block, unless the RANDOM_BLOCK
43 * flag is set. If it doesn't block, it will still always return some data from the kernel, regardless
44 * of whether the random pool is fully initialized or not. When creating cryptographic key material you
45 * should always use RANDOM_BLOCK. */
46
47 if (n == 0)
48 return 0;
49
50 /* Use the getrandom() syscall unless we know we don't have it. */
51 if (have_syscall != 0 && !HAS_FEATURE_MEMORY_SANITIZER) {
52 for (;;) {
53 ssize_t l = getrandom(p, n, FLAGS_SET(flags, RANDOM_BLOCK) ? 0 : GRND_INSECURE);
54
55 if (l > 0) {
56 have_syscall = true;
57
58 if ((size_t) l == n)
59 return 0; /* Yay, success! */
60
61 /* We didn't get enough data, so try again */
62 assert((size_t) l < n);
63 p = (uint8_t*) p + l;
64 n -= l;
65 continue;
66
67 } else if (l == 0) {
68 have_syscall = true;
69 return -EIO;
70
71 } else if (ERRNO_IS_NOT_SUPPORTED(errno)) {
72 /* We lack the syscall, continue with reading from /dev/urandom. */
73 have_syscall = false;
74 break;
75
76 } else if (errno == EINVAL) {
77 /* If we previously passed GRND_INSECURE, and this flag isn't known, then
78 * we're likely running an old kernel which has getrandom() but not
79 * GRND_INSECURE. In this case, fall back to /dev/urandom. */
80 if (!FLAGS_SET(flags, RANDOM_BLOCK))
81 break;
82
83 return -errno;
84 } else
85 return -errno;
86 }
87 }
88
89 fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
90 if (fd < 0)
91 return errno == ENOENT ? -ENOSYS : -errno;
92
93 return loop_read_exact(fd, p, n, true);
94 }
95
clear_srand_initialization(void)96 static void clear_srand_initialization(void) {
97 srand_called = false;
98 }
99
initialize_srand(void)100 void initialize_srand(void) {
101 static bool pthread_atfork_registered = false;
102 unsigned x;
103
104 if (srand_called)
105 return;
106
107 #if HAVE_SYS_AUXV_H
108 /* The kernel provides us with 16 bytes of entropy in auxv, so let's try to make use of that to seed
109 * the pseudo-random generator. It's better than nothing... But let's first hash it to make it harder
110 * to recover the original value by watching any pseudo-random bits we generate. After all the
111 * AT_RANDOM data might be used by other stuff too (in particular: ASLR), and we probably shouldn't
112 * leak the seed for that. */
113
114 const void *auxv = ULONG_TO_PTR(getauxval(AT_RANDOM));
115 if (auxv) {
116 static const uint8_t auxval_hash_key[16] = {
117 0x92, 0x6e, 0xfe, 0x1b, 0xcf, 0x00, 0x52, 0x9c, 0xcc, 0x42, 0xcf, 0xdc, 0x94, 0x1f, 0x81, 0x0f
118 };
119
120 x = (unsigned) siphash24(auxv, 16, auxval_hash_key);
121 } else
122 #endif
123 x = 0;
124
125 x ^= (unsigned) now(CLOCK_REALTIME);
126 x ^= (unsigned) gettid();
127
128 srand(x);
129 srand_called = true;
130
131 if (!pthread_atfork_registered) {
132 (void) pthread_atfork(NULL, NULL, clear_srand_initialization);
133 pthread_atfork_registered = true;
134 }
135 }
136
137 /* INT_MAX gives us only 31 bits, so use 24 out of that. */
138 #if RAND_MAX >= INT_MAX
139 assert_cc(RAND_MAX >= 16777215);
140 # define RAND_STEP 3
141 #else
142 /* SHORT_INT_MAX or lower gives at most 15 bits, we just use 8 out of that. */
143 assert_cc(RAND_MAX >= 255);
144 # define RAND_STEP 1
145 #endif
146
pseudo_random_bytes(void * p,size_t n)147 void pseudo_random_bytes(void *p, size_t n) {
148 uint8_t *q;
149
150 /* This returns pseudo-random data using libc's rand() function. You probably never want to call this
151 * directly, because why would you use this if you can get better stuff cheaply? Use random_bytes()
152 * instead, see below: it will fall back to this function if there's nothing better to get, but only
153 * then. */
154
155 initialize_srand();
156
157 for (q = p; q < (uint8_t*) p + n; q += RAND_STEP) {
158 unsigned rr;
159
160 rr = (unsigned) rand();
161
162 #if RAND_STEP >= 3
163 if ((size_t) (q - (uint8_t*) p + 2) < n)
164 q[2] = rr >> 16;
165 #endif
166 #if RAND_STEP >= 2
167 if ((size_t) (q - (uint8_t*) p + 1) < n)
168 q[1] = rr >> 8;
169 #endif
170 q[0] = rr;
171 }
172 }
173
random_bytes(void * p,size_t n)174 void random_bytes(void *p, size_t n) {
175
176 /* This returns high quality randomness if we can get it cheaply. If we can't because for some reason
177 * it is not available we'll try some crappy fallbacks.
178 *
179 * What this function will do:
180 *
181 * • Use getrandom(GRND_INSECURE) or /dev/urandom, to return high-quality random values if
182 * they are cheaply available, or less high-quality random values if they are not.
183 *
184 * • This function will return pseudo-random data, generated via libc rand() if nothing
185 * better is available.
186 *
187 * • This function will work fine in early boot
188 *
189 * • This function will always succeed
190 *
191 * What this function won't do:
192 *
193 * • This function will never fail: it will give you randomness no matter what. It might not
194 * be high quality, but it will return some, possibly generated via libc's rand() call.
195 *
196 * • This function will never block: if the only way to get good randomness is a blocking,
197 * synchronous getrandom() we'll instead provide you with pseudo-random data.
198 *
199 * This function is hence great for things like seeding hash tables, generating random numeric UNIX
200 * user IDs (that are checked for collisions before use) and such.
201 *
202 * This function is hence not useful for generating UUIDs or cryptographic key material.
203 */
204
205 if (genuine_random_bytes(p, n, 0) >= 0)
206 return;
207
208 /* If for some reason some user made /dev/urandom unavailable to us, or the kernel has no entropy, use a PRNG instead. */
209 pseudo_random_bytes(p, n);
210 }
211
random_pool_size(void)212 size_t random_pool_size(void) {
213 _cleanup_free_ char *s = NULL;
214 int r;
215
216 /* Read pool size, if possible */
217 r = read_one_line_file("/proc/sys/kernel/random/poolsize", &s);
218 if (r < 0)
219 log_debug_errno(r, "Failed to read pool size from kernel: %m");
220 else {
221 unsigned sz;
222
223 r = safe_atou(s, &sz);
224 if (r < 0)
225 log_debug_errno(r, "Failed to parse pool size: %s", s);
226 else
227 /* poolsize is in bits on 2.6, but we want bytes */
228 return CLAMP(sz / 8, RANDOM_POOL_SIZE_MIN, RANDOM_POOL_SIZE_MAX);
229 }
230
231 /* Use the minimum as default, if we can't retrieve the correct value */
232 return RANDOM_POOL_SIZE_MIN;
233 }
234
random_write_entropy(int fd,const void * seed,size_t size,bool credit)235 int random_write_entropy(int fd, const void *seed, size_t size, bool credit) {
236 _cleanup_close_ int opened_fd = -1;
237 int r;
238
239 assert(seed || size == 0);
240
241 if (size == 0)
242 return 0;
243
244 if (fd < 0) {
245 opened_fd = open("/dev/urandom", O_WRONLY|O_CLOEXEC|O_NOCTTY);
246 if (opened_fd < 0)
247 return -errno;
248
249 fd = opened_fd;
250 }
251
252 if (credit) {
253 _cleanup_free_ struct rand_pool_info *info = NULL;
254
255 /* The kernel API only accepts "int" as entropy count (which is in bits), let's avoid any
256 * chance for confusion here. */
257 if (size > INT_MAX / 8)
258 return -EOVERFLOW;
259
260 info = malloc(offsetof(struct rand_pool_info, buf) + size);
261 if (!info)
262 return -ENOMEM;
263
264 info->entropy_count = size * 8;
265 info->buf_size = size;
266 memcpy(info->buf, seed, size);
267
268 if (ioctl(fd, RNDADDENTROPY, info) < 0)
269 return -errno;
270 } else {
271 r = loop_write(fd, seed, size, false);
272 if (r < 0)
273 return r;
274 }
275
276 return 1;
277 }
278
random_u64_range(uint64_t m)279 uint64_t random_u64_range(uint64_t m) {
280 uint64_t x, remainder;
281
282 /* Generates a random number in the range 0…m-1, unbiased. (Java's algorithm) */
283
284 if (m == 0) /* Let's take m == 0 as special case to return an integer from the full range */
285 return random_u64();
286 if (m == 1)
287 return 0;
288
289 remainder = UINT64_MAX % m;
290
291 do {
292 x = random_u64();
293 } while (x >= UINT64_MAX - remainder);
294
295 return x % m;
296 }
297