Source code pulled from OpenBSD for OpenNTPD. The place to contribute to this code is via the OpenBSD CVS tree.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

396 lines
9.3 KiB

  1. /* $OpenBSD: getentropy_hpux.c,v 1.7 2020/05/17 14:44:20 deraadt Exp $ */
  2. /*
  3. * Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
  4. * Copyright (c) 2014 Bob Beck <beck@obtuse.com>
  5. *
  6. * Permission to use, copy, modify, and distribute this software for any
  7. * purpose with or without fee is hereby granted, provided that the above
  8. * copyright notice and this permission notice appear in all copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. *
  18. * Emulation of getentropy(2) as documented at:
  19. * http://man.openbsd.org/getentropy.2
  20. */
  21. #include <sys/types.h>
  22. #include <sys/param.h>
  23. #include <sys/ioctl.h>
  24. #include <sys/resource.h>
  25. #include <sys/syscall.h>
  26. #include <sys/statvfs.h>
  27. #include <sys/socket.h>
  28. #include <sys/mount.h>
  29. #include <sys/mman.h>
  30. #include <sys/stat.h>
  31. #include <sys/time.h>
  32. #include <stdlib.h>
  33. #include <stdint.h>
  34. #include <stdio.h>
  35. #include <termios.h>
  36. #include <fcntl.h>
  37. #include <signal.h>
  38. #include <string.h>
  39. #include <errno.h>
  40. #include <unistd.h>
  41. #include <time.h>
  42. #include <openssl/sha.h>
  43. #include <sys/vfs.h>
  44. #include <sys/pstat.h>
  45. #define REPEAT 5
  46. #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
  47. #define HX(a, b) \
  48. do { \
  49. if ((a)) \
  50. HD(errno); \
  51. else \
  52. HD(b); \
  53. } while (0)
  54. #define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
  55. #define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
  56. #define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
  57. int getentropy(void *buf, size_t len);
  58. static int getentropy_urandom(void *buf, size_t len, const char *path,
  59. int devfscheck);
  60. static int getentropy_fallback(void *buf, size_t len);
  61. int
  62. getentropy(void *buf, size_t len)
  63. {
  64. int ret = -1;
  65. if (len > 256) {
  66. errno = EIO;
  67. return (-1);
  68. }
  69. /*
  70. * Try to get entropy with /dev/urandom
  71. */
  72. ret = getentropy_urandom(buf, len, "/dev/urandom", 0);
  73. if (ret != -1)
  74. return (ret);
  75. /*
  76. * Entropy collection via /dev/urandom has failed.
  77. *
  78. * No other API exists for collecting entropy, and we have
  79. * no failsafe way to get it on hpux that is not sensitive
  80. * to resource exhaustion.
  81. *
  82. * We have very few options:
  83. * - Even syslog_r is unsafe to call at this low level, so
  84. * there is no way to alert the user or program.
  85. * - Cannot call abort() because some systems have unsafe
  86. * corefiles.
  87. * - Could raise(SIGKILL) resulting in silent program termination.
  88. * - Return EIO, to hint that arc4random's stir function
  89. * should raise(SIGKILL)
  90. * - Do the best under the circumstances....
  91. *
  92. * This code path exists to bring light to the issue that hpux
  93. * does not provide a failsafe API for entropy collection.
  94. *
  95. * We hope this demonstrates that hpux should consider
  96. * providing a new failsafe API which works in a chroot or
  97. * when file descriptors are exhausted.
  98. */
  99. #undef FAIL_INSTEAD_OF_TRYING_FALLBACK
  100. #ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
  101. raise(SIGKILL);
  102. #endif
  103. ret = getentropy_fallback(buf, len);
  104. if (ret != -1)
  105. return (ret);
  106. errno = EIO;
  107. return (ret);
  108. }
  109. static int
  110. getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
  111. {
  112. struct stat st;
  113. size_t i;
  114. int fd, flags;
  115. int save_errno = errno;
  116. start:
  117. flags = O_RDONLY;
  118. #ifdef O_NOFOLLOW
  119. flags |= O_NOFOLLOW;
  120. #endif
  121. #ifdef O_CLOEXEC
  122. flags |= O_CLOEXEC;
  123. #endif
  124. fd = open(path, flags, 0);
  125. if (fd == -1) {
  126. if (errno == EINTR)
  127. goto start;
  128. goto nodevrandom;
  129. }
  130. #ifndef O_CLOEXEC
  131. fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
  132. #endif
  133. /* Lightly verify that the device node looks sane */
  134. if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
  135. close(fd);
  136. goto nodevrandom;
  137. }
  138. for (i = 0; i < len; ) {
  139. size_t wanted = len - i;
  140. ssize_t ret = read(fd, (char *)buf + i, wanted);
  141. if (ret == -1) {
  142. if (errno == EAGAIN || errno == EINTR)
  143. continue;
  144. close(fd);
  145. goto nodevrandom;
  146. }
  147. i += ret;
  148. }
  149. close(fd);
  150. errno = save_errno;
  151. return (0); /* satisfied */
  152. nodevrandom:
  153. errno = EIO;
  154. return (-1);
  155. }
  156. static const int cl[] = {
  157. CLOCK_REALTIME,
  158. #ifdef CLOCK_MONOTONIC
  159. CLOCK_MONOTONIC,
  160. #endif
  161. #ifdef CLOCK_MONOTONIC_RAW
  162. CLOCK_MONOTONIC_RAW,
  163. #endif
  164. #ifdef CLOCK_TAI
  165. CLOCK_TAI,
  166. #endif
  167. #ifdef CLOCK_VIRTUAL
  168. CLOCK_VIRTUAL,
  169. #endif
  170. #ifdef CLOCK_UPTIME
  171. CLOCK_UPTIME,
  172. #endif
  173. #ifdef CLOCK_PROCESS_CPUTIME_ID
  174. CLOCK_PROCESS_CPUTIME_ID,
  175. #endif
  176. #ifdef CLOCK_THREAD_CPUTIME_ID
  177. CLOCK_THREAD_CPUTIME_ID,
  178. #endif
  179. };
  180. static int
  181. getentropy_fallback(void *buf, size_t len)
  182. {
  183. uint8_t results[SHA512_DIGEST_LENGTH];
  184. int save_errno = errno, e, pgs = sysconf(_SC_PAGESIZE), faster = 0, repeat;
  185. static int cnt;
  186. struct timespec ts;
  187. struct timeval tv;
  188. struct pst_vminfo pvi;
  189. struct pst_vm_status pvs;
  190. struct pst_dynamic pdy;
  191. struct rusage ru;
  192. sigset_t sigset;
  193. struct stat st;
  194. SHA512_CTX ctx;
  195. static pid_t lastpid;
  196. pid_t pid;
  197. size_t i, ii, m;
  198. char *p;
  199. pid = getpid();
  200. if (lastpid == pid) {
  201. faster = 1;
  202. repeat = 2;
  203. } else {
  204. faster = 0;
  205. lastpid = pid;
  206. repeat = REPEAT;
  207. }
  208. for (i = 0; i < len; ) {
  209. int j;
  210. SHA512_Init(&ctx);
  211. for (j = 0; j < repeat; j++) {
  212. HX((e = gettimeofday(&tv, NULL)) == -1, tv);
  213. if (e != -1) {
  214. cnt += (int)tv.tv_sec;
  215. cnt += (int)tv.tv_usec;
  216. }
  217. HX(pstat_getvminfo(&pvi, sizeof(pvi), 1, 0) != 1, pvi);
  218. HX(pstat_getprocvm(&pvs, sizeof(pvs), 0, 0) != 1, pvs);
  219. for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
  220. HX(clock_gettime(cl[ii], &ts) == -1, ts);
  221. HX((pid = getpid()) == -1, pid);
  222. HX((pid = getsid(pid)) == -1, pid);
  223. HX((pid = getppid()) == -1, pid);
  224. HX((pid = getpgid(0)) == -1, pid);
  225. HX((e = getpriority(0, 0)) == -1, e);
  226. if(pstat_getdynamic(&pdy, sizeof(pdy), 1, 0) != 1) {
  227. HD(errno);
  228. } else {
  229. HD(pdy.psd_avg_1_min);
  230. HD(pdy.psd_avg_5_min);
  231. HD(pdy.psd_avg_15_min);
  232. }
  233. if (!faster) {
  234. ts.tv_sec = 0;
  235. ts.tv_nsec = 1;
  236. (void) nanosleep(&ts, NULL);
  237. }
  238. HX(sigpending(&sigset) == -1, sigset);
  239. HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
  240. sigset);
  241. HF(getentropy); /* an addr in this library */
  242. HF(printf); /* an addr in libc */
  243. p = (char *)&p;
  244. HD(p); /* an addr on stack */
  245. p = (char *)&errno;
  246. HD(p); /* the addr of errno */
  247. if (i == 0) {
  248. struct sockaddr_storage ss;
  249. struct statvfs stvfs;
  250. struct termios tios;
  251. socklen_t ssl;
  252. off_t off;
  253. /*
  254. * Prime-sized mappings encourage fragmentation;
  255. * thus exposing some address entropy.
  256. */
  257. struct mm {
  258. size_t npg;
  259. void *p;
  260. } mm[] = {
  261. { 17, MAP_FAILED }, { 3, MAP_FAILED },
  262. { 11, MAP_FAILED }, { 2, MAP_FAILED },
  263. { 5, MAP_FAILED }, { 3, MAP_FAILED },
  264. { 7, MAP_FAILED }, { 1, MAP_FAILED },
  265. { 57, MAP_FAILED }, { 3, MAP_FAILED },
  266. { 131, MAP_FAILED }, { 1, MAP_FAILED },
  267. };
  268. for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
  269. HX(mm[m].p = mmap(NULL,
  270. mm[m].npg * pgs,
  271. PROT_READ|PROT_WRITE,
  272. MAP_PRIVATE|MAP_ANON, -1,
  273. (off_t)0), mm[m].p);
  274. if (mm[m].p != MAP_FAILED) {
  275. size_t mo;
  276. /* Touch some memory... */
  277. p = mm[m].p;
  278. mo = cnt %
  279. (mm[m].npg * pgs - 1);
  280. p[mo] = 1;
  281. cnt += (int)((long)(mm[m].p)
  282. / pgs);
  283. }
  284. /* Check cnts and times... */
  285. for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
  286. ii++) {
  287. HX((e = clock_gettime(cl[ii],
  288. &ts)) == -1, ts);
  289. if (e != -1)
  290. cnt += (int)ts.tv_nsec;
  291. }
  292. HX((e = getrusage(RUSAGE_SELF,
  293. &ru)) == -1, ru);
  294. if (e != -1) {
  295. cnt += (int)ru.ru_utime.tv_sec;
  296. cnt += (int)ru.ru_utime.tv_usec;
  297. }
  298. }
  299. for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
  300. if (mm[m].p != MAP_FAILED)
  301. munmap(mm[m].p, mm[m].npg * pgs);
  302. mm[m].p = MAP_FAILED;
  303. }
  304. HX(stat(".", &st) == -1, st);
  305. HX(statvfs(".", &stvfs) == -1, stvfs);
  306. HX(stat("/", &st) == -1, st);
  307. HX(statvfs("/", &stvfs) == -1, stvfs);
  308. HX((e = fstat(0, &st)) == -1, st);
  309. if (e == -1) {
  310. if (S_ISREG(st.st_mode) ||
  311. S_ISFIFO(st.st_mode) ||
  312. S_ISSOCK(st.st_mode)) {
  313. HX(fstatvfs(0, &stvfs) == -1,
  314. stvfs);
  315. HX((off = lseek(0, (off_t)0,
  316. SEEK_CUR)) < 0, off);
  317. }
  318. if (S_ISCHR(st.st_mode)) {
  319. HX(tcgetattr(0, &tios) == -1,
  320. tios);
  321. } else if (S_ISSOCK(st.st_mode)) {
  322. memset(&ss, 0, sizeof ss);
  323. ssl = sizeof(ss);
  324. HX(getpeername(0,
  325. (void *)&ss, &ssl) == -1,
  326. ss);
  327. }
  328. }
  329. HX((e = getrusage(RUSAGE_CHILDREN,
  330. &ru)) == -1, ru);
  331. if (e != -1) {
  332. cnt += (int)ru.ru_utime.tv_sec;
  333. cnt += (int)ru.ru_utime.tv_usec;
  334. }
  335. } else {
  336. /* Subsequent hashes absorb previous result */
  337. HD(results);
  338. }
  339. HX((e = gettimeofday(&tv, NULL)) == -1, tv);
  340. if (e != -1) {
  341. cnt += (int)tv.tv_sec;
  342. cnt += (int)tv.tv_usec;
  343. }
  344. HD(cnt);
  345. }
  346. SHA512_Final(results, &ctx);
  347. memcpy((char *)buf + i, results, MINIMUM(sizeof(results), len - i));
  348. i += MINIMUM(sizeof(results), len - i);
  349. }
  350. explicit_bzero(&ctx, sizeof ctx);
  351. explicit_bzero(results, sizeof results);
  352. errno = save_errno;
  353. return (0); /* satisfied */
  354. }