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