1 | /* Copyright (c) 2014, Google Inc. |
2 | * |
3 | * Permission to use, copy, modify, and/or distribute this software for any |
4 | * purpose with or without fee is hereby granted, provided that the above |
5 | * copyright notice and this permission notice appear in all copies. |
6 | * |
7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
8 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
9 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
10 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
11 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
12 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
13 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ |
14 | |
15 | #if !defined(_GNU_SOURCE) |
16 | #define _GNU_SOURCE // needed for syscall() on Linux. |
17 | #endif |
18 | |
19 | #include <openssl/rand.h> |
20 | |
21 | #if !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_FUCHSIA) && \ |
22 | !defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE) && !defined(OPENSSL_TRUSTY) |
23 | |
24 | #include <assert.h> |
25 | #include <errno.h> |
26 | #include <fcntl.h> |
27 | #include <stdio.h> |
28 | #include <string.h> |
29 | #include <unistd.h> |
30 | |
31 | #if defined(OPENSSL_LINUX) |
32 | #if defined(BORINGSSL_FIPS) |
33 | #include <linux/random.h> |
34 | #include <sys/ioctl.h> |
35 | #endif |
36 | #include <sys/syscall.h> |
37 | |
38 | #if !defined(OPENSSL_ANDROID) |
39 | #define OPENSSL_HAS_GETAUXVAL |
40 | #endif |
41 | // glibc prior to 2.16 does not have getauxval and sys/auxv.h. Android has some |
42 | // host builds (i.e. not building for Android itself, so |OPENSSL_ANDROID| is |
43 | // unset) which are still using a 2.15 sysroot. |
44 | // |
45 | // TODO(davidben): Remove this once Android updates their sysroot. |
46 | #if defined(__GLIBC_PREREQ) |
47 | #if !__GLIBC_PREREQ(2, 16) |
48 | #undef OPENSSL_HAS_GETAUXVAL |
49 | #endif |
50 | #endif |
51 | #if defined(OPENSSL_HAS_GETAUXVAL) |
52 | #include <sys/auxv.h> |
53 | #endif |
54 | #endif // OPENSSL_LINUX |
55 | |
56 | #include <openssl/thread.h> |
57 | #include <openssl/mem.h> |
58 | |
59 | #include "internal.h" |
60 | #include "../delocate.h" |
61 | #include "../../internal.h" |
62 | |
63 | |
64 | #if defined(OPENSSL_LINUX) |
65 | |
66 | #if defined(OPENSSL_X86_64) |
67 | #define EXPECTED_NR_getrandom 318 |
68 | #elif defined(OPENSSL_X86) |
69 | #define EXPECTED_NR_getrandom 355 |
70 | #elif defined(OPENSSL_AARCH64) |
71 | #define EXPECTED_NR_getrandom 278 |
72 | #elif defined(OPENSSL_ARM) |
73 | #define EXPECTED_NR_getrandom 384 |
74 | #elif defined(OPENSSL_PPC64LE) |
75 | #define EXPECTED_NR_getrandom 359 |
76 | #endif |
77 | |
78 | #if defined(EXPECTED_NR_getrandom) |
79 | #define USE_NR_getrandom |
80 | |
81 | #if defined(__NR_getrandom) |
82 | |
83 | #if __NR_getrandom != EXPECTED_NR_getrandom |
84 | #error "system call number for getrandom is not the expected value" |
85 | #endif |
86 | |
87 | #else // __NR_getrandom |
88 | |
89 | #define __NR_getrandom EXPECTED_NR_getrandom |
90 | |
91 | #endif // __NR_getrandom |
92 | |
93 | #if defined(OPENSSL_MSAN) |
94 | void __msan_unpoison(void *, size_t); |
95 | #endif |
96 | |
97 | static ssize_t boringssl_getrandom(void *buf, size_t buf_len, unsigned flags) { |
98 | ssize_t ret; |
99 | do { |
100 | ret = syscall(__NR_getrandom, buf, buf_len, flags); |
101 | } while (ret == -1 && errno == EINTR); |
102 | |
103 | #if defined(OPENSSL_MSAN) |
104 | if (ret > 0) { |
105 | // MSAN doesn't recognise |syscall| and thus doesn't notice that we have |
106 | // initialised the output buffer. |
107 | __msan_unpoison(buf, ret); |
108 | } |
109 | #endif // OPENSSL_MSAN |
110 | |
111 | return ret; |
112 | } |
113 | |
114 | #endif // EXPECTED_NR_getrandom |
115 | |
116 | #if !defined(GRND_NONBLOCK) |
117 | #define GRND_NONBLOCK 1 |
118 | #endif |
119 | |
120 | #endif // OPENSSL_LINUX |
121 | |
122 | // rand_lock is used to protect the |*_requested| variables. |
123 | DEFINE_STATIC_MUTEX(rand_lock) |
124 | |
125 | // The following constants are magic values of |urandom_fd|. |
126 | static const int kUnset = 0; |
127 | static const int kHaveGetrandom = -3; |
128 | |
129 | // urandom_fd_requested is set by |RAND_set_urandom_fd|. It's protected by |
130 | // |rand_lock|. |
131 | DEFINE_BSS_GET(int, urandom_fd_requested) |
132 | |
133 | // urandom_fd is a file descriptor to /dev/urandom. It's protected by |once|. |
134 | DEFINE_BSS_GET(int, urandom_fd) |
135 | |
136 | DEFINE_STATIC_ONCE(rand_once) |
137 | |
138 | // init_once initializes the state of this module to values previously |
139 | // requested. This is the only function that modifies |urandom_fd| and |
140 | // |urandom_buffering|, whose values may be read safely after calling the |
141 | // once. |
142 | static void init_once(void) { |
143 | CRYPTO_STATIC_MUTEX_lock_read(rand_lock_bss_get()); |
144 | int fd = *urandom_fd_requested_bss_get(); |
145 | CRYPTO_STATIC_MUTEX_unlock_read(rand_lock_bss_get()); |
146 | |
147 | #if defined(USE_NR_getrandom) |
148 | uint8_t dummy; |
149 | ssize_t getrandom_ret = |
150 | boringssl_getrandom(&dummy, sizeof(dummy), GRND_NONBLOCK); |
151 | |
152 | if (getrandom_ret == -1 && errno == EAGAIN) { |
153 | // Attempt to get the path of the current process to aid in debugging when |
154 | // something blocks. |
155 | const char *current_process = "<unknown>" ; |
156 | #if defined(OPENSSL_HAS_GETAUXVAL) |
157 | const unsigned long getauxval_ret = getauxval(AT_EXECFN); |
158 | if (getauxval_ret != 0) { |
159 | current_process = (const char *)getauxval_ret; |
160 | } |
161 | #endif |
162 | |
163 | fprintf(stderr, |
164 | "%s: getrandom indicates that the entropy pool has not been " |
165 | "initialized. Rather than continue with poor entropy, this process " |
166 | "will block until entropy is available.\n" , |
167 | current_process); |
168 | |
169 | getrandom_ret = |
170 | boringssl_getrandom(&dummy, sizeof(dummy), 0 /* no flags */); |
171 | } |
172 | |
173 | if (getrandom_ret == 1) { |
174 | *urandom_fd_bss_get() = kHaveGetrandom; |
175 | return; |
176 | } |
177 | |
178 | // Ignore ENOSYS and fallthrough to using /dev/urandom, below. Otherwise it's |
179 | // a fatal error. |
180 | if (getrandom_ret != -1 || errno != ENOSYS) { |
181 | perror("getrandom" ); |
182 | abort(); |
183 | } |
184 | #endif // USE_NR_getrandom |
185 | |
186 | if (fd == kUnset) { |
187 | do { |
188 | fd = open("/dev/urandom" , O_RDONLY); |
189 | } while (fd == -1 && errno == EINTR); |
190 | } |
191 | |
192 | if (fd < 0) { |
193 | perror("failed to open /dev/urandom" ); |
194 | abort(); |
195 | } |
196 | |
197 | assert(kUnset == 0); |
198 | if (fd == kUnset) { |
199 | // Because we want to keep |urandom_fd| in the BSS, we have to initialise |
200 | // it to zero. But zero is a valid file descriptor too. Thus if open |
201 | // returns zero for /dev/urandom, we dup it to get a non-zero number. |
202 | fd = dup(fd); |
203 | close(kUnset); |
204 | |
205 | if (fd <= 0) { |
206 | perror("failed to dup /dev/urandom fd" ); |
207 | abort(); |
208 | } |
209 | } |
210 | |
211 | #if defined(BORINGSSL_FIPS) |
212 | // In FIPS mode we ensure that the kernel has sufficient entropy before |
213 | // continuing. This is automatically handled by getrandom, which requires |
214 | // that the entropy pool has been initialised, but for urandom we have to |
215 | // poll. |
216 | for (;;) { |
217 | int entropy_bits; |
218 | if (ioctl(fd, RNDGETENTCNT, &entropy_bits)) { |
219 | fprintf(stderr, |
220 | "RNDGETENTCNT on /dev/urandom failed. We cannot continue in this " |
221 | "case when in FIPS mode.\n" ); |
222 | abort(); |
223 | } |
224 | |
225 | static const int kBitsNeeded = 256; |
226 | if (entropy_bits >= kBitsNeeded) { |
227 | break; |
228 | } |
229 | |
230 | usleep(250000); |
231 | } |
232 | #endif |
233 | |
234 | int flags = fcntl(fd, F_GETFD); |
235 | if (flags == -1) { |
236 | // Native Client doesn't implement |fcntl|. |
237 | if (errno != ENOSYS) { |
238 | perror("failed to get flags from urandom fd" ); |
239 | abort(); |
240 | } |
241 | } else { |
242 | flags |= FD_CLOEXEC; |
243 | if (fcntl(fd, F_SETFD, flags) == -1) { |
244 | perror("failed to set FD_CLOEXEC on urandom fd" ); |
245 | abort(); |
246 | } |
247 | } |
248 | *urandom_fd_bss_get() = fd; |
249 | } |
250 | |
251 | void RAND_set_urandom_fd(int fd) { |
252 | fd = dup(fd); |
253 | if (fd < 0) { |
254 | perror("failed to dup supplied urandom fd" ); |
255 | abort(); |
256 | } |
257 | |
258 | assert(kUnset == 0); |
259 | if (fd == kUnset) { |
260 | // Because we want to keep |urandom_fd| in the BSS, we have to initialise |
261 | // it to zero. But zero is a valid file descriptor too. Thus if dup |
262 | // returned zero we dup it again to get a non-zero number. |
263 | fd = dup(fd); |
264 | close(kUnset); |
265 | |
266 | if (fd <= 0) { |
267 | perror("failed to dup supplied urandom fd" ); |
268 | abort(); |
269 | } |
270 | } |
271 | |
272 | CRYPTO_STATIC_MUTEX_lock_write(rand_lock_bss_get()); |
273 | *urandom_fd_requested_bss_get() = fd; |
274 | CRYPTO_STATIC_MUTEX_unlock_write(rand_lock_bss_get()); |
275 | |
276 | CRYPTO_once(rand_once_bss_get(), init_once); |
277 | if (*urandom_fd_bss_get() == kHaveGetrandom) { |
278 | close(fd); |
279 | } else if (*urandom_fd_bss_get() != fd) { |
280 | fprintf(stderr, "RAND_set_urandom_fd called after initialisation.\n" ); |
281 | abort(); |
282 | } |
283 | } |
284 | |
285 | // fill_with_entropy writes |len| bytes of entropy into |out|. It returns one |
286 | // on success and zero on error. |
287 | static char fill_with_entropy(uint8_t *out, size_t len) { |
288 | while (len > 0) { |
289 | ssize_t r; |
290 | |
291 | if (*urandom_fd_bss_get() == kHaveGetrandom) { |
292 | #if defined(USE_NR_getrandom) |
293 | r = boringssl_getrandom(out, len, 0 /* no flags */); |
294 | #else // USE_NR_getrandom |
295 | fprintf(stderr, "urandom fd corrupt.\n" ); |
296 | abort(); |
297 | #endif |
298 | } else { |
299 | do { |
300 | r = read(*urandom_fd_bss_get(), out, len); |
301 | } while (r == -1 && errno == EINTR); |
302 | } |
303 | |
304 | if (r <= 0) { |
305 | return 0; |
306 | } |
307 | out += r; |
308 | len -= r; |
309 | } |
310 | |
311 | return 1; |
312 | } |
313 | |
314 | // CRYPTO_sysrand puts |requested| random bytes into |out|. |
315 | void CRYPTO_sysrand(uint8_t *out, size_t requested) { |
316 | if (requested == 0) { |
317 | return; |
318 | } |
319 | |
320 | CRYPTO_once(rand_once_bss_get(), init_once); |
321 | |
322 | if (!fill_with_entropy(out, requested)) { |
323 | perror("entropy fill failed" ); |
324 | abort(); |
325 | } |
326 | |
327 | #if defined(BORINGSSL_FIPS_BREAK_CRNG) |
328 | // This breaks the "continuous random number generator test" defined in FIPS |
329 | // 140-2, section 4.9.2, and implemented in rand_get_seed(). |
330 | OPENSSL_memset(out, 0, requested); |
331 | #endif |
332 | } |
333 | |
334 | #endif /* !OPENSSL_WINDOWS && !defined(OPENSSL_FUCHSIA) && \ |
335 | !BORINGSSL_UNSAFE_DETERMINISTIC_MODE && !OPENSSL_TRUSTY */ |
336 | |