diff --git a/fuzz/tls_client_target.cc b/fuzz/tls_client_target.cc index 5cb071250d..4b40257a90 100644 --- a/fuzz/tls_client_target.cc +++ b/fuzz/tls_client_target.cc @@ -81,7 +81,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) { #ifdef UNSAFE_FUZZER_MODE // Reset the RNG state. - assert(RNG_ResetForFuzzing() == SECSuccess); + assert(RNG_RandomUpdate(NULL, 0) == SECSuccess); #endif // Create and import dummy socket. diff --git a/fuzz/tls_server_target.cc b/fuzz/tls_server_target.cc index 84a5a75b29..9a533fb132 100644 --- a/fuzz/tls_server_target.cc +++ b/fuzz/tls_server_target.cc @@ -85,7 +85,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) { #ifdef UNSAFE_FUZZER_MODE // Reset the RNG state. - assert(RNG_ResetForFuzzing() == SECSuccess); + assert(RNG_RandomUpdate(NULL, 0) == SECSuccess); #endif // Create model socket. diff --git a/gtests/common/gtest.gypi b/gtests/common/gtest.gypi index e0ffc86e28..c4865bba51 100644 --- a/gtests/common/gtest.gypi +++ b/gtests/common/gtest.gypi @@ -27,7 +27,7 @@ '-lstdc++', ], }], - [ 'fuzz_tls==1', { + [ 'fuzz==1', { 'defines': [ 'UNSAFE_FUZZER_MODE', ], diff --git a/gtests/pk11_gtest/pk11_prng_unittest.cc b/gtests/pk11_gtest/pk11_prng_unittest.cc index fd28651696..ef05fe51cd 100644 --- a/gtests/pk11_gtest/pk11_prng_unittest.cc +++ b/gtests/pk11_gtest/pk11_prng_unittest.cc @@ -36,12 +36,12 @@ TEST_F(PK11PrngTest, Fuzz_DetPRNG_Reset) { std::vector rnd1(2048, 0); std::vector rnd2(2048, 0); - RNG_ResetForFuzzing(); + EXPECT_EQ(SECSuccess, RNG_RandomUpdate(NULL, 0)); SECStatus rv = PK11_GenerateRandom(rnd1.data(), rnd1.size()); EXPECT_EQ(rv, SECSuccess); - RNG_ResetForFuzzing(); + EXPECT_EQ(SECSuccess, RNG_RandomUpdate(NULL, 0)); rv = PK11_GenerateRandom(rnd2.data(), rnd2.size()); EXPECT_EQ(rv, SECSuccess); @@ -54,7 +54,7 @@ TEST_F(PK11PrngTest, Fuzz_DetPRNG_StatefulReset) { std::vector rnd1(2048, 0); std::vector rnd2(2048, 0); - RNG_ResetForFuzzing(); + EXPECT_EQ(SECSuccess, RNG_RandomUpdate(NULL, 0)); SECStatus rv = PK11_GenerateRandom(rnd1.data(), rnd1.size() - 1024); EXPECT_EQ(rv, SECSuccess); @@ -62,7 +62,50 @@ TEST_F(PK11PrngTest, Fuzz_DetPRNG_StatefulReset) { rv = PK11_GenerateRandom(rnd1.data() + 1024, rnd1.size() - 1024); EXPECT_EQ(rv, SECSuccess); - RNG_ResetForFuzzing(); + EXPECT_EQ(SECSuccess, RNG_RandomUpdate(NULL, 0)); + + rv = PK11_GenerateRandom(rnd2.data(), rnd2.size() - 1024); + EXPECT_EQ(rv, SECSuccess); + + rv = PK11_GenerateRandom(rnd2.data() + 1024, rnd2.size() - 1024); + EXPECT_EQ(rv, SECSuccess); + + EXPECT_EQ(rnd1, rnd2); +} + +TEST_F(PK11PrngTest, Fuzz_DetPRNG_Seed) { + std::vector rnd1(2048, 0); + std::vector rnd2(2048, 0); + std::vector seed = {0x01, 0x22, 0xAA, 0x45}; + + SECStatus rv = PK11_RandomUpdate(seed.data(), seed.size()); + EXPECT_EQ(rv, SECSuccess); + + rv = PK11_GenerateRandom(rnd1.data(), rnd1.size()); + EXPECT_EQ(rv, SECSuccess); + + rv = PK11_GenerateRandom(rnd2.data(), rnd2.size()); + EXPECT_EQ(rv, SECSuccess); + + EXPECT_NE(rnd1, rnd2); +} + +TEST_F(PK11PrngTest, Fuzz_DetPRNG_StatefulReset_Seed) { + std::vector rnd1(2048, 0); + std::vector rnd2(2048, 0); + std::vector seed = {0x01, 0x22, 0xAA, 0x45}; + + SECStatus rv = PK11_RandomUpdate(seed.data(), seed.size()); + EXPECT_EQ(rv, SECSuccess); + + rv = PK11_GenerateRandom(rnd1.data(), rnd1.size() - 1024); + EXPECT_EQ(rv, SECSuccess); + + rv = PK11_GenerateRandom(rnd1.data() + 1024, rnd1.size() - 1024); + EXPECT_EQ(rv, SECSuccess); + + rv = PK11_RandomUpdate(seed.data(), seed.size()); + EXPECT_EQ(rv, SECSuccess); rv = PK11_GenerateRandom(rnd2.data(), rnd2.size() - 1024); EXPECT_EQ(rv, SECSuccess); diff --git a/gtests/ssl_gtest/ssl_fuzz_unittest.cc b/gtests/ssl_gtest/ssl_fuzz_unittest.cc index b2abfa9a8e..5dcdd964d4 100644 --- a/gtests/ssl_gtest/ssl_fuzz_unittest.cc +++ b/gtests/ssl_gtest/ssl_fuzz_unittest.cc @@ -17,9 +17,6 @@ namespace nss_test { #else #define FUZZ_F(c, f) TEST_F(c, DISABLED_Fuzz_##f) #define FUZZ_P(c, f) TEST_P(c, DISABLED_Fuzz_##f) -// RNG_ResetForFuzzing() isn't exported from the shared libraries, rather than -// fail to link to it, make it fail (we're not running it anyway). -#define RNG_ResetForFuzzing() SECFailure #endif const uint8_t kShortEmptyFinished[8] = {0}; @@ -91,7 +88,7 @@ FUZZ_P(TlsConnectGeneric, DeterministicExporter) { DisableECDHEServerKeyReuse(); // Reset the RNG state. - EXPECT_EQ(SECSuccess, RNG_ResetForFuzzing()); + EXPECT_EQ(SECSuccess, RNG_RandomUpdate(NULL, 0)); Connect(); // Export a key derived from the MS and nonces. @@ -105,7 +102,7 @@ FUZZ_P(TlsConnectGeneric, DeterministicExporter) { DisableECDHEServerKeyReuse(); // Reset the RNG state. - EXPECT_EQ(SECSuccess, RNG_ResetForFuzzing()); + EXPECT_EQ(SECSuccess, RNG_RandomUpdate(NULL, 0)); Connect(); // Export another key derived from the MS and nonces. @@ -135,7 +132,7 @@ FUZZ_P(TlsConnectGeneric, DeterministicTranscript) { server_->SetPacketFilter(std::make_shared(buffer)); // Reset the RNG state. - EXPECT_EQ(SECSuccess, RNG_ResetForFuzzing()); + EXPECT_EQ(SECSuccess, RNG_RandomUpdate(NULL, 0)); Connect(); // Ensure the filters go away before |buffer| does. diff --git a/lib/freebl/blapi.h b/lib/freebl/blapi.h index e5a6cf30e0..592624bdf7 100644 --- a/lib/freebl/blapi.h +++ b/lib/freebl/blapi.h @@ -1429,8 +1429,6 @@ extern SECStatus RNG_RandomUpdate(const void *data, size_t bytes); */ extern SECStatus RNG_GenerateGlobalRandomBytes(void *dest, size_t len); -extern SECStatus RNG_ResetForFuzzing(void); - /* Destroy the global RNG context. After a call to RNG_RNGShutdown() ** a call to RNG_RNGInit() is required in order to use the generator again, ** along with seed data (see the comment above RNG_RNGInit()). diff --git a/lib/freebl/det_rng.c b/lib/freebl/det_rng.c index fcbf9b34a8..04fce30e80 100644 --- a/lib/freebl/det_rng.c +++ b/lib/freebl/det_rng.c @@ -9,10 +9,32 @@ #include "seccomon.h" #include "secerr.h" +#define GLOBAL_BYTES_SIZE 100 +static PRUint8 globalBytes[GLOBAL_BYTES_SIZE]; static unsigned long globalNumCalls = 0; +static PZLock *rng_lock = NULL; SECStatus -prng_ResetForFuzzing(PZLock *rng_lock) +RNG_RNGInit(void) +{ + rng_lock = PZ_NewLock(nssILockOther); + if (!rng_lock) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + /* --- LOCKED --- */ + PZ_Lock(rng_lock); + memset(globalBytes, 0, GLOBAL_BYTES_SIZE); + PZ_Unlock(rng_lock); + /* --- UNLOCKED --- */ + + return SECSuccess; +} + +/* Take min(size, GLOBAL_BYTES_SIZE) bytes from data and use as seed and reset + * the rng state. */ +SECStatus +RNG_RandomUpdate(const void *data, size_t bytes) { /* Check for a valid RNG lock. */ PORT_Assert(rng_lock != NULL); @@ -23,7 +45,11 @@ prng_ResetForFuzzing(PZLock *rng_lock) /* --- LOCKED --- */ PZ_Lock(rng_lock); + memset(globalBytes, 0, GLOBAL_BYTES_SIZE); globalNumCalls = 0; + if (data) { + memcpy(globalBytes, (PRUint8 *)data, PR_MIN(bytes, GLOBAL_BYTES_SIZE)); + } PZ_Unlock(rng_lock); /* --- UNLOCKED --- */ @@ -31,9 +57,9 @@ prng_ResetForFuzzing(PZLock *rng_lock) } SECStatus -prng_GenerateDeterministicRandomBytes(PZLock *rng_lock, void *dest, size_t len) +RNG_GenerateGlobalRandomBytes(void *dest, size_t len) { - static const uint8_t key[32]; + static const uint8_t key[32] = { 0 }; uint8_t nonce[12] = { 0 }; /* Check for a valid RNG lock. */ @@ -58,10 +84,60 @@ prng_GenerateDeterministicRandomBytes(PZLock *rng_lock, void *dest, size_t len) } memset(dest, 0, len); + memcpy(dest, globalBytes, PR_MIN(len, GLOBAL_BYTES_SIZE)); ChaCha20XOR(dest, dest, len, key, nonce, 0); ChaCha20Poly1305_DestroyContext(cx, PR_TRUE); PZ_Unlock(rng_lock); /* --- UNLOCKED --- */ + return SECSuccess; } + +void +RNG_RNGShutdown(void) +{ + PZ_DestroyLock(rng_lock); + rng_lock = NULL; +} + +/* Test functions are not implemented! */ +SECStatus +PRNGTEST_Instantiate(const PRUint8 *entropy, unsigned int entropy_len, + const PRUint8 *nonce, unsigned int nonce_len, + const PRUint8 *personal_string, unsigned int ps_len) +{ + return SECFailure; +} + +SECStatus +PRNGTEST_Reseed(const PRUint8 *entropy, unsigned int entropy_len, + const PRUint8 *additional, unsigned int additional_len) +{ + return SECFailure; +} + +SECStatus +PRNGTEST_Generate(PRUint8 *bytes, unsigned int bytes_len, + const PRUint8 *additional, unsigned int additional_len) +{ + return SECFailure; +} + +SECStatus +PRNGTEST_Uninstantiate() +{ + return SECFailure; +} + +SECStatus +PRNGTEST_RunHealthTests() +{ + return SECFailure; +} + +SECStatus +PRNGTEST_Instantiate_Kat() +{ + return SECFailure; +} diff --git a/lib/freebl/drbg.c b/lib/freebl/drbg.c index 0f8819938d..224bbe87d8 100644 --- a/lib/freebl/drbg.c +++ b/lib/freebl/drbg.c @@ -20,10 +20,6 @@ #include "secrng.h" /* for RNG_SystemRNG() */ #include "secmpi.h" -#ifdef UNSAFE_FUZZER_MODE -#include "det_rng.h" -#endif - /* PRNG_SEEDLEN defined in NIST SP 800-90 section 10.1 * for SHA-1, SHA-224, and SHA-256 it's 440 bits. * for SHA-384 and SHA-512 it's 888 bits */ @@ -401,10 +397,8 @@ static PRStatus rng_init(void) { PRUint8 bytes[PRNG_SEEDLEN * 2]; /* entropy + nonce */ -#ifndef UNSAFE_RNG_NO_URANDOM_SEED unsigned int numBytes; SECStatus rv = SECSuccess; -#endif if (globalrng == NULL) { /* bytes needs to have enough space to hold @@ -421,7 +415,6 @@ rng_init(void) return PR_FAILURE; } -#ifndef UNSAFE_RNG_NO_URANDOM_SEED /* Try to get some seed data for the RNG */ numBytes = (unsigned int)RNG_SystemRNG(bytes, sizeof bytes); PORT_Assert(numBytes == 0 || numBytes == sizeof bytes); @@ -444,7 +437,6 @@ rng_init(void) if (rv != SECSuccess) { return PR_FAILURE; } -#endif /* the RNG is in a valid state */ globalrng->isValid = PR_TRUE; @@ -662,21 +654,7 @@ prng_GenerateGlobalRandomBytes(RNGContext *rng, SECStatus RNG_GenerateGlobalRandomBytes(void *dest, size_t len) { -#ifdef UNSAFE_FUZZER_MODE - return prng_GenerateDeterministicRandomBytes(globalrng->lock, dest, len); -#else return prng_GenerateGlobalRandomBytes(globalrng, dest, len); -#endif -} - -SECStatus -RNG_ResetForFuzzing(void) -{ -#ifdef UNSAFE_FUZZER_MODE - return prng_ResetForFuzzing(globalrng->lock); -#else - return SECFailure; -#endif } void diff --git a/lib/freebl/freebl_base.gypi b/lib/freebl/freebl_base.gypi index 9e4d8031bc..91f186a457 100644 --- a/lib/freebl/freebl_base.gypi +++ b/lib/freebl/freebl_base.gypi @@ -158,15 +158,11 @@ }], ], }], - [ 'fuzz_oss==1', { - 'defines': [ - 'UNSAFE_RNG_NO_URANDOM_SEED', - ], + [ 'fuzz==1', { + 'sources!': [ 'drbg.c' ], + 'sources': [ 'det_rng.c' ], }], [ 'fuzz_tls==1', { - 'sources': [ - 'det_rng.c', - ], 'defines': [ 'UNSAFE_FUZZER_MODE', ],