Skip to content

Commit

Permalink
Backport entropy passive to fips-2022-11-02 (#1198)
Browse files Browse the repository at this point in the history
* Make PRNG model slightly more readable (#1079)

The way the PRNG model is written looks more complicated than what is actually needed. Attempt to re-write it. This also makes it slightly easier to amend with future potential changes.

* Remove CRNGT (#1112)

CRNGT is not a requirement for FIPS 140-3.

FIPS 140-2 Section 4.9.2 required the execution of the Continuous Randomness Number Generation Test (CRNGT). However, this requirement is not present in FIPS 140-3. In addition, later stages of FIPS 140-2 this test was not mandatory in all cases either (cf. FIPS 140-2 IG 9.8).

Executing this test requires maintaining state, which inevitably introduces complexity. Given CRNGT is redundant with respect to compliance and really provides zero practical value (see, again, FIPS 140-2 IG 9.8), we axe it.

* Abstract fips entropy functions (#1113)

Abstract getting data from the configured entropy source of FIPS. Atm, the configured source is hard-coded in multiple workflows. This allows adding another source more easily.

In addition, add some machinery to configure another source of build-time using the new define FIPS_ENTROPY_SOURCE_JITTER_CPU.

* Implementation passive entropy (#1125)

* Use passive entropy source method by default for FIPS build mode (#1188)

Enables passive entropy method by default. In addition, adds a build-time config that can modify (at build-time) the entropy source method to CPU Jitter.

* Kick CI bots

* Kick CI bots, again
  • Loading branch information
torben-hansen authored Sep 20, 2023
1 parent 093d713 commit 21e2cdc
Show file tree
Hide file tree
Showing 9 changed files with 423 additions and 140 deletions.
14 changes: 14 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,23 @@ option(BUILD_TESTING "Build all test targets for AWS-LC" ON)
option(BUILD_LIBSSL "Build libssl for AWS-LC" ON)
option(DISABLE_PERL "Disable Perl for AWS-LC" OFF)
option(DISABLE_GO "Disable Go for AWS-LC" OFF)
option(ENABLE_FIPS_ENTROPY_CPU_JITTER "Enable FIPS entropy source: CPU Jitter" OFF)

enable_language(C)

# Configure entropy source in case of FIPS build
if(FIPS)
message(STATUS "FIPS build mode configured")

if(ENABLE_FIPS_ENTROPY_CPU_JITTER)
add_definitions(-DFIPS_ENTROPY_SOURCE_JITTER_CPU)
message(STATUS "FIPS entropy source method configured: CPU Jitter")
else()
add_definitions(-DFIPS_ENTROPY_SOURCE_PASSIVE)
message(STATUS "FIPS entropy source method configured: Passive")
endif()
endif()

# Tests and libssl both require the CXX language to be enabled. If a consumer
# chooses to disable building the tests and libssl, do not enable CXX
if(BUILD_TESTING OR BUILD_LIBSSL)
Expand Down
1 change: 1 addition & 0 deletions crypto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@ add_library(
poly1305/poly1305_vec.c
pool/pool.c
rand_extra/deterministic.c
rand_extra/entropy_passive.c
rand_extra/forkunsafe.c
rand_extra/fuchsia.c
rand_extra/rand_extra.c
Expand Down
23 changes: 15 additions & 8 deletions crypto/fipsmodule/FIPS.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ Some FIPS tests cannot be broken by replacing a known string in the binary. For

1. `RSA_PWCT`
1. `ECDSA_PWCT`
1. `CRNG`

## Breaking the integrity test

Expand All @@ -37,13 +36,7 @@ The utility in `util/fipstools/break-hash.go` can be used to corrupt the FIPS mo

FIPS 140-2 requires that one of its PRNGs be used (which they call DRBGs). In BoringCrypto, we use CTR-DRBG with AES-256 exclusively and `RAND_bytes` (the primary interface for the rest of the system to get random data) takes its output from there.

The DRBG state is kept in a thread-local structure and is seeded from one of the following entropy sources in preference order: RDRAND (on Intel chips), `getrandom`, and `/dev/urandom`. In the case of `/dev/urandom`, in order to ensure that the system has a minimum level of entropy, BoringCrypto polls the kernel until the estimated entropy is at least 256 bits. This is a poor man's version of `getrandom` and we strongly recommend using a kernel recent enough to support the real thing.

In FIPS mode, each of those entropy sources is subject to a 10× overread. That is, when *n* bytes of entropy are needed, *10n* bytes will be read from the entropy source and XORed down to *n* bytes. Reads from the entropy source are also processed in blocks of 16 bytes and if two consecutive chunks are equal the process will abort.

In the case that the seed is taken from RDRAND, getrandom will also be queried with `GRND_NONBLOCK` to attempt to obtain additional entropy from the operating system. If available, that extra entropy will be XORed into the whitened seed.

On Android, only `getrandom` is supported and, when seeding for the first time, the system property `ro.boringcrypto.hwrand` is queried. If set to `true` then `getrandom` will be called with the `GRND_RANDOM` flag. Only entropy draws destined for DRBG seeds are affected by this. We are not suggesting that there is any security advantage at all to doing this, and thus recommend that Android vendors do _not_ set this flag.
The DRBG state is kept in a thread-local structure and is seeded using the configured entropy source.

The CTR-DRBG is reseeded every 4096 calls to `RAND_bytes`. Thus the process will randomly crash about every 2¹³⁵ calls.

Expand All @@ -53,6 +46,20 @@ There is a second interface to the RNG which allows the caller to supply bytes t

FIPS requires that RNG state be zeroed when the process exits. In order to implement this, all per-thread RNG states are tracked in a linked list and a destructor function is included which clears them. In order for this to be safe in the presence of threads, a lock is used to stop all other threads from using the RNG once this process has begun. Thus the main thread exiting may cause other threads to deadlock, and drawing on entropy in a destructor function may also deadlock.

## Entropy sources

By default, entropy is sourced using a "Passive" method where the specific entropy source depends on the OE. Seeding and reseeding material for the DRBG is sourced from the specific entropy source.

In FIPS mode, each of the entropy sources is subject to a 10× overread. That is, when *n* bytes of entropy are needed, *10n* bytes will be read from the entropy source and XORed down to *n* bytes.

### Modify entropy source - not recommended

Modifying the entropy source can invalidate your validation status. Changing the entropy is **not** recommended.

It is possible to modify the entropy method at build-time. Using `ENABLE_FIPS_ENTROPY_CPU_JITTER=ON`, the entropy source is switched to [CPU Jitter](https://github.com/smuellerDD/jitterentropy-library).

CPU Jitter is less performant than the default method and can incur up to a 2-digit millisecond latency when queried. You can test CPU Jitter entropy on your system using `bssl speed -filter Jitter`.

## Integrity Test

FIPS-140 mandates that a module calculate an HMAC of its own code in a constructor function and compare the result to a known-good value. Typical code produced by a C compiler includes large numbers of relocations: places in the machine code where the linker needs to resolve and inject the final value of a symbolic expression. These relocations mean that the bytes that make up any specific bit of code generally aren't known until the final link has completed.
Expand Down
20 changes: 20 additions & 0 deletions crypto/fipsmodule/rand/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,30 @@ OPENSSL_INLINE int have_fast_rdrand(void) {
#define MAX_BACKOFF_RETRIES 9
OPENSSL_EXPORT void HAZMAT_set_urandom_test_mode_for_testing(void);

// Final factor TBD
#define PASSIVE_ENTROPY_WHITEN_FACTOR 10
// Total number of bytes of entropy to load into FIPS module
#define PASSIVE_ENTROPY_LOAD_LENGTH (CTR_DRBG_ENTROPY_LEN * PASSIVE_ENTROPY_WHITEN_FACTOR)

#if defined(BORINGSSL_FIPS)

#if defined(FIPS_ENTROPY_SOURCE_JITTER_CPU)

#define JITTER_MAX_NUM_TRIES (3)

#elif defined(FIPS_ENTROPY_SOURCE_PASSIVE)

OPENSSL_EXPORT void RAND_module_entropy_depleted(uint8_t out_entropy[CTR_DRBG_ENTROPY_LEN],
int *out_want_additional_input);
void CRYPTO_get_seed_entropy(uint8_t entropy[PASSIVE_ENTROPY_LOAD_LENGTH],
int *out_want_additional_input);
OPENSSL_EXPORT void RAND_load_entropy(uint8_t out_entropy[CTR_DRBG_ENTROPY_LEN],
uint8_t entropy[PASSIVE_ENTROPY_LOAD_LENGTH]);

#endif

#endif // defined(BORINGSSL_FIPS)

#if defined(__cplusplus)
} // extern C
#endif
Expand Down
Loading

0 comments on commit 21e2cdc

Please sign in to comment.