xref: /aosp_15_r20/external/boringssl/src/crypto/fipsmodule/rand/urandom_test.cc (revision 8fb009dc861624b67b6cdb62ea21f0f22d0c584b)
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(&regs, child_pid)) {
249     return false;
250   }
251   regs.regs.rax = ret;
252   return ptrace(PTRACE_SETREGS, child_pid, nullptr, &regs.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, &regs) == 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(&regs, child_pid)) {
293     return false;
294   }
295   regs.regs.regs[0] = ret;
296   return set_regset(child_pid, NT_PRSTATUS, &regs.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(&regs, 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, &regs));
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(&regs, child_pid));
597       urandom_fd = regs.ret;
598     } else if (is_socket_call) {
599       ASSERT_TRUE(regs_read(&regs, 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