Bug 1345089 - add prng kat tests, r=ttaubert
--- a/lib/freebl/blapi.h
+++ b/lib/freebl/blapi.h
@@ -1464,16 +1464,22 @@ FIPS186Change_GenerateX(unsigned char *X
* q, DSA_SUBPRIME_LEN bytes
* Output: xj, DSA_SUBPRIME_LEN bytes
*/
extern SECStatus
FIPS186Change_ReduceModQForDSA(const unsigned char *w,
const unsigned char *q,
unsigned char *xj);
+/* To allow NIST KAT tests */
+extern SECStatus
+PRNGTEST_Instantiate_Kat(const PRUint8 *entropy, unsigned int entropy_len,
+ const PRUint8 *nonce, unsigned int nonce_len,
+ const PRUint8 *personal_string, unsigned int ps_len);
+
/*
* The following functions are for FIPS poweron self test and FIPS algorithm
* testing.
*/
extern 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);
--- a/lib/freebl/drbg.c
+++ b/lib/freebl/drbg.c
@@ -94,17 +94,18 @@ struct RNGContextStr {
* save the rest of the rng output for
* another partial block */
PRUint8 dataAvail; /* # bytes of output available in our cache,
* [0...SHA256_LENGTH] */
/* store additional data that has been shovelled off to us by
* RNG_RandomUpdate. */
PRUint8 additionalDataCache[PRNG_ADDITONAL_DATA_CACHE_SIZE];
PRUint32 additionalAvail;
- PRBool isValid; /* false if RNG reaches an invalid state */
+ PRBool isValid; /* false if RNG reaches an invalid state */
+ PRBool isKatTest; /* true if running NIST PRNG KAT tests */
};
typedef struct RNGContextStr RNGContext;
static RNGContext *globalrng = NULL;
static RNGContext theGlobalRng;
/*
* The next several functions are derived from the NIST SP 800-90
@@ -145,27 +146,29 @@ prng_Hash_df(PRUint8 *requested_bytes, u
no_of_bytes_to_return);
requested_bytes += hash_return_len;
no_of_bytes_to_return -= hash_return_len;
}
return SECSuccess;
}
/*
- * Hash_DRBG Instantiate NIST SP 800-80 10.1.1.2
+ * Hash_DRBG Instantiate NIST SP 800-90 10.1.1.2
*
* NOTE: bytes & len are entropy || nonce || personalization_string. In
* normal operation, NSS calculates them all together in a single call.
*/
static SECStatus
prng_instantiate(RNGContext *rng, const PRUint8 *bytes, unsigned int len)
{
- if (len < PRNG_SEEDLEN) {
- /* if the seedlen is to small, it's probably because we failed to get
- * enough random data */
+ if (!rng->isKatTest && len < PRNG_SEEDLEN) {
+ /* If the seedlen is too small, it's probably because we failed to get
+ * enough random data.
+ * This is stricter than NIST SP800-90A requires. Don't enforce it for
+ * tests. */
PORT_SetError(SEC_ERROR_NEED_RANDOM);
return SECFailure;
}
prng_Hash_df(V(rng), VSize(rng), bytes, len, NULL, 0);
rng->V_type = prngCGenerateType;
prng_Hash_df(rng->C, sizeof rng->C, rng->V_Data, sizeof rng->V_Data, NULL, 0);
PRNG_RESET_RESEED_COUNT(rng)
return SECSuccess;
@@ -267,17 +270,17 @@ prng_reseed_test(RNGContext *rng, const
carry += dest[k1] + add[k2]; \
dest[k1] = (PRUint8)carry; \
carry >>= 8; \
} \
}
#define PRNG_ADD_BITS_AND_CARRY(dest, dest_len, add, len, carry) \
PRNG_ADD_BITS(dest, dest_len, add, len, carry) \
- PRNG_ADD_CARRY_ONLY(dest, dest_len - len, carry)
+ PRNG_ADD_CARRY_ONLY(dest, dest_len - len - 1, carry)
/*
* This function expands the internal state of the prng to fulfill any number
* of bytes we need for this request. We only use this call if we need more
* than can be supplied by a single call to SHA256_HashBuf.
*
* This function is specified in NIST SP 800-90 section 10.1.1.4, Hashgen
*/
@@ -436,16 +439,17 @@ rng_init(void)
return PR_FAILURE;
}
if (rv != SECSuccess) {
return PR_FAILURE;
}
/* the RNG is in a valid state */
globalrng->isValid = PR_TRUE;
+ globalrng->isKatTest = PR_FALSE;
/* fetch one random value so that we can populate rng->oldV for our
* continous random number test. */
prng_generateNewBytes(globalrng, bytes, SHA256_LENGTH, NULL, 0);
/* Fetch more entropy into the PRNG */
RNG_SystemInfoForRNG();
}
@@ -691,16 +695,27 @@ RNG_RNGShutdown(void)
/*
* Test case interface. used by fips testing and power on self test
*/
/* make sure the test context is separate from the global context, This
* allows us to test the internal random number generator without losing
* entropy we may have previously collected. */
RNGContext testContext;
+SECStatus
+PRNGTEST_Instantiate_Kat(const PRUint8 *entropy, unsigned int entropy_len,
+ const PRUint8 *nonce, unsigned int nonce_len,
+ const PRUint8 *personal_string, unsigned int ps_len)
+{
+ testContext.isKatTest = PR_TRUE;
+ return PRNGTEST_Instantiate(entropy, entropy_len,
+ nonce, nonce_len,
+ personal_string, ps_len);
+}
+
/*
* Test vector API. Use NIST SP 800-90 general interface so one of the
* other NIST SP 800-90 algorithms may be used in the future.
*/
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)