Bug 891066, Part 1: Remove CertVerifier's dependency on nsNSSComponent, r=keeler, r=cviecco
authorBrian Smith <brian@briansmith.org>
Sun, 19 Jan 2014 14:05:40 -0800
changeset 181295 99cf3634be5dadf488320b12e5c884e6d9363870
parent 181294 914e2811cfca94cda5ac99a6252b9e8f1c37f9d1
child 181296 2dc56ee0e0e51a35ac0573b57451ad79361e6d0d
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskeeler, cviecco
bugs891066
milestone29.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 891066, Part 1: Remove CertVerifier's dependency on nsNSSComponent, r=keeler, r=cviecco
security/manager/ssl/src/CertVerifier.cpp
security/manager/ssl/src/CertVerifier.h
security/manager/ssl/src/SSLServerCertVerification.cpp
security/manager/ssl/src/SharedCertVerifier.h
security/manager/ssl/src/SharedSSLState.cpp
security/manager/ssl/src/SharedSSLState.h
security/manager/ssl/src/moz.build
security/manager/ssl/src/nsCMS.cpp
security/manager/ssl/src/nsIdentityChecking.cpp
security/manager/ssl/src/nsNSSCertificate.cpp
security/manager/ssl/src/nsNSSCertificateDB.cpp
security/manager/ssl/src/nsNSSComponent.cpp
security/manager/ssl/src/nsNSSComponent.h
security/manager/ssl/src/nsUsageArrayHelper.cpp
--- a/security/manager/ssl/src/CertVerifier.cpp
+++ b/security/manager/ssl/src/CertVerifier.cpp
@@ -1,55 +1,54 @@
 /* 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 "CertVerifier.h"
-#include "nsNSSComponent.h"
-#include "nsServiceManagerUtils.h"
+#include "ScopedNSSTypes.h"
 #include "cert.h"
 #include "secerr.h"
+#include "prerror.h"
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gPIPNSSLog;
 #endif
 
 namespace mozilla { namespace psm {
 
 extern SECStatus getFirstEVPolicy(CERTCertificate* cert, SECOidTag& outOidTag);
 extern CERTCertList* getRootsForOid(SECOidTag oid_tag);
 
 const CertVerifier::Flags CertVerifier::FLAG_LOCAL_ONLY = 1;
 const CertVerifier::Flags CertVerifier::FLAG_NO_DV_FALLBACK_FOR_EV = 2;
 
-CertVerifier::CertVerifier(missing_cert_download_config mcdc,
+CertVerifier::CertVerifier(implementation_config ic,
+                           missing_cert_download_config mcdc,
                            crl_download_config cdc,
                            ocsp_download_config odc,
                            ocsp_strict_config osc,
                            ocsp_get_config ogc)
-  : mMissingCertDownloadEnabled(mcdc == missing_cert_download_on)
+  : mImplementation(ic)
+  , mMissingCertDownloadEnabled(mcdc == missing_cert_download_on)
   , mCRLDownloadEnabled(cdc == crl_download_allowed)
   , mOCSPDownloadEnabled(odc == ocsp_on)
   , mOCSPStrict(osc == ocsp_strict)
   , mOCSPGETEnabled(ogc == ocsp_get_enabled)
 {
-  MOZ_COUNT_CTOR(CertVerifier);
 }
 
 CertVerifier::~CertVerifier()
 {
-  MOZ_COUNT_DTOR(CertVerifier);
 }
 
-
 static SECStatus
 ClassicVerifyCert(CERTCertificate* cert,
                   const SECCertificateUsage usage,
                   const PRTime time,
-                  nsIInterfaceRequestor* pinArg,
+                  void* pinArg,
                   /*optional out*/ CERTCertList** validationChain,
                   /*optional out*/ CERTVerifyLog* verifyLog)
 {
   SECStatus rv;
   SECCertUsage enumUsage;
   if (validationChain) {
     switch(usage){
       case  certificateUsageSSLClient:
@@ -112,23 +111,27 @@ ClassicVerifyCert(CERTCertificate* cert,
   }
   return rv;
 }
 
 SECStatus
 CertVerifier::VerifyCert(CERTCertificate* cert,
                          const SECCertificateUsage usage,
                          const PRTime time,
-                         nsIInterfaceRequestor* pinArg,
+                         void* pinArg,
                          const Flags flags,
                          /*optional out*/ CERTCertList** validationChain,
                          /*optional out*/ SECOidTag* evOidPolicy,
                          /*optional out*/ CERTVerifyLog* verifyLog)
 {
-  if (!cert) {
+  if (!cert ||
+      ((flags & FLAG_NO_DV_FALLBACK_FOR_EV) &&
+      (usage != certificateUsageSSLServer || !evOidPolicy)))
+  {
+    PR_NOT_REACHED("Invalid arguments to CertVerifier::VerifyCert");
     PORT_SetError(SEC_ERROR_INVALID_ARGS);
     return SECFailure;
   }
   if (validationChain) {
     *validationChain = nullptr;
   }
   if (evOidPolicy) {
     *evOidPolicy = SEC_OID_UNKNOWN;
@@ -144,27 +147,21 @@ CertVerifier::VerifyCert(CERTCertificate
     case certificateUsageStatusResponder:
       break;
     default:
       NS_WARNING("Calling VerifyCert with invalid usage");
       PORT_SetError(SEC_ERROR_INVALID_ARGS);
       return SECFailure;
   }
 
+#ifndef NSS_NO_LIBPKIX
   ScopedCERTCertList trustAnchors;
   SECStatus rv;
   SECOidTag evPolicy = SEC_OID_UNKNOWN;
 
-#ifdef NSS_NO_LIBPKIX
-  if (flags & FLAG_NO_DV_FALLBACK_FOR_EV) {
-    return SECSuccess;
-  }
-  return ClassicVerifyCert(cert, usage, time, pinArg, validationChain,
-                           verifyLog);
-#else
   // Do EV checking only for sslserver usage
   if (usage == certificateUsageSSLServer) {
     SECStatus srv = getFirstEVPolicy(cert, evPolicy);
     if (srv == SECSuccess) {
       if (evPolicy != SEC_OID_UNKNOWN) {
         trustAnchors = getRootsForOid(evPolicy);
       }
       if (!trustAnchors) {
@@ -310,30 +307,39 @@ CertVerifier::VerifyCert(CERTCertificate
          // No need to cleanup the actual nodes in the arena.
       }
       verifyLog->count = 0;
       verifyLog->head = nullptr;
       verifyLog->tail = nullptr;
     }
 
   }
+#endif
 
   // If we're here, PKIX EV verification failed.
   // If requested, don't do DV fallback.
   if (flags & FLAG_NO_DV_FALLBACK_FOR_EV) {
+    PR_ASSERT(*evOidPolicy == SEC_OID_UNKNOWN);
     return SECSuccess;
   }
 
-  if (!nsNSSComponent::globalConstFlagUsePKIXVerification){
+  if (mImplementation == classic) {
     // XXX: we do not care about the localOnly flag (currently) as the
     // caller that wants localOnly should disable and reenable the fetching.
     return ClassicVerifyCert(cert, usage, time, pinArg, validationChain,
                              verifyLog);
   }
 
+#ifdef NSS_NO_LIBPKIX
+  PR_NOT_REACHED("libpkix implementation chosen but not even compiled in");
+  PR_SetError(PR_INVALID_STATE_ERROR, 0);
+  return SECFailure;
+#else
+  PR_ASSERT(mImplementation == libpkix);
+
   // The current flags check the chain the same way as the leafs
   rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_crl] =
   rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_crl] =
     // implicit default source - makes no sense for CRLs
     CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE
 
     // let's not stop on fresh CRL. If OCSP is enabled, too, let's check it
     | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO
@@ -427,22 +433,9 @@ pkix_done:
       }
     }
   }
 
   return rv;
 #endif
 }
 
-TemporaryRef<CertVerifier>
-GetDefaultCertVerifier()
-{
-  static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
-
-  nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID));
-  RefPtr<CertVerifier> certVerifier;
-  if (nssComponent) {
-    (void) nssComponent->GetDefaultCertVerifier(certVerifier);
-  }
-  return certVerifier;
-}
-
 } } // namespace mozilla::psm
--- a/security/manager/ssl/src/CertVerifier.h
+++ b/security/manager/ssl/src/CertVerifier.h
@@ -1,66 +1,64 @@
 /* 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/. */
 
 #ifndef mozilla_psm__CertVerifier_h
 #define mozilla_psm__CertVerifier_h
 
-#include "mozilla/RefPtr.h"
-#include "CryptoUtil.h"
-#include "nsISupportsImpl.h"
 #include "certt.h"
-
-class nsIInterfaceRequestor;
-class nsNSSComponent;
+#include "insanity/ScopedPtr.h"
 
 namespace mozilla { namespace psm {
 
 class CertVerifier
 {
 public:
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CertVerifier)
-
   typedef unsigned int Flags;
   // XXX: FLAG_LOCAL_ONLY is ignored in the classic verification case
   static const Flags FLAG_LOCAL_ONLY;
   // Don't perform fallback DV validation on EV validation failure.
   static const Flags FLAG_NO_DV_FALLBACK_FOR_EV;
 
   // *evOidPolicy == SEC_OID_UNKNOWN means the cert is NOT EV
   // Only one usage per verification is supported.
   SECStatus VerifyCert(CERTCertificate* cert,
                        const SECCertificateUsage usage,
                        const PRTime time,
-                       nsIInterfaceRequestor* pinArg,
+                       void* pinArg,
                        const Flags flags = 0,
                        /*optional out*/ CERTCertList** validationChain = nullptr,
                        /*optional out*/ SECOidTag* evOidPolicy = nullptr ,
                        /*optional out*/ CERTVerifyLog* verifyLog = nullptr);
 
+  enum implementation_config {
+    classic = 0,
+#ifndef NSS_NO_LIBPKIX
+    libpkix = 1,
+#endif
+  };
+
   enum missing_cert_download_config { missing_cert_download_off = 0, missing_cert_download_on };
   enum crl_download_config { crl_local_only = 0, crl_download_allowed };
   enum ocsp_download_config { ocsp_off = 0, ocsp_on };
   enum ocsp_strict_config { ocsp_relaxed = 0, ocsp_strict };
   enum ocsp_get_config { ocsp_get_disabled = 0, ocsp_get_enabled = 1 };
 
   bool IsOCSPDownloadEnabled() const { return mOCSPDownloadEnabled; }
 
-private:
-  CertVerifier(missing_cert_download_config ac, crl_download_config cdc,
-               ocsp_download_config odc, ocsp_strict_config osc,
-               ocsp_get_config ogc);
+  CertVerifier(implementation_config ic, missing_cert_download_config ac,
+               crl_download_config cdc, ocsp_download_config odc,
+               ocsp_strict_config osc, ocsp_get_config ogc);
   ~CertVerifier();
 
+public:
+  const implementation_config mImplementation;
   const bool mMissingCertDownloadEnabled;
   const bool mCRLDownloadEnabled;
   const bool mOCSPDownloadEnabled;
   const bool mOCSPStrict;
   const bool mOCSPGETEnabled;
-  friend class ::nsNSSComponent;
 };
 
-MOZ_WARN_UNUSED_RESULT TemporaryRef<CertVerifier> GetDefaultCertVerifier();
-
 } } // namespace mozilla::psm
 
 #endif // mozilla_psm__CertVerifier_h
--- a/security/manager/ssl/src/SSLServerCertVerification.cpp
+++ b/security/manager/ssl/src/SSLServerCertVerification.cpp
@@ -460,17 +460,18 @@ PRErrorCodeToOverrideType(PRErrorCode er
     default:
       return 0;
   }
 }
 
 // Returns null with the error code (PR_GetError()) set if it does not create
 // the CertErrorRunnable.
 CertErrorRunnable*
-CreateCertErrorRunnable(PRErrorCode defaultErrorCodeToReport,
+CreateCertErrorRunnable(CertVerifier& certVerifier,
+                        PRErrorCode defaultErrorCodeToReport,
                         TransportSecurityInfo* infoObject,
                         CERTCertificate* cert,
                         const void* fdForLogging,
                         uint32_t providerFlags,
                         PRTime now)
 {
   MOZ_ASSERT(infoObject);
   MOZ_ASSERT(cert);
@@ -493,40 +494,33 @@ CreateCertErrorRunnable(PRErrorCode defa
   if (!nssCert) {
     NS_ERROR("nsNSSCertificate::Create failed");
     PR_SetError(SEC_ERROR_NO_MEMORY, 0);
     return nullptr;
   }
 
   SECStatus srv;
 
-  RefPtr<CertVerifier> certVerifier(GetDefaultCertVerifier());
-  if (!certVerifier) {
-    NS_ERROR("GetDefaultCerVerifier failed");
-    PR_SetError(defaultErrorCodeToReport, 0);
-    return nullptr;
-  }
-
   PLArenaPool* log_arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   PLArenaPoolCleanerFalseParam log_arena_cleaner(log_arena);
   if (!log_arena) {
     NS_ERROR("PORT_NewArena failed");
     return nullptr; // PORT_NewArena set error code
   }
 
   CERTVerifyLog* verify_log = PORT_ArenaZNew(log_arena, CERTVerifyLog);
   if (!verify_log) {
     NS_ERROR("PORT_ArenaZNew failed");
     return nullptr; // PORT_ArenaZNew set error code
   }
   CERTVerifyLogContentsCleaner verify_log_cleaner(verify_log);
   verify_log->arena = log_arena;
 
-  srv = certVerifier->VerifyCert(cert, certificateUsageSSLServer, now,
-                                 infoObject, 0, nullptr, nullptr, verify_log);
+  srv = certVerifier.VerifyCert(cert, certificateUsageSSLServer, now,
+                                infoObject, 0, nullptr, nullptr, verify_log);
 
   // We ignore the result code of the cert verification.
   // Either it is a failure, which is expected, and we'll process the
   //                         verify log below.
   // Or it is a success, then a domain mismatch is the only
   //                     possible failure.
 
   PRErrorCode errorCodeMismatch = 0;
@@ -619,67 +613,66 @@ private:
   }
   RefPtr<CertErrorRunnable> mCertErrorRunnable;
 };
 
 class SSLServerCertVerificationJob : public nsRunnable
 {
 public:
   // Must be called only on the socket transport thread
-  static SECStatus Dispatch(const void* fdForLogging,
-                            nsNSSSocketInfo* infoObject,
+  static SECStatus Dispatch(const RefPtr<SharedCertVerifier>& certVerifier,
+                            const void* fdForLogging,
+                            TransportSecurityInfo* infoObject,
                             CERTCertificate* serverCert,
                             SECItem* stapledOCSPResponse,
                             uint32_t providerFlags);
 private:
   NS_DECL_NSIRUNNABLE
 
   // Must be called only on the socket transport thread
-  SSLServerCertVerificationJob(const void* fdForLogging,
-                               nsNSSSocketInfo* infoObject,
+  SSLServerCertVerificationJob(const RefPtr<SharedCertVerifier>& certVerifier,
+                               const void* fdForLogging,
+                               TransportSecurityInfo* infoObject,
                                CERTCertificate* cert,
                                SECItem* stapledOCSPResponse,
                                uint32_t providerFlags);
+  const RefPtr<SharedCertVerifier> mCertVerifier;
   const void* const mFdForLogging;
-  const RefPtr<nsNSSSocketInfo> mInfoObject;
+  const RefPtr<TransportSecurityInfo> mInfoObject;
   const ScopedCERTCertificate mCert;
   const uint32_t mProviderFlags;
   const TimeStamp mJobStartTime;
   const ScopedSECItem mStapledOCSPResponse;
 };
 
 SSLServerCertVerificationJob::SSLServerCertVerificationJob(
-    const void* fdForLogging, nsNSSSocketInfo* infoObject,
-    CERTCertificate* cert, SECItem* stapledOCSPResponse,
-    uint32_t providerFlags)
-  : mFdForLogging(fdForLogging)
+    const RefPtr<SharedCertVerifier>& certVerifier, const void* fdForLogging,
+    TransportSecurityInfo* infoObject, CERTCertificate* cert,
+    SECItem* stapledOCSPResponse, uint32_t providerFlags)
+  : mCertVerifier(certVerifier)
+  , mFdForLogging(fdForLogging)
   , mInfoObject(infoObject)
   , mCert(CERT_DupCertificate(cert))
   , mProviderFlags(providerFlags)
   , mJobStartTime(TimeStamp::Now())
   , mStapledOCSPResponse(SECITEM_DupItem(stapledOCSPResponse))
 {
 }
 
 SECStatus
-PSM_SSL_PKIX_AuthCertificate(CERTCertificate* peerCert,
+PSM_SSL_PKIX_AuthCertificate(CertVerifier& certVerifier,
+                             CERTCertificate* peerCert,
                              nsIInterfaceRequestor* pinarg,
                              const char* hostname,
                              CERTCertList** validationChain,
                              SECOidTag* evOidPolicy)
 {
-    RefPtr<CertVerifier> certVerifier(GetDefaultCertVerifier());
-    if (!certVerifier) {
-      PR_SetError(PR_INVALID_STATE_ERROR, 0);
-      return SECFailure;
-    }
-
-    SECStatus rv = certVerifier->VerifyCert(peerCert,
-                                            certificateUsageSSLServer, PR_Now(),
-                                            pinarg, 0, validationChain , evOidPolicy);
+    SECStatus rv = certVerifier.VerifyCert(peerCert, certificateUsageSSLServer,
+                                           PR_Now(), pinarg, 0,
+                                           validationChain, evOidPolicy);
 
     if (rv == SECSuccess) {
         // cert is OK. This is the client side of an SSL connection.
         // Now check the name field in the cert against the desired hostname.
         // NB: This is our only defense against Man-In-The-Middle (MITM) attacks!
         if (hostname && hostname[0])
             rv = CERT_VerifyCertName(peerCert, hostname);
         else
@@ -840,18 +833,19 @@ BlockServerCertChangeForSpdy(nsNSSSocket
   // Report an error - changed cert is confirmed
   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
          ("SPDY Refused to allow new cert during renegotiation\n"));
   PR_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED, 0);
   return SECFailure;
 }
 
 SECStatus
-AuthCertificate(nsNSSSocketInfo* infoObject, CERTCertificate* cert,
-                SECItem* stapledOCSPResponse, uint32_t providerFlags)
+AuthCertificate(CertVerifier& certVerifier, TransportSecurityInfo* infoObject,
+                CERTCertificate* cert, SECItem* stapledOCSPResponse,
+                uint32_t providerFlags)
 {
   if (cert->serialNumber.data &&
       cert->issuerName &&
       !strcmp(cert->issuerName,
         "CN=UTN-USERFirst-Hardware,OU=http://www.usertrust.com,O=The USERTRUST Network,L=Salt Lake City,ST=UT,C=US")) {
 
     unsigned char* server_cert_comparison_start = cert->serialNumber.data;
     unsigned int server_cert_comparison_len = cert->serialNumber.len;
@@ -921,27 +915,28 @@ AuthCertificate(nsNSSSocketInfo* infoObj
       reasonsForNotFetching |= 1; // invalid/missing OCSP URI
     } else {
       if (std::strncmp(ocspURI, "http://", 7)) { // approximation
         reasonsForNotFetching |= 1; // invalid/missing OCSP URI
       }
       PORT_Free(ocspURI);
     }
 
-    if (!infoObject->SharedState().IsOCSPFetchingEnabled()) {
+    if (!certVerifier.mOCSPDownloadEnabled) {
       reasonsForNotFetching |= 2;
     }
 
     Telemetry::Accumulate(Telemetry::SSL_OCSP_MAY_FETCH,
                           reasonsForNotFetching);
   }
 
   CERTCertList* verifyCertChain = nullptr;
   SECOidTag evOidPolicy;
-  rv = PSM_SSL_PKIX_AuthCertificate(cert, infoObject, infoObject->GetHostNameRaw(),
+  rv = PSM_SSL_PKIX_AuthCertificate(certVerifier, cert, infoObject,
+                                    infoObject->GetHostNameRaw(),
                                     &verifyCertChain, &evOidPolicy);
 
   // We want to remember the CA certs in the temp db, so that the application can find the
   // complete chain at any time it might need it.
   // But we keep only those CA certs in the temp db, that we didn't already know.
 
   RefPtr<nsSSLStatus> status(infoObject->SSLStatus());
   RefPtr<nsNSSCertificate> nsc;
@@ -1047,32 +1042,35 @@ AuthCertificate(nsNSSSocketInfo* infoObj
              ("AuthCertificate setting NEW cert %p\n", status->mServerCert.get()));
     }
   }
 
   return rv;
 }
 
 /*static*/ SECStatus
-SSLServerCertVerificationJob::Dispatch(const void* fdForLogging,
-                                       nsNSSSocketInfo* infoObject,
-                                       CERTCertificate* serverCert,
-                                       SECItem* stapledOCSPResponse,
-                                       uint32_t providerFlags)
+SSLServerCertVerificationJob::Dispatch(
+  const RefPtr<SharedCertVerifier>& certVerifier,
+  const void* fdForLogging,
+  TransportSecurityInfo* infoObject,
+  CERTCertificate* serverCert,
+  SECItem* stapledOCSPResponse,
+  uint32_t providerFlags)
 {
   // Runs on the socket transport thread
-  if (!infoObject || !serverCert) {
+  if (!certVerifier || !infoObject || !serverCert) {
     NS_ERROR("Invalid parameters for SSL server cert validation");
     PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
     return SECFailure;
   }
 
   RefPtr<SSLServerCertVerificationJob> job(
-    new SSLServerCertVerificationJob(fdForLogging, infoObject, serverCert,
-                                     stapledOCSPResponse, providerFlags));
+    new SSLServerCertVerificationJob(certVerifier, fdForLogging, infoObject,
+                                     serverCert, stapledOCSPResponse,
+                                     providerFlags));
 
   nsresult nrv;
   if (!gCertVerificationThreadPool) {
     nrv = NS_ERROR_NOT_INITIALIZED;
   } else {
     nrv = gCertVerificationThreadPool->Dispatch(job, NS_DISPATCH_NORMAL);
   }
   if (NS_FAILED(nrv)) {
@@ -1103,65 +1101,63 @@ SSLServerCertVerificationJob::Run()
           ("[%p] SSLServerCertVerificationJob::Run\n", mInfoObject.get()));
 
   PRErrorCode error;
 
   nsNSSShutDownPreventionLock nssShutdownPrevention;
   if (mInfoObject->isAlreadyShutDown()) {
     error = SEC_ERROR_USER_CANCELLED;
   } else {
+    Telemetry::ID successTelemetry;
+    Telemetry::ID failureTelemetry;
+    switch (mCertVerifier->mImplementation) {
+      case CertVerifier::classic:
+        successTelemetry
+          = Telemetry::SSL_SUCCESFUL_CERT_VALIDATION_TIME_CLASSIC;
+        failureTelemetry
+          = Telemetry::SSL_INITIAL_FAILED_CERT_VALIDATION_TIME_CLASSIC;
+        break;
+#ifndef NSS_NO_LIBPKIX
+      case CertVerifier::libpkix:
+        successTelemetry
+          = Telemetry::SSL_SUCCESFUL_CERT_VALIDATION_TIME_LIBPKIX;
+        failureTelemetry
+          = Telemetry::SSL_INITIAL_FAILED_CERT_VALIDATION_TIME_LIBPKIX;
+        break;
+#endif
+      default:
+        MOZ_CRASH("Unknown CertVerifier mode");
+    }
+
     // Reset the error code here so we can detect if AuthCertificate fails to
     // set the error code if/when it fails.
     PR_SetError(0, 0);
-    SECStatus rv = AuthCertificate(mInfoObject, mCert, mStapledOCSPResponse,
-                                   mProviderFlags);
+    SECStatus rv = AuthCertificate(*mCertVerifier, mInfoObject, mCert,
+                                   mStapledOCSPResponse, mProviderFlags);
     if (rv == SECSuccess) {
       uint32_t interval = (uint32_t) ((TimeStamp::Now() - mJobStartTime).ToMilliseconds());
-      Telemetry::ID telemetryID;
-#ifndef NSS_NO_LIBPKIX
-      if(nsNSSComponent::globalConstFlagUsePKIXVerification){
-        telemetryID = Telemetry::SSL_SUCCESFUL_CERT_VALIDATION_TIME_LIBPKIX;
-      }
-      else{
-#endif
-        telemetryID = Telemetry::SSL_SUCCESFUL_CERT_VALIDATION_TIME_CLASSIC;
-#ifndef NSS_NO_LIBPKIX
-      }
-#endif
       RefPtr<SSLServerCertVerificationResult> restart(
         new SSLServerCertVerificationResult(mInfoObject, 0,
-                                            telemetryID, interval));
+                                            successTelemetry, interval));
       restart->Dispatch();
       return NS_OK;
     }
 
     // Note: the interval is not calculated once as PR_GetError MUST be called
     // before any other  function call
     error = PR_GetError();
     {
       TimeStamp now = TimeStamp::Now();
-      Telemetry::ID telemetryID;
-#ifndef NSS_NO_LIBPKIX
-      if(nsNSSComponent::globalConstFlagUsePKIXVerification) {
-        telemetryID = Telemetry::SSL_INITIAL_FAILED_CERT_VALIDATION_TIME_LIBPKIX;
-      }
-      else {
-#endif
-        telemetryID = Telemetry::SSL_INITIAL_FAILED_CERT_VALIDATION_TIME_CLASSIC;
-#ifndef NSS_NO_LIBPKIX
-      }
-#endif
       MutexAutoLock telemetryMutex(*gSSLVerificationTelemetryMutex);
-      Telemetry::AccumulateTimeDelta(telemetryID,
-                                     mJobStartTime,
-                                     now);
+      Telemetry::AccumulateTimeDelta(failureTelemetry, mJobStartTime, now);
     }
     if (error != 0) {
-      RefPtr<CertErrorRunnable> runnable(CreateCertErrorRunnable(
-        error, mInfoObject, mCert, mFdForLogging, mProviderFlags, PR_Now()));
+      RefPtr<CertErrorRunnable> runnable(
+          CreateCertErrorRunnable(*mCertVerifier, error, mInfoObject, mCert,
+                                  mFdForLogging, mProviderFlags, PR_Now()));
       if (!runnable) {
         // CreateCertErrorRunnable set a new error code
         error = PR_GetError();
       } else {
         // We must block the the socket transport service thread while the
         // main thread executes the CertErrorRunnable. The CertErrorRunnable
         // will dispatch the result asynchronously, so we don't have to block
         // this thread waiting for it.
@@ -1201,16 +1197,22 @@ SSLServerCertVerificationJob::Run()
 } // unnamed namespace
 
 // Extracts whatever information we need out of fd (using SSL_*) and passes it
 // to SSLServerCertVerificationJob::Dispatch. SSLServerCertVerificationJob should
 // never do anything with fd except logging.
 SECStatus
 AuthCertificateHook(void* arg, PRFileDesc* fd, PRBool checkSig, PRBool isServer)
 {
+  RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
+  if (!certVerifier) {
+    PR_SetError(SEC_ERROR_NOT_INITIALIZED, 0);
+    return SECFailure;
+  }
+
   // Runs on the socket transport thread
 
   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
          ("[%p] starting AuthCertificateHook\n", fd));
 
   // Modern libssl always passes PR_TRUE for checkSig, and we have no means of
   // doing verification without checking signatures.
   NS_ASSERTION(checkSig, "AuthCertificateHook: checkSig unexpectedly false");
@@ -1225,16 +1227,20 @@ AuthCertificateHook(void* arg, PRFileDes
 
   if (!checkSig || isServer || !socketInfo || !serverCert) {
       PR_SetError(PR_INVALID_STATE_ERROR, 0);
       return SECFailure;
   }
 
   socketInfo->SetFullHandshake();
 
+  // This value of "now" is used both here for OCSP stapling and later
+  // when calling CreateCertErrorRunnable.
+  PRTime now = PR_Now();
+
   if (BlockServerCertChangeForSpdy(socketInfo, serverCert) != SECSuccess)
     return SECFailure;
 
   bool onSTSThread;
   nsresult nrv;
   nsCOMPtr<nsIEventTarget> sts
     = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &nrv);
   if (NS_SUCCEEDED(nrv)) {
@@ -1264,37 +1270,38 @@ AuthCertificateHook(void* arg, PRFileDes
   if (onSTSThread) {
 
     // We *must* do certificate verification on a background thread because
     // we need the socket transport thread to be free for our OCSP requests,
     // and we *want* to do certificate verification on a background thread
     // because of the performance benefits of doing so.
     socketInfo->SetCertVerificationWaiting();
     SECStatus rv = SSLServerCertVerificationJob::Dispatch(
-                     static_cast<const void*>(fd), socketInfo, serverCert,
-                     stapledOCSPResponse, providerFlags);
+                     certVerifier, static_cast<const void*>(fd), socketInfo,
+                     serverCert, stapledOCSPResponse, providerFlags);
     return rv;
   }
 
   // We can't do certificate verification on a background thread, because the
   // thread doing the network I/O may not interrupt its network I/O on receipt
   // of our SSLServerCertVerificationResult event, and/or it might not even be
   // a non-blocking socket.
 
-  SECStatus rv = AuthCertificate(socketInfo, serverCert, stapledOCSPResponse,
-                                 providerFlags);
+  SECStatus rv = AuthCertificate(*certVerifier, socketInfo, serverCert,
+                                 stapledOCSPResponse, providerFlags);
   if (rv == SECSuccess) {
     return SECSuccess;
   }
 
   PRErrorCode error = PR_GetError();
   if (error != 0) {
-    RefPtr<CertErrorRunnable> runnable(CreateCertErrorRunnable(
-                    error, socketInfo, serverCert,
-                    static_cast<const void*>(fd), providerFlags, PR_Now()));
+    RefPtr<CertErrorRunnable> runnable(
+        CreateCertErrorRunnable(*certVerifier, error, socketInfo, serverCert,
+                                static_cast<const void*>(fd), providerFlags,
+                                now));
     if (!runnable) {
       // CreateCertErrorRunnable sets a new error code when it fails
       error = PR_GetError();
     } else {
       // We have to return SECSuccess or SECFailure based on the result of the
       // override processing, so we must block this thread waiting for it. The
       // CertErrorRunnable will NOT dispatch the result at all, since we passed
       // false for CreateCertErrorRunnable's async parameter
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/src/SharedCertVerifier.h
@@ -0,0 +1,29 @@
+/* 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/. */
+
+#ifndef mozilla_psm__SharedCertVerifier_h
+#define mozilla_psm__SharedCertVerifier_h
+
+#include "certt.h"
+#include "CertVerifier.h"
+#include "mozilla/RefPtr.h"
+
+namespace mozilla { namespace psm {
+
+class SharedCertVerifier : public mozilla::psm::CertVerifier,
+                           public mozilla::AtomicRefCounted<SharedCertVerifier>
+{
+public:
+  SharedCertVerifier(implementation_config ic, missing_cert_download_config ac,
+                     crl_download_config cdc, ocsp_download_config odc,
+                     ocsp_strict_config osc, ocsp_get_config ogc)
+    : mozilla::psm::CertVerifier(ic, ac, cdc, odc, osc, ogc)
+  {
+  }
+  ~SharedCertVerifier();
+};
+
+} } // namespace mozilla::psm
+
+#endif // mozilla_psm__SharedCertVerifier_h
--- a/security/manager/ssl/src/SharedSSLState.cpp
+++ b/security/manager/ssl/src/SharedSSLState.cpp
@@ -131,17 +131,16 @@ PrivateBrowsingObserver::Observe(nsISupp
   return NS_OK;
 }
 
 SharedSSLState::SharedSSLState()
 : mClientAuthRemember(new nsClientAuthRememberService)
 , mMutex("SharedSSLState::mMutex")
 , mSocketCreated(false)
 , mOCSPStaplingEnabled(false)
-, mOCSPFetchingEnabled(false)
 {
   mIOLayerHelpers.Init();
   mClientAuthRemember->Init();
 }
 
 SharedSSLState::~SharedSSLState()
 {
 }
--- a/security/manager/ssl/src/SharedSSLState.h
+++ b/security/manager/ssl/src/SharedSSLState.h
@@ -31,44 +31,41 @@ public:
 
   nsSSLIOLayerHelpers& IOLayerHelpers() {
     return mIOLayerHelpers;
   }
 
   // Main-thread only
   void ResetStoredData();
   void NotePrivateBrowsingStatus();
-  void SetOCSPOptions(bool fetchingEnabled, bool staplingEnabled)
+  void SetOCSPStaplingEnabled(bool staplingEnabled)
   {
-    mOCSPFetchingEnabled = fetchingEnabled;
     mOCSPStaplingEnabled = staplingEnabled;
   }
 
   // The following methods may be called from any thread
   bool SocketCreated();
   void NoteSocketCreated();
   static void NoteCertOverrideServiceInstantiated();
   static void NoteCertDBServiceInstantiated();
   bool IsOCSPStaplingEnabled() const { return mOCSPStaplingEnabled; }
-  bool IsOCSPFetchingEnabled() const { return mOCSPFetchingEnabled; }
 
 private:
   void Cleanup();
 
   nsCOMPtr<nsIObserver> mObserver;
   RefPtr<nsClientAuthRememberService> mClientAuthRemember;
   nsSSLIOLayerHelpers mIOLayerHelpers;
 
   // True if any sockets have been created that use this shared data.
   // Requires synchronization between the socket and main threads for
   // reading/writing.
   Mutex mMutex;
   bool mSocketCreated;
   bool mOCSPStaplingEnabled;
-  bool mOCSPFetchingEnabled;
 };
 
 SharedSSLState* PublicSSLState();
 SharedSSLState* PrivateSSLState();
 
 } // namespace psm
 } // namespace mozilla
 
--- a/security/manager/ssl/src/moz.build
+++ b/security/manager/ssl/src/moz.build
@@ -88,11 +88,16 @@ if CONFIG['MOZ_XUL']:
     ]
 
 UNIFIED_SOURCES += [
     'md4.c',
 ]
 
 FINAL_LIBRARY = 'xul'
 
+LOCAL_INCLUDES += [
+	'../../../insanity/include',
+]
+
+
 DEFINES['NSS_ENABLE_ECC'] = 'True'
 for var in ('DLL_PREFIX', 'DLL_SUFFIX'):
     DEFINES[var] = '"%s"' % CONFIG[var]
--- a/security/manager/ssl/src/nsCMS.cpp
+++ b/security/manager/ssl/src/nsCMS.cpp
@@ -208,17 +208,17 @@ nsresult nsCMSMessage::CommonVerifySigna
   if (isAlreadyShutDown())
     return NS_ERROR_NOT_AVAILABLE;
 
   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature, content level count %d\n", NSS_CMSMessage_ContentLevelCount(m_cmsMsg)));
   NSSCMSContentInfo *cinfo = nullptr;
   NSSCMSSignedData *sigd = nullptr;
   NSSCMSSignerInfo *si;
   int32_t nsigners;
-  RefPtr<CertVerifier> certVerifier;
+  RefPtr<SharedCertVerifier> certVerifier;
   nsresult rv = NS_ERROR_FAILURE;
 
   if (!NSS_CMSMessage_IsSigned(m_cmsMsg)) {
     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - not signed\n"));
     return NS_ERROR_CMS_VERIFY_NOT_SIGNED;
   } 
 
   cinfo = NSS_CMSMessage_ContentLevel(m_cmsMsg, 0);
--- a/security/manager/ssl/src/nsIdentityChecking.cpp
+++ b/security/manager/ssl/src/nsIdentityChecking.cpp
@@ -1275,17 +1275,18 @@ nsNSSCertificate::hasValidEVOidTag(SECOi
 
   nsresult nrv;
   nsCOMPtr<nsINSSComponent> nssComponent =
     do_GetService(PSM_COMPONENT_CONTRACTID, &nrv);
   if (NS_FAILED(nrv))
     return nrv;
   nssComponent->EnsureIdentityInfoLoaded();
 
-  RefPtr<mozilla::psm::CertVerifier> certVerifier(mozilla::psm::GetDefaultCertVerifier());
+  RefPtr<mozilla::psm::SharedCertVerifier>
+    certVerifier(mozilla::psm::GetDefaultCertVerifier());
   NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
 
   validEV = false;
   resultOidTag = SEC_OID_UNKNOWN;
 
   uint32_t flags = mozilla::psm::CertVerifier::FLAG_LOCAL_ONLY |
                    mozilla::psm::CertVerifier::FLAG_NO_DV_FALLBACK_FOR_EV;
   SECStatus rv = certVerifier->VerifyCert(mCert,
--- a/security/manager/ssl/src/nsNSSCertificate.cpp
+++ b/security/manager/ssl/src/nsNSSCertificate.cpp
@@ -819,17 +819,17 @@ nsNSSCertificate::GetChain(nsIArray** _r
 
   NS_ENSURE_ARG(_rvChain);
   nsresult rv;
   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Getting chain for \"%s\"\n", mCert->nickname));
 
   ScopedCERTCertList nssChain;
   SECStatus srv;
   nssChain = nullptr;
-  RefPtr<CertVerifier> certVerifier(GetDefaultCertVerifier());
+  RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
   NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
   CERTCertList* pkixNssChain = nullptr;
 
   // We want to test all usages, but we start with server because most of the
   // time Firefox users care about server certs.
   srv = certVerifier->VerifyCert(mCert,
                                  certificateUsageSSLServer, PR_Now(),
                                  nullptr, /*XXX fixme*/
--- a/security/manager/ssl/src/nsNSSCertificateDB.cpp
+++ b/security/manager/ssl/src/nsNSSCertificateDB.cpp
@@ -560,17 +560,17 @@ nsNSSCertificateDB::ImportEmailCertifica
     return NS_ERROR_OUT_OF_MEMORY;
 
   CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length, locker);
   if (!certCollection) {
     PORT_FreeArena(arena, false);
     return NS_ERROR_FAILURE;
   }
 
-  RefPtr<CertVerifier> certVerifier(GetDefaultCertVerifier());
+  RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
   NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
 
   certdb = CERT_GetDefaultCertDB();
   const PRTime now = PR_Now();
 
   numcerts = certCollection->numcerts;
 
   rawArray = (SECItem **) PORT_Alloc(sizeof(SECItem *) * numcerts);
@@ -765,17 +765,17 @@ nsNSSCertificateDB::ImportValidCACerts(i
 
   return ImportValidCACertsInList(certList, ctx, proofOfLock);
 }
 
 nsresult
 nsNSSCertificateDB::ImportValidCACertsInList(CERTCertList *certList, nsIInterfaceRequestor *ctx,
                                              const nsNSSShutDownPreventionLock &proofOfLock)
 {
-  RefPtr<CertVerifier> certVerifier(GetDefaultCertVerifier());
+  RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
   if (!certVerifier)
     return NS_ERROR_UNEXPECTED;
 
   /* filter out the certs we don't want */
   SECStatus srv = CERT_FilterCertListByUsage(certList, certUsageAnyCA, true);
   if (srv != SECSuccess) {
     return NS_ERROR_FAILURE;
   }
@@ -1342,17 +1342,17 @@ nsNSSCertificateDB::FindEmailSigningCert
 NS_IMETHODIMP
 nsNSSCertificateDB::FindCertByEmailAddress(nsISupports *aToken, const char *aEmailAddress, nsIX509Cert **_retval)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown()) {
     return NS_ERROR_NOT_AVAILABLE;
   }
   
-  RefPtr<CertVerifier> certVerifier(GetDefaultCertVerifier());
+  RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
   NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
 
   ScopedCERTCertList certlist(
       PK11_FindCertsFromEmailAddress(aEmailAddress, nullptr));
   if (!certlist)
     return NS_ERROR_FAILURE;  
 
   // certlist now contains certificates with the right email address,
@@ -1708,17 +1708,17 @@ nsNSSCertificateDB::VerifyCertNow(nsIX50
 #endif
 
   nsCOMPtr<nsIX509Cert2> x509Cert = do_QueryInterface(aCert);
   if (!x509Cert) {
     return NS_ERROR_INVALID_ARG;
   }
   ScopedCERTCertificate nssCert(x509Cert->GetCert());
 
-  RefPtr<CertVerifier> certVerifier(GetDefaultCertVerifier());
+  RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
   NS_ENSURE_TRUE(certVerifier, NS_ERROR_FAILURE);
 
   CERTCertList* resultChain = nullptr;
   SECOidTag evOidPolicy;
   SECStatus srv;
 
   srv = certVerifier->VerifyCert(nssCert,
                                  aUsage, PR_Now(),
--- a/security/manager/ssl/src/nsNSSComponent.cpp
+++ b/security/manager/ssl/src/nsNSSComponent.cpp
@@ -5,17 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifdef MOZ_LOGGING
 #define FORCE_PR_LOG 1
 #endif
 
 #include "nsNSSComponent.h"
 
-#include "CertVerifier.h"
 #include "mozilla/Telemetry.h"
 #include "nsCertVerificationThread.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsComponentManagerUtils.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsICertOverrideService.h"
 #include "mozilla/Preferences.h"
 #include "nsThreadUtils.h"
@@ -73,20 +72,16 @@ using namespace mozilla::dom;
 using namespace mozilla::psm;
 
 #ifdef MOZ_LOGGING
 PRLogModuleInfo* gPIPNSSLog = nullptr;
 #endif
 
 int nsNSSComponent::mInstanceCount = 0;
 
-#ifndef NSS_NO_LIBPKIX
-bool nsNSSComponent::globalConstFlagUsePKIXVerification = false;
-#endif
-
 // XXX tmp callback for slot password
 extern char* pk11PasswordPrompt(PK11SlotInfo* slot, PRBool retry, void* arg);
 
 #ifndef MOZ_DISABLE_CRYPTOLEGACY
 //This class is used to run the callback code
 //passed to the event handlers for smart card notification
 class nsTokenEventRunnable : public nsIRunnable {
 public:
@@ -1027,18 +1022,18 @@ void nsNSSComponent::setValidationOption
     Telemetry::Accumulate(Telemetry::CERT_OCSP_REQUIRED, ocspRequired);
   }
 
   bool aiaDownloadEnabled = Preferences::GetBool("security.missing_cert_download.enabled",
                                                  false);
 
   bool ocspStaplingEnabled = Preferences::GetBool("security.ssl.enable_ocsp_stapling",
                                                   true);
-  PublicSSLState()->SetOCSPOptions(ocspEnabled, ocspStaplingEnabled);
-  PrivateSSLState()->SetOCSPOptions(ocspEnabled, ocspStaplingEnabled);
+  PublicSSLState()->SetOCSPStaplingEnabled(ocspStaplingEnabled);
+  PrivateSSLState()->SetOCSPStaplingEnabled(ocspStaplingEnabled);
 
   setNonPkixOcspEnabled(ocspEnabled);
 
   CERT_SetOCSPFailureMode( ocspRequired ?
                            ocspMode_FailureIsVerificationFailure
                            : ocspMode_FailureIsNotAVerificationFailure);
 
   int OCSPTimeoutSeconds = 3;
@@ -1046,17 +1041,27 @@ void nsNSSComponent::setValidationOption
     OCSPTimeoutSeconds = 10;
   }
   CERT_SetOCSPTimeout(OCSPTimeoutSeconds);
 
   // XXX: Always use POST for OCSP; see bug 871954 for undoing this.
   bool ocspGetEnabled = Preferences::GetBool("security.OCSP.GET.enabled", false);
   CERT_ForcePostMethodForOCSP(!ocspGetEnabled);
 
-  mDefaultCertVerifier = new CertVerifier(
+  CertVerifier::implementation_config certVerifierImplementation
+    = CertVerifier::classic;
+
+#ifndef NSS_NO_LIBPKIX
+  if (Preferences::GetBool("security.use_libpkix_verification", false)) {
+    certVerifierImplementation = CertVerifier::libpkix;
+  }
+#endif
+
+  mDefaultCertVerifier = new SharedCertVerifier(
+      certVerifierImplementation,
       aiaDownloadEnabled ?
         CertVerifier::missing_cert_download_on : CertVerifier::missing_cert_download_off,
       crlDownloading ?
         CertVerifier::crl_download_allowed : CertVerifier::crl_local_only,
       ocspEnabled ?
         CertVerifier::ocsp_on : CertVerifier::ocsp_off,
       ocspRequired ?
         CertVerifier::ocsp_strict : CertVerifier::ocsp_relaxed,
@@ -1183,20 +1188,16 @@ nsNSSComponent::InitializeNSS()
       rv = profilePath->GetNativePath(profileStr);
   #endif
       if (NS_FAILED(rv)) {
         nsPSMInitPanic::SetPanic();
         return rv;
       }
     }
 
-#ifndef NSS_NO_LIBPKIX
-    globalConstFlagUsePKIXVerification =
-      Preferences::GetBool("security.use_libpkix_verification", false);
-#endif
 
     // init phase 2, init calls to NSS library
 
     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS Initialization beginning\n"));
 
     // The call to ConfigureInternalPKCS11Token needs to be done before NSS is initialized,
     // but affects only static data.
     // If we could assume i18n will not change between profiles, one call per application
@@ -1892,27 +1893,45 @@ nsNSSComponent::DoProfileChangeNetRestor
 NS_IMETHODIMP
 nsNSSComponent::IsNSSInitialized(bool* initialized)
 {
   MutexAutoLock lock(mutex);
   *initialized = mNSSInitialized;
   return NS_OK;
 }
 
+SharedCertVerifier::~SharedCertVerifier() { }
+
 //#ifndef NSS_NO_LIBPKIX
-NS_IMETHODIMP
-nsNSSComponent::GetDefaultCertVerifier(RefPtr<CertVerifier>& out)
+TemporaryRef<SharedCertVerifier>
+nsNSSComponent::GetDefaultCertVerifier()
 {
   MutexAutoLock lock(mutex);
-  if (!mNSSInitialized)
-      return NS_ERROR_NOT_INITIALIZED;
-  out = mDefaultCertVerifier;
-  return NS_OK;
+  MOZ_ASSERT(mNSSInitialized);
+  return mDefaultCertVerifier;
 }
 
+namespace mozilla { namespace psm {
+
+TemporaryRef<SharedCertVerifier>
+GetDefaultCertVerifier()
+{
+  static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
+
+  nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID));
+  RefPtr<SharedCertVerifier> certVerifier;
+  if (nssComponent) {
+    return nssComponent->GetDefaultCertVerifier();
+  }
+
+  return nullptr;
+}
+
+} } // namespace mozilla::psm
+
 NS_IMPL_ISUPPORTS1(PipUIContext, nsIInterfaceRequestor)
 
 PipUIContext::PipUIContext()
 {
 }
 
 PipUIContext::~PipUIContext()
 {
--- a/security/manager/ssl/src/nsNSSComponent.h
+++ b/security/manager/ssl/src/nsNSSComponent.h
@@ -15,27 +15,30 @@
 #include "nsIStringBundle.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
 #ifndef MOZ_DISABLE_CRYPTOLEGACY
 #endif
 #include "nsINSSErrorsService.h"
 #include "nsNSSCallbacks.h"
 #include "ScopedNSSTypes.h"
+#include "SharedCertVerifier.h"
 #include "nsNSSHelper.h"
 #include "nsClientAuthRemember.h"
 #include "prerror.h"
 
 class nsIDOMWindow;
 class nsIPrompt;
 class SmartCardThreadList;
 
 namespace mozilla { namespace psm {
 
-class CertVerifier;
+MOZ_WARN_UNUSED_RESULT
+  ::mozilla::TemporaryRef<mozilla::psm::SharedCertVerifier>
+  GetDefaultCertVerifier();
 
 } } // namespace mozilla::psm
 
 
 #define NS_NSSCOMPONENT_CID \
 {0xa277189c, 0x1dd1, 0x11b2, {0xa8, 0xc9, 0xe4, 0xe8, 0xbf, 0xb1, 0x33, 0x8e}}
 
 #define PSM_COMPONENT_CONTRACTID "@mozilla.org/psm;1"
@@ -105,18 +108,18 @@ class NS_NO_VTABLE nsINSSComponent : pub
 #endif
 
 #ifndef NSS_NO_LIBPKIX
   NS_IMETHOD EnsureIdentityInfoLoaded() = 0;
 #endif
 
   NS_IMETHOD IsNSSInitialized(bool* initialized) = 0;
 
-  NS_IMETHOD GetDefaultCertVerifier(
-                  mozilla::RefPtr<mozilla::psm::CertVerifier>& out) = 0;
+  virtual ::mozilla::TemporaryRef<mozilla::psm::SharedCertVerifier>
+    GetDefaultCertVerifier() = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsINSSComponent, NS_INSSCOMPONENT_IID)
 
 class nsNSSShutDownList;
 class nsCertVerificationThread;
 
 // Implementation of the PSM component interface.
@@ -172,20 +175,20 @@ public:
                                  const nsAString& token);
 #endif
 
 #ifndef NSS_NO_LIBPKIX
   NS_IMETHOD EnsureIdentityInfoLoaded();
 #endif
   NS_IMETHOD IsNSSInitialized(bool* initialized);
 
-  NS_IMETHOD GetDefaultCertVerifier(
-                  mozilla::RefPtr<mozilla::psm::CertVerifier>& out);
+  ::mozilla::TemporaryRef<mozilla::psm::SharedCertVerifier>
+    GetDefaultCertVerifier() MOZ_OVERRIDE;
+
 private:
-
   nsresult InitializeNSS();
   void ShutdownNSS();
 
   void InstallLoadableRoots();
   void UnloadLoadableRoots();
   void CleanupIdentityInfo();
   void setValidationOptions(bool isInitialSetting);
   nsresult setEnabledTLSVersions();
@@ -214,24 +217,21 @@ private:
 #endif
   bool mIsNetworkDown;
 
   void deleteBackgroundThreads();
   void createBackgroundThreads();
   nsCertVerificationThread* mCertVerificationThread;
 
   nsNSSHttpInterface mHttpForNSS;
-  mozilla::RefPtr<mozilla::psm::CertVerifier> mDefaultCertVerifier;
+  mozilla::RefPtr<mozilla::psm::SharedCertVerifier> mDefaultCertVerifier;
 
 
   static PRStatus IdentityInfoInit(void);
   PRCallOnceType mIdentityInfoCallOnce;
-
-public:
-  static bool globalConstFlagUsePKIXVerification;
 };
 
 class nsNSSErrors
 {
 public:
   static const char* getDefaultErrorStringName(PRErrorCode err);
   static const char* getOverrideErrorStringName(PRErrorCode aErrorCode);
   static nsresult getErrorMessageFromCode(PRErrorCode err,
--- a/security/manager/ssl/src/nsUsageArrayHelper.cpp
+++ b/security/manager/ssl/src/nsUsageArrayHelper.cpp
@@ -194,39 +194,36 @@ nsUsageArrayHelper::GetUsagesArray(const
   if (NS_FAILED(m_rv))
     return m_rv;
 
   NS_ENSURE_TRUE(nssComponent, NS_ERROR_NOT_AVAILABLE);
 
   if (outArraySize < max_returned_out_array_size)
     return NS_ERROR_FAILURE;
 
+  RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
+  NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
+
   // Bug 860076, this disabling ocsp for all NSS is incorrect.
-#ifndef NSS_NO_LIBPKIX
-  const bool localOSCPDisable = !nsNSSComponent::globalConstFlagUsePKIXVerification && localOnly;
-#else
-  const bool localOSCPDisable = localOnly;
-#endif 
+  const bool localOSCPDisable
+    = certVerifier->mImplementation == CertVerifier::classic;
   if (localOSCPDisable) {
     nsresult rv;
     nssComponent = do_GetService(kNSSComponentCID, &rv);
     if (NS_FAILED(rv))
       return rv;
     
     if (nssComponent) {
       nssComponent->SkipOcsp();
     }
   }
 
   uint32_t &count = *_count;
   count = 0;
 
-  RefPtr<CertVerifier> certVerifier(GetDefaultCertVerifier());
-  NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
-
   PRTime now = PR_Now();
   CertVerifier::Flags flags = localOnly ? CertVerifier::FLAG_LOCAL_ONLY : 0;
 
   // The following list of checks must be < max_returned_out_array_size
 
   uint32_t result;
   result = check(nsIX509Cert::VERIFIED_OK, suffix, certVerifier,
                  certificateUsageSSLClient, now, flags, count, outUsages);