bug 1570222 - avoid passing unrelated certificates to mozilla::pkix from NSSCertDBTrustDomain r?kjacobs a=lizzard
authorDana Keeler <dkeeler@mozilla.com>
Fri, 04 Oct 2019 19:46:08 +0300
changeset 555569 d69eab8be1bf6f591138af54dc383748f239cfeb
parent 555568 e62d13f0a325d0be38225507a93babccd76c3008
child 555570 fbf79b038eb751c4f528087735e4171701334ec8
push id2165
push userffxbld-merge
push dateMon, 14 Oct 2019 16:30:58 +0000
treeherdermozilla-release@0eae18af659f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskjacobs, lizzard
bugs1570222
milestone70.0
bug 1570222 - avoid passing unrelated certificates to mozilla::pkix from NSSCertDBTrustDomain r?kjacobs a=lizzard During path building, mozilla::pkix filters out candidate certificates provided by trust domains where the subject distinguished name does not match the issuer distinguished name of the certificate it's trying to find an issuer for. However, if there's a problem decoding the candidate issuer certificate, mozilla::pkix will make a note of this error, regardless of if that certificate was potentially a suitable issuer. If no trusted path is found, the error from that unrelated certificate may ultimately be returned by mozilla::pkix, resulting in confusion. Before this patch, NSSCertDBTrustDomain could cause this behavior by blithely passing every known 3rd party certificate to mozilla::pkix (other sources of certificates already filter on subject distinguished name). This patch adds filtering to 3rd party certificates as well. Differential Revision: https://phabricator.services.mozilla.com//D48120
security/certverifier/NSSCertDBTrustDomain.cpp
--- a/security/certverifier/NSSCertDBTrustDomain.cpp
+++ b/security/certverifier/NSSCertDBTrustDomain.cpp
@@ -267,23 +267,46 @@ Result NSSCertDBTrustDomain::FindIssuer(
       }
     }
   } else {
     MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
             ("NSSCertDBTrustDomain::FindIssuer: no built-in roots module"));
   }
 
   for (const auto& thirdPartyRootInput : mThirdPartyRootInputs) {
+    BackCert root(thirdPartyRootInput, EndEntityOrCA::MustBeCA, nullptr);
+    Result rv = root.Init();
+    if (rv != Success) {
+      continue;
+    }
+    // Filter out 3rd party roots that can't be issuers we're looking for
+    // because the subject distinguished name doesn't match. This prevents
+    // mozilla::pkix from accumulating spurious errors during path building.
+    if (!InputsAreEqual(encodedIssuerName, root.GetSubject())) {
+      continue;
+    }
     if (!geckoRootCandidates.append(thirdPartyRootInput)) {
       return Result::FATAL_ERROR_NO_MEMORY;
     }
   }
 
   for (const auto& thirdPartyIntermediateInput :
        mThirdPartyIntermediateInputs) {
+    BackCert intermediate(thirdPartyIntermediateInput, EndEntityOrCA::MustBeCA,
+                          nullptr);
+    Result rv = intermediate.Init();
+    if (rv != Success) {
+      continue;
+    }
+    // Filter out 3rd party intermediates that can't be issuers we're looking
+    // for because the subject distinguished name doesn't match. This prevents
+    // mozilla::pkix from accumulating spurious errors during path building.
+    if (!InputsAreEqual(encodedIssuerName, intermediate.GetSubject())) {
+      continue;
+    }
     if (!geckoIntermediateCandidates.append(thirdPartyIntermediateInput)) {
       return Result::FATAL_ERROR_NO_MEMORY;
     }
   }
 
   // Try all root certs first and then all (presumably) intermediates.
   if (!geckoRootCandidates.appendAll(geckoIntermediateCandidates)) {
     return Result::FATAL_ERROR_NO_MEMORY;