1 /* $OpenBSD: getentropy_linux.c,v 1.46 2018/11/20 08:04:28 deraadt Exp $ */
4 * Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
5 * Copyright (c) 2014 Bob Beck <beck@obtuse.com>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 * Emulation of getentropy(2) as documented at:
20 * http://man.openbsd.org/getentropy.2
25 #define _POSIX_C_SOURCE 199309L
28 #include <sys/types.h>
29 #include <sys/param.h>
30 #include <sys/ioctl.h>
31 #include <sys/resource.h>
32 #include <sys/syscall.h>
34 #include <linux/sysctl.h>
36 #include <sys/statvfs.h>
37 #include <sys/socket.h>
38 #include <sys/mount.h>
54 #include <openssl/sha.h>
56 #include <nettle/sha.h>
57 #define SHA512_CTX struct sha512_ctx
58 #define SHA512_Init(x) sha512_init(x)
59 #define SHA512_Update(x, b, s) sha512_update(x, s, b)
60 #define SHA512_Final(r, c) sha512_digest(c, SHA512_DIGEST_SIZE, r)
63 #include <linux/types.h>
64 #include <linux/random.h>
70 #define MAP_ANON MAP_ANONYMOUS
74 #define min(a, b) (((a) < (b)) ? (a) : (b))
84 #define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
85 #define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
86 #define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
88 int getentropy(void *buf, size_t len);
90 #if defined(SYS_getrandom) && defined(GRND_NONBLOCK)
91 static int getentropy_getrandom(void *buf, size_t len);
93 static int getentropy_urandom(void *buf, size_t len);
95 static int getentropy_sysctl(void *buf, size_t len);
97 static int getentropy_fallback(void *buf, size_t len);
98 static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
101 getentropy(void *buf, size_t len)
110 #if defined(SYS_getrandom) && defined(GRND_NONBLOCK)
112 * Try descriptor-less getrandom(), in non-blocking mode.
114 * The design of Linux getrandom is broken. It has an
115 * uninitialized phase coupled with blocking behaviour, which
116 * is unacceptable from within a library at boot time without
117 * possible recovery. See http://bugs.python.org/issue26839#msg267745
119 ret = getentropy_getrandom(buf, len);
125 * Try to get entropy with /dev/urandom
127 * This can fail if the process is inside a chroot or if file
128 * descriptors are exhausted.
130 ret = getentropy_urandom(buf, len);
136 * Try to use sysctl CTL_KERN, KERN_RANDOM, RANDOM_UUID.
137 * sysctl is a failsafe API, so it guarantees a result. This
138 * should work inside a chroot, or when file descriptors are
141 * However this can fail if the Linux kernel removes support
142 * for sysctl. Starting in 2007, there have been efforts to
143 * deprecate the sysctl API/ABI, and push callers towards use
144 * of the chroot-unavailable fd-using /proc mechanism --
145 * essentially the same problems as /dev/urandom.
147 * Numerous setbacks have been encountered in their deprecation
148 * schedule, so as of June 2014 the kernel ABI still exists on
149 * most Linux architectures. The sysctl() stub in libc is missing
150 * on some systems. There are also reports that some kernels
151 * spew messages to the console.
153 ret = getentropy_sysctl(buf, len);
156 #endif /* SYS__sysctl */
159 * Entropy collection via /dev/urandom and sysctl have failed.
161 * No other API exists for collecting entropy. See the large
162 * comment block above.
164 * We have very few options:
165 * - Even syslog_r is unsafe to call at this low level, so
166 * there is no way to alert the user or program.
167 * - Cannot call abort() because some systems have unsafe
169 * - Could raise(SIGKILL) resulting in silent program termination.
170 * - Return EIO, to hint that arc4random's stir function
171 * should raise(SIGKILL)
172 * - Do the best under the circumstances....
174 * This code path exists to bring light to the issue that Linux
175 * still does not provide a failsafe API for entropy collection.
177 * We hope this demonstrates that Linux should either retain their
178 * sysctl ABI, or consider providing a new failsafe API which
179 * works in a chroot or when file descriptors are exhausted.
181 #undef FAIL_INSTEAD_OF_TRYING_FALLBACK
182 #ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
185 ret = getentropy_fallback(buf, len);
193 #if defined(SYS_getrandom) && defined(GRND_NONBLOCK)
195 getentropy_getrandom(void *buf, size_t len)
197 int pre_errno = errno;
202 ret = syscall(SYS_getrandom, buf, len, GRND_NONBLOCK);
203 } while (ret == -1 && errno == EINTR);
213 getentropy_urandom(void *buf, size_t len)
218 int save_errno = errno;
229 fd = open("/dev/urandom", flags, 0);
236 fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
239 /* Lightly verify that the device node looks sane */
240 if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
244 if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) {
248 for (i = 0; i < len; ) {
249 size_t wanted = len - i;
250 ssize_t ret = read(fd, (char *)buf + i, wanted);
253 if (errno == EAGAIN || errno == EINTR)
262 return (0); /* satisfied */
270 getentropy_sysctl(void *buf, size_t len)
272 static int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID };
274 int save_errno = errno;
276 for (i = 0; i < len; ) {
277 size_t chunk = min(len - i, 16);
279 /* SYS__sysctl because some systems already removed sysctl() */
280 struct __sysctl_args args = {
283 .oldval = (char *)buf + i,
286 if (syscall(SYS__sysctl, &args) != 0)
291 return (0); /* satisfied */
296 #endif /* SYS__sysctl */
298 static const int cl[] = {
300 #ifdef CLOCK_MONOTONIC
303 #ifdef CLOCK_MONOTONIC_RAW
315 #ifdef CLOCK_PROCESS_CPUTIME_ID
316 CLOCK_PROCESS_CPUTIME_ID,
318 #ifdef CLOCK_THREAD_CPUTIME_ID
319 CLOCK_THREAD_CPUTIME_ID,
324 getentropy_phdr(struct dl_phdr_info *info, size_t ATTR_UNUSED(size), void *data)
326 SHA512_CTX *ctx = data;
328 SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr));
333 getentropy_fallback(void *buf, size_t len)
335 uint8_t results[SHA512_DIGEST_LENGTH];
336 int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
344 static pid_t lastpid;
350 if (lastpid == pid) {
358 for (i = 0; i < len; ) {
361 for (j = 0; j < repeat; j++) {
362 HX((e = gettimeofday(&tv, NULL)) == -1, tv);
364 cnt += (int)tv.tv_sec;
365 cnt += (int)tv.tv_usec;
368 dl_iterate_phdr(getentropy_phdr, &ctx);
370 for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
371 HX(clock_gettime(cl[ii], &ts) == -1, ts);
373 HX((pid = getpid()) == -1, pid);
374 HX((pid = getsid(pid)) == -1, pid);
375 HX((pid = getppid()) == -1, pid);
376 HX((pid = getpgid(0)) == -1, pid);
377 HX((e = getpriority(0, 0)) == -1, e);
382 (void) nanosleep(&ts, NULL);
385 HX(sigpending(&sigset) == -1, sigset);
386 HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
389 HF(getentropy); /* an addr in this library */
390 HF(printf); /* an addr in libc */
392 HD(p); /* an addr on stack */
394 HD(p); /* the addr of errno */
397 struct sockaddr_storage ss;
398 struct statvfs stvfs;
405 * Prime-sized mappings encourage fragmentation;
406 * thus exposing some address entropy.
412 { 17, MAP_FAILED }, { 3, MAP_FAILED },
413 { 11, MAP_FAILED }, { 2, MAP_FAILED },
414 { 5, MAP_FAILED }, { 3, MAP_FAILED },
415 { 7, MAP_FAILED }, { 1, MAP_FAILED },
416 { 57, MAP_FAILED }, { 3, MAP_FAILED },
417 { 131, MAP_FAILED }, { 1, MAP_FAILED },
420 for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
421 HX(mm[m].p = mmap(NULL,
423 PROT_READ|PROT_WRITE,
424 MAP_PRIVATE|MAP_ANON, -1,
426 if (mm[m].p != MAP_FAILED) {
429 /* Touch some memory... */
432 (mm[m].npg * pgs - 1);
434 cnt += (int)((long)(mm[m].p)
438 /* Check cnts and times... */
439 for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
441 HX((e = clock_gettime(cl[ii],
444 cnt += (int)ts.tv_nsec;
447 HX((e = getrusage(RUSAGE_SELF,
450 cnt += (int)ru.ru_utime.tv_sec;
451 cnt += (int)ru.ru_utime.tv_usec;
455 for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
456 if (mm[m].p != MAP_FAILED)
457 munmap(mm[m].p, mm[m].npg * pgs);
458 mm[m].p = MAP_FAILED;
461 HX(stat(".", &st) == -1, st);
462 HX(statvfs(".", &stvfs) == -1, stvfs);
463 HX(statfs(".", &stfs) == -1, stfs);
465 HX(stat("/", &st) == -1, st);
466 HX(statvfs("/", &stvfs) == -1, stvfs);
467 HX(statfs("/", &stfs) == -1, stfs);
469 HX((e = fstat(0, &st)) == -1, st);
471 if (S_ISREG(st.st_mode) ||
472 S_ISFIFO(st.st_mode) ||
473 S_ISSOCK(st.st_mode)) {
474 HX(fstatvfs(0, &stvfs) == -1,
476 HX(fstatfs(0, &stfs) == -1,
478 HX((off = lseek(0, (off_t)0,
479 SEEK_CUR)) < 0, off);
481 if (S_ISCHR(st.st_mode)) {
482 HX(tcgetattr(0, &tios) == -1,
484 } else if (S_ISSOCK(st.st_mode)) {
485 memset(&ss, 0, sizeof ss);
488 (void *)&ss, &ssl) == -1,
493 HX((e = getrusage(RUSAGE_CHILDREN,
496 cnt += (int)ru.ru_utime.tv_sec;
497 cnt += (int)ru.ru_utime.tv_usec;
500 /* Subsequent hashes absorb previous result */
504 HX((e = gettimeofday(&tv, NULL)) == -1, tv);
506 cnt += (int)tv.tv_sec;
507 cnt += (int)tv.tv_usec;
512 #ifdef HAVE_GETAUXVAL
514 /* Not as random as you think but we take what we are given */
515 p = (char *) getauxval(AT_RANDOM);
519 #ifdef AT_SYSINFO_EHDR
520 p = (char *) getauxval(AT_SYSINFO_EHDR);
525 p = (char *) getauxval(AT_BASE);
531 SHA512_Final(results, &ctx);
532 memcpy((char *)buf + i, results, min(sizeof(results), len - i));
533 i += min(sizeof(results), len - i);
535 explicit_bzero(&ctx, sizeof ctx);
536 explicit_bzero(results, sizeof results);
538 return (0); /* satisfied */