Require getrandom in all FIPS builds.

It is now 2022. See if we can assume getrandom in this configuration.

Update-Note: The /dev/urandom fallback is no longer available in FIPS
builds. This fallback relied on RNGGETENTCNT and was quite flaky.

Change-Id: Icf6d29f6d5952fb6c5656c9039a4cfaf1de2d724
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/54127
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/fipsmodule/rand/urandom.c b/crypto/fipsmodule/rand/urandom.c
index 11f1b5b..77dad74 100644
--- a/crypto/fipsmodule/rand/urandom.c
+++ b/crypto/fipsmodule/rand/urandom.c
@@ -62,14 +62,11 @@
 #include <sys/random.h>
 #endif
 
-#if defined(OPENSSL_FREEBSD)
-#define URANDOM_BLOCKS_FOR_ENTROPY
-#if __FreeBSD__ >= 12
+#if defined(OPENSSL_FREEBSD) && __FreeBSD__ >= 12
 // getrandom is supported in FreeBSD 12 and up.
 #define FREEBSD_GETRANDOM
 #include <sys/random.h>
 #endif
-#endif
 
 #include <openssl/thread.h>
 #include <openssl/mem.h>
@@ -190,8 +187,14 @@
   return;
 #endif
 
-  // Android FIPS builds must support getrandom.
-#if defined(BORINGSSL_FIPS) && defined(OPENSSL_ANDROID)
+  // FIPS builds must support getrandom.
+  //
+  // Historically, only Android FIPS builds required getrandom, while Linux FIPS
+  // builds had a /dev/urandom fallback which used RNDGETENTCNT as a poor
+  // approximation for getrandom's blocking behavior. This is now removed, but
+  // avoid making assumptions on this removal until March 2023, in case it needs
+  // to be restored. This comment can be deleted after March 2023.
+#if defined(BORINGSSL_FIPS)
   perror("getrandom not found");
   abort();
 #endif
@@ -255,29 +258,6 @@
 #endif  // USE_NR_getrandom
     return;
   }
-
-#if defined(BORINGSSL_FIPS) && !defined(URANDOM_BLOCKS_FOR_ENTROPY)
-  // In FIPS mode on platforms where urandom doesn't block at startup, we ensure
-  // that the kernel has sufficient entropy before continuing. This is
-  // automatically handled by getrandom, which requires that the entropy pool
-  // has been initialised, but for urandom we have to poll.
-  for (;;) {
-    int entropy_bits;
-    if (ioctl(fd, RNDGETENTCNT, &entropy_bits)) {
-      fprintf(stderr,
-              "RNDGETENTCNT on /dev/urandom failed. We cannot continue in this "
-              "case when in FIPS mode.\n");
-      abort();
-    }
-
-    static const int kBitsNeeded = 256;
-    if (entropy_bits >= kBitsNeeded) {
-      break;
-    }
-
-    usleep(250000);
-  }
-#endif  // BORINGSSL_FIPS && !URANDOM_BLOCKS_FOR_ENTROPY
 }
 
 // fill_with_entropy writes |len| bytes of entropy into |out|. It returns one
diff --git a/crypto/fipsmodule/rand/urandom_test.cc b/crypto/fipsmodule/rand/urandom_test.cc
index dabaf39..13ac610 100644
--- a/crypto/fipsmodule/rand/urandom_test.cc
+++ b/crypto/fipsmodule/rand/urandom_test.cc
@@ -45,7 +45,6 @@
     kGetRandom,
     kOpen,
     kUrandomRead,
-    kUrandomIoctl,
     kAbort,
   };
 
@@ -77,11 +76,6 @@
     return e;
   }
 
-  static Event UrandomIoctl() {
-    Event e(Syscall::kUrandomIoctl);
-    return e;
-  }
-
   static Event Abort() {
     Event e(Syscall::kAbort);
     return e;
@@ -103,9 +97,6 @@
         snprintf(buf, sizeof(buf), "read(urandom_fd, _, %zu)", length);
         break;
 
-      case Syscall::kUrandomIoctl:
-        return "ioctl(urandom_fd, RNDGETENTCNT, _)";
-
       case Syscall::kAbort:
         return "abort()";
     }
@@ -139,14 +130,11 @@
 static const unsigned NO_URANDOM = 2;
 // getrandom always returns |EAGAIN| if given |GRNG_NONBLOCK|.
 static const unsigned GETRANDOM_NOT_READY = 4;
-// The ioctl on urandom returns only 255 bits of entropy the first time that
-// it's called.
-static const unsigned URANDOM_NOT_READY = 8;
 // getrandom gives |EINVAL| unless |NO_GETRANDOM| is set.
-static const unsigned GETRANDOM_ERROR = 16;
+static const unsigned GETRANDOM_ERROR = 8;
 // Reading from /dev/urandom gives |EINVAL|.
-static const unsigned URANDOM_ERROR = 32;
-static const unsigned NEXT_FLAG = 64;
+static const unsigned URANDOM_ERROR = 16;
+static const unsigned NEXT_FLAG = 32;
 
 // GetTrace runs |thunk| in a forked process and observes the resulting system
 // calls using ptrace. It simulates a variety of failures based on the contents
@@ -204,8 +192,6 @@
     const auto syscall_number = regs.orig_rax;
 
     bool is_opening_urandom = false;
-    bool is_urandom_ioctl = false;
-    uintptr_t ioctl_output_addr = 0;
     // inject_error is zero to indicate that the system call should run
     // normally. Otherwise it's, e.g. -EINVAL, to indicate that the system call
     // should not run and that error should be injected on return.
@@ -251,16 +237,6 @@
         }
         break;
       }
-
-      case __NR_ioctl: {
-        const int ioctl_fd = regs.rdi;
-        if (urandom_fd >= 0 && ioctl_fd == urandom_fd &&
-            regs.rsi == RNDGETENTCNT) {
-          out_trace->push_back(Event::UrandomIoctl());
-          is_urandom_ioctl = true;
-          ioctl_output_addr = regs.rdx;
-        }
-      }
     }
 
     if (inject_error) {
@@ -294,33 +270,6 @@
     } else if (is_opening_urandom) {
       ASSERT_EQ(0, ptrace(PTRACE_GETREGS, child_pid, nullptr, &regs));
       urandom_fd = regs.rax;
-    } else if (is_urandom_ioctl) {
-      // The result is the number of bits of entropy that the kernel currently
-      // believes that it has. urandom.c waits until 256 bits are ready.
-      int result = 256;
-
-      // If we are simulating urandom not being ready then we have the ioctl
-      // indicate one too few bits of entropy the first time it's queried.
-      if (flags & URANDOM_NOT_READY) {
-        result--;
-        flags &= ~URANDOM_NOT_READY;
-      }
-
-      // ptrace always works with ill-defined "words", which appear to be 64-bit
-      // on x86-64. Since the ioctl result is a 32-bit int, do a
-      // read-modify-write to inject the answer.
-      const uintptr_t aligned_addr = ioctl_output_addr & ~7;
-      const uintptr_t offset = ioctl_output_addr - aligned_addr;
-      union {
-        uint64_t word;
-        uint8_t bytes[8];
-      } u;
-      u.word = ptrace(PTRACE_PEEKDATA, child_pid,
-                      reinterpret_cast<void *>(aligned_addr), nullptr);
-      memcpy(&u.bytes[offset], &result, sizeof(result));
-      ASSERT_EQ(0, ptrace(PTRACE_POKEDATA, child_pid,
-                          reinterpret_cast<void *>(aligned_addr),
-                          reinterpret_cast<void *>(u.word)));
     }
   }
 }
@@ -347,7 +296,6 @@
 #endif
 
   std::vector<Event> ret;
-  bool urandom_probed = false;
   bool getrandom_ready = false;
 
   // Probe for getrandom support
@@ -356,32 +304,19 @@
   std::function<bool(bool, size_t)> sysrand;
 
   if (flags & NO_GETRANDOM) {
+    if (is_fips) {
+      // FIPS builds require getrandom.
+      ret.push_back(Event::Abort());
+      return ret;
+    }
+
     ret.push_back(Event::Open("/dev/urandom"));
     if (flags & NO_URANDOM) {
       ret.push_back(Event::Abort());
       return ret;
     }
 
-    wait_for_entropy = [&ret, &urandom_probed, flags] {
-      if (!is_fips || urandom_probed) {
-        return;
-      }
-
-      // Probe urandom for entropy.
-      ret.push_back(Event::UrandomIoctl());
-      if (flags & URANDOM_NOT_READY) {
-        // If the first attempt doesn't report enough entropy, probe
-        // repeatedly until it does, which will happen with the second attempt.
-        ret.push_back(Event::UrandomIoctl());
-      }
-
-      urandom_probed = true;
-    };
-
-    sysrand = [&ret, &wait_for_entropy, flags](bool block, size_t len) {
-      if (block) {
-        wait_for_entropy();
-      }
+    sysrand = [&ret, flags](bool block, size_t len) {
       ret.push_back(Event::UrandomRead(len));
       if (flags & URANDOM_ERROR) {
         ret.push_back(Event::Abort());
@@ -457,11 +392,6 @@
           }
           break;
 
-        case Event::Syscall::kUrandomIoctl:
-          ADD_FAILURE() << "Urandom polling found with RDRAND: "
-                        << ToString(events);
-          break;
-
         default:
           break;
       }
@@ -483,7 +413,6 @@
     TRACE_FLAG(NO_GETRANDOM);
     TRACE_FLAG(NO_URANDOM);
     TRACE_FLAG(GETRANDOM_NOT_READY);
-    TRACE_FLAG(URANDOM_NOT_READY);
     TRACE_FLAG(GETRANDOM_ERROR);
     TRACE_FLAG(URANDOM_ERROR);