Blame SOURCES/nss-softokn-fips-update.patch

dbb9a2
diff --git a/lib/freebl/fipsfreebl.c b/lib/freebl/fipsfreebl.c
dbb9a2
--- a/lib/freebl/fipsfreebl.c
dbb9a2
+++ b/lib/freebl/fipsfreebl.c
dbb9a2
@@ -10,18 +10,20 @@
dbb9a2
 #ifdef FREEBL_NO_DEPEND
dbb9a2
 #include "stubs.h"
dbb9a2
 #endif
dbb9a2
 
dbb9a2
 #include "blapi.h"
dbb9a2
 #include "seccomon.h" /* Required for RSA and DSA. */
dbb9a2
 #include "secerr.h"
dbb9a2
 #include "prtypes.h"
dbb9a2
+#include "secitem.h"
dbb9a2
+#include "pkcs11t.h"
dbb9a2
 
dbb9a2
-#include "ec.h" /* Required for ECDSA */
dbb9a2
+#include "ec.h" /* Required for EC */
dbb9a2
 
dbb9a2
 /*
dbb9a2
  * different platforms have different ways of calling and initial entry point
dbb9a2
  * when the dll/.so is loaded. Most platforms support either a posix pragma
dbb9a2
  * or the GCC attribute. Some platforms suppor a pre-defined name, and some
dbb9a2
  * platforms have a link line way of invoking this function.
dbb9a2
  */
dbb9a2
 
dbb9a2
@@ -283,61 +285,88 @@ freebl_fips_AES_PowerUpSelfTest(int aes_
dbb9a2
 
dbb9a2
     /* AES-CBC Known Initialization Vector (128-bits). */
dbb9a2
     static const PRUint8 aes_cbc_known_initialization_vector[] =
dbb9a2
         { "SecurityytiruceS" };
dbb9a2
 
dbb9a2
     /* AES Known Plaintext (128-bits). (blocksize is 128-bits) */
dbb9a2
     static const PRUint8 aes_known_plaintext[] = { "NetscapeepacsteN" };
dbb9a2
 
dbb9a2
+    static const PRUint8 aes_gcm_known_aad[] = { "MozillaallizoM" };
dbb9a2
+
dbb9a2
     /* AES Known Ciphertext (128-bit key). */
dbb9a2
     static const PRUint8 aes_ecb128_known_ciphertext[] = {
dbb9a2
         0x3c, 0xa5, 0x96, 0xf3, 0x34, 0x6a, 0x96, 0xc1,
dbb9a2
         0x03, 0x88, 0x16, 0x7b, 0x20, 0xbf, 0x35, 0x47
dbb9a2
     };
dbb9a2
 
dbb9a2
     static const PRUint8 aes_cbc128_known_ciphertext[] = {
dbb9a2
         0xcf, 0x15, 0x1d, 0x4f, 0x96, 0xe4, 0x4f, 0x63,
dbb9a2
         0x15, 0x54, 0x14, 0x1d, 0x4e, 0xd8, 0xd5, 0xea
dbb9a2
     };
dbb9a2
 
dbb9a2
+    static const PRUint8 aes_gcm128_known_ciphertext[] = {
dbb9a2
+        0x63, 0xf4, 0x95, 0x28, 0xe6, 0x78, 0xee, 0x6e,
dbb9a2
+        0x4f, 0xe0, 0xfc, 0x8d, 0xd7, 0xa2, 0xb1, 0xff,
dbb9a2
+        0x0c, 0x97, 0x1b, 0x0a, 0xdd, 0x97, 0x75, 0xed,
dbb9a2
+        0x8b, 0xde, 0xbf, 0x16, 0x5e, 0x57, 0x6b, 0x4f
dbb9a2
+    };
dbb9a2
+
dbb9a2
     /* AES Known Ciphertext (192-bit key). */
dbb9a2
     static const PRUint8 aes_ecb192_known_ciphertext[] = {
dbb9a2
         0xa0, 0x18, 0x62, 0xed, 0x88, 0x19, 0xcb, 0x62,
dbb9a2
         0x88, 0x1d, 0x4d, 0xfe, 0x84, 0x02, 0x89, 0x0e
dbb9a2
     };
dbb9a2
 
dbb9a2
     static const PRUint8 aes_cbc192_known_ciphertext[] = {
dbb9a2
         0x83, 0xf7, 0xa4, 0x76, 0xd1, 0x6f, 0x07, 0xbe,
dbb9a2
         0x07, 0xbc, 0x43, 0x2f, 0x6d, 0xad, 0x29, 0xe1
dbb9a2
     };
dbb9a2
 
dbb9a2
+    static const PRUint8 aes_gcm192_known_ciphertext[] = {
dbb9a2
+        0xc1, 0x0b, 0x92, 0x1d, 0x68, 0x21, 0xf4, 0x25,
dbb9a2
+        0x41, 0x61, 0x20, 0x2d, 0x59, 0x7f, 0x53, 0xde,
dbb9a2
+        0x93, 0x39, 0xab, 0x09, 0x76, 0x41, 0x57, 0x2b,
dbb9a2
+        0x90, 0x2e, 0x44, 0xbb, 0x52, 0x03, 0xe9, 0x07
dbb9a2
+    };
dbb9a2
+
dbb9a2
     /* AES Known Ciphertext (256-bit key). */
dbb9a2
     static const PRUint8 aes_ecb256_known_ciphertext[] = {
dbb9a2
         0xdb, 0xa6, 0x52, 0x01, 0x8a, 0x70, 0xae, 0x66,
dbb9a2
         0x3a, 0x99, 0xd8, 0x95, 0x7f, 0xfb, 0x01, 0x67
dbb9a2
     };
dbb9a2
 
dbb9a2
     static const PRUint8 aes_cbc256_known_ciphertext[] = {
dbb9a2
         0x37, 0xea, 0x07, 0x06, 0x31, 0x1c, 0x59, 0x27,
dbb9a2
         0xc5, 0xc5, 0x68, 0x71, 0x6e, 0x34, 0x40, 0x16
dbb9a2
     };
dbb9a2
 
dbb9a2
+    static const PRUint8 aes_gcm256_known_ciphertext[] = {
dbb9a2
+        0x5d, 0x9e, 0xd2, 0xa2, 0x74, 0x9c, 0xd9, 0x1c,
dbb9a2
+        0xd1, 0xc9, 0xee, 0x5d, 0xb6, 0xf2, 0xc9, 0xb6,
dbb9a2
+        0x79, 0x27, 0x53, 0x02, 0xa3, 0xdc, 0x22, 0xce,
dbb9a2
+        0xf4, 0xb0, 0xc1, 0x8c, 0x86, 0x51, 0xf5, 0xa1
dbb9a2
+    };
dbb9a2
+
dbb9a2
     const PRUint8 *aes_ecb_known_ciphertext =
dbb9a2
         (aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_ecb128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_ecb192_known_ciphertext : aes_ecb256_known_ciphertext;
dbb9a2
 
dbb9a2
     const PRUint8 *aes_cbc_known_ciphertext =
dbb9a2
         (aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_cbc128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_cbc192_known_ciphertext : aes_cbc256_known_ciphertext;
dbb9a2
 
dbb9a2
+    const PRUint8 *aes_gcm_known_ciphertext =
dbb9a2
+        (aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_gcm128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_gcm192_known_ciphertext : aes_gcm256_known_ciphertext;
dbb9a2
+
dbb9a2
     /* AES variables. */
dbb9a2
-    PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH];
dbb9a2
-    PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH];
dbb9a2
+    PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH * 2];
dbb9a2
+    PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH * 2];
dbb9a2
     AESContext *aes_context;
dbb9a2
     unsigned int aes_bytes_encrypted;
dbb9a2
     unsigned int aes_bytes_decrypted;
dbb9a2
+    CK_GCM_PARAMS gcmParams;
dbb9a2
     SECStatus aes_status;
dbb9a2
 
dbb9a2
     /*check if aes_key_size is 128, 192, or 256 bits */
dbb9a2
     if ((aes_key_size != FIPS_AES_128_KEY_SIZE) &&
dbb9a2
         (aes_key_size != FIPS_AES_192_KEY_SIZE) &&
dbb9a2
         (aes_key_size != FIPS_AES_256_KEY_SIZE)) {
dbb9a2
         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
dbb9a2
         return (SECFailure);
dbb9a2
@@ -450,16 +479,79 @@ freebl_fips_AES_PowerUpSelfTest(int aes_
dbb9a2
     if ((aes_status != SECSuccess) ||
dbb9a2
         (aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH) ||
dbb9a2
         (PORT_Memcmp(aes_computed_plaintext, aes_known_plaintext,
dbb9a2
                      FIPS_AES_DECRYPT_LENGTH) != 0)) {
dbb9a2
         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
dbb9a2
         return (SECFailure);
dbb9a2
     }
dbb9a2
 
dbb9a2
+    /******************************************************/
dbb9a2
+    /* AES-GCM Single-Round Known Answer Encryption Test. */
dbb9a2
+    /******************************************************/
dbb9a2
+
dbb9a2
+    gcmParams.pIv = (PRUint8 *)aes_cbc_known_initialization_vector;
dbb9a2
+    gcmParams.ulIvLen = FIPS_AES_BLOCK_SIZE;
dbb9a2
+    gcmParams.pAAD = (PRUint8 *)aes_gcm_known_aad;
dbb9a2
+    gcmParams.ulAADLen = sizeof(aes_gcm_known_aad);
dbb9a2
+    gcmParams.ulTagBits = FIPS_AES_BLOCK_SIZE * 8;
dbb9a2
+    aes_context = AES_CreateContext(aes_known_key,
dbb9a2
+                                    (PRUint8 *)&gcmParams,
dbb9a2
+                                    NSS_AES_GCM, PR_TRUE, aes_key_size,
dbb9a2
+                                    FIPS_AES_BLOCK_SIZE);
dbb9a2
+
dbb9a2
+    if (aes_context == NULL) {
dbb9a2
+        PORT_SetError(SEC_ERROR_NO_MEMORY);
dbb9a2
+        return (SECFailure);
dbb9a2
+    }
dbb9a2
+
dbb9a2
+    aes_status = AES_Encrypt(aes_context, aes_computed_ciphertext,
dbb9a2
+                             &aes_bytes_encrypted, FIPS_AES_ENCRYPT_LENGTH * 2,
dbb9a2
+                             aes_known_plaintext,
dbb9a2
+                             FIPS_AES_DECRYPT_LENGTH);
dbb9a2
+
dbb9a2
+    AES_DestroyContext(aes_context, PR_TRUE);
dbb9a2
+
dbb9a2
+    if ((aes_status != SECSuccess) ||
dbb9a2
+        (aes_bytes_encrypted != FIPS_AES_ENCRYPT_LENGTH * 2) ||
dbb9a2
+        (PORT_Memcmp(aes_computed_ciphertext, aes_gcm_known_ciphertext,
dbb9a2
+                     FIPS_AES_ENCRYPT_LENGTH * 2) != 0)) {
dbb9a2
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
dbb9a2
+        return (SECFailure);
dbb9a2
+    }
dbb9a2
+
dbb9a2
+    /******************************************************/
dbb9a2
+    /* AES-GCM Single-Round Known Answer Decryption Test. */
dbb9a2
+    /******************************************************/
dbb9a2
+
dbb9a2
+    aes_context = AES_CreateContext(aes_known_key,
dbb9a2
+                                    (PRUint8 *)&gcmParams,
dbb9a2
+                                    NSS_AES_GCM, PR_FALSE, aes_key_size,
dbb9a2
+                                    FIPS_AES_BLOCK_SIZE);
dbb9a2
+
dbb9a2
+    if (aes_context == NULL) {
dbb9a2
+        PORT_SetError(SEC_ERROR_NO_MEMORY);
dbb9a2
+        return (SECFailure);
dbb9a2
+    }
dbb9a2
+
dbb9a2
+    aes_status = AES_Decrypt(aes_context, aes_computed_plaintext,
dbb9a2
+                             &aes_bytes_decrypted, FIPS_AES_DECRYPT_LENGTH * 2,
dbb9a2
+                             aes_gcm_known_ciphertext,
dbb9a2
+                             FIPS_AES_ENCRYPT_LENGTH * 2);
dbb9a2
+
dbb9a2
+    AES_DestroyContext(aes_context, PR_TRUE);
dbb9a2
+
dbb9a2
+    if ((aes_status != SECSuccess) ||
dbb9a2
+        (aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH) ||
dbb9a2
+        (PORT_Memcmp(aes_computed_plaintext, aes_known_plaintext,
dbb9a2
+                     FIPS_AES_DECRYPT_LENGTH) != 0)) {
dbb9a2
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
dbb9a2
+        return (SECFailure);
dbb9a2
+    }
dbb9a2
+
dbb9a2
     return (SECSuccess);
dbb9a2
 }
dbb9a2
 
dbb9a2
 /* Known Hash Message (512-bits).  Used for all hashes (incl. SHA-N [N>1]). */
dbb9a2
 static const PRUint8 known_hash_message[] = {
dbb9a2
     "The test message for the MD2, MD5, and SHA-1 hashing algorithms."
dbb9a2
 };
dbb9a2
 
dbb9a2
@@ -1089,17 +1181,17 @@ freebl_fips_ECDSA_Test(ECParams *ecparam
dbb9a2
         0x7b, 0x5a, 0x3b, 0x76, 0x4e, 0x7b, 0x7c, 0xbc,
dbb9a2
         0xf2, 0x76, 0x1c, 0x1c, 0x7f, 0xc5, 0x53, 0x2f
dbb9a2
     };
dbb9a2
 
dbb9a2
     static const PRUint8 msg[] = {
dbb9a2
         "Firefox and ThunderBird are awesome!"
dbb9a2
     };
dbb9a2
 
dbb9a2
-    unsigned char sha1[SHA1_LENGTH]; /* SHA-1 hash (160 bits) */
dbb9a2
+    unsigned char sha256[SHA256_LENGTH]; /* SHA-256 hash (256 bits) */
dbb9a2
     unsigned char sig[2 * MAX_ECKEY_LEN];
dbb9a2
     SECItem signature, digest;
dbb9a2
     ECPrivateKey *ecdsa_private_key = NULL;
dbb9a2
     ECPublicKey ecdsa_public_key;
dbb9a2
     SECStatus ecdsaStatus = SECSuccess;
dbb9a2
 
dbb9a2
     /* Generates a new EC key pair. The private key is a supplied
dbb9a2
      * random value (in seed) and the public key is the result of
dbb9a2
@@ -1131,23 +1223,23 @@ freebl_fips_ECDSA_Test(ECParams *ecparam
dbb9a2
     if (ecdsaStatus != SECSuccess) {
dbb9a2
         goto loser;
dbb9a2
     }
dbb9a2
 
dbb9a2
     /***************************************************/
dbb9a2
     /* ECDSA Single-Round Known Answer Signature Test. */
dbb9a2
     /***************************************************/
dbb9a2
 
dbb9a2
-    ecdsaStatus = SHA1_HashBuf(sha1, msg, sizeof msg);
dbb9a2
+    ecdsaStatus = SHA256_HashBuf(sha256, msg, sizeof msg);
dbb9a2
     if (ecdsaStatus != SECSuccess) {
dbb9a2
         goto loser;
dbb9a2
     }
dbb9a2
     digest.type = siBuffer;
dbb9a2
-    digest.data = sha1;
dbb9a2
-    digest.len = SHA1_LENGTH;
dbb9a2
+    digest.data = sha256;
dbb9a2
+    digest.len = SHA256_LENGTH;
dbb9a2
 
dbb9a2
     memset(sig, 0, sizeof sig);
dbb9a2
     signature.type = siBuffer;
dbb9a2
     signature.data = sig;
dbb9a2
     signature.len = sizeof sig;
dbb9a2
 
dbb9a2
     ecdsaStatus = ECDSA_SignDigestWithSeed(ecdsa_private_key, &signature,
dbb9a2
                                            &digest, ecdsa_Known_Seed, sizeof ecdsa_Known_Seed);
dbb9a2
@@ -1176,20 +1268,93 @@ loser:
dbb9a2
     if (ecdsaStatus != SECSuccess) {
dbb9a2
         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
dbb9a2
         return (SECFailure);
dbb9a2
     }
dbb9a2
     return (SECSuccess);
dbb9a2
 }
dbb9a2
 
dbb9a2
 static SECStatus
dbb9a2
-freebl_fips_ECDSA_PowerUpSelfTest()
dbb9a2
+freebl_fips_ECDH_Test(ECParams *ecparams)
dbb9a2
 {
dbb9a2
 
dbb9a2
-    /* ECDSA Known curve nistp256 == ECCCurve_X9_62_PRIME_256V1 params */
dbb9a2
+    /* ECDH Known result (reused old CAVS vector)  */
dbb9a2
+    static const PRUint8 ecdh_known_pub_key_1[] = {
dbb9a2
+        EC_POINT_FORM_UNCOMPRESSED,
dbb9a2
+        /* pubX */
dbb9a2
+        0x16, 0x81, 0x32, 0x86, 0xc8, 0xe4, 0x3a, 0x1f,
dbb9a2
+        0x5d, 0xe3, 0x06, 0x22, 0x8b, 0x99, 0x14, 0x25,
dbb9a2
+        0xf7, 0x9c, 0x5b, 0x1e, 0x96, 0x84, 0x85, 0x3b,
dbb9a2
+        0x17, 0xfe, 0xf3, 0x1c, 0x0e, 0xed, 0xc4, 0xce,
dbb9a2
+        /* pubY */
dbb9a2
+        0x7a, 0x44, 0xfe, 0xbd, 0x91, 0x71, 0x7d, 0x73,
dbb9a2
+        0xd9, 0x45, 0xea, 0xae, 0x66, 0x78, 0xfa, 0x6e,
dbb9a2
+        0x46, 0xcd, 0xfa, 0x95, 0x15, 0x47, 0x62, 0x5d,
dbb9a2
+        0xbb, 0x1b, 0x9f, 0xe6, 0x39, 0xfc, 0xfd, 0x47
dbb9a2
+    };
dbb9a2
+    static const PRUint8 ecdh_known_priv_key_2[] = {
dbb9a2
+        0xb4, 0x2a, 0xe3, 0x69, 0x19, 0xec, 0xf0, 0x42,
dbb9a2
+        0x6d, 0x45, 0x8c, 0x94, 0x4a, 0x26, 0xa7, 0x5c,
dbb9a2
+        0xea, 0x9d, 0xd9, 0x0f, 0x59, 0xe0, 0x1a, 0x9d,
dbb9a2
+        0x7c, 0xb7, 0x1c, 0x04, 0x53, 0xb8, 0x98, 0x5a
dbb9a2
+    };
dbb9a2
+    static const PRUint8 ecdh_known_hash_result[] = {
dbb9a2
+        0x16, 0xf3, 0x85, 0xa2, 0x41, 0xf3, 0x7f, 0xc4,
dbb9a2
+        0x0b, 0x56, 0x47, 0xee, 0xa7, 0x74, 0xb9, 0xdb,
dbb9a2
+        0xe1, 0xfa, 0x22, 0xe9, 0x04, 0xf1, 0xb6, 0x12,
dbb9a2
+        0x4b, 0x44, 0x8a, 0xbb, 0xbc, 0x08, 0x2b, 0xa7,
dbb9a2
+    };
dbb9a2
+
dbb9a2
+    SECItem ecdh_priv_2, ecdh_pub_1;
dbb9a2
+    SECItem ZZ = { 0, 0, 0 };
dbb9a2
+    SECStatus ecdhStatus = SECSuccess;
dbb9a2
+    PRUint8 computed_hash_result[HASH_LENGTH_MAX];
dbb9a2
+
dbb9a2
+    ecdh_priv_2.data = (PRUint8 *)ecdh_known_priv_key_2;
dbb9a2
+    ecdh_priv_2.len = sizeof(ecdh_known_priv_key_2);
dbb9a2
+    ecdh_pub_1.data = (PRUint8 *)ecdh_known_pub_key_1;
dbb9a2
+    ecdh_pub_1.len = sizeof(ecdh_known_pub_key_1);
dbb9a2
+
dbb9a2
+    /* Generates a new EC key pair. The private key is a supplied
dbb9a2
+     * random value (in seed) and the public key is the result of
dbb9a2
+     * performing a scalar point multiplication of that value with
dbb9a2
+     * the curve's base point.
dbb9a2
+     */
dbb9a2
+    ecdhStatus = ECDH_Derive(&ecdh_pub_1, ecparams, &ecdh_priv_2, PR_FALSE, &ZZ;;
dbb9a2
+    if (ecdhStatus != SECSuccess) {
dbb9a2
+        goto loser;
dbb9a2
+    }
dbb9a2
+    ecdhStatus = SHA256_HashBuf(computed_hash_result, ZZ.data, ZZ.len);
dbb9a2
+    if (ecdhStatus != SECSuccess) {
dbb9a2
+        goto loser;
dbb9a2
+    }
dbb9a2
+
dbb9a2
+    if (PORT_Memcmp(computed_hash_result, ecdh_known_hash_result,
dbb9a2
+                    sizeof(ecdh_known_hash_result)) != 0) {
dbb9a2
+        ecdhStatus = SECFailure;
dbb9a2
+        goto loser;
dbb9a2
+    }
dbb9a2
+
dbb9a2
+loser:
dbb9a2
+    if (ZZ.data) {
dbb9a2
+        SECITEM_FreeItem(&ZZ, PR_FALSE);
dbb9a2
+    }
dbb9a2
+
dbb9a2
+    if (ecdhStatus != SECSuccess) {
dbb9a2
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
dbb9a2
+        return (SECFailure);
dbb9a2
+    }
dbb9a2
+    return (SECSuccess);
dbb9a2
+}
dbb9a2
+
dbb9a2
+static SECStatus
dbb9a2
+freebl_fips_EC_PowerUpSelfTest()
dbb9a2
+{
dbb9a2
+
dbb9a2
+    /* EC Known curve nistp256 == ECCCurve_X9_62_PRIME_256V1 params */
dbb9a2
     static const unsigned char p256_prime[] = {
dbb9a2
         0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
dbb9a2
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
dbb9a2
         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
dbb9a2
     };
dbb9a2
     static const unsigned char p256_a[] = {
dbb9a2
         0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
dbb9a2
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
dbb9a2
@@ -1212,17 +1377,17 @@ freebl_fips_ECDSA_PowerUpSelfTest()
dbb9a2
     static const unsigned char p256_order[] = {
dbb9a2
         0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
dbb9a2
         0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9,
dbb9a2
         0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
dbb9a2
     };
dbb9a2
     static const unsigned char p256_encoding[] = {
dbb9a2
         0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
dbb9a2
     };
dbb9a2
-    static const ECParams ecdsa_known_P256_Params = {
dbb9a2
+    static const ECParams ec_known_P256_Params = {
dbb9a2
         NULL, ec_params_named,                                               /* arena, type */
dbb9a2
                                                                              /* fieldID */
dbb9a2
         { 256, ec_field_GFp,                                                 /* size and type */
dbb9a2
           { { siBuffer, (unsigned char *)p256_prime, sizeof(p256_prime) } }, /* u.prime */
dbb9a2
           0,
dbb9a2
           0,
dbb9a2
           0 },
dbb9a2
         /* curve */
dbb9a2
@@ -1245,34 +1410,39 @@ freebl_fips_ECDSA_PowerUpSelfTest()
dbb9a2
         { siBuffer, (unsigned char *)(p256_encoding) + 2, sizeof(p256_encoding) - 2 },
dbb9a2
     };
dbb9a2
 
dbb9a2
     static const PRUint8 ecdsa_known_P256_signature[] = {
dbb9a2
         0x07, 0xb1, 0xcb, 0x57, 0x20, 0xa7, 0x10, 0xd6,
dbb9a2
         0x9d, 0x37, 0x4b, 0x1c, 0xdc, 0x35, 0x90, 0xff,
dbb9a2
         0x1a, 0x2d, 0x98, 0x95, 0x1b, 0x2f, 0xeb, 0x7f,
dbb9a2
         0xbb, 0x81, 0xca, 0xc0, 0x69, 0x75, 0xea, 0xc5,
dbb9a2
-        0x59, 0x6a, 0x62, 0x49, 0x3d, 0x50, 0xc9, 0xe1,
dbb9a2
-        0x27, 0x3b, 0xff, 0x9b, 0x13, 0x66, 0x67, 0xdd,
dbb9a2
-        0x7d, 0xd1, 0x0d, 0x2d, 0x7c, 0x44, 0x04, 0x1b,
dbb9a2
-        0x16, 0x21, 0x12, 0xc5, 0xcb, 0xbd, 0x9e, 0x75
dbb9a2
+        0xa7, 0xd2, 0x20, 0xdd, 0x45, 0xf9, 0x2b, 0xdd,
dbb9a2
+        0xda, 0x98, 0x99, 0x5b, 0x1c, 0x02, 0x3a, 0x27,
dbb9a2
+        0x8b, 0x7d, 0xb6, 0xed, 0x0e, 0xe0, 0xa7, 0xac,
dbb9a2
+        0xaa, 0x36, 0x2c, 0xfa, 0x1a, 0xdf, 0x0d, 0xe1,
dbb9a2
     };
dbb9a2
 
dbb9a2
     ECParams ecparams;
dbb9a2
 
dbb9a2
     SECStatus rv;
dbb9a2
 
dbb9a2
     /* ECDSA GF(p) prime field curve test */
dbb9a2
-    ecparams = ecdsa_known_P256_Params;
dbb9a2
+    ecparams = ec_known_P256_Params;
dbb9a2
     rv = freebl_fips_ECDSA_Test(&ecparams,
dbb9a2
                                 ecdsa_known_P256_signature,
dbb9a2
                                 sizeof ecdsa_known_P256_signature);
dbb9a2
     if (rv != SECSuccess) {
dbb9a2
         return (SECFailure);
dbb9a2
     }
dbb9a2
+    /* ECDH GF(p) prime field curve test */
dbb9a2
+    rv = freebl_fips_ECDH_Test(&ecparams);
dbb9a2
+    if (rv != SECSuccess) {
dbb9a2
+        return (SECFailure);
dbb9a2
+    }
dbb9a2
 
dbb9a2
     return (SECSuccess);
dbb9a2
 }
dbb9a2
 
dbb9a2
 static SECStatus
dbb9a2
 freebl_fips_DSA_PowerUpSelfTest(void)
dbb9a2
 {
dbb9a2
     /* DSA Known P (1024-bits), Q (160-bits), and G (1024-bits) Values. */
dbb9a2
@@ -1413,16 +1583,148 @@ freebl_fips_DSA_PowerUpSelfTest(void)
dbb9a2
         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
dbb9a2
         return SECFailure;
dbb9a2
     }
dbb9a2
 
dbb9a2
     return (SECSuccess);
dbb9a2
 }
dbb9a2
 
dbb9a2
 static SECStatus
dbb9a2
+freebl_fips_DH_PowerUpSelfTest(void)
dbb9a2
+{
dbb9a2
+    /* DH Known P (2048-bits) */
dbb9a2
+    static const PRUint8 dh_known_P[] = {
dbb9a2
+        0xc2, 0x79, 0xbb, 0x76, 0x32, 0x0d, 0x43, 0xfd,
dbb9a2
+        0x1b, 0x8c, 0xa2, 0x3c, 0x00, 0xdd, 0x6d, 0xef,
dbb9a2
+        0xf8, 0x1a, 0xd9, 0xc1, 0xa2, 0xf5, 0x73, 0x2b,
dbb9a2
+        0xdb, 0x1a, 0x3e, 0x84, 0x90, 0xeb, 0xe7, 0x8e,
dbb9a2
+        0x5f, 0x5c, 0x6b, 0xb6, 0x61, 0x89, 0xd1, 0x03,
dbb9a2
+        0xb0, 0x5f, 0x91, 0xe4, 0xd2, 0x82, 0x90, 0xfc,
dbb9a2
+        0x3c, 0x49, 0x69, 0x59, 0xc1, 0x51, 0x6a, 0x85,
dbb9a2
+        0x71, 0xe7, 0x5d, 0x72, 0x5a, 0x45, 0xad, 0x01,
dbb9a2
+        0x6f, 0x82, 0xae, 0xec, 0x91, 0x08, 0x2e, 0x7c,
dbb9a2
+        0x64, 0x93, 0x46, 0x1c, 0x68, 0xef, 0xc2, 0x03,
dbb9a2
+        0x28, 0x1d, 0x75, 0x3a, 0xeb, 0x9c, 0x46, 0xf0,
dbb9a2
+        0xc9, 0xdb, 0x99, 0x95, 0x13, 0x66, 0x4d, 0xd5,
dbb9a2
+        0x1a, 0x78, 0x92, 0x51, 0x89, 0x72, 0x28, 0x7f,
dbb9a2
+        0x20, 0x70, 0x41, 0x49, 0xa2, 0x86, 0xe9, 0xf9,
dbb9a2
+        0x78, 0x5f, 0x8d, 0x2e, 0x5d, 0xfa, 0xdb, 0x57,
dbb9a2
+        0xd4, 0x71, 0xdf, 0x66, 0xe3, 0x9e, 0x88, 0x70,
dbb9a2
+        0xa4, 0x21, 0x44, 0x6a, 0xc7, 0xae, 0x30, 0x2c,
dbb9a2
+        0x9c, 0x1f, 0x91, 0x57, 0xc8, 0x24, 0x34, 0x2d,
dbb9a2
+        0x7a, 0x4a, 0x43, 0xc2, 0x5f, 0xab, 0x64, 0x2e,
dbb9a2
+        0xaa, 0x28, 0x32, 0x95, 0x42, 0x7b, 0xa0, 0xcc,
dbb9a2
+        0xdf, 0xfd, 0x22, 0xc8, 0x56, 0x84, 0xc1, 0x62,
dbb9a2
+        0x15, 0xb2, 0x77, 0x86, 0x81, 0xfc, 0xa5, 0x12,
dbb9a2
+        0x3c, 0xca, 0x28, 0x17, 0x8f, 0x03, 0x16, 0x6e,
dbb9a2
+        0xb8, 0x24, 0xfa, 0x1b, 0x15, 0x02, 0xfd, 0x8b,
dbb9a2
+        0xb6, 0x0a, 0x1a, 0xf7, 0x47, 0x41, 0xc5, 0x2b,
dbb9a2
+        0x37, 0x3e, 0xa1, 0xbf, 0x68, 0xda, 0x1c, 0x55,
dbb9a2
+        0x44, 0xc3, 0xee, 0xa1, 0x63, 0x07, 0x11, 0x3b,
dbb9a2
+        0x5f, 0x00, 0x84, 0xb4, 0xc4, 0xe4, 0xa7, 0x97,
dbb9a2
+        0x29, 0xf8, 0xce, 0xab, 0xfc, 0x27, 0x3e, 0x34,
dbb9a2
+        0xe4, 0xc7, 0x81, 0x52, 0x32, 0x0e, 0x27, 0x3c,
dbb9a2
+        0xa6, 0x70, 0x3f, 0x4a, 0x54, 0xda, 0xdd, 0x60,
dbb9a2
+        0x26, 0xb3, 0x6e, 0x45, 0x26, 0x19, 0x41, 0x6f
dbb9a2
+    };
dbb9a2
+
dbb9a2
+    static const PRUint8 dh_known_Y_1[] = {
dbb9a2
+        0xb4, 0xc7, 0x85, 0xba, 0xa6, 0x98, 0xb3, 0x77,
dbb9a2
+        0x41, 0x2b, 0xd9, 0x9a, 0x72, 0x90, 0xa4, 0xac,
dbb9a2
+        0xc4, 0xf7, 0xc2, 0x23, 0x9a, 0x68, 0xe2, 0x7d,
dbb9a2
+        0x3a, 0x54, 0x45, 0x91, 0xc1, 0xd7, 0x8a, 0x17,
dbb9a2
+        0x54, 0xd3, 0x37, 0xaa, 0x0c, 0xcd, 0x0b, 0xe2,
dbb9a2
+        0xf2, 0x34, 0x0f, 0x17, 0xa8, 0x07, 0x88, 0xaf,
dbb9a2
+        0xed, 0xc1, 0x02, 0xd4, 0xdb, 0xdc, 0x0f, 0x22,
dbb9a2
+        0x51, 0x23, 0x40, 0xb9, 0x65, 0x6d, 0x39, 0xf4,
dbb9a2
+        0xe1, 0x8b, 0x57, 0x7d, 0xb6, 0xd3, 0xf2, 0x6b,
dbb9a2
+        0x02, 0xa9, 0x36, 0xf0, 0x0d, 0xe3, 0xdb, 0x9a,
dbb9a2
+        0xbf, 0x20, 0x00, 0x4d, 0xec, 0x6f, 0x68, 0x95,
dbb9a2
+        0xee, 0x59, 0x4e, 0x3c, 0xb6, 0xda, 0x7b, 0x19,
dbb9a2
+        0x08, 0x9a, 0xef, 0x61, 0x43, 0xf5, 0xfb, 0x25,
dbb9a2
+        0x70, 0x19, 0xc1, 0x5f, 0x0e, 0x0f, 0x6a, 0x63,
dbb9a2
+        0x44, 0xe9, 0xcf, 0x33, 0xce, 0x13, 0x4f, 0x34,
dbb9a2
+        0x3c, 0x94, 0x40, 0x8d, 0xf2, 0x65, 0x42, 0xef,
dbb9a2
+        0x70, 0x54, 0xdd, 0x5f, 0xc1, 0xd7, 0x0b, 0xa6,
dbb9a2
+        0x06, 0xd5, 0xa6, 0x47, 0xae, 0x2c, 0x1f, 0x5a,
dbb9a2
+        0xa6, 0xb3, 0xc1, 0x38, 0x3a, 0x3b, 0x60, 0x94,
dbb9a2
+        0xa2, 0x95, 0xab, 0xb2, 0x86, 0x82, 0xc5, 0x3b,
dbb9a2
+        0xb8, 0x6f, 0x3e, 0x55, 0x86, 0x84, 0xe0, 0x00,
dbb9a2
+        0xe5, 0xef, 0xca, 0x5c, 0xec, 0x7e, 0x38, 0x0f,
dbb9a2
+        0x82, 0xa2, 0xb1, 0xee, 0x48, 0x1b, 0x32, 0xbb,
dbb9a2
+        0x5a, 0x33, 0xa5, 0x01, 0xba, 0xca, 0xa6, 0x64,
dbb9a2
+        0x61, 0xb6, 0xe5, 0x5c, 0x0e, 0x5f, 0x2c, 0x66,
dbb9a2
+        0x0d, 0x01, 0x6a, 0x20, 0x04, 0x70, 0x68, 0x82,
dbb9a2
+        0x93, 0x29, 0x15, 0x3b, 0x7a, 0x06, 0xb2, 0x92,
dbb9a2
+        0x61, 0xcd, 0x7e, 0xa4, 0xc1, 0x15, 0x64, 0x3b,
dbb9a2
+        0x3c, 0x51, 0x10, 0x4c, 0x87, 0xa6, 0xaf, 0x07,
dbb9a2
+        0xce, 0x46, 0x82, 0x75, 0xf3, 0x90, 0xf3, 0x21,
dbb9a2
+        0x55, 0x74, 0xc2, 0xe4, 0x96, 0x7d, 0xc3, 0xe6,
dbb9a2
+        0x33, 0xa5, 0xc6, 0x51, 0xef, 0xec, 0x90, 0x08
dbb9a2
+    };
dbb9a2
+
dbb9a2
+    static const PRUint8 dh_known_x_2[] = {
dbb9a2
+        0x9e, 0x9b, 0xc3, 0x25, 0x53, 0xf9, 0xfc, 0x92,
dbb9a2
+        0xb6, 0xae, 0x54, 0x8e, 0x23, 0x4c, 0x94, 0xba,
dbb9a2
+        0x41, 0xe6, 0x29, 0x33, 0xb9, 0xdb, 0xff, 0x6d,
dbb9a2
+        0xa8, 0xb8, 0x48, 0x49, 0x66, 0x11, 0xa6, 0x13
dbb9a2
+    };
dbb9a2
+
dbb9a2
+    static const PRUint8 dh_known_hash_result[] = {
dbb9a2
+        0x93, 0xa2, 0x89, 0x1c, 0x8a, 0xc3, 0x70, 0xbf,
dbb9a2
+        0xa7, 0xdf, 0xb6, 0xd7, 0x82, 0xfb, 0x87, 0x81,
dbb9a2
+        0x09, 0x47, 0xf3, 0x9f, 0x5a, 0xbf, 0x4f, 0x3f,
dbb9a2
+        0x8e, 0x5e, 0x06, 0xca, 0x30, 0xa7, 0xaf, 0x10
dbb9a2
+    };
dbb9a2
+
dbb9a2
+    /* DH variables. */
dbb9a2
+    SECStatus dhStatus;
dbb9a2
+    SECItem dh_prime;
dbb9a2
+    SECItem dh_pub_key_1;
dbb9a2
+    SECItem dh_priv_key_2;
dbb9a2
+    SECItem ZZ = { 0, 0, 0 };
dbb9a2
+    PRUint8 computed_hash_result[HASH_LENGTH_MAX];
dbb9a2
+
dbb9a2
+    dh_prime.data = (PRUint8 *)dh_known_P;
dbb9a2
+    dh_prime.len = sizeof(dh_known_P);
dbb9a2
+    dh_pub_key_1.data = (PRUint8 *)dh_known_Y_1;
dbb9a2
+    dh_pub_key_1.len = sizeof(dh_known_Y_1);
dbb9a2
+    dh_priv_key_2.data = (PRUint8 *)dh_known_x_2;
dbb9a2
+    dh_priv_key_2.len = sizeof(dh_known_x_2);
dbb9a2
+
dbb9a2
+    /* execute the derive */
dbb9a2
+    dhStatus = DH_Derive(&dh_pub_key_1, &dh_prime, &dh_priv_key_2, &ZZ, dh_prime.len);
dbb9a2
+    if (dhStatus != SECSuccess) {
dbb9a2
+        goto loser;
dbb9a2
+    }
dbb9a2
+
dbb9a2
+    dhStatus = SHA256_HashBuf(computed_hash_result, ZZ.data, ZZ.len);
dbb9a2
+    if (dhStatus != SECSuccess) {
dbb9a2
+        goto loser;
dbb9a2
+    }
dbb9a2
+
dbb9a2
+    if (PORT_Memcmp(computed_hash_result, dh_known_hash_result,
dbb9a2
+                    sizeof(dh_known_hash_result)) != 0) {
dbb9a2
+        dhStatus = SECFailure;
dbb9a2
+        goto loser;
dbb9a2
+    }
dbb9a2
+
dbb9a2
+loser:
dbb9a2
+    if (ZZ.data) {
dbb9a2
+        SECITEM_FreeItem(&ZZ, PR_FALSE);
dbb9a2
+    }
dbb9a2
+
dbb9a2
+    if (dhStatus != SECSuccess) {
dbb9a2
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
dbb9a2
+        return (SECFailure);
dbb9a2
+    }
dbb9a2
+    return (SECSuccess);
dbb9a2
+}
dbb9a2
+
dbb9a2
+static SECStatus
dbb9a2
 freebl_fips_RNG_PowerUpSelfTest(void)
dbb9a2
 {
dbb9a2
     static const PRUint8 Q[] = {
dbb9a2
         0x85, 0x89, 0x9c, 0x77, 0xa3, 0x79, 0xff, 0x1a,
dbb9a2
         0x86, 0x6f, 0x2f, 0x3e, 0x2e, 0xf9, 0x8c, 0x9c,
dbb9a2
         0x9d, 0xef, 0xeb, 0xed
dbb9a2
     };
dbb9a2
     static const PRUint8 GENX[] = {
dbb9a2
@@ -1536,31 +1838,37 @@ freebl_fipsPowerUpSelfTest(unsigned int 
dbb9a2
 
dbb9a2
         /* HMAC SHA-X Power-Up SelfTest(s). */
dbb9a2
         rv = freebl_fips_HMAC_PowerUpSelfTest();
dbb9a2
 
dbb9a2
         if (rv != SECSuccess)
dbb9a2
             return rv;
dbb9a2
 
dbb9a2
         /* NOTE: RSA can only be tested in full freebl. It requires access to
dbb9a2
-     * the locking primitives */
dbb9a2
+         * the locking primitives */
dbb9a2
         /* RSA Power-Up SelfTest(s). */
dbb9a2
         rv = freebl_fips_RSA_PowerUpSelfTest();
dbb9a2
 
dbb9a2
         if (rv != SECSuccess)
dbb9a2
             return rv;
dbb9a2
 
dbb9a2
         /* DSA Power-Up SelfTest(s). */
dbb9a2
         rv = freebl_fips_DSA_PowerUpSelfTest();
dbb9a2
 
dbb9a2
         if (rv != SECSuccess)
dbb9a2
             return rv;
dbb9a2
 
dbb9a2
-        /* ECDSA Power-Up SelfTest(s). */
dbb9a2
-        rv = freebl_fips_ECDSA_PowerUpSelfTest();
dbb9a2
+        /* DH Power-Up SelfTest(s). */
dbb9a2
+        rv = freebl_fips_DH_PowerUpSelfTest();
dbb9a2
+
dbb9a2
+        if (rv != SECSuccess)
dbb9a2
+            return rv;
dbb9a2
+
dbb9a2
+        /* EC Power-Up SelfTest(s). */
dbb9a2
+        rv = freebl_fips_EC_PowerUpSelfTest();
dbb9a2
 
dbb9a2
         if (rv != SECSuccess)
dbb9a2
             return rv;
dbb9a2
     }
dbb9a2
     /* Passed Power-Up SelfTest(s). */
dbb9a2
     return (SECSuccess);
dbb9a2
 }
dbb9a2
 
dbb9a2
diff --git a/lib/freebl/intel-gcm-wrap.c b/lib/freebl/intel-gcm-wrap.c
dbb9a2
--- a/lib/freebl/intel-gcm-wrap.c
dbb9a2
+++ b/lib/freebl/intel-gcm-wrap.c
dbb9a2
@@ -138,16 +138,17 @@ intel_AES_GCM_CreateContext(void *contex
dbb9a2
 loser:
dbb9a2
     PORT_Free(gcm);
dbb9a2
     return NULL;
dbb9a2
 }
dbb9a2
 
dbb9a2
 void
dbb9a2
 intel_AES_GCM_DestroyContext(intel_AES_GCMContext *gcm, PRBool freeit)
dbb9a2
 {
dbb9a2
+    PORT_Memset(gcm, 0, sizeof(intel_AES_GCMContext));
dbb9a2
     if (freeit) {
dbb9a2
         PORT_Free(gcm);
dbb9a2
     }
dbb9a2
 }
dbb9a2
 
dbb9a2
 SECStatus
dbb9a2
 intel_AES_GCM_EncryptUpdate(intel_AES_GCMContext *gcm,
dbb9a2
                             unsigned char *outbuf,
dbb9a2
diff --git a/lib/freebl/pqg.c b/lib/freebl/pqg.c
dbb9a2
--- a/lib/freebl/pqg.c
dbb9a2
+++ b/lib/freebl/pqg.c
dbb9a2
@@ -486,21 +486,21 @@ cleanup:
dbb9a2
 **  Perform steps from  FIPS 186-3, Appendix A.1.2.1 and Appendix C.6
dbb9a2
 **
dbb9a2
 **  This generates a provable prime from two smaller prime. The resulting
dbb9a2
 **  prime p will have q0 as a multiple of p-1. q0 can be 1.
dbb9a2
 **
dbb9a2
 ** This implments steps 4 thorough 22 of FIPS 186-3 A.1.2.1 and
dbb9a2
 **                steps 16 through 34 of FIPS 186-2 C.6
dbb9a2
 */
dbb9a2
-#define MAX_ST_SEED_BITS (HASH_LENGTH_MAX * PR_BITS_PER_BYTE)
dbb9a2
 static SECStatus
dbb9a2
 makePrimefromPrimesShaweTaylor(
dbb9a2
     HASH_HashType hashtype,          /* selected Hashing algorithm */
dbb9a2
     unsigned int length,             /* input. Length of prime in bits. */
dbb9a2
+    unsigned int seedlen,            /* input seed length in bits */
dbb9a2
     mp_int *c0,                      /* seed prime */
dbb9a2
     mp_int *q,                       /* sub prime, can be 1 */
dbb9a2
     mp_int *prime,                   /* output.  */
dbb9a2
     SECItem *prime_seed,             /* input/output.  */
dbb9a2
     unsigned int *prime_gen_counter) /* input/output.  */
dbb9a2
 {
dbb9a2
     mp_int c;
dbb9a2
     mp_int c0_2;
dbb9a2
@@ -552,33 +552,32 @@ makePrimefromPrimesShaweTaylor(
dbb9a2
     */
dbb9a2
 
dbb9a2
     /* Step 4/16 iterations = ceiling(length/outlen)-1 */
dbb9a2
     iterations = (length + outlen - 1) / outlen; /* NOTE: iterations +1 */
dbb9a2
     /* Step 5/17 old_counter = prime_gen_counter */
dbb9a2
     old_counter = *prime_gen_counter;
dbb9a2
     /*
dbb9a2
     ** Comment: Generate a pseudorandom integer x in the interval
dbb9a2
-    ** [2**(lenght-1), 2**length].
dbb9a2
+    ** [2**(length-1), 2**length].
dbb9a2
     **
dbb9a2
     ** Step 6/18 x = 0
dbb9a2
     */
dbb9a2
     PORT_Memset(x, 0, sizeof(x));
dbb9a2
     /*
dbb9a2
     ** Step 7/19 for i = 0 to iterations do
dbb9a2
     **  x = x + (HASH(prime_seed + i) * 2^(i*outlen))
dbb9a2
     */
dbb9a2
     for (i = 0; i < iterations; i++) {
dbb9a2
         /* is bigger than prime_seed should get to */
dbb9a2
         CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, i,
dbb9a2
-                                       MAX_ST_SEED_BITS, &x[(iterations - i - 1) * hashlen]));
dbb9a2
+                                       seedlen, &x[(iterations - i - 1) * hashlen]));
dbb9a2
     }
dbb9a2
     /* Step 8/20 prime_seed = prime_seed + iterations + 1 */
dbb9a2
-    CHECK_SEC_OK(addToSeed(prime_seed, iterations, MAX_ST_SEED_BITS,
dbb9a2
-                           prime_seed));
dbb9a2
+    CHECK_SEC_OK(addToSeed(prime_seed, iterations, seedlen, prime_seed));
dbb9a2
     /*
dbb9a2
     ** Step 9/21 x = 2 ** (length-1) + x mod 2 ** (length-1)
dbb9a2
     **
dbb9a2
     **   This step mathematically sets the high bit and clears out
dbb9a2
     **  all the other bits higher than length. 'x' is stored
dbb9a2
     **  in the x array, MSB first. The above formula gives us an 'x'
dbb9a2
     **  which is length bytes long and has the high bit set. We also know
dbb9a2
     **  that length <= iterations*outlen since
dbb9a2
@@ -590,17 +589,17 @@ makePrimefromPrimesShaweTaylor(
dbb9a2
      * multiple of 8,*/
dbb9a2
     bit = 1 << ((length - 1) & 0x7); /* select the proper bit in the byte */
dbb9a2
     /* we need to zero out the rest of the bits in the byte above */
dbb9a2
     mask = (bit - 1);
dbb9a2
     /* now we set it */
dbb9a2
     x[offset] = (mask & x[offset]) | bit;
dbb9a2
     /*
dbb9a2
     ** Comment: Generate a candidate prime c in the interval
dbb9a2
-    ** [2**(lenght-1), 2**length].
dbb9a2
+    ** [2**(length-1), 2**length].
dbb9a2
     **
dbb9a2
     ** Step 10 t = ceiling(x/(2q(p0)))
dbb9a2
     ** Step 22 t = ceiling(x/(2(c0)))
dbb9a2
     */
dbb9a2
     CHECK_MPI_OK(mp_read_unsigned_octets(&t, &x[offset],
dbb9a2
                                          hashlen * iterations - offset)); /* t = x */
dbb9a2
     CHECK_MPI_OK(mp_mul(c0, q, &c0_2));                                   /* c0_2 is now c0*q */
dbb9a2
     CHECK_MPI_OK(mp_add(&c0_2, &c0_2, &c0_2));                            /* c0_2 is now 2*q*c0 */
dbb9a2
@@ -619,17 +618,17 @@ makePrimefromPrimesShaweTaylor(
dbb9a2
 step_23:
dbb9a2
     CHECK_MPI_OK(mp_mul(&t, &c0_2, &c);;                /* c = t*2qc0 */
dbb9a2
     CHECK_MPI_OK(mp_add_d(&c, (mp_digit)1, &c);;        /* c= 2tqc0 + 1*/
dbb9a2
     if (mpl_significant_bits(&c) > length) {            /* if c > 2**length */
dbb9a2
         CHECK_MPI_OK(mp_sub_d(&c0_2, (mp_digit)1, &t);; /* t = 2qc0-1 */
dbb9a2
         /* t = 2**(length-1) + 2qc0 -1 */
dbb9a2
         CHECK_MPI_OK(mp_add(&two_length_minus_1, &t, &t);;
dbb9a2
         /* t = floor((2**(length-1)+2qc0 -1)/2qco)
dbb9a2
-         *   = ceil(2**(lenght-2)/2qc0) */
dbb9a2
+         *   = ceil(2**(length-2)/2qc0) */
dbb9a2
         CHECK_MPI_OK(mp_div(&t, &c0_2, &t, NULL));
dbb9a2
         CHECK_MPI_OK(mp_mul(&t, &c0_2, &c);;
dbb9a2
         CHECK_MPI_OK(mp_add_d(&c, (mp_digit)1, &c);; /* c= 2tqc0 + 1*/
dbb9a2
     }
dbb9a2
     /* Step 13/25 prime_gen_counter = prime_gen_counter + 1*/
dbb9a2
     (*prime_gen_counter)++;
dbb9a2
     /*
dbb9a2
     ** Comment: Test the candidate prime c for primality; first pick an
dbb9a2
@@ -640,23 +639,21 @@ step_23:
dbb9a2
     PORT_Memset(x, 0, sizeof(x)); /* use x for a */
dbb9a2
     /*
dbb9a2
     ** Step 15/27 for i = 0 to iterations do
dbb9a2
     **  a = a + (HASH(prime_seed + i) * 2^(i*outlen))
dbb9a2
     **
dbb9a2
     ** NOTE: we reuse the x array for 'a' initially.
dbb9a2
     */
dbb9a2
     for (i = 0; i < iterations; i++) {
dbb9a2
-        /* MAX_ST_SEED_BITS is bigger than prime_seed should get to */
dbb9a2
         CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, i,
dbb9a2
-                                       MAX_ST_SEED_BITS, &x[(iterations - i - 1) * hashlen]));
dbb9a2
+                                       seedlen, &x[(iterations - i - 1) * hashlen]));
dbb9a2
     }
dbb9a2
     /* Step 16/28 prime_seed = prime_seed + iterations + 1 */
dbb9a2
-    CHECK_SEC_OK(addToSeed(prime_seed, iterations, MAX_ST_SEED_BITS,
dbb9a2
-                           prime_seed));
dbb9a2
+    CHECK_SEC_OK(addToSeed(prime_seed, iterations, seedlen, prime_seed));
dbb9a2
     /* Step 17/29 a = 2 + (a mod (c-3)). */
dbb9a2
     CHECK_MPI_OK(mp_read_unsigned_octets(&a, x, iterations * hashlen));
dbb9a2
     CHECK_MPI_OK(mp_sub_d(&c, (mp_digit)3, &z);; /* z = c -3 */
dbb9a2
     CHECK_MPI_OK(mp_mod(&a, &z, &a);;            /* a = a mod c -3 */
dbb9a2
     CHECK_MPI_OK(mp_add_d(&a, (mp_digit)2, &a);; /* a = 2 + a mod c -3 */
dbb9a2
     /*
dbb9a2
     ** Step 18 z = a**(2tq) mod p.
dbb9a2
     ** Step 30 z = a**(2t) mod c.
dbb9a2
@@ -737,16 +734,17 @@ makePrimefromSeedShaweTaylor(
dbb9a2
 {
dbb9a2
     mp_int c;
dbb9a2
     mp_int c0;
dbb9a2
     mp_int one;
dbb9a2
     SECStatus rv = SECFailure;
dbb9a2
     int hashlen = HASH_ResultLen(hashtype);
dbb9a2
     int outlen = hashlen * PR_BITS_PER_BYTE;
dbb9a2
     int offset;
dbb9a2
+    int seedlen = input_seed->len * 8; /*seedlen is in bits */
dbb9a2
     unsigned char bit, mask;
dbb9a2
     unsigned char x[HASH_LENGTH_MAX * 2];
dbb9a2
     mp_digit dummy;
dbb9a2
     mp_err err = MP_OKAY;
dbb9a2
     int i;
dbb9a2
 
dbb9a2
     MP_DIGITS(&c) = 0;
dbb9a2
     MP_DIGITS(&c0) = 0;
dbb9a2
@@ -770,30 +768,29 @@ makePrimefromSeedShaweTaylor(
dbb9a2
     */
dbb9a2
         rv = makePrimefromSeedShaweTaylor(hashtype, (length + 1) / 2 + 1,
dbb9a2
                                           input_seed, &c0, prime_seed, prime_gen_counter);
dbb9a2
         /* Step 15 if FAILURE is returned, return (FAILURE, 0, 0, 0). */
dbb9a2
         if (rv != SECSuccess) {
dbb9a2
             goto cleanup;
dbb9a2
         }
dbb9a2
         /* Steps 16-34 */
dbb9a2
-        rv = makePrimefromPrimesShaweTaylor(hashtype, length, &c0, &one,
dbb9a2
+        rv = makePrimefromPrimesShaweTaylor(hashtype, length, seedlen, &c0, &one,
dbb9a2
                                             prime, prime_seed, prime_gen_counter);
dbb9a2
         goto cleanup; /* we're done, one way or the other */
dbb9a2
     }
dbb9a2
     /* Step 3 prime_seed = input_seed */
dbb9a2
     CHECK_SEC_OK(SECITEM_CopyItem(NULL, prime_seed, input_seed));
dbb9a2
     /* Step 4 prime_gen_count = 0 */
dbb9a2
     *prime_gen_counter = 0;
dbb9a2
 
dbb9a2
 step_5:
dbb9a2
     /* Step 5 c = Hash(prime_seed) xor Hash(prime_seed+1). */
dbb9a2
     CHECK_SEC_OK(HASH_HashBuf(hashtype, x, prime_seed->data, prime_seed->len));
dbb9a2
-    CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, 1,
dbb9a2
-                                   MAX_ST_SEED_BITS, &x[hashlen]));
dbb9a2
+    CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, 1, seedlen, &x[hashlen]));
dbb9a2
     for (i = 0; i < hashlen; i++) {
dbb9a2
         x[i] = x[i] ^ x[i + hashlen];
dbb9a2
     }
dbb9a2
     /* Step 6 c = 2**length-1 + c mod 2**length-1 */
dbb9a2
     /*   This step mathematically sets the high bit and clears out
dbb9a2
     **  all the other bits higher than length. Right now c is stored
dbb9a2
     **  in the x array, MSB first. The above formula gives us a c which
dbb9a2
     **  is length bytes long and has the high bit set. We also know that
dbb9a2
@@ -812,17 +809,17 @@ step_5:
dbb9a2
     /* Step 7 c = c*floor(c/2) + 1 */
dbb9a2
     /* set the low bit. much easier to find (the end of the array) */
dbb9a2
     x[hashlen - 1] |= 1;
dbb9a2
     /* now that we've set our bits, we can create our candidate "c" */
dbb9a2
     CHECK_MPI_OK(mp_read_unsigned_octets(&c, &x[offset], hashlen - offset));
dbb9a2
     /* Step 8 prime_gen_counter = prime_gen_counter + 1 */
dbb9a2
     (*prime_gen_counter)++;
dbb9a2
     /* Step 9 prime_seed = prime_seed + 2 */
dbb9a2
-    CHECK_SEC_OK(addToSeed(prime_seed, 2, MAX_ST_SEED_BITS, prime_seed));
dbb9a2
+    CHECK_SEC_OK(addToSeed(prime_seed, 2, seedlen, prime_seed));
dbb9a2
     /* Step 10 Perform deterministic primality test on c. For example, since
dbb9a2
     ** c is small, it's primality can be tested by trial division, See
dbb9a2
     ** See Appendic C.7.
dbb9a2
     **
dbb9a2
     ** We in fact test with trial division. mpi has a built int trial divider
dbb9a2
     ** that divides all divisors up to 2^16.
dbb9a2
     */
dbb9a2
     if (prime_tab[prime_tab_size - 1] < 0xFFF1) {
dbb9a2
@@ -885,17 +882,18 @@ findQfromSeed(
dbb9a2
     unsigned int L,             /* input.  Length of p in bits. */
dbb9a2
     unsigned int N,             /* input.  Length of q in bits. */
dbb9a2
     unsigned int g,             /* input.  Length of seed in bits. */
dbb9a2
     const SECItem *seed,        /* input.  */
dbb9a2
     mp_int *Q,                  /* input. */
dbb9a2
     mp_int *Q_,                 /* output. */
dbb9a2
     unsigned int *qseed_len,    /* output */
dbb9a2
     HASH_HashType *hashtypePtr, /* output. Hash uses */
dbb9a2
-    pqgGenType *typePtr)        /* output. Generation Type used */
dbb9a2
+    pqgGenType *typePtr,        /* output. Generation Type used */
dbb9a2
+    unsigned int *qgen_counter) /* output. q_counter */
dbb9a2
 {
dbb9a2
     HASH_HashType hashtype;
dbb9a2
     SECItem firstseed = { 0, 0, 0 };
dbb9a2
     SECItem qseed = { 0, 0, 0 };
dbb9a2
     SECStatus rv;
dbb9a2
 
dbb9a2
     *qseed_len = 0; /* only set if FIPS186_3_ST_TYPE */
dbb9a2
 
dbb9a2
@@ -959,16 +957,17 @@ findQfromSeed(
dbb9a2
          * accident, someone has been tweeking with the seeds, just
dbb9a2
          * fail a this point. */
dbb9a2
                 SECITEM_FreeItem(&qseed, PR_FALSE);
dbb9a2
                 return SECFailure;
dbb9a2
             }
dbb9a2
             *qseed_len = qseed.len;
dbb9a2
             *hashtypePtr = hashtype;
dbb9a2
             *typePtr = FIPS186_3_ST_TYPE;
dbb9a2
+            *qgen_counter = count;
dbb9a2
             SECITEM_FreeItem(&qseed, PR_FALSE);
dbb9a2
             return SECSuccess;
dbb9a2
         }
dbb9a2
         SECITEM_FreeItem(&qseed, PR_FALSE);
dbb9a2
     }
dbb9a2
     /* no hash algorithms found which match seed to Q, fail */
dbb9a2
     return SECFailure;
dbb9a2
 }
dbb9a2
@@ -1383,29 +1382,33 @@ step_5:
dbb9a2
         CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, N, &firstseed, &Q,
dbb9a2
                                                   &qseed, &qgen_counter));
dbb9a2
         /* Step 3. Use floor(L/2+1) and qseed to generate random prime p0
dbb9a2
      * using Appendix C.6 */
dbb9a2
         pgen_counter = 0;
dbb9a2
         CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, (L + 1) / 2 + 1,
dbb9a2
                                                   &qseed, &p0, &pseed, &pgen_counter));
dbb9a2
         /* Steps 4-22 FIPS 186-3 appendix A.1.2.1.2 */
dbb9a2
-        CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L,
dbb9a2
+        CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L, seedBytes * 8,
dbb9a2
                                                     &p0, &Q, &P, &pseed, &pgen_counter));
dbb9a2
 
dbb9a2
         /* combine all the seeds */
dbb9a2
-        seed->len = firstseed.len + qseed.len + pseed.len;
dbb9a2
+        if ((qseed.len > firstseed.len) || (pseed.len > firstseed.len)) {
dbb9a2
+            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); /* shouldn't happen */
dbb9a2
+            goto cleanup;
dbb9a2
+        }
dbb9a2
+        seed->len = firstseed.len * 3; /*handle leading zeros in pseed and qseed*/
dbb9a2
         seed->data = PORT_ArenaZAlloc(verify->arena, seed->len);
dbb9a2
         if (seed->data == NULL) {
dbb9a2
             goto cleanup;
dbb9a2
         }
dbb9a2
         PORT_Memcpy(seed->data, firstseed.data, firstseed.len);
dbb9a2
-        PORT_Memcpy(seed->data + firstseed.len, pseed.data, pseed.len);
dbb9a2
-        PORT_Memcpy(seed->data + firstseed.len + pseed.len, qseed.data, qseed.len);
dbb9a2
-        counter = 0; /* (qgen_counter << 16) | pgen_counter; */
dbb9a2
+        PORT_Memcpy(seed->data + 2 * firstseed.len - pseed.len, pseed.data, pseed.len);
dbb9a2
+        PORT_Memcpy(seed->data + 3 * firstseed.len - qseed.len, qseed.data, qseed.len);
dbb9a2
+        counter = (qgen_counter << 16) | pgen_counter;
dbb9a2
 
dbb9a2
         /* we've generated both P and Q now, skip to generating G */
dbb9a2
         goto generate_G;
dbb9a2
     }
dbb9a2
     /* ******************************************************************
dbb9a2
     ** Step 8. (Step 4 in 186-1)
dbb9a2
     ** "Use a robust primality testing algorithm to test whether q is prime."
dbb9a2
     **
dbb9a2
@@ -1615,16 +1618,17 @@ PQG_VerifyParams(const PQGParams *params
dbb9a2
 {
dbb9a2
     SECStatus rv = SECSuccess;
dbb9a2
     unsigned int g, n, L, N, offset, outlen;
dbb9a2
     mp_int p0, P, Q, G, P_, Q_, G_, r, h;
dbb9a2
     mp_err err = MP_OKAY;
dbb9a2
     int j;
dbb9a2
     unsigned int counter_max = 0; /* handle legacy L < 1024 */
dbb9a2
     unsigned int qseed_len;
dbb9a2
+    unsigned int qgen_counter_ = 0;
dbb9a2
     SECItem pseed_ = { 0, 0, 0 };
dbb9a2
     HASH_HashType hashtype;
dbb9a2
     pqgGenType type;
dbb9a2
 
dbb9a2
 #define CHECKPARAM(cond)      \
dbb9a2
     if (!(cond)) {            \
dbb9a2
         *result = SECFailure; \
dbb9a2
         goto cleanup;         \
dbb9a2
@@ -1694,77 +1698,104 @@ PQG_VerifyParams(const PQGParams *params
dbb9a2
     CHECKPARAM(mp_cmp_d(&r, 1) == 0);
dbb9a2
     /* 5.  Q is prime */
dbb9a2
     CHECKPARAM(mpp_pprime(&Q, prime_testcount_q(L, N)) == MP_YES);
dbb9a2
     /* 6.  P is prime */
dbb9a2
     CHECKPARAM(mpp_pprime(&P, prime_testcount_p(L, N)) == MP_YES);
dbb9a2
     /* Steps 7-12 are done only if the optional PQGVerify is supplied. */
dbb9a2
     /* continue processing P */
dbb9a2
     /* 7.  counter < 4*L */
dbb9a2
-    CHECKPARAM((vfy->counter == -1) || (vfy->counter < counter_max));
dbb9a2
     /* 8.  g >= N and g < 2*L   (g is length of seed in bits) */
dbb9a2
-    g = vfy->seed.len * 8;
dbb9a2
-    CHECKPARAM(g >= N && g < counter_max / 2);
dbb9a2
+    /* step 7 and 8 are delayed until we determine which type of generation
dbb9a2
+     * was used */
dbb9a2
     /* 9.  Q generated from SEED matches Q in PQGParams. */
dbb9a2
     /* This function checks all possible hash and generation types to
dbb9a2
      * find a Q_ which matches Q. */
dbb9a2
+    g = vfy->seed.len * 8;
dbb9a2
     CHECKPARAM(findQfromSeed(L, N, g, &vfy->seed, &Q, &Q_, &qseed_len,
dbb9a2
-                             &hashtype, &type) == SECSuccess);
dbb9a2
+                             &hashtype, &type, &qgen_counter_) == SECSuccess);
dbb9a2
     CHECKPARAM(mp_cmp(&Q, &Q_) == 0);
dbb9a2
+    /* now we can do steps 7  & 8*/
dbb9a2
+    if ((type == FIPS186_1_TYPE) || (type == FIPS186_3_TYPE)) {
dbb9a2
+        CHECKPARAM((vfy->counter == -1) || (vfy->counter < counter_max));
dbb9a2
+        CHECKPARAM(g >= N && g < counter_max / 2);
dbb9a2
+    }
dbb9a2
     if (type == FIPS186_3_ST_TYPE) {
dbb9a2
         SECItem qseed = { 0, 0, 0 };
dbb9a2
         SECItem pseed = { 0, 0, 0 };
dbb9a2
         unsigned int first_seed_len;
dbb9a2
-        unsigned int pgen_counter = 0;
dbb9a2
+        unsigned int pgen_counter_ = 0;
dbb9a2
+        unsigned int qgen_counter = (vfy->counter >> 16) & 0xffff;
dbb9a2
+        unsigned int pgen_counter = (vfy->counter) & 0xffff;
dbb9a2
 
dbb9a2
         /* extract pseed and qseed from domain_parameter_seed, which is
dbb9a2
          * first_seed || pseed || qseed. qseed is first_seed + small_integer
dbb9a2
-         * pseed is qseed + small_integer. This means most of the time
dbb9a2
+         * mod the length of first_seed. pseed is qseed + small_integer mod
dbb9a2
+         * the length of first_seed. This means most of the time
dbb9a2
          * first_seed.len == qseed.len == pseed.len. Rarely qseed.len and/or
dbb9a2
-         * pseed.len will be one greater than first_seed.len, so we can
dbb9a2
-         * depend on the fact that
dbb9a2
-         *   first_seed.len = floor(domain_parameter_seed.len/3).
dbb9a2
-         * findQfromSeed returned qseed.len, so we can calculate pseed.len as
dbb9a2
-         *   pseed.len = domain_parameter_seed.len - first_seed.len - qseed.len
dbb9a2
-         * this is probably over kill, since 99.999% of the time they will all
dbb9a2
-         * be equal.
dbb9a2
-         *
dbb9a2
-         * With the lengths, we can now find the offsets;
dbb9a2
+         * pseed.len will be smaller because mpi clamps them. pqgGen
dbb9a2
+         * automatically adds the zero pad back though, so we can depend
dbb9a2
+         * domain_parameter_seed.len to be a multiple of three. We only have
dbb9a2
+         * to deal with the fact that the returned seeds from our functions
dbb9a2
+         * could be shorter.
dbb9a2
+         *   first_seed.len = domain_parameter_seed.len/3
dbb9a2
+         * We can now find the offsets;
dbb9a2
          * first_seed.data = domain_parameter_seed.data + 0
dbb9a2
          * pseed.data = domain_parameter_seed.data + first_seed.len
dbb9a2
          * qseed.data = domain_parameter_seed.data
dbb9a2
          *         + domain_paramter_seed.len - qseed.len
dbb9a2
-         *
dbb9a2
+         * We deal with pseed possibly having zero pad in the pseed check later.
dbb9a2
          */
dbb9a2
         first_seed_len = vfy->seed.len / 3;
dbb9a2
         CHECKPARAM(qseed_len < vfy->seed.len);
dbb9a2
         CHECKPARAM(first_seed_len * 8 > N - 1);
dbb9a2
-        CHECKPARAM(first_seed_len + qseed_len < vfy->seed.len);
dbb9a2
+        CHECKPARAM(first_seed_len * 8 < counter_max / 2);
dbb9a2
+        CHECKPARAM(first_seed_len >= qseed_len);
dbb9a2
         qseed.len = qseed_len;
dbb9a2
         qseed.data = vfy->seed.data + vfy->seed.len - qseed.len;
dbb9a2
-        pseed.len = vfy->seed.len - (first_seed_len + qseed_len);
dbb9a2
+        pseed.len = first_seed_len;
dbb9a2
         pseed.data = vfy->seed.data + first_seed_len;
dbb9a2
 
dbb9a2
         /*
dbb9a2
          * now complete FIPS 186-3 A.1.2.1.2. Step 1 was completed
dbb9a2
          * above in our initial checks, Step 2 was completed by
dbb9a2
          * findQfromSeed */
dbb9a2
 
dbb9a2
         /* Step 3 (status, c0, prime_seed, prime_gen_counter) =
dbb9a2
         ** (ST_Random_Prime((ceil(length/2)+1, input_seed)
dbb9a2
         */
dbb9a2
         CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, (L + 1) / 2 + 1,
dbb9a2
-                                                  &qseed, &p0, &pseed_, &pgen_counter));
dbb9a2
+                                                  &qseed, &p0, &pseed_, &pgen_counter_));
dbb9a2
         /* Steps 4-22 FIPS 186-3 appendix A.1.2.1.2 */
dbb9a2
-        CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L,
dbb9a2
-                                                    &p0, &Q_, &P_, &pseed_, &pgen_counter));
dbb9a2
+        CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L, first_seed_len * 8,
dbb9a2
+                                                    &p0, &Q_, &P_, &pseed_, &pgen_counter_));
dbb9a2
         CHECKPARAM(mp_cmp(&P, &P_) == 0);
dbb9a2
         /* make sure pseed wasn't tampered with (since it is part of
dbb9a2
          * calculating G) */
dbb9a2
+        if (pseed.len > pseed_.len) {
dbb9a2
+            /* handle the case of zero pad for pseed */
dbb9a2
+            int extra = pseed.len - pseed_.len;
dbb9a2
+            int i;
dbb9a2
+            for (i = 0; i < extra; i++) {
dbb9a2
+                if (pseed.data[i] != 0) {
dbb9a2
+                    *result = SECFailure;
dbb9a2
+                    goto cleanup;
dbb9a2
+                }
dbb9a2
+            }
dbb9a2
+            pseed.data += extra;
dbb9a2
+            pseed.len -= extra;
dbb9a2
+            /* the rest is handled in the normal compare below */
dbb9a2
+        }
dbb9a2
         CHECKPARAM(SECITEM_CompareItem(&pseed, &pseed_) == SECEqual);
dbb9a2
+        if (vfy->counter != -1) {
dbb9a2
+            CHECKPARAM(pgen_counter < counter_max);
dbb9a2
+            CHECKPARAM(qgen_counter < counter_max);
dbb9a2
+            CHECKPARAM((pgen_counter_ == pgen_counter));
dbb9a2
+            CHECKPARAM((qgen_counter_ == qgen_counter));
dbb9a2
+        }
dbb9a2
     } else if (vfy->counter == -1) {
dbb9a2
         /* If counter is set to -1, we are really only verifying G, skip
dbb9a2
          * the remainder of the checks for P */
dbb9a2
         CHECKPARAM(type != FIPS186_1_TYPE); /* we only do this for DSA2 */
dbb9a2
     } else {
dbb9a2
         /* 10. P generated from (L, counter, g, SEED, Q) matches P
dbb9a2
          * in PQGParams. */
dbb9a2
         outlen = HASH_ResultLen(hashtype) * PR_BITS_PER_BYTE;
dbb9a2
diff --git a/lib/freebl/rijndael.c b/lib/freebl/rijndael.c
dbb9a2
--- a/lib/freebl/rijndael.c
dbb9a2
+++ b/lib/freebl/rijndael.c
dbb9a2
@@ -1027,23 +1027,25 @@ AES_CreateContext(const unsigned char *k
dbb9a2
  * AES_DestroyContext
dbb9a2
  *
dbb9a2
  * Zero an AES cipher context.  If freeit is true, also free the pointer
dbb9a2
  * to the context.
dbb9a2
  */
dbb9a2
 void
dbb9a2
 AES_DestroyContext(AESContext *cx, PRBool freeit)
dbb9a2
 {
dbb9a2
+    void *mem = cx->mem;
dbb9a2
     if (cx->worker_cx && cx->destroy) {
dbb9a2
         (*cx->destroy)(cx->worker_cx, PR_TRUE);
dbb9a2
         cx->worker_cx = NULL;
dbb9a2
         cx->destroy = NULL;
dbb9a2
     }
dbb9a2
+    PORT_Memset(cx, 0, sizeof(AESContext));
dbb9a2
     if (freeit) {
dbb9a2
-        PORT_Free(cx->mem);
dbb9a2
+        PORT_Free(mem);
dbb9a2
     }
dbb9a2
 }
dbb9a2
 
dbb9a2
 /*
dbb9a2
  * AES_Encrypt
dbb9a2
  *
dbb9a2
  * Encrypt an arbitrary-length buffer.  The output buffer must already be
dbb9a2
  * allocated to at least inputLen.
dbb9a2
diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c
dbb9a2
--- a/lib/softoken/pkcs11c.c
dbb9a2
+++ b/lib/softoken/pkcs11c.c
dbb9a2
@@ -4708,16 +4708,24 @@ sftk_PairwiseConsistencyCheck(CK_SESSION
dbb9a2
                        pairwise_digest_length,
dbb9a2
                        signature,
dbb9a2
                        &signature_length);
dbb9a2
         if (crv != CKR_OK) {
dbb9a2
             PORT_Free(signature);
dbb9a2
             return crv;
dbb9a2
         }
dbb9a2
 
dbb9a2
+        /* detect trivial signing transforms */
dbb9a2
+        if (signature_length >= pairwise_digest_length) {
dbb9a2
+            if (PORT_Memcmp(known_digest, signature + (signature_length - pairwise_digest_length), pairwise_digest_length) == 0) {
dbb9a2
+                PORT_Free(signature);
dbb9a2
+                return CKR_DEVICE_ERROR;
dbb9a2
+            }
dbb9a2
+        }
dbb9a2
+
dbb9a2
         /* Verify the known hash using the public key. */
dbb9a2
         crv = NSC_VerifyInit(hSession, &mech, publicKey->handle);
dbb9a2
         if (crv != CKR_OK) {
dbb9a2
             PORT_Free(signature);
dbb9a2
             return crv;
dbb9a2
         }
dbb9a2
 
dbb9a2
         crv = NSC_Verify(hSession,
dbb9a2
@@ -7543,40 +7551,55 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
dbb9a2
             SHA512_HashBuf(key_block, (const unsigned char *)att->attrib.pValue,
dbb9a2
                            att->attrib.ulValueLen);
dbb9a2
 
dbb9a2
             crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize);
dbb9a2
             break;
dbb9a2
 
dbb9a2
         case CKM_DH_PKCS_DERIVE: {
dbb9a2
             SECItem derived, dhPublic;
dbb9a2
-            SECItem dhPrime, dhValue;
dbb9a2
+            SECItem dhPrime, dhSubPrime, dhValue;
dbb9a2
             /* sourceKey - values for the local existing low key */
dbb9a2
             /* get prime and value attributes */
dbb9a2
             crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME);
dbb9a2
-            if (crv != SECSuccess)
dbb9a2
+            if (crv != CKR_OK)
dbb9a2
                 break;
dbb9a2
             crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE);
dbb9a2
-            if (crv != SECSuccess) {
dbb9a2
+            if (crv != CKR_OK) {
dbb9a2
                 PORT_Free(dhPrime.data);
dbb9a2
                 break;
dbb9a2
             }
dbb9a2
 
dbb9a2
             dhPublic.data = pMechanism->pParameter;
dbb9a2
             dhPublic.len = pMechanism->ulParameterLen;
dbb9a2
 
dbb9a2
+            /* if the caller bothered to provide Q, use Q to validate.
dbb9a2
+             * the public key */
dbb9a2
+            crv = sftk_Attribute2SecItem(NULL, &dhSubPrime, sourceKey, CKA_SUBPRIME);
dbb9a2
+            if (crv == CKR_OK) {
dbb9a2
+                rv = KEA_Verify(&dhPublic, &dhPrime, &dhSubPrime);
dbb9a2
+                PORT_Free(dhSubPrime.data);
dbb9a2
+                if (rv != SECSuccess) {
dbb9a2
+                    crv = CKR_ARGUMENTS_BAD;
dbb9a2
+                    PORT_Free(dhPrime.data);
dbb9a2
+                    PORT_Free(dhValue.data);
dbb9a2
+                    break;
dbb9a2
+                }
dbb9a2
+            }
dbb9a2
+
dbb9a2
             /* calculate private value - oct */
dbb9a2
             rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize);
dbb9a2
 
dbb9a2
             PORT_Free(dhPrime.data);
dbb9a2
             PORT_Free(dhValue.data);
dbb9a2
 
dbb9a2
             if (rv == SECSuccess) {
dbb9a2
                 sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
dbb9a2
                 PORT_ZFree(derived.data, derived.len);
dbb9a2
+                crv = CKR_OK;
dbb9a2
             } else
dbb9a2
                 crv = CKR_HOST_MEMORY;
dbb9a2
 
dbb9a2
             break;
dbb9a2
         }
dbb9a2
 
dbb9a2
         case CKM_ECDH1_DERIVE:
dbb9a2
         case CKM_ECDH1_COFACTOR_DERIVE: {