Commit f3945122 authored by Franziskus Kiefer's avatar Franziskus Kiefer

Bug 1349936 - make fuzzing rng a complete rng, r=ttaubert

Differential Revision: https://nss-review.dev.mozaws.net/D246

--HG--
extra : rebase_source : 8177a2a66153177826a5359f1c3caa0c418729a9
extra : amend_source : e7d88d1047346210e40e68f0cc83ab3a8ca44d1f
extra : histedit_source : c321d3862f95670b324a8c838ae8d5d03ad68771%2Cd11de0ba2474976c712aa9397a10a1fd682dc492
parent b89882d6
......@@ -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.
......
......@@ -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.
......
......@@ -27,7 +27,7 @@
'-lstdc++',
],
}],
[ 'fuzz_tls==1', {
[ 'fuzz==1', {
'defines': [
'UNSAFE_FUZZER_MODE',
],
......
......@@ -36,12 +36,12 @@ TEST_F(PK11PrngTest, Fuzz_DetPRNG_Reset) {
std::vector<uint8_t> rnd1(2048, 0);
std::vector<uint8_t> 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<uint8_t> rnd1(2048, 0);
std::vector<uint8_t> 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<uint8_t> rnd1(2048, 0);
std::vector<uint8_t> rnd2(2048, 0);
std::vector<uint8_t> 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<uint8_t> rnd1(2048, 0);
std::vector<uint8_t> rnd2(2048, 0);
std::vector<uint8_t> 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);
......
......@@ -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<TlsConversationRecorder>(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.
......
......@@ -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()).
......
......@@ -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;
}
......@@ -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
......
......@@ -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',
],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment