Bug 1345089 - add prng kat tests, r=ttaubert NSS_3_21_BRANCH
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Wed, 05 Apr 2017 16:04:57 +0200
branchNSS_3_21_BRANCH
changeset 13276 e126381a3c29
parent 12730 295f16833a75
child 13277 99a86619eac9
push id2137
push userfranziskuskiefer@gmail.com
push date2017-04-05 14:31 +0000
reviewersttaubert
bugs1345089
Bug 1345089 - add prng kat tests, r=ttaubert
lib/freebl/blapi.h
lib/freebl/drbg.c
--- a/lib/freebl/blapi.h
+++ b/lib/freebl/blapi.h
@@ -1439,16 +1439,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
@@ -91,17 +91,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;
 
 
 /*
@@ -144,27 +145,29 @@ prng_Hash_df(PRUint8 *requested_bytes, u
 	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
  */
@@ -418,16 +421,17 @@ static PRStatus 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();
     }
@@ -662,16 +666,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)