Use getentropy on macOS 10.12 and later.
Bug: 287
Change-Id: I40760bdba8dcaab9c5c38d52d6479138f52eccbd
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/37284
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/fipsmodule/rand/urandom.c b/crypto/fipsmodule/rand/urandom.c
index 1d26534..9fa0c97 100644
--- a/crypto/fipsmodule/rand/urandom.c
+++ b/crypto/fipsmodule/rand/urandom.c
@@ -54,6 +54,10 @@
#endif
#endif // OPENSSL_LINUX
+#if defined(OPENSSL_MACOS)
+#include <sys/random.h>
+#endif
+
#include <openssl/thread.h>
#include <openssl/mem.h>
@@ -176,6 +180,15 @@
}
#endif // USE_NR_getrandom
+#if defined(OPENSSL_MACOS)
+ // getentropy is available in macOS 10.12 and up. iOS 10 and up may also
+ // support it, but the header is missing. See https://crbug.com/boringssl/287.
+ if (__builtin_available(macos 10.12, *)) {
+ *urandom_fd_bss_get() = kHaveGetrandom;
+ return;
+ }
+#endif
+
// Android FIPS builds must support getrandom.
#if defined(BORINGSSL_FIPS) && defined(OPENSSL_ANDROID)
perror("getrandom not found");
@@ -229,6 +242,9 @@
static void wait_for_entropy(void) {
int fd = *urandom_fd_bss_get();
if (fd == kHaveGetrandom) {
+ // |getrandom| and |getentropy| support blocking in |fill_with_entropy|
+ // directly. For |getrandom|, we first probe with a non-blocking call to aid
+ // debugging.
#if defined(USE_NR_getrandom)
if (*getrandom_ready_bss_get()) {
// The entropy pool was already initialized in |init_once|.
@@ -260,16 +276,12 @@
boringssl_getrandom(&dummy, sizeof(dummy), 0 /* no flags */);
}
- if (getrandom_ret == 1) {
- return;
+ if (getrandom_ret != 1) {
+ perror("getrandom");
+ abort();
}
-
- perror("getrandom");
- abort();
-#else
- fprintf(stderr, "urandom fd corrupt.\n");
- abort();
#endif // USE_NR_getrandom
+ return;
}
#if defined(BORINGSSL_FIPS)
@@ -353,6 +365,19 @@
if (*urandom_fd_bss_get() == kHaveGetrandom) {
#if defined(USE_NR_getrandom)
r = boringssl_getrandom(out, len, block ? 0 : GRND_NONBLOCK);
+#elif defined(OPENSSL_MACOS)
+ if (__builtin_available(macos 10.12, *)) {
+ // |getentropy| can only request 256 bytes at a time.
+ size_t todo = len <= 256 ? len : 256;
+ if (getentropy(out, todo) != 0) {
+ r = -1;
+ } else {
+ r = (ssize_t)todo;
+ }
+ } else {
+ fprintf(stderr, "urandom fd corrupt.\n");
+ abort();
+ }
#else // USE_NR_getrandom
fprintf(stderr, "urandom fd corrupt.\n");
abort();
diff --git a/include/openssl/base.h b/include/openssl/base.h
index cb1affa..e347c09 100644
--- a/include/openssl/base.h
+++ b/include/openssl/base.h
@@ -124,6 +124,11 @@
#if defined(__APPLE__)
#define OPENSSL_APPLE
+// Note |TARGET_OS_MAC| is set for all Apple OS variants. |TARGET_OS_OSX|
+// targets macOS specifically.
+#if defined(TARGET_OS_OSX) && TARGET_OS_OSX
+#define OPENSSL_MACOS
+#endif
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
#define OPENSSL_IOS
#endif