1 /* $OpenBSD: getentropy_linux.c,v 1.20 2014/07/12 15:43:49 beck Exp $ */ 2 3 /* 4 * Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org> 5 * Copyright (c) 2014 Bob Beck <beck@obtuse.com> 6 * 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. 10 * 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. 18 */ 19 #include "config.h" 20 21 /* 22 #define _POSIX_C_SOURCE 199309L 23 #define _GNU_SOURCE 1 24 */ 25 #include <sys/types.h> 26 #include <sys/param.h> 27 #include <sys/ioctl.h> 28 #include <sys/resource.h> 29 #include <sys/syscall.h> 30 #ifdef HAVE_SYS_SYSCTL_H 31 #include <sys/sysctl.h> 32 #endif 33 #include <sys/statvfs.h> 34 #include <sys/socket.h> 35 #include <sys/mount.h> 36 #include <sys/mman.h> 37 #include <sys/stat.h> 38 #include <sys/time.h> 39 #include <stdlib.h> 40 #include <stdint.h> 41 #include <stdio.h> 42 #include <termios.h> 43 #include <fcntl.h> 44 #include <signal.h> 45 #include <string.h> 46 #include <errno.h> 47 #include <unistd.h> 48 #include <time.h> 49 50 #if defined(HAVE_SSL) 51 #include <openssl/sha.h> 52 #elif defined(HAVE_NETTLE) 53 #include <nettle/sha.h> 54 #endif 55 56 #include <linux/types.h> 57 #include <linux/random.h> 58 #include <linux/sysctl.h> 59 #ifdef HAVE_GETAUXVAL 60 #include <sys/auxv.h> 61 #endif 62 #include <sys/vfs.h> 63 #ifndef MAP_ANON 64 #define MAP_ANON MAP_ANONYMOUS 65 #endif 66 67 #define REPEAT 5 68 #define min(a, b) (((a) < (b)) ? (a) : (b)) 69 70 #define HX(a, b) \ 71 do { \ 72 if ((a)) \ 73 HD(errno); \ 74 else \ 75 HD(b); \ 76 } while (0) 77 78 #if defined(HAVE_SSL) 79 #define CRYPTO_SHA512_CTX SHA512_CTX 80 #define CRYPTO_SHA512_INIT(x) SHA512_Init(x) 81 #define CRYPTO_SHA512_FINAL(r, c) SHA512_Final(r, c) 82 #define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l))) 83 #define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x))) 84 #define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*))) 85 #elif defined(HAVE_NETTLE) 86 #define CRYPTO_SHA512_CTX struct sha512_ctx 87 #define CRYPTO_SHA512_INIT(x) sha512_init(x) 88 #define CRYPTO_SHA512_FINAL(r, c) sha512_digest(c, SHA512_DIGEST_SIZE, r) 89 #define HR(x, l) (sha512_update(&ctx, (l), (uint8_t *)(x))) 90 #define HD(x) (sha512_update(&ctx, sizeof (x), (uint8_t *)&(x))) 91 #define HF(x) (sha512_update(&ctx, sizeof (void*), (uint8_t *)&(x))) 92 #endif 93 94 int getentropy(void *buf, size_t len); 95 96 #ifdef CAN_REFERENCE_MAIN 97 extern int main(int, char *argv[]); 98 #endif 99 static int gotdata(char *buf, size_t len); 100 #if defined(SYS_getrandom) && defined(__NR_getrandom) 101 static int getentropy_getrandom(void *buf, size_t len); 102 #endif 103 static int getentropy_urandom(void *buf, size_t len); 104 #ifdef SYS__sysctl 105 static int getentropy_sysctl(void *buf, size_t len); 106 #endif 107 static int getentropy_fallback(void *buf, size_t len); 108 109 int 110 getentropy(void *buf, size_t len) 111 { 112 int ret = -1; 113 114 if (len > 256) { 115 errno = EIO; 116 return -1; 117 } 118 119 #if defined(SYS_getrandom) && defined(__NR_getrandom) 120 /* 121 * Try descriptor-less getrandom() 122 */ 123 ret = getentropy_getrandom(buf, len); 124 if (ret != -1) 125 return (ret); 126 if (errno != ENOSYS) 127 return (-1); 128 #endif 129 130 /* 131 * Try to get entropy with /dev/urandom 132 * 133 * This can fail if the process is inside a chroot or if file 134 * descriptors are exhausted. 135 */ 136 ret = getentropy_urandom(buf, len); 137 if (ret != -1) 138 return (ret); 139 140 #ifdef SYS__sysctl 141 /* 142 * Try to use sysctl CTL_KERN, KERN_RANDOM, RANDOM_UUID. 143 * sysctl is a failsafe API, so it guarantees a result. This 144 * should work inside a chroot, or when file descriptors are 145 * exhausted. 146 * 147 * However this can fail if the Linux kernel removes support 148 * for sysctl. Starting in 2007, there have been efforts to 149 * deprecate the sysctl API/ABI, and push callers towards use 150 * of the chroot-unavailable fd-using /proc mechanism -- 151 * essentially the same problems as /dev/urandom. 152 * 153 * Numerous setbacks have been encountered in their deprecation 154 * schedule, so as of June 2014 the kernel ABI still exists on 155 * most Linux architectures. The sysctl() stub in libc is missing 156 * on some systems. There are also reports that some kernels 157 * spew messages to the console. 158 */ 159 ret = getentropy_sysctl(buf, len); 160 if (ret != -1) 161 return (ret); 162 #endif /* SYS__sysctl */ 163 164 /* 165 * Entropy collection via /dev/urandom and sysctl have failed. 166 * 167 * No other API exists for collecting entropy. See the large 168 * comment block above. 169 * 170 * We have very few options: 171 * - Even syslog_r is unsafe to call at this low level, so 172 * there is no way to alert the user or program. 173 * - Cannot call abort() because some systems have unsafe 174 * corefiles. 175 * - Could raise(SIGKILL) resulting in silent program termination. 176 * - Return EIO, to hint that arc4random's stir function 177 * should raise(SIGKILL) 178 * - Do the best under the circumstances.... 179 * 180 * This code path exists to bring light to the issue that Linux 181 * does not provide a failsafe API for entropy collection. 182 * 183 * We hope this demonstrates that Linux should either retain their 184 * sysctl ABI, or consider providing a new failsafe API which 185 * works in a chroot or when file descriptors are exhausted. 186 */ 187 #undef FAIL_INSTEAD_OF_TRYING_FALLBACK 188 #ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK 189 raise(SIGKILL); 190 #endif 191 ret = getentropy_fallback(buf, len); 192 if (ret != -1) 193 return (ret); 194 195 errno = EIO; 196 return (ret); 197 } 198 199 /* 200 * Basic sanity checking; wish we could do better. 201 */ 202 static int 203 gotdata(char *buf, size_t len) 204 { 205 char any_set = 0; 206 size_t i; 207 208 for (i = 0; i < len; ++i) 209 any_set |= buf[i]; 210 if (any_set == 0) 211 return -1; 212 return 0; 213 } 214 215 #if defined(SYS_getrandom) && defined(__NR_getrandom) 216 static int 217 getentropy_getrandom(void *buf, size_t len) 218 { 219 int pre_errno = errno; 220 int ret; 221 if (len > 256) 222 return (-1); 223 do { 224 ret = syscall(SYS_getrandom, buf, len, 0); 225 } while (ret == -1 && errno == EINTR); 226 227 if (ret != (int)len) 228 return (-1); 229 errno = pre_errno; 230 return (0); 231 } 232 #endif 233 234 static int 235 getentropy_urandom(void *buf, size_t len) 236 { 237 struct stat st; 238 size_t i; 239 int fd, cnt, flags; 240 int save_errno = errno; 241 242 start: 243 244 flags = O_RDONLY; 245 #ifdef O_NOFOLLOW 246 flags |= O_NOFOLLOW; 247 #endif 248 #ifdef O_CLOEXEC 249 flags |= O_CLOEXEC; 250 #endif 251 fd = open("/dev/urandom", flags, 0); 252 if (fd == -1) { 253 if (errno == EINTR) 254 goto start; 255 goto nodevrandom; 256 } 257 #ifndef O_CLOEXEC 258 fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); 259 #endif 260 261 /* Lightly verify that the device node looks sane */ 262 if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) { 263 close(fd); 264 goto nodevrandom; 265 } 266 if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) { 267 close(fd); 268 goto nodevrandom; 269 } 270 for (i = 0; i < len; ) { 271 size_t wanted = len - i; 272 ssize_t ret = read(fd, (char*)buf + i, wanted); 273 274 if (ret == -1) { 275 if (errno == EAGAIN || errno == EINTR) 276 continue; 277 close(fd); 278 goto nodevrandom; 279 } 280 i += ret; 281 } 282 close(fd); 283 if (gotdata(buf, len) == 0) { 284 errno = save_errno; 285 return 0; /* satisfied */ 286 } 287 nodevrandom: 288 errno = EIO; 289 return -1; 290 } 291 292 #ifdef SYS__sysctl 293 static int 294 getentropy_sysctl(void *buf, size_t len) 295 { 296 static int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID }; 297 size_t i; 298 int save_errno = errno; 299 300 for (i = 0; i < len; ) { 301 size_t chunk = min(len - i, 16); 302 303 /* SYS__sysctl because some systems already removed sysctl() */ 304 struct __sysctl_args args = { 305 .name = mib, 306 .nlen = 3, 307 .oldval = (char *)buf + i, 308 .oldlenp = &chunk, 309 }; 310 if (syscall(SYS__sysctl, &args) != 0) 311 goto sysctlfailed; 312 i += chunk; 313 } 314 if (gotdata(buf, len) == 0) { 315 errno = save_errno; 316 return (0); /* satisfied */ 317 } 318 sysctlfailed: 319 errno = EIO; 320 return -1; 321 } 322 #endif /* SYS__sysctl */ 323 324 static int cl[] = { 325 CLOCK_REALTIME, 326 #ifdef CLOCK_MONOTONIC 327 CLOCK_MONOTONIC, 328 #endif 329 #ifdef CLOCK_MONOTONIC_RAW 330 CLOCK_MONOTONIC_RAW, 331 #endif 332 #ifdef CLOCK_TAI 333 CLOCK_TAI, 334 #endif 335 #ifdef CLOCK_VIRTUAL 336 CLOCK_VIRTUAL, 337 #endif 338 #ifdef CLOCK_UPTIME 339 CLOCK_UPTIME, 340 #endif 341 #ifdef CLOCK_PROCESS_CPUTIME_ID 342 CLOCK_PROCESS_CPUTIME_ID, 343 #endif 344 #ifdef CLOCK_THREAD_CPUTIME_ID 345 CLOCK_THREAD_CPUTIME_ID, 346 #endif 347 }; 348 349 static int 350 getentropy_fallback(void *buf, size_t len) 351 { 352 uint8_t results[SHA512_DIGEST_LENGTH]; 353 int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat; 354 static int cnt; 355 struct timespec ts; 356 struct timeval tv; 357 struct rusage ru; 358 sigset_t sigset; 359 struct stat st; 360 CRYPTO_SHA512_CTX ctx; 361 static pid_t lastpid; 362 pid_t pid; 363 size_t i, ii, m; 364 char *p; 365 366 pid = getpid(); 367 if (lastpid == pid) { 368 faster = 1; 369 repeat = 2; 370 } else { 371 faster = 0; 372 lastpid = pid; 373 repeat = REPEAT; 374 } 375 for (i = 0; i < len; ) { 376 int j; 377 CRYPTO_SHA512_INIT(&ctx); 378 for (j = 0; j < repeat; j++) { 379 HX((e = gettimeofday(&tv, NULL)) == -1, tv); 380 if (e != -1) { 381 cnt += (int)tv.tv_sec; 382 cnt += (int)tv.tv_usec; 383 } 384 385 for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++) 386 HX(clock_gettime(cl[ii], &ts) == -1, ts); 387 388 HX((pid = getpid()) == -1, pid); 389 HX((pid = getsid(pid)) == -1, pid); 390 HX((pid = getppid()) == -1, pid); 391 HX((pid = getpgid(0)) == -1, pid); 392 HX((e = getpriority(0, 0)) == -1, e); 393 394 if (!faster) { 395 ts.tv_sec = 0; 396 ts.tv_nsec = 1; 397 (void) nanosleep(&ts, NULL); 398 } 399 400 HX(sigpending(&sigset) == -1, sigset); 401 HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1, 402 sigset); 403 404 #ifdef CAN_REFERENCE_MAIN 405 HF(main); /* an addr in program */ 406 #endif 407 HF(getentropy); /* an addr in this library */ 408 HF(printf); /* an addr in libc */ 409 p = (char *)&p; 410 HD(p); /* an addr on stack */ 411 p = (char *)&errno; 412 HD(p); /* the addr of errno */ 413 414 if (i == 0) { 415 struct sockaddr_storage ss; 416 struct statvfs stvfs; 417 struct termios tios; 418 struct statfs stfs; 419 socklen_t ssl; 420 off_t off; 421 422 /* 423 * Prime-sized mappings encourage fragmentation; 424 * thus exposing some address entropy. 425 */ 426 struct mm { 427 size_t npg; 428 void *p; 429 } mm[] = { 430 { 17, MAP_FAILED }, { 3, MAP_FAILED }, 431 { 11, MAP_FAILED }, { 2, MAP_FAILED }, 432 { 5, MAP_FAILED }, { 3, MAP_FAILED }, 433 { 7, MAP_FAILED }, { 1, MAP_FAILED }, 434 { 57, MAP_FAILED }, { 3, MAP_FAILED }, 435 { 131, MAP_FAILED }, { 1, MAP_FAILED }, 436 }; 437 438 for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) { 439 HX(mm[m].p = mmap(NULL, 440 mm[m].npg * pgs, 441 PROT_READ|PROT_WRITE, 442 MAP_PRIVATE|MAP_ANON, -1, 443 (off_t)0), mm[m].p); 444 if (mm[m].p != MAP_FAILED) { 445 size_t mo; 446 447 /* Touch some memory... */ 448 p = mm[m].p; 449 mo = cnt % 450 (mm[m].npg * pgs - 1); 451 p[mo] = 1; 452 cnt += (int)((long)(mm[m].p) 453 / pgs); 454 } 455 456 /* Check cnts and times... */ 457 for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); 458 ii++) { 459 HX((e = clock_gettime(cl[ii], 460 &ts)) == -1, ts); 461 if (e != -1) 462 cnt += (int)ts.tv_nsec; 463 } 464 465 HX((e = getrusage(RUSAGE_SELF, 466 &ru)) == -1, ru); 467 if (e != -1) { 468 cnt += (int)ru.ru_utime.tv_sec; 469 cnt += (int)ru.ru_utime.tv_usec; 470 } 471 } 472 473 for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) { 474 if (mm[m].p != MAP_FAILED) 475 munmap(mm[m].p, mm[m].npg * pgs); 476 mm[m].p = MAP_FAILED; 477 } 478 479 HX(stat(".", &st) == -1, st); 480 HX(statvfs(".", &stvfs) == -1, stvfs); 481 HX(statfs(".", &stfs) == -1, stfs); 482 483 HX(stat("/", &st) == -1, st); 484 HX(statvfs("/", &stvfs) == -1, stvfs); 485 HX(statfs("/", &stfs) == -1, stfs); 486 487 HX((e = fstat(0, &st)) == -1, st); 488 if (e == -1) { 489 if (S_ISREG(st.st_mode) || 490 S_ISFIFO(st.st_mode) || 491 S_ISSOCK(st.st_mode)) { 492 HX(fstatvfs(0, &stvfs) == -1, 493 stvfs); 494 HX(fstatfs(0, &stfs) == -1, 495 stfs); 496 HX((off = lseek(0, (off_t)0, 497 SEEK_CUR)) < 0, off); 498 } 499 if (S_ISCHR(st.st_mode)) { 500 HX(tcgetattr(0, &tios) == -1, 501 tios); 502 } else if (S_ISSOCK(st.st_mode)) { 503 memset(&ss, 0, sizeof ss); 504 ssl = sizeof(ss); 505 HX(getpeername(0, 506 (void *)&ss, &ssl) == -1, 507 ss); 508 } 509 } 510 511 HX((e = getrusage(RUSAGE_CHILDREN, 512 &ru)) == -1, ru); 513 if (e != -1) { 514 cnt += (int)ru.ru_utime.tv_sec; 515 cnt += (int)ru.ru_utime.tv_usec; 516 } 517 } else { 518 /* Subsequent hashes absorb previous result */ 519 HD(results); 520 } 521 522 HX((e = gettimeofday(&tv, NULL)) == -1, tv); 523 if (e != -1) { 524 cnt += (int)tv.tv_sec; 525 cnt += (int)tv.tv_usec; 526 } 527 528 HD(cnt); 529 } 530 #ifdef HAVE_GETAUXVAL 531 # ifdef AT_RANDOM 532 /* Not as random as you think but we take what we are given */ 533 p = (char *) getauxval(AT_RANDOM); 534 if (p) 535 HR(p, 16); 536 # endif 537 # ifdef AT_SYSINFO_EHDR 538 p = (char *) getauxval(AT_SYSINFO_EHDR); 539 if (p) 540 HR(p, pgs); 541 # endif 542 # ifdef AT_BASE 543 p = (char *) getauxval(AT_BASE); 544 if (p) 545 HD(p); 546 # endif 547 #endif /* HAVE_GETAUXVAL */ 548 549 CRYPTO_SHA512_FINAL(results, &ctx); 550 memcpy((char*)buf + i, results, min(sizeof(results), len - i)); 551 i += min(sizeof(results), len - i); 552 } 553 memset(results, 0, sizeof results); 554 if (gotdata(buf, len) == 0) { 555 errno = save_errno; 556 return 0; /* satisfied */ 557 } 558 errno = EIO; 559 return -1; 560 } 561