// 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"
#include "starboard/memory.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_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 = NULL;
  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 = NULL;
  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 = NULL;
  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(
        NULL, 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;
  SbMemorySet(&local_params, 0, sizeof(local_params));
  if (revocation_params) {
    DWORD bytes_to_copy = std::min(revocation_params->cbSize,
                                   static_cast<DWORD>(sizeof(local_params)));
    SbMemoryCopy(&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,
    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;
  SbMemorySet(&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 = NULL;
  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 = 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;
  SbMemorySet(&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;
  SbMemorySet(&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(),
                              NULL,  // current system time
                              cert_list->hCertStore, &chain_para, chain_flags,
                              NULL,  // 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(),
                                NULL,  // current system time
                                cert_list->hCertStore, &chain_para, chain_flags,
                                NULL,  // 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 = kCRLSetUnknown;
  if (crl_set)
    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(),
             NULL,  // current system time
             cert_list->hCertStore,
             &chain_para,
             chain_flags,
             NULL,  // 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) {
    ev_policy_oid = NULL;
    chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 0;
    chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = NULL;
    CertFreeCertificateChain(chain_context);
    if (!CertGetCertificateChain(
             chain_engine,
             cert_list.get(),
             NULL,  // current system time
             cert_list->hCertStore,
             &chain_para,
             chain_flags,
             NULL,  // 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(),
             NULL,  // current system time
             cert_list->hCertStore,
             &chain_para,
             chain_flags,
             NULL,  // reserved
             &chain_context)) {
      verify_result->cert_status |= CERT_STATUS_INVALID;
      return MapSecurityError(GetLastError());
    }
    GetCertChainInfo(chain_context, verify_result);

    if (chain_context->TrustStatus.dwErrorStatus &
        CERT_TRUST_IS_OFFLINE_REVOCATION) {
      verify_result->cert_status |= CERT_STATUS_REVOKED;
    }
  }

  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;
  SbMemorySet(&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 =
      const_cast<base::char16*>(hostname16.c_str());

  CERT_CHAIN_POLICY_PARA policy_para;
  SbMemorySet(&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;
  SbMemorySet(&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));
  }

  // TODO(wtc): Suppress CERT_STATUS_NO_REVOCATION_MECHANISM for now to be
  // compatible with WinHTTP, which doesn't report this error (bug 3004).
  verify_result->cert_status &= ~CERT_STATUS_NO_REVOCATION_MECHANISM;

  if (!rev_checking_enabled) {
    // If we didn't do online revocation checking then Windows will report
    // CERT_UNABLE_TO_CHECK_REVOCATION unless it had cached OCSP or CRL
    // information for every certificate. We only want to put up revoked
    // statuses from the offline checks so we squash this error.
    verify_result->cert_status &= ~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;
  }
  return OK;
}

}  // namespace net
