1*29a36ee6Sbcook /* $OpenBSD: arc4random_netbsd.h,v 1.1 2015/01/19 20:21:40 bcook Exp $ */ 2*29a36ee6Sbcook 3*29a36ee6Sbcook /* 4*29a36ee6Sbcook * Copyright (c) 1996, David Mazieres <dm@uun.org> 5*29a36ee6Sbcook * Copyright (c) 2008, Damien Miller <djm@openbsd.org> 6*29a36ee6Sbcook * Copyright (c) 2013, Markus Friedl <markus@openbsd.org> 7*29a36ee6Sbcook * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org> 8*29a36ee6Sbcook * 9*29a36ee6Sbcook * Permission to use, copy, modify, and distribute this software for any 10*29a36ee6Sbcook * purpose with or without fee is hereby granted, provided that the above 11*29a36ee6Sbcook * copyright notice and this permission notice appear in all copies. 12*29a36ee6Sbcook * 13*29a36ee6Sbcook * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14*29a36ee6Sbcook * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15*29a36ee6Sbcook * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16*29a36ee6Sbcook * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17*29a36ee6Sbcook * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18*29a36ee6Sbcook * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19*29a36ee6Sbcook * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20*29a36ee6Sbcook */ 21*29a36ee6Sbcook 22*29a36ee6Sbcook /* 23*29a36ee6Sbcook * Stub functions for portability. 24*29a36ee6Sbcook */ 25*29a36ee6Sbcook 26*29a36ee6Sbcook #include <sys/mman.h> 27*29a36ee6Sbcook 28*29a36ee6Sbcook #include <pthread.h> 29*29a36ee6Sbcook #include <signal.h> 30*29a36ee6Sbcook 31*29a36ee6Sbcook static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER; 32*29a36ee6Sbcook #define _ARC4_LOCK() pthread_mutex_lock(&arc4random_mtx) 33*29a36ee6Sbcook #define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx) 34*29a36ee6Sbcook 35*29a36ee6Sbcook /* 36*29a36ee6Sbcook * Unfortunately, pthread_atfork() is broken on FreeBSD (at least 9 and 10) if 37*29a36ee6Sbcook * a program does not link to -lthr. Callbacks registered with pthread_atfork() 38*29a36ee6Sbcook * appear to fail silently. So, it is not always possible to detect a PID 39*29a36ee6Sbcook * wraparound. 40*29a36ee6Sbcook */ 41*29a36ee6Sbcook #define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f)) 42*29a36ee6Sbcook 43*29a36ee6Sbcook static inline void 44*29a36ee6Sbcook _getentropy_fail(void) 45*29a36ee6Sbcook { 46*29a36ee6Sbcook raise(SIGKILL); 47*29a36ee6Sbcook } 48*29a36ee6Sbcook 49*29a36ee6Sbcook static volatile sig_atomic_t _rs_forked; 50*29a36ee6Sbcook 51*29a36ee6Sbcook static inline void 52*29a36ee6Sbcook _rs_forkhandler(void) 53*29a36ee6Sbcook { 54*29a36ee6Sbcook _rs_forked = 1; 55*29a36ee6Sbcook } 56*29a36ee6Sbcook 57*29a36ee6Sbcook static inline void 58*29a36ee6Sbcook _rs_forkdetect(void) 59*29a36ee6Sbcook { 60*29a36ee6Sbcook static pid_t _rs_pid = 0; 61*29a36ee6Sbcook pid_t pid = getpid(); 62*29a36ee6Sbcook 63*29a36ee6Sbcook if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) { 64*29a36ee6Sbcook _rs_pid = pid; 65*29a36ee6Sbcook _rs_forked = 0; 66*29a36ee6Sbcook if (rs) 67*29a36ee6Sbcook memset(rs, 0, sizeof(*rs)); 68*29a36ee6Sbcook } 69*29a36ee6Sbcook } 70*29a36ee6Sbcook 71*29a36ee6Sbcook static inline int 72*29a36ee6Sbcook _rs_allocate(struct _rs **rsp, struct _rsx **rsxp) 73*29a36ee6Sbcook { 74*29a36ee6Sbcook if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE, 75*29a36ee6Sbcook MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) 76*29a36ee6Sbcook return -1; 77*29a36ee6Sbcook 78*29a36ee6Sbcook if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE, 79*29a36ee6Sbcook MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) { 80*29a36ee6Sbcook munmap(*rsp, sizeof(**rsp)); 81*29a36ee6Sbcook return -1; 82*29a36ee6Sbcook } 83*29a36ee6Sbcook 84*29a36ee6Sbcook _ARC4_ATFORK(_rs_forkhandler); 85*29a36ee6Sbcook return 0; 86*29a36ee6Sbcook } 87