Skip to content

Commit

Permalink
Bug 1349936 - make fuzzing rng a complete rng, r=ttaubert
Browse files Browse the repository at this point in the history
Differential Revision: https://nss-review.dev.mozaws.net/D246

--HG--
extra : rebase_source : 8177a2a66153177826a5359f1c3caa0c418729a9
extra : amend_source : e7d88d1047346210e40e68f0cc83ab3a8ca44d1f
extra : histedit_source : c321d3862f95670b324a8c838ae8d5d03ad68771%2Cd11de0ba2474976c712aa9397a10a1fd682dc492
  • Loading branch information
franziskuskiefer committed Mar 22, 2017
1 parent b89882d commit f394512
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 47 deletions.
2 changes: 1 addition & 1 deletion fuzz/tls_client_target.cc
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion fuzz/tls_server_target.cc
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion gtests/common/gtest.gypi
Expand Up @@ -27,7 +27,7 @@
'-lstdc++',
],
}],
[ 'fuzz_tls==1', {
[ 'fuzz==1', {
'defines': [
'UNSAFE_FUZZER_MODE',
],
Expand Down
51 changes: 47 additions & 4 deletions gtests/pk11_gtest/pk11_prng_unittest.cc
Expand Up @@ -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);
Expand All @@ -54,15 +54,58 @@ 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);

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);
Expand Down
9 changes: 3 additions & 6 deletions gtests/ssl_gtest/ssl_fuzz_unittest.cc
Expand Up @@ -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};
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 0 additions & 2 deletions lib/freebl/blapi.h
Expand Up @@ -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()).
Expand Down
82 changes: 79 additions & 3 deletions lib/freebl/det_rng.c
Expand Up @@ -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);
Expand All @@ -23,17 +45,21 @@ 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 --- */

return SECSuccess;
}

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. */
Expand All @@ -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;
}
22 changes: 0 additions & 22 deletions lib/freebl/drbg.c
Expand Up @@ -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 */
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down
10 changes: 3 additions & 7 deletions lib/freebl/freebl_base.gypi
Expand Up @@ -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',
],
Expand Down

0 comments on commit f394512

Please sign in to comment.