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