1*ff825849SDag-Erling Smørgrav /* $OpenBSD: getentropy_osx.c,v 1.3 2014/07/12 14:48:00 deraadt Exp $ */ 2*ff825849SDag-Erling Smørgrav 3*ff825849SDag-Erling Smørgrav /* 4*ff825849SDag-Erling Smørgrav * Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org> 5*ff825849SDag-Erling Smørgrav * Copyright (c) 2014 Bob Beck <beck@obtuse.com> 6*ff825849SDag-Erling Smørgrav * 7*ff825849SDag-Erling Smørgrav * Permission to use, copy, modify, and distribute this software for any 8*ff825849SDag-Erling Smørgrav * purpose with or without fee is hereby granted, provided that the above 9*ff825849SDag-Erling Smørgrav * copyright notice and this permission notice appear in all copies. 10*ff825849SDag-Erling Smørgrav * 11*ff825849SDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12*ff825849SDag-Erling Smørgrav * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13*ff825849SDag-Erling Smørgrav * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14*ff825849SDag-Erling Smørgrav * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15*ff825849SDag-Erling Smørgrav * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16*ff825849SDag-Erling Smørgrav * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17*ff825849SDag-Erling Smørgrav * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18*ff825849SDag-Erling Smørgrav */ 19*ff825849SDag-Erling Smørgrav #include "config.h" 20*ff825849SDag-Erling Smørgrav 21*ff825849SDag-Erling Smørgrav #include <sys/types.h> 22*ff825849SDag-Erling Smørgrav #include <sys/param.h> 23*ff825849SDag-Erling Smørgrav #include <sys/ioctl.h> 24*ff825849SDag-Erling Smørgrav #include <sys/resource.h> 25*ff825849SDag-Erling Smørgrav #include <sys/syscall.h> 26*ff825849SDag-Erling Smørgrav #include <sys/sysctl.h> 27*ff825849SDag-Erling Smørgrav #include <sys/statvfs.h> 28*ff825849SDag-Erling Smørgrav #include <sys/socket.h> 29*ff825849SDag-Erling Smørgrav #include <sys/mount.h> 30*ff825849SDag-Erling Smørgrav #include <sys/mman.h> 31*ff825849SDag-Erling Smørgrav #include <sys/stat.h> 32*ff825849SDag-Erling Smørgrav #include <sys/time.h> 33*ff825849SDag-Erling Smørgrav #include <stdlib.h> 34*ff825849SDag-Erling Smørgrav #include <stdint.h> 35*ff825849SDag-Erling Smørgrav #include <stdio.h> 36*ff825849SDag-Erling Smørgrav #include <termios.h> 37*ff825849SDag-Erling Smørgrav #include <fcntl.h> 38*ff825849SDag-Erling Smørgrav #include <signal.h> 39*ff825849SDag-Erling Smørgrav #include <string.h> 40*ff825849SDag-Erling Smørgrav #include <errno.h> 41*ff825849SDag-Erling Smørgrav #include <unistd.h> 42*ff825849SDag-Erling Smørgrav #include <time.h> 43*ff825849SDag-Erling Smørgrav #include <mach/mach_time.h> 44*ff825849SDag-Erling Smørgrav #include <mach/mach_host.h> 45*ff825849SDag-Erling Smørgrav #include <mach/host_info.h> 46*ff825849SDag-Erling Smørgrav #include <sys/socketvar.h> 47*ff825849SDag-Erling Smørgrav #include <sys/vmmeter.h> 48*ff825849SDag-Erling Smørgrav #include <netinet/in.h> 49*ff825849SDag-Erling Smørgrav #include <netinet/tcp.h> 50*ff825849SDag-Erling Smørgrav #include <netinet/udp.h> 51*ff825849SDag-Erling Smørgrav #include <netinet/ip_var.h> 52*ff825849SDag-Erling Smørgrav #include <netinet/tcp_var.h> 53*ff825849SDag-Erling Smørgrav #include <netinet/udp_var.h> 54*ff825849SDag-Erling Smørgrav #include <CommonCrypto/CommonDigest.h> 55*ff825849SDag-Erling Smørgrav #define SHA512_Update(a, b, c) (CC_SHA512_Update((a), (b), (c))) 56*ff825849SDag-Erling Smørgrav #define SHA512_Init(xxx) (CC_SHA512_Init((xxx))) 57*ff825849SDag-Erling Smørgrav #define SHA512_Final(xxx, yyy) (CC_SHA512_Final((xxx), (yyy))) 58*ff825849SDag-Erling Smørgrav #define SHA512_CTX CC_SHA512_CTX 59*ff825849SDag-Erling Smørgrav #define SHA512_DIGEST_LENGTH CC_SHA512_DIGEST_LENGTH 60*ff825849SDag-Erling Smørgrav 61*ff825849SDag-Erling Smørgrav #define REPEAT 5 62*ff825849SDag-Erling Smørgrav #define min(a, b) (((a) < (b)) ? (a) : (b)) 63*ff825849SDag-Erling Smørgrav 64*ff825849SDag-Erling Smørgrav #define HX(a, b) \ 65*ff825849SDag-Erling Smørgrav do { \ 66*ff825849SDag-Erling Smørgrav if ((a)) \ 67*ff825849SDag-Erling Smørgrav HD(errno); \ 68*ff825849SDag-Erling Smørgrav else \ 69*ff825849SDag-Erling Smørgrav HD(b); \ 70*ff825849SDag-Erling Smørgrav } while (0) 71*ff825849SDag-Erling Smørgrav 72*ff825849SDag-Erling Smørgrav #define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l))) 73*ff825849SDag-Erling Smørgrav #define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x))) 74*ff825849SDag-Erling Smørgrav #define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*))) 75*ff825849SDag-Erling Smørgrav 76*ff825849SDag-Erling Smørgrav int getentropy(void *buf, size_t len); 77*ff825849SDag-Erling Smørgrav 78*ff825849SDag-Erling Smørgrav #ifdef CAN_REFERENCE_MAIN 79*ff825849SDag-Erling Smørgrav extern int main(int, char *argv[]); 80*ff825849SDag-Erling Smørgrav #endif 81*ff825849SDag-Erling Smørgrav static int gotdata(char *buf, size_t len); 82*ff825849SDag-Erling Smørgrav static int getentropy_urandom(void *buf, size_t len); 83*ff825849SDag-Erling Smørgrav static int getentropy_fallback(void *buf, size_t len); 84*ff825849SDag-Erling Smørgrav 85*ff825849SDag-Erling Smørgrav int 86*ff825849SDag-Erling Smørgrav getentropy(void *buf, size_t len) 87*ff825849SDag-Erling Smørgrav { 88*ff825849SDag-Erling Smørgrav int ret = -1; 89*ff825849SDag-Erling Smørgrav 90*ff825849SDag-Erling Smørgrav if (len > 256) { 91*ff825849SDag-Erling Smørgrav errno = EIO; 92*ff825849SDag-Erling Smørgrav return -1; 93*ff825849SDag-Erling Smørgrav } 94*ff825849SDag-Erling Smørgrav 95*ff825849SDag-Erling Smørgrav /* 96*ff825849SDag-Erling Smørgrav * Try to get entropy with /dev/urandom 97*ff825849SDag-Erling Smørgrav * 98*ff825849SDag-Erling Smørgrav * This can fail if the process is inside a chroot or if file 99*ff825849SDag-Erling Smørgrav * descriptors are exhausted. 100*ff825849SDag-Erling Smørgrav */ 101*ff825849SDag-Erling Smørgrav ret = getentropy_urandom(buf, len); 102*ff825849SDag-Erling Smørgrav if (ret != -1) 103*ff825849SDag-Erling Smørgrav return (ret); 104*ff825849SDag-Erling Smørgrav 105*ff825849SDag-Erling Smørgrav /* 106*ff825849SDag-Erling Smørgrav * Entropy collection via /dev/urandom and sysctl have failed. 107*ff825849SDag-Erling Smørgrav * 108*ff825849SDag-Erling Smørgrav * No other API exists for collecting entropy, and we have 109*ff825849SDag-Erling Smørgrav * no failsafe way to get it on OSX that is not sensitive 110*ff825849SDag-Erling Smørgrav * to resource exhaustion. 111*ff825849SDag-Erling Smørgrav * 112*ff825849SDag-Erling Smørgrav * We have very few options: 113*ff825849SDag-Erling Smørgrav * - Even syslog_r is unsafe to call at this low level, so 114*ff825849SDag-Erling Smørgrav * there is no way to alert the user or program. 115*ff825849SDag-Erling Smørgrav * - Cannot call abort() because some systems have unsafe 116*ff825849SDag-Erling Smørgrav * corefiles. 117*ff825849SDag-Erling Smørgrav * - Could raise(SIGKILL) resulting in silent program termination. 118*ff825849SDag-Erling Smørgrav * - Return EIO, to hint that arc4random's stir function 119*ff825849SDag-Erling Smørgrav * should raise(SIGKILL) 120*ff825849SDag-Erling Smørgrav * - Do the best under the circumstances.... 121*ff825849SDag-Erling Smørgrav * 122*ff825849SDag-Erling Smørgrav * This code path exists to bring light to the issue that OSX 123*ff825849SDag-Erling Smørgrav * does not provide a failsafe API for entropy collection. 124*ff825849SDag-Erling Smørgrav * 125*ff825849SDag-Erling Smørgrav * We hope this demonstrates that OSX should consider 126*ff825849SDag-Erling Smørgrav * providing a new failsafe API which works in a chroot or 127*ff825849SDag-Erling Smørgrav * when file descriptors are exhausted. 128*ff825849SDag-Erling Smørgrav */ 129*ff825849SDag-Erling Smørgrav #undef FAIL_INSTEAD_OF_TRYING_FALLBACK 130*ff825849SDag-Erling Smørgrav #ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK 131*ff825849SDag-Erling Smørgrav raise(SIGKILL); 132*ff825849SDag-Erling Smørgrav #endif 133*ff825849SDag-Erling Smørgrav ret = getentropy_fallback(buf, len); 134*ff825849SDag-Erling Smørgrav if (ret != -1) 135*ff825849SDag-Erling Smørgrav return (ret); 136*ff825849SDag-Erling Smørgrav 137*ff825849SDag-Erling Smørgrav errno = EIO; 138*ff825849SDag-Erling Smørgrav return (ret); 139*ff825849SDag-Erling Smørgrav } 140*ff825849SDag-Erling Smørgrav 141*ff825849SDag-Erling Smørgrav /* 142*ff825849SDag-Erling Smørgrav * Basic sanity checking; wish we could do better. 143*ff825849SDag-Erling Smørgrav */ 144*ff825849SDag-Erling Smørgrav static int 145*ff825849SDag-Erling Smørgrav gotdata(char *buf, size_t len) 146*ff825849SDag-Erling Smørgrav { 147*ff825849SDag-Erling Smørgrav char any_set = 0; 148*ff825849SDag-Erling Smørgrav size_t i; 149*ff825849SDag-Erling Smørgrav 150*ff825849SDag-Erling Smørgrav for (i = 0; i < len; ++i) 151*ff825849SDag-Erling Smørgrav any_set |= buf[i]; 152*ff825849SDag-Erling Smørgrav if (any_set == 0) 153*ff825849SDag-Erling Smørgrav return -1; 154*ff825849SDag-Erling Smørgrav return 0; 155*ff825849SDag-Erling Smørgrav } 156*ff825849SDag-Erling Smørgrav 157*ff825849SDag-Erling Smørgrav static int 158*ff825849SDag-Erling Smørgrav getentropy_urandom(void *buf, size_t len) 159*ff825849SDag-Erling Smørgrav { 160*ff825849SDag-Erling Smørgrav struct stat st; 161*ff825849SDag-Erling Smørgrav size_t i; 162*ff825849SDag-Erling Smørgrav int fd, flags; 163*ff825849SDag-Erling Smørgrav int save_errno = errno; 164*ff825849SDag-Erling Smørgrav 165*ff825849SDag-Erling Smørgrav start: 166*ff825849SDag-Erling Smørgrav 167*ff825849SDag-Erling Smørgrav flags = O_RDONLY; 168*ff825849SDag-Erling Smørgrav #ifdef O_NOFOLLOW 169*ff825849SDag-Erling Smørgrav flags |= O_NOFOLLOW; 170*ff825849SDag-Erling Smørgrav #endif 171*ff825849SDag-Erling Smørgrav #ifdef O_CLOEXEC 172*ff825849SDag-Erling Smørgrav flags |= O_CLOEXEC; 173*ff825849SDag-Erling Smørgrav #endif 174*ff825849SDag-Erling Smørgrav fd = open("/dev/urandom", flags, 0); 175*ff825849SDag-Erling Smørgrav if (fd == -1) { 176*ff825849SDag-Erling Smørgrav if (errno == EINTR) 177*ff825849SDag-Erling Smørgrav goto start; 178*ff825849SDag-Erling Smørgrav goto nodevrandom; 179*ff825849SDag-Erling Smørgrav } 180*ff825849SDag-Erling Smørgrav #ifndef O_CLOEXEC 181*ff825849SDag-Erling Smørgrav fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); 182*ff825849SDag-Erling Smørgrav #endif 183*ff825849SDag-Erling Smørgrav 184*ff825849SDag-Erling Smørgrav /* Lightly verify that the device node looks sane */ 185*ff825849SDag-Erling Smørgrav if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) { 186*ff825849SDag-Erling Smørgrav close(fd); 187*ff825849SDag-Erling Smørgrav goto nodevrandom; 188*ff825849SDag-Erling Smørgrav } 189*ff825849SDag-Erling Smørgrav for (i = 0; i < len; ) { 190*ff825849SDag-Erling Smørgrav size_t wanted = len - i; 191*ff825849SDag-Erling Smørgrav ssize_t ret = read(fd, (char*)buf + i, wanted); 192*ff825849SDag-Erling Smørgrav 193*ff825849SDag-Erling Smørgrav if (ret == -1) { 194*ff825849SDag-Erling Smørgrav if (errno == EAGAIN || errno == EINTR) 195*ff825849SDag-Erling Smørgrav continue; 196*ff825849SDag-Erling Smørgrav close(fd); 197*ff825849SDag-Erling Smørgrav goto nodevrandom; 198*ff825849SDag-Erling Smørgrav } 199*ff825849SDag-Erling Smørgrav i += ret; 200*ff825849SDag-Erling Smørgrav } 201*ff825849SDag-Erling Smørgrav close(fd); 202*ff825849SDag-Erling Smørgrav if (gotdata(buf, len) == 0) { 203*ff825849SDag-Erling Smørgrav errno = save_errno; 204*ff825849SDag-Erling Smørgrav return 0; /* satisfied */ 205*ff825849SDag-Erling Smørgrav } 206*ff825849SDag-Erling Smørgrav nodevrandom: 207*ff825849SDag-Erling Smørgrav errno = EIO; 208*ff825849SDag-Erling Smørgrav return -1; 209*ff825849SDag-Erling Smørgrav } 210*ff825849SDag-Erling Smørgrav 211*ff825849SDag-Erling Smørgrav static int tcpmib[] = { CTL_NET, AF_INET, IPPROTO_TCP, TCPCTL_STATS }; 212*ff825849SDag-Erling Smørgrav static int udpmib[] = { CTL_NET, AF_INET, IPPROTO_UDP, UDPCTL_STATS }; 213*ff825849SDag-Erling Smørgrav static int ipmib[] = { CTL_NET, AF_INET, IPPROTO_IP, IPCTL_STATS }; 214*ff825849SDag-Erling Smørgrav static int kmib[] = { CTL_KERN, KERN_USRSTACK }; 215*ff825849SDag-Erling Smørgrav static int hwmib[] = { CTL_HW, HW_USERMEM }; 216*ff825849SDag-Erling Smørgrav 217*ff825849SDag-Erling Smørgrav static int 218*ff825849SDag-Erling Smørgrav getentropy_fallback(void *buf, size_t len) 219*ff825849SDag-Erling Smørgrav { 220*ff825849SDag-Erling Smørgrav uint8_t results[SHA512_DIGEST_LENGTH]; 221*ff825849SDag-Erling Smørgrav int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat; 222*ff825849SDag-Erling Smørgrav static int cnt; 223*ff825849SDag-Erling Smørgrav struct timespec ts; 224*ff825849SDag-Erling Smørgrav struct timeval tv; 225*ff825849SDag-Erling Smørgrav struct rusage ru; 226*ff825849SDag-Erling Smørgrav sigset_t sigset; 227*ff825849SDag-Erling Smørgrav struct stat st; 228*ff825849SDag-Erling Smørgrav SHA512_CTX ctx; 229*ff825849SDag-Erling Smørgrav static pid_t lastpid; 230*ff825849SDag-Erling Smørgrav pid_t pid; 231*ff825849SDag-Erling Smørgrav size_t i, ii, m; 232*ff825849SDag-Erling Smørgrav char *p; 233*ff825849SDag-Erling Smørgrav struct tcpstat tcpstat; 234*ff825849SDag-Erling Smørgrav struct udpstat udpstat; 235*ff825849SDag-Erling Smørgrav struct ipstat ipstat; 236*ff825849SDag-Erling Smørgrav u_int64_t mach_time; 237*ff825849SDag-Erling Smørgrav unsigned int idata; 238*ff825849SDag-Erling Smørgrav void *addr; 239*ff825849SDag-Erling Smørgrav 240*ff825849SDag-Erling Smørgrav pid = getpid(); 241*ff825849SDag-Erling Smørgrav if (lastpid == pid) { 242*ff825849SDag-Erling Smørgrav faster = 1; 243*ff825849SDag-Erling Smørgrav repeat = 2; 244*ff825849SDag-Erling Smørgrav } else { 245*ff825849SDag-Erling Smørgrav faster = 0; 246*ff825849SDag-Erling Smørgrav lastpid = pid; 247*ff825849SDag-Erling Smørgrav repeat = REPEAT; 248*ff825849SDag-Erling Smørgrav } 249*ff825849SDag-Erling Smørgrav for (i = 0; i < len; ) { 250*ff825849SDag-Erling Smørgrav int j; 251*ff825849SDag-Erling Smørgrav SHA512_Init(&ctx); 252*ff825849SDag-Erling Smørgrav for (j = 0; j < repeat; j++) { 253*ff825849SDag-Erling Smørgrav HX((e = gettimeofday(&tv, NULL)) == -1, tv); 254*ff825849SDag-Erling Smørgrav if (e != -1) { 255*ff825849SDag-Erling Smørgrav cnt += (int)tv.tv_sec; 256*ff825849SDag-Erling Smørgrav cnt += (int)tv.tv_usec; 257*ff825849SDag-Erling Smørgrav } 258*ff825849SDag-Erling Smørgrav 259*ff825849SDag-Erling Smørgrav mach_time = mach_absolute_time(); 260*ff825849SDag-Erling Smørgrav HD(mach_time); 261*ff825849SDag-Erling Smørgrav 262*ff825849SDag-Erling Smørgrav ii = sizeof(addr); 263*ff825849SDag-Erling Smørgrav HX(sysctl(kmib, sizeof(kmib) / sizeof(kmib[0]), 264*ff825849SDag-Erling Smørgrav &addr, &ii, NULL, 0) == -1, addr); 265*ff825849SDag-Erling Smørgrav 266*ff825849SDag-Erling Smørgrav ii = sizeof(idata); 267*ff825849SDag-Erling Smørgrav HX(sysctl(hwmib, sizeof(hwmib) / sizeof(hwmib[0]), 268*ff825849SDag-Erling Smørgrav &idata, &ii, NULL, 0) == -1, idata); 269*ff825849SDag-Erling Smørgrav 270*ff825849SDag-Erling Smørgrav ii = sizeof(tcpstat); 271*ff825849SDag-Erling Smørgrav HX(sysctl(tcpmib, sizeof(tcpmib) / sizeof(tcpmib[0]), 272*ff825849SDag-Erling Smørgrav &tcpstat, &ii, NULL, 0) == -1, tcpstat); 273*ff825849SDag-Erling Smørgrav 274*ff825849SDag-Erling Smørgrav ii = sizeof(udpstat); 275*ff825849SDag-Erling Smørgrav HX(sysctl(udpmib, sizeof(udpmib) / sizeof(udpmib[0]), 276*ff825849SDag-Erling Smørgrav &udpstat, &ii, NULL, 0) == -1, udpstat); 277*ff825849SDag-Erling Smørgrav 278*ff825849SDag-Erling Smørgrav ii = sizeof(ipstat); 279*ff825849SDag-Erling Smørgrav HX(sysctl(ipmib, sizeof(ipmib) / sizeof(ipmib[0]), 280*ff825849SDag-Erling Smørgrav &ipstat, &ii, NULL, 0) == -1, ipstat); 281*ff825849SDag-Erling Smørgrav 282*ff825849SDag-Erling Smørgrav HX((pid = getpid()) == -1, pid); 283*ff825849SDag-Erling Smørgrav HX((pid = getsid(pid)) == -1, pid); 284*ff825849SDag-Erling Smørgrav HX((pid = getppid()) == -1, pid); 285*ff825849SDag-Erling Smørgrav HX((pid = getpgid(0)) == -1, pid); 286*ff825849SDag-Erling Smørgrav HX((e = getpriority(0, 0)) == -1, e); 287*ff825849SDag-Erling Smørgrav 288*ff825849SDag-Erling Smørgrav if (!faster) { 289*ff825849SDag-Erling Smørgrav ts.tv_sec = 0; 290*ff825849SDag-Erling Smørgrav ts.tv_nsec = 1; 291*ff825849SDag-Erling Smørgrav (void) nanosleep(&ts, NULL); 292*ff825849SDag-Erling Smørgrav } 293*ff825849SDag-Erling Smørgrav 294*ff825849SDag-Erling Smørgrav HX(sigpending(&sigset) == -1, sigset); 295*ff825849SDag-Erling Smørgrav HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1, 296*ff825849SDag-Erling Smørgrav sigset); 297*ff825849SDag-Erling Smørgrav 298*ff825849SDag-Erling Smørgrav #ifdef CAN_REFERENCE_MAIN 299*ff825849SDag-Erling Smørgrav HF(main); /* an addr in program */ 300*ff825849SDag-Erling Smørgrav #endif 301*ff825849SDag-Erling Smørgrav HF(getentropy); /* an addr in this library */ 302*ff825849SDag-Erling Smørgrav HF(printf); /* an addr in libc */ 303*ff825849SDag-Erling Smørgrav p = (char *)&p; 304*ff825849SDag-Erling Smørgrav HD(p); /* an addr on stack */ 305*ff825849SDag-Erling Smørgrav p = (char *)&errno; 306*ff825849SDag-Erling Smørgrav HD(p); /* the addr of errno */ 307*ff825849SDag-Erling Smørgrav 308*ff825849SDag-Erling Smørgrav if (i == 0) { 309*ff825849SDag-Erling Smørgrav struct sockaddr_storage ss; 310*ff825849SDag-Erling Smørgrav struct statvfs stvfs; 311*ff825849SDag-Erling Smørgrav struct termios tios; 312*ff825849SDag-Erling Smørgrav struct statfs stfs; 313*ff825849SDag-Erling Smørgrav socklen_t ssl; 314*ff825849SDag-Erling Smørgrav off_t off; 315*ff825849SDag-Erling Smørgrav 316*ff825849SDag-Erling Smørgrav /* 317*ff825849SDag-Erling Smørgrav * Prime-sized mappings encourage fragmentation; 318*ff825849SDag-Erling Smørgrav * thus exposing some address entropy. 319*ff825849SDag-Erling Smørgrav */ 320*ff825849SDag-Erling Smørgrav struct mm { 321*ff825849SDag-Erling Smørgrav size_t npg; 322*ff825849SDag-Erling Smørgrav void *p; 323*ff825849SDag-Erling Smørgrav } mm[] = { 324*ff825849SDag-Erling Smørgrav { 17, MAP_FAILED }, { 3, MAP_FAILED }, 325*ff825849SDag-Erling Smørgrav { 11, MAP_FAILED }, { 2, MAP_FAILED }, 326*ff825849SDag-Erling Smørgrav { 5, MAP_FAILED }, { 3, MAP_FAILED }, 327*ff825849SDag-Erling Smørgrav { 7, MAP_FAILED }, { 1, MAP_FAILED }, 328*ff825849SDag-Erling Smørgrav { 57, MAP_FAILED }, { 3, MAP_FAILED }, 329*ff825849SDag-Erling Smørgrav { 131, MAP_FAILED }, { 1, MAP_FAILED }, 330*ff825849SDag-Erling Smørgrav }; 331*ff825849SDag-Erling Smørgrav 332*ff825849SDag-Erling Smørgrav for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) { 333*ff825849SDag-Erling Smørgrav HX(mm[m].p = mmap(NULL, 334*ff825849SDag-Erling Smørgrav mm[m].npg * pgs, 335*ff825849SDag-Erling Smørgrav PROT_READ|PROT_WRITE, 336*ff825849SDag-Erling Smørgrav MAP_PRIVATE|MAP_ANON, -1, 337*ff825849SDag-Erling Smørgrav (off_t)0), mm[m].p); 338*ff825849SDag-Erling Smørgrav if (mm[m].p != MAP_FAILED) { 339*ff825849SDag-Erling Smørgrav size_t mo; 340*ff825849SDag-Erling Smørgrav 341*ff825849SDag-Erling Smørgrav /* Touch some memory... */ 342*ff825849SDag-Erling Smørgrav p = mm[m].p; 343*ff825849SDag-Erling Smørgrav mo = cnt % 344*ff825849SDag-Erling Smørgrav (mm[m].npg * pgs - 1); 345*ff825849SDag-Erling Smørgrav p[mo] = 1; 346*ff825849SDag-Erling Smørgrav cnt += (int)((long)(mm[m].p) 347*ff825849SDag-Erling Smørgrav / pgs); 348*ff825849SDag-Erling Smørgrav } 349*ff825849SDag-Erling Smørgrav 350*ff825849SDag-Erling Smørgrav /* Check cnts and times... */ 351*ff825849SDag-Erling Smørgrav mach_time = mach_absolute_time(); 352*ff825849SDag-Erling Smørgrav HD(mach_time); 353*ff825849SDag-Erling Smørgrav cnt += (int)mach_time; 354*ff825849SDag-Erling Smørgrav 355*ff825849SDag-Erling Smørgrav HX((e = getrusage(RUSAGE_SELF, 356*ff825849SDag-Erling Smørgrav &ru)) == -1, ru); 357*ff825849SDag-Erling Smørgrav if (e != -1) { 358*ff825849SDag-Erling Smørgrav cnt += (int)ru.ru_utime.tv_sec; 359*ff825849SDag-Erling Smørgrav cnt += (int)ru.ru_utime.tv_usec; 360*ff825849SDag-Erling Smørgrav } 361*ff825849SDag-Erling Smørgrav } 362*ff825849SDag-Erling Smørgrav 363*ff825849SDag-Erling Smørgrav for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) { 364*ff825849SDag-Erling Smørgrav if (mm[m].p != MAP_FAILED) 365*ff825849SDag-Erling Smørgrav munmap(mm[m].p, mm[m].npg * pgs); 366*ff825849SDag-Erling Smørgrav mm[m].p = MAP_FAILED; 367*ff825849SDag-Erling Smørgrav } 368*ff825849SDag-Erling Smørgrav 369*ff825849SDag-Erling Smørgrav HX(stat(".", &st) == -1, st); 370*ff825849SDag-Erling Smørgrav HX(statvfs(".", &stvfs) == -1, stvfs); 371*ff825849SDag-Erling Smørgrav HX(statfs(".", &stfs) == -1, stfs); 372*ff825849SDag-Erling Smørgrav 373*ff825849SDag-Erling Smørgrav HX(stat("/", &st) == -1, st); 374*ff825849SDag-Erling Smørgrav HX(statvfs("/", &stvfs) == -1, stvfs); 375*ff825849SDag-Erling Smørgrav HX(statfs("/", &stfs) == -1, stfs); 376*ff825849SDag-Erling Smørgrav 377*ff825849SDag-Erling Smørgrav HX((e = fstat(0, &st)) == -1, st); 378*ff825849SDag-Erling Smørgrav if (e == -1) { 379*ff825849SDag-Erling Smørgrav if (S_ISREG(st.st_mode) || 380*ff825849SDag-Erling Smørgrav S_ISFIFO(st.st_mode) || 381*ff825849SDag-Erling Smørgrav S_ISSOCK(st.st_mode)) { 382*ff825849SDag-Erling Smørgrav HX(fstatvfs(0, &stvfs) == -1, 383*ff825849SDag-Erling Smørgrav stvfs); 384*ff825849SDag-Erling Smørgrav HX(fstatfs(0, &stfs) == -1, 385*ff825849SDag-Erling Smørgrav stfs); 386*ff825849SDag-Erling Smørgrav HX((off = lseek(0, (off_t)0, 387*ff825849SDag-Erling Smørgrav SEEK_CUR)) < 0, off); 388*ff825849SDag-Erling Smørgrav } 389*ff825849SDag-Erling Smørgrav if (S_ISCHR(st.st_mode)) { 390*ff825849SDag-Erling Smørgrav HX(tcgetattr(0, &tios) == -1, 391*ff825849SDag-Erling Smørgrav tios); 392*ff825849SDag-Erling Smørgrav } else if (S_ISSOCK(st.st_mode)) { 393*ff825849SDag-Erling Smørgrav memset(&ss, 0, sizeof ss); 394*ff825849SDag-Erling Smørgrav ssl = sizeof(ss); 395*ff825849SDag-Erling Smørgrav HX(getpeername(0, 396*ff825849SDag-Erling Smørgrav (void *)&ss, &ssl) == -1, 397*ff825849SDag-Erling Smørgrav ss); 398*ff825849SDag-Erling Smørgrav } 399*ff825849SDag-Erling Smørgrav } 400*ff825849SDag-Erling Smørgrav 401*ff825849SDag-Erling Smørgrav HX((e = getrusage(RUSAGE_CHILDREN, 402*ff825849SDag-Erling Smørgrav &ru)) == -1, ru); 403*ff825849SDag-Erling Smørgrav if (e != -1) { 404*ff825849SDag-Erling Smørgrav cnt += (int)ru.ru_utime.tv_sec; 405*ff825849SDag-Erling Smørgrav cnt += (int)ru.ru_utime.tv_usec; 406*ff825849SDag-Erling Smørgrav } 407*ff825849SDag-Erling Smørgrav } else { 408*ff825849SDag-Erling Smørgrav /* Subsequent hashes absorb previous result */ 409*ff825849SDag-Erling Smørgrav HD(results); 410*ff825849SDag-Erling Smørgrav } 411*ff825849SDag-Erling Smørgrav 412*ff825849SDag-Erling Smørgrav HX((e = gettimeofday(&tv, NULL)) == -1, tv); 413*ff825849SDag-Erling Smørgrav if (e != -1) { 414*ff825849SDag-Erling Smørgrav cnt += (int)tv.tv_sec; 415*ff825849SDag-Erling Smørgrav cnt += (int)tv.tv_usec; 416*ff825849SDag-Erling Smørgrav } 417*ff825849SDag-Erling Smørgrav 418*ff825849SDag-Erling Smørgrav HD(cnt); 419*ff825849SDag-Erling Smørgrav } 420*ff825849SDag-Erling Smørgrav 421*ff825849SDag-Erling Smørgrav SHA512_Final(results, &ctx); 422*ff825849SDag-Erling Smørgrav memcpy((char*)buf + i, results, min(sizeof(results), len - i)); 423*ff825849SDag-Erling Smørgrav i += min(sizeof(results), len - i); 424*ff825849SDag-Erling Smørgrav } 425*ff825849SDag-Erling Smørgrav memset(results, 0, sizeof results); 426*ff825849SDag-Erling Smørgrav if (gotdata(buf, len) == 0) { 427*ff825849SDag-Erling Smørgrav errno = save_errno; 428*ff825849SDag-Erling Smørgrav return 0; /* satisfied */ 429*ff825849SDag-Erling Smørgrav } 430*ff825849SDag-Erling Smørgrav errno = EIO; 431*ff825849SDag-Erling Smørgrav return -1; 432*ff825849SDag-Erling Smørgrav } 433