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(&regs, child_pid)) {
255     return false;
256   }
257   regs.regs.rax = ret;
258   return ptrace(PTRACE_SETREGS, child_pid, nullptr, &regs.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, &regs) == 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(&regs, child_pid)) {
299     return false;
300   }
301   regs.regs.regs[0] = ret;
302   return set_regset(child_pid, NT_PRSTATUS, &regs.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(&regs, 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, &regs));
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(&regs, child_pid));
580       urandom_fd = regs.ret;
581     } else if (is_socket_call) {
582       ASSERT_TRUE(regs_read(&regs, 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