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

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