Skip to content

Commit

Permalink
Make PRNG model slightly more readable (#1079)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
torben-hansen authored Jul 5, 2023
1 parent 2f9c3b6 commit a33d16a
Showing 1 changed file with 55 additions and 30 deletions.
85 changes: 55 additions & 30 deletions crypto/fipsmodule/rand/urandom_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@
#define PTRACE_O_TRACESYSGOOD (1)
#endif

#if defined(AWSLC_FIPS)
static const bool kIsFIPS = true;
#else
static const bool kIsFIPS = false;
#endif


// This test can be run with $OPENSSL_ia32cap=~0x4000000000000000 in order to
// simulate the absence of RDRAND of machines that have it.

Expand Down Expand Up @@ -390,11 +397,6 @@ static bool have_fork_detection() {
// |TestFunction| is run. It should return the same trace of events that
// |GetTrace| will observe the real code making.
static std::vector<Event> TestFunctionPRNGModel(unsigned flags) {
#if defined(BORINGSSL_FIPS)
static const bool is_fips = true;
#else
static const bool is_fips = false;
#endif

std::vector<Event> ret;
bool urandom_probed = false;
Expand All @@ -413,7 +415,7 @@ static std::vector<Event> TestFunctionPRNGModel(unsigned flags) {
}

wait_for_entropy = [&ret, &urandom_probed, flags] {
if (!is_fips || urandom_probed) {
if (!kIsFIPS || urandom_probed) {
return;
}

Expand Down Expand Up @@ -471,39 +473,62 @@ static std::vector<Event> TestFunctionPRNGModel(unsigned flags) {

const size_t kSeedLength = CTR_DRBG_ENTROPY_LEN;
const size_t kAdditionalDataLength = 32;

if (!have_rdrand()) {
if ((!have_fork_detection() && !sysrand(true, kAdditionalDataLength)) ||
// Initialise CRNGT. In FIPS mode we use a blocking sysrand call for
// a personalization string, while in non-FIPS mode the same call is
// used for generating entropy for a seed. Note that the length
// of the personalization string is the same as that of the seed.
!sysrand(true, kSeedLength) ||
// Second entropy draw.
(!have_fork_detection() && !sysrand(true, kAdditionalDataLength))) {
const size_t kPersonalizationStringLength = CTR_DRBG_ENTROPY_LEN;
const bool kHaveRdrand = have_rdrand();
const bool kHaveFastRdrand = have_fast_rdrand();
const bool kHaveForkDetection = have_fork_detection();

// Additional data might be drawn on each invocation of RAND_bytes(). In case
// it is and there is no rdrand at all, the call is blocking. In the case
// where there is at least a "slow" rdrand, first a non-blocking call to
// system random is performed followed by an rdrand call.

// First call to RAND_bytes() will do two things:
// * maybe draw for additional data
// * seed the CTR-DRBG
// First is deciding on additional data.
if (!kHaveRdrand || !kHaveFastRdrand) {
if (!kHaveForkDetection) {
// If no rdrand, we use additional data if fork detection is not enabled.
if (!sysrand(!kHaveRdrand, kAdditionalDataLength)) {
return ret;
}
}
}
// Now the entropy for seeding.
if (kIsFIPS) {
// In FIPS mode we use Jitter Entropy for the seed but Jitter is not modeled
// A blocking system random call for a personalization string always follows.
if (!sysrand(true, kPersonalizationStringLength)) {
return ret;
}
} else {
// In non-FIPS mode entropy for the seed is drawn from system random.
if (!sysrand(true, kSeedLength)) {
return ret;
}
} else if (
// First additional data. If fast RDRAND isn't available then a
// non-blocking OS entropy draw will be tried.
(!have_fast_rdrand() && !have_fork_detection() &&
!sysrand(false, kAdditionalDataLength)) ||
// Initialise CRNGT. In FIPS mode we use a blocking sysrand call for
// a personalization string, while in non-FIPS mode the same call is
// used for generating entropy for a seed. Note that the length
// of the personalization string is the same as that of the seed.
!sysrand(true, kSeedLength) ||
// Second entropy draw's additional data.
(!have_fast_rdrand() && !have_fork_detection() &&
!sysrand(false, kAdditionalDataLength))) {
return ret;
}

// Second RAND_bytes() call. No seeding or re-seeding, but in some cases
// entropy is drawn for additional data as in the first call to RAND_bytes().
if (!kHaveRdrand || !kHaveFastRdrand) {
if (!kHaveForkDetection) {
if (!sysrand(!kHaveRdrand, kAdditionalDataLength)) {
return ret;
}
}
}

return ret;
}

// Tests that |TestFunctionPRNGModel| is a correct model for the code in
// urandom.c, at least to the limits of the the |Event| type.
//
// |TestFunctionPRNGModel| creates the entropy function call model, for
// various configs. |GetTrace| records the actual entropy function calls for
// each config and compares it against the model.
// Only system entropy function calls are modeled e.g. /dev/random and getrandom.
TEST(URandomTest, Test) {
char buf[256];

Expand Down

0 comments on commit a33d16a

Please sign in to comment.