]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/rand/rand_unix.c
rand/rand_unix.c: mask getentropy ELF detection on HP-UX.
[thirdparty/openssl.git] / crypto / rand / rand_unix.c
1 /*
2 * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
3 *
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
8 */
9
10 #define _GNU_SOURCE
11 #include "e_os.h"
12 #include <stdio.h>
13 #include "internal/cryptlib.h"
14 #include <openssl/rand.h>
15 #include "rand_lcl.h"
16 #include "internal/rand_int.h"
17 #include <stdio.h>
18 #include "internal/dso.h"
19 #if defined(__linux)
20 # include <sys/syscall.h>
21 #endif
22 #if defined(__FreeBSD__)
23 # include <sys/types.h>
24 # include <sys/sysctl.h>
25 # include <sys/param.h>
26 #endif
27 #if defined(__OpenBSD__) || defined(__NetBSD__)
28 # include <sys/param.h>
29 #endif
30
31 #if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__)
32 # include <sys/types.h>
33 # include <unistd.h>
34 # include <sys/time.h>
35
36 static uint64_t get_time_stamp(void);
37 static uint64_t get_timer_bits(void);
38
39 /* Macro to convert two thirty two bit values into a sixty four bit one */
40 # define TWO32TO64(a, b) ((((uint64_t)(a)) << 32) + (b))
41
42 /*
43 * Check for the existence and support of POSIX timers. The standard
44 * says that the _POSIX_TIMERS macro will have a positive value if they
45 * are available.
46 *
47 * However, we want an additional constraint: that the timer support does
48 * not require an extra library dependency. Early versions of glibc
49 * require -lrt to be specified on the link line to access the timers,
50 * so this needs to be checked for.
51 *
52 * It is worse because some libraries define __GLIBC__ but don't
53 * support the version testing macro (e.g. uClibc). This means
54 * an extra check is needed.
55 *
56 * The final condition is:
57 * "have posix timers and either not glibc or glibc without -lrt"
58 *
59 * The nested #if sequences are required to avoid using a parameterised
60 * macro that might be undefined.
61 */
62 # undef OSSL_POSIX_TIMER_OKAY
63 # if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0
64 # if defined(__GLIBC__)
65 # if defined(__GLIBC_PREREQ)
66 # if __GLIBC_PREREQ(2, 17)
67 # define OSSL_POSIX_TIMER_OKAY
68 # endif
69 # endif
70 # else
71 # define OSSL_POSIX_TIMER_OKAY
72 # endif
73 # endif
74 #endif /* defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) */
75
76 int syscall_random(void *buf, size_t buflen);
77
78 #if (defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)) && \
79 !defined(OPENSSL_RAND_SEED_NONE)
80 # error "UEFI and VXWorks only support seeding NONE"
81 #endif
82
83 #if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) \
84 || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_VXWORKS) \
85 || defined(OPENSSL_SYS_UEFI))
86
87 # if defined(OPENSSL_SYS_VOS)
88
89 # ifndef OPENSSL_RAND_SEED_OS
90 # error "Unsupported seeding method configured; must be os"
91 # endif
92
93 # if defined(OPENSSL_SYS_VOS_HPPA) && defined(OPENSSL_SYS_VOS_IA32)
94 # error "Unsupported HP-PA and IA32 at the same time."
95 # endif
96 # if !defined(OPENSSL_SYS_VOS_HPPA) && !defined(OPENSSL_SYS_VOS_IA32)
97 # error "Must have one of HP-PA or IA32"
98 # endif
99
100 /*
101 * The following algorithm repeatedly samples the real-time clock (RTC) to
102 * generate a sequence of unpredictable data. The algorithm relies upon the
103 * uneven execution speed of the code (due to factors such as cache misses,
104 * interrupts, bus activity, and scheduling) and upon the rather large
105 * relative difference between the speed of the clock and the rate at which
106 * it can be read. If it is ported to an environment where execution speed
107 * is more constant or where the RTC ticks at a much slower rate, or the
108 * clock can be read with fewer instructions, it is likely that the results
109 * would be far more predictable. This should only be used for legacy
110 * platforms.
111 *
112 * As a precaution, we assume only 2 bits of entropy per byte.
113 */
114 size_t rand_pool_acquire_entropy(RAND_POOL *pool)
115 {
116 short int code;
117 int i, k;
118 size_t bytes_needed;
119 struct timespec ts;
120 unsigned char v;
121 # ifdef OPENSSL_SYS_VOS_HPPA
122 long duration;
123 extern void s$sleep(long *_duration, short int *_code);
124 # else
125 long long duration;
126 extern void s$sleep2(long long *_duration, short int *_code);
127 # endif
128
129 bytes_needed = rand_pool_bytes_needed(pool, 4 /*entropy_factor*/);
130
131 for (i = 0; i < bytes_needed; i++) {
132 /*
133 * burn some cpu; hope for interrupts, cache collisions, bus
134 * interference, etc.
135 */
136 for (k = 0; k < 99; k++)
137 ts.tv_nsec = random();
138
139 # ifdef OPENSSL_SYS_VOS_HPPA
140 /* sleep for 1/1024 of a second (976 us). */
141 duration = 1;
142 s$sleep(&duration, &code);
143 # else
144 /* sleep for 1/65536 of a second (15 us). */
145 duration = 1;
146 s$sleep2(&duration, &code);
147 # endif
148
149 /* Get wall clock time, take 8 bits. */
150 clock_gettime(CLOCK_REALTIME, &ts);
151 v = (unsigned char)(ts.tv_nsec & 0xFF);
152 rand_pool_add(pool, arg, &v, sizeof(v) , 2);
153 }
154 return rand_pool_entropy_available(pool);
155 }
156
157 # else
158
159 # if defined(OPENSSL_RAND_SEED_EGD) && \
160 (defined(OPENSSL_NO_EGD) || !defined(DEVRANDOM_EGD))
161 # error "Seeding uses EGD but EGD is turned off or no device given"
162 # endif
163
164 # if defined(OPENSSL_RAND_SEED_DEVRANDOM) && !defined(DEVRANDOM)
165 # error "Seeding uses urandom but DEVRANDOM is not configured"
166 # endif
167
168 # if defined(OPENSSL_RAND_SEED_OS)
169 # if !defined(DEVRANDOM)
170 # error "OS seeding requires DEVRANDOM to be configured"
171 # endif
172 # define OPENSSL_RAND_SEED_GETRANDOM
173 # define OPENSSL_RAND_SEED_DEVRANDOM
174 # endif
175
176 # if defined(OPENSSL_RAND_SEED_LIBRANDOM)
177 # error "librandom not (yet) supported"
178 # endif
179
180 # if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
181 /*
182 * sysctl_random(): Use sysctl() to read a random number from the kernel
183 * Returns the size on success, 0 on failure.
184 */
185 static size_t sysctl_random(char *buf, size_t buflen)
186 {
187 int mib[2];
188 size_t done = 0;
189 size_t len;
190
191 /*
192 * On FreeBSD old implementations returned longs, newer versions support
193 * variable sizes up to 256 byte. The code below would not work properly
194 * when the sysctl returns long and we want to request something not a
195 * multiple of longs, which should never be the case.
196 */
197 if (!ossl_assert(buflen % sizeof(long) == 0))
198 return 0;
199
200 /*
201 * On NetBSD before 4.0 KERN_ARND was an alias for KERN_URND, and only
202 * filled in an int, leaving the rest uninitialized. Since NetBSD 4.0
203 * it returns a variable number of bytes with the current version supporting
204 * up to 256 bytes.
205 * Just return an error on older NetBSD versions.
206 */
207 #if defined(__NetBSD__) && __NetBSD_Version__ < 400000000
208 return 0;
209 #endif
210
211 mib[0] = CTL_KERN;
212 mib[1] = KERN_ARND;
213
214 do {
215 len = buflen;
216 if (sysctl(mib, 2, buf, &len, NULL, 0) == -1)
217 return done;
218 done += len;
219 buf += len;
220 buflen -= len;
221 } while (buflen > 0);
222
223 return done;
224 }
225 # endif
226
227 /*
228 * syscall_random(): Try to get random data using a system call
229 * returns the number of bytes returned in buf, or <= 0 on error.
230 */
231 int syscall_random(void *buf, size_t buflen)
232 {
233 /*
234 * Do runtime detection to find getentropy().
235 *
236 * Known OSs that should support this:
237 * - Darwin since 16 (OSX 10.12, IOS 10.0).
238 * - Solaris since 11.3
239 * - OpenBSD since 5.6
240 * - Linux since 3.17 with glibc 2.25
241 * - FreeBSD since 12.0 (1200061)
242 */
243 # if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux)
244 extern int getentropy(void *bufer, size_t length) __attribute__((weak));
245
246 if (getentropy != NULL)
247 return getentropy(buf, buflen) == 0 ? buflen : 0;
248 # else
249 union {
250 void *p;
251 int (*f)(void *buffer, size_t length);
252 } p_getentropy;
253
254 /*
255 * We could cache the result of the lookup, but we normally don't
256 * call this function often.
257 */
258 ERR_set_mark();
259 p_getentropy.p = DSO_global_lookup("getentropy");
260 ERR_pop_to_mark();
261 if (p_getentropy.p != NULL)
262 return p_getentropy.f(buf, buflen) == 0 ? buflen : 0;
263 # endif
264
265 /* Linux supports this since version 3.17 */
266 # if defined(__linux) && defined(SYS_getrandom)
267 return (int)syscall(SYS_getrandom, buf, buflen, 0);
268 # endif
269
270 # if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
271 return (int)sysctl_random(buf, buflen);
272 # endif
273
274 return -1;
275 }
276
277 /*
278 * Try the various seeding methods in turn, exit when successful.
279 *
280 * TODO(DRBG): If more than one entropy source is available, is it
281 * preferable to stop as soon as enough entropy has been collected
282 * (as favored by @rsalz) or should one rather be defensive and add
283 * more entropy than requested and/or from different sources?
284 *
285 * Currently, the user can select multiple entropy sources in the
286 * configure step, yet in practice only the first available source
287 * will be used. A more flexible solution has been requested, but
288 * currently it is not clear how this can be achieved without
289 * overengineering the problem. There are many parameters which
290 * could be taken into account when selecting the order and amount
291 * of input from the different entropy sources (trust, quality,
292 * possibility of blocking).
293 */
294 size_t rand_pool_acquire_entropy(RAND_POOL *pool)
295 {
296 # ifdef OPENSSL_RAND_SEED_NONE
297 return rand_pool_entropy_available(pool);
298 # else
299 size_t bytes_needed;
300 size_t entropy_available = 0;
301 unsigned char *buffer;
302
303 # ifdef OPENSSL_RAND_SEED_GETRANDOM
304 bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
305 buffer = rand_pool_add_begin(pool, bytes_needed);
306 if (buffer != NULL) {
307 size_t bytes = 0;
308
309 if (syscall_random(buffer, bytes_needed) == (int)bytes_needed)
310 bytes = bytes_needed;
311
312 rand_pool_add_end(pool, bytes, 8 * bytes);
313 entropy_available = rand_pool_entropy_available(pool);
314 }
315 if (entropy_available > 0)
316 return entropy_available;
317 # endif
318
319 # if defined(OPENSSL_RAND_SEED_LIBRANDOM)
320 {
321 /* Not yet implemented. */
322 }
323 # endif
324
325 # ifdef OPENSSL_RAND_SEED_DEVRANDOM
326 bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
327 if (bytes_needed > 0) {
328 static const char *paths[] = { DEVRANDOM, NULL };
329 FILE *fp;
330 int i;
331
332 for (i = 0; paths[i] != NULL; i++) {
333 if ((fp = fopen(paths[i], "rb")) == NULL)
334 continue;
335 setbuf(fp, NULL);
336 buffer = rand_pool_add_begin(pool, bytes_needed);
337 if (buffer != NULL) {
338 size_t bytes = 0;
339 if (fread(buffer, 1, bytes_needed, fp) == bytes_needed)
340 bytes = bytes_needed;
341
342 rand_pool_add_end(pool, bytes, 8 * bytes);
343 entropy_available = rand_pool_entropy_available(pool);
344 }
345 fclose(fp);
346 if (entropy_available > 0)
347 return entropy_available;
348
349 bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
350 }
351 }
352 # endif
353
354 # ifdef OPENSSL_RAND_SEED_RDTSC
355 entropy_available = rand_acquire_entropy_from_tsc(pool);
356 if (entropy_available > 0)
357 return entropy_available;
358 # endif
359
360 # ifdef OPENSSL_RAND_SEED_RDCPU
361 entropy_available = rand_acquire_entropy_from_cpu(pool);
362 if (entropy_available > 0)
363 return entropy_available;
364 # endif
365
366 # ifdef OPENSSL_RAND_SEED_EGD
367 bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
368 if (bytes_needed > 0) {
369 static const char *paths[] = { DEVRANDOM_EGD, NULL };
370 int i;
371
372 for (i = 0; paths[i] != NULL; i++) {
373 buffer = rand_pool_add_begin(pool, bytes_needed);
374 if (buffer != NULL) {
375 size_t bytes = 0;
376 int num = RAND_query_egd_bytes(paths[i],
377 buffer, (int)bytes_needed);
378 if (num == (int)bytes_needed)
379 bytes = bytes_needed;
380
381 rand_pool_add_end(pool, bytes, 8 * bytes);
382 entropy_available = rand_pool_entropy_available(pool);
383 }
384 if (entropy_available > 0)
385 return entropy_available;
386 }
387 }
388 # endif
389
390 return rand_pool_entropy_available(pool);
391 # endif
392 }
393 # endif
394 #endif
395
396 #if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__)
397 int rand_pool_add_nonce_data(RAND_POOL *pool)
398 {
399 struct {
400 pid_t pid;
401 CRYPTO_THREAD_ID tid;
402 uint64_t time;
403 } data = { 0 };
404
405 /*
406 * Add process id, thread id, and a high resolution timestamp to
407 * ensure that the nonce is unique whith high probability for
408 * different process instances.
409 */
410 data.pid = getpid();
411 data.tid = CRYPTO_THREAD_get_current_id();
412 data.time = get_time_stamp();
413
414 return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
415 }
416
417 int rand_pool_add_additional_data(RAND_POOL *pool)
418 {
419 struct {
420 CRYPTO_THREAD_ID tid;
421 uint64_t time;
422 } data = { 0 };
423
424 /*
425 * Add some noise from the thread id and a high resolution timer.
426 * The thread id adds a little randomness if the drbg is accessed
427 * concurrently (which is the case for the <master> drbg).
428 */
429 data.tid = CRYPTO_THREAD_get_current_id();
430 data.time = get_timer_bits();
431
432 return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
433 }
434
435
436
437 /*
438 * Get the current time with the highest possible resolution
439 *
440 * The time stamp is added to the nonce, so it is optimized for not repeating.
441 * The current time is ideal for this purpose, provided the computer's clock
442 * is synchronized.
443 */
444 static uint64_t get_time_stamp(void)
445 {
446 # if defined(OSSL_POSIX_TIMER_OKAY)
447 {
448 struct timespec ts;
449
450 if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
451 return TWO32TO64(ts.tv_sec, ts.tv_nsec);
452 }
453 # endif
454 # if defined(__unix__) \
455 || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
456 {
457 struct timeval tv;
458
459 if (gettimeofday(&tv, NULL) == 0)
460 return TWO32TO64(tv.tv_sec, tv.tv_usec);
461 }
462 # endif
463 return time(NULL);
464 }
465
466 /*
467 * Get an arbitrary timer value of the highest possible resolution
468 *
469 * The timer value is added as random noise to the additional data,
470 * which is not considered a trusted entropy sourec, so any result
471 * is acceptable.
472 */
473 static uint64_t get_timer_bits(void)
474 {
475 uint64_t res = OPENSSL_rdtsc();
476
477 if (res != 0)
478 return res;
479
480 # if defined(__sun) || defined(__hpux)
481 return gethrtime();
482 # elif defined(_AIX)
483 {
484 timebasestruct_t t;
485
486 read_wall_time(&t, TIMEBASE_SZ);
487 return TWO32TO64(t.tb_high, t.tb_low);
488 }
489 # elif defined(OSSL_POSIX_TIMER_OKAY)
490 {
491 struct timespec ts;
492
493 # ifdef CLOCK_BOOTTIME
494 # define CLOCK_TYPE CLOCK_BOOTTIME
495 # elif defined(_POSIX_MONOTONIC_CLOCK)
496 # define CLOCK_TYPE CLOCK_MONOTONIC
497 # else
498 # define CLOCK_TYPE CLOCK_REALTIME
499 # endif
500
501 if (clock_gettime(CLOCK_TYPE, &ts) == 0)
502 return TWO32TO64(ts.tv_sec, ts.tv_nsec);
503 }
504 # endif
505 # if defined(__unix__) \
506 || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
507 {
508 struct timeval tv;
509
510 if (gettimeofday(&tv, NULL) == 0)
511 return TWO32TO64(tv.tv_sec, tv.tv_usec);
512 }
513 # endif
514 return time(NULL);
515 }
516 #endif /* defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) */