Backed out changeset 2df66e8b7411 (bug 1302140) for Windows build bustage in CertVerifier.cpp. r=backout on a CLOSED TREE
authorSebastian Hengst <archaeopteryx@coole-files.de>
Wed, 21 Sep 2016 20:47:08 +0200
changeset 314731 d8b95e0d8843fd08aebefe39b102b99291610c91
parent 314730 1f866a7b1db49fb8dfe8f9d7dc2935d5f91fe836
child 314732 770a9b2e9ab6a88562f675d9787c735b51876472
push id32448
push userarchaeopteryx@coole-files.de
push dateWed, 21 Sep 2016 18:47:25 +0000
treeherderautoland@d8b95e0d8843 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1302140
milestone52.0a1
backs out2df66e8b7411fa3f7a998f9d87dc967371577c17
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
Backed out changeset 2df66e8b7411 (bug 1302140) for Windows build bustage in CertVerifier.cpp. r=backout on a CLOSED TREE
netwerk/base/security-prefs.js
security/certverifier/CertVerifier.cpp
security/certverifier/CertVerifier.h
security/certverifier/NSSCertDBTrustDomain.cpp
security/manager/ssl/nsNSSComponent.cpp
security/manager/ssl/tests/unit/test_cert_sha1.js
security/manager/ssl/tests/unit/test_ocsp_caching.js
security/manager/ssl/tests/unit/test_ocsp_stapling_expired.js
toolkit/components/telemetry/Histograms.json
--- a/netwerk/base/security-prefs.js
+++ b/netwerk/base/security-prefs.js
@@ -50,18 +50,18 @@ pref("security.family_safety.mode", 2);
 
 pref("security.OCSP.enabled", 1);
 pref("security.OCSP.require", false);
 pref("security.OCSP.GET.enabled", false);
 
 pref("security.pki.cert_short_lifetime_in_days", 10);
 // NB: Changes to this pref affect CERT_CHAIN_SHA1_POLICY_STATUS telemetry.
 // See the comment in CertVerifier.cpp.
-// 4 = allow SHA-1 for certificates issued before 2016 or by an imported root.
-pref("security.pki.sha1_enforcement_level", 4);
+// 3 = allow SHA-1 for certificates issued before 2016 or by an imported root.
+pref("security.pki.sha1_enforcement_level", 3);
 
 // security.pki.name_matching_mode controls how the platform matches hostnames
 // to name information in TLS certificates. The possible values are:
 // 0: always fall back to the subject common name if necessary (as in, if the
 //    subject alternative name extension is either not present or does not
 //    contain any DNS names or IP addresses)
 // 1: fall back to the subject common name for certificates valid before 23
 //    August 2016 if necessary
--- a/security/certverifier/CertVerifier.cpp
+++ b/security/certverifier/CertVerifier.cpp
@@ -147,19 +147,19 @@ BuildCertChainForOneKeyUsage(NSSCertDBTr
 }
 
 bool
 CertVerifier::SHA1ModeMoreRestrictiveThanGivenMode(SHA1Mode mode)
 {
   switch (mSHA1Mode) {
     case SHA1Mode::Forbidden:
       return mode != SHA1Mode::Forbidden;
+    case SHA1Mode::Before2016:
+      return mode != SHA1Mode::Forbidden && mode != SHA1Mode::Before2016;
     case SHA1Mode::ImportedRoot:
-      return mode != SHA1Mode::Forbidden && mode != SHA1Mode::ImportedRoot;
-    case SHA1Mode::ImportedRootOrBefore2016:
       return mode == SHA1Mode::Allowed;
     case SHA1Mode::Allowed:
       return false;
     default:
       MOZ_ASSERT(false, "unexpected SHA1Mode type");
       return true;
   }
 }
@@ -278,25 +278,25 @@ CertVerifier::VerifyCert(CERTCertificate
       // restrict the acceptable key usage based on the key exchange method
       // chosen by the server.
 
       // These configurations are in order of most restrictive to least
       // restrictive. This enables us to gather telemetry on the expected
       // results of setting the default policy to a particular configuration.
       SHA1Mode sha1ModeConfigurations[] = {
         SHA1Mode::Forbidden,
+        SHA1Mode::Before2016,
         SHA1Mode::ImportedRoot,
-        SHA1Mode::ImportedRootOrBefore2016,
         SHA1Mode::Allowed,
       };
 
       SHA1ModeResult sha1ModeResults[] = {
         SHA1ModeResult::SucceededWithoutSHA1,
+        SHA1ModeResult::SucceededWithSHA1Before2016,
         SHA1ModeResult::SucceededWithImportedRoot,
-        SHA1ModeResult::SucceededWithImportedRootOrSHA1Before2016,
         SHA1ModeResult::SucceededWithSHA1,
       };
 
       size_t sha1ModeConfigurationsCount = MOZ_ARRAY_LENGTH(sha1ModeConfigurations);
 
       static_assert(MOZ_ARRAY_LENGTH(sha1ModeConfigurations) ==
                     MOZ_ARRAY_LENGTH(sha1ModeResults),
                     "digestAlgorithm array lengths differ");
@@ -341,16 +341,25 @@ CertVerifier::VerifyCert(CERTCertificate
                       builtChain, pinningTelemetryInfo, hostname);
         rv = BuildCertChainForOneKeyUsage(trustDomain, certDER, time,
                                           KeyUsage::digitalSignature,// (EC)DHE
                                           KeyUsage::keyEncipherment, // RSA
                                           KeyUsage::keyAgreement,    // (EC)DH
                                           KeyPurposeId::id_kp_serverAuth,
                                           evPolicy, stapledOCSPResponse,
                                           ocspStaplingStatus);
+        // If we succeeded with the SHA1Mode of only allowing imported roots to
+        // issue SHA1 certificates after 2015, if the chain we built doesn't
+        // terminate with an imported root, we must reject it. (This only works
+        // because we try SHA1 configurations in order of decreasing
+        // strictness.)
+        // Note that if there existed a certificate chain with a built-in root
+        // that had SHA1 certificates issued before 2016, it would have already
+        // been accepted. If such a chain had SHA1 certificates issued after
+        // 2015, it will only be accepted in the SHA1Mode::Allowed case.
         if (rv == Success &&
             sha1ModeConfigurations[i] == SHA1Mode::ImportedRoot) {
           bool isBuiltInRoot = false;
           rv = IsCertChainRootBuiltInRoot(builtChain, isBuiltInRoot);
           if (rv != Success) {
             break;
           }
           if (isBuiltInRoot) {
@@ -424,16 +433,25 @@ CertVerifier::VerifyCert(CERTCertificate
           rv = BuildCertChainForOneKeyUsage(trustDomain, certDER, time,
                                             KeyUsage::digitalSignature,//(EC)DHE
                                             KeyUsage::keyEncipherment,//RSA
                                             KeyUsage::keyAgreement,//(EC)DH
                                             KeyPurposeId::id_kp_serverAuth,
                                             CertPolicyId::anyPolicy,
                                             stapledOCSPResponse,
                                             ocspStaplingStatus);
+          // If we succeeded with the SHA1Mode of only allowing imported roots
+          // to issue SHA1 certificates after 2015, if the chain we built
+          // doesn't terminate with an imported root, we must reject it. (This
+          // only works because we try SHA1 configurations in order of
+          // decreasing strictness.)
+          // Note that if there existed a certificate chain with a built-in root
+          // that had SHA1 certificates issued before 2016, it would have
+          // already been accepted. If such a chain had SHA1 certificates issued
+          // after 2015, it will only be accepted in the SHA1Mode::Allowed case.
           if (rv == Success &&
               sha1ModeConfigurations[j] == SHA1Mode::ImportedRoot) {
             bool isBuiltInRoot = false;
             rv = IsCertChainRootBuiltInRoot(builtChain, isBuiltInRoot);
             if (rv != Success) {
               break;
             }
             if (isBuiltInRoot) {
@@ -453,36 +471,33 @@ CertVerifier::VerifyCert(CERTCertificate
 
       if (rv == Success) {
         break;
       }
 
       if (keySizeStatus) {
         *keySizeStatus = KeySizeStatus::AlreadyBad;
       }
-      // The telemetry probe CERT_CHAIN_SHA1_POLICY_STATUS gives us feedback on
-      // the result of setting a specific policy. However, we don't want noise
-      // from users who have manually set the policy to Allowed or Forbidden, so
-      // we only collect for ImportedRoot or ImportedRootOrBefore2016.
-      if (sha1ModeResult &&
-          (mSHA1Mode == SHA1Mode::ImportedRoot ||
-           mSHA1Mode == SHA1Mode::ImportedRootOrBefore2016)) {
+      // Only collect CERT_CHAIN_SHA1_POLICY_STATUS telemetry indicating a
+      // failure when mSHA1Mode is the default.
+      // NB: When we change the default, we have to change this.
+      if (sha1ModeResult && mSHA1Mode == SHA1Mode::ImportedRoot) {
         *sha1ModeResult = SHA1ModeResult::Failed;
       }
 
       break;
     }
 
     case certificateUsageSSLCA: {
       NSSCertDBTrustDomain trustDomain(trustSSL, defaultOCSPFetching,
                                        mOCSPCache, pinArg, ocspGETConfig,
                                        mCertShortLifetimeInDays,
                                        pinningDisabled, MIN_RSA_BITS_WEAK,
                                        ValidityCheckingMode::CheckingOff,
-                                       SHA1Mode::Allowed, mNetscapeStepUpPolicy,
+                                       mSHA1Mode, mNetscapeStepUpPolicy,
                                        builtChain, nullptr, nullptr);
       rv = BuildCertChain(trustDomain, certDER, time,
                           EndEntityOrCA::MustBeCA, KeyUsage::keyCertSign,
                           KeyPurposeId::id_kp_serverAuth,
                           CertPolicyId::anyPolicy, stapledOCSPResponse);
       break;
     }
 
--- a/security/certverifier/CertVerifier.h
+++ b/security/certverifier/CertVerifier.h
@@ -22,18 +22,18 @@ enum class KeySizeStatus {
   CompatibilityRisk = 2,
   AlreadyBad = 3,
 };
 
 // These values correspond to the CERT_CHAIN_SHA1_POLICY_STATUS telemetry.
 enum class SHA1ModeResult {
   NeverChecked = 0,
   SucceededWithoutSHA1 = 1,
-  SucceededWithImportedRoot = 2,
-  SucceededWithImportedRootOrSHA1Before2016 = 3,
+  SucceededWithSHA1Before2016 = 2,
+  SucceededWithImportedRoot = 3,
   SucceededWithSHA1 = 4,
   Failed = 5,
 };
 
 enum class NetscapeStepUpPolicy : uint32_t;
 
 class PinningTelemetryInfo
 {
@@ -105,22 +105,18 @@ public:
     pinningAllowUserCAMITM = 1,
     pinningStrict = 2,
     pinningEnforceTestMode = 3
   };
 
   enum class SHA1Mode {
     Allowed = 0,
     Forbidden = 1,
-    // There used to be a policy that only allowed SHA1 for certificates issued
-    // before 2016. This is no longer available. If a user has selected this
-    // policy in about:config, it now maps to Forbidden.
-    UsedToBeBefore2016ButNowIsForbidden = 2,
+    Before2016 = 2,
     ImportedRoot = 3,
-    ImportedRootOrBefore2016 = 4,
   };
 
   enum OcspDownloadConfig {
     ocspOff = 0,
     ocspOn = 1,
     ocspEVOnly = 2
   };
   enum OcspStrictConfig { ocspRelaxed = 0, ocspStrict };
@@ -144,18 +140,18 @@ public:
   const BRNameMatchingPolicy::Mode mNameMatchingMode;
   const NetscapeStepUpPolicy mNetscapeStepUpPolicy;
 
 private:
   OCSPCache mOCSPCache;
 
   // Returns true if the configured SHA1 mode is more restrictive than the given
   // mode. SHA1Mode::Forbidden is more restrictive than any other mode except
-  // Forbidden. Next is ImportedRoot, then ImportedRootOrBefore2016, then
-  // Allowed. (A mode is never more restrictive than itself.)
+  // Forbidden. Next is Before2016, then ImportedRoot, then Allowed.
+  // (A mode is never more restrictive than itself.)
   bool SHA1ModeMoreRestrictiveThanGivenMode(SHA1Mode mode);
 };
 
 mozilla::pkix::Result IsCertBuiltInRoot(CERTCertificate* cert, bool& result);
 mozilla::pkix::Result CertListContainsExpectedKeys(
   const CERTCertList* certList, const char* hostname, mozilla::pkix::Time time,
   CertVerifier::PinningMode pinningMode);
 
--- a/security/certverifier/NSSCertDBTrustDomain.cpp
+++ b/security/certverifier/NSSCertDBTrustDomain.cpp
@@ -830,17 +830,17 @@ NSSCertDBTrustDomain::CheckSignatureDige
 
   MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
           ("NSSCertDBTrustDomain: CheckSignatureDigestAlgorithm"));
   if (aAlg == DigestAlgorithm::sha1) {
     switch (mSHA1Mode) {
       case CertVerifier::SHA1Mode::Forbidden:
         MOZ_LOG(gCertVerifierLog, LogLevel::Debug, ("SHA-1 certificate rejected"));
         return Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED;
-      case CertVerifier::SHA1Mode::ImportedRootOrBefore2016:
+      case CertVerifier::SHA1Mode::Before2016:
         if (JANUARY_FIRST_2016 <= notBefore) {
           MOZ_LOG(gCertVerifierLog, LogLevel::Debug, ("Post-2015 SHA-1 certificate rejected"));
           return Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED;
         }
         break;
       case CertVerifier::SHA1Mode::Allowed:
       // Enforcing that the resulting chain uses an imported root is only
       // possible at a higher level. This is done in CertVerifier::VerifyCert.
--- a/security/manager/ssl/nsNSSComponent.cpp
+++ b/security/manager/ssl/nsNSSComponent.cpp
@@ -1511,30 +1511,24 @@ void nsNSSComponent::setValidationOption
   }
 
   CertVerifier::SHA1Mode sha1Mode = static_cast<CertVerifier::SHA1Mode>
       (Preferences::GetInt("security.pki.sha1_enforcement_level",
                            static_cast<int32_t>(CertVerifier::SHA1Mode::Allowed)));
   switch (sha1Mode) {
     case CertVerifier::SHA1Mode::Allowed:
     case CertVerifier::SHA1Mode::Forbidden:
-    case CertVerifier::SHA1Mode::UsedToBeBefore2016ButNowIsForbidden:
+    case CertVerifier::SHA1Mode::Before2016:
     case CertVerifier::SHA1Mode::ImportedRoot:
-    case CertVerifier::SHA1Mode::ImportedRootOrBefore2016:
       break;
     default:
       sha1Mode = CertVerifier::SHA1Mode::Allowed;
       break;
   }
 
-  // Convert a previously-available setting to a safe one.
-  if (sha1Mode == CertVerifier::SHA1Mode::UsedToBeBefore2016ButNowIsForbidden) {
-    sha1Mode = CertVerifier::SHA1Mode::Forbidden;
-  }
-
   BRNameMatchingPolicy::Mode nameMatchingMode =
     static_cast<BRNameMatchingPolicy::Mode>
       (Preferences::GetInt("security.pki.name_matching_mode",
                            static_cast<int32_t>(BRNameMatchingPolicy::Mode::DoNotEnforce)));
   switch (nameMatchingMode) {
     case BRNameMatchingPolicy::Mode::Enforce:
     case BRNameMatchingPolicy::Mode::EnforceAfter23August2015:
     case BRNameMatchingPolicy::Mode::EnforceAfter23August2016:
--- a/security/manager/ssl/tests/unit/test_cert_sha1.js
+++ b/security/manager/ssl/tests/unit/test_cert_sha1.js
@@ -26,117 +26,102 @@ function loadCertWithTrust(certName, tru
   addCertFromFile(certdb, "test_cert_sha1/" + certName + ".pem", trustString);
 }
 
 function checkEndEntity(cert, expectedResult) {
   checkCertErrorGenericAtTime(certdb, cert, expectedResult,
                               certificateUsageSSLServer, VALIDATION_TIME);
 }
 
+function checkIntermediate(cert, expectedResult) {
+  checkCertErrorGenericAtTime(certdb, cert, expectedResult,
+                              certificateUsageSSLCA, VALIDATION_TIME);
+}
+
 function run_test() {
   loadCertWithTrust("ca", "CTu,,");
   loadCertWithTrust("int-pre", ",,");
   loadCertWithTrust("int-post", ",,");
 
   // Test cases per pref setting
   //
   // root  intermed.  end entity
   // ===========================
   // root
   //  |
-  //  +--- pre-2016
+  //  +--- pre-2016             <--- (a)
   //  |       |
-  //  |       +----- pre-2016   <--- (a)
-  //  |       +----- post-2016  <--- (b)
+  //  |       +----- pre-2016   <--- (b)
+  //  |       +----- post-2016  <--- (c)
   //  |
-  //  +--- post-2016
+  //  +--- post-2016            <--- (d)
   //          |
-  //          +----- post-2016  <--- (c)
+  //          +----- post-2016  <--- (e)
   //
   // Expected outcomes (accept / reject):
   //
-  //                              a      b      c
-  // Allowed (0)                  Accept Accept Accept
-  // Forbidden (1)                Reject Reject Reject
-  // (2) is no longer available and is treated as Forbidden (1) internally.
-  // ImportedRoot (3)             Reject Reject Reject (for built-in roots)
-  // ImportedRoot                 Accept Accept Accept (for non-built-in roots)
-  // ImportedRootOrBefore2016 (4) Accept Reject Reject (for built-in roots)
-  // ImportedRootOrBefore2016     Accept Accept Accept (for non-built-in roots)
-  //
-  // The pref setting of ImportedRoot accepts usage of SHA-1 only for
-  // certificates issued by non-built-in roots. By default, the testing
-  // certificates are all considered issued by a non-built-in root. However, we
-  // have the ability to treat a given non-built-in root as built-in. We test
-  // both of these situations below.
+  //                     a   b   c   d   e
+  // Allowed=0          Acc Acc Acc Acc Acc
+  // Forbidden=1        Rej Rej Rej Rej Rej
+  // Before2016=2       Acc Acc Rej Rej Rej
   //
-  // As a historical note, a policy option (Before2016) was previously available
-  // that only allowed SHA-1 for certificates with a notBefore before 2016.
-  // However, to enable the policy of only allowing SHA-1 from non-built-in
-  // roots in the most straightforward way (while still having a time-based
-  // policy that users could enable if this new policy were problematic),
-  // Before2016 was shifted to also allow SHA-1 from non-built-in roots, hence
-  // ImportedRootOrBefore2016.
-  //
-  // A note about intermediate certificates: the certificate verifier has the
-  // ability to directly verify a given certificate for the purpose of issuing
-  // TLS web server certificates. However, when asked to do so, the certificate
-  // verifier does not take into account the currently configured SHA-1 policy.
-  // This is in part due to implementation complexity and because this isn't
-  // actually how TLS web server certificates are verified in the TLS handshake
-  // (which makes a full implementation that supports heeding the SHA-1 policy
-  // unnecessary).
+  // The pref setting of ImportedRoot (3) accepts usage of SHA-1 for
+  // certificates valid before 2016 issued by built-in roots or SHA-1 for
+  // certificates issued any time by non-built-in roots. By default, the testing
+  // certificates are all considered issued by a non-built-in root. However, we
+  // now have the ability to treat a given non-built-in root as built-in. We
+  // test both of these situations below.
 
   // SHA-1 allowed
   Services.prefs.setIntPref("security.pki.sha1_enforcement_level", 0);
+  checkIntermediate(certFromFile("int-pre"), PRErrorCodeSuccess);
   checkEndEntity(certFromFile("ee-pre_int-pre"), PRErrorCodeSuccess);
   checkEndEntity(certFromFile("ee-post_int-pre"), PRErrorCodeSuccess);
+  checkIntermediate(certFromFile("int-post"), PRErrorCodeSuccess);
   checkEndEntity(certFromFile("ee-post_int-post"), PRErrorCodeSuccess);
 
   // SHA-1 forbidden
   Services.prefs.setIntPref("security.pki.sha1_enforcement_level", 1);
+  checkIntermediate(certFromFile("int-pre"), SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
   checkEndEntity(certFromFile("ee-pre_int-pre"), SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
   checkEndEntity(certFromFile("ee-post_int-pre"), SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
+  checkIntermediate(certFromFile("int-post"), SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
   checkEndEntity(certFromFile("ee-post_int-post"), SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
 
-  // SHA-1 forbidden (test the case where the pref has been set to 2)
+  // SHA-1 allowed only before 2016
   Services.prefs.setIntPref("security.pki.sha1_enforcement_level", 2);
-  checkEndEntity(certFromFile("ee-pre_int-pre"), SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
+  checkIntermediate(certFromFile("int-pre"), PRErrorCodeSuccess);
+  checkEndEntity(certFromFile("ee-pre_int-pre"), PRErrorCodeSuccess);
   checkEndEntity(certFromFile("ee-post_int-pre"), SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
+  checkIntermediate(certFromFile("int-post"), SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
   checkEndEntity(certFromFile("ee-post_int-post"), SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
 
-  // SHA-1 allowed only when issued by an imported root. First test with the
-  // test root considered a built-in (on debug only - this functionality is
-  // disabled on non-debug builds).
+  // SHA-1 allowed only before 2016 or when issued by an imported root. First
+  // test with the test root considered a built-in (on debug only - this
+  // functionality is disabled on non-debug builds).
   Services.prefs.setIntPref("security.pki.sha1_enforcement_level", 3);
   if (isDebugBuild) {
     let root = certFromFile("ca");
     Services.prefs.setCharPref("security.test.built_in_root_hash", root.sha256Fingerprint);
-    checkEndEntity(certFromFile("ee-pre_int-pre"), SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
+    checkIntermediate(certFromFile("int-pre"), PRErrorCodeSuccess);
+    checkEndEntity(certFromFile("ee-pre_int-pre"), PRErrorCodeSuccess);
     checkEndEntity(certFromFile("ee-post_int-pre"), SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
+    // This should fail but it doesn't, because the implementation makes no
+    // effort to enforce that when verifying a certificate for the capability
+    // of issuing TLS server auth certificates (i.e. the
+    // "certificateUsageSSLCA" usage), if SHA-1 was necessary, then the root of
+    // trust is an imported certificate. We don't really care, though, because
+    // the platform doesn't actually make trust decisions in this way and the
+    // ability to even verify a certificate for this purpose is intended to go
+    // away in bug 1257362.
+    // checkIntermediate(certFromFile("int-post"), SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
     checkEndEntity(certFromFile("ee-post_int-post"), SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
     Services.prefs.clearUserPref("security.test.built_in_root_hash");
   }
 
-  // SHA-1 still allowed only when issued by an imported root.
+  // SHA-1 still allowed only before 2016 or when issued by an imported root.
   // Now test with the test root considered a non-built-in.
+  checkIntermediate(certFromFile("int-pre"), PRErrorCodeSuccess);
   checkEndEntity(certFromFile("ee-pre_int-pre"), PRErrorCodeSuccess);
   checkEndEntity(certFromFile("ee-post_int-pre"), PRErrorCodeSuccess);
-  checkEndEntity(certFromFile("ee-post_int-post"), PRErrorCodeSuccess);
-
-  // SHA-1 allowed before 2016 or when issued by an imported root. First test
-  // with the test root considered a built-in.
-  Services.prefs.setIntPref("security.pki.sha1_enforcement_level", 4);
-  if (isDebugBuild) {
-    let root = certFromFile("ca");
-    Services.prefs.setCharPref("security.test.built_in_root_hash", root.sha256Fingerprint);
-    checkEndEntity(certFromFile("ee-pre_int-pre"), PRErrorCodeSuccess);
-    checkEndEntity(certFromFile("ee-post_int-pre"), SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
-    checkEndEntity(certFromFile("ee-post_int-post"), SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
-    Services.prefs.clearUserPref("security.test.built_in_root_hash");
-  }
-
-  // SHA-1 still only allowed before 2016 or when issued by an imported root.
-  // Now test with the test root considered a non-built-in.
-  checkEndEntity(certFromFile("ee-pre_int-pre"), PRErrorCodeSuccess);
-  checkEndEntity(certFromFile("ee-post_int-pre"), PRErrorCodeSuccess);
+  checkIntermediate(certFromFile("int-post"), PRErrorCodeSuccess);
   checkEndEntity(certFromFile("ee-post_int-post"), PRErrorCodeSuccess);
 }
--- a/security/manager/ssl/tests/unit/test_ocsp_caching.js
+++ b/security/manager/ssl/tests/unit/test_ocsp_caching.js
@@ -57,17 +57,17 @@ function add_ocsp_test(aHost, aExpectedR
               " OCSP request" + (aResponses.length == 1 ? "" : "s"));
       });
 }
 
 function run_test() {
   do_get_profile();
   Services.prefs.setBoolPref("security.ssl.enable_ocsp_stapling", true);
   Services.prefs.setIntPref("security.OCSP.enabled", 1);
-  Services.prefs.setIntPref("security.pki.sha1_enforcement_level", 4);
+  Services.prefs.setIntPref("security.pki.sha1_enforcement_level", 3);
   add_tls_server_setup("OCSPStaplingServer", "ocsp_certs");
 
   let ocspResponder = new HttpServer();
   ocspResponder.registerPrefixHandler("/", function(request, response) {
 
     do_print("gFetchCount: " + gFetchCount);
     let responseFunction = gResponsePattern[gFetchCount];
     Assert.notEqual(undefined, responseFunction);
--- a/security/manager/ssl/tests/unit/test_ocsp_stapling_expired.js
+++ b/security/manager/ssl/tests/unit/test_ocsp_stapling_expired.js
@@ -26,17 +26,17 @@ function add_ocsp_test(aHost, aExpectedR
             "Should have made " + aExpectedRequestCount +
             " fallback OCSP request" + (aExpectedRequestCount == 1 ? "" : "s"));
     });
 }
 
 do_get_profile();
 Services.prefs.setBoolPref("security.ssl.enable_ocsp_stapling", true);
 Services.prefs.setIntPref("security.OCSP.enabled", 1);
-Services.prefs.setIntPref("security.pki.sha1_enforcement_level", 4);
+Services.prefs.setIntPref("security.pki.sha1_enforcement_level", 3);
 var args = [["good", "default-ee", "unused"],
              ["expiredresponse", "default-ee", "unused"],
              ["oldvalidperiod", "default-ee", "unused"],
              ["revoked", "default-ee", "unused"],
              ["unknown", "default-ee", "unused"],
             ];
 var ocspResponses = generateOCSPResponses(args, "ocsp_certs");
 // Fresh response, certificate is good.
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -8171,17 +8171,17 @@
     "kind": "enumerated",
     "n_values": 4,
     "description": "Does enforcing a larger minimum RSA key size cause verification failures? 1 = no, 2 = yes, 3 = another error prevented finding a verified chain"
   },
   "CERT_CHAIN_SHA1_POLICY_STATUS": {
     "expires_in_version": "default",
     "kind": "enumerated",
     "n_values": 6,
-    "description": "1 = No SHA1 signatures, 2 = SHA1 certificates issued by an imported root, 3 = SHA1 certificates issued before 2016, 4 = SHA1 certificates issued after 2015, 5 = another error prevented successful verification"
+    "description": "1 = No SHA1 signatures, 2 = SHA1 certificates issued before 2016, 3 = SHA1 certificates issued by an imported root, 4 = SHA1 certificates issued after 2015, 5 = another error prevented successful verification"
   },
   "WEAVE_CONFIGURED": {
     "expires_in_version": "default",
     "kind": "boolean",
     "description": "If any version of Firefox Sync is configured for this device",
     "releaseChannelCollection": "opt-out"
   },
   "WEAVE_CONFIGURED_MASTER_PASSWORD": {