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