// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/cert/cert_verify_proc_win.h"

#include <algorithm>
#include <memory>
#include <string>
#include <vector>

#include "base/memory/free_deleter.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_local.h"
#include "crypto/capi_util.h"
#include "crypto/scoped_capi_types.h"
#include "crypto/sha2.h"
#include "net/base/net_errors.h"
#include "net/cert/asn1_util.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/cert_verify_result.h"
#include "net/cert/crl_set.h"
#include "net/cert/ev_root_ca_metadata.h"
#include "net/cert/known_roots.h"
#include "net/cert/known_roots_win.h"
#include "net/cert/test_root_certs.h"
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util_win.h"

#if !defined(CERT_TRUST_HAS_WEAK_SIGNATURE)
// This was introduced in Windows 8 / Windows Server 2012, but retroactively
// ported as far back as Windows XP via system update.
#define CERT_TRUST_HAS_WEAK_SIGNATURE 0x00100000
#endif

namespace net {

namespace {

struct FreeChainEngineFunctor {
  void operator()(HCERTCHAINENGINE engine) const {
    if (engine)
      CertFreeCertificateChainEngine(engine);
  }
};

struct FreeCertChainContextFunctor {
  void operator()(PCCERT_CHAIN_CONTEXT chain_context) const {
    if (chain_context)
      CertFreeCertificateChain(chain_context);
  }
};

typedef crypto::ScopedCAPIHandle<HCERTCHAINENGINE, FreeChainEngineFunctor>
    ScopedHCERTCHAINENGINE;

typedef std::unique_ptr<const CERT_CHAIN_CONTEXT, FreeCertChainContextFunctor>
    ScopedPCCERT_CHAIN_CONTEXT;

//-----------------------------------------------------------------------------

int MapSecurityError(SECURITY_STATUS err) {
  // There are numerous security error codes, but these are the ones we thus
  // far find interesting.
  switch (err) {
    case SEC_E_WRONG_PRINCIPAL:  // Schannel
    case CERT_E_CN_NO_MATCH:  // CryptoAPI
      return ERR_CERT_COMMON_NAME_INVALID;
    case SEC_E_UNTRUSTED_ROOT:  // Schannel
    case CERT_E_UNTRUSTEDROOT:  // CryptoAPI
    case TRUST_E_CERT_SIGNATURE:  // CryptoAPI. Caused by weak crypto or bad
                                  // signatures, but not differentiable.
      return ERR_CERT_AUTHORITY_INVALID;
    case SEC_E_CERT_EXPIRED:  // Schannel
    case CERT_E_EXPIRED:  // CryptoAPI
      return ERR_CERT_DATE_INVALID;
    case CRYPT_E_NO_REVOCATION_CHECK:
      return ERR_CERT_NO_REVOCATION_MECHANISM;
    case CRYPT_E_REVOCATION_OFFLINE:
      return ERR_CERT_UNABLE_TO_CHECK_REVOCATION;
    case CRYPT_E_REVOKED:  // Schannel and CryptoAPI
      return ERR_CERT_REVOKED;
    case SEC_E_CERT_UNKNOWN:
    case CERT_E_ROLE:
      return ERR_CERT_INVALID;
    case CERT_E_WRONG_USAGE:
      // TODO(wtc): Should we add ERR_CERT_WRONG_USAGE?
      return ERR_CERT_INVALID;
    // We received an unexpected_message or illegal_parameter alert message
    // from the server.
    case SEC_E_ILLEGAL_MESSAGE:
      return ERR_SSL_PROTOCOL_ERROR;
    case SEC_E_ALGORITHM_MISMATCH:
      return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
    case SEC_E_INVALID_HANDLE:
      return ERR_UNEXPECTED;
    case SEC_E_OK:
      return OK;
    default:
      LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED";
      return ERR_FAILED;
  }
}

// Map the errors in the chain_context->TrustStatus.dwErrorStatus returned by
// CertGetCertificateChain to our certificate status flags.
int MapCertChainErrorStatusToCertStatus(DWORD error_status) {
  CertStatus cert_status = 0;

  // We don't include CERT_TRUST_IS_NOT_TIME_NESTED because it's obsolete and
  // we wouldn't consider it an error anyway
  const DWORD kDateInvalidErrors = CERT_TRUST_IS_NOT_TIME_VALID |
                                   CERT_TRUST_CTL_IS_NOT_TIME_VALID;
  if (error_status & kDateInvalidErrors)
    cert_status |= CERT_STATUS_DATE_INVALID;

  const DWORD kAuthorityInvalidErrors = CERT_TRUST_IS_UNTRUSTED_ROOT |
                                        CERT_TRUST_IS_EXPLICIT_DISTRUST |
                                        CERT_TRUST_IS_PARTIAL_CHAIN;
  if (error_status & kAuthorityInvalidErrors)
    cert_status |= CERT_STATUS_AUTHORITY_INVALID;

  if ((error_status & CERT_TRUST_REVOCATION_STATUS_UNKNOWN) &&
      !(error_status & CERT_TRUST_IS_OFFLINE_REVOCATION))
    cert_status |= CERT_STATUS_NO_REVOCATION_MECHANISM;

  if (error_status & CERT_TRUST_IS_OFFLINE_REVOCATION)
    cert_status |= CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;

  if (error_status & CERT_TRUST_IS_REVOKED)
    cert_status |= CERT_STATUS_REVOKED;

  const DWORD kWrongUsageErrors = CERT_TRUST_IS_NOT_VALID_FOR_USAGE |
                                  CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE;
  if (error_status & kWrongUsageErrors) {
    // TODO(wtc): Should we add CERT_STATUS_WRONG_USAGE?
    cert_status |= CERT_STATUS_INVALID;
  }

  if (error_status & CERT_TRUST_IS_NOT_SIGNATURE_VALID) {
    // Check for a signature that does not meet the OS criteria for strong
    // signatures.
    // Note: These checks may be more restrictive than the current weak key
    // criteria implemented within CertVerifier, such as excluding SHA-1 or
    // excluding RSA keys < 2048 bits. However, if the user has configured
    // these more stringent checks, respect that configuration and err on the
    // more restrictive criteria.
    if (error_status & CERT_TRUST_HAS_WEAK_SIGNATURE) {
      cert_status |= CERT_STATUS_WEAK_KEY;
    } else {
      cert_status |= CERT_STATUS_AUTHORITY_INVALID;
    }
  }

  // The rest of the errors.
  const DWORD kCertInvalidErrors =
      CERT_TRUST_IS_CYCLIC |
      CERT_TRUST_INVALID_EXTENSION |
      CERT_TRUST_INVALID_POLICY_CONSTRAINTS |
      CERT_TRUST_INVALID_BASIC_CONSTRAINTS |
      CERT_TRUST_INVALID_NAME_CONSTRAINTS |
      CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID |
      CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT |
      CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT |
      CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT |
      CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT |
      CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY |
      CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT;
  if (error_status & kCertInvalidErrors)
    cert_status |= CERT_STATUS_INVALID;

  return cert_status;
}

// Returns true if any common name in the certificate's Subject field contains
// a NULL character.
bool CertSubjectCommonNameHasNull(PCCERT_CONTEXT cert) {
  CRYPT_DECODE_PARA decode_para;
  decode_para.cbSize = sizeof(decode_para);
  decode_para.pfnAlloc = crypto::CryptAlloc;
  decode_para.pfnFree = crypto::CryptFree;
  CERT_NAME_INFO* name_info = nullptr;
  DWORD name_info_size = 0;
  BOOL rv;
  rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                           WINCRYPT_X509_NAME,
                           cert->pCertInfo->Subject.pbData,
                           cert->pCertInfo->Subject.cbData,
                           CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
                           &decode_para,
                           &name_info,
                           &name_info_size);
  if (rv) {
    std::unique_ptr<CERT_NAME_INFO, base::FreeDeleter> scoped_name_info(
        name_info);

    // The Subject field may have multiple common names.  According to the
    // "PKI Layer Cake" paper, CryptoAPI uses every common name in the
    // Subject field, so we inspect every common name.
    //
    // From RFC 5280:
    // X520CommonName ::= CHOICE {
    //       teletexString     TeletexString   (SIZE (1..ub-common-name)),
    //       printableString   PrintableString (SIZE (1..ub-common-name)),
    //       universalString   UniversalString (SIZE (1..ub-common-name)),
    //       utf8String        UTF8String      (SIZE (1..ub-common-name)),
    //       bmpString         BMPString       (SIZE (1..ub-common-name)) }
    //
    // We also check IA5String and VisibleString.
    for (DWORD i = 0; i < name_info->cRDN; ++i) {
      PCERT_RDN rdn = &name_info->rgRDN[i];
      for (DWORD j = 0; j < rdn->cRDNAttr; ++j) {
        PCERT_RDN_ATTR rdn_attr = &rdn->rgRDNAttr[j];
        if (strcmp(rdn_attr->pszObjId, szOID_COMMON_NAME) == 0) {
          switch (rdn_attr->dwValueType) {
            // After the CryptoAPI ASN.1 security vulnerabilities described in
            // http://www.microsoft.com/technet/security/Bulletin/MS09-056.mspx
            // were patched, we get CERT_RDN_ENCODED_BLOB for a common name
            // that contains a NULL character.
            case CERT_RDN_ENCODED_BLOB:
              break;
            // Array of 8-bit characters.
            case CERT_RDN_PRINTABLE_STRING:
            case CERT_RDN_TELETEX_STRING:
            case CERT_RDN_IA5_STRING:
            case CERT_RDN_VISIBLE_STRING:
              for (DWORD k = 0; k < rdn_attr->Value.cbData; ++k) {
                if (rdn_attr->Value.pbData[k] == '\0')
                  return true;
              }
              break;
            // Array of 16-bit characters.
            case CERT_RDN_BMP_STRING:
            case CERT_RDN_UTF8_STRING: {
              DWORD num_wchars = rdn_attr->Value.cbData / 2;
              wchar_t* common_name =
                  reinterpret_cast<wchar_t*>(rdn_attr->Value.pbData);
              for (DWORD k = 0; k < num_wchars; ++k) {
                if (common_name[k] == L'\0')
                  return true;
              }
              break;
            }
            // Array of ints (32-bit).
            case CERT_RDN_UNIVERSAL_STRING: {
              DWORD num_ints = rdn_attr->Value.cbData / 4;
              int* common_name =
                  reinterpret_cast<int*>(rdn_attr->Value.pbData);
              for (DWORD k = 0; k < num_ints; ++k) {
                if (common_name[k] == 0)
                  return true;
              }
              break;
            }
            default:
              NOTREACHED();
              break;
          }
        }
      }
    }
  }
  return false;
}

// Saves some information about the certificate chain |chain_context| in
// |*verify_result|. The caller MUST initialize |*verify_result| before
// calling this function.
void GetCertChainInfo(PCCERT_CHAIN_CONTEXT chain_context,
                      CertVerifyResult* verify_result) {
  if (chain_context->cChain == 0)
    return;

  PCERT_SIMPLE_CHAIN first_chain = chain_context->rgpChain[0];
  DWORD num_elements = first_chain->cElement;
  PCERT_CHAIN_ELEMENT* element = first_chain->rgpElement;

  PCCERT_CONTEXT verified_cert = nullptr;
  std::vector<PCCERT_CONTEXT> verified_chain;

  bool has_root_ca = num_elements > 1 &&
      !(chain_context->TrustStatus.dwErrorStatus &
          CERT_TRUST_IS_PARTIAL_CHAIN);

  // Each chain starts with the end entity certificate (i = 0) and ends with
  // either the root CA certificate or the last available intermediate. If a
  // root CA certificate is present, do not inspect the signature algorithm of
  // the root CA certificate because the signature on the trust anchor is not
  // important.
  if (has_root_ca) {
    // If a full chain was constructed, regardless of whether it was trusted,
    // don't inspect the root's signature algorithm.
    num_elements -= 1;
  }

  for (DWORD i = 0; i < num_elements; ++i) {
    PCCERT_CONTEXT cert = element[i]->pCertContext;
    if (i == 0) {
      verified_cert = cert;
    } else {
      verified_chain.push_back(cert);
    }
  }

  if (verified_cert) {
    // Add the root certificate, if present, as it was not added above.
    if (has_root_ca)
      verified_chain.push_back(element[num_elements]->pCertContext);
    scoped_refptr<X509Certificate> verified_cert_with_chain =
        x509_util::CreateX509CertificateFromCertContexts(verified_cert,
                                                         verified_chain);
    if (verified_cert_with_chain)
      verify_result->verified_cert = std::move(verified_cert_with_chain);
    else
      verify_result->cert_status |= CERT_STATUS_INVALID;
  }
}

// Decodes the cert's certificatePolicies extension into a CERT_POLICIES_INFO
// structure and stores it in *output.
void GetCertPoliciesInfo(
    PCCERT_CONTEXT cert,
    std::unique_ptr<CERT_POLICIES_INFO, base::FreeDeleter>* output) {
  PCERT_EXTENSION extension = CertFindExtension(szOID_CERT_POLICIES,
                                                cert->pCertInfo->cExtension,
                                                cert->pCertInfo->rgExtension);
  if (!extension)
    return;

  CRYPT_DECODE_PARA decode_para;
  decode_para.cbSize = sizeof(decode_para);
  decode_para.pfnAlloc = crypto::CryptAlloc;
  decode_para.pfnFree = crypto::CryptFree;
  CERT_POLICIES_INFO* policies_info = nullptr;
  DWORD policies_info_size = 0;
  BOOL rv;
  rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                           szOID_CERT_POLICIES,
                           extension->Value.pbData,
                           extension->Value.cbData,
                           CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
                           &decode_para,
                           &policies_info,
                           &policies_info_size);
  if (rv)
    output->reset(policies_info);
}

// Computes the SHA-256 hash of the SPKI of |cert| and stores it in |hash|,
// returning true. If an error occurs, returns false and leaves |hash|
// unmodified.
bool HashSPKI(PCCERT_CONTEXT cert, std::string* hash) {
  base::StringPiece der_bytes(
      reinterpret_cast<const char*>(cert->pbCertEncoded), cert->cbCertEncoded);

  base::StringPiece spki;
  if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki))
    return false;

  *hash = crypto::SHA256HashString(spki);
  return true;
}

bool GetSubject(PCCERT_CONTEXT cert, base::StringPiece* out_subject) {
  base::StringPiece der_bytes(
      reinterpret_cast<const char*>(cert->pbCertEncoded), cert->cbCertEncoded);
  return asn1::ExtractSubjectFromDERCert(der_bytes, out_subject);
}

enum CRLSetResult {
  // Indicates an error happened while attempting to determine CRLSet status.
  // For example, if the certificate's SPKI could not be extracted.
  kCRLSetError,

  // Indicates there is no fresh information about the certificate, or if the
  // CRLSet has expired.
  // In the case of certificate chains, this is only returned if the leaf
  // certificate is not covered by the CRLSet; this is because some
  // intermediates are fully covered, but after filtering, the issuer's CRL
  // is empty and thus omitted from the CRLSet. Since online checking is
  // performed for EV certificates when this status is returned, this would
  // result in needless online lookups for certificates known not-revoked.
  kCRLSetUnknown,

  // Indicates that the certificate (or a certificate in the chain) has been
  // revoked.
  kCRLSetRevoked,

  // The certificate (or certificate chain) has no revocations.
  kCRLSetOk,
};

// Determines if |subject_cert| is revoked within |crl_set|,
// storing the SubjectPublicKeyInfo hash of |subject_cert| in
// |*previous_hash|.
//
// CRLSets store revocations by both SPKI and by the tuple of Issuer SPKI
// Hash & Serial. While |subject_cert| contains enough information to check
// for SPKI revocations, to determine the issuer's SPKI, either |issuer_cert|
// must be supplied, or the hash of the issuer's SPKI provided in
// |*previous_hash|. If |issuer_cert| is omitted, and |*previous_hash| is empty,
// only SPKI checks are performed.
//
// To avoid recomputing SPKI hashes, the hash of |subject_cert| is stored in
// |*previous_hash|. This allows chaining revocation checking, by starting
// at the root and iterating to the leaf, supplying |previous_hash| each time.
//
// In the event of a parsing error, |*previous_hash| is cleared, to prevent the
// wrong Issuer&Serial tuple from being used.
CRLSetResult CheckRevocationWithCRLSet(CRLSet* crl_set,
                                       PCCERT_CONTEXT subject_cert,
                                       PCCERT_CONTEXT issuer_cert,
                                       std::string* previous_hash) {
  DCHECK(crl_set);
  DCHECK(subject_cert);

  // Check to see if |subject_cert|'s SPKI or Subject is revoked.
  std::string subject_hash;
  base::StringPiece subject_name;
  if (!HashSPKI(subject_cert, &subject_hash) ||
      !GetSubject(subject_cert, &subject_name)) {
    NOTREACHED();  // Indicates Windows accepted something irrecoverably bad.
    previous_hash->clear();
    return kCRLSetError;
  }

  if (crl_set->CheckSPKI(subject_hash) == CRLSet::REVOKED ||
      crl_set->CheckSubject(subject_name, subject_hash) == CRLSet::REVOKED) {
    return kCRLSetRevoked;
  }

  // If no issuer cert is provided, nor a hash of the issuer's SPKI, no
  // further checks can be done.
  if (!issuer_cert && previous_hash->empty()) {
    previous_hash->swap(subject_hash);
    return kCRLSetUnknown;
  }

  // Compute the subject's serial.
  const CRYPT_INTEGER_BLOB* serial_blob =
      &subject_cert->pCertInfo->SerialNumber;
  std::unique_ptr<uint8_t[]> serial_bytes(new uint8_t[serial_blob->cbData]);
  // The bytes of the serial number are stored little-endian.
  // Note: While MSDN implies that bytes are stripped from this serial,
  // they are not - only CertCompareIntegerBlob actually removes bytes.
  for (DWORD j = 0; j < serial_blob->cbData; j++)
    serial_bytes[j] = serial_blob->pbData[serial_blob->cbData - j - 1];
  base::StringPiece serial(reinterpret_cast<const char*>(serial_bytes.get()),
                           serial_blob->cbData);

  // Compute the issuer's hash. If it was provided (via previous_hash),
  // use that; otherwise, compute it based on |issuer_cert|.
  std::string issuer_hash_local;
  std::string* issuer_hash = previous_hash;
  if (issuer_hash->empty()) {
    if (!HashSPKI(issuer_cert, &issuer_hash_local)) {
      NOTREACHED();  // Indicates Windows accepted something irrecoverably bad.
      previous_hash->clear();
      return kCRLSetError;
    }
    issuer_hash = &issuer_hash_local;
  }

  // Look up by serial & issuer SPKI.
  const CRLSet::Result result = crl_set->CheckSerial(serial, *issuer_hash);
  if (result == CRLSet::REVOKED)
    return kCRLSetRevoked;

  previous_hash->swap(subject_hash);
  if (result == CRLSet::GOOD)
    return kCRLSetOk;
  if (result == CRLSet::UNKNOWN)
    return kCRLSetUnknown;

  NOTREACHED();
  return kCRLSetError;
}

// CheckChainRevocationWithCRLSet attempts to check each element of |chain|
// against |crl_set|. It returns:
//   kCRLSetRevoked: if any element of the chain is known to have been revoked.
//   kCRLSetUnknown: if there is no fresh information about the leaf
//       certificate in the chain or if the CRLSet has expired.
//
//       Only the leaf certificate is considered for coverage because some
//       intermediates have CRLs with no revocations (after filtering) and
//       those CRLs are pruned from the CRLSet at generation time. This means
//       that some EV sites would otherwise take the hit of an OCSP lookup for
//       no reason.
//   kCRLSetOk: otherwise.
CRLSetResult CheckChainRevocationWithCRLSet(PCCERT_CHAIN_CONTEXT chain,
                                            CRLSet* crl_set) {
  if (chain->cChain == 0 || chain->rgpChain[0]->cElement == 0)
    return kCRLSetOk;

  PCERT_CHAIN_ELEMENT* elements = chain->rgpChain[0]->rgpElement;
  DWORD num_elements = chain->rgpChain[0]->cElement;

  bool had_error = false;
  CRLSetResult result = kCRLSetError;
  std::string issuer_spki_hash;
  for (DWORD i = 0; i < num_elements; ++i) {
    PCCERT_CONTEXT subject = elements[num_elements - i - 1]->pCertContext;
    result =
        CheckRevocationWithCRLSet(crl_set, subject, nullptr, &issuer_spki_hash);
    if (result == kCRLSetRevoked)
      return result;
    if (result == kCRLSetError)
      had_error = true;
  }
  if (had_error || crl_set->IsExpired())
    return kCRLSetUnknown;
  return result;
}

void AppendPublicKeyHashesAndUpdateKnownRoot(PCCERT_CHAIN_CONTEXT chain,
                                             HashValueVector* hashes,
                                             bool* known_root) {
  if (chain->cChain == 0)
    return;

  PCERT_SIMPLE_CHAIN first_chain = chain->rgpChain[0];
  PCERT_CHAIN_ELEMENT* const element = first_chain->rgpElement;
  const DWORD num_elements = first_chain->cElement;

  // Walk the chain in reverse, from the probable root to the known leaf, as
  // an optimization for IsKnownRoot checks.
  for (DWORD i = num_elements; i > 0; i--) {
    PCCERT_CONTEXT cert = element[i - 1]->pCertContext;

    base::StringPiece der_bytes(
        reinterpret_cast<const char*>(cert->pbCertEncoded),
        cert->cbCertEncoded);
    base::StringPiece spki_bytes;
    if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes))
      continue;

    HashValue sha256(HASH_VALUE_SHA256);
    crypto::SHA256HashString(spki_bytes, sha256.data(), crypto::kSHA256Length);
    hashes->push_back(sha256);

    if (!*known_root) {
      *known_root =
          GetNetTrustAnchorHistogramIdForSPKI(sha256) != 0 || IsKnownRoot(cert);
    }
  }

  // Reverse the hash list, such that it's ordered from leaf to root.
  std::reverse(hashes->begin(), hashes->end());
}

// Returns true if the certificate is an extended-validation certificate.
//
// This function checks the certificatePolicies extensions of the
// certificates in the certificate chain according to Section 7 (pp. 11-12)
// of the EV Certificate Guidelines Version 1.0 at
// http://cabforum.org/EV_Certificate_Guidelines.pdf.
bool CheckEV(PCCERT_CHAIN_CONTEXT chain_context,
             bool rev_checking_enabled,
             const char* policy_oid) {
  DCHECK_NE(static_cast<DWORD>(0), chain_context->cChain);
  // If the cert doesn't match any of the policies, the
  // CERT_TRUST_IS_NOT_VALID_FOR_USAGE bit (0x10) in
  // chain_context->TrustStatus.dwErrorStatus is set.
  DWORD error_status = chain_context->TrustStatus.dwErrorStatus;

  if (!rev_checking_enabled) {
    // If online revocation checking is disabled then we will have still
    // requested that the revocation cache be checked. However, that will often
    // cause the following two error bits to be set. These error bits mean that
    // the local OCSP/CRL is stale or missing entries for these certificates.
    // Since they are expected, we mask them away.
    error_status &= ~(CERT_TRUST_IS_OFFLINE_REVOCATION |
                      CERT_TRUST_REVOCATION_STATUS_UNKNOWN);
  }
  if (!chain_context->cChain || error_status != CERT_TRUST_NO_ERROR)
    return false;

  // Check the end certificate simple chain (chain_context->rgpChain[0]).
  // If the end certificate's certificatePolicies extension contains the
  // EV policy OID of the root CA, return true.
  PCERT_CHAIN_ELEMENT* element = chain_context->rgpChain[0]->rgpElement;
  int num_elements = chain_context->rgpChain[0]->cElement;
  if (num_elements < 2)
    return false;

  // Look up the EV policy OID of the root CA.
  PCCERT_CONTEXT root_cert = element[num_elements - 1]->pCertContext;
  SHA256HashValue fingerprint = x509_util::CalculateFingerprint256(root_cert);
  EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance();
  return metadata->HasEVPolicyOID(fingerprint, policy_oid);
}

// Custom revocation provider function that compares incoming certificates with
// those in CRLSets. This is called BEFORE the default CRL & OCSP handling
// is invoked (which is handled by the revocation provider function
// "CertDllVerifyRevocation" in cryptnet.dll)
BOOL WINAPI
CertDllVerifyRevocationWithCRLSet(DWORD encoding_type,
                                  DWORD revocation_type,
                                  DWORD num_contexts,
                                  void* rgpvContext[],
                                  DWORD flags,
                                  PCERT_REVOCATION_PARA revocation_params,
                                  PCERT_REVOCATION_STATUS revocation_status);

// Helper class that installs the CRLSet-based Revocation Provider as the
// default revocation provider. Because it is installed as a function address
// (meaning only scoped to the process, and not stored in the registry), it
// will be used before any registry-based providers, including Microsoft's
// default provider.
class RevocationInjector {
 public:
  CRLSet* GetCRLSet() { return thread_local_crlset.Get(); }

  void SetCRLSet(CRLSet* crl_set) { thread_local_crlset.Set(crl_set); }

 private:
  friend struct base::LazyInstanceTraitsBase<RevocationInjector>;

  RevocationInjector() {
    const CRYPT_OID_FUNC_ENTRY kInterceptFunction[] = {
        {CRYPT_DEFAULT_OID,
         reinterpret_cast<void*>(&CertDllVerifyRevocationWithCRLSet)},
    };
    BOOL ok = CryptInstallOIDFunctionAddress(
        nullptr, X509_ASN_ENCODING, CRYPT_OID_VERIFY_REVOCATION_FUNC,
        base::size(kInterceptFunction), kInterceptFunction,
        CRYPT_INSTALL_OID_FUNC_BEFORE_FLAG);
    DCHECK(ok);
  }

  ~RevocationInjector() {}

  // As the revocation parameters passed to CertVerifyProc::VerifyInternal
  // cannot be officially smuggled to the Revocation Provider
  base::ThreadLocalPointer<CRLSet> thread_local_crlset;
};

// Leaky, as CertVerifyProc workers are themselves leaky.
base::LazyInstance<RevocationInjector>::Leaky g_revocation_injector =
    LAZY_INSTANCE_INITIALIZER;

BOOL WINAPI
CertDllVerifyRevocationWithCRLSet(DWORD encoding_type,
                                  DWORD revocation_type,
                                  DWORD num_contexts,
                                  void* rgpvContext[],
                                  DWORD flags,
                                  PCERT_REVOCATION_PARA revocation_params,
                                  PCERT_REVOCATION_STATUS revocation_status) {
  PCERT_CONTEXT* cert_contexts = reinterpret_cast<PCERT_CONTEXT*>(rgpvContext);
  // The dummy CRLSet provider never returns that something is affirmatively
  // *un*revoked, as this would disable other revocation providers from being
  // checked for this certificate (much like an OCSP "Good" status would).
  // Instead, it merely indicates that insufficient information existed to
  // determine if the certificate was revoked (in the good case), or that a cert
  // is affirmatively revoked in the event it appears within the CRLSet.
  // Because of this, set up some basic bookkeeping for the results.
  CHECK(revocation_status);
  revocation_status->dwIndex = 0;
  revocation_status->dwError = static_cast<DWORD>(CRYPT_E_NO_REVOCATION_CHECK);
  revocation_status->dwReason = 0;

  if (num_contexts == 0 || !cert_contexts[0]) {
    SetLastError(static_cast<DWORD>(E_INVALIDARG));
    return FALSE;
  }

  if ((GET_CERT_ENCODING_TYPE(encoding_type) != X509_ASN_ENCODING) ||
      revocation_type != CERT_CONTEXT_REVOCATION_TYPE) {
    SetLastError(static_cast<DWORD>(CRYPT_E_NO_REVOCATION_CHECK));
    return FALSE;
  }

  // No revocation checking possible if there is no associated
  // CRLSet.
  CRLSet* crl_set = g_revocation_injector.Get().GetCRLSet();
  if (!crl_set)
    return FALSE;

  // |revocation_params| is an optional structure; to make life simple and avoid
  // the need to constantly check whether or not it was supplied, create a local
  // copy. If the caller didn't supply anything, it will be empty; otherwise,
  // it will be (non-owning) copies of the caller's original params.
  CERT_REVOCATION_PARA local_params;
  memset(&local_params, 0, sizeof(local_params));
  if (revocation_params) {
    DWORD bytes_to_copy = std::min(revocation_params->cbSize,
                                   static_cast<DWORD>(sizeof(local_params)));
    memcpy(&local_params, revocation_params, bytes_to_copy);
  }
  local_params.cbSize = sizeof(local_params);

  PCERT_CONTEXT subject_cert = cert_contexts[0];

  if ((flags & CERT_VERIFY_REV_CHAIN_FLAG) && num_contexts > 1) {
    // Verifying a chain; first verify from the last certificate in the
    // chain to the first, and then leave the last certificate (which
    // is presumably self-issued, although it may simply be a trust
    // anchor) as the |subject_cert| in order to scan for more
    // revocations.
    std::string issuer_hash;
    PCCERT_CONTEXT issuer_cert = nullptr;
    for (DWORD i = num_contexts; i > 0; --i) {
      subject_cert = cert_contexts[i - 1];
      if (!subject_cert) {
        SetLastError(static_cast<DWORD>(E_INVALIDARG));
        return FALSE;
      }
      CRLSetResult result = CheckRevocationWithCRLSet(
          crl_set, subject_cert, issuer_cert, &issuer_hash);
      if (result == kCRLSetRevoked) {
        revocation_status->dwIndex = i - 1;
        revocation_status->dwError = static_cast<DWORD>(CRYPT_E_REVOKED);
        revocation_status->dwReason = CRL_REASON_UNSPECIFIED;
        SetLastError(revocation_status->dwError);
        return FALSE;
      }
      issuer_cert = subject_cert;
    }
    // Verified all certificates from the trust anchor to the leaf, and none
    // were explicitly revoked. Now do a second pass to attempt to determine
    // the issuer for cert_contexts[num_contexts - 1], so that the
    // Issuer SPKI+Serial can be checked for that certificate.
    //
    // This code intentionally ignores the flag
    subject_cert = cert_contexts[num_contexts - 1];
    // Reset local_params.pIssuerCert, since it would contain the issuer
    // for cert_contexts[0].
    local_params.pIssuerCert = nullptr;
    // Fixup the revocation index to point to this cert (in the event it is
    // revoked). If it isn't revoked, this will be done undone later.
    revocation_status->dwIndex = num_contexts - 1;
  }

  // Determine the issuer cert for the incoming cert
  ScopedPCCERT_CONTEXT issuer_cert;
  if (local_params.pIssuerCert &&
      CryptVerifyCertificateSignatureEx(
          NULL, subject_cert->dwCertEncodingType,
          CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT, subject_cert,
          CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT,
          const_cast<PCERT_CONTEXT>(local_params.pIssuerCert), 0, nullptr)) {
    // Caller has already supplied the issuer cert via the revocation params;
    // just use that.
    issuer_cert.reset(
        CertDuplicateCertificateContext(local_params.pIssuerCert));
  } else if (CertCompareCertificateName(subject_cert->dwCertEncodingType,
                                        &subject_cert->pCertInfo->Subject,
                                        &subject_cert->pCertInfo->Issuer) &&
             CryptVerifyCertificateSignatureEx(
                 NULL, subject_cert->dwCertEncodingType,
                 CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT, subject_cert,
                 CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT, subject_cert, 0,
                 nullptr)) {
    // Certificate is self-signed; use it as its own issuer.
    issuer_cert.reset(CertDuplicateCertificateContext(subject_cert));
  } else {
    // Scan the caller-supplied stores first, to try and find the issuer cert.
    for (DWORD i = 0; i < local_params.cCertStore && !issuer_cert; ++i) {
      PCCERT_CONTEXT previous_cert = nullptr;
      for (;;) {
        DWORD store_search_flags = CERT_STORE_SIGNATURE_FLAG;
        previous_cert = CertGetIssuerCertificateFromStore(
            local_params.rgCertStore[i], subject_cert, previous_cert,
            &store_search_flags);
        if (!previous_cert)
          break;
        // If a cert is found and meets the criteria, the flag will be reset to
        // zero. Thus NOT having the bit set is equivalent to having found a
        // matching certificate.
        if (!(store_search_flags & CERT_STORE_SIGNATURE_FLAG)) {
          // No need to dupe; reference is held.
          issuer_cert.reset(previous_cert);
          break;
        }
      }
      if (issuer_cert)
        break;
      if (GetLastError() == static_cast<DWORD>(CRYPT_E_SELF_SIGNED)) {
        issuer_cert.reset(CertDuplicateCertificateContext(subject_cert));
        break;
      }
    }

    // At this point, the Microsoft provider opens up the "CA", "Root", and
    // "SPC" stores to search for the issuer certificate, if not found in the
    // caller-supplied stores. It is unclear whether that is necessary here.
  }

  if (!issuer_cert) {
    // Rather than return CRYPT_E_NO_REVOCATION_CHECK (indicating everything
    // is fine to try the next provider), return CRYPT_E_REVOCATION_OFFLINE.
    // This propogates up to the caller as an error while checking revocation,
    // which is the desired intent if there are certificates that cannot
    // be checked.
    revocation_status->dwIndex = 0;
    revocation_status->dwError = static_cast<DWORD>(CRYPT_E_REVOCATION_OFFLINE);
    SetLastError(revocation_status->dwError);
    return FALSE;
  }

  std::string unused;
  CRLSetResult result = CheckRevocationWithCRLSet(crl_set, subject_cert,
                                                  issuer_cert.get(), &unused);
  if (result == kCRLSetRevoked) {
    revocation_status->dwError = static_cast<DWORD>(CRYPT_E_REVOKED);
    revocation_status->dwReason = CRL_REASON_UNSPECIFIED;
    SetLastError(revocation_status->dwError);
    return FALSE;
  }

  // The result is ALWAYS FALSE in order to allow the next revocation provider
  // a chance to examine. The only difference is whether or not an error is
  // indicated via dwError (and SetLastError()).
  // Reset the error index so that Windows does not believe this code has
  // examined the entire chain and found no issues until the last cert (thus
  // skipping other revocation providers).
  revocation_status->dwIndex = 0;
  return FALSE;
}

class ScopedThreadLocalCRLSet {
 public:
  explicit ScopedThreadLocalCRLSet(CRLSet* crl_set) {
    g_revocation_injector.Get().SetCRLSet(crl_set);
  }
  ~ScopedThreadLocalCRLSet() { g_revocation_injector.Get().SetCRLSet(nullptr); }
};

}  // namespace

CertVerifyProcWin::CertVerifyProcWin() {}

CertVerifyProcWin::~CertVerifyProcWin() {}

bool CertVerifyProcWin::SupportsAdditionalTrustAnchors() const {
  return false;
}

int CertVerifyProcWin::VerifyInternal(
    X509Certificate* cert,
    const std::string& hostname,
    const std::string& ocsp_response,
    const std::string& sct_list,
    int flags,
    CRLSet* crl_set,
    const CertificateList& additional_trust_anchors,
    CertVerifyResult* verify_result) {
  // Ensure the Revocation Provider has been installed and configured for this
  // CRLSet.
  ScopedThreadLocalCRLSet thread_local_crlset(crl_set);

  ScopedPCCERT_CONTEXT cert_list = x509_util::CreateCertContextWithChain(
      cert, x509_util::InvalidIntermediateBehavior::kIgnore);
  if (!cert_list) {
    verify_result->cert_status |= CERT_STATUS_INVALID;
    return ERR_CERT_INVALID;
  }

  // Build and validate certificate chain.
  CERT_CHAIN_PARA chain_para;
  memset(&chain_para, 0, sizeof(chain_para));
  chain_para.cbSize = sizeof(chain_para);
  // ExtendedKeyUsage.
  // We still need to request szOID_SERVER_GATED_CRYPTO and szOID_SGC_NETSCAPE
  // today because some certificate chains need them.  IE also requests these
  // two usages.
  static const LPCSTR usage[] = {
    szOID_PKIX_KP_SERVER_AUTH,
    szOID_SERVER_GATED_CRYPTO,
    szOID_SGC_NETSCAPE
  };
  chain_para.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
  chain_para.RequestedUsage.Usage.cUsageIdentifier = base::size(usage);
  chain_para.RequestedUsage.Usage.rgpszUsageIdentifier =
      const_cast<LPSTR*>(usage);

  // Get the certificatePolicies extension of the certificate.
  std::unique_ptr<CERT_POLICIES_INFO, base::FreeDeleter> policies_info;
  LPSTR ev_policy_oid = nullptr;
  GetCertPoliciesInfo(cert_list.get(), &policies_info);
  if (policies_info) {
    EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance();
    for (DWORD i = 0; i < policies_info->cPolicyInfo; ++i) {
      LPSTR policy_oid = policies_info->rgPolicyInfo[i].pszPolicyIdentifier;
      if (metadata->IsEVPolicyOID(policy_oid)) {
        ev_policy_oid = policy_oid;
        chain_para.RequestedIssuancePolicy.dwType = USAGE_MATCH_TYPE_AND;
        chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 1;
        chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier =
            &ev_policy_oid;

        // De-prioritize the CA/Browser forum Extended Validation policy
        // (2.23.140.1.1). See https://crbug.com/705285.
        if (!EVRootCAMetadata::IsCaBrowserForumEvOid(ev_policy_oid))
          break;
      }
    }
  }

  // Revocation checking is always enabled, in order to enable CRLSets to be
  // evaluated as part of a revocation provider. However, when the caller did
  // not explicitly request revocation checking (which is to say, online
  // revocation checking), then only enable cached results. This disables OCSP
  // and CRL fetching, but still allows the revocation provider to be called.
  // Note: The root cert is also checked for revocation status, so that CRLSets
  // will cover revoked SPKIs.
  DWORD chain_flags = CERT_CHAIN_REVOCATION_CHECK_CHAIN;
  bool rev_checking_enabled = (flags & VERIFY_REV_CHECKING_ENABLED);
  if (rev_checking_enabled) {
    verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
  } else {
    chain_flags |= CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY;
  }

  // By default, use the default HCERTCHAINENGINE (aka HCCE_CURRENT_USER). When
  // running tests, use a dynamic HCERTCHAINENGINE. All of the status and cache
  // of verified certificates and chains is tied to the HCERTCHAINENGINE. As
  // each invocation may have changed the set of known roots, invalidate the
  // cache between runs.
  //
  // This is not the most efficient means of doing so; it's possible to mark the
  // Root store used by TestRootCerts as changed, via CertControlStore with the
  // CERT_STORE_CTRL_NOTIFY_CHANGE / CERT_STORE_CTRL_RESYNC, but that's more
  // complexity for what is test-only code.
  ScopedHCERTCHAINENGINE chain_engine(NULL);
  if (TestRootCerts::HasInstance())
    chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine());

  // Add stapled OCSP response data, which will be preferred over online checks
  // and used when in cache-only mode.
  if (!ocsp_response.empty()) {
    CRYPT_DATA_BLOB ocsp_response_blob;
    ocsp_response_blob.cbData = base::checked_cast<DWORD>(ocsp_response.size());
    ocsp_response_blob.pbData =
        reinterpret_cast<BYTE*>(const_cast<char*>(ocsp_response.data()));
    CertSetCertificateContextProperty(
        cert_list.get(), CERT_OCSP_RESPONSE_PROP_ID,
        CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG, &ocsp_response_blob);
  }

  CERT_STRONG_SIGN_SERIALIZED_INFO strong_signed_info;
  memset(&strong_signed_info, 0, sizeof(strong_signed_info));
  strong_signed_info.dwFlags = 0;  // Don't check OCSP or CRL signatures.

  // Note that the following two configurations result in disabling support for
  // any CNG-added algorithms, which may result in some disruption for internal
  // PKI operations that use national forms of crypto (e.g. GOST). However, the
  // fallback mechanism for this (to support SHA-1 chains) will re-enable them,
  // so they should continue to work - just with added latency.
  wchar_t hash_algs[] =
      L"RSA/SHA256;RSA/SHA384;RSA/SHA512;"
      L"ECDSA/SHA256;ECDSA/SHA384;ECDSA/SHA512";
  strong_signed_info.pwszCNGSignHashAlgids = hash_algs;

  // RSA-1024 bit support is intentionally enabled here. More investigation is
  // needed to determine if setting CERT_STRONG_SIGN_DISABLE_END_CHECK_FLAG in
  // the dwStrongSignFlags of |chain_para| would allow the ability to disable
  // support for intermediates/roots < 2048-bits, while still ensuring that
  // end-entity certs signed with SHA-1 are flagged/rejected.
  wchar_t key_sizes[] = L"RSA/1024;ECDSA/256";
  strong_signed_info.pwszCNGPubKeyMinBitLengths = key_sizes;

  CERT_STRONG_SIGN_PARA strong_sign_params;
  memset(&strong_sign_params, 0, sizeof(strong_sign_params));
  strong_sign_params.cbSize = sizeof(strong_sign_params);
  strong_sign_params.dwInfoChoice = CERT_STRONG_SIGN_SERIALIZED_INFO_CHOICE;
  strong_sign_params.pSerializedInfo = &strong_signed_info;

  chain_para.dwStrongSignFlags = 0;
  chain_para.pStrongSignPara = &strong_sign_params;

  PCCERT_CHAIN_CONTEXT chain_context = nullptr;

  // First, try to verify with strong signing enabled. If this fails, or if the
  // chain is rejected, then clear it from |chain_para| so that all subsequent
  // calls will use the fallback path.
  BOOL chain_result =
      CertGetCertificateChain(chain_engine, cert_list.get(),
                              nullptr,  // current system time
                              cert_list->hCertStore, &chain_para, chain_flags,
                              nullptr,  // reserved
                              &chain_context);
  if (chain_result && chain_context &&
      (chain_context->TrustStatus.dwErrorStatus &
       (CERT_TRUST_HAS_WEAK_SIGNATURE | CERT_TRUST_IS_NOT_SIGNATURE_VALID))) {
    // The attempt to verify with strong-sign (only SHA-2) failed, so fall back
    // to disabling it. This will allow SHA-1 chains to be returned, which will
    // then be subsequently signalled as weak if necessary.
    CertFreeCertificateChain(chain_context);
    chain_context = nullptr;

    chain_para.pStrongSignPara = nullptr;
    chain_para.dwStrongSignFlags = 0;
    chain_result =
        CertGetCertificateChain(chain_engine, cert_list.get(),
                                nullptr,  // current system time
                                cert_list->hCertStore, &chain_para, chain_flags,
                                nullptr,  // reserved
                                &chain_context);
  }

  if (!chain_result) {
    verify_result->cert_status |= CERT_STATUS_INVALID;
    return MapSecurityError(GetLastError());
  }

  // Perform a second check with CRLSets. Although the Revocation Provider
  // should have prevented invalid paths from being built, the behaviour and
  // timing of how a Revocation Provider is invoked is not well documented. This
  // is just defense in depth.
  CRLSetResult crl_set_result =
      CheckChainRevocationWithCRLSet(chain_context, crl_set);

  if (crl_set_result == kCRLSetRevoked) {
    verify_result->cert_status |= CERT_STATUS_REVOKED;
  } else if (crl_set_result == kCRLSetUnknown && !rev_checking_enabled &&
             ev_policy_oid) {
    // We don't have fresh information about this chain from the CRLSet and
    // it's probably an EV certificate. Retry with online revocation checking.
    rev_checking_enabled = true;
    chain_flags &= ~CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY;
    verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;

    CertFreeCertificateChain(chain_context);
    if (!CertGetCertificateChain(chain_engine, cert_list.get(),
                                 nullptr,  // current system time
                                 cert_list->hCertStore, &chain_para,
                                 chain_flags,
                                 nullptr,  // reserved
                                 &chain_context)) {
      verify_result->cert_status |= CERT_STATUS_INVALID;
      return MapSecurityError(GetLastError());
    }
  }

  if (chain_context->TrustStatus.dwErrorStatus &
      CERT_TRUST_IS_NOT_VALID_FOR_USAGE) {
    // Could not verify the cert with the EV policy. Remove the EV policy and
    // try again.
    ev_policy_oid = nullptr;
    chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 0;
    chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = nullptr;
    CertFreeCertificateChain(chain_context);
    if (!CertGetCertificateChain(chain_engine, cert_list.get(),
                                 nullptr,  // current system time
                                 cert_list->hCertStore, &chain_para,
                                 chain_flags,
                                 nullptr,  // reserved
                                 &chain_context)) {
      verify_result->cert_status |= CERT_STATUS_INVALID;
      return MapSecurityError(GetLastError());
    }
  }

  CertVerifyResult temp_verify_result = *verify_result;
  GetCertChainInfo(chain_context, verify_result);
  if (!verify_result->is_issued_by_known_root &&
      (flags & VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS)) {
    *verify_result = temp_verify_result;

    rev_checking_enabled = true;
    verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
    chain_flags &= ~CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY;

    CertFreeCertificateChain(chain_context);
    if (!CertGetCertificateChain(chain_engine, cert_list.get(),
                                 nullptr,  // current system time
                                 cert_list->hCertStore, &chain_para,
                                 chain_flags,
                                 nullptr,  // reserved
                                 &chain_context)) {
      verify_result->cert_status |= CERT_STATUS_INVALID;
      return MapSecurityError(GetLastError());
    }
    GetCertChainInfo(chain_context, verify_result);
  }

  ScopedPCCERT_CHAIN_CONTEXT scoped_chain_context(chain_context);

  verify_result->cert_status |= MapCertChainErrorStatusToCertStatus(
      chain_context->TrustStatus.dwErrorStatus);

  // Flag certificates that have a Subject common name with a NULL character.
  if (CertSubjectCommonNameHasNull(cert_list.get()))
    verify_result->cert_status |= CERT_STATUS_INVALID;

  base::string16 hostname16 = base::ASCIIToUTF16(hostname);

  SSL_EXTRA_CERT_CHAIN_POLICY_PARA extra_policy_para;
  memset(&extra_policy_para, 0, sizeof(extra_policy_para));
  extra_policy_para.cbSize = sizeof(extra_policy_para);
  extra_policy_para.dwAuthType = AUTHTYPE_SERVER;
  // Certificate name validation happens separately, later, using an internal
  // routine that has better support for RFC 6125 name matching.
  extra_policy_para.fdwChecks =
      0x00001000;  // SECURITY_FLAG_IGNORE_CERT_CN_INVALID
  extra_policy_para.pwszServerName = base::as_writable_wcstr(hostname16);

  CERT_CHAIN_POLICY_PARA policy_para;
  memset(&policy_para, 0, sizeof(policy_para));
  policy_para.cbSize = sizeof(policy_para);
  policy_para.dwFlags = 0;
  policy_para.pvExtraPolicyPara = &extra_policy_para;

  CERT_CHAIN_POLICY_STATUS policy_status;
  memset(&policy_status, 0, sizeof(policy_status));
  policy_status.cbSize = sizeof(policy_status);

  if (!CertVerifyCertificateChainPolicy(
           CERT_CHAIN_POLICY_SSL,
           chain_context,
           &policy_para,
           &policy_status)) {
    return MapSecurityError(GetLastError());
  }

  if (policy_status.dwError) {
    verify_result->cert_status |= MapNetErrorToCertStatus(
        MapSecurityError(policy_status.dwError));
  }

  // Mask off revocation checking failures unless hard-fail revocation checking
  // for local anchors is enabled and the chain is issued by a local root.
  // (CheckEV will still check chain_context->TrustStatus.dwErrorStatus directly
  // so as to not mark as EV if revocation information was not available.)
  if (!(!verify_result->is_issued_by_known_root &&
        (flags & VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS))) {
    verify_result->cert_status &= ~(CERT_STATUS_NO_REVOCATION_MECHANISM |
                                    CERT_STATUS_UNABLE_TO_CHECK_REVOCATION);
  }

  AppendPublicKeyHashesAndUpdateKnownRoot(
      chain_context, &verify_result->public_key_hashes,
      &verify_result->is_issued_by_known_root);

  if (IsCertStatusError(verify_result->cert_status))
    return MapCertStatusToNetError(verify_result->cert_status);

  if (ev_policy_oid &&
      CheckEV(chain_context, rev_checking_enabled, ev_policy_oid)) {
    verify_result->cert_status |= CERT_STATUS_IS_EV;
  }

  LogNameNormalizationMetrics(".Win", verify_result->verified_cert.get(),
                              verify_result->is_issued_by_known_root);

  return OK;
}

}  // namespace net
