xref: /freebsd/crypto/openssh/openbsd-compat/arc4random.h (revision 3d9fd9fcb432750f3716b28f6ccb0104cd9d351a)
138a52bd3SEd Maste /*	$OpenBSD: arc4random_linux.h,v 1.12 2019/07/11 10:37:28 inoguchi Exp $	*/
238a52bd3SEd Maste 
338a52bd3SEd Maste /*
438a52bd3SEd Maste  * Copyright (c) 1996, David Mazieres <dm@uun.org>
538a52bd3SEd Maste  * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
638a52bd3SEd Maste  * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
738a52bd3SEd Maste  * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
838a52bd3SEd Maste  *
938a52bd3SEd Maste  * Permission to use, copy, modify, and distribute this software for any
1038a52bd3SEd Maste  * purpose with or without fee is hereby granted, provided that the above
1138a52bd3SEd Maste  * copyright notice and this permission notice appear in all copies.
1238a52bd3SEd Maste  *
1338a52bd3SEd Maste  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1438a52bd3SEd Maste  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1538a52bd3SEd Maste  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1638a52bd3SEd Maste  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1738a52bd3SEd Maste  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1838a52bd3SEd Maste  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1938a52bd3SEd Maste  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2038a52bd3SEd Maste  */
2138a52bd3SEd Maste 
2238a52bd3SEd Maste /*
2338a52bd3SEd Maste  * Stub functions for portability.  From LibreSSL with some adaptations.
2438a52bd3SEd Maste  */
2538a52bd3SEd Maste 
26*3d9fd9fcSEd Maste #ifdef HAVE_SYS_MMAN_H
2738a52bd3SEd Maste #include <sys/mman.h>
28*3d9fd9fcSEd Maste #endif
2938a52bd3SEd Maste 
3038a52bd3SEd Maste #include <signal.h>
3138a52bd3SEd Maste 
3238a52bd3SEd Maste /* OpenSSH isn't multithreaded */
3338a52bd3SEd Maste #define _ARC4_LOCK()
3438a52bd3SEd Maste #define _ARC4_UNLOCK()
3538a52bd3SEd Maste #define _ARC4_ATFORK(f)
3638a52bd3SEd Maste 
3738a52bd3SEd Maste static inline void
_getentropy_fail(void)3838a52bd3SEd Maste _getentropy_fail(void)
3938a52bd3SEd Maste {
4038a52bd3SEd Maste 	fatal("getentropy failed");
4138a52bd3SEd Maste }
4238a52bd3SEd Maste 
4338a52bd3SEd Maste static volatile sig_atomic_t _rs_forked;
4438a52bd3SEd Maste 
4538a52bd3SEd Maste static inline void
_rs_forkhandler(void)4638a52bd3SEd Maste _rs_forkhandler(void)
4738a52bd3SEd Maste {
4838a52bd3SEd Maste 	_rs_forked = 1;
4938a52bd3SEd Maste }
5038a52bd3SEd Maste 
5138a52bd3SEd Maste static inline void
_rs_forkdetect(void)5238a52bd3SEd Maste _rs_forkdetect(void)
5338a52bd3SEd Maste {
5438a52bd3SEd Maste 	static pid_t _rs_pid = 0;
5538a52bd3SEd Maste 	pid_t pid = getpid();
5638a52bd3SEd Maste 
5738a52bd3SEd Maste 	if (_rs_pid == 0 || _rs_pid == 1 || _rs_pid != pid || _rs_forked) {
5838a52bd3SEd Maste 		_rs_pid = pid;
5938a52bd3SEd Maste 		_rs_forked = 0;
6038a52bd3SEd Maste 		if (rs)
6138a52bd3SEd Maste 			memset(rs, 0, sizeof(*rs));
6238a52bd3SEd Maste 	}
6338a52bd3SEd Maste }
6438a52bd3SEd Maste 
6538a52bd3SEd Maste static inline int
_rs_allocate(struct _rs ** rsp,struct _rsx ** rsxp)6638a52bd3SEd Maste _rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
6738a52bd3SEd Maste {
68f374ba41SEd Maste #if defined(MAP_ANON) && defined(MAP_PRIVATE)
6938a52bd3SEd Maste 	if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
7038a52bd3SEd Maste 	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
7138a52bd3SEd Maste 		return (-1);
7238a52bd3SEd Maste 
7338a52bd3SEd Maste 	if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
7438a52bd3SEd Maste 	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
7538a52bd3SEd Maste 		munmap(*rsp, sizeof(**rsp));
7638a52bd3SEd Maste 		*rsp = NULL;
7738a52bd3SEd Maste 		return (-1);
7838a52bd3SEd Maste 	}
79f374ba41SEd Maste #else
80f374ba41SEd Maste 	if ((*rsp = calloc(1, sizeof(**rsp))) == NULL)
81f374ba41SEd Maste 		return (-1);
82f374ba41SEd Maste 	if ((*rsxp = calloc(1, sizeof(**rsxp))) == NULL) {
83f374ba41SEd Maste 		free(*rsp);
84f374ba41SEd Maste 		*rsp = NULL;
85f374ba41SEd Maste 		return (-1);
86f374ba41SEd Maste 	}
87f374ba41SEd Maste #endif
8838a52bd3SEd Maste 
8938a52bd3SEd Maste 	_ARC4_ATFORK(_rs_forkhandler);
9038a52bd3SEd Maste 	return (0);
9138a52bd3SEd Maste }
92