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