Skip to content

Commit

Permalink
Move urandom and OS entropy support out of BCM
Browse files Browse the repository at this point in the history
BCM uses only passive entropy, in that from BCM's
point of view, entropy is requested and obtained
from an external source, and fed to BCM's CTR_DRBG
as required. With this change entropy is always gathered
in an OS specific manner outside of BCM by libcrypto,
while the CTR_DRBG remains in BCM using that entropy.

BCM functions (but not yet the tests!) now no longer
use the public RAND_bytes function, but instead use
BCM_rand_bytes which uses the BCM module CTR_DRBG.
BCM_rand_bytes is in turn used by libcrypto to implement
the public RAND_bytes function. All public RAND_
functions are now implemented in rand_extra.

As part of this two new headers are introduced to
start defining the interface boundary between libcrypto
and BCM.

crypto/bcm_support.h <- Functions implemented by libcrypto
and used by bcm

fipsmodule/bcm_interface.h <- Functions implemented by
bcm and used by libcrypto.

Bug: 723

Change-Id: I6b618dfe4df257f67971e88cbd79126c837e21d6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/68147
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Bob Beck <bbe@google.com>
  • Loading branch information
Bob Beck authored and Boringssl LUCI CQ committed Aug 29, 2024
1 parent c25c376 commit ec09a2d
Show file tree
Hide file tree
Showing 27 changed files with 390 additions and 220 deletions.
10 changes: 6 additions & 4 deletions build.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@
"crypto/fipsmodule/rand/ctrdrbg.c",
"crypto/fipsmodule/rand/fork_detect.c",
"crypto/fipsmodule/rand/rand.c",
"crypto/fipsmodule/rand/urandom.c",
"crypto/fipsmodule/rsa/blinding.c",
"crypto/fipsmodule/rsa/padding.c",
"crypto/fipsmodule/rsa/rsa.c",
Expand Down Expand Up @@ -298,6 +297,7 @@
"crypto/rand_extra/passive.c",
"crypto/rand_extra/rand_extra.c",
"crypto/rand_extra/trusty.c",
"crypto/rand_extra/urandom.c",
"crypto/rand_extra/windows.c",
"crypto/rc4/rc4.c",
"crypto/refcount.c",
Expand Down Expand Up @@ -496,7 +496,7 @@
"crypto/ec_extra/internal.h",
"crypto/err/internal.h",
"crypto/evp/internal.h",
"crypto/fipsmodule/aes/internal.h",
"crypto/fipsmodule/bcm_interface.h",
"crypto/fipsmodule/bn/internal.h",
"crypto/fipsmodule/bn/rsaz_exp.h",
"crypto/fipsmodule/cipher/internal.h",
Expand All @@ -513,13 +513,13 @@
"crypto/fipsmodule/md5/internal.h",
"crypto/fipsmodule/modes/internal.h",
"crypto/fipsmodule/rand/fork_detect.h",
"crypto/fipsmodule/rand/getrandom_fillin.h",
"crypto/fipsmodule/rand/internal.h",
"crypto/fipsmodule/rsa/internal.h",
"crypto/fipsmodule/service_indicator/internal.h",
"crypto/fipsmodule/sha/internal.h",
"crypto/fipsmodule/tls/internal.h",
"crypto/hrss/internal.h",
"crypto/bcm_support.h",
"crypto/internal.h",
"crypto/keccak/internal.h",
"crypto/kyber/internal.h",
Expand All @@ -531,6 +531,8 @@
"crypto/pkcs8/internal.h",
"crypto/poly1305/internal.h",
"crypto/pool/internal.h",
"crypto/rand_extra/getrandom_fillin.h",
"crypto/rand_extra/sysrand_internal.h",
"crypto/rsa_extra/internal.h",
"crypto/spx/address.h",
"crypto/spx/fors.h",
Expand Down Expand Up @@ -913,7 +915,7 @@
},
"urandom_test": {
"srcs": [
"crypto/fipsmodule/rand/urandom_test.cc"
"crypto/rand_extra/urandom_test.cc"
]
},
"pki_test": {
Expand Down
73 changes: 73 additions & 0 deletions crypto/bcm_support.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/* Copyright (c) 2024, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */

#ifndef OPENSSL_HEADER_CRYPTO_BCM_SUPPORT_H
#define OPENSSL_HEADER_CRYPTO_BCM_SUPPORT_H

#include <openssl/base.h>

// Provided by libcrypto, called from BCM

#if defined(__cplusplus)
extern "C" {
#endif

#if defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
#define OPENSSL_RAND_DETERMINISTIC
#elif defined(OPENSSL_TRUSTY)
#define OPENSSL_RAND_TRUSTY
#elif defined(OPENSSL_WINDOWS)
#define OPENSSL_RAND_WINDOWS
#elif defined(OPENSSL_LINUX)
#define OPENSSL_RAND_URANDOM
#elif defined(OPENSSL_APPLE) && !defined(OPENSSL_MACOS)
// Unlike macOS, iOS and similar hide away getentropy().
#define OPENSSL_RAND_IOS
#else
// By default if you are integrating BoringSSL we expect you to
// provide getentropy from the <unistd.h> header file.
#define OPENSSL_RAND_GETENTROPY
#endif

// Provided by libcrypto, called from BCM

// CRYPTO_init_sysrand initializes long-lived resources needed to draw entropy
// from the operating system, if the operating system requires initialization.
void CRYPTO_init_sysrand(void);

// CRYPTO_sysrand fills |len| bytes at |buf| with entropy from the operating
// system.
void CRYPTO_sysrand(uint8_t *buf, size_t len);

// CRYPTO_sysrand_if_available fills |len| bytes at |buf| with entropy from the
// operating system, or early /dev/urandom data, and returns 1, _if_ the entropy
// pool is initialized or if getrandom() is not available and not in FIPS mode.
// Otherwise it will not block and will instead fill |buf| with all zeros and
// return 0.
int CRYPTO_sysrand_if_available(uint8_t *buf, size_t len);

// CRYPTO_sysrand_for_seed fills |len| bytes at |buf| with entropy from the
// operating system. It may draw from the |GRND_RANDOM| pool on Android,
// depending on the vendor's configuration.
void CRYPTO_sysrand_for_seed(uint8_t *buf, size_t len);

// RAND_need_entropy is called whenever the BCM module has stopped because it
// has run out of entropy.
void RAND_need_entropy(size_t bytes_needed);

#if defined(__cplusplus)
} // extern C
#endif

#endif // OPENSSL_HEADER_CRYPTO_BCM_SUPPORT_H
1 change: 1 addition & 0 deletions crypto/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

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


Expand Down
4 changes: 2 additions & 2 deletions crypto/fipsmodule/bcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <openssl/hmac.h>
#include <openssl/sha.h>

#include "bcm_interface.h"
#include "../internal.h"

#include "aes/aes.c"
Expand Down Expand Up @@ -94,7 +95,6 @@
#include "rand/ctrdrbg.c"
#include "rand/fork_detect.c"
#include "rand/rand.c"
#include "rand/urandom.c"
#include "rsa/blinding.c"
#include "rsa/padding.c"
#include "rsa/rsa.c"
Expand Down Expand Up @@ -193,7 +193,7 @@ int BORINGSSL_integrity_test(void) {

assert_within(start, AES_encrypt, end);
assert_within(start, RSA_sign, end);
assert_within(start, RAND_bytes, end);
assert_within(start, BCM_rand_bytes, end);
assert_within(start, EC_GROUP_cmp, end);
assert_within(start, SHA256_Update, end);
assert_within(start, ecdsa_verify_fixed, end);
Expand Down
89 changes: 89 additions & 0 deletions crypto/fipsmodule/bcm_interface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/* Copyright (c) 2024, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */

#ifndef OPENSSL_HEADER_CRYPTO_BCM_INTERFACE_H
#define OPENSSL_HEADER_CRYPTO_BCM_INTERFACE_H

// This header will eventually become the interface between BCM and the
// rest of libcrypto. More cleanly separating the two is still a work in
// progress (see https://crbug.com/boringssl/722) so, at the moment, we
// consider this no different from any other header in BCM.
//
// Over time, calls from libcrypto to BCM will all move to this header
// and the separation will become more meaningful.

#if defined(__cplusplus)
extern "C" {
#endif

// Enumerated types for return values from bcm functions, both infallible
// and fallible functions. Two success values are used to correspond to the
// FIPS service indicator. For the moment, the official service indicator
// remains the counter, not these values. Once we fully transition to
// these return values from bcm we will change that.
enum bcm_infallible_t {
bcm_infallible_approved,
bcm_infallible_not_approved,
};

enum bcm_status_t {
bcm_status_approved,
bcm_status_not_approved,

// Failure codes, which must all be negative.
bcm_status_failure,
};
typedef enum bcm_status_t bcm_status;
typedef enum bcm_infallible_t bcm_infallible;

OPENSSL_INLINE int bcm_success(bcm_status status) {
return status == bcm_status_approved || status == bcm_status_not_approved;
}

#if defined(BORINGSSL_FIPS)

// We overread from /dev/urandom or RDRAND by a factor of 10 and XOR to whiten.
// TODO(bbe): disentangle this value which is used to calculate the size of the
// stack buffer in RAND_need entropy based on a calculation.
#define BORINGSSL_FIPS_OVERREAD 10

#endif // BORINGSSL_FIPS

// BCM_rand_load_entropy supplies |entropy_len| bytes of entropy to the BCM
// module. The |want_additional_input| parameter is true iff the entropy was
// obtained from a source other than the system, e.g. directly from the CPU.
bcm_infallible BCM_rand_load_entropy(const uint8_t *entropy, size_t entropy_len,
int want_additional_input);

// BCM_rand_bytes is the same as the public |RAND_bytes| function, other
// than returning a bcm_infallible status indicator.
OPENSSL_EXPORT bcm_infallible BCM_rand_bytes(uint8_t *out, size_t out_len);

// BCM_rand_bytes_hwrng attempts to fill |out| with |len| bytes of entropy from
// the CPU hardware random number generator if one is present.
// bcm_status_approved is returned on success, and a failure status is
// returned otherwise.
bcm_status BCM_rand_bytes_hwrng(uint8_t *out, size_t len);

// BCM_rand_bytes_with_additional_data samples from the RNG after mixing 32
// bytes from |user_additional_data| in.
bcm_infallible BCM_rand_bytes_with_additional_data(
uint8_t *out, size_t out_len, const uint8_t user_additional_data[32]);


#if defined(__cplusplus)
} // extern C
#endif

#endif // OPENSSL_HEADER_CRYPTO_BCM_INTERFACE_H
14 changes: 6 additions & 8 deletions crypto/fipsmodule/bn/random.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,9 @@
#include <string.h>

#include <openssl/err.h>
#include <openssl/rand.h>

#include "../../bcm_support.h"
#include "../../internal.h"
#include "../rand/internal.h"
#include "../service_indicator/internal.h"
#include "internal.h"

Expand Down Expand Up @@ -157,7 +156,7 @@ int BN_rand(BIGNUM *rnd, int bits, int top, int bottom) {
}

FIPS_service_indicator_lock_state();
RAND_bytes((uint8_t *)rnd->d, words * sizeof(BN_ULONG));
BCM_rand_bytes((uint8_t *)rnd->d, words * sizeof(BN_ULONG));
FIPS_service_indicator_unlock_state();

rnd->d[words - 1] &= mask;
Expand Down Expand Up @@ -225,8 +224,7 @@ static int bn_range_to_mask(size_t *out_words, BN_ULONG *out_mask,
while (words > 0 && max_exclusive[words - 1] == 0) {
words--;
}
if (words == 0 ||
(words == 1 && max_exclusive[0] <= min_inclusive)) {
if (words == 0 || (words == 1 && max_exclusive[0] <= min_inclusive)) {
OPENSSL_PUT_ERROR(BN, BN_R_INVALID_RANGE);
return 0;
}
Expand Down Expand Up @@ -275,8 +273,8 @@ int bn_rand_range_words(BN_ULONG *out, BN_ULONG min_inclusive,
// Steps 4 and 5. Use |words| and |mask| together to obtain a string of N
// bits, where N is the bit length of |max_exclusive|.
FIPS_service_indicator_lock_state();
RAND_bytes_with_additional_data((uint8_t *)out, words * sizeof(BN_ULONG),
additional_data);
BCM_rand_bytes_with_additional_data(
(uint8_t *)out, words * sizeof(BN_ULONG), additional_data);
FIPS_service_indicator_unlock_state();
out[words - 1] &= mask;

Expand Down Expand Up @@ -326,7 +324,7 @@ int bn_rand_secret_range(BIGNUM *r, int *out_is_uniform, BN_ULONG min_inclusive,

// Select a uniform random number with num_bits(max_exclusive) bits.
FIPS_service_indicator_lock_state();
RAND_bytes((uint8_t *)r->d, words * sizeof(BN_ULONG));
BCM_rand_bytes((uint8_t *)r->d, words * sizeof(BN_ULONG));
FIPS_service_indicator_unlock_state();
r->d[words - 1] &= mask;

Expand Down
17 changes: 9 additions & 8 deletions crypto/fipsmodule/cipher/e_aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/nid.h>
#include <openssl/rand.h>

#include "internal.h"
#include "../../internal.h"
#include "../aes/internal.h"
#include "../bcm_interface.h"
#include "../modes/internal.h"
#include "../service_indicator/internal.h"
#include "../delocate.h"
Expand Down Expand Up @@ -471,11 +471,11 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) {
}
OPENSSL_memcpy(gctx->iv, ptr, arg);
if (c->encrypt) {
// |RAND_bytes| calls within the fipsmodule should be wrapped with state
// lock functions to avoid updating the service indicator with the DRBG
// functions.
// |BCM_rand_bytes| calls within the fipsmodule should be wrapped with
// state lock functions to avoid updating the service indicator with the
// DRBG functions.
FIPS_service_indicator_lock_state();
RAND_bytes(gctx->iv + arg, gctx->ivlen - arg);
BCM_rand_bytes(gctx->iv + arg, gctx->ivlen - arg);
FIPS_service_indicator_unlock_state();
}
gctx->iv_gen = 1;
Expand Down Expand Up @@ -1167,10 +1167,11 @@ static int aead_aes_gcm_seal_scatter_randnonce(
return 0;
}

// |RAND_bytes| calls within the fipsmodule should be wrapped with state lock
// functions to avoid updating the service indicator with the DRBG functions.
// |BCM_rand_bytes| calls within the fipsmodule should be wrapped with state
// lock functions to avoid updating the service indicator with the DRBG
// functions.
FIPS_service_indicator_lock_state();
RAND_bytes(nonce, sizeof(nonce));
BCM_rand_bytes(nonce, sizeof(nonce));
FIPS_service_indicator_unlock_state();

const struct aead_aes_gcm_ctx *gcm_ctx =
Expand Down
Loading

0 comments on commit ec09a2d

Please sign in to comment.