1275970Scy/*
2275970Scy * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
3275970Scy *
4275970Scy * Redistribution and use in source and binary forms, with or without
5275970Scy * modification, are permitted provided that the following conditions
6275970Scy * are met:
7275970Scy * 1. Redistributions of source code must retain the above copyright
8275970Scy *    notice, this list of conditions and the following disclaimer.
9275970Scy * 2. Redistributions in binary form must reproduce the above copyright
10275970Scy *    notice, this list of conditions and the following disclaimer in the
11275970Scy *    documentation and/or other materials provided with the distribution.
12275970Scy * 3. The name of the author may not be used to endorse or promote products
13275970Scy *    derived from this software without specific prior written permission.
14275970Scy *
15275970Scy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16275970Scy * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17275970Scy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18275970Scy * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19275970Scy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20275970Scy * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21275970Scy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22275970Scy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23275970Scy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24275970Scy * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25275970Scy */
26275970Scy
27275970Scy/* This file has our secure PRNG code.  On platforms that have arc4random(),
28275970Scy * we just use that.  Otherwise, we include arc4random.c as a bunch of static
29275970Scy * functions, and wrap it lightly.  We don't expose the arc4random*() APIs
30275970Scy * because A) they aren't in our namespace, and B) it's not nice to name your
31275970Scy * APIs after their implementations.  We keep them in a separate file
32275970Scy * so that other people can rip it out and use it for whatever.
33275970Scy */
34275970Scy
35275970Scy#include "event2/event-config.h"
36275970Scy#include "evconfig-private.h"
37275970Scy
38275970Scy#include <limits.h>
39275970Scy
40275970Scy#include "util-internal.h"
41275970Scy#include "evthread-internal.h"
42275970Scy
43275970Scy#ifdef EVENT__HAVE_ARC4RANDOM
44275970Scy#include <stdlib.h>
45275970Scy#include <string.h>
46275970Scyint
47275970Scyevutil_secure_rng_set_urandom_device_file(char *fname)
48275970Scy{
49275970Scy	(void) fname;
50275970Scy	return -1;
51275970Scy}
52275970Scyint
53275970Scyevutil_secure_rng_init(void)
54275970Scy{
55275970Scy	/* call arc4random() now to force it to self-initialize */
56275970Scy	(void) arc4random();
57275970Scy	return 0;
58275970Scy}
59275970Scy#ifndef EVENT__DISABLE_THREAD_SUPPORT
60275970Scyint
61275970Scyevutil_secure_rng_global_setup_locks_(const int enable_locks)
62275970Scy{
63275970Scy	return 0;
64275970Scy}
65275970Scy#endif
66275970Scystatic void
67275970Scyevutil_free_secure_rng_globals_locks(void)
68275970Scy{
69275970Scy}
70275970Scy
71275970Scystatic void
72275970Scyev_arc4random_buf(void *buf, size_t n)
73275970Scy{
74275970Scy#if defined(EVENT__HAVE_ARC4RANDOM_BUF) && !defined(__APPLE__)
75275970Scy	arc4random_buf(buf, n);
76275970Scy	return;
77275970Scy#else
78275970Scy	unsigned char *b = buf;
79275970Scy
80275970Scy#if defined(EVENT__HAVE_ARC4RANDOM_BUF)
81275970Scy	/* OSX 10.7 introducd arc4random_buf, so if you build your program
82275970Scy	 * there, you'll get surprised when older versions of OSX fail to run.
83275970Scy	 * To solve this, we can check whether the function pointer is set,
84275970Scy	 * and fall back otherwise.  (OSX does this using some linker
85275970Scy	 * trickery.)
86275970Scy	 */
87275970Scy	{
88275970Scy		void (*tptr)(void *,size_t) =
89275970Scy		    (void (*)(void*,size_t))arc4random_buf;
90275970Scy		if (tptr != NULL) {
91275970Scy			arc4random_buf(buf, n);
92275970Scy			return;
93275970Scy		}
94275970Scy	}
95275970Scy#endif
96275970Scy	/* Make sure that we start out with b at a 4-byte alignment; plenty
97275970Scy	 * of CPUs care about this for 32-bit access. */
98275970Scy	if (n >= 4 && ((ev_uintptr_t)b) & 3) {
99275970Scy		ev_uint32_t u = arc4random();
100275970Scy		int n_bytes = 4 - (((ev_uintptr_t)b) & 3);
101275970Scy		memcpy(b, &u, n_bytes);
102275970Scy		b += n_bytes;
103275970Scy		n -= n_bytes;
104275970Scy	}
105275970Scy	while (n >= 4) {
106275970Scy		*(ev_uint32_t*)b = arc4random();
107275970Scy		b += 4;
108275970Scy		n -= 4;
109275970Scy	}
110275970Scy	if (n) {
111275970Scy		ev_uint32_t u = arc4random();
112275970Scy		memcpy(b, &u, n);
113275970Scy	}
114275970Scy#endif
115275970Scy}
116275970Scy
117275970Scy#else /* !EVENT__HAVE_ARC4RANDOM { */
118275970Scy
119275970Scy#ifdef EVENT__ssize_t
120275970Scy#define ssize_t EVENT__ssize_t
121275970Scy#endif
122275970Scy#define ARC4RANDOM_EXPORT static
123275970Scy#define ARC4_LOCK_() EVLOCK_LOCK(arc4rand_lock, 0)
124275970Scy#define ARC4_UNLOCK_() EVLOCK_UNLOCK(arc4rand_lock, 0)
125275970Scy#ifndef EVENT__DISABLE_THREAD_SUPPORT
126275970Scystatic void *arc4rand_lock;
127275970Scy#endif
128275970Scy
129275970Scy#define ARC4RANDOM_UINT32 ev_uint32_t
130275970Scy#define ARC4RANDOM_NOSTIR
131275970Scy#define ARC4RANDOM_NORANDOM
132275970Scy#define ARC4RANDOM_NOUNIFORM
133275970Scy
134275970Scy#include "./arc4random.c"
135275970Scy
136275970Scy#ifndef EVENT__DISABLE_THREAD_SUPPORT
137275970Scyint
138275970Scyevutil_secure_rng_global_setup_locks_(const int enable_locks)
139275970Scy{
140275970Scy	EVTHREAD_SETUP_GLOBAL_LOCK(arc4rand_lock, 0);
141275970Scy	return 0;
142275970Scy}
143275970Scy#endif
144275970Scy
145275970Scystatic void
146275970Scyevutil_free_secure_rng_globals_locks(void)
147275970Scy{
148275970Scy#ifndef EVENT__DISABLE_THREAD_SUPPORT
149275970Scy	if (arc4rand_lock != NULL) {
150275970Scy		EVTHREAD_FREE_LOCK(arc4rand_lock, 0);
151275970Scy		arc4rand_lock = NULL;
152275970Scy	}
153275970Scy#endif
154275970Scy	return;
155275970Scy}
156275970Scy
157275970Scyint
158275970Scyevutil_secure_rng_set_urandom_device_file(char *fname)
159275970Scy{
160275970Scy#ifdef TRY_SEED_URANDOM
161275970Scy	ARC4_LOCK_();
162275970Scy	arc4random_urandom_filename = fname;
163275970Scy	ARC4_UNLOCK_();
164275970Scy#endif
165275970Scy	return 0;
166275970Scy}
167275970Scy
168275970Scyint
169275970Scyevutil_secure_rng_init(void)
170275970Scy{
171275970Scy	int val;
172275970Scy
173275970Scy	ARC4_LOCK_();
174275970Scy	if (!arc4_seeded_ok)
175275970Scy		arc4_stir();
176275970Scy	val = arc4_seeded_ok ? 0 : -1;
177275970Scy	ARC4_UNLOCK_();
178275970Scy	return val;
179275970Scy}
180275970Scy
181275970Scystatic void
182275970Scyev_arc4random_buf(void *buf, size_t n)
183275970Scy{
184275970Scy	arc4random_buf(buf, n);
185275970Scy}
186275970Scy
187275970Scy#endif /* } !EVENT__HAVE_ARC4RANDOM */
188275970Scy
189275970Scyvoid
190275970Scyevutil_secure_rng_get_bytes(void *buf, size_t n)
191275970Scy{
192275970Scy	ev_arc4random_buf(buf, n);
193275970Scy}
194275970Scy
195275970Scyvoid
196275970Scyevutil_secure_rng_add_bytes(const char *buf, size_t n)
197275970Scy{
198275970Scy	arc4random_addrandom((unsigned char*)buf,
199275970Scy	    n>(size_t)INT_MAX ? INT_MAX : (int)n);
200275970Scy}
201275970Scy
202275970Scyvoid
203275970Scyevutil_free_secure_rng_globals_(void)
204275970Scy{
205275970Scy    evutil_free_secure_rng_globals_locks();
206275970Scy}
207