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