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