// 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_mac.h"

#include <CommonCrypto/CommonDigest.h>
#include <CoreServices/CoreServices.h>
#include <Security/Security.h>

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

#include "base/logging.h"
#include "base/mac/mac_logging.h"
#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/strings/string_piece.h"
#include "base/synchronization/lock.h"
#include "crypto/mac_security_services_lock.h"
#include "crypto/sha2.h"
#include "net/base/hash_value.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/internal/certificate_policies.h"
#include "net/cert/internal/parsed_certificate.h"
#include "net/cert/known_roots.h"
#include "net/cert/known_roots_mac.h"
#include "net/cert/test_keychain_search_list_mac.h"
#include "net/cert/test_root_certs.h"
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util.h"
#include "net/cert/x509_util_ios_and_mac.h"
#include "net/cert/x509_util_mac.h"

// CSSM functions are deprecated as of OSX 10.7, but have no replacement.
// https://bugs.chromium.org/p/chromium/issues/detail?id=590914#c1
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"

using base::ScopedCFTypeRef;

namespace net {

namespace {

typedef OSStatus (*SecTrustCopyExtendedResultFuncPtr)(SecTrustRef,
                                                      CFDictionaryRef*);

int NetErrorFromOSStatus(OSStatus status) {
  switch (status) {
    case noErr:
      return OK;
    case errSecNotAvailable:
    case errSecNoCertificateModule:
    case errSecNoPolicyModule:
      return ERR_NOT_IMPLEMENTED;
    case errSecAuthFailed:
      return ERR_ACCESS_DENIED;
    default: {
      OSSTATUS_LOG(ERROR, status) << "Unknown error mapped to ERR_FAILED";
      return ERR_FAILED;
    }
  }
}

CertStatus CertStatusFromOSStatus(OSStatus status) {
  switch (status) {
    case noErr:
      return 0;

    case CSSMERR_TP_INVALID_ANCHOR_CERT:
    case CSSMERR_TP_NOT_TRUSTED:
    case CSSMERR_TP_INVALID_CERT_AUTHORITY:
      return CERT_STATUS_AUTHORITY_INVALID;

    case CSSMERR_TP_CERT_EXPIRED:
    case CSSMERR_TP_CERT_NOT_VALID_YET:
      // "Expired" and "not yet valid" collapse into a single status.
      return CERT_STATUS_DATE_INVALID;

    case CSSMERR_TP_CERT_REVOKED:
    case CSSMERR_TP_CERT_SUSPENDED:
      return CERT_STATUS_REVOKED;

    case CSSMERR_APPLETP_HOSTNAME_MISMATCH:
      return CERT_STATUS_COMMON_NAME_INVALID;

    case CSSMERR_APPLETP_CRL_NOT_FOUND:
    case CSSMERR_APPLETP_OCSP_UNAVAILABLE:
      return CERT_STATUS_NO_REVOCATION_MECHANISM;

    case CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK:
      // Starting with later 10.12 versions,
      // CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK is a catch-all code for
      // failures to check revocation status.
      // However, on pre-10.12 versions, it would also be used on revocation
      // failures. (CERT_STATUS_NO_REVOCATION_MECHANISM isn't really right
      // there either, but that's what the old code has, and it just gets
      // masked off later so has no actual effect.)
      return base::mac::IsAtLeastOS10_12()
                 ? CERT_STATUS_UNABLE_TO_CHECK_REVOCATION
                 : CERT_STATUS_NO_REVOCATION_MECHANISM;

    case CSSMERR_APPLETP_CRL_EXPIRED:
    case CSSMERR_APPLETP_CRL_NOT_VALID_YET:
    case CSSMERR_APPLETP_CRL_SERVER_DOWN:
    case CSSMERR_APPLETP_CRL_NOT_TRUSTED:
    case CSSMERR_APPLETP_CRL_INVALID_ANCHOR_CERT:
    case CSSMERR_APPLETP_CRL_POLICY_FAIL:
    case CSSMERR_APPLETP_OCSP_BAD_RESPONSE:
    case CSSMERR_APPLETP_OCSP_BAD_REQUEST:
    case CSSMERR_APPLETP_OCSP_STATUS_UNRECOGNIZED:
    case CSSMERR_APPLETP_NETWORK_FAILURE:
    case CSSMERR_APPLETP_OCSP_NOT_TRUSTED:
    case CSSMERR_APPLETP_OCSP_INVALID_ANCHOR_CERT:
    case CSSMERR_APPLETP_OCSP_SIG_ERROR:
    case CSSMERR_APPLETP_OCSP_NO_SIGNER:
    case CSSMERR_APPLETP_OCSP_RESP_MALFORMED_REQ:
    case CSSMERR_APPLETP_OCSP_RESP_INTERNAL_ERR:
    case CSSMERR_APPLETP_OCSP_RESP_TRY_LATER:
    case CSSMERR_APPLETP_OCSP_RESP_SIG_REQUIRED:
    case CSSMERR_APPLETP_OCSP_RESP_UNAUTHORIZED:
    case CSSMERR_APPLETP_OCSP_NONCE_MISMATCH:
      // We asked for a revocation check, but didn't get it.
      return CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;

    case CSSMERR_APPLETP_SSL_BAD_EXT_KEY_USE:
      // TODO(wtc): Should we add CERT_STATUS_WRONG_USAGE?
      return CERT_STATUS_INVALID;

    case CSSMERR_APPLETP_CRL_BAD_URI:
    case CSSMERR_APPLETP_IDP_FAIL:
      return CERT_STATUS_INVALID;

    case CSSMERR_CSP_UNSUPPORTED_KEY_SIZE:
      // Mapping UNSUPPORTED_KEY_SIZE to CERT_STATUS_WEAK_KEY is not strictly
      // accurate, as the error may have been returned due to a key size
      // that exceeded the maximum supported. However, within
      // CertVerifyProcMac::VerifyInternal(), this code should only be
      // encountered as a certificate status code, and only when the key size
      // is smaller than the minimum required (1024 bits).
      return CERT_STATUS_WEAK_KEY;

    default: {
      // Failure was due to something Chromium doesn't define a
      // specific status for (such as basic constraints violation, or
      // unknown critical extension)
      OSSTATUS_LOG(WARNING, status)
          << "Unknown error mapped to CERT_STATUS_INVALID";
      return CERT_STATUS_INVALID;
    }
  }
}

// Creates a series of SecPolicyRefs to be added to a SecTrustRef used to
// validate a certificate for an SSL server. |flags| is a bitwise-OR of
// VerifyFlags that can further alter how trust is validated, such as how
// revocation is checked. If successful, returns noErr, and stores the
// resultant array of SecPolicyRefs in |policies|.
OSStatus CreateTrustPolicies(int flags, ScopedCFTypeRef<CFArrayRef>* policies) {
  ScopedCFTypeRef<CFMutableArrayRef> local_policies(
      CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks));
  if (!local_policies)
    return memFullErr;

  SecPolicyRef ssl_policy;
  OSStatus status =
      x509_util::CreateSSLServerPolicy(std::string(), &ssl_policy);
  if (status)
    return status;
  CFArrayAppendValue(local_policies, ssl_policy);
  CFRelease(ssl_policy);

  // Explicitly add revocation policies, in order to override system
  // revocation checking policies and instead respect the application-level
  // revocation preference.
  status = x509_util::CreateRevocationPolicies(
      (flags & CertVerifyProc::VERIFY_REV_CHECKING_ENABLED), local_policies);
  if (status)
    return status;

  policies->reset(local_policies.release());
  return noErr;
}

// Stores the constructed certificate chain |cert_chain| into
// |*verify_result|. |cert_chain| must not be empty.
void CopyCertChainToVerifyResult(CFArrayRef cert_chain,
                                 CertVerifyResult* verify_result) {
  DCHECK_LT(0, CFArrayGetCount(cert_chain));

  SecCertificateRef verified_cert = NULL;
  std::vector<SecCertificateRef> verified_chain;
  for (CFIndex i = 0, count = CFArrayGetCount(cert_chain); i < count; ++i) {
    SecCertificateRef chain_cert = reinterpret_cast<SecCertificateRef>(
        const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i)));
    if (i == 0) {
      verified_cert = chain_cert;
    } else {
      verified_chain.push_back(chain_cert);
    }
  }
  if (!verified_cert) {
    NOTREACHED();
    verify_result->cert_status |= CERT_STATUS_INVALID;
    return;
  }

  scoped_refptr<X509Certificate> verified_cert_with_chain =
      x509_util::CreateX509CertificateFromSecCertificate(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;
}

// Returns true if the certificate uses MD2, MD4, MD5, or SHA1, and false
// otherwise. A return of false also includes the case where the signature
// algorithm couldn't be conclusively labeled as weak.
bool CertUsesWeakHash(SecCertificateRef cert_handle) {
  x509_util::CSSMCachedCertificate cached_cert;
  OSStatus status = cached_cert.Init(cert_handle);
  if (status)
    return false;

  x509_util::CSSMFieldValue signature_field;
  status =
      cached_cert.GetField(&CSSMOID_X509V1SignatureAlgorithm, &signature_field);
  if (status || !signature_field.field())
    return false;

  const CSSM_X509_ALGORITHM_IDENTIFIER* sig_algorithm =
      signature_field.GetAs<CSSM_X509_ALGORITHM_IDENTIFIER>();
  if (!sig_algorithm)
    return false;

  const CSSM_OID* alg_oid = &sig_algorithm->algorithm;

  return (x509_util::CSSMOIDEqual(alg_oid, &CSSMOID_MD2WithRSA) ||
          x509_util::CSSMOIDEqual(alg_oid, &CSSMOID_MD4WithRSA) ||
          x509_util::CSSMOIDEqual(alg_oid, &CSSMOID_MD5WithRSA) ||
          x509_util::CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithRSA) ||
          x509_util::CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithRSA_OIW) ||
          x509_util::CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA) ||
          x509_util::CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA_CMS) ||
          x509_util::CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA_JDK) ||
          x509_util::CSSMOIDEqual(alg_oid, &CSSMOID_ECDSA_WithSHA1));
}

// Returns true if the intermediates (excluding trusted certificates) use a
// weak hashing algorithm, but the target does not use a weak hash.
bool IsWeakChainBasedOnHashingAlgorithms(
    CFArrayRef cert_chain,
    CSSM_TP_APPLE_EVIDENCE_INFO* chain_info) {
  DCHECK_LT(0, CFArrayGetCount(cert_chain));

  bool intermediates_contain_weak_hash = false;
  bool leaf_uses_weak_hash = false;

  for (CFIndex i = 0, count = CFArrayGetCount(cert_chain); i < count; ++i) {
    SecCertificateRef chain_cert = reinterpret_cast<SecCertificateRef>(
        const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i)));

    if ((chain_info[i].StatusBits & CSSM_CERT_STATUS_IS_IN_ANCHORS) ||
        (chain_info[i].StatusBits & CSSM_CERT_STATUS_IS_ROOT)) {
      // The current certificate is either in the user's trusted store or is
      // a root (self-signed) certificate. Ignore the signature algorithm for
      // these certificates, as it is meaningless for security. We allow
      // self-signed certificates (i == 0 & IS_ROOT), since we accept that
      // any security assertions by such a cert are inherently meaningless.
      continue;
    }

    if (CertUsesWeakHash(chain_cert)) {
      if (i == 0) {
        leaf_uses_weak_hash = true;
      } else {
        intermediates_contain_weak_hash = true;
      }
    }
  }

  return !leaf_uses_weak_hash && intermediates_contain_weak_hash;
}

// Checks if |*cert| has a Certificate Policies extension containing either
// of |ev_policy_oid| or anyPolicy.
bool HasPolicyOrAnyPolicy(const ParsedCertificate* cert,
                          const der::Input& ev_policy_oid) {
  if (!cert->has_policy_oids())
    return false;

  for (const der::Input& policy_oid : cert->policy_oids()) {
    if (policy_oid == ev_policy_oid || policy_oid == AnyPolicy())
      return true;
  }
  return false;
}

// Looks for known EV policy OIDs in |cert_input|, if one is found it will be
// stored in |*ev_policy_oid| as a DER-encoded OID value (no tag or length).
void GetCandidateEVPolicy(const X509Certificate* cert_input,
                          std::string* ev_policy_oid) {
  ev_policy_oid->clear();

  scoped_refptr<ParsedCertificate> cert(ParsedCertificate::Create(
      bssl::UpRef(cert_input->cert_buffer()), {}, nullptr));
  if (!cert)
    return;

  if (!cert->has_policy_oids())
    return;

  EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance();
  for (const der::Input& policy_oid : cert->policy_oids()) {
    if (metadata->IsEVPolicyOID(policy_oid)) {
      *ev_policy_oid = policy_oid.AsString();

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

// Checks that the certificate chain of |cert| has policies consistent with
// |ev_policy_oid_string|. The leaf is not checked, as it is assumed that is
// where the policy came from.
bool CheckCertChainEV(const X509Certificate* cert,
                      const std::string& ev_policy_oid_string) {
  der::Input ev_policy_oid(&ev_policy_oid_string);
  const std::vector<bssl::UniquePtr<CRYPTO_BUFFER>>& cert_chain =
      cert->intermediate_buffers();

  // Root should have matching policy in EVRootCAMetadata.
  if (cert_chain.empty())
    return false;
  SHA256HashValue fingerprint =
      X509Certificate::CalculateFingerprint256(cert_chain.back().get());
  EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance();
  if (!metadata->HasEVPolicyOID(fingerprint, ev_policy_oid))
    return false;

  // Intermediates should have Certificate Policies extension with the EV policy
  // or AnyPolicy.
  for (size_t i = 0; i < cert_chain.size() - 1; ++i) {
    scoped_refptr<ParsedCertificate> intermediate_cert(
        ParsedCertificate::Create(bssl::UpRef(cert_chain[i].get()), {},
                                  nullptr));
    if (!intermediate_cert)
      return false;
    if (!HasPolicyOrAnyPolicy(intermediate_cert.get(), ev_policy_oid))
      return false;
  }

  return true;
}

void AppendPublicKeyHashesAndUpdateKnownRoot(CFArrayRef chain,
                                             HashValueVector* hashes,
                                             bool* known_root) {
  // Walk the chain in reverse, to optimize for IsKnownRoot checks.
  for (CFIndex i = CFArrayGetCount(chain); i > 0; i--) {
    SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(
        const_cast<void*>(CFArrayGetValueAtIndex(chain, i - 1)));

    CSSM_DATA cert_data;
    OSStatus err = SecCertificateGetData(cert, &cert_data);
    DCHECK_EQ(err, noErr);
    base::StringPiece der_bytes(reinterpret_cast<const char*>(cert_data.Data),
                               cert_data.Length);
    base::StringPiece spki_bytes;
    if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes))
      continue;

    HashValue sha256(HASH_VALUE_SHA256);
    CC_SHA256(spki_bytes.data(), spki_bytes.size(), sha256.data());
    hashes->push_back(sha256);

    if (!*known_root) {
      *known_root =
          GetNetTrustAnchorHistogramIdForSPKI(sha256) != 0 || IsKnownRoot(cert);
    }
  }
  // Reverse the hash array, to maintain the leaf-first ordering.
  std::reverse(hashes->begin(), hashes->end());
}

enum CRLSetResult {
  kCRLSetOk,
  kCRLSetRevoked,
  kCRLSetUnknown,
};

// CheckRevocationWithCRLSet attempts to check each element of |cert_list|
// 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 CheckRevocationWithCRLSet(CFArrayRef chain, CRLSet* crl_set) {
  if (CFArrayGetCount(chain) == 0)
    return kCRLSetOk;

  // error is set to true if any errors are found. It causes such chains to be
  // considered as not covered.
  bool error = false;
  // last_covered is set to the coverage state of the previous certificate. The
  // certificates are iterated over backwards thus, after the iteration,
  // |last_covered| contains the coverage state of the leaf certificate.
  bool last_covered = false;

  // We iterate from the root certificate down to the leaf, keeping track of
  // the issuer's SPKI at each step.
  std::string issuer_spki_hash;
  for (CFIndex i = CFArrayGetCount(chain); i > 0; i--) {
    SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(
        const_cast<void*>(CFArrayGetValueAtIndex(chain, i - 1)));

    CSSM_DATA cert_data;
    OSStatus err = SecCertificateGetData(cert, &cert_data);
    if (err != noErr) {
      NOTREACHED();
      error = true;
      continue;
    }
    base::StringPiece der_bytes(reinterpret_cast<const char*>(cert_data.Data),
                                cert_data.Length);
    base::StringPiece spki, subject;
    if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki) ||
        !asn1::ExtractSubjectFromDERCert(der_bytes, &subject)) {
      NOTREACHED();
      error = true;
      continue;
    }

    const std::string spki_hash = crypto::SHA256HashString(spki);
    x509_util::CSSMCachedCertificate cached_cert;
    if (cached_cert.Init(cert) != CSSM_OK) {
      NOTREACHED();
      error = true;
      continue;
    }
    x509_util::CSSMFieldValue serial_number;
    err = cached_cert.GetField(&CSSMOID_X509V1SerialNumber, &serial_number);
    if (err || !serial_number.field()) {
      NOTREACHED();
      error = true;
      continue;
    }

    base::StringPiece serial(
        reinterpret_cast<const char*>(serial_number.field()->Data),
        serial_number.field()->Length);

    CRLSet::Result result = crl_set->CheckSPKI(spki_hash);

    if (result != CRLSet::REVOKED)
      result = crl_set->CheckSubject(subject, spki_hash);
    if (result != CRLSet::REVOKED && !issuer_spki_hash.empty())
      result = crl_set->CheckSerial(serial, issuer_spki_hash);

    issuer_spki_hash = spki_hash;

    switch (result) {
      case CRLSet::REVOKED:
        return kCRLSetRevoked;
      case CRLSet::UNKNOWN:
        last_covered = false;
        continue;
      case CRLSet::GOOD:
        last_covered = true;
        continue;
      default:
        NOTREACHED();
        error = true;
        continue;
    }
  }

  if (error || !last_covered || crl_set->IsExpired())
    return kCRLSetUnknown;
  return kCRLSetOk;
}

// Builds and evaluates a SecTrustRef for the certificate chain contained
// in |cert_array|, using the verification policies in |trust_policies|. On
// success, returns OK, and updates |trust_ref|, |trust_result|,
// |verified_chain|, and |chain_info| with the verification results. On
// failure, no output parameters are modified.
//
// Note: An OK return does not mean that |cert_array| is trusted, merely that
// verification was performed successfully.
//
// This function should only be called while the Mac Security Services lock is
// held.
int BuildAndEvaluateSecTrustRef(CFArrayRef cert_array,
                                CFArrayRef trust_policies,
                                int flags,
                                CFArrayRef keychain_search_list,
                                ScopedCFTypeRef<SecTrustRef>* trust_ref,
                                SecTrustResultType* trust_result,
                                ScopedCFTypeRef<CFArrayRef>* verified_chain,
                                CSSM_TP_APPLE_EVIDENCE_INFO** chain_info) {
  SecTrustRef tmp_trust = NULL;
  OSStatus status = SecTrustCreateWithCertificates(cert_array, trust_policies,
                                                   &tmp_trust);
  if (status)
    return NetErrorFromOSStatus(status);
  ScopedCFTypeRef<SecTrustRef> scoped_tmp_trust(tmp_trust);

  if (TestRootCerts::HasInstance()) {
    status = TestRootCerts::GetInstance()->FixupSecTrustRef(tmp_trust);
    if (status)
      return NetErrorFromOSStatus(status);
  }

  if (keychain_search_list) {
    status = SecTrustSetKeychains(tmp_trust, keychain_search_list);
    if (status)
      return NetErrorFromOSStatus(status);
  }

  CSSM_APPLE_TP_ACTION_DATA tp_action_data;
  memset(&tp_action_data, 0, sizeof(tp_action_data));
  tp_action_data.Version = CSSM_APPLE_TP_ACTION_VERSION;
  // Allow CSSM to download any missing intermediate certificates if an
  // authorityInfoAccess extension or issuerAltName extension is present.
  tp_action_data.ActionFlags = CSSM_TP_ACTION_FETCH_CERT_FROM_NET |
                               CSSM_TP_ACTION_TRUST_SETTINGS;

  // Note: For EV certificates, the Apple TP will handle setting these flags
  // as part of EV evaluation.
  if (flags & CertVerifyProc::VERIFY_REV_CHECKING_ENABLED) {
    // Require a positive result from an OCSP responder or a CRL (or both)
    // for every certificate in the chain. The Apple TP automatically
    // excludes the self-signed root from this requirement. If a certificate
    // is missing both a crlDistributionPoints extension and an
    // authorityInfoAccess extension with an OCSP responder URL, then we
    // will get a kSecTrustResultRecoverableTrustFailure back from
    // SecTrustEvaluate(), with a
    // CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK error code. In that case,
    // we'll set our own result to include
    // CERT_STATUS_NO_REVOCATION_MECHANISM. If one or both extensions are
    // present, and a check fails (server unavailable, OCSP retry later,
    // signature mismatch), then we'll set our own result to include
    // CERT_STATUS_UNABLE_TO_CHECK_REVOCATION.
    tp_action_data.ActionFlags |= CSSM_TP_ACTION_REQUIRE_REV_PER_CERT;

    // Note, even if revocation checking is disabled, SecTrustEvaluate() will
    // modify the OCSP options so as to attempt OCSP checking if it believes a
    // certificate may chain to an EV root. However, because network fetches
    // are disabled in CreateTrustPolicies() when revocation checking is
    // disabled, these will only go against the local cache.
  }

  CFDataRef action_data_ref =
      CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
                                  reinterpret_cast<UInt8*>(&tp_action_data),
                                  sizeof(tp_action_data), kCFAllocatorNull);
  if (!action_data_ref)
    return ERR_OUT_OF_MEMORY;
  ScopedCFTypeRef<CFDataRef> scoped_action_data_ref(action_data_ref);
  status = SecTrustSetParameters(tmp_trust, CSSM_TP_ACTION_DEFAULT,
                                 action_data_ref);
  if (status)
    return NetErrorFromOSStatus(status);

  // Verify the certificate. A non-zero result from SecTrustGetResult()
  // indicates that some fatal error occurred and the chain couldn't be
  // processed, not that the chain contains no errors. We need to examine the
  // output of SecTrustGetResult() to determine that.
  SecTrustResultType tmp_trust_result;
  status = SecTrustEvaluate(tmp_trust, &tmp_trust_result);
  if (status)
    return NetErrorFromOSStatus(status);
  CFArrayRef tmp_verified_chain = NULL;
  CSSM_TP_APPLE_EVIDENCE_INFO* tmp_chain_info;
  status = SecTrustGetResult(tmp_trust, &tmp_trust_result, &tmp_verified_chain,
                             &tmp_chain_info);
  if (status)
    return NetErrorFromOSStatus(status);

  trust_ref->swap(scoped_tmp_trust);
  *trust_result = tmp_trust_result;
  verified_chain->reset(tmp_verified_chain);
  *chain_info = tmp_chain_info;

  return OK;
}

// Runs path building & verification loop for |cert|, given |flags|. This is
// split into a separate function so verification can be repeated with different
// flags. This function does not handle EV.
int VerifyWithGivenFlags(X509Certificate* cert,
                         const std::string& hostname,
                         const int flags,
                         CRLSet* crl_set,
                         CertVerifyResult* verify_result,
                         CRLSetResult* completed_chain_crl_result) {
  ScopedCFTypeRef<CFArrayRef> trust_policies;
  OSStatus status = CreateTrustPolicies(flags, &trust_policies);
  if (status)
    return NetErrorFromOSStatus(status);

  *completed_chain_crl_result = kCRLSetUnknown;

  // Serialize all calls that may use the Keychain, to work around various
  // issues in OS X 10.6+ with multi-threaded access to Security.framework.
  base::AutoLock lock(crypto::GetMacSecurityServicesLock());

  ScopedCFTypeRef<SecTrustRef> trust_ref;
  SecTrustResultType trust_result = kSecTrustResultDeny;
  ScopedCFTypeRef<CFArrayRef> completed_chain;
  CSSM_TP_APPLE_EVIDENCE_INFO* chain_info = NULL;
  bool candidate_untrusted = true;
  bool candidate_weak = false;

  // OS X lacks proper path discovery; it will take the input certs and never
  // backtrack the graph attempting to discover valid paths.
  // This can create issues in some situations:
  // - When OS X changes the trust store, there may be a chain
  //     A -> B -> C -> D
  //   where OS X trusts D (on some versions) and trusts C (on some versions).
  //   If a server supplies a chain A, B, C (cross-signed by D), then this chain
  //   will successfully validate on systems that trust D, but fail for systems
  //   that trust C. If the server supplies a chain of A -> B, then it forces
  //   all clients to fetch C (via AIA) if they trust D, and not all clients
  //   (notably, Firefox and Android) will do this, thus breaking them.
  //   An example of this is the Verizon Business Services root - GTE CyberTrust
  //   and Baltimore CyberTrust roots represent old and new roots that cause
  //   issues depending on which version of OS X being used.
  //
  // - A server may be (misconfigured) to send an expired intermediate
  //   certificate. On platforms with path discovery, the graph traversal
  //   will back up to immediately before this intermediate, and then
  //   attempt an AIA fetch or retrieval from local store. However, OS X
  //   does not do this, and thus prevents access. While this is ostensibly
  //   a server misconfiguration issue, the fact that it works on other
  //   platforms is a jarring inconsistency for users.
  //
  // - When OS X trusts both C and D (simultaneously), it's possible that the
  //   version of C signed by D is signed using a weak algorithm (e.g. SHA-1),
  //   while the version of C in the trust store's signature doesn't matter.
  //   Since a 'strong' chain exists, it would be desirable to prefer this
  //   chain.
  //
  // - A variant of the above example, it may be that the version of B sent by
  //   the server is signed using a weak algorithm, but the version of B
  //   present in the AIA of A is signed using a strong algorithm. Since a
  //   'strong' chain exists, it would be desirable to prefer this chain.
  //
  // - A user keychain may contain a less desirable intermediate or root.
  //   OS X gives the user keychains higher priority than the system keychain,
  //   so it may build a weak chain.
  //
  // Because of this, the code below first attempts to validate the peer's
  // identity using the supplied chain. If it is not trusted (e.g. the OS only
  // trusts C, but the version of C signed by D was sent, and D is not trusted),
  // or if it contains a weak chain, it will begin lopping off certificates
  // from the end of the chain and attempting to verify. If a stronger, trusted
  // chain is found, it is used, otherwise, the algorithm continues until only
  // the peer's certificate remains.
  //
  // If the loop does not find a trusted chain, the loop will be repeated with
  // the keychain search order altered to give priority to the System Roots
  // keychain.
  //
  // This does cause a performance hit for these users, but only in cases where
  // OS X is building weaker chains than desired, or when it would otherwise
  // fail the connection.
  for (bool try_reordered_keychain : {false, true}) {
    ScopedCFTypeRef<CFArrayRef> scoped_alternate_keychain_search_list;
    if (TestKeychainSearchList::HasInstance()) {
      // Unit tests need to be able to hermetically simulate situations where a
      // user has an undesirable certificate in a per-user keychain.
      // Adding/Removing a Keychain using SecKeychainCreate/SecKeychainDelete
      // has global side effects, which would break other tests and processes
      // running on the same machine, so instead tests may load pre-created
      // keychains using SecKeychainOpen and then inject them through
      // TestKeychainSearchList.
      CFArrayRef keychain_search_list;
      status = TestKeychainSearchList::GetInstance()->CopySearchList(
          &keychain_search_list);
      if (status)
        return NetErrorFromOSStatus(status);
      scoped_alternate_keychain_search_list.reset(keychain_search_list);
    }
    if (try_reordered_keychain) {
      // If a TestKeychainSearchList is present, it will have already set
      // |scoped_alternate_keychain_search_list|, which will be used as the
      // basis for reordering the keychain. Otherwise, get the current keychain
      // search list and use that.
      if (!scoped_alternate_keychain_search_list) {
        CFArrayRef keychain_search_list;
        status = SecKeychainCopySearchList(&keychain_search_list);
        if (status)
          return NetErrorFromOSStatus(status);
        scoped_alternate_keychain_search_list.reset(keychain_search_list);
      }
      CFMutableArrayRef mutable_keychain_search_list = CFArrayCreateMutableCopy(
          kCFAllocatorDefault,
          CFArrayGetCount(scoped_alternate_keychain_search_list.get()) + 1,
          scoped_alternate_keychain_search_list.get());
      if (!mutable_keychain_search_list)
        return ERR_OUT_OF_MEMORY;
      scoped_alternate_keychain_search_list.reset(mutable_keychain_search_list);

      SecKeychainRef keychain;
      // Get a reference to the System Roots keychain. The System Roots
      // keychain is not normally present in the keychain search list, but is
      // implicitly checked after the keychains in the search list. By
      // including it directly, force it to be checked first.  This is a gross
      // hack, but the path is known to be valid on OS X 10.9-10.11.
      status = SecKeychainOpen(
          "/System/Library/Keychains/SystemRootCertificates.keychain",
          &keychain);
      if (status)
        return NetErrorFromOSStatus(status);
      ScopedCFTypeRef<SecKeychainRef> scoped_keychain(keychain);

      CFArrayInsertValueAtIndex(mutable_keychain_search_list, 0, keychain);
    }

    ScopedCFTypeRef<CFMutableArrayRef> cert_array(
        x509_util::CreateSecCertificateArrayForX509Certificate(
            cert, x509_util::InvalidIntermediateBehavior::kIgnore));
    if (!cert_array) {
      verify_result->cert_status |= CERT_STATUS_INVALID;
      return ERR_CERT_INVALID;
    }

    // Beginning with the certificate chain as supplied by the server, attempt
    // to verify the chain. If a failure is encountered, trim a certificate
    // from the end (so long as one remains) and retry, in the hope of forcing
    // OS X to find a better path.
    while (CFArrayGetCount(cert_array) > 0) {
      ScopedCFTypeRef<SecTrustRef> temp_ref;
      SecTrustResultType temp_trust_result = kSecTrustResultDeny;
      ScopedCFTypeRef<CFArrayRef> temp_chain;
      CSSM_TP_APPLE_EVIDENCE_INFO* temp_chain_info = NULL;

      int rv = BuildAndEvaluateSecTrustRef(
          cert_array, trust_policies, flags,
          scoped_alternate_keychain_search_list.get(), &temp_ref,
          &temp_trust_result, &temp_chain, &temp_chain_info);
      if (rv != OK)
        return rv;

      // Check to see if the path |temp_chain| has been revoked. This is less
      // than ideal to perform after path building, rather than during, because
      // there may be multiple paths to trust anchors, and only some of them
      // are revoked. Ideally, CRLSets would be part of path building, which
      // they are when using NSS (Linux) or CryptoAPI (Windows).
      //
      // The CRLSet checking is performed inside the loop in the hope that if a
      // path is revoked, it's an older path, and the only reason it was built
      // is because the server forced it (by supplying an older or less
      // desirable intermediate) or because the user had installed a
      // certificate in their Keychain forcing this path. However, this means
      // its still possible for a CRLSet block of an intermediate to prevent
      // access, even when there is a 'good' chain. To fully remedy this, a
      // solution might be to have CRLSets contain enough knowledge about what
      // the 'desired' path might be, but for the time being, the
      // implementation is kept as 'simple' as it can be.
      CRLSetResult crl_result = CheckRevocationWithCRLSet(temp_chain, crl_set);
      bool untrusted = (temp_trust_result != kSecTrustResultUnspecified &&
                        temp_trust_result != kSecTrustResultProceed) ||
                       crl_result == kCRLSetRevoked;
      bool weak_chain = false;
      if (CFArrayGetCount(temp_chain) == 0) {
        // If the chain is empty, it cannot be trusted or have recoverable
        // errors.
        DCHECK(untrusted);
        DCHECK_NE(kSecTrustResultRecoverableTrustFailure, temp_trust_result);
      } else {
        weak_chain =
            IsWeakChainBasedOnHashingAlgorithms(temp_chain, temp_chain_info);
      }
      // Set the result to the current chain if:
      // - This is the first verification attempt. This ensures that if
      //   everything is awful (e.g. it may just be an untrusted cert), that
      //   what is reported is exactly what was sent by the server
      // - If the current chain is trusted, and the old chain was not trusted,
      //   then prefer this chain. This ensures that if there is at least a
      //   valid path to a trust anchor, it's preferred over reporting an error.
      // - If the current chain is trusted, and the old chain is trusted, but
      //   the old chain contained weak algorithms while the current chain only
      //   contains strong algorithms, then prefer the current chain over the
      //   old chain.
      //
      // Note: If the leaf certificate itself is weak, then the only
      // consideration is whether or not there is a trusted chain. That's
      // because no amount of path discovery will fix a weak leaf.
      if (!trust_ref || (!untrusted && (candidate_untrusted ||
                                        (candidate_weak && !weak_chain)))) {
        trust_ref = temp_ref;
        trust_result = temp_trust_result;
        completed_chain = temp_chain;
        *completed_chain_crl_result = crl_result;
        chain_info = temp_chain_info;

        candidate_untrusted = untrusted;
        candidate_weak = weak_chain;
      }
      // Short-circuit when a current, trusted chain is found.
      if (!untrusted && !weak_chain)
        break;
      CFArrayRemoveValueAtIndex(cert_array, CFArrayGetCount(cert_array) - 1);
    }
    // Short-circuit when a current, trusted chain is found.
    if (!candidate_untrusted && !candidate_weak)
      break;
  }

  if (flags & CertVerifyProc::VERIFY_REV_CHECKING_ENABLED)
    verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;

  if (*completed_chain_crl_result == kCRLSetRevoked)
    verify_result->cert_status |= CERT_STATUS_REVOKED;

  if (CFArrayGetCount(completed_chain) > 0) {
    CopyCertChainToVerifyResult(completed_chain, verify_result);
  }

  // As of Security Update 2012-002/OS X 10.7.4, when an RSA key < 1024 bits
  // is encountered, CSSM returns CSSMERR_TP_VERIFY_ACTION_FAILED and adds
  // CSSMERR_CSP_UNSUPPORTED_KEY_SIZE as a certificate status. Avoid mapping
  // the CSSMERR_TP_VERIFY_ACTION_FAILED to CERT_STATUS_INVALID if the only
  // error was due to an unsupported key size.
  bool policy_failed = false;
  bool policy_fail_already_mapped = false;
  bool weak_key_or_signature_algorithm = false;

  // Evaluate the results
  OSStatus cssm_result;
  switch (trust_result) {
    case kSecTrustResultUnspecified:
    case kSecTrustResultProceed:
      // Certificate chain is valid and trusted ("unspecified" indicates that
      // the user has not explicitly set a trust setting)
      break;

    // According to SecTrust.h, kSecTrustResultConfirm isn't returned on 10.5+,
    // and it is marked deprecated in the 10.9 SDK.
    case kSecTrustResultDeny:
      // Certificate chain is explicitly untrusted.
      verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
      break;

    case kSecTrustResultRecoverableTrustFailure:
      // Certificate chain has a failure that can be overridden by the user.
      status = SecTrustGetCssmResultCode(trust_ref, &cssm_result);
      if (status)
        return NetErrorFromOSStatus(status);
      if (cssm_result == CSSMERR_TP_VERIFY_ACTION_FAILED) {
        policy_failed = true;
      } else {
        verify_result->cert_status |= CertStatusFromOSStatus(cssm_result);
      }
      // Walk the chain of error codes in the CSSM_TP_APPLE_EVIDENCE_INFO
      // structure which can catch multiple errors from each certificate.
      for (CFIndex index = 0, chain_count = CFArrayGetCount(completed_chain);
           index < chain_count; ++index) {
        if (chain_info[index].StatusBits & CSSM_CERT_STATUS_EXPIRED ||
            chain_info[index].StatusBits & CSSM_CERT_STATUS_NOT_VALID_YET)
          verify_result->cert_status |= CERT_STATUS_DATE_INVALID;
        if (!IsCertStatusError(verify_result->cert_status) &&
            chain_info[index].NumStatusCodes == 0) {
          LOG(WARNING) << "chain_info[" << index << "].NumStatusCodes is 0"
                          ", chain_info[" << index << "].StatusBits is "
                       << chain_info[index].StatusBits;
        }
        for (uint32_t status_code_index = 0;
             status_code_index < chain_info[index].NumStatusCodes;
             ++status_code_index) {
          // As of OS X 10.9, attempting to verify a certificate chain that
          // contains a weak signature algorithm (MD2, MD5) in an intermediate
          // or leaf cert will be treated as a (recoverable) policy validation
          // failure, with the status code CSSMERR_TP_INVALID_CERTIFICATE
          // added to the Status Codes. Don't treat this code as an invalid
          // certificate; instead, map it to a weak key. Any truly invalid
          // certificates will have the major error (cssm_result) set to
          // CSSMERR_TP_INVALID_CERTIFICATE, rather than
          // CSSMERR_TP_VERIFY_ACTION_FAILED.
          CertStatus mapped_status = 0;
          if (policy_failed &&
              chain_info[index].StatusCodes[status_code_index] ==
                  CSSMERR_TP_INVALID_CERTIFICATE) {
            mapped_status = CERT_STATUS_WEAK_SIGNATURE_ALGORITHM;
            weak_key_or_signature_algorithm = true;
            policy_fail_already_mapped = true;
          } else if (policy_failed &&
                     (flags & CertVerifyProc::VERIFY_REV_CHECKING_ENABLED) &&
                     chain_info[index].StatusCodes[status_code_index] ==
                         CSSMERR_TP_VERIFY_ACTION_FAILED &&
                     base::mac::IsOS10_12()) {
            // On early versions of 10.12, using
            // kSecRevocationRequirePositiveResponse flag causes a
            // CSSMERR_TP_VERIFY_ACTION_FAILED status if revocation couldn't be
            // checked. (Note: even if the cert had no crlDistributionPoints or
            // OCSP AIA.) This isn't needed on later 10.12 versions, but it
            // should be mostly harmless.
            mapped_status = CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
            policy_fail_already_mapped = true;
          } else {
            mapped_status = CertStatusFromOSStatus(
                chain_info[index].StatusCodes[status_code_index]);
            if (mapped_status == CERT_STATUS_WEAK_KEY) {
              weak_key_or_signature_algorithm = true;
              policy_fail_already_mapped = true;
            }
          }
          verify_result->cert_status |= mapped_status;
        }
      }
      if (policy_failed && !policy_fail_already_mapped) {
        // If CSSMERR_TP_VERIFY_ACTION_FAILED wasn't returned due to a weak
        // key or problem checking revocation, map it back to an appropriate
        // error code.
        verify_result->cert_status |= CertStatusFromOSStatus(cssm_result);
      }
      if (!IsCertStatusError(verify_result->cert_status)) {
        LOG(ERROR) << "cssm_result=" << cssm_result;
        verify_result->cert_status |= CERT_STATUS_INVALID;
        NOTREACHED();
      }
      break;

    default:
      status = SecTrustGetCssmResultCode(trust_ref, &cssm_result);
      if (status)
        return NetErrorFromOSStatus(status);
      verify_result->cert_status |= CertStatusFromOSStatus(cssm_result);
      if (!IsCertStatusError(verify_result->cert_status)) {
        LOG(WARNING) << "trust_result=" << trust_result;
        verify_result->cert_status |= CERT_STATUS_INVALID;
      }
      break;
  }

  // Hostname validation is handled by CertVerifyProc, so mask off any errors
  // that SecTrustEvaluate may have set, as its results are not used.
  verify_result->cert_status &= ~CERT_STATUS_COMMON_NAME_INVALID;

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

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

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

  return OK;
}

}  // namespace

CertVerifyProcMac::CertVerifyProcMac() {}

CertVerifyProcMac::~CertVerifyProcMac() {}

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

int CertVerifyProcMac::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) {
  // Save the input state of |*verify_result|, which may be needed to re-do
  // verification with different flags.
  const CertVerifyResult input_verify_result(*verify_result);

  // Check for EV policy in leaf cert.
  std::string candidate_ev_policy_oid;
  GetCandidateEVPolicy(cert, &candidate_ev_policy_oid);

  CRLSetResult completed_chain_crl_result;
  int rv = VerifyWithGivenFlags(cert, hostname, flags, crl_set, verify_result,
                                &completed_chain_crl_result);
  if (rv != OK)
    return rv;

  if (!candidate_ev_policy_oid.empty() &&
      CheckCertChainEV(verify_result->verified_cert.get(),
                       candidate_ev_policy_oid)) {
    // EV policies check out and the verification succeeded. See if revocation
    // checking still needs to be done before it can be marked as EV.
    if (completed_chain_crl_result == kCRLSetUnknown &&
        !(flags & VERIFY_REV_CHECKING_ENABLED)) {
      // If this is an EV cert and it wasn't covered by CRLSets and revocation
      // checking wasn't already on, try again with revocation forced on.
      //
      // Restore the input state of |*verify_result|, so that the
      // re-verification starts with a clean slate.
      *verify_result = input_verify_result;
      int tmp_rv =
          VerifyWithGivenFlags(verify_result->verified_cert.get(), hostname,
                               flags | VERIFY_REV_CHECKING_ENABLED, crl_set,
                               verify_result, &completed_chain_crl_result);
      // If re-verification failed, return those results without setting EV
      // status.
      if (tmp_rv != OK)
        return tmp_rv;
      // Otherwise, fall through and add the EV status flag.
    }
    // EV cert and it was covered by CRLSets or revocation checking passed.
    verify_result->cert_status |= CERT_STATUS_IS_EV;
  }

  return OK;
}

}  // namespace net

#pragma clang diagnostic pop  // "-Wdeprecated-declarations"
