Add RNG support for FreeBSD.
Get entropy from /dev/urandom on FreeBSD < 12, or getrandom() on FreeBSD
12, per
https://www.freebsd.org/cgi/man.cgi?query=getrandom&sektion=2&format=html
Tested manually with `ninja run_tests` on both FreeBSD 11 and 12.
Change-Id: I72ef54d1a83104d1fbe172fd86f6cd32dacc9819
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/46188
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
diff --git a/crypto/fipsmodule/rand/urandom.c b/crypto/fipsmodule/rand/urandom.c
index 3def3aa..8464e9e 100644
--- a/crypto/fipsmodule/rand/urandom.c
+++ b/crypto/fipsmodule/rand/urandom.c
@@ -62,6 +62,15 @@
#include <sys/random.h>
#endif
+#if defined(OPENSSL_FREEBSD)
+#define URANDOM_BLOCKS_FOR_ENTROPY
+#if __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>
@@ -176,6 +185,11 @@
}
#endif
+#if defined(FREEBSD_GETRANDOM)
+ *urandom_fd_bss_get() = kHaveGetrandom;
+ return;
+#endif
+
// Android FIPS builds must support getrandom.
#if defined(BORINGSSL_FIPS) && defined(OPENSSL_ANDROID)
perror("getrandom not found");
@@ -256,11 +270,11 @@
return;
}
-#if defined(BORINGSSL_FIPS)
- // In FIPS mode 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.
+#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)) {
@@ -277,7 +291,7 @@
usleep(250000);
}
-#endif // BORINGSSL_FIPS
+#endif // BORINGSSL_FIPS && !URANDOM_BLOCKS_FOR_ENTROPY
}
// fill_with_entropy writes |len| bytes of entropy into |out|. It returns one
@@ -291,11 +305,14 @@
return 1;
}
-#if defined(USE_NR_getrandom)
+#if defined(USE_NR_getrandom) || defined(FREEBSD_GETRANDOM)
int getrandom_flags = 0;
if (!block) {
getrandom_flags |= GRND_NONBLOCK;
}
+#endif
+
+#if defined (USE_NR_getrandom)
if (seed) {
getrandom_flags |= *extra_getrandom_flags_for_seed_bss_get();
}
@@ -315,6 +332,8 @@
if (*urandom_fd_bss_get() == kHaveGetrandom) {
#if defined(USE_NR_getrandom)
r = boringssl_getrandom(out, len, getrandom_flags);
+#elif defined(FREEBSD_GETRANDOM)
+ r = getrandom(out, len, getrandom_flags);
#elif defined(OPENSSL_MACOS)
if (__builtin_available(macos 10.12, *)) {
// |getentropy| can only request 256 bytes at a time.
diff --git a/include/openssl/base.h b/include/openssl/base.h
index 79c4444..61a8886 100644
--- a/include/openssl/base.h
+++ b/include/openssl/base.h
@@ -166,6 +166,10 @@
#endif
#endif
+#if defined(__FreeBSD__)
+#define OPENSSL_FREEBSD
+#endif
+
// BoringSSL requires platform's locking APIs to make internal global state
// thread-safe, including the PRNG. On some single-threaded embedded platforms,
// locking APIs may not exist, so this dependency may be disabled with the