1 /* Copyright (c) 2019, 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 #include <gtest/gtest.h>
16 #include <stdlib.h>
17
18 #include <openssl/bytestring.h>
19 #include <openssl/ctrdrbg.h>
20 #include <openssl/rand.h>
21
22 #include "getrandom_fillin.h"
23 #include "internal.h"
24
25 #if (defined(OPENSSL_X86_64) || defined(OPENSSL_AARCH64)) && \
26 !defined(BORINGSSL_SHARED_LIBRARY) && defined(OPENSSL_RAND_URANDOM) && \
27 defined(USE_NR_getrandom)
28
29 #include <elf.h>
30 #include <linux/random.h>
31 #include <sys/ptrace.h>
32 #include <sys/socket.h>
33 #include <sys/syscall.h>
34 #include <sys/uio.h>
35 #include <sys/un.h>
36 #include <sys/user.h>
37
38 #include "fork_detect.h"
39 #include "getrandom_fillin.h"
40
41 #if !defined(PTRACE_O_EXITKILL)
42 #define PTRACE_O_EXITKILL (1 << 20)
43 #endif
44
45 #if defined(OPENSSL_ANDROID)
46 static const bool kIsAndroid = true;
47 #else
48 static const bool kIsAndroid = false;
49 #endif
50
51 #if defined(BORINGSSL_FIPS)
52 static const bool kIsFIPS = true;
53 #else
54 static const bool kIsFIPS = false;
55 #endif
56
57 static const bool kUsesDaemon = kIsFIPS && kIsAndroid;
58
59 // kDaemonWriteLength is the number of bytes that the entropy daemon writes.
60 static const size_t kDaemonWriteLength = 496;
61
62 // This test can be run with $OPENSSL_ia32cap=~0x4000000000000000 in order to
63 // simulate the absence of RDRAND of machines that have it.
64
65 // Event represents a system call from urandom.c that is observed by the ptrace
66 // code in |GetTrace|.
67 struct Event {
68 enum class Syscall {
69 kGetRandom,
70 kOpen,
71 kUrandomRead,
72 kSocket,
73 kConnect,
74 kSocketRead,
75 kSocketClose,
76 kAbort,
77 };
78
EventEvent79 explicit Event(Syscall syscall) : type(syscall) {}
80
operator ==Event81 bool operator==(const Event &other) const {
82 return type == other.type && length == other.length &&
83 flags == other.flags &&
84 filename == other.filename;
85 }
86
GetRandomEvent87 static Event GetRandom(size_t length, unsigned flags) {
88 Event e(Syscall::kGetRandom);
89 e.length = length;
90 e.flags = flags;
91 return e;
92 }
93
OpenEvent94 static Event Open(const std::string &filename) {
95 Event e(Syscall::kOpen);
96 e.filename = filename;
97 return e;
98 }
99
UrandomReadEvent100 static Event UrandomRead(size_t length) {
101 Event e(Syscall::kUrandomRead);
102 e.length = length;
103 return e;
104 }
105
SocketEvent106 static Event Socket() {
107 Event e(Syscall::kSocket);
108 return e;
109 }
110
ConnectEvent111 static Event Connect() {
112 Event e(Syscall::kConnect);
113 return e;
114 }
115
SocketReadEvent116 static Event SocketRead(size_t length) {
117 Event e(Syscall::kSocketRead);
118 e.length = length;
119 return e;
120 }
121
SocketCloseEvent122 static Event SocketClose() {
123 Event e(Syscall::kSocketClose);
124 return e;
125 }
126
AbortEvent127 static Event Abort() {
128 Event e(Syscall::kAbort);
129 return e;
130 }
131
StringEvent132 std::string String() const {
133 char buf[256];
134
135 switch (type) {
136 case Syscall::kGetRandom:
137 snprintf(buf, sizeof(buf), "getrandom(_, %zu, %u)", length, flags);
138 break;
139
140 case Syscall::kOpen:
141 snprintf(buf, sizeof(buf), "open(%s, _)", filename.c_str());
142 break;
143
144 case Syscall::kUrandomRead:
145 snprintf(buf, sizeof(buf), "read(urandom_fd, _, %zu)", length);
146 break;
147
148 case Syscall::kSocket:
149 return "socket(UNIX, STREAM, _)";
150
151 case Syscall::kConnect:
152 return "connect(sock, _, _)";
153
154 case Syscall::kSocketRead:
155 snprintf(buf, sizeof(buf), "read(sock_fd, _, %zu)", length);
156 break;
157
158 case Syscall::kSocketClose:
159 return "close(sock)";
160
161 case Syscall::kAbort:
162 return "abort()";
163 }
164
165 return std::string(buf);
166 }
167
168 const Syscall type;
169 size_t length = 0;
170 unsigned flags = 0;
171 std::string filename;
172 };
173
ToString(const std::vector<Event> & trace)174 static std::string ToString(const std::vector<Event> &trace) {
175 std::string ret;
176 for (const auto &event : trace) {
177 if (!ret.empty()) {
178 ret += ", ";
179 }
180 ret += event.String();
181 }
182 return ret;
183 }
184
185 // The following are flags to tell |GetTrace| to inject faults, using ptrace,
186 // into the entropy-related system calls.
187
188 // getrandom gives |ENOSYS|.
189 static const unsigned NO_GETRANDOM = 1;
190 // opening /dev/urandom fails.
191 static const unsigned NO_URANDOM = 2;
192 // getrandom always returns |EAGAIN| if given |GRNG_NONBLOCK|.
193 static const unsigned GETRANDOM_NOT_READY = 4;
194 // getrandom gives |EINVAL| unless |NO_GETRANDOM| is set.
195 static const unsigned GETRANDOM_ERROR = 8;
196 // Reading from /dev/urandom gives |EINVAL|.
197 static const unsigned URANDOM_ERROR = 16;
198 static const unsigned SOCKET_ERROR = 32;
199 static const unsigned CONNECT_ERROR = 64;
200 static const unsigned SOCKET_READ_ERROR = 128;
201 static const unsigned SOCKET_READ_SHORT = 256;
202 static const unsigned NEXT_FLAG = 512;
203
204 // regs_read fetches the registers of |child_pid| and writes them to |out_regs|.
205 // That structure will contain at least the following members:
206 // syscall: the syscall number, if registers were read just before entering
207 // one.
208 // args[0..2]: syscall arguments, if registers were read just before
209 // entering one.
210 // ret: the syscall return value, if registers were read just after finishing
211 // one.
212 //
213 // This call returns true on success and false otherwise.
214 static bool regs_read(struct regs *out_regs, int child_pid);
215
216 // regs_set_ret sets the return value of the system call that |child_pid| has
217 // just finished, to |ret|. It returns true on success and false otherwise.
218 static bool regs_set_ret(int child_pid, int ret);
219
220 // regs_break_syscall causes the system call that |child_pid| is about to enter
221 // to fail to run.
222 static bool regs_break_syscall(int child_pid, const struct regs *orig_regs);
223
224 struct regs {
225 uintptr_t syscall;
226 uintptr_t args[3];
227 uintptr_t ret;
228 struct user_regs_struct regs;
229 };
230
231 #if defined(OPENSSL_X86_64)
232
regs_read(struct regs * out_regs,int child_pid)233 static bool regs_read(struct regs *out_regs, int child_pid) {
234 if (ptrace(PTRACE_GETREGS, child_pid, nullptr, &out_regs->regs) != 0) {
235 return false;
236 }
237
238 out_regs->syscall = out_regs->regs.orig_rax;
239 out_regs->ret = out_regs->regs.rax;
240 out_regs->args[0] = out_regs->regs.rdi;
241 out_regs->args[1] = out_regs->regs.rsi;
242 out_regs->args[2] = out_regs->regs.rdx;
243 return true;
244 }
245
regs_set_ret(int child_pid,int ret)246 static bool regs_set_ret(int child_pid, int ret) {
247 struct regs regs;
248 if (!regs_read(®s, child_pid)) {
249 return false;
250 }
251 regs.regs.rax = ret;
252 return ptrace(PTRACE_SETREGS, child_pid, nullptr, ®s.regs) == 0;
253 }
254
regs_break_syscall(int child_pid,const struct regs * orig_regs)255 static bool regs_break_syscall(int child_pid, const struct regs *orig_regs) {
256 // Replace the syscall number with -1 to cause the kernel to fail the call.
257 struct user_regs_struct regs = orig_regs->regs;
258 regs.orig_rax = -1;
259 return ptrace(PTRACE_SETREGS, child_pid, nullptr, ®s) == 0;
260 }
261
262 #elif defined(OPENSSL_AARCH64)
263
regs_read(struct regs * out_regs,int child_pid)264 static bool regs_read(struct regs *out_regs, int child_pid) {
265 struct iovec io;
266 io.iov_base = &out_regs->regs;
267 io.iov_len = sizeof(out_regs->regs);
268 if (ptrace(PTRACE_GETREGSET, child_pid, NT_PRSTATUS, &io) != 0) {
269 return false;
270 }
271
272 out_regs->syscall = out_regs->regs.regs[8];
273 out_regs->ret = out_regs->regs.regs[0];
274 out_regs->args[0] = out_regs->regs.regs[0];
275 out_regs->args[1] = out_regs->regs.regs[1];
276 out_regs->args[2] = out_regs->regs.regs[2];
277
278 return true;
279 }
280
set_regset(int child_pid,int regset,const void * data,size_t len)281 static bool set_regset(int child_pid, int regset, const void *data,
282 size_t len) {
283 struct iovec io;
284 io.iov_base = const_cast<void *>(data);
285 io.iov_len = len;
286 return ptrace(PTRACE_SETREGSET, child_pid, reinterpret_cast<void *>(regset),
287 &io) == 0;
288 }
289
regs_set_ret(int child_pid,int ret)290 static bool regs_set_ret(int child_pid, int ret) {
291 struct regs regs;
292 if (!regs_read(®s, child_pid)) {
293 return false;
294 }
295 regs.regs.regs[0] = ret;
296 return set_regset(child_pid, NT_PRSTATUS, ®s.regs, sizeof(regs.regs));
297 }
298
regs_break_syscall(int child_pid,const struct regs * orig_regs)299 static bool regs_break_syscall(int child_pid, const struct regs *orig_regs) {
300 // Replace the syscall number with -1 to cause the kernel to fail the call.
301 int syscall = -1;
302 return set_regset(child_pid, NT_ARM_SYSTEM_CALL, &syscall, sizeof(syscall));
303 }
304
305 #endif
306
307 // SyscallResult is like std::optional<int>.
308 // TODO: use std::optional when we can use C++17.
309 class SyscallResult {
310 public:
operator =(int value)311 SyscallResult &operator=(int value) {
312 has_value_ = true;
313 value_ = value;
314 return *this;
315 }
316
value() const317 int value() const {
318 if (!has_value_) {
319 abort();
320 }
321 return value_;
322 }
323
has_value() const324 bool has_value() const { return has_value_; }
325
326 private:
327 bool has_value_ = false;
328 int value_ = 0;
329 };
330
331 // memcpy_to_remote copies |n| bytes from |in_src| in the local address space,
332 // to |dest| in the address space of |child_pid|.
memcpy_to_remote(int child_pid,uint64_t dest,const void * in_src,size_t n)333 static void memcpy_to_remote(int child_pid, uint64_t dest, const void *in_src,
334 size_t n) {
335 const uint8_t *src = reinterpret_cast<const uint8_t *>(in_src);
336
337 // ptrace always works with ill-defined "words", which appear to be 64-bit
338 // on 64-bit systems.
339 #if !defined(OPENSSL_64_BIT)
340 #error "This code probably doesn't work"
341 #endif
342
343 while (n) {
344 const uintptr_t aligned_addr = dest & ~7;
345 const uintptr_t offset = dest - aligned_addr;
346 const size_t space = 8 - offset;
347 size_t todo = n;
348 if (todo > space) {
349 todo = space;
350 }
351
352 uint64_t word;
353 if (offset == 0 && todo == 8) {
354 word = CRYPTO_load_u64_le(src);
355 } else {
356 uint8_t bytes[8];
357 CRYPTO_store_u64_le(
358 bytes, ptrace(PTRACE_PEEKDATA, child_pid,
359 reinterpret_cast<void *>(aligned_addr), nullptr));
360 memcpy(&bytes[offset], src, todo);
361 word = CRYPTO_load_u64_le(bytes);
362 }
363
364 ASSERT_EQ(0, ptrace(PTRACE_POKEDATA, child_pid,
365 reinterpret_cast<void *>(aligned_addr),
366 reinterpret_cast<void *>(word)));
367
368 src += todo;
369 n -= todo;
370 dest += todo;
371 }
372 }
373
get_byte_from_remote(int child_pid,uint64_t ptr)374 static uint8_t get_byte_from_remote(int child_pid, uint64_t ptr) {
375 // ptrace always works with ill-defined "words", which appear to be 64-bit
376 // on 64-bit systems.
377 #if !defined(OPENSSL_64_BIT)
378 #error "This code probably doesn't work"
379 #endif
380
381 const uintptr_t aligned_addr = ptr & ~7;
382 const uintptr_t offset = ptr - aligned_addr;
383
384 uint64_t word = ptrace(PTRACE_PEEKDATA, child_pid,
385 reinterpret_cast<void *>(aligned_addr), 0);
386 uint8_t bytes[8];
387 CRYPTO_store_u64_le(bytes, word);
388 return bytes[offset];
389 }
390
get_string_from_remote(int child_pid,uint64_t ptr)391 static std::string get_string_from_remote(int child_pid, uint64_t ptr) {
392 std::string ret;
393
394 for (;;) {
395 const uint8_t byte = get_byte_from_remote(child_pid, ptr);
396 if (byte == 0) {
397 break;
398 }
399 ret.push_back((char)byte);
400 ptr++;
401 }
402
403 return ret;
404 }
405
406 // GetTrace runs |thunk| in a forked process and observes the resulting system
407 // calls using ptrace. It simulates a variety of failures based on the contents
408 // of |flags| and records the observed events by appending to |out_trace|.
GetTrace(std::vector<Event> * out_trace,unsigned flags,std::function<void ()> thunk)409 static void GetTrace(std::vector<Event> *out_trace, unsigned flags,
410 std::function<void()> thunk) {
411 const int child_pid = fork();
412 ASSERT_NE(-1, child_pid);
413
414 if (child_pid == 0) {
415 // Child process
416 if (ptrace(PTRACE_TRACEME, 0, 0, 0) != 0) {
417 perror("PTRACE_TRACEME");
418 _exit(1);
419 }
420 raise(SIGSTOP);
421 thunk();
422 _exit(0);
423 }
424
425 // Parent process
426 int status;
427 ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
428 ASSERT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP)
429 << "Child was not stopped with SIGSTOP: " << status;
430
431 // Set options so that:
432 // a) the child process is killed once this process dies.
433 // b) System calls result in a WSTOPSIG value of (SIGTRAP | 0x80) rather
434 // than just SIGTRAP. (This doesn't matter here, but it's recommended
435 // practice so that it's distinct from the signal itself.)
436 ASSERT_EQ(0, ptrace(PTRACE_SETOPTIONS, child_pid, nullptr,
437 PTRACE_O_EXITKILL | PTRACE_O_TRACESYSGOOD))
438 << strerror(errno);
439
440 // urandom_fd tracks the file descriptor number for /dev/urandom in the child
441 // process, if it opens it.
442 int urandom_fd = -1;
443
444 // sock_fd tracks the file descriptor number for the socket to the entropy
445 // daemon, if one is opened.
446 int sock_fd = -1;
447
448 for (;;) {
449 // Advance the child to the next system call.
450 ASSERT_EQ(0, ptrace(PTRACE_SYSCALL, child_pid, 0, 0));
451 ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
452
453 // The child may have aborted rather than made a system call.
454 if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGABRT) {
455 out_trace->push_back(Event::Abort());
456 break;
457 }
458
459 // Otherwise the only valid ptrace event is a system call stop.
460 ASSERT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP | 0x80))
461 << "Child was not stopped with a syscall stop: " << status;
462
463 struct regs regs;
464 ASSERT_TRUE(regs_read(®s, child_pid));
465
466 bool is_opening_urandom = false;
467 bool is_socket_call = false;
468 bool is_socket_read = false;
469 uint64_t socket_read_bytes = 0;
470 // force_result is unset to indicate that the system call should run
471 // normally. Otherwise it's, e.g. -EINVAL, to indicate that the system call
472 // should not run and that the given value should be injected on return.
473 SyscallResult force_result;
474
475 switch (regs.syscall) {
476 case __NR_getrandom:
477 if (flags & NO_GETRANDOM) {
478 force_result = -ENOSYS;
479 } else if (flags & GETRANDOM_ERROR) {
480 force_result = -EINVAL;
481 } else if (flags & GETRANDOM_NOT_READY) {
482 if (regs.args[2] & GRND_NONBLOCK) {
483 force_result = -EAGAIN;
484 }
485 }
486 out_trace->push_back(
487 Event::GetRandom(/*length=*/regs.args[1], /*flags=*/regs.args[2]));
488 break;
489
490 case __NR_openat:
491 #if defined(OPENSSL_X86_64)
492 case __NR_open:
493 #endif
494 {
495 uintptr_t filename_ptr =
496 (regs.syscall == __NR_openat) ? regs.args[1] : regs.args[0];
497 const std::string filename = get_string_from_remote(child_pid, filename_ptr);
498 if (filename.find("/dev/__properties__/") == 0) {
499 // Android may try opening these files as part of SELinux support.
500 // They are ignored here.
501 } else {
502 out_trace->push_back(Event::Open(filename));
503 }
504 is_opening_urandom = (filename == "/dev/urandom");
505 if (is_opening_urandom && (flags & NO_URANDOM)) {
506 force_result = -ENOENT;
507 }
508 break;
509 }
510
511 case __NR_read: {
512 const int read_fd = regs.args[0];
513 if (urandom_fd >= 0 && urandom_fd == read_fd) {
514 out_trace->push_back(Event::UrandomRead(/*length=*/regs.args[2]));
515 if (flags & URANDOM_ERROR) {
516 force_result = -EINVAL;
517 }
518 } else if (sock_fd >= 0 && sock_fd == read_fd) {
519 uint64_t length = regs.args[2];
520 out_trace->push_back(Event::SocketRead(length));
521 if (flags & SOCKET_READ_ERROR) {
522 force_result = -EINVAL;
523 } else {
524 is_socket_read = true;
525 socket_read_bytes = length;
526
527 if (flags & SOCKET_READ_SHORT) {
528 ASSERT_GT(socket_read_bytes, 0u);
529 socket_read_bytes--;
530 flags &= ~SOCKET_READ_SHORT;
531 }
532 }
533 }
534 break;
535 }
536
537 case __NR_close: {
538 if (sock_fd >= 0 && static_cast<int>(regs.args[0]) == sock_fd) {
539 out_trace->push_back(Event::SocketClose());
540 sock_fd = -1;
541 }
542 break;
543 }
544
545 case __NR_socket: {
546 const int family = regs.args[0];
547 const int type = regs.args[1];
548 if (family == AF_UNIX && type == SOCK_STREAM) {
549 out_trace->push_back(Event::Socket());
550 is_socket_call = true;
551 if (flags & SOCKET_ERROR) {
552 force_result = -EINVAL;
553 }
554 }
555 break;
556 }
557
558 case __NR_connect: {
559 const int connect_fd = regs.args[0];
560 if (sock_fd >= 0 && connect_fd == sock_fd) {
561 out_trace->push_back(Event::Connect());
562 if (flags & CONNECT_ERROR) {
563 force_result = -EINVAL;
564 } else {
565 // The test system might not have an entropy daemon running so
566 // inject a success result.
567 force_result = 0;
568 }
569 }
570
571 break;
572 }
573 }
574
575 if (force_result.has_value()) {
576 ASSERT_TRUE(regs_break_syscall(child_pid, ®s));
577 }
578
579 ASSERT_EQ(0, ptrace(PTRACE_SYSCALL, child_pid, 0, 0));
580 ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
581 // If the system call was exit/exit_group, the process may be terminated
582 // rather than have exited the system call.
583 if (WIFEXITED(status)) {
584 ASSERT_EQ(0, WEXITSTATUS(status));
585 return;
586 }
587
588 // Otherwise the next state must be a system call exit stop. This is
589 // indistinguishable from a system call entry, we just have to keep track
590 // and know that these events happen in pairs.
591 ASSERT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP | 0x80));
592
593 if (force_result.has_value()) {
594 ASSERT_TRUE(regs_set_ret(child_pid, force_result.value()));
595 } else if (is_opening_urandom) {
596 ASSERT_TRUE(regs_read(®s, child_pid));
597 urandom_fd = regs.ret;
598 } else if (is_socket_call) {
599 ASSERT_TRUE(regs_read(®s, child_pid));
600 sock_fd = regs.ret;
601 } else if (is_socket_read) {
602 // Simulate a response from the entropy daemon since it might not be
603 // running on the current system.
604 uint8_t entropy[kDaemonWriteLength];
605 ASSERT_LE(socket_read_bytes, sizeof(entropy));
606
607 for (size_t i = 0; i < sizeof(entropy); i++) {
608 entropy[i] = i & 0xff;
609 }
610 memcpy_to_remote(child_pid, regs.args[1], entropy, socket_read_bytes);
611
612 ASSERT_TRUE(regs_set_ret(child_pid, socket_read_bytes));
613 }
614 }
615 }
616
617 // TestFunction is the function that |GetTrace| is asked to trace.
TestFunction()618 static void TestFunction() {
619 uint8_t byte;
620 RAND_bytes(&byte, sizeof(byte));
621 RAND_bytes(&byte, sizeof(byte));
622 }
623
have_fork_detection()624 static bool have_fork_detection() { return CRYPTO_get_fork_generation() != 0; }
625
AppendDaemonEvents(std::vector<Event> * events,unsigned flags)626 static bool AppendDaemonEvents(std::vector<Event> *events, unsigned flags) {
627 events->push_back(Event::Socket());
628 if (flags & SOCKET_ERROR) {
629 return false;
630 }
631
632 bool ret = false;
633 events->push_back(Event::Connect());
634 if (flags & CONNECT_ERROR) {
635 goto out;
636 }
637
638 events->push_back(Event::SocketRead(kDaemonWriteLength));
639 if (flags & SOCKET_READ_ERROR) {
640 goto out;
641 }
642
643 if (flags & SOCKET_READ_SHORT) {
644 events->push_back(Event::SocketRead(1));
645 }
646
647 ret = true;
648
649 out:
650 events->push_back(Event::SocketClose());
651 return ret;
652 }
653
654 // TestFunctionPRNGModel is a model of how the urandom.c code will behave when
655 // |TestFunction| is run. It should return the same trace of events that
656 // |GetTrace| will observe the real code making.
TestFunctionPRNGModel(unsigned flags)657 static std::vector<Event> TestFunctionPRNGModel(unsigned flags) {
658 std::vector<Event> ret;
659 bool getrandom_ready = false;
660 bool used_daemon = false;
661
662 if (have_fork_detection()) {
663 used_daemon = kUsesDaemon && AppendDaemonEvents(&ret, flags);
664 }
665
666 // Probe for getrandom support
667 ret.push_back(Event::GetRandom(1, GRND_NONBLOCK));
668 std::function<void()> wait_for_entropy;
669 std::function<bool(bool, size_t)> sysrand;
670
671 if (flags & NO_GETRANDOM) {
672 if (kIsFIPS) {
673 // FIPS builds require getrandom.
674 ret.push_back(Event::Abort());
675 return ret;
676 }
677
678 ret.push_back(Event::Open("/dev/urandom"));
679 if (flags & NO_URANDOM) {
680 ret.push_back(Event::Abort());
681 return ret;
682 }
683
684 sysrand = [&ret, flags](bool block, size_t len) {
685 ret.push_back(Event::UrandomRead(len));
686 if (flags & URANDOM_ERROR) {
687 ret.push_back(Event::Abort());
688 return false;
689 }
690 return true;
691 };
692 } else {
693 if (flags & GETRANDOM_ERROR) {
694 ret.push_back(Event::Abort());
695 return ret;
696 }
697
698 getrandom_ready = (flags & GETRANDOM_NOT_READY) == 0;
699 wait_for_entropy = [&ret, &getrandom_ready] {
700 if (getrandom_ready) {
701 return;
702 }
703
704 ret.push_back(Event::GetRandom(1, GRND_NONBLOCK));
705 ret.push_back(Event::GetRandom(1, 0));
706 getrandom_ready = true;
707 };
708 sysrand = [&ret, &wait_for_entropy](bool block, size_t len) {
709 if (block) {
710 wait_for_entropy();
711 }
712 ret.push_back(Event::GetRandom(len, block ? 0 : GRND_NONBLOCK));
713 return true;
714 };
715 }
716
717 const size_t kSeedLength = CTR_DRBG_ENTROPY_LEN * (kIsFIPS ? 10 : 1);
718 const size_t kAdditionalDataLength = 32;
719
720 if (!have_rdrand()) {
721 if (!have_fork_detection()) {
722 if (!sysrand(true, kAdditionalDataLength)) {
723 return ret;
724 }
725 used_daemon = kUsesDaemon && AppendDaemonEvents(&ret, flags);
726 }
727 if (// Initialise CRNGT.
728 (!used_daemon && !sysrand(true, kSeedLength + (kIsFIPS ? 16 : 0))) ||
729 // Personalisation draw if the daemon was used.
730 (used_daemon && !sysrand(false, CTR_DRBG_ENTROPY_LEN)) ||
731 // Second entropy draw.
732 (!have_fork_detection() && !sysrand(true, kAdditionalDataLength))) {
733 return ret;
734 }
735 } else if (
736 // First additional data. If fast RDRAND isn't available then a
737 // non-blocking OS entropy draw will be tried.
738 (!have_fast_rdrand() && !have_fork_detection() &&
739 !sysrand(false, kAdditionalDataLength)) ||
740 // Opportuntistic entropy draw in FIPS mode because RDRAND was used.
741 // In non-FIPS mode it's just drawn from |CRYPTO_sysrand| in a blocking
742 // way.
743 !sysrand(!kIsFIPS, CTR_DRBG_ENTROPY_LEN) ||
744 // Second entropy draw's additional data.
745 (!have_fast_rdrand() && !have_fork_detection() &&
746 !sysrand(false, kAdditionalDataLength))) {
747 return ret;
748 }
749
750 return ret;
751 }
752
CheckInvariants(const std::vector<Event> & events)753 static void CheckInvariants(const std::vector<Event> &events) {
754 // If RDRAND is available then there should be no blocking syscalls in FIPS
755 // mode.
756 #if defined(BORINGSSL_FIPS)
757 if (have_rdrand()) {
758 for (const auto &event : events) {
759 switch (event.type) {
760 case Event::Syscall::kGetRandom:
761 if ((event.flags & GRND_NONBLOCK) == 0) {
762 ADD_FAILURE() << "Blocking getrandom found with RDRAND: "
763 << ToString(events);
764 }
765 break;
766
767 default:
768 break;
769 }
770 }
771 }
772 #endif
773 }
774
775 // Tests that |TestFunctionPRNGModel| is a correct model for the code in
776 // urandom.c, at least to the limits of the the |Event| type.
TEST(URandomTest,Test)777 TEST(URandomTest, Test) {
778 char buf[256];
779
780 // Some Android systems lack getrandom.
781 uint8_t scratch[1];
782 const bool has_getrandom =
783 (syscall(__NR_getrandom, scratch, sizeof(scratch), GRND_NONBLOCK) != -1 ||
784 errno != ENOSYS);
785
786 #define TRACE_FLAG(flag) \
787 snprintf(buf, sizeof(buf), #flag ": %d", (flags & flag) != 0); \
788 SCOPED_TRACE(buf);
789
790 for (unsigned flags = 0; flags < NEXT_FLAG; flags++) {
791 if (!kUsesDaemon && (flags & (SOCKET_ERROR | CONNECT_ERROR |
792 SOCKET_READ_ERROR | SOCKET_READ_SHORT))) {
793 // These cases are meaningless unless the code will try to use the entropy
794 // daemon.
795 continue;
796 }
797
798 if (!has_getrandom && !(flags & NO_GETRANDOM)) {
799 continue;
800 }
801
802 TRACE_FLAG(NO_GETRANDOM);
803 TRACE_FLAG(NO_URANDOM);
804 TRACE_FLAG(GETRANDOM_NOT_READY);
805 TRACE_FLAG(GETRANDOM_ERROR);
806 TRACE_FLAG(URANDOM_ERROR);
807 TRACE_FLAG(SOCKET_ERROR);
808 TRACE_FLAG(CONNECT_ERROR);
809 TRACE_FLAG(SOCKET_READ_ERROR);
810 TRACE_FLAG(SOCKET_READ_SHORT);
811
812 const std::vector<Event> expected_trace = TestFunctionPRNGModel(flags);
813 CheckInvariants(expected_trace);
814 std::vector<Event> actual_trace;
815 GetTrace(&actual_trace, flags, TestFunction);
816
817 if (expected_trace != actual_trace) {
818 ADD_FAILURE() << "Expected: " << ToString(expected_trace)
819 << "\nFound: " << ToString(actual_trace);
820 }
821 }
822 }
823
main(int argc,char ** argv)824 int main(int argc, char **argv) {
825 ::testing::InitGoogleTest(&argc, argv);
826
827 if (getenv("BORINGSSL_IGNORE_MADV_WIPEONFORK")) {
828 CRYPTO_fork_detect_force_madv_wipeonfork_for_testing(0);
829 } else {
830 CRYPTO_fork_detect_force_madv_wipeonfork_for_testing(1);
831 }
832
833 return RUN_ALL_TESTS();
834 }
835
836 #else
837
main(int argc,char ** argv)838 int main(int argc, char **argv) {
839 printf("PASS\n");
840 return 0;
841 }
842
843 #endif // (X86_64 || AARCH64) && !SHARED_LIBRARY &&
844 // !UNSAFE_DETERMINISTIC_MODE && USE_NR_getrandom
845