Bug 891066, part 2: Move CertVerifier to security/certverifier, r=keeler
authorBrian Smith <brian@briansmith.org>
Sun, 26 Jan 2014 19:36:28 -0800
changeset 181296 2dc56ee0e0e51a35ac0573b57451ad79361e6d0d
parent 181295 99cf3634be5dadf488320b12e5c884e6d9363870
child 181297 95f848f55c90176dd061a54c6d8d9855dbfed258
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
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 2: Move CertVerifier to security/certverifier, r=keeler
build/dumbmake-dependencies
security/certverifier/CertVerifier.cpp
security/certverifier/CertVerifier.h
security/certverifier/ExtendedValidation.cpp
security/certverifier/ExtendedValidation.h
security/certverifier/moz.build
security/manager/ssl/src/CertVerifier.cpp
security/manager/ssl/src/CertVerifier.h
security/manager/ssl/src/SSLServerCertVerification.cpp
security/manager/ssl/src/moz.build
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/nsSSLStatus.cpp
toolkit/toolkit.mozbuild
--- a/build/dumbmake-dependencies
+++ b/build/dumbmake-dependencies
@@ -13,20 +13,19 @@ toolkit/library
   docshell/build
     docshell
     uriloader
   modules
   widget
   gfx
   toolkit/components/build
     toolkit/components
-  security/build
   security/manager
-  security/dbm
-  security/nss
+    security/certverifier
+      security/build
   accessible
   dom
   content
   layout
   editor
   parser
   js/src
     mfbt
new file mode 100644
--- /dev/null
+++ b/security/certverifier/CertVerifier.cpp
@@ -0,0 +1,439 @@
+/* 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 "ExtendedValidation.h"
+#include "ScopedNSSTypes.h"
+#include "cert.h"
+#include "secerr.h"
+#include "prerror.h"
+
+#ifdef PR_LOGGING
+extern PRLogModuleInfo* gPIPNSSLog;
+#endif
+
+namespace mozilla { namespace psm {
+
+const CertVerifier::Flags CertVerifier::FLAG_LOCAL_ONLY = 1;
+const CertVerifier::Flags CertVerifier::FLAG_NO_DV_FALLBACK_FOR_EV = 2;
+
+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)
+  : 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)
+{
+}
+
+CertVerifier::~CertVerifier()
+{
+}
+
+static SECStatus
+ClassicVerifyCert(CERTCertificate* cert,
+                  const SECCertificateUsage usage,
+                  const PRTime time,
+                  void* pinArg,
+                  /*optional out*/ CERTCertList** validationChain,
+                  /*optional out*/ CERTVerifyLog* verifyLog)
+{
+  SECStatus rv;
+  SECCertUsage enumUsage;
+  if (validationChain) {
+    switch(usage){
+      case  certificateUsageSSLClient:
+        enumUsage = certUsageSSLClient;
+        break;
+      case  certificateUsageSSLServer:
+        enumUsage = certUsageSSLServer;
+        break;
+      case certificateUsageSSLServerWithStepUp:
+        enumUsage = certUsageSSLServerWithStepUp;
+        break;
+      case certificateUsageSSLCA:
+        enumUsage = certUsageSSLCA;
+        break;
+      case certificateUsageEmailSigner:
+        enumUsage = certUsageEmailSigner;
+        break;
+      case certificateUsageEmailRecipient:
+        enumUsage = certUsageEmailRecipient;
+        break;
+      case certificateUsageObjectSigner:
+        enumUsage = certUsageObjectSigner;
+        break;
+      case certificateUsageUserCertImport:
+        enumUsage = certUsageUserCertImport;
+        break;
+      case certificateUsageVerifyCA:
+        enumUsage = certUsageVerifyCA;
+        break;
+      case certificateUsageProtectedObjectSigner:
+        enumUsage = certUsageProtectedObjectSigner;
+        break;
+      case certificateUsageStatusResponder:
+        enumUsage = certUsageStatusResponder;
+        break;
+      case certificateUsageAnyCA:
+        enumUsage = certUsageAnyCA;
+        break;
+       default:
+        return SECFailure;
+    }
+  }
+  if (usage == certificateUsageSSLServer) {
+    // SSL server cert verification has always used CERT_VerifyCert, so we
+    // continue to use it for SSL cert verification to minimize the risk of
+    // there being any differnce in results between CERT_VerifyCert and
+    // CERT_VerifyCertificate.
+    rv = CERT_VerifyCert(CERT_GetDefaultCertDB(), cert, true,
+                         certUsageSSLServer, time, pinArg, verifyLog);
+  } else {
+    rv = CERT_VerifyCertificate(CERT_GetDefaultCertDB(), cert, true,
+                                usage, time, pinArg, verifyLog, nullptr);
+  }
+  if (rv == SECSuccess && validationChain) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("VerifyCert: getting chain in 'classic' \n"));
+    *validationChain = CERT_GetCertChainFromCert(cert, time, enumUsage);
+    if (!*validationChain) {
+      rv = SECFailure;
+    }
+  }
+  return rv;
+}
+
+SECStatus
+CertVerifier::VerifyCert(CERTCertificate* cert,
+                         const SECCertificateUsage usage,
+                         const PRTime time,
+                         void* pinArg,
+                         const Flags flags,
+                         /*optional out*/ CERTCertList** validationChain,
+                         /*optional out*/ SECOidTag* evOidPolicy,
+                         /*optional out*/ CERTVerifyLog* verifyLog)
+{
+  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;
+  }
+
+  switch(usage){
+    case certificateUsageSSLClient:
+    case certificateUsageSSLServer:
+    case certificateUsageSSLCA:
+    case certificateUsageEmailSigner:
+    case certificateUsageEmailRecipient:
+    case certificateUsageObjectSigner:
+    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;
+
+  // 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) {
+        return SECFailure;
+      }
+      // pkix ignores an empty trustanchors list and
+      // decides then to use the whole set of trust in the DB
+      // so we set the evPolicy to unkown in this case
+      if (CERT_LIST_EMPTY(trustAnchors)) {
+        evPolicy = SEC_OID_UNKNOWN;
+      }
+    } else {
+      // Do not setup EV verification params
+      evPolicy = SEC_OID_UNKNOWN;
+    }
+  }
+
+  MOZ_ASSERT_IF(evPolicy != SEC_OID_UNKNOWN, trustAnchors);
+
+  size_t i = 0;
+  size_t validationChainLocation = 0;
+  size_t validationTrustAnchorLocation = 0;
+  CERTValOutParam cvout[4];
+  if (verifyLog) {
+     cvout[i].type = cert_po_errorLog;
+     cvout[i].value.pointer.log = verifyLog;
+     ++i;
+  }
+  if (validationChain) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("VerifyCert: setting up validation chain outparam.\n"));
+    validationChainLocation = i;
+    cvout[i].type = cert_po_certList;
+    cvout[i].value.pointer.cert = nullptr;
+    ++i;
+    validationTrustAnchorLocation = i;
+    cvout[i].type = cert_po_trustAnchor;
+    cvout[i].value.pointer.chain = nullptr;
+    ++i;
+  }
+  cvout[i].type = cert_po_end;
+
+  CERTRevocationFlags rev;
+
+  CERTRevocationMethodIndex revPreferredMethods[2];
+  rev.leafTests.preferred_methods =
+  rev.chainTests.preferred_methods = revPreferredMethods;
+
+  uint64_t revFlagsPerMethod[2];
+  rev.leafTests.cert_rev_flags_per_method =
+  rev.chainTests.cert_rev_flags_per_method = revFlagsPerMethod;
+  rev.leafTests.number_of_preferred_methods =
+  rev.chainTests.number_of_preferred_methods = 1;
+
+  rev.leafTests.number_of_defined_methods =
+  rev.chainTests.number_of_defined_methods = cert_revocation_method_ocsp + 1;
+
+  const bool localOnly = flags & FLAG_LOCAL_ONLY;
+  CERTValInParam cvin[6];
+
+  // Parameters for both EV and DV validation
+  cvin[0].type = cert_pi_useAIACertFetch;
+  cvin[0].value.scalar.b = mMissingCertDownloadEnabled && !localOnly;
+  cvin[1].type = cert_pi_revocationFlags;
+  cvin[1].value.pointer.revocation = &rev;
+  cvin[2].type = cert_pi_date;
+  cvin[2].value.scalar.time = time;
+  i = 3;
+  const size_t evParamLocation = i;
+
+  if (evPolicy != SEC_OID_UNKNOWN) {
+    // EV setup!
+    // XXX 859872 The current flags are not quite correct. (use
+    // of ocsp flags for crl preferences).
+    uint64_t ocspRevMethodFlags =
+      CERT_REV_M_TEST_USING_THIS_METHOD
+      | ((mOCSPDownloadEnabled && !localOnly) ?
+          CERT_REV_M_ALLOW_NETWORK_FETCHING : CERT_REV_M_FORBID_NETWORK_FETCHING)
+      | CERT_REV_M_ALLOW_IMPLICIT_DEFAULT_SOURCE
+      | CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE
+      | CERT_REV_M_IGNORE_MISSING_FRESH_INFO
+      | CERT_REV_M_STOP_TESTING_ON_FRESH_INFO
+      | (mOCSPGETEnabled ? 0 : CERT_REV_M_FORCE_POST_METHOD_FOR_OCSP);
+
+    rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_crl] =
+    rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_crl]
+      = CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD;
+
+    rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] =
+    rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_ocsp]
+      = ocspRevMethodFlags;
+
+    rev.leafTests.cert_rev_method_independent_flags =
+    rev.chainTests.cert_rev_method_independent_flags =
+      // avoiding the network is good, let's try local first
+      CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST
+      // is overall revocation requirement strict or relaxed?
+      |  CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE
+      ;
+
+    rev.leafTests.preferred_methods[0] =
+    rev.chainTests.preferred_methods[0] = cert_revocation_method_ocsp;
+
+    cvin[i].type = cert_pi_policyOID;
+    cvin[i].value.arraySize = 1;
+    cvin[i].value.array.oids = &evPolicy;
+    ++i;
+    MOZ_ASSERT(trustAnchors);
+    cvin[i].type = cert_pi_trustAnchors;
+    cvin[i].value.pointer.chain = trustAnchors;
+    ++i;
+
+    cvin[i].type = cert_pi_end;
+
+    rv = CERT_PKIXVerifyCert(cert, usage, cvin, cvout, pinArg);
+    if (rv == SECSuccess) {
+      if (evOidPolicy) {
+        *evOidPolicy = evPolicy;
+      }
+      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
+             ("VerifyCert: successful CERT_PKIXVerifyCert(ev) \n"));
+      goto pkix_done;
+    }
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
+           ("VerifyCert: failed CERT_PKIXVerifyCert(ev)\n"));
+
+    if (validationChain && *validationChain) {
+      // There SHOULD not be a validation chain on failure, asserion here for
+      // the debug builds AND a fallback for production builds
+      MOZ_ASSERT(false,
+                 "certPKIXVerifyCert returned failure AND a validationChain");
+      CERT_DestroyCertList(*validationChain);
+      *validationChain = nullptr;
+    }
+
+    if (verifyLog) {
+      // Cleanup the log so that it is ready the the next validation
+      CERTVerifyLogNode* i_node;
+      for (i_node = verifyLog->head; i_node; i_node = i_node->next) {
+         //destroy cert if any.
+         if (i_node->cert) {
+           CERT_DestroyCertificate(i_node->cert);
+         }
+         // 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 (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
+
+    // no fresh CRL? well, let other flag decide whether to fail or not
+    | CERT_REV_M_IGNORE_MISSING_FRESH_INFO
+
+    // testing using local CRLs is always allowed
+    | CERT_REV_M_TEST_USING_THIS_METHOD
+
+    // no local crl and don't know where to get it from? ignore
+    | CERT_REV_M_SKIP_TEST_ON_MISSING_SOURCE
+
+    // crl download based on parameter
+    | ((mCRLDownloadEnabled && !localOnly) ?
+        CERT_REV_M_ALLOW_NETWORK_FETCHING : CERT_REV_M_FORBID_NETWORK_FETCHING)
+    ;
+
+  rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] =
+  rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] =
+    // use OCSP
+      CERT_REV_M_TEST_USING_THIS_METHOD
+
+    // if app has a default OCSP responder configured, let's use it
+    | CERT_REV_M_ALLOW_IMPLICIT_DEFAULT_SOURCE
+
+    // of course OCSP doesn't work without a source. let's accept such certs
+    | CERT_REV_M_SKIP_TEST_ON_MISSING_SOURCE
+
+    // if ocsp is required stop on lack of freshness
+    | (mOCSPStrict ?
+       CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO : CERT_REV_M_IGNORE_MISSING_FRESH_INFO)
+
+    // ocsp success is sufficient
+    | CERT_REV_M_STOP_TESTING_ON_FRESH_INFO
+
+    // ocsp enabled controls network fetching, too
+    | ((mOCSPDownloadEnabled && !localOnly) ?
+        CERT_REV_M_ALLOW_NETWORK_FETCHING : CERT_REV_M_FORBID_NETWORK_FETCHING)
+
+    | (mOCSPGETEnabled ? 0 : CERT_REV_M_FORCE_POST_METHOD_FOR_OCSP);
+    ;
+
+  rev.leafTests.preferred_methods[0] =
+  rev.chainTests.preferred_methods[0] = cert_revocation_method_ocsp;
+
+  rev.leafTests.cert_rev_method_independent_flags =
+  rev.chainTests.cert_rev_method_independent_flags =
+    // avoiding the network is good, let's try local first
+    CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST;
+
+  // Skip EV parameters
+  cvin[evParamLocation].type = cert_pi_end;
+
+  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("VerifyCert: calling CERT_PKIXVerifyCert(dv) \n"));
+  rv = CERT_PKIXVerifyCert(cert, usage, cvin, cvout, pinArg);
+
+pkix_done:
+  if (validationChain) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("VerifyCert: validation chain requested\n"));
+    ScopedCERTCertificate trustAnchor(cvout[validationTrustAnchorLocation].value.pointer.cert);
+
+    if (rv == SECSuccess) {
+      if (! cvout[validationChainLocation].value.pointer.chain) {
+        PR_SetError(PR_UNKNOWN_ERROR, 0);
+        return SECFailure;
+      }
+      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("VerifyCert: I have a chain\n"));
+      *validationChain = cvout[validationChainLocation].value.pointer.chain;
+      if (trustAnchor) {
+        // we should only add the issuer to the chain if it is not already
+        // present. On CA cert checking, the issuer is the same cert, so in
+        // that case we do not add the cert to the chain.
+        if (!CERT_CompareCerts(trustAnchor, cert)) {
+          PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("VerifyCert:  adding issuer to tail for display\n"));
+          // note: rv is reused to catch errors on cert creation!
+          ScopedCERTCertificate tempCert(CERT_DupCertificate(trustAnchor));
+          rv = CERT_AddCertToListTail(*validationChain, tempCert);
+          if (rv == SECSuccess) {
+            tempCert.forget(); // ownership traferred to validationChain
+          } else {
+            CERT_DestroyCertList(*validationChain);
+            *validationChain = nullptr;
+          }
+        }
+      }
+    } else {
+      // Validation was a fail, clean up if needed
+      if (cvout[validationChainLocation].value.pointer.chain) {
+        CERT_DestroyCertList(cvout[validationChainLocation].value.pointer.chain);
+      }
+    }
+  }
+
+  return rv;
+#endif
+}
+
+} } // namespace mozilla::psm
new file mode 100644
--- /dev/null
+++ b/security/certverifier/CertVerifier.h
@@ -0,0 +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 "certt.h"
+#include "insanity/ScopedPtr.h"
+
+namespace mozilla { namespace psm {
+
+class CertVerifier
+{
+public:
+  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,
+                       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; }
+
+  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;
+};
+
+} } // namespace mozilla::psm
+
+#endif // mozilla_psm__CertVerifier_h
new file mode 100644
--- /dev/null
+++ b/security/certverifier/ExtendedValidation.cpp
@@ -0,0 +1,1017 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * 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 "ExtendedValidation.h"
+
+#include "cert.h"
+#include "certdb.h"
+#include "base64.h"
+#include "pk11pub.h"
+#include "secerr.h"
+#include "prerror.h"
+#include "prinit.h"
+
+#ifdef PR_LOGGING
+extern PRLogModuleInfo* gPIPNSSLog;
+#endif
+
+#define CONST_OID static const unsigned char
+#define OI(x) { siDEROID, (unsigned char*) x, sizeof x }
+
+struct nsMyTrustedEVInfo
+{
+  const char* dotted_oid;
+  const char* oid_name; // Set this to null to signal an invalid structure,
+                  // (We can't have an empty list, so we'll use a dummy entry)
+  SECOidTag oid_tag;
+  const unsigned char ev_root_sha1_fingerprint[20];
+  const char* issuer_base64;
+  const char* serial_base64;
+  CERTCertificate* cert;
+};
+
+// HOWTO enable additional CA root certificates for EV:
+//
+// For each combination of "root certificate" and "policy OID",
+// one entry must be added to the array named myTrustedEVInfos.
+//
+// We use the combination of "issuer name" and "serial number" to
+// uniquely identify the certificate. In order to avoid problems
+// because of encodings when comparing certificates, we don't
+// use plain text representation, we rather use the original encoding
+// as it can be found in the root certificate (in base64 format).
+//
+// We can use the NSS utility named "pp" to extract the encoding.
+//
+// Build standalone NSS including the NSS tools, then run
+//   pp -t certificate-identity -i the-cert-filename
+//
+// You will need the output from sections "Issuer", "Fingerprint (SHA1)",
+// "Issuer DER Base64" and "Serial DER Base64".
+//
+// The new section consists of 8 lines:
+//
+// - a comment that should contain the human readable issuer name
+//   of the certificate, as printed by the pp tool
+// - the EV policy OID that is associated to the EV grant
+// - a text description of the EV policy OID. The array can contain
+//   multiple entries with the same OID.
+//   Please make sure to use the identical OID text description for
+//   all entries with the same policy OID (use the text search
+//   feature of your text editor to find duplicates).
+//   When adding a new policy OID that is not yet contained in the array,
+//   please make sure that your new description is different from
+//   all the other descriptions (again use the text search feature
+//   to be sure).
+// - the constant SEC_OID_UNKNOWN
+//   (it will be replaced at runtime with another identifier)
+// - the SHA1 fingerprint
+// - the "Issuer DER Base64" as printed by the pp tool.
+//   Remove all whitespaces. If you use multiple lines, make sure that
+//   only the final line will be followed by a comma.
+// - the "Serial DER Base64" (as printed by pp)
+// - nullptr
+//
+// After adding an entry, test it locally against the test site that
+// has been provided by the CA. Note that you must use a version of NSS
+// where the root certificate has already been added and marked as trusted
+// for issueing SSL server certificates (at least).
+//
+// If you are able to connect to the site without certificate errors,
+// but you don't see the EV status indicator, then most likely the CA
+// has a problem in their infrastructure. The most common problems are
+// related to the CA's OCSP infrastructure, either they use an incorrect
+// OCSP signing certificate, or OCSP for the intermediate certificates
+// isn't working, or OCSP isn't working at all.
+
+static struct nsMyTrustedEVInfo myTrustedEVInfos[] = {
+  // IMPORTANT! When extending this list,
+  // pairs of dotted_oid and oid_name should always be unique pairs.
+  // In other words, if you add another list, that uses the same dotted_oid
+  // as an existing entry, then please use the same oid_name.
+#ifdef DEBUG
+  // Debug EV certificates should all use the OID (repeating EV OID is OK):
+  // 1.3.6.1.4.1.13769.666.666.666.1.500.9.1.
+  // If you add or remove debug EV certs you must also modify IdentityInfoInit
+  // (there is another #ifdef DEBUG section there) so that the correct number of
+  // certs are skipped as these debug EV certs are NOT part of the default trust
+  // store.
+  {
+    // This is the testing EV signature (xpcshell) (RSA)
+    // CN=XPCShell EV Testing (untrustworthy) CA,OU=Security Engineering,O=Mozilla - EV debug test CA,L=Mountain View,ST=CA,C=US"
+    "1.3.6.1.4.1.13769.666.666.666.1.500.9.1",
+    "DEBUGtesting EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x9C, 0x62, 0xEF, 0xDB, 0xAE, 0xF9, 0xEB, 0x36, 0x58, 0xFB,
+      0x3B, 0xD3, 0x47, 0x64, 0x93, 0x9D, 0x86, 0x29, 0x6A, 0xE0 },
+    "MIGnMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWlu"
+    "IFZpZXcxIzAhBgNVBAoMGk1vemlsbGEgLSBFViBkZWJ1ZyB0ZXN0IENBMR0wGwYD"
+    "VQQLDBRTZWN1cml0eSBFbmdpbmVlcmluZzEvMC0GA1UEAwwmWFBDU2hlbGwgRVYg"
+    "VGVzdGluZyAodW50cnVzdHdvcnRoeSkgQ0E=",
+    "At+3zdo=",
+    nullptr
+  },
+#endif
+  {
+    // OU=Security Communication EV RootCA1,O="SECOM Trust Systems CO.,LTD.",C=JP
+    "1.2.392.200091.100.721.1",
+    "SECOM EV OID",
+    SEC_OID_UNKNOWN,
+    { 0xFE, 0xB8, 0xC4, 0x32, 0xDC, 0xF9, 0x76, 0x9A, 0xCE, 0xAE,
+      0x3D, 0xD8, 0x90, 0x8F, 0xFD, 0x28, 0x86, 0x65, 0x64, 0x7D },
+    "MGAxCzAJBgNVBAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENP"
+    "LixMVEQuMSowKAYDVQQLEyFTZWN1cml0eSBDb21tdW5pY2F0aW9uIEVWIFJvb3RD"
+    "QTE=",
+    "AA==",
+    nullptr
+  },
+  {
+    // CN=Cybertrust Global Root,O=Cybertrust, Inc
+    "1.3.6.1.4.1.6334.1.100.1",
+    "Cybertrust EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x5F, 0x43, 0xE5, 0xB1, 0xBF, 0xF8, 0x78, 0x8C, 0xAC, 0x1C,
+      0xC7, 0xCA, 0x4A, 0x9A, 0xC6, 0x22, 0x2B, 0xCC, 0x34, 0xC6 },
+    "MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVz"
+    "dCBHbG9iYWwgUm9vdA==",
+    "BAAAAAABD4WqLUg=",
+    nullptr
+  },
+  {
+    // CN=SwissSign Gold CA - G2,O=SwissSign AG,C=CH
+    "2.16.756.1.89.1.2.1.1",
+    "SwissSign EV OID",
+    SEC_OID_UNKNOWN,
+    { 0xD8, 0xC5, 0x38, 0x8A, 0xB7, 0x30, 0x1B, 0x1B, 0x6E, 0xD4,
+      0x7A, 0xE6, 0x45, 0x25, 0x3A, 0x6F, 0x9F, 0x1A, 0x27, 0x61 },
+    "MEUxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMT"
+    "FlN3aXNzU2lnbiBHb2xkIENBIC0gRzI=",
+    "ALtAHEP1Xk+w",
+    nullptr
+  },
+  {
+    // CN=StartCom Certification Authority,OU=Secure Digital Certificate Signing,O=StartCom Ltd.,C=IL
+    "1.3.6.1.4.1.23223.1.1.1",
+    "StartCom EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x3E, 0x2B, 0xF7, 0xF2, 0x03, 0x1B, 0x96, 0xF3, 0x8C, 0xE6,
+      0xC4, 0xD8, 0xA8, 0x5D, 0x3E, 0x2D, 0x58, 0x47, 0x6A, 0x0F },
+    "MH0xCzAJBgNVBAYTAklMMRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSswKQYDVQQL"
+    "EyJTZWN1cmUgRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTaWduaW5nMSkwJwYDVQQDEyBT"
+    "dGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==",
+    "AQ==",
+    nullptr
+  },
+  {
+    // CN=StartCom Certification Authority,OU=Secure Digital Certificate Signing,O=StartCom Ltd.,C=IL
+    "1.3.6.1.4.1.23223.1.1.1",
+    "StartCom EV OID",
+    SEC_OID_UNKNOWN,
+    { 0xA3, 0xF1, 0x33, 0x3F, 0xE2, 0x42, 0xBF, 0xCF, 0xC5, 0xD1,
+      0x4E, 0x8F, 0x39, 0x42, 0x98, 0x40, 0x68, 0x10, 0xD1, 0xA0 },
+    "MH0xCzAJBgNVBAYTAklMMRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSswKQYDVQQL"
+    "EyJTZWN1cmUgRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTaWduaW5nMSkwJwYDVQQDEyBT"
+    "dGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==",
+    "LQ==",
+    nullptr
+  },
+  {
+    // CN=StartCom Certification Authority G2,O=StartCom Ltd.,C=IL
+    "1.3.6.1.4.1.23223.1.1.1",
+    "StartCom EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x31, 0xF1, 0xFD, 0x68, 0x22, 0x63, 0x20, 0xEE, 0xC6, 0x3B,
+      0x3F, 0x9D, 0xEA, 0x4A, 0x3E, 0x53, 0x7C, 0x7C, 0x39, 0x17 },
+    "MFMxCzAJBgNVBAYTAklMMRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSwwKgYDVQQD"
+    "EyNTdGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBHMg==",
+    "Ow==",
+    nullptr
+  },
+  {
+    // CN=VeriSign Class 3 Public Primary Certification Authority - G5,OU="(c) 2006 VeriSign, Inc. - For authorized use only",OU=VeriSign Trust Network,O="VeriSign, Inc.",C=US
+    "2.16.840.1.113733.1.7.23.6",
+    "VeriSign EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x4E, 0xB6, 0xD5, 0x78, 0x49, 0x9B, 0x1C, 0xCF, 0x5F, 0x58,
+      0x1E, 0xAD, 0x56, 0xBE, 0x3D, 0x9B, 0x67, 0x44, 0xA5, 0xE5 },
+    "MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNV"
+    "BAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA2IFZl"
+    "cmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMT"
+    "PFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBB"
+    "dXRob3JpdHkgLSBHNQ==",
+    "GNrRniZ96LtKIVjNzGs7Sg==",
+    nullptr
+  },
+  {
+    // CN=GeoTrust Primary Certification Authority,O=GeoTrust Inc.,C=US
+    "1.3.6.1.4.1.14370.1.6",
+    "GeoTrust EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x32, 0x3C, 0x11, 0x8E, 0x1B, 0xF7, 0xB8, 0xB6, 0x52, 0x54,
+      0xE2, 0xE2, 0x10, 0x0D, 0xD6, 0x02, 0x90, 0x37, 0xF0, 0x96 },
+    "MFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQD"
+    "EyhHZW9UcnVzdCBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5",
+    "GKy1av1pthU6Y2yv2vrEoQ==",
+    nullptr
+  },
+  {
+    // CN=thawte Primary Root CA,OU="(c) 2006 thawte, Inc. - For authorized use only",OU=Certification Services Division,O="thawte, Inc.",C=US
+    "2.16.840.1.113733.1.7.48.1",
+    "Thawte EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x91, 0xC6, 0xD6, 0xEE, 0x3E, 0x8A, 0xC8, 0x63, 0x84, 0xE5,
+      0x48, 0xC2, 0x99, 0x29, 0x5C, 0x75, 0x6C, 0x81, 0x7B, 0x81 },
+    "MIGpMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3RlLCBJbmMuMSgwJgYDVQQL"
+    "Ex9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYDVQQLEy8oYykg"
+    "MjAwNiB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0G"
+    "A1UEAxMWdGhhd3RlIFByaW1hcnkgUm9vdCBDQQ==",
+    "NE7VVyDV7exJ9C/ON9srbQ==",
+    nullptr
+  },
+  {
+    // CN=XRamp Global Certification Authority,O=XRamp Security Services Inc,OU=www.xrampsecurity.com,C=US
+    "2.16.840.1.114404.1.1.2.4.1",
+    "Trustwave EV OID",
+    SEC_OID_UNKNOWN,
+    { 0xB8, 0x01, 0x86, 0xD1, 0xEB, 0x9C, 0x86, 0xA5, 0x41, 0x04,
+      0xCF, 0x30, 0x54, 0xF3, 0x4C, 0x52, 0xB7, 0xE5, 0x58, 0xC6 },
+    "MIGCMQswCQYDVQQGEwJVUzEeMBwGA1UECxMVd3d3LnhyYW1wc2VjdXJpdHkuY29t"
+    "MSQwIgYDVQQKExtYUmFtcCBTZWN1cml0eSBTZXJ2aWNlcyBJbmMxLTArBgNVBAMT"
+    "JFhSYW1wIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==",
+    "UJRs7Bjq1ZxN1ZfvdY+grQ==",
+    nullptr
+  },
+  {
+    // CN=SecureTrust CA,O=SecureTrust Corporation,C=US
+    "2.16.840.1.114404.1.1.2.4.1",
+    "Trustwave EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x87, 0x82, 0xC6, 0xC3, 0x04, 0x35, 0x3B, 0xCF, 0xD2, 0x96,
+      0x92, 0xD2, 0x59, 0x3E, 0x7D, 0x44, 0xD9, 0x34, 0xFF, 0x11 },
+    "MEgxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlv"
+    "bjEXMBUGA1UEAxMOU2VjdXJlVHJ1c3QgQ0E=",
+    "DPCOXAgWpa1Cf/DrJxhZ0A==",
+    nullptr
+  },
+  {
+    // CN=Secure Global CA,O=SecureTrust Corporation,C=US
+    "2.16.840.1.114404.1.1.2.4.1",
+    "Trustwave EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x3A, 0x44, 0x73, 0x5A, 0xE5, 0x81, 0x90, 0x1F, 0x24, 0x86,
+      0x61, 0x46, 0x1E, 0x3B, 0x9C, 0xC4, 0x5F, 0xF5, 0x3A, 0x1B },
+    "MEoxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlv"
+    "bjEZMBcGA1UEAxMQU2VjdXJlIEdsb2JhbCBDQQ==",
+    "B1YipOjUiolN9BPI8PjqpQ==",
+    nullptr
+  },
+  {
+    // CN=COMODO ECC Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB
+    "1.3.6.1.4.1.6449.1.2.1.5.1",
+    "Comodo EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x9F, 0x74, 0x4E, 0x9F, 0x2B, 0x4D, 0xBA, 0xEC, 0x0F, 0x31,
+      0x2C, 0x50, 0xB6, 0x56, 0x3B, 0x8E, 0x2D, 0x93, 0xC3, 0x11 },
+    "MIGFMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAw"
+    "DgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDErMCkG"
+    "A1UEAxMiQ09NT0RPIEVDQyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==",
+    "H0evqmIAcFBUTAGem2OZKg==",
+    nullptr
+  },
+  {
+    // CN=COMODO Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB
+    "1.3.6.1.4.1.6449.1.2.1.5.1",
+    "Comodo EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x66, 0x31, 0xBF, 0x9E, 0xF7, 0x4F, 0x9E, 0xB6, 0xC9, 0xD5,
+      0xA6, 0x0C, 0xBA, 0x6A, 0xBE, 0xD1, 0xF7, 0xBD, 0xEF, 0x7B },
+    "MIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAw"
+    "DgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEnMCUG"
+    "A1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5",
+    "ToEtioJl4AsC7j41AkblPQ==",
+    nullptr
+  },
+  {
+    // CN=AddTrust External CA Root,OU=AddTrust External TTP Network,O=AddTrust AB,C=SE
+    "1.3.6.1.4.1.6449.1.2.1.5.1",
+    "Comodo EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x02, 0xFA, 0xF3, 0xE2, 0x91, 0x43, 0x54, 0x68, 0x60, 0x78,
+      0x57, 0x69, 0x4D, 0xF5, 0xE4, 0x5B, 0x68, 0x85, 0x18, 0x68 },
+    "MG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMd"
+    "QWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0"
+    "IEV4dGVybmFsIENBIFJvb3Q=",
+    "AQ==",
+    nullptr
+  },
+  {
+    // CN=UTN - DATACorp SGC,OU=http://www.usertrust.com,O=The USERTRUST Network,L=Salt Lake City,ST=UT,C=US
+    "1.3.6.1.4.1.6449.1.2.1.5.1",
+    "Comodo EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x58, 0x11, 0x9F, 0x0E, 0x12, 0x82, 0x87, 0xEA, 0x50, 0xFD,
+      0xD9, 0x87, 0x45, 0x6F, 0x4F, 0x78, 0xDC, 0xFA, 0xD6, 0xD4 },
+    "MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFr"
+    "ZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsT"
+    "GGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNv"
+    "cnAgU0dD",
+    "RL4Mi1AAIbQR0ypoBqmtaQ==",
+    nullptr
+  },
+  {
+    // CN=UTN-USERFirst-Hardware,OU=http://www.usertrust.com,O=The USERTRUST Network,L=Salt Lake City,ST=UT,C=US
+    "1.3.6.1.4.1.6449.1.2.1.5.1",
+    "Comodo EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x04, 0x83, 0xED, 0x33, 0x99, 0xAC, 0x36, 0x08, 0x05, 0x87,
+      0x22, 0xED, 0xBC, 0x5E, 0x46, 0x00, 0xE3, 0xBE, 0xF9, 0xD7 },
+    "MIGXMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFr"
+    "ZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsT"
+    "GGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEfMB0GA1UEAxMWVVROLVVTRVJGaXJz"
+    "dC1IYXJkd2FyZQ==",
+    "RL4Mi1AAJLQR0zYq/mUK/Q==",
+    nullptr
+  },
+  {
+    // OU=Go Daddy Class 2 Certification Authority,O=\"The Go Daddy Group, Inc.\",C=US
+    "2.16.840.1.114413.1.7.23.3",
+    "Go Daddy EV OID a",
+    SEC_OID_UNKNOWN,
+    { 0x27, 0x96, 0xBA, 0xE6, 0x3F, 0x18, 0x01, 0xE2, 0x77, 0x26,
+      0x1B, 0xA0, 0xD7, 0x77, 0x70, 0x02, 0x8F, 0x20, 0xEE, 0xE4 },
+    "MGMxCzAJBgNVBAYTAlVTMSEwHwYDVQQKExhUaGUgR28gRGFkZHkgR3JvdXAsIElu"
+    "Yy4xMTAvBgNVBAsTKEdvIERhZGR5IENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRo"
+    "b3JpdHk=",
+    "AA==",
+    nullptr
+  },
+  {
+    // CN=Go Daddy Root Certificate Authority - G2,O="GoDaddy.com, Inc.",L=Scottsdale,ST=Arizona,C=US
+    "2.16.840.1.114413.1.7.23.3",
+    "Go Daddy EV OID a",
+    SEC_OID_UNKNOWN,
+    { 0x47, 0xBE, 0xAB, 0xC9, 0x22, 0xEA, 0xE8, 0x0E, 0x78, 0x78,
+      0x34, 0x62, 0xA7, 0x9F, 0x45, 0xC2, 0x54, 0xFD, 0xE6, 0x8B },
+    "MIGDMQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2Nv"
+    "dHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4xMTAvBgNVBAMTKEdv"
+    "IERhZGR5IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzI=",
+    "AA==",
+    nullptr
+  },
+  {
+    // E=info@valicert.com,CN=http://www.valicert.com/,OU=ValiCert Class 2 Policy Validation Authority,O=\"ValiCert, Inc.\",L=ValiCert Validation Network
+    "2.16.840.1.114413.1.7.23.3",
+    "Go Daddy EV OID a",
+    SEC_OID_UNKNOWN,
+    { 0x31, 0x7A, 0x2A, 0xD0, 0x7F, 0x2B, 0x33, 0x5E, 0xF5, 0xA1,
+      0xC3, 0x4E, 0x4B, 0x57, 0xE8, 0xB7, 0xD8, 0xF1, 0xFC, 0xA6 },
+    "MIG7MSQwIgYDVQQHExtWYWxpQ2VydCBWYWxpZGF0aW9uIE5ldHdvcmsxFzAVBgNV"
+    "BAoTDlZhbGlDZXJ0LCBJbmMuMTUwMwYDVQQLEyxWYWxpQ2VydCBDbGFzcyAyIFBv"
+    "bGljeSBWYWxpZGF0aW9uIEF1dGhvcml0eTEhMB8GA1UEAxMYaHR0cDovL3d3dy52"
+    "YWxpY2VydC5jb20vMSAwHgYJKoZIhvcNAQkBFhFpbmZvQHZhbGljZXJ0LmNvbQ==",
+    "AQ==",
+    nullptr
+  },
+  {
+    // E=info@valicert.com,CN=http://www.valicert.com/,OU=ValiCert Class 2 Policy Validation Authority,O=\"ValiCert, Inc.\",L=ValiCert Validation Network
+    "2.16.840.1.114414.1.7.23.3",
+    "Go Daddy EV OID b",
+    SEC_OID_UNKNOWN,
+    { 0x31, 0x7A, 0x2A, 0xD0, 0x7F, 0x2B, 0x33, 0x5E, 0xF5, 0xA1,
+      0xC3, 0x4E, 0x4B, 0x57, 0xE8, 0xB7, 0xD8, 0xF1, 0xFC, 0xA6 },
+    "MIG7MSQwIgYDVQQHExtWYWxpQ2VydCBWYWxpZGF0aW9uIE5ldHdvcmsxFzAVBgNV"
+    "BAoTDlZhbGlDZXJ0LCBJbmMuMTUwMwYDVQQLEyxWYWxpQ2VydCBDbGFzcyAyIFBv"
+    "bGljeSBWYWxpZGF0aW9uIEF1dGhvcml0eTEhMB8GA1UEAxMYaHR0cDovL3d3dy52"
+    "YWxpY2VydC5jb20vMSAwHgYJKoZIhvcNAQkBFhFpbmZvQHZhbGljZXJ0LmNvbQ==",
+    "AQ==",
+    nullptr
+  },
+  {
+    // OU=Starfield Class 2 Certification Authority,O=\"Starfield Technologies, Inc.\",C=US
+    "2.16.840.1.114414.1.7.23.3",
+    "Go Daddy EV OID b",
+    SEC_OID_UNKNOWN,
+    { 0xAD, 0x7E, 0x1C, 0x28, 0xB0, 0x64, 0xEF, 0x8F, 0x60, 0x03,
+      0x40, 0x20, 0x14, 0xC3, 0xD0, 0xE3, 0x37, 0x0E, 0xB5, 0x8A },
+    "MGgxCzAJBgNVBAYTAlVTMSUwIwYDVQQKExxTdGFyZmllbGQgVGVjaG5vbG9naWVz"
+    "LCBJbmMuMTIwMAYDVQQLEylTdGFyZmllbGQgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9u"
+    "IEF1dGhvcml0eQ==",
+    "AA==",
+    nullptr
+  },
+  {
+    // CN=Starfield Root Certificate Authority - G2,O="Starfield Technologies, Inc.",L=Scottsdale,ST=Arizona,C=US
+    "2.16.840.1.114414.1.7.23.3",
+    "Go Daddy EV OID b",
+    SEC_OID_UNKNOWN,
+    { 0xB5, 0x1C, 0x06, 0x7C, 0xEE, 0x2B, 0x0C, 0x3D, 0xF8, 0x55,
+      0xAB, 0x2D, 0x92, 0xF4, 0xFE, 0x39, 0xD4, 0xE7, 0x0F, 0x0E },
+    "MIGPMQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2Nv"
+    "dHRzZGFsZTElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEy"
+    "MDAGA1UEAxMpU3RhcmZpZWxkIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0g"
+    "RzI=",
+    "AA==",
+    nullptr
+  },
+  {
+    // CN=DigiCert High Assurance EV Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US
+    "2.16.840.1.114412.2.1",
+    "DigiCert EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x5F, 0xB7, 0xEE, 0x06, 0x33, 0xE2, 0x59, 0xDB, 0xAD, 0x0C,
+      0x4C, 0x9A, 0xE6, 0xD3, 0X8F, 0x1A, 0x61, 0xC7, 0xDC, 0x25 },
+    "MGwxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsT"
+    "EHd3dy5kaWdpY2VydC5jb20xKzApBgNVBAMTIkRpZ2lDZXJ0IEhpZ2ggQXNzdXJh"
+    "bmNlIEVWIFJvb3QgQ0E=",
+    "AqxcJmoLQJuPC3nyrkYldw==",
+    nullptr
+  },
+  {
+    // CN=QuoVadis Root CA 2,O=QuoVadis Limited,C=BM
+    "1.3.6.1.4.1.8024.0.2.100.1.2",
+    "Quo Vadis EV OID",
+    SEC_OID_UNKNOWN,
+    { 0xCA, 0x3A, 0xFB, 0xCF, 0x12, 0x40, 0x36, 0x4B, 0x44, 0xB2,
+      0x16, 0x20, 0x88, 0x80, 0x48, 0x39, 0x19, 0x93, 0x7C, 0xF7 },
+    "MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYD"
+    "VQQDExJRdW9WYWRpcyBSb290IENBIDI=",
+    "BQk=",
+    nullptr
+  },
+  {
+    // CN=Network Solutions Certificate Authority,O=Network Solutions L.L.C.,C=US
+    "1.3.6.1.4.1.782.1.2.1.8.1",
+    "Network Solutions EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x74, 0xF8, 0xA3, 0xC3, 0xEF, 0xE7, 0xB3, 0x90, 0x06, 0x4B,
+      0x83, 0x90, 0x3C, 0x21, 0x64, 0x60, 0x20, 0xE5, 0xDF, 0xCE },
+    "MGIxCzAJBgNVBAYTAlVTMSEwHwYDVQQKExhOZXR3b3JrIFNvbHV0aW9ucyBMLkwu"
+    "Qy4xMDAuBgNVBAMTJ05ldHdvcmsgU29sdXRpb25zIENlcnRpZmljYXRlIEF1dGhv"
+    "cml0eQ==",
+    "V8szb8JcFuZHFhfjkDFo4A==",
+    nullptr
+  },
+  {
+    // CN=Entrust Root Certification Authority,OU="(c) 2006 Entrust, Inc.",OU=www.entrust.net/CPS is incorporated by reference,O="Entrust, Inc.",C=US
+    "2.16.840.1.114028.10.1.2",
+    "Entrust EV OID",
+    SEC_OID_UNKNOWN,
+    { 0xB3, 0x1E, 0xB1, 0xB7, 0x40, 0xE3, 0x6C, 0x84, 0x02, 0xDA,
+      0xDC, 0x37, 0xD4, 0x4D, 0xF5, 0xD4, 0x67, 0x49, 0x52, 0xF9 },
+    "MIGwMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNRW50cnVzdCwgSW5jLjE5MDcGA1UE"
+    "CxMwd3d3LmVudHJ1c3QubmV0L0NQUyBpcyBpbmNvcnBvcmF0ZWQgYnkgcmVmZXJl"
+    "bmNlMR8wHQYDVQQLExYoYykgMjAwNiBFbnRydXN0LCBJbmMuMS0wKwYDVQQDEyRF"
+    "bnRydXN0IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHk=",
+    "RWtQVA==",
+    nullptr
+  },
+  {
+    // CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE
+    "1.3.6.1.4.1.4146.1.1",
+    "GlobalSign EV OID",
+    SEC_OID_UNKNOWN,
+    { 0xB1, 0xBC, 0x96, 0x8B, 0xD4, 0xF4, 0x9D, 0x62, 0x2A, 0xA8,
+      0x9A, 0x81, 0xF2, 0x15, 0x01, 0x52, 0xA4, 0x1D, 0x82, 0x9C },
+    "MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYD"
+    "VQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=",
+    "BAAAAAABFUtaw5Q=",
+    nullptr
+  },
+  {
+    // CN=GlobalSign,O=GlobalSign,OU=GlobalSign Root CA - R2
+    "1.3.6.1.4.1.4146.1.1",
+    "GlobalSign EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x75, 0xE0, 0xAB, 0xB6, 0x13, 0x85, 0x12, 0x27, 0x1C, 0x04,
+      0xF8, 0x5F, 0xDD, 0xDE, 0x38, 0xE4, 0xB7, 0x24, 0x2E, 0xFE },
+    "MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpH"
+    "bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu",
+    "BAAAAAABD4Ym5g0=",
+    nullptr
+  },
+  {
+    // CN=GlobalSign,O=GlobalSign,OU=GlobalSign Root CA - R3
+    "1.3.6.1.4.1.4146.1.1",
+    "GlobalSign EV OID",
+    SEC_OID_UNKNOWN,
+    { 0xD6, 0x9B, 0x56, 0x11, 0x48, 0xF0, 0x1C, 0x77, 0xC5, 0x45,
+      0x78, 0xC1, 0x09, 0x26, 0xDF, 0x5B, 0x85, 0x69, 0x76, 0xAD },
+    "MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpH"
+    "bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu",
+    "BAAAAAABIVhTCKI=",
+    nullptr
+  },
+  {
+    // CN=Buypass Class 3 CA 1,O=Buypass AS-983163327,C=NO
+    "2.16.578.1.26.1.3.3",
+    "Buypass EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x61, 0x57, 0x3A, 0x11, 0xDF, 0x0E, 0xD8, 0x7E, 0xD5, 0x92,
+      0x65, 0x22, 0xEA, 0xD0, 0x56, 0xD7, 0x44, 0xB3, 0x23, 0x71 },
+    "MEsxCzAJBgNVBAYTAk5PMR0wGwYDVQQKDBRCdXlwYXNzIEFTLTk4MzE2MzMyNzEd"
+    "MBsGA1UEAwwUQnV5cGFzcyBDbGFzcyAzIENBIDE=",
+    "Ag==",
+    nullptr
+  },
+  {
+    // CN=Buypass Class 3 Root CA,O=Buypass AS-983163327,C=NO
+    "2.16.578.1.26.1.3.3",
+    "Buypass EV OID",
+    SEC_OID_UNKNOWN,
+    { 0xDA, 0xFA, 0xF7, 0xFA, 0x66, 0x84, 0xEC, 0x06, 0x8F, 0x14,
+      0x50, 0xBD, 0xC7, 0xC2, 0x81, 0xA5, 0xBC, 0xA9, 0x64, 0x57 },
+    "ME4xCzAJBgNVBAYTAk5PMR0wGwYDVQQKDBRCdXlwYXNzIEFTLTk4MzE2MzMyNzEg"
+    "MB4GA1UEAwwXQnV5cGFzcyBDbGFzcyAzIFJvb3QgQ0E=",
+    "Ag==",
+    nullptr
+  },
+  {
+    // CN=Class 2 Primary CA,O=Certplus,C=FR
+    "1.3.6.1.4.1.22234.2.5.2.3.1",
+    "Certplus EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x74, 0x20, 0x74, 0x41, 0x72, 0x9C, 0xDD, 0x92, 0xEC, 0x79,
+      0x31, 0xD8, 0x23, 0x10, 0x8D, 0xC2, 0x81, 0x92, 0xE2, 0xBB },
+    "MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xh"
+    "c3MgMiBQcmltYXJ5IENB",
+    "AIW9S/PY2uNp9pTXX8OlRCM=",
+    nullptr
+  },
+  {
+    // CN=Chambers of Commerce Root - 2008,O=AC Camerfirma S.A.,serialNumber=A82743287,L=Madrid (see current address at www.camerfirma.com/address),C=EU
+    "1.3.6.1.4.1.17326.10.14.2.1.2",
+    "Camerfirma EV OID a",
+    SEC_OID_UNKNOWN,
+    { 0x78, 0x6A, 0x74, 0xAC, 0x76, 0xAB, 0x14, 0x7F, 0x9C, 0x6A,
+      0x30, 0x50, 0xBA, 0x9E, 0xA8, 0x7E, 0xFE, 0x9A, 0xCE, 0x3C },
+    "MIGuMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBh"
+    "ZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ"
+    "QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMT"
+    "IENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4",
+    "AKPaQn6ksa7a",
+    nullptr
+  },
+  {
+    // CN=Global Chambersign Root - 2008,O=AC Camerfirma S.A.,serialNumber=A82743287,L=Madrid (see current address at www.camerfirma.com/address),C=EU
+    "1.3.6.1.4.1.17326.10.8.12.1.2",
+    "Camerfirma EV OID b",
+    SEC_OID_UNKNOWN,
+    { 0x4A, 0xBD, 0xEE, 0xEC, 0x95, 0x0D, 0x35, 0x9C, 0x89, 0xAE,
+      0xC7, 0x52, 0xA1, 0x2C, 0x5B, 0x29, 0xF6, 0xD6, 0xAA, 0x0C },
+    "MIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBh"
+    "ZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ"
+    "QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMT"
+    "Hkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwOA==",
+    "AMnN0+nVfSPO",
+    nullptr
+  },
+  {
+    // CN=TC TrustCenter Universal CA III,OU=TC TrustCenter Universal CA,O=TC TrustCenter GmbH,C=DE
+    "1.2.276.0.44.1.1.1.4",
+    "TC TrustCenter EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x96, 0x56, 0xCD, 0x7B, 0x57, 0x96, 0x98, 0x95, 0xD0, 0xE1,
+      0x41, 0x46, 0x68, 0x06, 0xFB, 0xB8, 0xC6, 0x11, 0x06, 0x87 },
+    "MHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNUQyBUcnVzdENlbnRlciBHbWJIMSQw"
+    "IgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0ExKDAmBgNVBAMTH1RD"
+    "IFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUk=",
+    "YyUAAQACFI0zFQLkbPQ=",
+    nullptr
+  },
+  {
+    // CN=AffirmTrust Commercial,O=AffirmTrust,C=US
+    "1.3.6.1.4.1.34697.2.1",
+    "AffirmTrust EV OID a",
+    SEC_OID_UNKNOWN,
+    { 0xF9, 0xB5, 0xB6, 0x32, 0x45, 0x5F, 0x9C, 0xBE, 0xEC, 0x57,
+      0x5F, 0x80, 0xDC, 0xE9, 0x6E, 0x2C, 0xC7, 0xB2, 0x78, 0xB7 },
+    "MEQxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEfMB0GA1UEAwwW"
+    "QWZmaXJtVHJ1c3QgQ29tbWVyY2lhbA==",
+    "d3cGJyapsXw=",
+    nullptr
+  },
+  {
+    // CN=AffirmTrust Networking,O=AffirmTrust,C=US
+    "1.3.6.1.4.1.34697.2.2",
+    "AffirmTrust EV OID b",
+    SEC_OID_UNKNOWN,
+    { 0x29, 0x36, 0x21, 0x02, 0x8B, 0x20, 0xED, 0x02, 0xF5, 0x66,
+      0xC5, 0x32, 0xD1, 0xD6, 0xED, 0x90, 0x9F, 0x45, 0x00, 0x2F },
+    "MEQxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEfMB0GA1UEAwwW"
+    "QWZmaXJtVHJ1c3QgTmV0d29ya2luZw==",
+    "fE8EORzUmS0=",
+    nullptr
+  },
+  {
+    // CN=AffirmTrust Premium,O=AffirmTrust,C=US
+    "1.3.6.1.4.1.34697.2.3",
+    "AffirmTrust EV OID c",
+    SEC_OID_UNKNOWN,
+    { 0xD8, 0xA6, 0x33, 0x2C, 0xE0, 0x03, 0x6F, 0xB1, 0x85, 0xF6,
+      0x63, 0x4F, 0x7D, 0x6A, 0x06, 0x65, 0x26, 0x32, 0x28, 0x27 },
+    "MEExCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEcMBoGA1UEAwwT"
+    "QWZmaXJtVHJ1c3QgUHJlbWl1bQ==",
+    "bYwURrGmCu4=",
+    nullptr
+  },
+  {
+    // CN=AffirmTrust Premium ECC,O=AffirmTrust,C=US
+    "1.3.6.1.4.1.34697.2.4",
+    "AffirmTrust EV OID d",
+    SEC_OID_UNKNOWN,
+    { 0xB8, 0x23, 0x6B, 0x00, 0x2F, 0x1D, 0x16, 0x86, 0x53, 0x01,
+      0x55, 0x6C, 0x11, 0xA4, 0x37, 0xCA, 0xEB, 0xFF, 0xC3, 0xBB },
+    "MEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwX"
+    "QWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0M=",
+    "dJclisc/elQ=",
+    nullptr
+  },
+  {
+    // CN=Certum Trusted Network CA,OU=Certum Certification Authority,O=Unizeto Technologies S.A.,C=PL
+    "1.2.616.1.113527.2.5.1.1",
+    "Certum EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x07, 0xE0, 0x32, 0xE0, 0x20, 0xB7, 0x2C, 0x3F, 0x19, 0x2F,
+      0x06, 0x28, 0xA2, 0x59, 0x3A, 0x19, 0xA7, 0x0F, 0x06, 0x9E },
+    "MH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBT"
+    "LkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAg"
+    "BgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0E=",
+    "BETA",
+    nullptr
+  },
+  {
+    // CN=Izenpe.com,O=IZENPE S.A.,C=ES
+    "1.3.6.1.4.1.14777.6.1.1",
+    "Izenpe EV OID 1",
+    SEC_OID_UNKNOWN,
+    { 0x2F, 0x78, 0x3D, 0x25, 0x52, 0x18, 0xA7, 0x4A, 0x65, 0x39,
+      0x71, 0xB5, 0x2C, 0xA2, 0x9C, 0x45, 0x15, 0x6F, 0xE9, 0x19 },
+    "MDgxCzAJBgNVBAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwK"
+    "SXplbnBlLmNvbQ==",
+    "ALC3WhZIX7/hy/WL1xnmfQ==",
+    nullptr
+  },
+  {
+    // CN=Izenpe.com,O=IZENPE S.A.,C=ES
+    "1.3.6.1.4.1.14777.6.1.2",
+    "Izenpe EV OID 2",
+    SEC_OID_UNKNOWN,
+    { 0x2F, 0x78, 0x3D, 0x25, 0x52, 0x18, 0xA7, 0x4A, 0x65, 0x39,
+      0x71, 0xB5, 0x2C, 0xA2, 0x9C, 0x45, 0x15, 0x6F, 0xE9, 0x19 },
+    "MDgxCzAJBgNVBAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwK"
+    "SXplbnBlLmNvbQ==",
+    "ALC3WhZIX7/hy/WL1xnmfQ==",
+    nullptr
+  },
+  {
+    // CN=A-Trust-nQual-03,OU=A-Trust-nQual-03,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT
+    "1.2.40.0.17.1.22",
+    "A-Trust EV OID",
+    SEC_OID_UNKNOWN,
+    { 0xD3, 0xC0, 0x63, 0xF2, 0x19, 0xED, 0x07, 0x3E, 0x34, 0xAD,
+      0x5D, 0x75, 0x0B, 0x32, 0x76, 0x29, 0xFF, 0xD5, 0x9A, 0xF2 },
+    "MIGNMQswCQYDVQQGEwJBVDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hl"
+    "cmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMRkwFwYD"
+    "VQQLDBBBLVRydXN0LW5RdWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5RdWFsLTAz",
+    "AWwe",
+    nullptr
+  },
+  {
+    // CN=T-TeleSec GlobalRoot Class 3,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE
+    "1.3.6.1.4.1.7879.13.24.1",
+    "T-Systems EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x55, 0xA6, 0x72, 0x3E, 0xCB, 0xF2, 0xEC, 0xCD, 0xC3, 0x23,
+      0x74, 0x70, 0x19, 0x9D, 0x2A, 0xBE, 0x11, 0xE3, 0x81, 0xD1 },
+    "MIGCMQswCQYDVQQGEwJERTErMCkGA1UECgwiVC1TeXN0ZW1zIEVudGVycHJpc2Ug"
+    "U2VydmljZXMgR21iSDEfMB0GA1UECwwWVC1TeXN0ZW1zIFRydXN0IENlbnRlcjEl"
+    "MCMGA1UEAwwcVC1UZWxlU2VjIEdsb2JhbFJvb3QgQ2xhc3MgMw==",
+    "AQ==",
+    nullptr
+  },
+  {
+    // CN=TURKTRUST Elektronik Sertifika Hizmet Saglayicisi,O=TURKTRUST Bilgi Illetisim ve Bilisim Guvenligi Hizmetleri A.S.,C=TR
+    "2.16.792.3.0.3.1.1.5",
+    "TurkTrust EV OID",
+    SEC_OID_UNKNOWN,
+    { 0xF1, 0x7F, 0x6F, 0xB6, 0x31, 0xDC, 0x99, 0xE3, 0xA3, 0xC8,
+      0x7F, 0xFE, 0x1C, 0xF1, 0x81, 0x10, 0x88, 0xD9, 0x60, 0x33 },
+    "MIG/MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU2VydGlmaWthIEhp"
+    "em1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmth"
+    "cmExXjBcBgNVBAoMVVTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBCaWxp"
+    "xZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEuxZ4uIChjKSBBcmFsxLFrIDIw"
+    "MDc=",
+    "AQ==",
+    nullptr
+  },
+  {
+    // CN=China Internet Network Information Center EV Certificates Root,O=China Internet Network Information Center,C=CN
+    "1.3.6.1.4.1.29836.1.10",
+    "CNNIC EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x4F, 0x99, 0xAA, 0x93, 0xFB, 0x2B, 0xD1, 0x37, 0x26, 0xA1,
+      0x99, 0x4A, 0xCE, 0x7F, 0xF0, 0x05, 0xF2, 0x93, 0x5D, 0x1E },
+    "MIGKMQswCQYDVQQGEwJDTjEyMDAGA1UECgwpQ2hpbmEgSW50ZXJuZXQgTmV0d29y"
+    "ayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMMPkNoaW5hIEludGVybmV0IE5l"
+    "dHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRpZmljYXRlcyBSb290",
+    "SJ8AAQ==",
+    nullptr
+  },
+  {
+    // CN=TWCA Root Certification Authority,OU=Root CA,O=TAIWAN-CA,C=TW
+    "1.3.6.1.4.1.40869.1.1.22.3",
+    "TWCA EV OID",
+    SEC_OID_UNKNOWN,
+    { 0xCF, 0x9E, 0x87, 0x6D, 0xD3, 0xEB, 0xFC, 0x42, 0x26, 0x97,
+      0xA3, 0xB5, 0xA3, 0x7A, 0xA0, 0x76, 0xA9, 0x06, 0x23, 0x48 },
+    "MF8xCzAJBgNVBAYTAlRXMRIwEAYDVQQKDAlUQUlXQU4tQ0ExEDAOBgNVBAsMB1Jv"
+    "b3QgQ0ExKjAoBgNVBAMMIVRXQ0EgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0"
+    "eQ==",
+    "AQ==",
+    nullptr
+  },
+  {
+    // CN=D-TRUST Root Class 3 CA 2 EV 2009,O=D-Trust GmbH,C=DE
+    "1.3.6.1.4.1.4788.2.202.1",
+    "D-TRUST EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x96, 0xC9, 0x1B, 0x0B, 0x95, 0xB4, 0x10, 0x98, 0x42, 0xFA,
+      0xD0, 0xD8, 0x22, 0x79, 0xFE, 0x60, 0xFA, 0xB9, 0x16, 0x83 },
+    "MFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMM"
+    "IUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOQ==",
+    "CYP0",
+    nullptr
+  },
+  {
+    // CN=Swisscom Root EV CA 2,OU=Digital Certificate Services,O=Swisscom,C=ch
+    "2.16.756.1.83.21.0",
+    "Swisscom  EV OID",
+    SEC_OID_UNKNOWN,
+    { 0xE7, 0xA1, 0x90, 0x29, 0xD3, 0xD5, 0x52, 0xDC, 0x0D, 0x0F,
+      0xC6, 0x92, 0xD3, 0xEA, 0x88, 0x0D, 0x15, 0x2E, 0x1A, 0x6B },
+    "MGcxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln"
+    "aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEeMBwGA1UEAxMVU3dpc3Njb20gUm9v"
+    "dCBFViBDQSAy",
+    "APL6ZOJ0Y9ON/RAdBB92ylg=",
+    nullptr
+  },
+  {
+    // CN=VeriSign Universal Root Certification Authority,OU="(c) 2008 VeriSign, Inc. - For authorized use only",OU=VeriSign Trust Network,O="VeriSign, Inc.",C=US
+    "2.16.840.1.113733.1.7.23.6",
+    "VeriSign EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x36, 0x79, 0xCA, 0x35, 0x66, 0x87, 0x72, 0x30, 0x4D, 0x30,
+      0xA5, 0xFB, 0x87, 0x3B, 0x0F, 0xA7, 0x7B, 0xB7, 0x0D, 0x54 },
+    "MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNV"
+    "BAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZl"
+    "cmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMT"
+    "L1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5",
+    "QBrEZCGzEyEDDrvkEhrFHQ==",
+    nullptr
+  },
+  {
+    // CN=GeoTrust Primary Certification Authority - G3,OU=(c) 2008 GeoTrust Inc. - For authorized use only,O=GeoTrust Inc.,C=US
+    "1.3.6.1.4.1.14370.1.6",
+    "GeoTrust EV OID",
+    SEC_OID_UNKNOWN,
+    { 0x03, 0x9E, 0xED, 0xB8, 0x0B, 0xE7, 0xA0, 0x3C, 0x69, 0x53,
+      0x89, 0x3B, 0x20, 0xD2, 0xD9, 0x32, 0x3A, 0x4C, 0x2A, 0xFD },
+    "MIGYMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjE5MDcGA1UE"
+    "CxMwKGMpIDIwMDggR2VvVHJ1c3QgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBv"
+    "bmx5MTYwNAYDVQQDEy1HZW9UcnVzdCBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0"
+    "aG9yaXR5IC0gRzM=",
+    "FaxulBmyeUtB9iepwxgPHw==",
+    nullptr
+  },
+  {
+    // CN=thawte Primary Root CA - G3,OU="(c) 2008 thawte, Inc. - For authorized use only",OU=Certification Services Division,O="thawte, Inc.",C=US
+    "2.16.840.1.113733.1.7.48.1",
+    "Thawte EV OID",
+    SEC_OID_UNKNOWN,
+    { 0xF1, 0x8B, 0x53, 0x8D, 0x1B, 0xE9, 0x03, 0xB6, 0xA6, 0xF0,
+      0x56, 0x43, 0x5B, 0x17, 0x15, 0x89, 0xCA, 0xF3, 0x6B, 0xF2 },
+    "MIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3RlLCBJbmMuMSgwJgYDVQQL"
+    "Ex9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYDVQQLEy8oYykg"
+    "MjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG"
+    "A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz",
+    "YAGXt0an6rS0mtZLL/eQ+w==",
+    nullptr
+  }
+};
+
+static SECOidTag
+register_oid(const SECItem* oid_item, const char* oid_name)
+{
+  if (!oid_item)
+    return SEC_OID_UNKNOWN;
+
+  SECOidData od;
+  od.oid.len = oid_item->len;
+  od.oid.data = oid_item->data;
+  od.offset = SEC_OID_UNKNOWN;
+  od.desc = oid_name;
+  od.mechanism = CKM_INVALID_MECHANISM;
+  od.supportedExtension = INVALID_CERT_EXTENSION;
+  return SECOID_AddEntry(&od);
+}
+
+static void
+addToCertListIfTrusted(CERTCertList* certList, CERTCertificate* cert) {
+  CERTCertTrust nssTrust;
+  if (CERT_GetCertTrust(cert, &nssTrust) != SECSuccess) {
+    return;
+  }
+  unsigned int flags = SEC_GET_TRUST_FLAGS(&nssTrust, trustSSL);
+
+  if (flags & CERTDB_TRUSTED_CA) {
+    CERT_AddCertToListTail(certList, CERT_DupCertificate(cert));
+  }
+}
+
+static bool
+isEVPolicy(SECOidTag policyOIDTag)
+{
+  for (size_t iEV = 0; iEV < PR_ARRAY_SIZE(myTrustedEVInfos); ++iEV) {
+    nsMyTrustedEVInfo& entry = myTrustedEVInfos[iEV];
+    if (policyOIDTag == entry.oid_tag) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+namespace mozilla { namespace psm {
+
+CERTCertList*
+GetRootsForOid(SECOidTag oid_tag)
+{
+  CERTCertList* certList = CERT_NewCertList();
+  if (!certList)
+    return nullptr;
+
+  for (size_t iEV = 0; iEV < PR_ARRAY_SIZE(myTrustedEVInfos); ++iEV) {
+    nsMyTrustedEVInfo& entry = myTrustedEVInfos[iEV];
+    if (entry.oid_tag == oid_tag) {
+      addToCertListIfTrusted(certList, entry.cert);
+    }
+  }
+
+  return certList;
+}
+
+static PRStatus
+IdentityInfoInit()
+{
+  for (size_t iEV = 0; iEV < PR_ARRAY_SIZE(myTrustedEVInfos); ++iEV) {
+    nsMyTrustedEVInfo& entry = myTrustedEVInfos[iEV];
+
+    SECStatus rv;
+    CERTIssuerAndSN ias;
+
+    rv = ATOB_ConvertAsciiToItem(&ias.derIssuer, const_cast<char*>(entry.issuer_base64));
+    PR_ASSERT(rv == SECSuccess);
+    if (rv != SECSuccess) {
+      return PR_FAILURE;
+    }
+    rv = ATOB_ConvertAsciiToItem(&ias.serialNumber,
+                                 const_cast<char*>(entry.serial_base64));
+    PR_ASSERT(rv == SECSuccess);
+    if (rv != SECSuccess) {
+      SECITEM_FreeItem(&ias.derIssuer, false);
+      return PR_FAILURE;
+    }
+
+    ias.serialNumber.type = siUnsignedInteger;
+
+    entry.cert = CERT_FindCertByIssuerAndSN(nullptr, &ias);
+
+    SECITEM_FreeItem(&ias.derIssuer, false);
+    SECITEM_FreeItem(&ias.serialNumber, false);
+
+    // If an entry is missing in the NSS root database, it may be because the
+    // root database is out of sync with what we expect (e.g. a different
+    // version of system NSS is installed). We will just silently avoid
+    // treating that root cert as EV.
+    if (!entry.cert) {
+#ifdef DEBUG
+      // The debug CA info is at position 0, and is NOT on the NSS root db
+      if (iEV == 0) {
+        continue;
+      }
+#endif
+      PR_NOT_REACHED("Could not find EV root in NSS storage");
+      continue;
+    }
+
+    unsigned char certFingerprint[20];
+    rv = PK11_HashBuf(SEC_OID_SHA1, certFingerprint,
+                      entry.cert->derCert.data, entry.cert->derCert.len);
+    MOZ_ASSERT(rv == SECSuccess);
+    if (rv == SECSuccess) {
+      bool same = !memcmp(certFingerprint, entry.ev_root_sha1_fingerprint, 20);
+      MOZ_ASSERT(same);
+      if (same) {
+
+        SECItem ev_oid_item;
+        ev_oid_item.data = nullptr;
+        ev_oid_item.len = 0;
+        rv = SEC_StringToOID(nullptr, &ev_oid_item, entry.dotted_oid, 0);
+        MOZ_ASSERT(rv == SECSuccess);
+        if (rv == SECSuccess) {
+          entry.oid_tag = register_oid(&ev_oid_item, entry.oid_name);
+          if (entry.oid_tag == SEC_OID_UNKNOWN) {
+            rv = SECFailure;
+          }
+          SECITEM_FreeItem(&ev_oid_item, false);
+        }
+      } else {
+        PR_SetError(SEC_ERROR_BAD_DATA, 0);
+        rv = SECFailure;
+      }
+    }
+
+    if (rv != SECSuccess) {
+      CERT_DestroyCertificate(entry.cert);
+      entry.cert = nullptr;
+      entry.oid_tag = SEC_OID_UNKNOWN;
+      return PR_FAILURE;
+    }
+  }
+
+  return PR_SUCCESS;
+}
+
+static PRCallOnceType sIdentityInfoCallOnce;
+
+void
+EnsureIdentityInfoLoaded()
+{
+  (void) PR_CallOnce(&sIdentityInfoCallOnce, IdentityInfoInit);
+}
+
+void
+CleanupIdentityInfo()
+{
+  for (size_t iEV = 0; iEV < PR_ARRAY_SIZE(myTrustedEVInfos); ++iEV) {
+    nsMyTrustedEVInfo &entry = myTrustedEVInfos[iEV];
+    if (entry.cert) {
+      CERT_DestroyCertificate(entry.cert);
+      entry.cert = nullptr;
+    }
+  }
+
+  memset(&sIdentityInfoCallOnce, 0, sizeof(PRCallOnceType));
+}
+
+// Find the first policy OID that is known to be an EV policy OID.
+SECStatus
+GetFirstEVPolicy(CERTCertificate* cert, SECOidTag& outOidTag)
+{
+  if (!cert)
+    return SECFailure;
+
+  if (cert->extensions) {
+    for (int i=0; cert->extensions[i]; i++) {
+      const SECItem* oid = &cert->extensions[i]->id;
+
+      SECOidTag oidTag = SECOID_FindOIDTag(oid);
+      if (oidTag != SEC_OID_X509_CERTIFICATE_POLICIES)
+        continue;
+
+      SECItem* value = &cert->extensions[i]->value;
+
+      CERTCertificatePolicies* policies;
+      CERTPolicyInfo** policyInfos;
+
+      policies = CERT_DecodeCertificatePoliciesExtension(value);
+      if (!policies)
+        continue;
+
+      policyInfos = policies->policyInfos;
+
+      bool found = false;
+      while (*policyInfos) {
+        const CERTPolicyInfo* policyInfo = *policyInfos++;
+
+        SECOidTag oid_tag = policyInfo->oid;
+        if (oid_tag != SEC_OID_UNKNOWN && isEVPolicy(oid_tag)) {
+          // in our list of OIDs accepted for EV
+          outOidTag = oid_tag;
+          found = true;
+          break;
+        }
+      }
+      CERT_DestroyCertificatePoliciesExtension(policies);
+      if (found)
+        return SECSuccess;
+    }
+  }
+
+  return SECFailure;
+}
+
+} } // namespace mozilla::psm
new file mode 100644
--- /dev/null
+++ b/security/certverifier/ExtendedValidation.h
@@ -0,0 +1,23 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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_ExtendedValidation_h
+#define mozilla_psm_ExtendedValidation_h
+
+#include "certt.h"
+#include "prtypes.h"
+
+namespace mozilla { namespace psm {
+
+#ifndef NSS_NO_LIBPKIX
+void EnsureIdentityInfoLoaded();
+SECStatus GetFirstEVPolicy(CERTCertificate *cert, SECOidTag &outOidTag);
+CERTCertList* GetRootsForOid(SECOidTag oid_tag);
+void CleanupIdentityInfo();
+#endif
+
+} } // namespace mozilla::psm
+
+#endif // mozilla_psm_ExtendedValidation_h
new file mode 100644
--- /dev/null
+++ b/security/certverifier/moz.build
@@ -0,0 +1,20 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+UNIFIED_SOURCES += [
+    'CertVerifier.cpp',
+]
+
+if not CONFIG['NSS_NO_LIBPKIX']:
+    UNIFIED_SOURCES += [
+        'ExtendedValidation.cpp',
+    ]
+
+LOCAL_INCLUDES += [
+    '../insanity/include',
+]
+
+FINAL_LIBRARY = 'xul'
deleted file mode 100644
--- a/security/manager/ssl/src/CertVerifier.cpp
+++ /dev/null
@@ -1,441 +0,0 @@
-/* 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 "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(implementation_config ic,
-                           missing_cert_download_config mcdc,
-                           crl_download_config cdc,
-                           ocsp_download_config odc,
-                           ocsp_strict_config osc,
-                           ocsp_get_config ogc)
-  : 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)
-{
-}
-
-CertVerifier::~CertVerifier()
-{
-}
-
-static SECStatus
-ClassicVerifyCert(CERTCertificate* cert,
-                  const SECCertificateUsage usage,
-                  const PRTime time,
-                  void* pinArg,
-                  /*optional out*/ CERTCertList** validationChain,
-                  /*optional out*/ CERTVerifyLog* verifyLog)
-{
-  SECStatus rv;
-  SECCertUsage enumUsage;
-  if (validationChain) {
-    switch(usage){
-      case  certificateUsageSSLClient:
-        enumUsage = certUsageSSLClient;
-        break;
-      case  certificateUsageSSLServer:
-        enumUsage = certUsageSSLServer;
-        break;
-      case certificateUsageSSLServerWithStepUp:
-        enumUsage = certUsageSSLServerWithStepUp;
-        break;
-      case certificateUsageSSLCA:
-        enumUsage = certUsageSSLCA;
-        break;
-      case certificateUsageEmailSigner:
-        enumUsage = certUsageEmailSigner;
-        break;
-      case certificateUsageEmailRecipient:
-        enumUsage = certUsageEmailRecipient;
-        break;
-      case certificateUsageObjectSigner:
-        enumUsage = certUsageObjectSigner;
-        break;
-      case certificateUsageUserCertImport:
-        enumUsage = certUsageUserCertImport;
-        break;
-      case certificateUsageVerifyCA:
-        enumUsage = certUsageVerifyCA;
-        break;
-      case certificateUsageProtectedObjectSigner:
-        enumUsage = certUsageProtectedObjectSigner;
-        break;
-      case certificateUsageStatusResponder:
-        enumUsage = certUsageStatusResponder;
-        break;
-      case certificateUsageAnyCA:
-        enumUsage = certUsageAnyCA;
-        break;
-       default:
-        return SECFailure;
-    }
-  }
-  if (usage == certificateUsageSSLServer) {
-    // SSL server cert verification has always used CERT_VerifyCert, so we
-    // continue to use it for SSL cert verification to minimize the risk of
-    // there being any differnce in results between CERT_VerifyCert and
-    // CERT_VerifyCertificate.
-    rv = CERT_VerifyCert(CERT_GetDefaultCertDB(), cert, true,
-                         certUsageSSLServer, time, pinArg, verifyLog);
-  } else {
-    rv = CERT_VerifyCertificate(CERT_GetDefaultCertDB(), cert, true,
-                                usage, time, pinArg, verifyLog, nullptr);
-  }
-  if (rv == SECSuccess && validationChain) {
-    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("VerifyCert: getting chain in 'classic' \n"));
-    *validationChain = CERT_GetCertChainFromCert(cert, time, enumUsage);
-    if (!*validationChain) {
-      rv = SECFailure;
-    }
-  }
-  return rv;
-}
-
-SECStatus
-CertVerifier::VerifyCert(CERTCertificate* cert,
-                         const SECCertificateUsage usage,
-                         const PRTime time,
-                         void* pinArg,
-                         const Flags flags,
-                         /*optional out*/ CERTCertList** validationChain,
-                         /*optional out*/ SECOidTag* evOidPolicy,
-                         /*optional out*/ CERTVerifyLog* verifyLog)
-{
-  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;
-  }
-
-  switch(usage){
-    case certificateUsageSSLClient:
-    case certificateUsageSSLServer:
-    case certificateUsageSSLCA:
-    case certificateUsageEmailSigner:
-    case certificateUsageEmailRecipient:
-    case certificateUsageObjectSigner:
-    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;
-
-  // 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) {
-        return SECFailure;
-      }
-      // pkix ignores an empty trustanchors list and
-      // decides then to use the whole set of trust in the DB
-      // so we set the evPolicy to unkown in this case
-      if (CERT_LIST_EMPTY(trustAnchors)) {
-        evPolicy = SEC_OID_UNKNOWN;
-      }
-    } else {
-      // Do not setup EV verification params
-      evPolicy = SEC_OID_UNKNOWN;
-    }
-  }
-
-  MOZ_ASSERT_IF(evPolicy != SEC_OID_UNKNOWN, trustAnchors);
-
-  size_t i = 0;
-  size_t validationChainLocation = 0;
-  size_t validationTrustAnchorLocation = 0;
-  CERTValOutParam cvout[4];
-  if (verifyLog) {
-     cvout[i].type = cert_po_errorLog;
-     cvout[i].value.pointer.log = verifyLog;
-     ++i;
-  }
-  if (validationChain) {
-    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("VerifyCert: setting up validation chain outparam.\n"));
-    validationChainLocation = i;
-    cvout[i].type = cert_po_certList;
-    cvout[i].value.pointer.cert = nullptr;
-    ++i;
-    validationTrustAnchorLocation = i;
-    cvout[i].type = cert_po_trustAnchor;
-    cvout[i].value.pointer.chain = nullptr;
-    ++i;
-  }
-  cvout[i].type = cert_po_end;
-
-  CERTRevocationFlags rev;
-
-  CERTRevocationMethodIndex revPreferredMethods[2];
-  rev.leafTests.preferred_methods =
-  rev.chainTests.preferred_methods = revPreferredMethods;
-
-  uint64_t revFlagsPerMethod[2];
-  rev.leafTests.cert_rev_flags_per_method =
-  rev.chainTests.cert_rev_flags_per_method = revFlagsPerMethod;
-  rev.leafTests.number_of_preferred_methods =
-  rev.chainTests.number_of_preferred_methods = 1;
-
-  rev.leafTests.number_of_defined_methods =
-  rev.chainTests.number_of_defined_methods = cert_revocation_method_ocsp + 1;
-
-  const bool localOnly = flags & FLAG_LOCAL_ONLY;
-  CERTValInParam cvin[6];
-
-  // Parameters for both EV and DV validation
-  cvin[0].type = cert_pi_useAIACertFetch;
-  cvin[0].value.scalar.b = mMissingCertDownloadEnabled && !localOnly;
-  cvin[1].type = cert_pi_revocationFlags;
-  cvin[1].value.pointer.revocation = &rev;
-  cvin[2].type = cert_pi_date;
-  cvin[2].value.scalar.time = time;
-  i = 3;
-  const size_t evParamLocation = i;
-
-  if (evPolicy != SEC_OID_UNKNOWN) {
-    // EV setup!
-    // XXX 859872 The current flags are not quite correct. (use
-    // of ocsp flags for crl preferences).
-    uint64_t ocspRevMethodFlags =
-      CERT_REV_M_TEST_USING_THIS_METHOD
-      | ((mOCSPDownloadEnabled && !localOnly) ?
-          CERT_REV_M_ALLOW_NETWORK_FETCHING : CERT_REV_M_FORBID_NETWORK_FETCHING)
-      | CERT_REV_M_ALLOW_IMPLICIT_DEFAULT_SOURCE
-      | CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE
-      | CERT_REV_M_IGNORE_MISSING_FRESH_INFO
-      | CERT_REV_M_STOP_TESTING_ON_FRESH_INFO
-      | (mOCSPGETEnabled ? 0 : CERT_REV_M_FORCE_POST_METHOD_FOR_OCSP);
-
-    rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_crl] =
-    rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_crl]
-      = CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD;
-
-    rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] =
-    rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_ocsp]
-      = ocspRevMethodFlags;
-
-    rev.leafTests.cert_rev_method_independent_flags =
-    rev.chainTests.cert_rev_method_independent_flags =
-      // avoiding the network is good, let's try local first
-      CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST
-      // is overall revocation requirement strict or relaxed?
-      |  CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE
-      ;
-
-    rev.leafTests.preferred_methods[0] =
-    rev.chainTests.preferred_methods[0] = cert_revocation_method_ocsp;
-
-    cvin[i].type = cert_pi_policyOID;
-    cvin[i].value.arraySize = 1;
-    cvin[i].value.array.oids = &evPolicy;
-    ++i;
-    MOZ_ASSERT(trustAnchors);
-    cvin[i].type = cert_pi_trustAnchors;
-    cvin[i].value.pointer.chain = trustAnchors;
-    ++i;
-
-    cvin[i].type = cert_pi_end;
-
-    rv = CERT_PKIXVerifyCert(cert, usage, cvin, cvout, pinArg);
-    if (rv == SECSuccess) {
-      if (evOidPolicy) {
-        *evOidPolicy = evPolicy;
-      }
-      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
-             ("VerifyCert: successful CERT_PKIXVerifyCert(ev) \n"));
-      goto pkix_done;
-    }
-    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
-           ("VerifyCert: failed CERT_PKIXVerifyCert(ev)\n"));
-
-    if (validationChain && *validationChain) {
-      // There SHOULD not be a validation chain on failure, asserion here for
-      // the debug builds AND a fallback for production builds
-      MOZ_ASSERT(false,
-                 "certPKIXVerifyCert returned failure AND a validationChain");
-      CERT_DestroyCertList(*validationChain);
-      *validationChain = nullptr;
-    }
-
-    if (verifyLog) {
-      // Cleanup the log so that it is ready the the next validation
-      CERTVerifyLogNode* i_node;
-      for (i_node = verifyLog->head; i_node; i_node = i_node->next) {
-         //destroy cert if any.
-         if (i_node->cert) {
-           CERT_DestroyCertificate(i_node->cert);
-         }
-         // 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 (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
-
-    // no fresh CRL? well, let other flag decide whether to fail or not
-    | CERT_REV_M_IGNORE_MISSING_FRESH_INFO
-
-    // testing using local CRLs is always allowed
-    | CERT_REV_M_TEST_USING_THIS_METHOD
-
-    // no local crl and don't know where to get it from? ignore
-    | CERT_REV_M_SKIP_TEST_ON_MISSING_SOURCE
-
-    // crl download based on parameter
-    | ((mCRLDownloadEnabled && !localOnly) ?
-        CERT_REV_M_ALLOW_NETWORK_FETCHING : CERT_REV_M_FORBID_NETWORK_FETCHING)
-    ;
-
-  rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] =
-  rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] =
-    // use OCSP
-      CERT_REV_M_TEST_USING_THIS_METHOD
-
-    // if app has a default OCSP responder configured, let's use it
-    | CERT_REV_M_ALLOW_IMPLICIT_DEFAULT_SOURCE
-
-    // of course OCSP doesn't work without a source. let's accept such certs
-    | CERT_REV_M_SKIP_TEST_ON_MISSING_SOURCE
-
-    // if ocsp is required stop on lack of freshness
-    | (mOCSPStrict ?
-       CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO : CERT_REV_M_IGNORE_MISSING_FRESH_INFO)
-
-    // ocsp success is sufficient
-    | CERT_REV_M_STOP_TESTING_ON_FRESH_INFO
-
-    // ocsp enabled controls network fetching, too
-    | ((mOCSPDownloadEnabled && !localOnly) ?
-        CERT_REV_M_ALLOW_NETWORK_FETCHING : CERT_REV_M_FORBID_NETWORK_FETCHING)
-
-    | (mOCSPGETEnabled ? 0 : CERT_REV_M_FORCE_POST_METHOD_FOR_OCSP);
-    ;
-
-  rev.leafTests.preferred_methods[0] =
-  rev.chainTests.preferred_methods[0] = cert_revocation_method_ocsp;
-
-  rev.leafTests.cert_rev_method_independent_flags =
-  rev.chainTests.cert_rev_method_independent_flags =
-    // avoiding the network is good, let's try local first
-    CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST;
-
-  // Skip EV parameters
-  cvin[evParamLocation].type = cert_pi_end;
-
-  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("VerifyCert: calling CERT_PKIXVerifyCert(dv) \n"));
-  rv = CERT_PKIXVerifyCert(cert, usage, cvin, cvout, pinArg);
-
-pkix_done:
-  if (validationChain) {
-    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("VerifyCert: validation chain requested\n"));
-    ScopedCERTCertificate trustAnchor(cvout[validationTrustAnchorLocation].value.pointer.cert);
-
-    if (rv == SECSuccess) {
-      if (! cvout[validationChainLocation].value.pointer.chain) {
-        PR_SetError(PR_UNKNOWN_ERROR, 0);
-        return SECFailure;
-      }
-      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("VerifyCert: I have a chain\n"));
-      *validationChain = cvout[validationChainLocation].value.pointer.chain;
-      if (trustAnchor) {
-        // we should only add the issuer to the chain if it is not already
-        // present. On CA cert checking, the issuer is the same cert, so in
-        // that case we do not add the cert to the chain.
-        if (!CERT_CompareCerts(trustAnchor, cert)) {
-          PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("VerifyCert:  adding issuer to tail for display\n"));
-          // note: rv is reused to catch errors on cert creation!
-          ScopedCERTCertificate tempCert(CERT_DupCertificate(trustAnchor));
-          rv = CERT_AddCertToListTail(*validationChain, tempCert);
-          if (rv == SECSuccess) {
-            tempCert.forget(); // ownership traferred to validationChain
-          } else {
-            CERT_DestroyCertList(*validationChain);
-            *validationChain = nullptr;
-          }
-        }
-      }
-    } else {
-      // Validation was a fail, clean up if needed
-      if (cvout[validationChainLocation].value.pointer.chain) {
-        CERT_DestroyCertList(cvout[validationChainLocation].value.pointer.chain);
-      }
-    }
-  }
-
-  return rv;
-#endif
-}
-
-} } // namespace mozilla::psm
deleted file mode 100644
--- a/security/manager/ssl/src/CertVerifier.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* 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 "certt.h"
-#include "insanity/ScopedPtr.h"
-
-namespace mozilla { namespace psm {
-
-class CertVerifier
-{
-public:
-  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,
-                       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; }
-
-  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;
-};
-
-} } // namespace mozilla::psm
-
-#endif // mozilla_psm__CertVerifier_h
--- a/security/manager/ssl/src/SSLServerCertVerification.cpp
+++ b/security/manager/ssl/src/SSLServerCertVerification.cpp
@@ -92,16 +92,18 @@
 // we need the event to interrupt the PR_Poll that may waiting for I/O on the
 // socket for which we are validating the cert.
 
 #include "SSLServerCertVerification.h"
 
 #include <cstring>
 
 #include "CertVerifier.h"
+#include "CryptoTask.h"
+#include "ExtendedValidation.h"
 #include "nsIBadCertListener2.h"
 #include "nsICertOverrideService.h"
 #include "nsISiteSecurityService.h"
 #include "nsNSSComponent.h"
 #include "nsNSSCleaner.h"
 #include "nsRecentBadCerts.h"
 #include "nsNSSIOLayer.h"
 #include "nsNSSShutDown.h"
@@ -1338,43 +1340,26 @@ AuthCertificateHook(void* arg, PRFileDes
     error = PR_UNKNOWN_ERROR;
   }
 
   PR_SetError(error, 0);
   return SECFailure;
 }
 
 #ifndef NSS_NO_LIBPKIX
-class InitializeIdentityInfo : public nsRunnable
-                             , public nsNSSShutDownObject
+class InitializeIdentityInfo : public CryptoTask
 {
-private:
-  NS_IMETHOD Run()
+  virtual nsresult CalculateResult() MOZ_OVERRIDE
   {
-    nsNSSShutDownPreventionLock nssShutdownPrevention;
-    if (isAlreadyShutDown())
-      return NS_OK;
-
-    nsresult rv;
-    nsCOMPtr<nsINSSComponent> inss = do_GetService(PSM_COMPONENT_CONTRACTID, &rv);
-    if (NS_SUCCEEDED(rv))
-      inss->EnsureIdentityInfoLoaded();
+    EnsureIdentityInfoLoaded();
     return NS_OK;
   }
 
-  virtual void virtualDestroyNSSReference()
-  {
-  }
-
-  ~InitializeIdentityInfo()
-  {
-    nsNSSShutDownPreventionLock nssShutdownPrevention;
-    if (!isAlreadyShutDown())
-      shutdown(calledFromObject);
-  }
+  virtual void ReleaseNSSResources() MOZ_OVERRIDE { } // no-op
+  virtual void CallCallback(nsresult rv) MOZ_OVERRIDE { } // no-op
 };
 #endif
 
 void EnsureServerVerificationInitialized()
 {
 #ifndef NSS_NO_LIBPKIX
   // Should only be called from socket transport thread due to the static
   // variable and the reference to gCertVerificationThreadPool
--- a/security/manager/ssl/src/moz.build
+++ b/security/manager/ssl/src/moz.build
@@ -11,28 +11,26 @@ EXPORTS += [
     'ScopedNSSTypes.h',
 ]
 
 EXPORTS.mozilla += [
     'PublicSSL.h',
 ]
 
 UNIFIED_SOURCES += [
-    'CertVerifier.cpp',
     'CryptoTask.cpp',
     'nsCertificatePrincipal.cpp',
     'nsCertOverrideService.cpp',
     'nsCertPicker.cpp',
     'nsCertVerificationThread.cpp',
     'nsClientAuthRemember.cpp',
     'nsCMS.cpp',
     'nsCMSSecureMessage.cpp',
     'nsCrypto.cpp',
     'nsDataSignatureVerifier.cpp',
-    'nsIdentityChecking.cpp',
     'nsKeygenHandler.cpp',
     'nsKeygenThread.cpp',
     'nsKeyModule.cpp',
     'nsNSSASN1Object.cpp',
     'nsNSSCallbacks.cpp',
     'nsNSSCertCache.cpp',
     'nsNSSCertHelper.cpp',
     'nsNSSCertificate.cpp',
@@ -89,15 +87,16 @@ if CONFIG['MOZ_XUL']:
 
 UNIFIED_SOURCES += [
     'md4.c',
 ]
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
-	'../../../insanity/include',
+    '../../../certverifier',
+    '../../../insanity/include',
 ]
 
 
 DEFINES['NSS_ENABLE_ECC'] = 'True'
 for var in ('DLL_PREFIX', 'DLL_SUFFIX'):
     DEFINES[var] = '"%s"' % CONFIG[var]
deleted file mode 100644
--- a/security/manager/ssl/src/nsIdentityChecking.cpp
+++ /dev/null
@@ -1,1423 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * 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 "nsNSSCertificate.h"
-#include "nsNSSComponent.h"
-#include "mozilla/RefPtr.h"
-#include "nsAppDirectoryServiceDefs.h"
-#include "nsStreamUtils.h"
-#include "nsNetUtil.h"
-#include "nsILineInputStream.h"
-#include "nsPromiseFlatString.h"
-#include "nsTArray.h"
-#include "nsNSSCertTrust.h"
-
-#include "cert.h"
-#include "base64.h"
-#include "nsSSLStatus.h"
-#include "ScopedNSSTypes.h"
-
-using namespace mozilla;
-
-#ifdef DEBUG
-#ifndef PSM_ENABLE_TEST_EV_ROOTS
-#define PSM_ENABLE_TEST_EV_ROOTS
-#endif
-#endif
-
-#ifdef PR_LOGGING
-extern PRLogModuleInfo* gPIPNSSLog;
-#endif
-
-#define CONST_OID static const unsigned char
-#define OI(x) { siDEROID, (unsigned char*) x, sizeof x }
-
-struct nsMyTrustedEVInfo
-{
-  const char* dotted_oid;
-  const char* oid_name; // Set this to null to signal an invalid structure,
-                  // (We can't have an empty list, so we'll use a dummy entry)
-  SECOidTag oid_tag;
-  const char* ev_root_sha1_fingerprint;
-  const char* issuer_base64;
-  const char* serial_base64;
-  CERTCertificate* cert;
-};
-
-// HOWTO enable additional CA root certificates for EV:
-//
-// For each combination of "root certificate" and "policy OID",
-// one entry must be added to the array named myTrustedEVInfos.
-//
-// We use the combination of "issuer name" and "serial number" to
-// uniquely identify the certificate. In order to avoid problems
-// because of encodings when comparing certificates, we don't
-// use plain text representation, we rather use the original encoding
-// as it can be found in the root certificate (in base64 format).
-//
-// We can use the NSS utility named "pp" to extract the encoding.
-//
-// Build standalone NSS including the NSS tools, then run
-//   pp -t certificate-identity -i the-cert-filename
-//
-// You will need the output from sections "Issuer", "Fingerprint (SHA1)",
-// "Issuer DER Base64" and "Serial DER Base64".
-//
-// The new section consists of 8 lines:
-//
-// - a comment that should contain the human readable issuer name
-//   of the certificate, as printed by the pp tool
-// - the EV policy OID that is associated to the EV grant
-// - a text description of the EV policy OID. The array can contain
-//   multiple entries with the same OID.
-//   Please make sure to use the identical OID text description for
-//   all entries with the same policy OID (use the text search
-//   feature of your text editor to find duplicates).
-//   When adding a new policy OID that is not yet contained in the array,
-//   please make sure that your new description is different from
-//   all the other descriptions (again use the text search feature
-//   to be sure).
-// - the constant SEC_OID_UNKNOWN
-//   (it will be replaced at runtime with another identifier)
-// - the UPPERCASE version of the SHA1 fingerprint, hexadecimal,
-//   bytes separated by colons (as printed by pp)
-// - the "Issuer DER Base64" as printed by the pp tool.
-//   Remove all whitespaces. If you use multiple lines, make sure that
-//   only the final line will be followed by a comma.
-// - the "Serial DER Base64" (as printed by pp)
-// - a nullptr value
-//
-// After adding an entry, test it locally against the test site that
-// has been provided by the CA. Note that you must use a version of NSS
-// where the root certificate has already been added and marked as trusted
-// for issueing SSL server certificates (at least).
-//
-// If you are able to connect to the site without certificate errors,
-// but you don't see the EV status indicator, then most likely the CA
-// has a problem in their infrastructure. The most common problems are
-// related to the CA's OCSP infrastructure, either they use an incorrect
-// OCSP signing certificate, or OCSP for the intermediate certificates
-// isn't working, or OCSP isn't working at all.
-
-static struct nsMyTrustedEVInfo myTrustedEVInfos[] = {
-  // IMPORTANT! When extending this list,
-  // pairs of dotted_oid and oid_name should always be unique pairs.
-  // In other words, if you add another list, that uses the same dotted_oid
-  // as an existing entry, then please use the same oid_name.
-#ifdef DEBUG
-  // Debug EV certificates should all use the OID (repeating EV OID is OK):
-  // 1.3.6.1.4.1.13769.666.666.666.1.500.9.1.
-  // If you add or remove debug EV certs you must also modify IdentityInfoInit
-  // (there is another #ifdef DEBUG section there) so that the correct number of
-  // certs are skipped as these debug EV certs are NOT part of the default trust
-  // store.
-  {
-    // This is the testing EV signature (xpcshell) (RSA)
-    // CN=XPCShell EV Testing (untrustworthy) CA,OU=Security Engineering,O=Mozilla - EV debug test CA,L=Mountain View,ST=CA,C=US"
-    "1.3.6.1.4.1.13769.666.666.666.1.500.9.1",
-    "DEBUGtesting EV OID",
-    SEC_OID_UNKNOWN,
-    "9C:62:EF:DB:AE:F9:EB:36:58:FB:3B:D3:47:64:93:9D:86:29:6A:E0",
-    "MIGnMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWlu"
-    "IFZpZXcxIzAhBgNVBAoMGk1vemlsbGEgLSBFViBkZWJ1ZyB0ZXN0IENBMR0wGwYD"
-    "VQQLDBRTZWN1cml0eSBFbmdpbmVlcmluZzEvMC0GA1UEAwwmWFBDU2hlbGwgRVYg"
-    "VGVzdGluZyAodW50cnVzdHdvcnRoeSkgQ0E=",
-    "At+3zdo=",
-    nullptr
-  },
-#endif
-  {
-    // OU=Security Communication EV RootCA1,O="SECOM Trust Systems CO.,LTD.",C=JP
-    "1.2.392.200091.100.721.1",
-    "SECOM EV OID",
-    SEC_OID_UNKNOWN,
-    "FE:B8:C4:32:DC:F9:76:9A:CE:AE:3D:D8:90:8F:FD:28:86:65:64:7D",
-    "MGAxCzAJBgNVBAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENP"
-    "LixMVEQuMSowKAYDVQQLEyFTZWN1cml0eSBDb21tdW5pY2F0aW9uIEVWIFJvb3RD"
-    "QTE=",
-    "AA==",
-    nullptr
-  },
-  {
-    // CN=Cybertrust Global Root,O=Cybertrust, Inc
-    "1.3.6.1.4.1.6334.1.100.1",
-    "Cybertrust EV OID",
-    SEC_OID_UNKNOWN,
-    "5F:43:E5:B1:BF:F8:78:8C:AC:1C:C7:CA:4A:9A:C6:22:2B:CC:34:C6",
-    "MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVz"
-    "dCBHbG9iYWwgUm9vdA==",
-    "BAAAAAABD4WqLUg=",
-    nullptr
-  },
-  {
-    // CN=SwissSign Gold CA - G2,O=SwissSign AG,C=CH
-    "2.16.756.1.89.1.2.1.1",
-    "SwissSign EV OID",
-    SEC_OID_UNKNOWN,
-    "D8:C5:38:8A:B7:30:1B:1B:6E:D4:7A:E6:45:25:3A:6F:9F:1A:27:61",
-    "MEUxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMT"
-    "FlN3aXNzU2lnbiBHb2xkIENBIC0gRzI=",
-    "ALtAHEP1Xk+w",
-    nullptr
-  },
-  {
-    // CN=StartCom Certification Authority,OU=Secure Digital Certificate Signing,O=StartCom Ltd.,C=IL
-    "1.3.6.1.4.1.23223.1.1.1",
-    "StartCom EV OID",
-    SEC_OID_UNKNOWN,
-    "3E:2B:F7:F2:03:1B:96:F3:8C:E6:C4:D8:A8:5D:3E:2D:58:47:6A:0F",
-    "MH0xCzAJBgNVBAYTAklMMRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSswKQYDVQQL"
-    "EyJTZWN1cmUgRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTaWduaW5nMSkwJwYDVQQDEyBT"
-    "dGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==",
-    "AQ==",
-    nullptr
-  },
-  {
-    // CN=StartCom Certification Authority,OU=Secure Digital Certificate Signing,O=StartCom Ltd.,C=IL
-    "1.3.6.1.4.1.23223.1.1.1",
-    "StartCom EV OID",
-    SEC_OID_UNKNOWN,
-    "A3:F1:33:3F:E2:42:BF:CF:C5:D1:4E:8F:39:42:98:40:68:10:D1:A0",
-    "MH0xCzAJBgNVBAYTAklMMRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSswKQYDVQQL"
-    "EyJTZWN1cmUgRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTaWduaW5nMSkwJwYDVQQDEyBT"
-    "dGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==",
-    "LQ==",
-    nullptr
-  },
-  {
-    // CN=StartCom Certification Authority G2,O=StartCom Ltd.,C=IL
-    "1.3.6.1.4.1.23223.1.1.1",
-    "StartCom EV OID",
-    SEC_OID_UNKNOWN,
-    "31:F1:FD:68:22:63:20:EE:C6:3B:3F:9D:EA:4A:3E:53:7C:7C:39:17",
-    "MFMxCzAJBgNVBAYTAklMMRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSwwKgYDVQQD"
-    "EyNTdGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBHMg==",
-    "Ow==",
-    nullptr
-  },
-  {
-    // CN=VeriSign Class 3 Public Primary Certification Authority - G5,OU="(c) 2006 VeriSign, Inc. - For authorized use only",OU=VeriSign Trust Network,O="VeriSign, Inc.",C=US
-    "2.16.840.1.113733.1.7.23.6",
-    "VeriSign EV OID",
-    SEC_OID_UNKNOWN,
-    "4E:B6:D5:78:49:9B:1C:CF:5F:58:1E:AD:56:BE:3D:9B:67:44:A5:E5",
-    "MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNV"
-    "BAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA2IFZl"
-    "cmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMT"
-    "PFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBB"
-    "dXRob3JpdHkgLSBHNQ==",
-    "GNrRniZ96LtKIVjNzGs7Sg==",
-    nullptr
-  },
-  {
-    // CN=GeoTrust Primary Certification Authority,O=GeoTrust Inc.,C=US
-    "1.3.6.1.4.1.14370.1.6",
-    "GeoTrust EV OID",
-    SEC_OID_UNKNOWN,
-    "32:3C:11:8E:1B:F7:B8:B6:52:54:E2:E2:10:0D:D6:02:90:37:F0:96",
-    "MFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQD"
-    "EyhHZW9UcnVzdCBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5",
-    "GKy1av1pthU6Y2yv2vrEoQ==",
-    nullptr
-  },
-  {
-    // CN=thawte Primary Root CA,OU="(c) 2006 thawte, Inc. - For authorized use only",OU=Certification Services Division,O="thawte, Inc.",C=US
-    "2.16.840.1.113733.1.7.48.1",
-    "Thawte EV OID",
-    SEC_OID_UNKNOWN,
-    "91:C6:D6:EE:3E:8A:C8:63:84:E5:48:C2:99:29:5C:75:6C:81:7B:81",
-    "MIGpMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3RlLCBJbmMuMSgwJgYDVQQL"
-    "Ex9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYDVQQLEy8oYykg"
-    "MjAwNiB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0G"
-    "A1UEAxMWdGhhd3RlIFByaW1hcnkgUm9vdCBDQQ==",
-    "NE7VVyDV7exJ9C/ON9srbQ==",
-    nullptr
-  },
-  {
-    // CN=XRamp Global Certification Authority,O=XRamp Security Services Inc,OU=www.xrampsecurity.com,C=US
-    "2.16.840.1.114404.1.1.2.4.1",
-    "Trustwave EV OID",
-    SEC_OID_UNKNOWN,
-    "B8:01:86:D1:EB:9C:86:A5:41:04:CF:30:54:F3:4C:52:B7:E5:58:C6",
-    "MIGCMQswCQYDVQQGEwJVUzEeMBwGA1UECxMVd3d3LnhyYW1wc2VjdXJpdHkuY29t"
-    "MSQwIgYDVQQKExtYUmFtcCBTZWN1cml0eSBTZXJ2aWNlcyBJbmMxLTArBgNVBAMT"
-    "JFhSYW1wIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==",
-    "UJRs7Bjq1ZxN1ZfvdY+grQ==",
-    nullptr
-  },
-  {
-    // CN=SecureTrust CA,O=SecureTrust Corporation,C=US
-    "2.16.840.1.114404.1.1.2.4.1",
-    "Trustwave EV OID",
-    SEC_OID_UNKNOWN,
-    "87:82:C6:C3:04:35:3B:CF:D2:96:92:D2:59:3E:7D:44:D9:34:FF:11",
-    "MEgxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlv"
-    "bjEXMBUGA1UEAxMOU2VjdXJlVHJ1c3QgQ0E=",
-    "DPCOXAgWpa1Cf/DrJxhZ0A==",
-    nullptr
-  },
-  {
-    // CN=Secure Global CA,O=SecureTrust Corporation,C=US
-    "2.16.840.1.114404.1.1.2.4.1",
-    "Trustwave EV OID",
-    SEC_OID_UNKNOWN,
-    "3A:44:73:5A:E5:81:90:1F:24:86:61:46:1E:3B:9C:C4:5F:F5:3A:1B",
-    "MEoxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlv"
-    "bjEZMBcGA1UEAxMQU2VjdXJlIEdsb2JhbCBDQQ==",
-    "B1YipOjUiolN9BPI8PjqpQ==",
-    nullptr
-  },
-  {
-    // CN=COMODO ECC Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB
-    "1.3.6.1.4.1.6449.1.2.1.5.1",
-    "Comodo EV OID",
-    SEC_OID_UNKNOWN,
-    "9F:74:4E:9F:2B:4D:BA:EC:0F:31:2C:50:B6:56:3B:8E:2D:93:C3:11",
-    "MIGFMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAw"
-    "DgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDErMCkG"
-    "A1UEAxMiQ09NT0RPIEVDQyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==",
-    "H0evqmIAcFBUTAGem2OZKg==",
-    nullptr
-  },
-  {
-    // CN=COMODO Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB
-    "1.3.6.1.4.1.6449.1.2.1.5.1",
-    "Comodo EV OID",
-    SEC_OID_UNKNOWN,
-    "66:31:BF:9E:F7:4F:9E:B6:C9:D5:A6:0C:BA:6A:BE:D1:F7:BD:EF:7B",
-    "MIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAw"
-    "DgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEnMCUG"
-    "A1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5",
-    "ToEtioJl4AsC7j41AkblPQ==",
-    nullptr
-  },
-  {
-    // CN=AddTrust External CA Root,OU=AddTrust External TTP Network,O=AddTrust AB,C=SE
-    "1.3.6.1.4.1.6449.1.2.1.5.1",
-    "Comodo EV OID",
-    SEC_OID_UNKNOWN,
-    "02:FA:F3:E2:91:43:54:68:60:78:57:69:4D:F5:E4:5B:68:85:18:68",
-    "MG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMd"
-    "QWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0"
-    "IEV4dGVybmFsIENBIFJvb3Q=",
-    "AQ==",
-    nullptr
-  },
-  {
-    // CN=UTN - DATACorp SGC,OU=http://www.usertrust.com,O=The USERTRUST Network,L=Salt Lake City,ST=UT,C=US
-    "1.3.6.1.4.1.6449.1.2.1.5.1",
-    "Comodo EV OID",
-    SEC_OID_UNKNOWN,
-    "58:11:9F:0E:12:82:87:EA:50:FD:D9:87:45:6F:4F:78:DC:FA:D6:D4",
-    "MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFr"
-    "ZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsT"
-    "GGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNv"
-    "cnAgU0dD",
-    "RL4Mi1AAIbQR0ypoBqmtaQ==",
-    nullptr
-  },
-  {
-    // CN=UTN-USERFirst-Hardware,OU=http://www.usertrust.com,O=The USERTRUST Network,L=Salt Lake City,ST=UT,C=US
-    "1.3.6.1.4.1.6449.1.2.1.5.1",
-    "Comodo EV OID",
-    SEC_OID_UNKNOWN,
-    "04:83:ED:33:99:AC:36:08:05:87:22:ED:BC:5E:46:00:E3:BE:F9:D7",
-    "MIGXMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFr"
-    "ZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsT"
-    "GGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEfMB0GA1UEAxMWVVROLVVTRVJGaXJz"
-    "dC1IYXJkd2FyZQ==",
-    "RL4Mi1AAJLQR0zYq/mUK/Q==",
-    nullptr
-  },
-  {
-    // OU=Go Daddy Class 2 Certification Authority,O=\"The Go Daddy Group, Inc.\",C=US
-    "2.16.840.1.114413.1.7.23.3",
-    "Go Daddy EV OID a",
-    SEC_OID_UNKNOWN,
-    "27:96:BA:E6:3F:18:01:E2:77:26:1B:A0:D7:77:70:02:8F:20:EE:E4",
-    "MGMxCzAJBgNVBAYTAlVTMSEwHwYDVQQKExhUaGUgR28gRGFkZHkgR3JvdXAsIElu"
-    "Yy4xMTAvBgNVBAsTKEdvIERhZGR5IENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRo"
-    "b3JpdHk=",
-    "AA==",
-    nullptr
-  },
-  {
-    // CN=Go Daddy Root Certificate Authority - G2,O="GoDaddy.com, Inc.",L=Scottsdale,ST=Arizona,C=US
-    "2.16.840.1.114413.1.7.23.3",
-    "Go Daddy EV OID a",
-    SEC_OID_UNKNOWN,
-    "47:BE:AB:C9:22:EA:E8:0E:78:78:34:62:A7:9F:45:C2:54:FD:E6:8B",
-    "MIGDMQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2Nv"
-    "dHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4xMTAvBgNVBAMTKEdv"
-    "IERhZGR5IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzI=",
-    "AA==",
-    nullptr
-  },
-  {
-    // E=info@valicert.com,CN=http://www.valicert.com/,OU=ValiCert Class 2 Policy Validation Authority,O=\"ValiCert, Inc.\",L=ValiCert Validation Network
-    "2.16.840.1.114413.1.7.23.3",
-    "Go Daddy EV OID a",
-    SEC_OID_UNKNOWN,
-    "31:7A:2A:D0:7F:2B:33:5E:F5:A1:C3:4E:4B:57:E8:B7:D8:F1:FC:A6",
-    "MIG7MSQwIgYDVQQHExtWYWxpQ2VydCBWYWxpZGF0aW9uIE5ldHdvcmsxFzAVBgNV"
-    "BAoTDlZhbGlDZXJ0LCBJbmMuMTUwMwYDVQQLEyxWYWxpQ2VydCBDbGFzcyAyIFBv"
-    "bGljeSBWYWxpZGF0aW9uIEF1dGhvcml0eTEhMB8GA1UEAxMYaHR0cDovL3d3dy52"
-    "YWxpY2VydC5jb20vMSAwHgYJKoZIhvcNAQkBFhFpbmZvQHZhbGljZXJ0LmNvbQ==",
-    "AQ==",
-    nullptr
-  },
-  {
-    // E=info@valicert.com,CN=http://www.valicert.com/,OU=ValiCert Class 2 Policy Validation Authority,O=\"ValiCert, Inc.\",L=ValiCert Validation Network
-    "2.16.840.1.114414.1.7.23.3",
-    "Go Daddy EV OID b",
-    SEC_OID_UNKNOWN,
-    "31:7A:2A:D0:7F:2B:33:5E:F5:A1:C3:4E:4B:57:E8:B7:D8:F1:FC:A6",
-    "MIG7MSQwIgYDVQQHExtWYWxpQ2VydCBWYWxpZGF0aW9uIE5ldHdvcmsxFzAVBgNV"
-    "BAoTDlZhbGlDZXJ0LCBJbmMuMTUwMwYDVQQLEyxWYWxpQ2VydCBDbGFzcyAyIFBv"
-    "bGljeSBWYWxpZGF0aW9uIEF1dGhvcml0eTEhMB8GA1UEAxMYaHR0cDovL3d3dy52"
-    "YWxpY2VydC5jb20vMSAwHgYJKoZIhvcNAQkBFhFpbmZvQHZhbGljZXJ0LmNvbQ==",
-    "AQ==",
-    nullptr
-  },
-  {
-    // OU=Starfield Class 2 Certification Authority,O=\"Starfield Technologies, Inc.\",C=US
-    "2.16.840.1.114414.1.7.23.3",
-    "Go Daddy EV OID b",
-    SEC_OID_UNKNOWN,
-    "AD:7E:1C:28:B0:64:EF:8F:60:03:40:20:14:C3:D0:E3:37:0E:B5:8A",
-    "MGgxCzAJBgNVBAYTAlVTMSUwIwYDVQQKExxTdGFyZmllbGQgVGVjaG5vbG9naWVz"
-    "LCBJbmMuMTIwMAYDVQQLEylTdGFyZmllbGQgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9u"
-    "IEF1dGhvcml0eQ==",
-    "AA==",
-    nullptr
-  },
-  {
-    // CN=Starfield Root Certificate Authority - G2,O="Starfield Technologies, Inc.",L=Scottsdale,ST=Arizona,C=US
-    "2.16.840.1.114414.1.7.23.3",
-    "Go Daddy EV OID b",
-    SEC_OID_UNKNOWN,
-    "B5:1C:06:7C:EE:2B:0C:3D:F8:55:AB:2D:92:F4:FE:39:D4:E7:0F:0E",
-    "MIGPMQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2Nv"
-    "dHRzZGFsZTElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEy"
-    "MDAGA1UEAxMpU3RhcmZpZWxkIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0g"
-    "RzI=",
-    "AA==",
-    nullptr
-  },
-  {
-    // CN=DigiCert High Assurance EV Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US
-    "2.16.840.1.114412.2.1",
-    "DigiCert EV OID",
-    SEC_OID_UNKNOWN,
-    "5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25",
-    "MGwxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsT"
-    "EHd3dy5kaWdpY2VydC5jb20xKzApBgNVBAMTIkRpZ2lDZXJ0IEhpZ2ggQXNzdXJh"
-    "bmNlIEVWIFJvb3QgQ0E=",
-    "AqxcJmoLQJuPC3nyrkYldw==",
-    nullptr
-  },
-  {
-    // CN=QuoVadis Root CA 2,O=QuoVadis Limited,C=BM
-    "1.3.6.1.4.1.8024.0.2.100.1.2",
-    "Quo Vadis EV OID",
-    SEC_OID_UNKNOWN,
-    "CA:3A:FB:CF:12:40:36:4B:44:B2:16:20:88:80:48:39:19:93:7C:F7",
-    "MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYD"
-    "VQQDExJRdW9WYWRpcyBSb290IENBIDI=",
-    "BQk=",
-    nullptr
-  },
-  {
-    // CN=Network Solutions Certificate Authority,O=Network Solutions L.L.C.,C=US
-    "1.3.6.1.4.1.782.1.2.1.8.1",
-    "Network Solutions EV OID",
-    SEC_OID_UNKNOWN,
-    "74:F8:A3:C3:EF:E7:B3:90:06:4B:83:90:3C:21:64:60:20:E5:DF:CE",
-    "MGIxCzAJBgNVBAYTAlVTMSEwHwYDVQQKExhOZXR3b3JrIFNvbHV0aW9ucyBMLkwu"
-    "Qy4xMDAuBgNVBAMTJ05ldHdvcmsgU29sdXRpb25zIENlcnRpZmljYXRlIEF1dGhv"
-    "cml0eQ==",
-    "V8szb8JcFuZHFhfjkDFo4A==",
-    nullptr
-  },
-  {
-    // CN=Entrust Root Certification Authority,OU="(c) 2006 Entrust, Inc.",OU=www.entrust.net/CPS is incorporated by reference,O="Entrust, Inc.",C=US
-    "2.16.840.1.114028.10.1.2",
-    "Entrust EV OID",
-    SEC_OID_UNKNOWN,
-    "B3:1E:B1:B7:40:E3:6C:84:02:DA:DC:37:D4:4D:F5:D4:67:49:52:F9",
-    "MIGwMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNRW50cnVzdCwgSW5jLjE5MDcGA1UE"
-    "CxMwd3d3LmVudHJ1c3QubmV0L0NQUyBpcyBpbmNvcnBvcmF0ZWQgYnkgcmVmZXJl"
-    "bmNlMR8wHQYDVQQLExYoYykgMjAwNiBFbnRydXN0LCBJbmMuMS0wKwYDVQQDEyRF"
-    "bnRydXN0IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHk=",
-    "RWtQVA==",
-    nullptr
-  },
-  {
-    // CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE
-    "1.3.6.1.4.1.4146.1.1",
-    "GlobalSign EV OID",
-    SEC_OID_UNKNOWN,
-    "B1:BC:96:8B:D4:F4:9D:62:2A:A8:9A:81:F2:15:01:52:A4:1D:82:9C",
-    "MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYD"
-    "VQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=",
-    "BAAAAAABFUtaw5Q=",
-    nullptr
-  },
-  {
-    // CN=GlobalSign,O=GlobalSign,OU=GlobalSign Root CA - R2
-    "1.3.6.1.4.1.4146.1.1",
-    "GlobalSign EV OID",
-    SEC_OID_UNKNOWN,
-    "75:E0:AB:B6:13:85:12:27:1C:04:F8:5F:DD:DE:38:E4:B7:24:2E:FE",
-    "MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpH"
-    "bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu",
-    "BAAAAAABD4Ym5g0=",
-    nullptr
-  },
-  {
-    // CN=GlobalSign,O=GlobalSign,OU=GlobalSign Root CA - R3
-    "1.3.6.1.4.1.4146.1.1",
-    "GlobalSign EV OID",
-    SEC_OID_UNKNOWN,
-    "D6:9B:56:11:48:F0:1C:77:C5:45:78:C1:09:26:DF:5B:85:69:76:AD",
-    "MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpH"
-    "bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu",
-    "BAAAAAABIVhTCKI=",
-    nullptr
-  },
-  {
-    // CN=Buypass Class 3 CA 1,O=Buypass AS-983163327,C=NO
-    "2.16.578.1.26.1.3.3",
-    "Buypass EV OID",
-    SEC_OID_UNKNOWN,
-    "61:57:3A:11:DF:0E:D8:7E:D5:92:65:22:EA:D0:56:D7:44:B3:23:71",
-    "MEsxCzAJBgNVBAYTAk5PMR0wGwYDVQQKDBRCdXlwYXNzIEFTLTk4MzE2MzMyNzEd"
-    "MBsGA1UEAwwUQnV5cGFzcyBDbGFzcyAzIENBIDE=",
-    "Ag==",
-    nullptr
-  },
-  {
-    // CN=Buypass Class 3 Root CA,O=Buypass AS-983163327,C=NO
-    "2.16.578.1.26.1.3.3",
-    "Buypass EV OID",
-    SEC_OID_UNKNOWN,
-    "DA:FA:F7:FA:66:84:EC:06:8F:14:50:BD:C7:C2:81:A5:BC:A9:64:57",
-    "ME4xCzAJBgNVBAYTAk5PMR0wGwYDVQQKDBRCdXlwYXNzIEFTLTk4MzE2MzMyNzEg"
-    "MB4GA1UEAwwXQnV5cGFzcyBDbGFzcyAzIFJvb3QgQ0E=",
-    "Ag==",
-    nullptr
-  },
-  {
-    // CN=Class 2 Primary CA,O=Certplus,C=FR
-    "1.3.6.1.4.1.22234.2.5.2.3.1",
-    "Certplus EV OID",
-    SEC_OID_UNKNOWN,
-    "74:20:74:41:72:9C:DD:92:EC:79:31:D8:23:10:8D:C2:81:92:E2:BB",
-    "MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xh"
-    "c3MgMiBQcmltYXJ5IENB",
-    "AIW9S/PY2uNp9pTXX8OlRCM=",
-    nullptr
-  },
-  {
-    // CN=Chambers of Commerce Root - 2008,O=AC Camerfirma S.A.,serialNumber=A82743287,L=Madrid (see current address at www.camerfirma.com/address),C=EU
-    "1.3.6.1.4.1.17326.10.14.2.1.2",
-    "Camerfirma EV OID a",
-    SEC_OID_UNKNOWN,
-    "78:6A:74:AC:76:AB:14:7F:9C:6A:30:50:BA:9E:A8:7E:FE:9A:CE:3C",
-    "MIGuMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBh"
-    "ZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ"
-    "QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMT"
-    "IENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4",
-    "AKPaQn6ksa7a",
-    nullptr
-  },
-  {
-    // CN=Global Chambersign Root - 2008,O=AC Camerfirma S.A.,serialNumber=A82743287,L=Madrid (see current address at www.camerfirma.com/address),C=EU
-    "1.3.6.1.4.1.17326.10.8.12.1.2",
-    "Camerfirma EV OID b",
-    SEC_OID_UNKNOWN,
-    "4A:BD:EE:EC:95:0D:35:9C:89:AE:C7:52:A1:2C:5B:29:F6:D6:AA:0C",
-    "MIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBh"
-    "ZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ"
-    "QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMT"
-    "Hkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwOA==",
-    "AMnN0+nVfSPO",
-    nullptr
-  },
-  {
-    // CN=TC TrustCenter Universal CA III,OU=TC TrustCenter Universal CA,O=TC TrustCenter GmbH,C=DE
-    "1.2.276.0.44.1.1.1.4",
-    "TC TrustCenter EV OID",
-    SEC_OID_UNKNOWN,
-    "96:56:CD:7B:57:96:98:95:D0:E1:41:46:68:06:FB:B8:C6:11:06:87",
-    "MHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNUQyBUcnVzdENlbnRlciBHbWJIMSQw"
-    "IgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0ExKDAmBgNVBAMTH1RD"
-    "IFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUk=",
-    "YyUAAQACFI0zFQLkbPQ=",
-    nullptr
-  },
-  {
-    // CN=AffirmTrust Commercial,O=AffirmTrust,C=US
-    "1.3.6.1.4.1.34697.2.1",
-    "AffirmTrust EV OID a",
-    SEC_OID_UNKNOWN,
-    "F9:B5:B6:32:45:5F:9C:BE:EC:57:5F:80:DC:E9:6E:2C:C7:B2:78:B7",
-    "MEQxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEfMB0GA1UEAwwW"
-    "QWZmaXJtVHJ1c3QgQ29tbWVyY2lhbA==",
-    "d3cGJyapsXw=",
-    nullptr
-  },
-  {
-    // CN=AffirmTrust Networking,O=AffirmTrust,C=US
-    "1.3.6.1.4.1.34697.2.2",
-    "AffirmTrust EV OID b",
-    SEC_OID_UNKNOWN,
-    "29:36:21:02:8B:20:ED:02:F5:66:C5:32:D1:D6:ED:90:9F:45:00:2F",
-    "MEQxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEfMB0GA1UEAwwW"
-    "QWZmaXJtVHJ1c3QgTmV0d29ya2luZw==",
-    "fE8EORzUmS0=",
-    nullptr
-  },
-  {
-    // CN=AffirmTrust Premium,O=AffirmTrust,C=US
-    "1.3.6.1.4.1.34697.2.3",
-    "AffirmTrust EV OID c",
-    SEC_OID_UNKNOWN,
-    "D8:A6:33:2C:E0:03:6F:B1:85:F6:63:4F:7D:6A:06:65:26:32:28:27",
-    "MEExCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEcMBoGA1UEAwwT"
-    "QWZmaXJtVHJ1c3QgUHJlbWl1bQ==",
-    "bYwURrGmCu4=",
-    nullptr
-  },
-  {
-    // CN=AffirmTrust Premium ECC,O=AffirmTrust,C=US
-    "1.3.6.1.4.1.34697.2.4",
-    "AffirmTrust EV OID d",
-    SEC_OID_UNKNOWN,
-    "B8:23:6B:00:2F:1D:16:86:53:01:55:6C:11:A4:37:CA:EB:FF:C3:BB",
-    "MEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwX"
-    "QWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0M=",
-    "dJclisc/elQ=",
-    nullptr
-  },
-  {
-    // CN=Certum Trusted Network CA,OU=Certum Certification Authority,O=Unizeto Technologies S.A.,C=PL
-    "1.2.616.1.113527.2.5.1.1",
-    "Certum EV OID",
-    SEC_OID_UNKNOWN,
-    "07:E0:32:E0:20:B7:2C:3F:19:2F:06:28:A2:59:3A:19:A7:0F:06:9E",
-    "MH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBT"
-    "LkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAg"
-    "BgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0E=",
-    "BETA",
-    nullptr
-  },
-  {
-    // CN=Izenpe.com,O=IZENPE S.A.,C=ES
-    "1.3.6.1.4.1.14777.6.1.1",
-    "Izenpe EV OID 1",
-    SEC_OID_UNKNOWN,
-    "2F:78:3D:25:52:18:A7:4A:65:39:71:B5:2C:A2:9C:45:15:6F:E9:19",
-    "MDgxCzAJBgNVBAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwK"
-    "SXplbnBlLmNvbQ==",
-    "ALC3WhZIX7/hy/WL1xnmfQ==",
-    nullptr
-  },
-  {
-    // CN=Izenpe.com,O=IZENPE S.A.,C=ES
-    "1.3.6.1.4.1.14777.6.1.2",
-    "Izenpe EV OID 2",
-    SEC_OID_UNKNOWN,
-    "2F:78:3D:25:52:18:A7:4A:65:39:71:B5:2C:A2:9C:45:15:6F:E9:19",
-    "MDgxCzAJBgNVBAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwK"
-    "SXplbnBlLmNvbQ==",
-    "ALC3WhZIX7/hy/WL1xnmfQ==",
-    nullptr
-  },
-  {
-    // CN=A-Trust-nQual-03,OU=A-Trust-nQual-03,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT
-    "1.2.40.0.17.1.22",
-    "A-Trust EV OID",
-    SEC_OID_UNKNOWN,
-    "D3:C0:63:F2:19:ED:07:3E:34:AD:5D:75:0B:32:76:29:FF:D5:9A:F2",
-    "MIGNMQswCQYDVQQGEwJBVDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hl"
-    "cmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMRkwFwYD"
-    "VQQLDBBBLVRydXN0LW5RdWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5RdWFsLTAz",
-    "AWwe",
-    nullptr
-  },
-  {
-    // CN=T-TeleSec GlobalRoot Class 3,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE
-    "1.3.6.1.4.1.7879.13.24.1",
-    "T-Systems EV OID",
-    SEC_OID_UNKNOWN,
-    "55:A6:72:3E:CB:F2:EC:CD:C3:23:74:70:19:9D:2A:BE:11:E3:81:D1",
-    "MIGCMQswCQYDVQQGEwJERTErMCkGA1UECgwiVC1TeXN0ZW1zIEVudGVycHJpc2Ug"
-    "U2VydmljZXMgR21iSDEfMB0GA1UECwwWVC1TeXN0ZW1zIFRydXN0IENlbnRlcjEl"
-    "MCMGA1UEAwwcVC1UZWxlU2VjIEdsb2JhbFJvb3QgQ2xhc3MgMw==",
-    "AQ==",
-    nullptr
-  },
-  {
-    // CN=TURKTRUST Elektronik Sertifika Hizmet Saglayicisi,O=TURKTRUST Bilgi Illetisim ve Bilisim Guvenligi Hizmetleri A.S.,C=TR
-    "2.16.792.3.0.3.1.1.5",
-    "TurkTrust EV OID",
-    SEC_OID_UNKNOWN,
-    "F1:7F:6F:B6:31:DC:99:E3:A3:C8:7F:FE:1C:F1:81:10:88:D9:60:33",
-    "MIG/MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU2VydGlmaWthIEhp"
-    "em1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmth"
-    "cmExXjBcBgNVBAoMVVTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBCaWxp"
-    "xZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEuxZ4uIChjKSBBcmFsxLFrIDIw"
-    "MDc=",
-    "AQ==",
-    nullptr
-  },
-  {
-    // CN=China Internet Network Information Center EV Certificates Root,O=China Internet Network Information Center,C=CN
-    "1.3.6.1.4.1.29836.1.10",
-    "CNNIC EV OID",
-    SEC_OID_UNKNOWN,
-    "4F:99:AA:93:FB:2B:D1:37:26:A1:99:4A:CE:7F:F0:05:F2:93:5D:1E",
-    "MIGKMQswCQYDVQQGEwJDTjEyMDAGA1UECgwpQ2hpbmEgSW50ZXJuZXQgTmV0d29y"
-    "ayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMMPkNoaW5hIEludGVybmV0IE5l"
-    "dHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRpZmljYXRlcyBSb290",
-    "SJ8AAQ==",
-    nullptr
-  },
-  {
-    // CN=TWCA Root Certification Authority,OU=Root CA,O=TAIWAN-CA,C=TW
-    "1.3.6.1.4.1.40869.1.1.22.3",
-    "TWCA EV OID",
-    SEC_OID_UNKNOWN,
-    "CF:9E:87:6D:D3:EB:FC:42:26:97:A3:B5:A3:7A:A0:76:A9:06:23:48",
-    "MF8xCzAJBgNVBAYTAlRXMRIwEAYDVQQKDAlUQUlXQU4tQ0ExEDAOBgNVBAsMB1Jv"
-    "b3QgQ0ExKjAoBgNVBAMMIVRXQ0EgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0"
-    "eQ==",
-    "AQ==",
-    nullptr
-  },
-  {
-    // CN=D-TRUST Root Class 3 CA 2 EV 2009,O=D-Trust GmbH,C=DE
-    "1.3.6.1.4.1.4788.2.202.1",
-    "D-TRUST EV OID",
-    SEC_OID_UNKNOWN,
-    "96:C9:1B:0B:95:B4:10:98:42:FA:D0:D8:22:79:FE:60:FA:B9:16:83",
-    "MFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMM"
-    "IUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOQ==",
-    "CYP0",
-    nullptr
-  },
-  {
-    // CN=Swisscom Root EV CA 2,OU=Digital Certificate Services,O=Swisscom,C=ch
-    "2.16.756.1.83.21.0",
-    "Swisscom  EV OID",
-    SEC_OID_UNKNOWN,
-    "E7:A1:90:29:D3:D5:52:DC:0D:0F:C6:92:D3:EA:88:0D:15:2E:1A:6B",
-    "MGcxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln"
-    "aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEeMBwGA1UEAxMVU3dpc3Njb20gUm9v"
-    "dCBFViBDQSAy",
-    "APL6ZOJ0Y9ON/RAdBB92ylg=",
-    nullptr
-  },
-  {
-    // CN=VeriSign Universal Root Certification Authority,OU="(c) 2008 VeriSign, Inc. - For authorized use only",OU=VeriSign Trust Network,O="VeriSign, Inc.",C=US
-    "2.16.840.1.113733.1.7.23.6",
-    "VeriSign EV OID",
-    SEC_OID_UNKNOWN,
-    "36:79:CA:35:66:87:72:30:4D:30:A5:FB:87:3B:0F:A7:7B:B7:0D:54",
-    "MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNV"
-    "BAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZl"
-    "cmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMT"
-    "L1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5",
-    "QBrEZCGzEyEDDrvkEhrFHQ==",
-    nullptr
-  },
-  {
-    // CN=GeoTrust Primary Certification Authority - G3,OU=(c) 2008 GeoTrust Inc. - For authorized use only,O=GeoTrust Inc.,C=US
-    "1.3.6.1.4.1.14370.1.6",
-    "GeoTrust EV OID",
-    SEC_OID_UNKNOWN,
-    "03:9E:ED:B8:0B:E7:A0:3C:69:53:89:3B:20:D2:D9:32:3A:4C:2A:FD",
-    "MIGYMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjE5MDcGA1UE"
-    "CxMwKGMpIDIwMDggR2VvVHJ1c3QgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBv"
-    "bmx5MTYwNAYDVQQDEy1HZW9UcnVzdCBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0"
-    "aG9yaXR5IC0gRzM=",
-    "FaxulBmyeUtB9iepwxgPHw==",
-    nullptr
-  },
-  {
-    // CN=thawte Primary Root CA - G3,OU="(c) 2008 thawte, Inc. - For authorized use only",OU=Certification Services Division,O="thawte, Inc.",C=US
-    "2.16.840.1.113733.1.7.48.1",
-    "Thawte EV OID",
-    SEC_OID_UNKNOWN,
-    "F1:8B:53:8D:1B:E9:03:B6:A6:F0:56:43:5B:17:15:89:CA:F3:6B:F2",
-    "MIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3RlLCBJbmMuMSgwJgYDVQQL"
-    "Ex9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYDVQQLEy8oYykg"
-    "MjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG"
-    "A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz",
-    "YAGXt0an6rS0mtZLL/eQ+w==",
-    nullptr
-  },
-  {
-    // OU=Sample Certification Authority,O=\"Sample, Inc.\",C=US
-    "0.0.0.0",
-    0, // for real entries use a string like "Sample INVALID EV OID"
-    SEC_OID_UNKNOWN,
-    "00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33", //UPPERCASE!
-    "Cg==",
-    "Cg==",
-    nullptr
-  }
-};
-
-static SECOidTag
-register_oid(const SECItem* oid_item, const char* oid_name)
-{
-  if (!oid_item)
-    return SEC_OID_UNKNOWN;
-
-  SECOidData od;
-  od.oid.len = oid_item->len;
-  od.oid.data = oid_item->data;
-  od.offset = SEC_OID_UNKNOWN;
-  od.desc = oid_name;
-  od.mechanism = CKM_INVALID_MECHANISM;
-  od.supportedExtension = INVALID_CERT_EXTENSION;
-  return SECOID_AddEntry(&od);
-}
-
-static void
-addToCertListIfTrusted(CERTCertList* certList, CERTCertificate* cert) {
-  CERTCertTrust nssTrust;
-  if (CERT_GetCertTrust(cert, &nssTrust) != SECSuccess) {
-    return;
-  }
-  unsigned int flags = SEC_GET_TRUST_FLAGS(&nssTrust, trustSSL);
-
-  if (flags & CERTDB_TRUSTED_CA) {
-    CERT_AddCertToListTail(certList, CERT_DupCertificate(cert));
-  }
-}
-
-#ifdef PSM_ENABLE_TEST_EV_ROOTS
-class nsMyTrustedEVInfoClass : public nsMyTrustedEVInfo
-{
-public:
-  nsMyTrustedEVInfoClass();
-  ~nsMyTrustedEVInfoClass();
-};
-
-nsMyTrustedEVInfoClass::nsMyTrustedEVInfoClass()
-{
-  dotted_oid = nullptr;
-  oid_name = nullptr;
-  oid_tag = SEC_OID_UNKNOWN;
-  ev_root_sha1_fingerprint = nullptr;
-  issuer_base64 = nullptr;
-  serial_base64 = nullptr;
-  cert = nullptr;
-}
-
-nsMyTrustedEVInfoClass::~nsMyTrustedEVInfoClass()
-{
-  // Cast away const-ness in order to free these strings
-  free(const_cast<char*>(dotted_oid));
-  free(const_cast<char*>(oid_name));
-  free(const_cast<char*>(ev_root_sha1_fingerprint));
-  free(const_cast<char*>(issuer_base64));
-  free(const_cast<char*>(serial_base64));
-  if (cert)
-    CERT_DestroyCertificate(cert);
-}
-
-typedef nsTArray<nsMyTrustedEVInfoClass*> testEVArray;
-static testEVArray* testEVInfos;
-static bool testEVInfosLoaded = false;
-#endif
-
-#ifdef PSM_ENABLE_TEST_EV_ROOTS
-static const char kTestEVRootsFileName[] = "test_ev_roots.txt";
-
-static void
-loadTestEVInfos()
-{
-  if (!testEVInfos)
-    return;
-
-  testEVInfos->Clear();
-
-  char* env_val = getenv("ENABLE_TEST_EV_ROOTS_FILE");
-  if (!env_val)
-    return;
-
-  int enabled_val = atoi(env_val);
-  if (!enabled_val)
-    return;
-
-  nsCOMPtr<nsIFile> aFile;
-  NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(aFile));
-  if (!aFile)
-    return;
-
-  aFile->AppendNative(NS_LITERAL_CSTRING(kTestEVRootsFileName));
-
-  nsresult rv;
-  nsCOMPtr<nsIInputStream> fileInputStream;
-  rv = NS_NewLocalFileInputStream(getter_AddRefs(fileInputStream), aFile);
-  if (NS_FAILED(rv))
-    return;
-
-  nsCOMPtr<nsILineInputStream> lineInputStream =
-      do_QueryInterface(fileInputStream, &rv);
-  if (NS_FAILED(rv))
-    return;
-
-  nsAutoCString buffer;
-  bool isMore = true;
-
-  // file format
-  //
-  // file format must be strictly followed
-  // strings in file must be UTF-8
-  // each record consists of multiple lines
-  // each line consists of a descriptor, a single space, and the data
-  // the descriptors are:
-  //   1_fingerprint (in format XX:XX:XX:...)
-  //   2_readable_oid (treated as a comment)
-  // the input file must strictly follow this order
-  // the input file may contain 0, 1 or many records
-  // completely empty lines are ignored
-  // lines that start with the # char are ignored
-
-  int line_counter = 0;
-  bool found_error = false;
-
-  enum {
-    pos_fingerprint, pos_readable_oid, pos_issuer, pos_serial
-  } reader_position = pos_fingerprint;
-
-  nsCString fingerprint, readable_oid, issuer, serial;
-
-  while (isMore && NS_SUCCEEDED(lineInputStream->ReadLine(buffer, &isMore))) {
-    ++line_counter;
-    if (buffer.IsEmpty() || buffer.First() == '#') {
-      continue;
-    }
-
-    int32_t seperatorIndex = buffer.FindChar(' ', 0);
-    if (seperatorIndex == 0) {
-      found_error = true;
-      break;
-    }
-
-    const nsASingleFragmentCString& descriptor =
-            Substring(buffer, 0, seperatorIndex);
-    const nsASingleFragmentCString& data =
-            Substring(buffer, seperatorIndex + 1,
-                      buffer.Length() - seperatorIndex + 1);
-
-    if (reader_position == pos_fingerprint &&
-        descriptor.EqualsLiteral(("1_fingerprint"))) {
-      fingerprint = data;
-      reader_position = pos_readable_oid;
-      continue;
-    }
-    else if (reader_position == pos_readable_oid &&
-        descriptor.EqualsLiteral(("2_readable_oid"))) {
-      readable_oid = data;
-      reader_position = pos_issuer;
-      continue;
-    }
-    else if (reader_position == pos_issuer &&
-        descriptor.EqualsLiteral(("3_issuer"))) {
-      issuer = data;
-      reader_position = pos_serial;
-      continue;
-    }
-    else if (reader_position == pos_serial &&
-        descriptor.EqualsLiteral(("4_serial"))) {
-      serial = data;
-      reader_position = pos_fingerprint;
-    }
-    else {
-      found_error = true;
-      break;
-    }
-
-    nsMyTrustedEVInfoClass* temp_ev = new nsMyTrustedEVInfoClass;
-    if (!temp_ev)
-      return;
-
-    temp_ev->ev_root_sha1_fingerprint = strdup(fingerprint.get());
-    temp_ev->oid_name = strdup(readable_oid.get());
-    temp_ev->dotted_oid = strdup(readable_oid.get());
-    temp_ev->issuer_base64 = strdup(issuer.get());
-    temp_ev->serial_base64 = strdup(serial.get());
-
-    SECStatus rv;
-    CERTIssuerAndSN ias;
-
-    rv = ATOB_ConvertAsciiToItem(&ias.derIssuer, const_cast<char*>(temp_ev->issuer_base64));
-    NS_ASSERTION(rv==SECSuccess, "error converting ascii to binary.");
-    rv = ATOB_ConvertAsciiToItem(&ias.serialNumber, const_cast<char*>(temp_ev->serial_base64));
-    NS_ASSERTION(rv==SECSuccess, "error converting ascii to binary.");
-
-    temp_ev->cert = CERT_FindCertByIssuerAndSN(nullptr, &ias);
-    NS_ASSERTION(temp_ev->cert, "Could not find EV root in NSS storage");
-
-    SECITEM_FreeItem(&ias.derIssuer, false);
-    SECITEM_FreeItem(&ias.serialNumber, false);
-
-    if (!temp_ev->cert)
-      return;
-
-    nsNSSCertificate c(temp_ev->cert);
-    nsAutoString fingerprint;
-    c.GetSha1Fingerprint(fingerprint);
-
-    NS_ConvertASCIItoUTF16 sha1(temp_ev->ev_root_sha1_fingerprint);
-
-    if (sha1 != fingerprint) {
-      NS_ASSERTION(sha1 == fingerprint, "found EV root with unexpected SHA1 mismatch");
-      CERT_DestroyCertificate(temp_ev->cert);
-      temp_ev->cert = nullptr;
-      return;
-    }
-
-    SECItem ev_oid_item;
-    ev_oid_item.data = nullptr;
-    ev_oid_item.len = 0;
-    SECStatus srv = SEC_StringToOID(nullptr, &ev_oid_item,
-                                    readable_oid.get(), readable_oid.Length());
-    if (srv != SECSuccess) {
-      delete temp_ev;
-      found_error = true;
-      break;
-    }
-
-    temp_ev->oid_tag = register_oid(&ev_oid_item, temp_ev->oid_name);
-    SECITEM_FreeItem(&ev_oid_item, false);
-
-    testEVInfos->AppendElement(temp_ev);
-  }
-
-  if (found_error) {
-    fprintf(stderr, "invalid line %d in test_ev_roots file\n", line_counter);
-  }
-}
-
-static bool
-isEVPolicyInExternalDebugRootsFile(SECOidTag policyOIDTag)
-{
-  if (!testEVInfos)
-    return false;
-
-  char* env_val = getenv("ENABLE_TEST_EV_ROOTS_FILE");
-  if (!env_val)
-    return false;
-
-  int enabled_val = atoi(env_val);
-  if (!enabled_val)
-    return false;
-
-  for (size_t i=0; i<testEVInfos->Length(); ++i) {
-    nsMyTrustedEVInfoClass* ev = testEVInfos->ElementAt(i);
-    if (!ev)
-      continue;
-    if (policyOIDTag == ev->oid_tag)
-      return true;
-  }
-
-  return false;
-}
-
-static bool
-getRootsForOidFromExternalRootsFile(CERTCertList* certList,
-                                    SECOidTag policyOIDTag)
-{
-  if (!testEVInfos)
-    return false;
-
-  char* env_val = getenv("ENABLE_TEST_EV_ROOTS_FILE");
-  if (!env_val)
-    return false;
-
-  int enabled_val = atoi(env_val);
-  if (!enabled_val)
-    return false;
-
-  for (size_t i=0; i<testEVInfos->Length(); ++i) {
-    nsMyTrustedEVInfoClass* ev = testEVInfos->ElementAt(i);
-    if (!ev)
-      continue;
-    if (policyOIDTag == ev->oid_tag) {
-      addToCertListIfTrusted(certList, ev->cert);
-    }
-  }
-
-  return false;
-}
-#endif
-
-static bool
-isEVPolicy(SECOidTag policyOIDTag)
-{
-  for (size_t iEV=0; iEV < (sizeof(myTrustedEVInfos)/sizeof(nsMyTrustedEVInfo)); ++iEV) {
-    nsMyTrustedEVInfo& entry = myTrustedEVInfos[iEV];
-    if (!entry.oid_name) // invalid or placeholder list entry
-      continue;
-    if (policyOIDTag == entry.oid_tag) {
-      return true;
-    }
-  }
-
-#ifdef PSM_ENABLE_TEST_EV_ROOTS
-  if (isEVPolicyInExternalDebugRootsFile(policyOIDTag)) {
-    return true;
-  }
-#endif
-
-  return false;
-}
-
-namespace mozilla { namespace psm {
-
-CERTCertList*
-getRootsForOid(SECOidTag oid_tag)
-{
-  CERTCertList* certList = CERT_NewCertList();
-  if (!certList)
-    return nullptr;
-
-  for (size_t iEV=0; iEV < (sizeof(myTrustedEVInfos)/sizeof(nsMyTrustedEVInfo)); ++iEV) {
-    nsMyTrustedEVInfo& entry = myTrustedEVInfos[iEV];
-    if (!entry.oid_name) // invalid or placeholder list entry
-      continue;
-    if (entry.oid_tag == oid_tag) {
-      addToCertListIfTrusted(certList, entry.cert);
-    }
-  }
-
-#ifdef PSM_ENABLE_TEST_EV_ROOTS
-  getRootsForOidFromExternalRootsFile(certList, oid_tag);
-#endif
-  return certList;
-}
-
-} } // namespace mozilla::psm
-
-PRStatus
-nsNSSComponent::IdentityInfoInit()
-{
-  for (size_t iEV=0; iEV < (sizeof(myTrustedEVInfos)/sizeof(nsMyTrustedEVInfo)); ++iEV) {
-    nsMyTrustedEVInfo& entry = myTrustedEVInfos[iEV];
-    if (!entry.oid_name) // invalid or placeholder list entry
-      continue;
-
-    SECStatus rv;
-    CERTIssuerAndSN ias;
-
-    rv = ATOB_ConvertAsciiToItem(&ias.derIssuer, const_cast<char*>(entry.issuer_base64));
-    NS_ASSERTION(rv==SECSuccess, "error converting ascii to binary.");
-    rv = ATOB_ConvertAsciiToItem(&ias.serialNumber, const_cast<char*>(entry.serial_base64));
-    NS_ASSERTION(rv==SECSuccess, "error converting ascii to binary.");
-    ias.serialNumber.type = siUnsignedInteger;
-
-    entry.cert = CERT_FindCertByIssuerAndSN(nullptr, &ias);
-
-#ifdef DEBUG
-    // The debug CA cert is at positions 0, and is NOT in the NSS root db.
-    if (iEV > 0) {
-       NS_ASSERTION(entry.cert, "Could not find EV root in NSS storage");
-    }
-#endif
-
-    SECITEM_FreeItem(&ias.derIssuer, false);
-    SECITEM_FreeItem(&ias.serialNumber, false);
-
-    if (!entry.cert)
-      continue;
-
-    nsNSSCertificate c(entry.cert);
-    nsAutoString fingerprint;
-    c.GetSha1Fingerprint(fingerprint);
-
-    NS_ConvertASCIItoUTF16 sha1(entry.ev_root_sha1_fingerprint);
-
-    if (sha1 != fingerprint) {
-      NS_ASSERTION(sha1 == fingerprint, "found EV root with unexpected SHA1 mismatch");
-      CERT_DestroyCertificate(entry.cert);
-      entry.cert = nullptr;
-      continue;
-    }
-
-    SECItem ev_oid_item;
-    ev_oid_item.data = nullptr;
-    ev_oid_item.len = 0;
-    SECStatus srv = SEC_StringToOID(nullptr, &ev_oid_item,
-                                    entry.dotted_oid, 0);
-    if (srv != SECSuccess)
-      continue;
-
-    entry.oid_tag = register_oid(&ev_oid_item, entry.oid_name);
-
-    SECITEM_FreeItem(&ev_oid_item, false);
-  }
-
-#ifdef PSM_ENABLE_TEST_EV_ROOTS
-  if (!testEVInfosLoaded) {
-    testEVInfosLoaded = true;
-    testEVInfos = new testEVArray;
-    if (testEVInfos) {
-      loadTestEVInfos();
-    }
-  }
-#endif
-
-  return PR_SUCCESS;
-}
-
-namespace mozilla { namespace psm {
-
-// Find the first policy OID that is known to be an EV policy OID.
-SECStatus
-getFirstEVPolicy(CERTCertificate* cert, SECOidTag& outOidTag)
-{
-  if (!cert)
-    return SECFailure;
-
-  if (cert->extensions) {
-    for (int i=0; cert->extensions[i]; i++) {
-      const SECItem* oid = &cert->extensions[i]->id;
-
-      SECOidTag oidTag = SECOID_FindOIDTag(oid);
-      if (oidTag != SEC_OID_X509_CERTIFICATE_POLICIES)
-        continue;
-
-      SECItem* value = &cert->extensions[i]->value;
-
-      CERTCertificatePolicies* policies;
-      CERTPolicyInfo** policyInfos;
-
-      policies = CERT_DecodeCertificatePoliciesExtension(value);
-      if (!policies)
-        continue;
-
-      policyInfos = policies->policyInfos;
-
-      bool found = false;
-      while (*policyInfos) {
-        const CERTPolicyInfo* policyInfo = *policyInfos++;
-
-        SECOidTag oid_tag = policyInfo->oid;
-        if (oid_tag != SEC_OID_UNKNOWN && isEVPolicy(oid_tag)) {
-          // in our list of OIDs accepted for EV
-          outOidTag = oid_tag;
-          found = true;
-          break;
-        }
-      }
-      CERT_DestroyCertificatePoliciesExtension(policies);
-      if (found)
-        return SECSuccess;
-    }
-  }
-
-  return SECFailure;
-}
-
-} } // namespace mozilla::psm
-
-NS_IMETHODIMP
-nsSSLStatus::GetIsExtendedValidation(bool* aIsEV)
-{
-  NS_ENSURE_ARG_POINTER(aIsEV);
-  *aIsEV = false;
-
-#ifdef NSS_NO_LIBPKIX
-  return NS_OK;
-#else
-  nsCOMPtr<nsIX509Cert> cert = mServerCert;
-  nsresult rv;
-  nsCOMPtr<nsIIdentityInfo> idinfo = do_QueryInterface(cert, &rv);
-
-  // mServerCert should never be null when this method is called because
-  // nsSSLStatus objects always have mServerCert set right after they are
-  // constructed and before they are returned. GetIsExtendedValidation should
-  // only be called in the chrome process (in e10s), and mServerCert will always
-  // implement nsIIdentityInfo in the chrome process.
-  if (!idinfo) {
-    NS_ERROR("nsSSLStatus has null mServerCert or was called in the content "
-             "process");
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  // Never allow bad certs for EV, regardless of overrides.
-  if (mHaveCertErrorBits)
-    return NS_OK;
-
-  return idinfo->GetIsExtendedValidation(aIsEV);
-#endif
-}
-
-#ifndef NSS_NO_LIBPKIX
-
-nsresult
-nsNSSCertificate::hasValidEVOidTag(SECOidTag& resultOidTag, bool& validEV)
-{
-  nsNSSShutDownPreventionLock locker;
-  if (isAlreadyShutDown())
-    return NS_ERROR_NOT_AVAILABLE;
-
-  nsresult nrv;
-  nsCOMPtr<nsINSSComponent> nssComponent =
-    do_GetService(PSM_COMPONENT_CONTRACTID, &nrv);
-  if (NS_FAILED(nrv))
-    return nrv;
-  nssComponent->EnsureIdentityInfoLoaded();
-
-  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,
-                                          certificateUsageSSLServer, PR_Now(),
-                                          nullptr /* XXX pinarg */,
-                                          flags, nullptr, &resultOidTag);
-
-  if (rv != SECSuccess) {
-    resultOidTag = SEC_OID_UNKNOWN;
-  }
-  if (resultOidTag != SEC_OID_UNKNOWN) {
-    validEV = true;
-  }
-  return NS_OK;
-}
-
-nsresult
-nsNSSCertificate::getValidEVOidTag(SECOidTag& resultOidTag, bool& validEV)
-{
-  if (mCachedEVStatus != ev_status_unknown) {
-    validEV = (mCachedEVStatus == ev_status_valid);
-    if (validEV)
-      resultOidTag = mCachedEVOidTag;
-    return NS_OK;
-  }
-
-  nsresult rv = hasValidEVOidTag(resultOidTag, validEV);
-  if (NS_SUCCEEDED(rv)) {
-    if (validEV) {
-      mCachedEVOidTag = resultOidTag;
-    }
-    mCachedEVStatus = validEV ? ev_status_valid : ev_status_invalid;
-  }
-  return rv;
-}
-
-#endif // NSS_NO_LIBPKIX
-
-NS_IMETHODIMP
-nsNSSCertificate::GetIsExtendedValidation(bool* aIsEV)
-{
-#ifdef NSS_NO_LIBPKIX
-  *aIsEV = false;
-  return NS_OK;
-#else
-  nsNSSShutDownPreventionLock locker;
-  if (isAlreadyShutDown())
-    return NS_ERROR_NOT_AVAILABLE;
-
-  NS_ENSURE_ARG(aIsEV);
-  *aIsEV = false;
-
-  if (mCachedEVStatus != ev_status_unknown) {
-    *aIsEV = (mCachedEVStatus == ev_status_valid);
-    return NS_OK;
-  }
-
-  SECOidTag oid_tag;
-  return getValidEVOidTag(oid_tag, *aIsEV);
-#endif
-}
-
-NS_IMETHODIMP
-nsNSSCertificate::GetValidEVPolicyOid(nsACString& outDottedOid)
-{
-  outDottedOid.Truncate();
-
-#ifndef NSS_NO_LIBPKIX
-  nsNSSShutDownPreventionLock locker;
-  if (isAlreadyShutDown())
-    return NS_ERROR_NOT_AVAILABLE;
-
-  SECOidTag oid_tag;
-  bool valid;
-  nsresult rv = getValidEVOidTag(oid_tag, valid);
-  if (NS_FAILED(rv))
-    return rv;
-
-  if (valid) {
-    SECOidData* oid_data = SECOID_FindOIDByTag(oid_tag);
-    if (!oid_data)
-      return NS_ERROR_FAILURE;
-
-    char* oid_str = CERT_GetOidString(&oid_data->oid);
-    if (!oid_str)
-      return NS_ERROR_FAILURE;
-
-    outDottedOid = oid_str;
-    PR_smprintf_free(oid_str);
-  }
-#endif
-
-  return NS_OK;
-}
-
-#ifndef NSS_NO_LIBPKIX
-
-NS_IMETHODIMP
-nsNSSComponent::EnsureIdentityInfoLoaded()
-{
-  PRStatus rv = PR_CallOnce(&mIdentityInfoCallOnce, IdentityInfoInit);
-  return (rv == PR_SUCCESS) ? NS_OK : NS_ERROR_FAILURE;
-}
-
-// only called during shutdown
-void
-nsNSSComponent::CleanupIdentityInfo()
-{
-  nsNSSShutDownPreventionLock locker;
-  for (size_t iEV=0; iEV < (sizeof(myTrustedEVInfos)/sizeof(nsMyTrustedEVInfo)); ++iEV) {
-    nsMyTrustedEVInfo& entry = myTrustedEVInfos[iEV];
-    if (entry.cert) {
-      CERT_DestroyCertificate(entry.cert);
-      entry.cert = nullptr;
-    }
-  }
-
-#ifdef PSM_ENABLE_TEST_EV_ROOTS
-  if (testEVInfosLoaded) {
-    testEVInfosLoaded = false;
-    if (testEVInfos) {
-      for (size_t i = 0; i<testEVInfos->Length(); ++i) {
-        delete testEVInfos->ElementAt(i);
-      }
-      testEVInfos->Clear();
-      delete testEVInfos;
-      testEVInfos = nullptr;
-    }
-  }
-#endif
-  memset(&mIdentityInfoCallOnce, 0, sizeof(PRCallOnceType));
-}
-
-#endif
--- a/security/manager/ssl/src/nsNSSCertificate.cpp
+++ b/security/manager/ssl/src/nsNSSCertificate.cpp
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "prmem.h"
 #include "prerror.h"
 #include "prprf.h"
 
 #include "nsNSSCertificate.h"
 #include "CertVerifier.h"
+#include "ExtendedValidation.h"
 #include "nsNSSComponent.h" // for PIPNSS string bundle calls.
 #include "nsNSSCleaner.h"
 #include "nsCOMPtr.h"
 #include "nsIMutableArray.h"
 #include "nsNSSCertValidity.h"
 #include "nsPKCS12Blob.h"
 #include "nsPK11TokenDB.h"
 #include "nsIX509Cert.h"
@@ -1476,16 +1477,135 @@ char* nsNSSCertificate::defaultServerNic
     }
     PR_Free(nickname);
     count++;
   }
   PR_FREEIF(servername);
   return nickname;
 }
 
+#ifndef NSS_NO_LIBPKIX
+
+nsresult
+nsNSSCertificate::hasValidEVOidTag(SECOidTag& resultOidTag, bool& validEV)
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return NS_ERROR_NOT_AVAILABLE;
+
+  EnsureIdentityInfoLoaded();
+
+  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,
+    certificateUsageSSLServer, PR_Now(),
+    nullptr /* XXX pinarg */,
+    flags, nullptr, &resultOidTag);
+
+  if (rv != SECSuccess) {
+    resultOidTag = SEC_OID_UNKNOWN;
+  }
+  if (resultOidTag != SEC_OID_UNKNOWN) {
+    validEV = true;
+  }
+  return NS_OK;
+}
+
+nsresult
+nsNSSCertificate::getValidEVOidTag(SECOidTag& resultOidTag, bool& validEV)
+{
+  if (mCachedEVStatus != ev_status_unknown) {
+    validEV = (mCachedEVStatus == ev_status_valid);
+    if (validEV) {
+      resultOidTag = mCachedEVOidTag;
+    }
+    return NS_OK;
+  }
+
+  nsresult rv = hasValidEVOidTag(resultOidTag, validEV);
+  if (NS_SUCCEEDED(rv)) {
+    if (validEV) {
+      mCachedEVOidTag = resultOidTag;
+    }
+    mCachedEVStatus = validEV ? ev_status_valid : ev_status_invalid;
+  }
+  return rv;
+}
+
+#endif // NSS_NO_LIBPKIX
+
+NS_IMETHODIMP
+nsNSSCertificate::GetIsExtendedValidation(bool* aIsEV)
+{
+#ifdef NSS_NO_LIBPKIX
+  *aIsEV = false;
+  return NS_OK;
+#else
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  NS_ENSURE_ARG(aIsEV);
+  *aIsEV = false;
+
+  if (mCachedEVStatus != ev_status_unknown) {
+    *aIsEV = (mCachedEVStatus == ev_status_valid);
+    return NS_OK;
+  }
+
+  SECOidTag oid_tag;
+  return getValidEVOidTag(oid_tag, *aIsEV);
+#endif
+}
+
+NS_IMETHODIMP
+nsNSSCertificate::GetValidEVPolicyOid(nsACString& outDottedOid)
+{
+  outDottedOid.Truncate();
+
+#ifndef NSS_NO_LIBPKIX
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  SECOidTag oid_tag;
+  bool valid;
+  nsresult rv = getValidEVOidTag(oid_tag, valid);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  if (valid) {
+    SECOidData* oid_data = SECOID_FindOIDByTag(oid_tag);
+    if (!oid_data) {
+      return NS_ERROR_FAILURE;
+    }
+
+    char* oid_str = CERT_GetOidString(&oid_data->oid);
+    if (!oid_str) {
+      return NS_ERROR_FAILURE;
+    }
+
+    outDottedOid.Assign(oid_str);
+    PR_smprintf_free(oid_str);
+  }
+#endif
+
+  return NS_OK;
+}
+
 NS_IMPL_ISUPPORTS1(nsNSSCertList, nsIX509CertList)
 
 nsNSSCertList::nsNSSCertList(CERTCertList* certList,
                              const nsNSSShutDownPreventionLock& proofOfLock)
 {
   if (certList) {
     mCertList = certList;
   } else {
--- a/security/manager/ssl/src/nsNSSCertificateDB.cpp
+++ b/security/manager/ssl/src/nsNSSCertificateDB.cpp
@@ -6,16 +6,17 @@
 // CERT_AddTempCertToPerm is exposed as __CERT_AddTempCertToPerm, but it is
 // only exported so PSM can use it for this specific purpose.
 #define CERT_AddTempCertToPerm __CERT_AddTempCertToPerm
 
 #include "nsNSSComponent.h"
 #include "nsNSSCertificateDB.h"
 
 #include "CertVerifier.h"
+#include "ExtendedValidation.h"
 #include "nsNSSComponent.h"
 #include "mozilla/Base64.h"
 #include "nsCOMPtr.h"
 #include "nsNSSCertificate.h"
 #include "nsNSSHelper.h"
 #include "nsNSSCertHelper.h"
 #include "nsNSSCertCache.h"
 #include "nsCRT.h"
@@ -1693,23 +1694,18 @@ nsNSSCertificateDB::VerifyCertNow(nsIX50
   *aHasEVPolicy = false;
   *_retval = PR_UNKNOWN_ERROR;
 
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown()) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  nsresult rv;
 #ifndef NSS_NO_LIBPKIX
-  nsCOMPtr<nsINSSComponent> inss = do_GetService(PSM_COMPONENT_CONTRACTID, &rv);
-  if (NS_FAILED(rv)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  inss->EnsureIdentityInfoLoaded();
+  EnsureIdentityInfoLoaded();
 #endif
 
   nsCOMPtr<nsIX509Cert2> x509Cert = do_QueryInterface(aCert);
   if (!x509Cert) {
     return NS_ERROR_INVALID_ARG;
   }
   ScopedCERTCertificate nssCert(x509Cert->GetCert());
 
--- a/security/manager/ssl/src/nsNSSComponent.cpp
+++ b/security/manager/ssl/src/nsNSSComponent.cpp
@@ -5,16 +5,17 @@
  * 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 "ExtendedValidation.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"
@@ -215,22 +216,16 @@ nsNSSComponent::nsNSSComponent()
 {
 #ifdef PR_LOGGING
   if (!gPIPNSSLog)
     gPIPNSSLog = PR_NewLogModule("pipnss");
 #endif
   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::ctor\n"));
   mObserversRegistered = false;
 
-#ifndef NSS_NO_LIBPKIX
-  // In order to keep startup time lower, we delay loading and
-  // registering all identity data until first needed.
-  memset(&mIdentityInfoCallOnce, 0, sizeof(PRCallOnceType));
-#endif
-
   NS_ASSERTION( (0 == mInstanceCount), "nsNSSComponent is a singleton, but instantiated multiple times!");
   ++mInstanceCount;
   mShutdownObjectList = nsNSSShutDownList::construct();
   mIsNetworkDown = false;
 }
 
 void
 nsNSSComponent::deleteBackgroundThreads()
@@ -899,22 +894,21 @@ static const CipherPref sCipherPrefs[] =
  { nullptr, 0 } // end marker
 };
 
 static void
 setNonPkixOcspEnabled(int32_t ocspEnabled)
 {
   // Note: this preference is numeric vs boolean because previously we
   // supported more than two options.
+  CERT_DisableOCSPDefaultResponder(CERT_GetDefaultCertDB());
   if (!ocspEnabled) {
     CERT_DisableOCSPChecking(CERT_GetDefaultCertDB());
-    CERT_DisableOCSPDefaultResponder(CERT_GetDefaultCertDB());
   } else {
     CERT_EnableOCSPChecking(CERT_GetDefaultCertDB());
-    CERT_DisableOCSPDefaultResponder(CERT_GetDefaultCertDB());
   }
 }
 
 static const int32_t OCSP_ENABLED_DEFAULT = 1;
 static const bool REQUIRE_SAFE_NEGOTIATION_DEFAULT = false;
 static const bool ALLOW_UNRESTRICTED_RENEGO_DEFAULT = false;
 static const bool FALSE_START_ENABLED_DEFAULT = true;
 static const bool NPN_ENABLED_DEFAULT = true;
--- a/security/manager/ssl/src/nsNSSComponent.h
+++ b/security/manager/ssl/src/nsNSSComponent.h
@@ -102,20 +102,16 @@ class NS_NO_VTABLE nsINSSComponent : pub
 
   NS_IMETHOD PostEvent(const nsAString& eventType,
                        const nsAString& token) = 0;
 
   NS_IMETHOD DispatchEvent(const nsAString& eventType,
                            const nsAString& token) = 0;
 #endif
 
-#ifndef NSS_NO_LIBPKIX
-  NS_IMETHOD EnsureIdentityInfoLoaded() = 0;
-#endif
-
   NS_IMETHOD IsNSSInitialized(bool* initialized) = 0;
 
   virtual ::mozilla::TemporaryRef<mozilla::psm::SharedCertVerifier>
     GetDefaultCertVerifier() = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsINSSComponent, NS_INSSCOMPONENT_IID)
 
@@ -170,31 +166,27 @@ public:
   NS_IMETHOD DispatchEvent(const nsAString& eventType, const nsAString& token);
   void LaunchSmartCardThreads();
   void ShutdownSmartCardThreads();
   nsresult DispatchEventToWindow(nsIDOMWindow* domWin,
                                  const nsAString& eventType,
                                  const nsAString& token);
 #endif
 
-#ifndef NSS_NO_LIBPKIX
-  NS_IMETHOD EnsureIdentityInfoLoaded();
-#endif
   NS_IMETHOD IsNSSInitialized(bool* initialized);
 
   ::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();
   nsresult InitializePIPNSSBundle();
   nsresult ConfigureInternalPKCS11Token();
   nsresult RegisterObservers();
   nsresult DeregisterObservers();
 
   // Methods that we use to handle the profile change notifications (and to
@@ -221,17 +213,16 @@ private:
   void createBackgroundThreads();
   nsCertVerificationThread* mCertVerificationThread;
 
   nsNSSHttpInterface mHttpForNSS;
   mozilla::RefPtr<mozilla::psm::SharedCertVerifier> mDefaultCertVerifier;
 
 
   static PRStatus IdentityInfoInit(void);
-  PRCallOnceType mIdentityInfoCallOnce;
 };
 
 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/nsSSLStatus.cpp
+++ b/security/manager/ssl/src/nsSSLStatus.cpp
@@ -2,16 +2,17 @@
  *
  * 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 "nsSSLStatus.h"
 #include "plstr.h"
 #include "nsIClassInfoImpl.h"
+#include "nsIIdentityInfo.h"
 #include "nsIProgrammingLanguage.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIObjectInputStream.h"
 
 NS_IMETHODIMP
 nsSSLStatus::GetServerCert(nsIX509Cert** _result)
 {
   NS_ASSERTION(_result, "non-NULL destination required");
@@ -84,16 +85,49 @@ nsSSLStatus::GetIsUntrusted(bool* _resul
   NS_ASSERTION(_result, "non-NULL destination required");
 
   *_result = mHaveCertErrorBits && mIsUntrusted;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsSSLStatus::GetIsExtendedValidation(bool* aIsEV)
+{
+  NS_ENSURE_ARG_POINTER(aIsEV);
+  *aIsEV = false;
+
+#ifdef NSS_NO_LIBPKIX
+  return NS_OK;
+#else
+  nsCOMPtr<nsIX509Cert> cert = mServerCert;
+  nsresult rv;
+  nsCOMPtr<nsIIdentityInfo> idinfo = do_QueryInterface(cert, &rv);
+
+  // mServerCert should never be null when this method is called because
+  // nsSSLStatus objects always have mServerCert set right after they are
+  // constructed and before they are returned. GetIsExtendedValidation should
+  // only be called in the chrome process (in e10s), and mServerCert will always
+  // implement nsIIdentityInfo in the chrome process.
+  if (!idinfo) {
+    NS_ERROR("nsSSLStatus has null mServerCert or was called in the content "
+             "process");
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  // Never allow bad certs for EV, regardless of overrides.
+  if (mHaveCertErrorBits) {
+    return NS_OK;
+  }
+
+  return idinfo->GetIsExtendedValidation(aIsEV);
+#endif
+}
+
+NS_IMETHODIMP
 nsSSLStatus::Read(nsIObjectInputStream* stream)
 {
   nsCOMPtr<nsISupports> cert;
   nsresult rv = stream->ReadObject(true, getter_AddRefs(cert));
   NS_ENSURE_SUCCESS(rv, rv);
 
   mServerCert = do_QueryInterface(cert);
   if (!mServerCert)
--- a/toolkit/toolkit.mozbuild
+++ b/toolkit/toolkit.mozbuild
@@ -15,16 +15,20 @@ if CONFIG['COMPILE_ENVIRONMENT']:
     if not CONFIG['MOZ_NATIVE_NSS']:
         add_tier_dir('nss', 'security/build')
 
     include('/config/js/js.mozbuild')
 
 if CONFIG['MOZ_CONTENT_SANDBOX']:
     add_tier_dir('sandbox', 'security/sandbox')
 
+# Depends on NSS and NSPR, and must be built after sandbox or else B2G emulator
+# builds fail.
+add_tier_dir('platform', 'security/certverifier')
+
 # the signing related bits of libmar depend on nss
 if CONFIG['MOZ_UPDATER']:
     add_tier_dir('platform', 'modules/libmar')
 
 if CONFIG['NS_TRACE_MALLOC']:
     add_tier_dir('platform', 'tools/trace-malloc/lib')
 
 if CONFIG['MOZ_DMD']: