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

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