1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/*
2c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard *
4b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * Redistribution and use in source and binary forms, with or without
5b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * modification, are permitted provided that the following conditions
6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * are met:
7de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * 1. Redistributions of source code must retain the above copyright
8b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    notice, this list of conditions and the following disclaimer.
9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * 2. Redistributions in binary form must reproduce the above copyright
10de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard *    notice, this list of conditions and the following disclaimer in the
11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard *    documentation and/or other materials provided with the distribution.
12de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * 3. The name of the author may not be used to endorse or promote products
13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard *    derived from this software without specific prior written permission.
14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard *
15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper */
26de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
27de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard/* This file has our secure PRNG code.  On platforms that have arc4random(),
28de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * we just use that.  Otherwise, we include arc4random.c as a bunch of static
29b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * functions, and wrap it lightly.  We don't expose the arc4random*() APIs
30b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * because A) they aren't in our namespace, and B) it's not nice to name your
31b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * APIs after their implementations.  We keep them in a separate file
32b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * so that other people can rip it out and use it for whatever.
33b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper */
34b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
35b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "event2/event-config.h"
36390dd3d21c5b92dda139da744edae7093d70fc9bMark Wielaard
37b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <limits.h>
38b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
39b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "util-internal.h"
40b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "evthread-internal.h"
41b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
421ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaard#ifdef _EVENT_HAVE_ARC4RANDOM
431ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaard#include <stdlib.h>
44b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <string.h>
45b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperint
46c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaardevutil_secure_rng_set_urandom_device_file(char *fname)
47c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard{
48bb9d1b4bf225a604ceb69130f5a54a66f95b525dMark Wielaard	(void) fname;
49c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	return -1;
50bb9d1b4bf225a604ceb69130f5a54a66f95b525dMark Wielaard}
51c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaardint
52c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaardevutil_secure_rng_init(void)
53c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard{
54c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	/* call arc4random() now to force it to self-initialize */
55c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	(void) arc4random();
56bb9d1b4bf225a604ceb69130f5a54a66f95b525dMark Wielaard	return 0;
57c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard}
58c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaardint
59c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaardevutil_secure_rng_global_setup_locks_(const int enable_locks)
60bb9d1b4bf225a604ceb69130f5a54a66f95b525dMark Wielaard{
61c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	return 0;
62bb9d1b4bf225a604ceb69130f5a54a66f95b525dMark Wielaard}
63c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard
64c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaardstatic void
65c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaardev_arc4random_buf(void *buf, size_t n)
66c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard{
67c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#if defined(_EVENT_HAVE_ARC4RANDOM_BUF) && !defined(__APPLE__)
68c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	return arc4random_buf(buf, n);
69c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#else
70c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	unsigned char *b = buf;
71c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard
72c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#if defined(_EVENT_HAVE_ARC4RANDOM_BUF)
73c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	/* OSX 10.7 introducd arc4random_buf, so if you build your program
74c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	 * there, you'll get surprised when older versions of OSX fail to run.
75c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	 * To solve this, we can check whether the function pointer is set,
76c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	 * and fall back otherwise.  (OSX does this using some linker
77c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	 * trickery.)
78c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	 */
79c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	{
80c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard		void (*tptr)(void *,size_t) =
81c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard		    (void (*)(void*,size_t))arc4random_buf;
82c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard		if (tptr != NULL) {
83c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard			return arc4random_buf(buf, n);
84c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard		}
85c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	}
86c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#endif
87c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	/* Make sure that we start out with b at a 4-byte alignment; plenty
88c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	 * of CPUs care about this for 32-bit access. */
89c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	if (n >= 4 && ((ev_uintptr_t)b) & 3) {
90c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard		ev_uint32_t u = arc4random();
91c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard		int n_bytes = 4 - (((ev_uintptr_t)b) & 3);
92c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard		memcpy(b, &u, n_bytes);
93c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard		b += n_bytes;
94c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard		n -= n_bytes;
95c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	}
96c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	while (n >= 4) {
97c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard		*(ev_uint32_t*)b = arc4random();
98c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard		b += 4;
99c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard		n -= 4;
100c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	}
101c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	if (n) {
102c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard		ev_uint32_t u = arc4random();
103c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard		memcpy(b, &u, n);
104c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	}
105c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#endif
106c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard}
107c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard
108c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#else /* !_EVENT_HAVE_ARC4RANDOM { */
109c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard
110c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#ifdef _EVENT_ssize_t
111c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#define ssize_t _EVENT_SSIZE_t
112c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#endif
113c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#define ARC4RANDOM_EXPORT static
114c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#define _ARC4_LOCK() EVLOCK_LOCK(arc4rand_lock, 0)
115c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#define _ARC4_UNLOCK() EVLOCK_UNLOCK(arc4rand_lock, 0)
116c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#ifndef _EVENT_DISABLE_THREAD_SUPPORT
117c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaardstatic void *arc4rand_lock;
118c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#endif
119c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard
120c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#define ARC4RANDOM_UINT32 ev_uint32_t
121c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#define ARC4RANDOM_NOSTIR
122c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#define ARC4RANDOM_NORANDOM
123c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#define ARC4RANDOM_NOUNIFORM
124c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard
125c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#include "./arc4random.c"
126c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard
127c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#ifndef _EVENT_DISABLE_THREAD_SUPPORT
128c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaardint
129c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaardevutil_secure_rng_global_setup_locks_(const int enable_locks)
130c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard{
131c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	EVTHREAD_SETUP_GLOBAL_LOCK(arc4rand_lock, 0);
132c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	return 0;
133c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard}
134c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#endif
135c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard
136c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaardint
137c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaardevutil_secure_rng_set_urandom_device_file(char *fname)
138c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard{
139c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#ifdef TRY_SEED_URANDOM
140c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	_ARC4_LOCK();
141c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	arc4random_urandom_filename = fname;
142c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	_ARC4_UNLOCK();
143c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#endif
144c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	return 0;
145c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard}
146c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard
147c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaardint
148c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaardevutil_secure_rng_init(void)
149c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard{
150c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	int val;
151c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard
152c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	_ARC4_LOCK();
153c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	if (!arc4_seeded_ok)
154c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard		arc4_stir();
155c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	val = arc4_seeded_ok ? 0 : -1;
156c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	_ARC4_UNLOCK();
157c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	return val;
158c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard}
159c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard
160c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaardstatic void
161c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaardev_arc4random_buf(void *buf, size_t n)
162c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard{
163c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	arc4random_buf(buf, n);
164c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard}
165c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard
166c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#endif /* } !_EVENT_HAVE_ARC4RANDOM */
167c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard
168390dd3d21c5b92dda139da744edae7093d70fc9bMark Wielaardvoid
169c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaardevutil_secure_rng_get_bytes(void *buf, size_t n)
170c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard{
171c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	ev_arc4random_buf(buf, n);
172c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard}
173c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard
174c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaardvoid
175c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaardevutil_secure_rng_add_bytes(const char *buf, size_t n)
176c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard{
177c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#if !defined(__BIONIC__) /* bionic and OpenBSD removed this; it's a no-op in their current implementation. */
178c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	arc4random_addrandom((unsigned char*)buf,
179c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard	    n>(size_t)INT_MAX ? INT_MAX : (int)n);
180c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard#endif
181c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard}
182c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard
183c5da7c9e08c2bdb6dba8e115dcc09ed51a07f0e4Mark Wielaard