Blame SOURCES/nss-3.44-handle-malformed-ecdh-gtests.patch

a6c4ed
diff -up ./gtests/pk11_gtest/manifest.mn.handle-malformed-ecdh-gtests ./gtests/pk11_gtest/manifest.mn
a6c4ed
--- ./gtests/pk11_gtest/manifest.mn.handle-malformed-ecdh-gtests	2019-12-05 10:56:41.827832606 -0800
a6c4ed
+++ ./gtests/pk11_gtest/manifest.mn	2019-12-05 10:59:53.802966671 -0800
a6c4ed
@@ -10,16 +10,18 @@ CPPSRCS = \
a6c4ed
       pk11_aeskeywrap_unittest.cc \
a6c4ed
       pk11_chacha20poly1305_unittest.cc \
a6c4ed
       pk11_curve25519_unittest.cc \
a6c4ed
+      pk11_der_private_key_import_unittest.cc \
a6c4ed
       pk11_ecdsa_unittest.cc \
a6c4ed
       pk11_encrypt_derive_unittest.cc \
a6c4ed
       pk11_export_unittest.cc \
a6c4ed
       pk11_import_unittest.cc \
a6c4ed
+      pk11_keygen.cc \
a6c4ed
+      pk11_key_unittest.cc \
a6c4ed
       pk11_pbkdf2_unittest.cc \
a6c4ed
       pk11_prf_unittest.cc \
a6c4ed
       pk11_prng_unittest.cc \
a6c4ed
       pk11_rsapkcs1_unittest.cc \
a6c4ed
       pk11_rsapss_unittest.cc \
a6c4ed
-      pk11_der_private_key_import_unittest.cc \
a6c4ed
       $(NULL)
a6c4ed
 
a6c4ed
 INCLUDES += -I$(CORE_DEPTH)/gtests/google_test/gtest/include \
a6c4ed
diff -up ./gtests/pk11_gtest/pk11_gtest.gyp.handle-malformed-ecdh-gtests ./gtests/pk11_gtest/pk11_gtest.gyp
a6c4ed
--- ./gtests/pk11_gtest/pk11_gtest.gyp.handle-malformed-ecdh-gtests	2019-12-05 10:56:41.828832617 -0800
a6c4ed
+++ ./gtests/pk11_gtest/pk11_gtest.gyp	2019-12-05 11:01:38.874134681 -0800
a6c4ed
@@ -11,20 +11,22 @@
a6c4ed
       'target_name': 'pk11_gtest',
a6c4ed
       'type': 'executable',
a6c4ed
       'sources': [
a6c4ed
-        'pk11_aeskeywrap_unittest.cc',
a6c4ed
         'pk11_aes_gcm_unittest.cc',
a6c4ed
+        'pk11_aeskeywrap_unittest.cc',
a6c4ed
         'pk11_chacha20poly1305_unittest.cc',
a6c4ed
         'pk11_cipherop_unittest.cc',
a6c4ed
         'pk11_curve25519_unittest.cc',
a6c4ed
+        'pk11_der_private_key_import_unittest.cc',
a6c4ed
         'pk11_ecdsa_unittest.cc',
a6c4ed
         'pk11_encrypt_derive_unittest.cc',
a6c4ed
         'pk11_import_unittest.cc',
a6c4ed
+        'pk11_keygen.cc',
a6c4ed
+        'pk11_key_unittest.cc',
a6c4ed
         'pk11_pbkdf2_unittest.cc',
a6c4ed
         'pk11_prf_unittest.cc',
a6c4ed
         'pk11_prng_unittest.cc',
a6c4ed
         'pk11_rsapkcs1_unittest.cc',
a6c4ed
         'pk11_rsapss_unittest.cc',
a6c4ed
-        'pk11_der_private_key_import_unittest.cc',
a6c4ed
         '<(DEPTH)/gtests/common/gtests.cc'
a6c4ed
       ],
a6c4ed
       'dependencies': [
a6c4ed
diff -up ./gtests/pk11_gtest/pk11_import_unittest.cc.handle-malformed-ecdh-gtests ./gtests/pk11_gtest/pk11_import_unittest.cc
a6c4ed
--- ./gtests/pk11_gtest/pk11_import_unittest.cc.handle-malformed-ecdh-gtests	2019-12-05 10:56:41.821832539 -0800
a6c4ed
+++ ./gtests/pk11_gtest/pk11_import_unittest.cc	2019-12-05 11:08:42.394842692 -0800
a6c4ed
@@ -15,6 +15,7 @@
a6c4ed
 #include "nss_scoped_ptrs.h"
a6c4ed
 #include "gtest/gtest.h"
a6c4ed
 #include "databuffer.h"
a6c4ed
+#include "pk11_keygen.h"
a6c4ed
 
a6c4ed
 namespace nss_test {
a6c4ed
 
a6c4ed
@@ -30,7 +31,7 @@ struct PK11GenericObjectsDeleter {
a6c4ed
 
a6c4ed
 class Pk11KeyImportTestBase : public ::testing::Test {
a6c4ed
  public:
a6c4ed
-  Pk11KeyImportTestBase(CK_MECHANISM_TYPE mech) : mech_(mech) {}
a6c4ed
+  Pk11KeyImportTestBase() = default;
a6c4ed
   virtual ~Pk11KeyImportTestBase() = default;
a6c4ed
 
a6c4ed
   void SetUp() override {
a6c4ed
@@ -42,12 +43,18 @@ class Pk11KeyImportTestBase : public ::t
a6c4ed
     password_.reset(SECITEM_DupItem(&pwItem));
a6c4ed
   }
a6c4ed
 
a6c4ed
-  void Test() {
a6c4ed
+  void Test(const Pkcs11KeyPairGenerator& generator) {
a6c4ed
     // Generate a key and export it.
a6c4ed
-    KeyType key_type;
a6c4ed
+    KeyType key_type = nullKey;
a6c4ed
     ScopedSECKEYEncryptedPrivateKeyInfo key_info;
a6c4ed
     ScopedSECItem public_value;
a6c4ed
-    GenerateAndExport(&key_type, &key_info, &public_value);
a6c4ed
+    GenerateAndExport(generator, &key_type, &key_info, &public_value);
a6c4ed
+
a6c4ed
+    // Note: NSS is currently unable export wrapped DH keys, so this doesn't
a6c4ed
+    // test those beyond generate and verify.
a6c4ed
+    if (key_type == dhKey) {
a6c4ed
+      return;
a6c4ed
+    }
a6c4ed
     ASSERT_NE(nullptr, key_info);
a6c4ed
     ASSERT_NE(nullptr, public_value);
a6c4ed
 
a6c4ed
@@ -66,17 +73,6 @@ class Pk11KeyImportTestBase : public ::t
a6c4ed
     CheckForPublicKey(priv_key, public_value.get());
a6c4ed
   }
a6c4ed
 
a6c4ed
- protected:
a6c4ed
-  class ParamHolder {
a6c4ed
-   public:
a6c4ed
-    virtual ~ParamHolder() = default;
a6c4ed
-    virtual void* get() = 0;
a6c4ed
-  };
a6c4ed
-
a6c4ed
-  virtual std::unique_ptr<ParamHolder> MakeParams() = 0;
a6c4ed
-
a6c4ed
-  CK_MECHANISM_TYPE mech_;
a6c4ed
-
a6c4ed
  private:
a6c4ed
   SECItem GetPublicComponent(ScopedSECKEYPublicKey& pub_key) {
a6c4ed
     SECItem null = { siBuffer, NULL, 0};
a6c4ed
@@ -196,20 +192,14 @@ class Pk11KeyImportTestBase : public ::t
a6c4ed
     }
a6c4ed
   }
a6c4ed
 
a6c4ed
-  void GenerateAndExport(KeyType* key_type,
a6c4ed
+  void GenerateAndExport(const Pkcs11KeyPairGenerator& generator,
a6c4ed
+                         KeyType* key_type,
a6c4ed
                          ScopedSECKEYEncryptedPrivateKeyInfo* key_info,
a6c4ed
                          ScopedSECItem* public_value) {
a6c4ed
-    auto params = MakeParams();
a6c4ed
-    ASSERT_NE(nullptr, params);
a6c4ed
-
a6c4ed
-    SECKEYPublicKey* pub_tmp;
a6c4ed
-    ScopedSECKEYPrivateKey priv_key(
a6c4ed
-        PK11_GenerateKeyPair(slot_.get(), mech_, params->get(), &pub_tmp,
a6c4ed
-                             PR_FALSE, PR_TRUE, nullptr));
a6c4ed
-    ASSERT_NE(nullptr, priv_key) << "PK11_GenerateKeyPair failed: "
a6c4ed
-                                 << PORT_ErrorToName(PORT_GetError());
a6c4ed
-    ScopedSECKEYPublicKey pub_key(pub_tmp);
a6c4ed
-    ASSERT_NE(nullptr, pub_key);
a6c4ed
+    ScopedSECKEYPrivateKey priv_key;
a6c4ed
+    ScopedSECKEYPublicKey pub_key;
a6c4ed
+    generator.GenerateKey(&priv_key, &pub_key);
a6c4ed
+    ASSERT_TRUE(priv_key);
a6c4ed
 
a6c4ed
     // Wrap and export the key.
a6c4ed
     ScopedSECKEYEncryptedPrivateKeyInfo epki(PK11_ExportEncryptedPrivKeyInfo(
a6c4ed
@@ -239,6 +229,11 @@ class Pk11KeyImportTestBase : public ::t
a6c4ed
     }
a6c4ed
 
a6c4ed
     CheckForPublicKey(priv_key, pub_val);
a6c4ed
+    // Note: NSS is currently unable export wrapped DH keys, so this doesn't
a6c4ed
+    // test those beyond generate and verify.
a6c4ed
+    if (t == dhKey) {
a6c4ed
+      return;
a6c4ed
+    }
a6c4ed
 
a6c4ed
     *key_type = t;
a6c4ed
     key_info->swap(epki);
a6c4ed
@@ -253,82 +248,13 @@ class Pk11KeyImportTest
a6c4ed
     : public Pk11KeyImportTestBase,
a6c4ed
       public ::testing::WithParamInterface<CK_MECHANISM_TYPE> {
a6c4ed
  public:
a6c4ed
-  Pk11KeyImportTest() : Pk11KeyImportTestBase(GetParam()) {}
a6c4ed
+  Pk11KeyImportTest() = default;
a6c4ed
   virtual ~Pk11KeyImportTest() = default;
a6c4ed
-
a6c4ed
- protected:
a6c4ed
-  std::unique_ptr<ParamHolder> MakeParams() override {
a6c4ed
-    switch (mech_) {
a6c4ed
-      case CKM_RSA_PKCS_KEY_PAIR_GEN:
a6c4ed
-        return std::unique_ptr<ParamHolder>(new RsaParamHolder());
a6c4ed
-
a6c4ed
-      case CKM_DSA_KEY_PAIR_GEN:
a6c4ed
-      case CKM_DH_PKCS_KEY_PAIR_GEN: {
a6c4ed
-        PQGParams* pqg_params = nullptr;
a6c4ed
-        PQGVerify* pqg_verify = nullptr;
a6c4ed
-        const unsigned int key_size = 1024;
a6c4ed
-        SECStatus rv = PK11_PQG_ParamGenV2(key_size, 0, key_size / 16,
a6c4ed
-                                           &pqg_params, &pqg_verify);
a6c4ed
-        if (rv != SECSuccess) {
a6c4ed
-          ADD_FAILURE() << "PK11_PQG_ParamGenV2 failed";
a6c4ed
-          return nullptr;
a6c4ed
-        }
a6c4ed
-        EXPECT_NE(nullptr, pqg_verify);
a6c4ed
-        EXPECT_NE(nullptr, pqg_params);
a6c4ed
-        PK11_PQG_DestroyVerify(pqg_verify);
a6c4ed
-        if (mech_ == CKM_DSA_KEY_PAIR_GEN) {
a6c4ed
-          return std::unique_ptr<ParamHolder>(new PqgParamHolder(pqg_params));
a6c4ed
-        }
a6c4ed
-        return std::unique_ptr<ParamHolder>(new DhParamHolder(pqg_params));
a6c4ed
-      }
a6c4ed
-
a6c4ed
-      default:
a6c4ed
-        ADD_FAILURE() << "unknown OID " << mech_;
a6c4ed
-    }
a6c4ed
-    return nullptr;
a6c4ed
-  }
a6c4ed
-
a6c4ed
- private:
a6c4ed
-  class RsaParamHolder : public ParamHolder {
a6c4ed
-   public:
a6c4ed
-    RsaParamHolder()
a6c4ed
-        : params_({/*.keySizeInBits = */ 1024, /*.pe = */ 0x010001}) {}
a6c4ed
-    ~RsaParamHolder() = default;
a6c4ed
-
a6c4ed
-    void* get() override { return &params_; }
a6c4ed
-
a6c4ed
-   private:
a6c4ed
-    PK11RSAGenParams params_;
a6c4ed
-  };
a6c4ed
-
a6c4ed
-  class PqgParamHolder : public ParamHolder {
a6c4ed
-   public:
a6c4ed
-    PqgParamHolder(PQGParams* params) : params_(params) {}
a6c4ed
-    ~PqgParamHolder() = default;
a6c4ed
-
a6c4ed
-    void* get() override { return params_.get(); }
a6c4ed
-
a6c4ed
-   private:
a6c4ed
-    ScopedPQGParams params_;
a6c4ed
-  };
a6c4ed
-
a6c4ed
-  class DhParamHolder : public PqgParamHolder {
a6c4ed
-   public:
a6c4ed
-    DhParamHolder(PQGParams* params)
a6c4ed
-        : PqgParamHolder(params),
a6c4ed
-          params_({/*.arena = */ nullptr,
a6c4ed
-                   /*.prime = */ params->prime,
a6c4ed
-                   /*.base = */ params->base}) {}
a6c4ed
-    ~DhParamHolder() = default;
a6c4ed
-
a6c4ed
-    void* get() override { return &params_; }
a6c4ed
-
a6c4ed
-   private:
a6c4ed
-    SECKEYDHParams params_;
a6c4ed
-  };
a6c4ed
 };
a6c4ed
 
a6c4ed
-TEST_P(Pk11KeyImportTest, GenerateExportImport) { Test(); }
a6c4ed
+TEST_P(Pk11KeyImportTest, GenerateExportImport) {
a6c4ed
+  Test(Pkcs11KeyPairGenerator(GetParam()));
a6c4ed
+}
a6c4ed
 
a6c4ed
 INSTANTIATE_TEST_CASE_P(Pk11KeyImportTest, Pk11KeyImportTest,
a6c4ed
                         ::testing::Values(CKM_RSA_PKCS_KEY_PAIR_GEN,
a6c4ed
@@ -339,42 +265,13 @@ INSTANTIATE_TEST_CASE_P(Pk11KeyImportTes
a6c4ed
 class Pk11KeyImportTestEC : public Pk11KeyImportTestBase,
a6c4ed
                             public ::testing::WithParamInterface<SECOidTag> {
a6c4ed
  public:
a6c4ed
-  Pk11KeyImportTestEC() : Pk11KeyImportTestBase(CKM_EC_KEY_PAIR_GEN) {}
a6c4ed
+  Pk11KeyImportTestEC() = default;
a6c4ed
   virtual ~Pk11KeyImportTestEC() = default;
a6c4ed
-
a6c4ed
- protected:
a6c4ed
-  std::unique_ptr<ParamHolder> MakeParams() override {
a6c4ed
-    return std::unique_ptr<ParamHolder>(new EcParamHolder(GetParam()));
a6c4ed
-  }
a6c4ed
-
a6c4ed
- private:
a6c4ed
-  class EcParamHolder : public ParamHolder {
a6c4ed
-   public:
a6c4ed
-    EcParamHolder(SECOidTag curve_oid) {
a6c4ed
-      SECOidData* curve = SECOID_FindOIDByTag(curve_oid);
a6c4ed
-      EXPECT_NE(nullptr, curve);
a6c4ed
-
a6c4ed
-      size_t plen = curve->oid.len + 2;
a6c4ed
-      extra_.reset(new uint8_t[plen]);
a6c4ed
-      extra_[0] = SEC_ASN1_OBJECT_ID;
a6c4ed
-      extra_[1] = static_cast<uint8_t>(curve->oid.len);
a6c4ed
-      memcpy(&extra_[2], curve->oid.data, curve->oid.len);
a6c4ed
-
a6c4ed
-      ec_params_ = {/*.type = */ siBuffer,
a6c4ed
-                    /*.data = */ extra_.get(),
a6c4ed
-                    /*.len = */ static_cast<unsigned int>(plen)};
a6c4ed
-    }
a6c4ed
-    ~EcParamHolder() = default;
a6c4ed
-
a6c4ed
-    void* get() override { return &ec_params_; }
a6c4ed
-
a6c4ed
-   private:
a6c4ed
-    SECKEYECParams ec_params_;
a6c4ed
-    std::unique_ptr<uint8_t[]> extra_;
a6c4ed
-  };
a6c4ed
 };
a6c4ed
 
a6c4ed
-TEST_P(Pk11KeyImportTestEC, GenerateExportImport) { Test(); }
a6c4ed
+TEST_P(Pk11KeyImportTestEC, GenerateExportImport) {
a6c4ed
+  Test(Pkcs11KeyPairGenerator(CKM_EC_KEY_PAIR_GEN, GetParam()));
a6c4ed
+}
a6c4ed
 
a6c4ed
 INSTANTIATE_TEST_CASE_P(Pk11KeyImportTestEC, Pk11KeyImportTestEC,
a6c4ed
                         ::testing::Values(SEC_OID_SECG_EC_SECP256R1,
a6c4ed
diff -up ./gtests/pk11_gtest/pk11_keygen.cc.handle-malformed-ecdh-gtests ./gtests/pk11_gtest/pk11_keygen.cc
a6c4ed
--- ./gtests/pk11_gtest/pk11_keygen.cc.handle-malformed-ecdh-gtests	2019-12-05 10:56:41.829832628 -0800
a6c4ed
+++ ./gtests/pk11_gtest/pk11_keygen.cc	2019-12-05 10:56:41.829832628 -0800
a6c4ed
@@ -0,0 +1,143 @@
a6c4ed
+/* This Source Code Form is subject to the terms of the Mozilla Public
a6c4ed
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
a6c4ed
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
a6c4ed
+
a6c4ed
+#include "pk11_keygen.h"
a6c4ed
+
a6c4ed
+#include "pk11pub.h"
a6c4ed
+#include "pk11pqg.h"
a6c4ed
+#include "prerror.h"
a6c4ed
+
a6c4ed
+#include "gtest/gtest.h"
a6c4ed
+
a6c4ed
+namespace nss_test {
a6c4ed
+
a6c4ed
+class ParamHolder {
a6c4ed
+ public:
a6c4ed
+  virtual void* get() = 0;
a6c4ed
+  virtual ~ParamHolder() = default;
a6c4ed
+
a6c4ed
+ protected:
a6c4ed
+  ParamHolder() = default;
a6c4ed
+};
a6c4ed
+
a6c4ed
+void Pkcs11KeyPairGenerator::GenerateKey(ScopedSECKEYPrivateKey* priv_key,
a6c4ed
+                                         ScopedSECKEYPublicKey* pub_key) const {
a6c4ed
+  // This function returns if an assertion fails, so don't leak anything.
a6c4ed
+  priv_key->reset(nullptr);
a6c4ed
+  pub_key->reset(nullptr);
a6c4ed
+
a6c4ed
+  auto params = MakeParams();
a6c4ed
+  ASSERT_NE(nullptr, params);
a6c4ed
+
a6c4ed
+  ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
a6c4ed
+  ASSERT_TRUE(slot);
a6c4ed
+
a6c4ed
+  SECKEYPublicKey* pub_tmp;
a6c4ed
+  ScopedSECKEYPrivateKey priv_tmp(PK11_GenerateKeyPair(
a6c4ed
+      slot.get(), mech_, params->get(), &pub_tmp, PR_FALSE, PR_TRUE, nullptr));
a6c4ed
+  ASSERT_NE(nullptr, priv_tmp) << "PK11_GenerateKeyPair failed: "
a6c4ed
+                               << PORT_ErrorToName(PORT_GetError());
a6c4ed
+  ASSERT_NE(nullptr, pub_tmp);
a6c4ed
+
a6c4ed
+  priv_key->swap(priv_tmp);
a6c4ed
+  pub_key->reset(pub_tmp);
a6c4ed
+}
a6c4ed
+
a6c4ed
+class RsaParamHolder : public ParamHolder {
a6c4ed
+ public:
a6c4ed
+  RsaParamHolder() : params_({1024, 0x010001}) {}
a6c4ed
+  ~RsaParamHolder() = default;
a6c4ed
+
a6c4ed
+  void* get() override { return &params_; }
a6c4ed
+
a6c4ed
+ private:
a6c4ed
+  PK11RSAGenParams params_;
a6c4ed
+};
a6c4ed
+
a6c4ed
+class PqgParamHolder : public ParamHolder {
a6c4ed
+ public:
a6c4ed
+  PqgParamHolder(PQGParams* params) : params_(params) {}
a6c4ed
+  ~PqgParamHolder() = default;
a6c4ed
+
a6c4ed
+  void* get() override { return params_.get(); }
a6c4ed
+
a6c4ed
+ private:
a6c4ed
+  ScopedPQGParams params_;
a6c4ed
+};
a6c4ed
+
a6c4ed
+class DhParamHolder : public PqgParamHolder {
a6c4ed
+ public:
a6c4ed
+  DhParamHolder(PQGParams* params)
a6c4ed
+      : PqgParamHolder(params),
a6c4ed
+        params_({nullptr, params->prime, params->base}) {}
a6c4ed
+  ~DhParamHolder() = default;
a6c4ed
+
a6c4ed
+  void* get() override { return &params_; }
a6c4ed
+
a6c4ed
+ private:
a6c4ed
+  SECKEYDHParams params_;
a6c4ed
+};
a6c4ed
+
a6c4ed
+class EcParamHolder : public ParamHolder {
a6c4ed
+ public:
a6c4ed
+  EcParamHolder(SECOidTag curve_oid) {
a6c4ed
+    SECOidData* curve = SECOID_FindOIDByTag(curve_oid);
a6c4ed
+    EXPECT_NE(nullptr, curve);
a6c4ed
+
a6c4ed
+    size_t plen = curve->oid.len + 2;
a6c4ed
+    extra_.reset(new uint8_t[plen]);
a6c4ed
+    extra_[0] = SEC_ASN1_OBJECT_ID;
a6c4ed
+    extra_[1] = static_cast<uint8_t>(curve->oid.len);
a6c4ed
+    memcpy(&extra_[2], curve->oid.data, curve->oid.len);
a6c4ed
+
a6c4ed
+    ec_params_ = {siBuffer, extra_.get(), static_cast<unsigned int>(plen)};
a6c4ed
+  }
a6c4ed
+  ~EcParamHolder() = default;
a6c4ed
+
a6c4ed
+  void* get() override { return &ec_params_; }
a6c4ed
+
a6c4ed
+ private:
a6c4ed
+  SECKEYECParams ec_params_;
a6c4ed
+  std::unique_ptr<uint8_t[]> extra_;
a6c4ed
+};
a6c4ed
+
a6c4ed
+std::unique_ptr<ParamHolder> Pkcs11KeyPairGenerator::MakeParams() const {
a6c4ed
+  switch (mech_) {
a6c4ed
+    case CKM_RSA_PKCS_KEY_PAIR_GEN:
a6c4ed
+      std::cerr << "Generate RSA pair" << std::endl;
a6c4ed
+      return std::unique_ptr<ParamHolder>(new RsaParamHolder());
a6c4ed
+
a6c4ed
+    case CKM_DSA_KEY_PAIR_GEN:
a6c4ed
+    case CKM_DH_PKCS_KEY_PAIR_GEN: {
a6c4ed
+      PQGParams* pqg_params = nullptr;
a6c4ed
+      PQGVerify* pqg_verify = nullptr;
a6c4ed
+      const unsigned int key_size = 1024;
a6c4ed
+      SECStatus rv = PK11_PQG_ParamGenV2(key_size, 0, key_size / 16,
a6c4ed
+                                         &pqg_params, &pqg_verify);
a6c4ed
+      if (rv != SECSuccess) {
a6c4ed
+        ADD_FAILURE() << "PK11_PQG_ParamGenV2 failed";
a6c4ed
+        return nullptr;
a6c4ed
+      }
a6c4ed
+      EXPECT_NE(nullptr, pqg_verify);
a6c4ed
+      EXPECT_NE(nullptr, pqg_params);
a6c4ed
+      PK11_PQG_DestroyVerify(pqg_verify);
a6c4ed
+      if (mech_ == CKM_DSA_KEY_PAIR_GEN) {
a6c4ed
+        std::cerr << "Generate DSA pair" << std::endl;
a6c4ed
+        return std::unique_ptr<ParamHolder>(new PqgParamHolder(pqg_params));
a6c4ed
+      }
a6c4ed
+      std::cerr << "Generate DH pair" << std::endl;
a6c4ed
+      return std::unique_ptr<ParamHolder>(new DhParamHolder(pqg_params));
a6c4ed
+    }
a6c4ed
+
a6c4ed
+    case CKM_EC_KEY_PAIR_GEN:
a6c4ed
+      std::cerr << "Generate EC pair on " << curve_ << std::endl;
a6c4ed
+      return std::unique_ptr<ParamHolder>(new EcParamHolder(curve_));
a6c4ed
+
a6c4ed
+    default:
a6c4ed
+      ADD_FAILURE() << "unknown OID " << mech_;
a6c4ed
+  }
a6c4ed
+  return nullptr;
a6c4ed
+}
a6c4ed
+
a6c4ed
+}  // namespace nss_test
a6c4ed
diff -up ./gtests/pk11_gtest/pk11_keygen.h.handle-malformed-ecdh-gtests ./gtests/pk11_gtest/pk11_keygen.h
a6c4ed
--- ./gtests/pk11_gtest/pk11_keygen.h.handle-malformed-ecdh-gtests	2019-12-05 10:56:41.828832617 -0800
a6c4ed
+++ ./gtests/pk11_gtest/pk11_keygen.h	2019-12-05 10:56:41.828832617 -0800
a6c4ed
@@ -0,0 +1,34 @@
a6c4ed
+/* This Source Code Form is subject to the terms of the Mozilla Public
a6c4ed
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
a6c4ed
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
a6c4ed
+
a6c4ed
+#include "nss.h"
a6c4ed
+#include "secoid.h"
a6c4ed
+
a6c4ed
+#include "nss_scoped_ptrs.h"
a6c4ed
+
a6c4ed
+namespace nss_test {
a6c4ed
+
a6c4ed
+class ParamHolder;
a6c4ed
+
a6c4ed
+class Pkcs11KeyPairGenerator {
a6c4ed
+ public:
a6c4ed
+  Pkcs11KeyPairGenerator(CK_MECHANISM_TYPE mech, SECOidTag curve_oid)
a6c4ed
+      : mech_(mech), curve_(curve_oid) {}
a6c4ed
+  Pkcs11KeyPairGenerator(CK_MECHANISM_TYPE mech)
a6c4ed
+      : Pkcs11KeyPairGenerator(mech, SEC_OID_UNKNOWN) {}
a6c4ed
+
a6c4ed
+  CK_MECHANISM_TYPE mechanism() const { return mech_; }
a6c4ed
+  SECOidTag curve() const { return curve_; }
a6c4ed
+
a6c4ed
+  void GenerateKey(ScopedSECKEYPrivateKey* priv_key,
a6c4ed
+                   ScopedSECKEYPublicKey* pub_key) const;
a6c4ed
+
a6c4ed
+ private:
a6c4ed
+  std::unique_ptr<ParamHolder> MakeParams() const;
a6c4ed
+
a6c4ed
+  CK_MECHANISM_TYPE mech_;
a6c4ed
+  SECOidTag curve_;
a6c4ed
+};
a6c4ed
+
a6c4ed
+}  // namespace nss_test
a6c4ed
diff -up ./gtests/pk11_gtest/pk11_key_unittest.cc.handle-malformed-ecdh-gtests ./gtests/pk11_gtest/pk11_key_unittest.cc
a6c4ed
--- ./gtests/pk11_gtest/pk11_key_unittest.cc.handle-malformed-ecdh-gtests	2019-12-05 10:56:41.828832617 -0800
a6c4ed
+++ ./gtests/pk11_gtest/pk11_key_unittest.cc	2019-12-05 10:56:41.828832617 -0800
a6c4ed
@@ -0,0 +1,80 @@
a6c4ed
+/* This Source Code Form is subject to the terms of the Mozilla Public
a6c4ed
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
a6c4ed
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
a6c4ed
+
a6c4ed
+#include <memory>
a6c4ed
+#include "nss.h"
a6c4ed
+#include "pk11pub.h"
a6c4ed
+#include "pk11pqg.h"
a6c4ed
+#include "prerror.h"
a6c4ed
+#include "secoid.h"
a6c4ed
+
a6c4ed
+#include "gtest/gtest.h"
a6c4ed
+#include "nss_scoped_ptrs.h"
a6c4ed
+#include "pk11_keygen.h"
a6c4ed
+
a6c4ed
+namespace nss_test {
a6c4ed
+
a6c4ed
+class Pkcs11NullKeyTestBase : public ::testing::Test {
a6c4ed
+ protected:
a6c4ed
+  // This constructs a key pair, then erases the public value from the public
a6c4ed
+  // key.  NSS should reject this.
a6c4ed
+  void Test(const Pkcs11KeyPairGenerator& generator,
a6c4ed
+            CK_MECHANISM_TYPE dh_mech) {
a6c4ed
+    ScopedSECKEYPrivateKey priv;
a6c4ed
+    ScopedSECKEYPublicKey pub;
a6c4ed
+    generator.GenerateKey(&priv, &pub;;
a6c4ed
+    ASSERT_TRUE(priv);
a6c4ed
+
a6c4ed
+    // These don't leak because they are allocated to the arena associated with
a6c4ed
+    // the public key.
a6c4ed
+    SECItem* pub_val = nullptr;
a6c4ed
+    switch (SECKEY_GetPublicKeyType(pub.get())) {
a6c4ed
+      case rsaKey:
a6c4ed
+        pub_val = &pub->u.rsa.modulus;
a6c4ed
+        break;
a6c4ed
+
a6c4ed
+      case dsaKey:
a6c4ed
+        pub_val = &pub->u.dsa.publicValue;
a6c4ed
+        break;
a6c4ed
+
a6c4ed
+      case dhKey:
a6c4ed
+        pub_val = &pub->u.dh.publicValue;
a6c4ed
+        break;
a6c4ed
+
a6c4ed
+      case ecKey:
a6c4ed
+        pub_val = &pub->u.ec.publicValue;
a6c4ed
+        break;
a6c4ed
+
a6c4ed
+      default:
a6c4ed
+        FAIL() << "Unknown key type " << SECKEY_GetPublicKeyType(pub.get());
a6c4ed
+    }
a6c4ed
+    pub_val->data = nullptr;
a6c4ed
+    pub_val->len = 0;
a6c4ed
+
a6c4ed
+    ScopedPK11SymKey symKey(PK11_PubDeriveWithKDF(
a6c4ed
+        priv.get(), pub.get(), false, nullptr, nullptr, dh_mech,
a6c4ed
+        CKM_SHA512_HMAC, CKA_DERIVE, 0, CKD_NULL, nullptr, nullptr));
a6c4ed
+    ASSERT_FALSE(symKey);
a6c4ed
+  }
a6c4ed
+};
a6c4ed
+
a6c4ed
+class Pkcs11DhNullKeyTest : public Pkcs11NullKeyTestBase {};
a6c4ed
+TEST_F(Pkcs11DhNullKeyTest, UseNullPublicValue) {
a6c4ed
+  Test(Pkcs11KeyPairGenerator(CKM_DH_PKCS_KEY_PAIR_GEN), CKM_DH_PKCS_DERIVE);
a6c4ed
+}
a6c4ed
+
a6c4ed
+class Pkcs11EcdhNullKeyTest : public Pkcs11NullKeyTestBase,
a6c4ed
+                              public ::testing::WithParamInterface<SECOidTag> {
a6c4ed
+};
a6c4ed
+TEST_P(Pkcs11EcdhNullKeyTest, UseNullPublicValue) {
a6c4ed
+  Test(Pkcs11KeyPairGenerator(CKM_EC_KEY_PAIR_GEN, GetParam()),
a6c4ed
+       CKM_ECDH1_DERIVE);
a6c4ed
+}
a6c4ed
+INSTANTIATE_TEST_CASE_P(Pkcs11EcdhNullKeyTest, Pkcs11EcdhNullKeyTest,
a6c4ed
+                        ::testing::Values(SEC_OID_SECG_EC_SECP256R1,
a6c4ed
+                                          SEC_OID_SECG_EC_SECP384R1,
a6c4ed
+                                          SEC_OID_SECG_EC_SECP521R1,
a6c4ed
+                                          SEC_OID_CURVE25519));
a6c4ed
+
a6c4ed
+}  // namespace nss_test
a6c4ed
diff --git ./gtests/pk11_gtest/pk11_curve25519_unittest.cc.handle-malformed-ecdh-gtests ./gtests/pk11_gtest/pk11_curve25519_unittest.cc
a6c4ed
--- ./gtests/pk11_gtest/pk11_curve25519_unittest.cc.handle-malformed-ecdh-gtests
a6c4ed
+++ ./gtests/pk11_gtest/pk11_curve25519_unittest.cc
a6c4ed
@@ -40,6 +40,9 @@
a6c4ed
 
a6c4ed
     ScopedCERTSubjectPublicKeyInfo certSpki(
a6c4ed
         SECKEY_DecodeDERSubjectPublicKeyInfo(&spkiItem));
a6c4ed
+    if (!expect_success && !certSpki) {
a6c4ed
+      return;
a6c4ed
+    }
a6c4ed
     ASSERT_TRUE(certSpki);
a6c4ed
 
a6c4ed
     ScopedSECKEYPublicKey pubKey(SECKEY_ExtractPublicKey(certSpki.get()));
a6c4ed
a6c4ed
diff -up ./gtests/ssl_gtest/tls_connect.cc.addtime ./gtests/ssl_gtest/tls_connect.cc
a6c4ed
--- ./gtests/ssl_gtest/tls_connect.cc.addtime	2019-12-06 09:02:39.006583359 -0800
a6c4ed
+++ ./gtests/ssl_gtest/tls_connect.cc	2019-12-06 09:02:54.120745545 -0800
a6c4ed
@@ -292,7 +292,7 @@ void TlsConnectTestBase::Handshake() {
a6c4ed
 
a6c4ed
   ASSERT_TRUE_WAIT((client_->state() != TlsAgent::STATE_CONNECTING) &&
a6c4ed
                        (server_->state() != TlsAgent::STATE_CONNECTING),
a6c4ed
-                   5000);
a6c4ed
+                   10000);
a6c4ed
 }
a6c4ed
 
a6c4ed
 void TlsConnectTestBase::EnableExtendedMasterSecret() {
a6c4ed