Skip to content

Commit

Permalink
Use getentropy for OpenBSD, FreeBSD, and MacOS (#2099)
Browse files Browse the repository at this point in the history
Use getentropy for some operating systems. Namely, Apple MacOS, OpenBSD, and FreeBSD. getentropy is closer to the noise sources.
  • Loading branch information
torben-hansen authored Feb 1, 2025
1 parent 19e9b93 commit 3da1ba6
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 55 deletions.
1 change: 1 addition & 0 deletions crypto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ add_library(
rand_extra/deterministic.c
rand_extra/entropy_passive.c
rand_extra/forkunsafe.c
rand_extra/getentropy.c
rand_extra/rand_extra.c
rand_extra/pq_custom_randombytes.c
rand_extra/windows.c
Expand Down
2 changes: 1 addition & 1 deletion crypto/fipsmodule/rand/getrandom_fillin.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#include <openssl/base.h>


#if defined(OPENSSL_LINUX)
#if defined(OPENSSL_RAND_URANDOM)

#include <sys/syscall.h>

Expand Down
3 changes: 2 additions & 1 deletion crypto/fipsmodule/rand/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@
extern "C" {
#endif


#if defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
#define OPENSSL_RAND_DETERMINISTIC
#elif defined(OPENSSL_WINDOWS)
#define OPENSSL_RAND_WINDOWS
#elif defined(OPENSSL_MACOS) || defined(OPENSSL_OPENBSD) || defined(OPENSSL_FREEBSD)
#define OPENSSL_RAND_GETENTROPY
#else
#define OPENSSL_RAND_URANDOM
#endif
Expand Down
47 changes: 6 additions & 41 deletions crypto/fipsmodule/rand/urandom.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,20 +69,6 @@
#include <CommonCrypto/CommonRandom.h>
#endif

#if defined(OPENSSL_FREEBSD)
#define URANDOM_BLOCKS_FOR_ENTROPY
#include <sys/param.h>
#if __FreeBSD_version >= 1200000
// getrandom is supported in FreeBSD 12 and up.
#define FREEBSD_GETRANDOM
#include <sys/random.h>
#endif
#endif

#if defined(OPENSSL_OPENBSD)
#include <stdlib.h>
#endif

#include <openssl/thread.h>
#include <openssl/mem.h>

Expand Down Expand Up @@ -250,22 +236,9 @@ static void init_once(void) {
}
#endif // USE_NR_getrandom

#if defined(OPENSSL_APPLE)
// To get system randomness on MacOS and iOS we use |CCRandomGenerateBytes|
// function provided by Apple rather than /dev/urandom or |getentropy|
// function which is available on MacOS but not on iOS.
return;
#endif

#if defined(OPENSSL_OPENBSD)
// To get system randomness on OpenBSD we use |arc4random_buf| function
// which is recommended to use for C APIs rather then /dev/urandom.
// See https://man.openbsd.org/arc4random.3
return;
#endif

#if defined(FREEBSD_GETRANDOM)
*urandom_fd_bss_get() = kHaveGetrandom;
#if defined(OPENSSL_IOS)
// To get system randomness on iOS we use |CCRandomGenerateBytes| because
// |getentroopy| is not available.
return;
#endif

Expand Down Expand Up @@ -350,7 +323,7 @@ static void wait_for_entropy(void) {
}

#if defined(BORINGSSL_FIPS) && !defined(URANDOM_BLOCKS_FOR_ENTROPY) && \
!(defined(OPENSSL_APPLE) || defined(OPENSSL_OPENBSD)) // On MacOS, iOS, and OpenBSD we don't use /dev/urandom.
!defined(OPENSSL_IOS) // On iOS we don't use /dev/urandom.

// In FIPS mode on platforms where urandom doesn't block at startup, we ensure
// that the kernel has sufficient entropy before continuing. This is
Expand Down Expand Up @@ -388,7 +361,7 @@ static int fill_with_entropy(uint8_t *out, size_t len, int block, int seed) {
return 1;
}

#if defined(OPENSSL_APPLE)
#if defined(OPENSSL_IOS)
// To get system randomness on MacOS and iOS we use |CCRandomGenerateBytes|
// rather than |getentropy| and /dev/urandom.
if (CCRandomGenerateBytes(out, len) == kCCSuccess) {
Expand All @@ -399,13 +372,7 @@ static int fill_with_entropy(uint8_t *out, size_t len, int block, int seed) {
}
#endif

#if defined(OPENSSL_OPENBSD)
// Return value is void, no error to check
arc4random_buf(out, len);
return 1;
#endif

#if defined(USE_NR_getrandom) || defined(FREEBSD_GETRANDOM)
#if defined(USE_NR_getrandom)
int getrandom_flags = 0;
if (!block) {
getrandom_flags |= GRND_NONBLOCK;
Expand All @@ -432,8 +399,6 @@ static int fill_with_entropy(uint8_t *out, size_t len, int block, int seed) {
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);
#else // USE_NR_getrandom
fprintf(stderr, "urandom fd corrupt.\n");
abort();
Expand Down
3 changes: 2 additions & 1 deletion crypto/fipsmodule/rand/urandom_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
#include "internal.h"
#include "../../ube/snapsafe_detect.h"

#if defined(OPENSSL_X86_64) && !defined(BORINGSSL_SHARED_LIBRARY) && \
#if defined(OPENSSL_RAND_URANDOM) && defined(OPENSSL_X86_64) && \
!defined(BORINGSSL_SHARED_LIBRARY) && \
!defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE) && \
defined(USE_NR_getrandom) && !defined(AWSLC_SNAPSAFE_TESTING)

Expand Down
48 changes: 48 additions & 0 deletions crypto/rand_extra/getentropy.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR ISC

#if !defined(_DEFAULT_SOURCE)
// Needed for getentropy on musl and glibc per man pages.
#define _DEFAULT_SOURCE
#endif

#include <openssl/rand.h>

#include "../fipsmodule/rand/internal.h"

#if defined(OPENSSL_RAND_GETENTROPY)

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#if defined(OPENSSL_MACOS)
// MacOS does not declare getentropy in uinstd.h like other OS's.
#include <sys/random.h>
#endif

#if !defined(GETENTROPY_MAX)
// Per POSIX 2024
// https://pubs.opengroup.org/onlinepubs/9799919799/functions/getentropy.html
#define GETENTROPY_MAX 256
#endif

void CRYPTO_sysrand(uint8_t *out, size_t requested) {
// getentropy max request size is GETENTROPY_MAX.
while (requested > 0) {
size_t request_chunk = (requested > GETENTROPY_MAX) ? GETENTROPY_MAX : requested;
if (getentropy(out, request_chunk) != 0) {
fprintf(stderr, "getentropy failed.\n");
abort();
}
requested -= request_chunk;
out += request_chunk;
}
}

void CRYPTO_sysrand_for_seed(uint8_t *out, size_t requested) {
CRYPTO_sysrand(out, requested);
}

#endif
11 changes: 0 additions & 11 deletions include/openssl/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,6 @@ extern "C" {
#define AWSLC_FIPS
#endif

#if defined(__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
#endif

#define AWSLC_VERSION_NAME "AWS-LC"
#define OPENSSL_IS_AWSLC
// |OPENSSL_VERSION_NUMBER| should match the version number in opensslv.h.
Expand Down
8 changes: 8 additions & 0 deletions include/openssl/target.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@

#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
#endif

#if defined(_WIN32)
Expand Down

0 comments on commit 3da1ba6

Please sign in to comment.