Bug 1523175 - land NSS 794984bb1169 UPGRADE_NSS_RELEASE, r=me
authorJ.C. Jones <jc@mozilla.com>
Fri, 08 Feb 2019 00:04:23 +0000
changeset 516193 eee8ce2afe60f5fcd62c7aaaf4122cdce02d4544
parent 516192 6a91ccdd57304071ce382527232e24f3363e8b9e
child 516194 f78d0fba26fa4b6dda48bcfc9c515af9d2b5ecf9
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs1523175
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1523175 - land NSS 794984bb1169 UPGRADE_NSS_RELEASE, r=me
security/nss/TAG-INFO
security/nss/cmd/ssltap/ssltap.c
security/nss/coreconf/coreconf.dep
security/nss/gtests/pk11_gtest/pk11_import_unittest.cc
security/nss/gtests/pk11_gtest/pk11_rsapss_unittest.cc
security/nss/gtests/util_gtest/manifest.mn
security/nss/gtests/util_gtest/util_gtest.gyp
security/nss/gtests/util_gtest/util_gtests.cc
security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c
security/nss/lib/softoken/pkcs11c.c
security/nss/tests/chains/scenarios/nameconstraints.cfg
security/nss/tests/libpkix/certs/NameConstraints.ipaca.cert
security/nss/tests/libpkix/certs/NameConstraints.ocsp1.cert
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-d0a282507d59
+794984bb1169
--- a/security/nss/cmd/ssltap/ssltap.c
+++ b/security/nss/cmd/ssltap/ssltap.c
@@ -2255,17 +2255,16 @@ print_hex(int amt, unsigned char *buf)
         }
         PR_fprintf(PR_STDOUT, " | %s\n", string);
     }
 }
 
 void
 Usage(void)
 {
-    PR_fprintf(PR_STDERR, "SSLTAP (C) 1997, 1998 Netscape Communications Corporation.\n");
     PR_fprintf(PR_STDERR, "Usage: ssltap [-vhfsxl] [-p port] hostname:port\n");
     PR_fprintf(PR_STDERR, "   -v      [prints version string]\n");
     PR_fprintf(PR_STDERR, "   -h      [outputs hex instead of ASCII]\n");
     PR_fprintf(PR_STDERR, "   -f      [turn on Fancy HTML coloring]\n");
     PR_fprintf(PR_STDERR, "   -s      [turn on SSL decoding]\n");
     PR_fprintf(PR_STDERR, "   -x      [turn on extra SSL hex dumps]\n");
     PR_fprintf(PR_STDERR, "   -p port [specify rendezvous port (default 1924)]\n");
     PR_fprintf(PR_STDERR, "   -l      [loop - continue to wait for more connections]\n");
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,9 +5,8 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
-
new file mode 100644
--- /dev/null
+++ b/security/nss/gtests/pk11_gtest/pk11_import_unittest.cc
@@ -0,0 +1,334 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <memory>
+#include "nss.h"
+#include "pk11pub.h"
+#include "pk11pqg.h"
+#include "prerror.h"
+#include "secoid.h"
+
+#include "cpputil.h"
+#include "nss_scoped_ptrs.h"
+#include "gtest/gtest.h"
+#include "databuffer.h"
+
+namespace nss_test {
+
+// This deleter deletes a set of objects, unlike the deleter on
+// ScopedPK11GenericObject, which only deletes one.
+struct PK11GenericObjectsDeleter {
+  void operator()(PK11GenericObject* objs) {
+    if (objs) {
+      PK11_DestroyGenericObjects(objs);
+    }
+  }
+};
+
+class Pk11KeyImportTestBase : public ::testing::Test {
+ public:
+  Pk11KeyImportTestBase(CK_MECHANISM_TYPE mech) : mech_(mech) {}
+  virtual ~Pk11KeyImportTestBase() = default;
+
+  void SetUp() override {
+    slot_.reset(PK11_GetInternalKeySlot());
+    ASSERT_TRUE(slot_);
+
+    static const uint8_t pw[] = "pw";
+    SECItem pwItem = {siBuffer, toUcharPtr(pw), sizeof(pw)};
+    password_.reset(SECITEM_DupItem(&pwItem));
+  }
+
+  void Test() {
+    // Generate a key and export it.
+    KeyType key_type;
+    ScopedSECKEYEncryptedPrivateKeyInfo key_info;
+    ScopedSECItem public_value;
+    GenerateAndExport(&key_type, &key_info, &public_value);
+    ASSERT_NE(nullptr, key_info);
+    ASSERT_NE(nullptr, public_value);
+
+    // Now import the encrypted key.
+    static const uint8_t nick[] = "nick";
+    SECItem nickname = {siBuffer, toUcharPtr(nick), sizeof(nick)};
+    SECKEYPrivateKey* priv_tmp;
+    SECStatus rv = PK11_ImportEncryptedPrivateKeyInfoAndReturnKey(
+        slot_.get(), key_info.get(), password_.get(), &nickname,
+        public_value.get(), PR_TRUE, PR_TRUE, key_type, 0, &priv_tmp, NULL);
+    ASSERT_EQ(SECSuccess, rv) << "PK11_ImportEncryptedPrivateKeyInfo failed "
+                              << PORT_ErrorToName(PORT_GetError());
+    ScopedSECKEYPrivateKey priv_key(priv_tmp);
+    ASSERT_NE(nullptr, priv_key);
+
+    CheckForPublicKey(priv_key, public_value.get());
+  }
+
+ protected:
+  class ParamHolder {
+   public:
+    virtual ~ParamHolder() = default;
+    virtual void* get() = 0;
+  };
+
+  virtual std::unique_ptr<ParamHolder> MakeParams() = 0;
+
+  CK_MECHANISM_TYPE mech_;
+
+ private:
+  void CheckForPublicKey(const ScopedSECKEYPrivateKey& priv_key,
+                         const SECItem* expected_public) {
+    // Verify the public key exists.
+    StackSECItem priv_id;
+    SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, priv_key.get(),
+                                         CKA_ID, &priv_id);
+    ASSERT_EQ(SECSuccess, rv) << "Couldn't read CKA_ID from private key: "
+                              << PORT_ErrorToName(PORT_GetError());
+
+    CK_ATTRIBUTE_TYPE value_type = CKA_VALUE;
+    switch (SECKEY_GetPrivateKeyType(priv_key.get())) {
+      case rsaKey:
+        value_type = CKA_MODULUS;
+        break;
+
+      case dhKey:
+      case dsaKey:
+        value_type = CKA_VALUE;
+        break;
+
+      case ecKey:
+        value_type = CKA_EC_POINT;
+        break;
+
+      default:
+        FAIL() << "unknown key type";
+    }
+
+    std::unique_ptr<PK11GenericObject, PK11GenericObjectsDeleter> objs(
+        PK11_FindGenericObjects(slot_.get(), CKO_PUBLIC_KEY));
+    ASSERT_NE(nullptr, objs);
+    for (PK11GenericObject* obj = objs.get(); obj != nullptr;
+         obj = PK11_GetNextGenericObject(obj)) {
+      StackSECItem pub_id;
+      rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, CKA_ID, &pub_id);
+      if (rv != SECSuccess) {
+        // Can't read CKA_ID from object.
+        continue;
+      }
+      if (!SECITEM_ItemsAreEqual(&priv_id, &pub_id)) {
+        // This isn't the object we're looking for.
+        continue;
+      }
+
+      StackSECItem token;
+      rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, CKA_TOKEN, &token);
+      ASSERT_EQ(SECSuccess, rv);
+      ASSERT_EQ(1U, token.len);
+      ASSERT_NE(0, token.data[0]);
+
+      StackSECItem value;
+      rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, value_type, &value);
+      ASSERT_EQ(SECSuccess, rv);
+
+      // CKA_EC_POINT isn't stable, see Bug 1520649.
+      if (value_type == CKA_EC_POINT) {
+        continue;
+      }
+
+      ASSERT_TRUE(SECITEM_ItemsAreEqual(expected_public, &value))
+          << "expected: "
+          << DataBuffer(expected_public->data, expected_public->len)
+          << std::endl
+          << "actual: " << DataBuffer(value.data, value.len) << std::endl;
+    }
+  }
+
+  void GenerateAndExport(KeyType* key_type,
+                         ScopedSECKEYEncryptedPrivateKeyInfo* key_info,
+                         ScopedSECItem* public_value) {
+    auto params = MakeParams();
+    ASSERT_NE(nullptr, params);
+
+    SECKEYPublicKey* pub_tmp;
+    ScopedSECKEYPrivateKey priv_key(
+        PK11_GenerateKeyPair(slot_.get(), mech_, params->get(), &pub_tmp,
+                             PR_FALSE, PR_TRUE, nullptr));
+    ASSERT_NE(nullptr, priv_key) << "PK11_GenerateKeyPair failed: "
+                                 << PORT_ErrorToName(PORT_GetError());
+    ScopedSECKEYPublicKey pub_key(pub_tmp);
+    ASSERT_NE(nullptr, pub_key);
+
+    // Wrap and export the key.
+    ScopedSECKEYEncryptedPrivateKeyInfo epki(PK11_ExportEncryptedPrivKeyInfo(
+        slot_.get(), SEC_OID_AES_256_CBC, password_.get(), priv_key.get(), 1,
+        nullptr));
+    ASSERT_NE(nullptr, epki) << "PK11_ExportEncryptedPrivKeyInfo failed: "
+                             << PORT_ErrorToName(PORT_GetError());
+
+    // Save the public value, which we will need on import */
+    SECItem* pub_val;
+    KeyType t = SECKEY_GetPublicKeyType(pub_key.get());
+    switch (t) {
+      case rsaKey:
+        pub_val = &pub_key->u.rsa.modulus;
+        break;
+      case dhKey:
+        pub_val = &pub_key->u.dh.publicValue;
+        break;
+      case dsaKey:
+        pub_val = &pub_key->u.dsa.publicValue;
+        break;
+      case ecKey:
+        pub_val = &pub_key->u.ec.publicValue;
+        break;
+      default:
+        FAIL() << "Unknown key type";
+    }
+
+    CheckForPublicKey(priv_key, pub_val);
+
+    *key_type = t;
+    key_info->swap(epki);
+    public_value->reset(SECITEM_DupItem(pub_val));
+  }
+
+  ScopedPK11SlotInfo slot_;
+  ScopedSECItem password_;
+};
+
+class Pk11KeyImportTest
+    : public Pk11KeyImportTestBase,
+      public ::testing::WithParamInterface<CK_MECHANISM_TYPE> {
+ public:
+  Pk11KeyImportTest() : Pk11KeyImportTestBase(GetParam()) {}
+  virtual ~Pk11KeyImportTest() = default;
+
+ protected:
+  std::unique_ptr<ParamHolder> MakeParams() override {
+    switch (mech_) {
+      case CKM_RSA_PKCS_KEY_PAIR_GEN:
+        return std::unique_ptr<ParamHolder>(new RsaParamHolder());
+
+      case CKM_DSA_KEY_PAIR_GEN:
+      case CKM_DH_PKCS_KEY_PAIR_GEN: {
+        PQGParams* pqg_params = nullptr;
+        PQGVerify* pqg_verify = nullptr;
+        const unsigned int key_size = 1024;
+        SECStatus rv = PK11_PQG_ParamGenV2(key_size, 0, key_size / 16,
+                                           &pqg_params, &pqg_verify);
+        if (rv != SECSuccess) {
+          ADD_FAILURE() << "PK11_PQG_ParamGenV2 failed";
+          return nullptr;
+        }
+        EXPECT_NE(nullptr, pqg_verify);
+        EXPECT_NE(nullptr, pqg_params);
+        PK11_PQG_DestroyVerify(pqg_verify);
+        if (mech_ == CKM_DSA_KEY_PAIR_GEN) {
+          return std::unique_ptr<ParamHolder>(new PqgParamHolder(pqg_params));
+        }
+        return std::unique_ptr<ParamHolder>(new DhParamHolder(pqg_params));
+      }
+
+      default:
+        ADD_FAILURE() << "unknown OID " << mech_;
+    }
+    return nullptr;
+  }
+
+ private:
+  class RsaParamHolder : public ParamHolder {
+   public:
+    RsaParamHolder()
+        : params_({/*.keySizeInBits = */ 1024, /*.pe = */ 0x010001}) {}
+    ~RsaParamHolder() = default;
+
+    void* get() override { return &params_; }
+
+   private:
+    PK11RSAGenParams params_;
+  };
+
+  class PqgParamHolder : public ParamHolder {
+   public:
+    PqgParamHolder(PQGParams* params) : params_(params) {}
+    ~PqgParamHolder() = default;
+
+    void* get() override { return params_.get(); }
+
+   private:
+    ScopedPQGParams params_;
+  };
+
+  class DhParamHolder : public PqgParamHolder {
+   public:
+    DhParamHolder(PQGParams* params)
+        : PqgParamHolder(params),
+          params_({/*.arena = */ nullptr,
+                   /*.prime = */ params->prime,
+                   /*.base = */ params->base}) {}
+    ~DhParamHolder() = default;
+
+    void* get() override { return &params_; }
+
+   private:
+    SECKEYDHParams params_;
+  };
+};
+
+TEST_P(Pk11KeyImportTest, GenerateExportImport) { Test(); }
+
+INSTANTIATE_TEST_CASE_P(Pk11KeyImportTest, Pk11KeyImportTest,
+                        ::testing::Values(CKM_RSA_PKCS_KEY_PAIR_GEN,
+                                          CKM_DSA_KEY_PAIR_GEN));
+// Note: NSS is currently unable export wrapped DH keys, so this doesn't test
+// CKM_DH_PKCS_KEY_PAIR_GEN.
+
+class Pk11KeyImportTestEC : public Pk11KeyImportTestBase,
+                            public ::testing::WithParamInterface<SECOidTag> {
+ public:
+  Pk11KeyImportTestEC() : Pk11KeyImportTestBase(CKM_EC_KEY_PAIR_GEN) {}
+  virtual ~Pk11KeyImportTestEC() = default;
+
+ protected:
+  std::unique_ptr<ParamHolder> MakeParams() override {
+    return std::unique_ptr<ParamHolder>(new EcParamHolder(GetParam()));
+  }
+
+ private:
+  class EcParamHolder : public ParamHolder {
+   public:
+    EcParamHolder(SECOidTag curve_oid) {
+      SECOidData* curve = SECOID_FindOIDByTag(curve_oid);
+      EXPECT_NE(nullptr, curve);
+
+      size_t plen = curve->oid.len + 2;
+      extra_.reset(new uint8_t[plen]);
+      extra_[0] = SEC_ASN1_OBJECT_ID;
+      extra_[1] = static_cast<uint8_t>(curve->oid.len);
+      memcpy(&extra_[2], curve->oid.data, curve->oid.len);
+
+      ec_params_ = {/*.type = */ siBuffer,
+                    /*.data = */ extra_.get(),
+                    /*.len = */ static_cast<unsigned int>(plen)};
+    }
+    ~EcParamHolder() = default;
+
+    void* get() override { return &ec_params_; }
+
+   private:
+    SECKEYECParams ec_params_;
+    std::unique_ptr<uint8_t[]> extra_;
+  };
+};
+
+TEST_P(Pk11KeyImportTestEC, GenerateExportImport) { Test(); }
+
+INSTANTIATE_TEST_CASE_P(Pk11KeyImportTestEC, Pk11KeyImportTestEC,
+                        ::testing::Values(SEC_OID_SECG_EC_SECP256R1,
+                                          SEC_OID_SECG_EC_SECP384R1,
+                                          SEC_OID_SECG_EC_SECP521R1,
+                                          SEC_OID_CURVE25519));
+
+}  // namespace nss_test
--- a/security/nss/gtests/pk11_gtest/pk11_rsapss_unittest.cc
+++ b/security/nss/gtests/pk11_gtest/pk11_rsapss_unittest.cc
@@ -88,16 +88,30 @@ TEST_F(Pkcs11RsaPssTest, GenerateAndSign
   // Verification with original data but the wrong signature must fail.
   data.data[0] ^= 0xff;  // Revert previous changes.
   sig.data[0] ^= 0xff;
   rv = PK11_VerifyWithMechanism(pubKey.get(), mechanism(), &params, &sig, &data,
                                 nullptr);
   EXPECT_EQ(rv, SECFailure);
 }
 
+TEST_F(Pkcs11RsaPssTest, NoLeakWithInvalidExponent) {
+  // Attempt to generate an RSA key with a public exponent of 1. This should
+  // fail, but it shouldn't leak memory.
+  PK11RSAGenParams rsaGenParams = {1024, 0x01};
+
+  // Generate RSA key pair.
+  ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
+  SECKEYPublicKey* pubKey = nullptr;
+  SECKEYPrivateKey* privKey =
+      PK11_GenerateKeyPair(slot.get(), CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaGenParams,
+                           &pubKey, false, false, nullptr);
+  EXPECT_FALSE(privKey);
+  EXPECT_FALSE(pubKey);
+}
 class Pkcs11RsaPssVectorTest
     : public Pkcs11RsaPssTest,
       public ::testing::WithParamInterface<Pkcs11SignatureTestParams> {};
 
 TEST_P(Pkcs11RsaPssVectorTest, Verify) { Verify(GetParam()); }
 
 TEST_P(Pkcs11RsaPssVectorTest, SignAndVerify) { SignAndVerify(GetParam()); }
 
--- a/security/nss/gtests/util_gtest/manifest.mn
+++ b/security/nss/gtests/util_gtest/manifest.mn
@@ -1,31 +1,32 @@
 # -*- makefile -*-
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 CORE_DEPTH = ../..
-DEPTH      = ../..
+DEPTH = ../..
 MODULE = nss
 
 CPPSRCS = \
-	util_utf8_unittest.cc \
-	util_b64_unittest.cc \
-	util_pkcs11uri_unittest.cc \
-	util_aligned_malloc_unittest.cc \
-	util_memcmpzero_unittest.cc \
-	$(NULL)
+        util_aligned_malloc_unittest.cc \
+        util_b64_unittest.cc \
+        util_gtests.cc \
+        util_memcmpzero_unittest.cc \
+        util_pkcs11uri_unittest.cc \
+        util_utf8_unittest.cc \
+        $(NULL)
 
 INCLUDES += \
-	-I$(CORE_DEPTH)/gtests/google_test/gtest/include \
-	-I$(CORE_DEPTH)/gtests/common \
-	-I$(CORE_DEPTH)/cpputil \
-	$(NULL)
+        -I$(CORE_DEPTH)/gtests/google_test/gtest/include \
+        -I$(CORE_DEPTH)/gtests/common \
+        -I$(CORE_DEPTH)/cpputil \
+        $(NULL)
 
 REQUIRES = nspr gtest
 
 PROGRAM = util_gtest
 
 EXTRA_LIBS = \
-	$(DIST)/lib/$(LIB_PREFIX)gtest.$(LIB_SUFFIX) \
-	$(DIST)/lib/$(LIB_PREFIX)nssutil.$(LIB_SUFFIX) \
-	$(DIST)/lib/$(LIB_PREFIX)gtestutil.$(LIB_SUFFIX) \
-	$(NULL)
+        $(DIST)/lib/$(LIB_PREFIX)gtest.$(LIB_SUFFIX) \
+        $(DIST)/lib/$(LIB_PREFIX)nssutil.$(LIB_SUFFIX) \
+        $(DIST)/lib/$(LIB_PREFIX)gtestutil.$(LIB_SUFFIX) \
+        $(NULL)
--- a/security/nss/gtests/util_gtest/util_gtest.gyp
+++ b/security/nss/gtests/util_gtest/util_gtest.gyp
@@ -6,37 +6,27 @@
     '../../coreconf/config.gypi',
     '../common/gtest.gypi',
   ],
   'targets': [
     {
       'target_name': 'util_gtest',
       'type': 'executable',
       'sources': [
-        'util_utf8_unittest.cc',
+        'util_aligned_malloc_unittest.cc',
         'util_b64_unittest.cc',
+        'util_gtests.cc',
+        'util_memcmpzero_unittest.cc',
         'util_pkcs11uri_unittest.cc',
-        'util_aligned_malloc_unittest.cc',
-        'util_memcmpzero_unittest.cc',
-        '<(DEPTH)/gtests/common/gtests.cc',
+        'util_utf8_unittest.cc',
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
         '<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
         '<(DEPTH)/lib/util/util.gyp:nssutil',
-        '<(DEPTH)/lib/nss/nss.gyp:nss_static',
-        '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static',
-        '<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
-        '<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
-        '<(DEPTH)/lib/certdb/certdb.gyp:certdb',
-        '<(DEPTH)/lib/base/base.gyp:nssb',
-        '<(DEPTH)/lib/dev/dev.gyp:nssdev',
-        '<(DEPTH)/lib/pki/pki.gyp:nsspki',
-        '<(DEPTH)/lib/ssl/ssl.gyp:ssl',
-        '<(DEPTH)/lib/libpkix/libpkix.gyp:libpkix',
       ],
       'conditions': [
         [ 'OS=="win"', {
           'libraries': [
             'advapi32.lib',
           ],
         }],
       ],
new file mode 100644
--- /dev/null
+++ b/security/nss/gtests/util_gtest/util_gtests.cc
@@ -0,0 +1,9 @@
+#include <cstdlib>
+
+#define GTEST_HAS_RTTI 0
+#include "gtest/gtest.h"
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
--- a/security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c
@@ -163,16 +163,19 @@ pkix_NameConstraintsChecker_Check(
         void **pNBIOContext,
         void *plContext)
 {
         pkix_NameConstraintsCheckerState *state = NULL;
         PKIX_PL_CertNameConstraints *nameConstraints = NULL;
         PKIX_PL_CertNameConstraints *mergedNameConstraints = NULL;
         PKIX_Boolean selfIssued = PKIX_FALSE;
         PKIX_Boolean lastCert = PKIX_FALSE;
+        PKIX_Boolean treatCommonNameAsDNSName = PKIX_FALSE;
+        PKIX_List *extKeyUsageList = NULL;
+        PKIX_PL_OID *serverAuthOID = NULL;
 
         PKIX_ENTER(CERTCHAINCHECKER, "pkix_NameConstraintsChecker_Check");
         PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
 
         *pNBIOContext = NULL; /* we never block on pending I/O */
 
         PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
                     (checker, (PKIX_PL_Object **)&state, plContext),
@@ -180,21 +183,48 @@ pkix_NameConstraintsChecker_Check(
 
         state->certsRemaining--;
         lastCert = state->certsRemaining == 0;
 
         /* Get status of self issued */
         PKIX_CHECK(pkix_IsCertSelfIssued(cert, &selfIssued, plContext),
                     PKIX_ISCERTSELFISSUEDFAILED);
 
+        if (lastCert) {
+            /* For the last cert, treat the CN as a DNS name for name
+             * constraint check.  But only if EKU has id-kp-serverAuth
+             * or EKU is absent.  It does not make sense to treat CN
+             * as a DNS name for an OCSP signing certificate, for example.
+             */
+            PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage
+                       (cert, &extKeyUsageList, plContext),
+                       PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
+            if (extKeyUsageList == NULL) {
+                treatCommonNameAsDNSName = PKIX_TRUE;
+            } else {
+                PKIX_CHECK(PKIX_PL_OID_Create
+                        (PKIX_KEY_USAGE_SERVER_AUTH_OID,
+                        &serverAuthOID,
+                        plContext),
+                        PKIX_OIDCREATEFAILED);
+
+                PKIX_CHECK(pkix_List_Contains
+                           (extKeyUsageList,
+                            (PKIX_PL_Object *) serverAuthOID,
+                            &treatCommonNameAsDNSName,
+                            plContext),
+                           PKIX_LISTCONTAINSFAILED);
+            }
+        }
+
         /* Check on non self-issued and if so only for last cert */
         if (selfIssued == PKIX_FALSE ||
             (selfIssued == PKIX_TRUE && lastCert)) {
                 PKIX_CHECK(PKIX_PL_Cert_CheckNameConstraints
-                    (cert, state->nameConstraints, lastCert,
+                    (cert, state->nameConstraints, treatCommonNameAsDNSName,
                       plContext),
                     PKIX_CERTCHECKNAMECONSTRAINTSFAILED);
         }
 
         if (!lastCert) {
 
             PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
                     (cert, &nameConstraints, plContext),
@@ -236,16 +266,18 @@ pkix_NameConstraintsChecker_Check(
 
         PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
                     (checker, (PKIX_PL_Object *)state, plContext),
                     PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
 
 cleanup:
 
         PKIX_DECREF(state);
+        PKIX_DECREF(extKeyUsageList);
+        PKIX_DECREF(serverAuthOID);
 
         PKIX_RETURN(CERTCHAINCHECKER);
 }
 
 /*
  * FUNCTION: pkix_NameConstraintsChecker_Initialize
  *
  * DESCRIPTION:
--- a/security/nss/lib/softoken/pkcs11c.c
+++ b/security/nss/lib/softoken/pkcs11c.c
@@ -4833,16 +4833,17 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS
 
             /* extract the exponent */
             crv = sftk_Attribute2SSecItem(NULL, &pubExp, publicKey, CKA_PUBLIC_EXPONENT);
             if (crv != CKR_OK)
                 break;
             bitSize = sftk_GetLengthInBits(pubExp.data, pubExp.len);
             if (bitSize < 2) {
                 crv = CKR_ATTRIBUTE_VALUE_INVALID;
+                PORT_Free(pubExp.data);
                 break;
             }
             crv = sftk_AddAttributeType(privateKey, CKA_PUBLIC_EXPONENT,
                                         sftk_item_expand(&pubExp));
             if (crv != CKR_OK) {
                 PORT_Free(pubExp.data);
                 break;
             }
--- a/security/nss/tests/chains/scenarios/nameconstraints.cfg
+++ b/security/nss/tests/chains/scenarios/nameconstraints.cfg
@@ -5,16 +5,17 @@
 scenario TrustAnchors
 
 db trustanchors
 
 import NameConstraints.ca:x:CT,C,C
 # Name Constrained CA:  Name constrained to permited DNSName ".example"
 import NameConstraints.ncca:x:CT,C,C
 import NameConstraints.dcisscopy:x:CT,C,C
+import NameConstraints.ipaca:x:CT,C,C
 
 # Intermediate 1: Name constrained to permited DNSName ".example"
 
 # Subject: "C=US, ST=California, L=Mountain View, O=BOGUS NSS, CN=test.invalid"
 # altDNS: test.invalid
 #   Fail: CN not in name constraints, altDNS not in name constraints
 verify NameConstraints.server1:x
   cert NameConstraints.intermediate:x
@@ -153,9 +154,17 @@ verify NameConstraints.server17:x
 # Subject: "C = US, ST=CA, O=Foo CN=foo.example.com"
 verify NameConstraints.dcissblocked:x
   result fail
 
 # Subject: "C = US, ST=CA, O=Foo CN=foo.example.fr"
 verify NameConstraints.dcissallowed:x
   result pass
 
+# Subject: "O = IPA.LOCAL 201901211552, CN = OCSP Subsystem"
+#
+# This tests that a non server certificate (i.e. id-kp-serverAuth
+# not present in EKU) does *NOT* have CN treated as dnsName for
+# purposes of Name Constraints validation
+verify NameConstraints.ocsp1:x
+  usage 10
+  result pass
 
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6c7d68c770062d12f3a90693142e0a08f0f1e8d5
GIT binary patch
literal 981
zc$_n6V!mk5#I$n(GZP~d6DPyP?%>QT)${udc-c6$+C196^D;8>ure4#8gd(OvN4CU
zun99ch8hYR2!c2qJY0dLsi}FzIf;2GhJptCAVGE>4yU5b;-tj9R6_v+K9CR>4|`B*
zih@UC2~32Uhdm^<xJ1F((Lhd|*U-|y(8$oh%)r>lEJ~c$2*@?GfN~8S4do4F!KMg{
zc?LM@`S?3K`Y0F~Kr|Veni?6(8OVSQ6&7_)Eh@=O%S=uzNmXzxEy>6)$}FigXkt`C
z_7Ed019KB2KLb#li>Zl`k>OD9n_12KU9L6!+ZXK~vwC~`l3Et?dtI+BZ3AY$a6cTn
z)8f?pCA0p_<==Maz$K<zGL{F!U&rwJluYP7T<Khupz`AW2kVV4O}59EZRy|Vk*xRc
z?s~brH{W+}w*CKX^2g^7=G=(Rp4Yi9@0Rjo|Jx}thH;LU+2;#9oYlsim0*12+N;w_
zzY=$~uJyW5T*P`Jignqi3n2xml1(q~oZNQQ)!^;>JvSSycOSgzGim3ipf<t!9^2#7
zO8zsi(G`8SNGE0LsXM2#_(f-Lyd!bN>eu_G&pZ5AedlLUJj)tjw%c{lWSc8Z>{<&;
z@16e{X)a-AClbCS>X_f}NyY4^rZmlcIVsjd_$(7MBLm~&#?1ze8^CcWE6m9FpM}+c
z8AyS{UY3tVj720rB5ghQ;)Mzm^iJ%UewF{X##^Ty2J#?jWflnou?7*3=<3UFnKxKO
ztSWxbAD(wzS%y^?9N)71AOl%|iR_qxFNiP4;%4Boz{!BSi8HexQ7<PyIWfn8r-@4s
z!BbtLY@i5_dmbEdkCsrGLDA{;RDE~BmoUatnvn(h<q?|aU$ywp<GmxEz!SHRtNL}^
zK3)!!P|nMN%H>YX_0u%>gcnqP{1Nk1KTeBxVmjxts%^0>52LIN81lDnDyh%2o20YS
z;a|atpFh)eWMsW`);<<vOrGG>v#I-+WKj#(shgL$%v{*#?>V_!k9UFaZPWgfrG?k*
z-^DNJWARU)y8S(iiAme;9TU&9RPJ_leeeF{z0$3Y%ZggnuWOf=AM@MkyutRhXO^61
zn#e)s&AZ*ZO#jtfn)bn2bM;o&_t~~edQwV{cgMBd)903WasK6=(=JEnrt1G*TQkvU
f*|(X0PpvLcYzp3S_1C$$TrLZSjZNl)QYNAR)+%lI
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ce7325fca9c56337d866b05cfbd42baa97944685
GIT binary patch
literal 898
zc$_n6Vy-i2VoF=U%*4pV#K>*H%f_kI=F#?@mywa1mBGN#P~Je6jX9KsOIXY^z){b~
z-`UYe!N|bS(!kKj(9qP>$WYEe2Bd&lSkyVSs3bEjGdZy&Rl%{eBqP5lv!v2MPMjC4
z8mQdB$iyH@oY%<Ezz_t$Tmvh(6+F1C5H}D7TfxKU?;ISU5L}v6Tv=R_nrqO+sD$id
zMpg#qCPsb+pg0#(6C)$TB0u+^@drH@cQsbUxf{)PKly<DV&8f`M~Odnt6Sbq_I~MM
zWb%pKL@NGG(%T8Di%)b`TRPPJSmEoIs<~jry<_L?F23G(?C-k!Q=hOYtw=p_sIu2D
ze_2Oj-1V*NrZUWH^sjqz`F}Bw-;yg_8>U@Viq(xW;Bso<cv8E*<DL`$CEs~AC1(Dq
zF)EhRDsPnq`TKW$5dO%V+WBPd#2inD!dc<R=bWGPg#Cev+K~(Ck7L(acrJN%DLdfj
z#rGC0e!J8+>-}!CUzoY)xb5BMVEI=LHWN=}t*M)pzm%a$_uKZWl66_jSAG|sv{rRW
zOvTg%52`O*Ni%liJW*-L{z~xYo~j}Vokk{RMh3>kjqL`FEe7(yAe2>RkuVTz5Xp~7
zThG0Cp~3{c6Fa6~<^Qem)@g?UKO3hu8zU<#y8$CB3llK%t=Tvr0*s6-`UbiN+AzKW
zW1D<NNlAf~zJ6vwqHc1c9+1+@$xlwq(N9j)&rdEcFc1b=r^>=(zy;IA%!!t|m_bpb
zle<(t_vec&dDXOKm(NH1WQ?*re8N$?pk?KWyz>v2NQ#6B)X06|eW-PD+r^L-n>Tn)
zb#nA&{KVd}vSS<b_jNWq^Zg!PSjL;QagW8siy{+#OpAG_tv6-u$J+H32T#rTKlfWk
zlHu0YyKXx~=UsZj+y6IA_rLEJ)waX?wk%^@VfY}2Vfyzy`IAq*Q~V{By(9V@_rr`o
zR;7z(ecQdDyI=D7&JN~;zU^)H2bLDpWJJw!$<lpaCb)1}^rU{K*snsrF1bsKe3_H$
zZL(|TrQgy=lIBd)lJ!xD|Ft8sdB!TO3lkUAisjfEYt0DWzuubR!kdWcel>4IzXrZ>
PTJzKBqIaIftnG{do@`Wz