// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "verify_certificate_chain.h"

#include <algorithm>
#include <cassert>

#include <openssl/base.h>
#include "cert_error_params.h"
#include "cert_errors.h"
#include "common_cert_errors.h"
#include "extended_key_usage.h"
#include "input.h"
#include "name_constraints.h"
#include "parse_certificate.h"
#include "signature_algorithm.h"
#include "trust_store.h"
#include "verify_signed_data.h"

namespace bssl {

namespace {

bool IsHandledCriticalExtension(const ParsedExtension &extension,
                                const ParsedCertificate &cert) {
  if (extension.oid == der::Input(kBasicConstraintsOid)) {
    return true;
  }
  // Key Usage is NOT processed for end-entity certificates (this is the
  // responsibility of callers), however it is considered "handled" here in
  // order to allow being marked as critical.
  if (extension.oid == der::Input(kKeyUsageOid)) {
    return true;
  }
  if (extension.oid == der::Input(kExtKeyUsageOid)) {
    return true;
  }
  if (extension.oid == der::Input(kNameConstraintsOid)) {
    return true;
  }
  if (extension.oid == der::Input(kSubjectAltNameOid)) {
    return true;
  }
  if (extension.oid == der::Input(kCertificatePoliciesOid)) {
    // Policy qualifiers are skipped during processing, so if the
    // extension is marked critical need to ensure there weren't any
    // qualifiers other than User Notice / CPS.
    //
    // This follows from RFC 5280 section 4.2.1.4:
    //
    //   If this extension is critical, the path validation software MUST
    //   be able to interpret this extension (including the optional
    //   qualifier), or MUST reject the certificate.
    std::vector<der::Input> unused_policies;
    CertErrors unused_errors;
    return ParseCertificatePoliciesExtensionOids(
        extension.value, true /*fail_parsing_unknown_qualifier_oids*/,
        &unused_policies, &unused_errors);

    // TODO(eroman): Give a better error message.
  }
  if (extension.oid == der::Input(kPolicyMappingsOid)) {
    return true;
  }
  if (extension.oid == der::Input(kPolicyConstraintsOid)) {
    return true;
  }
  if (extension.oid == der::Input(kInhibitAnyPolicyOid)) {
    return true;
  }
  if (extension.oid == der::Input(kMSApplicationPoliciesOid)) {
    // Per https://crbug.com/1439638 and
    // https://learn.microsoft.com/en-us/windows/win32/seccertenroll/supported-extensions#msapplicationpolicies
    // The MSApplicationPolicies extension may be ignored if the
    // extendedKeyUsage extension is also present.
    return cert.has_extended_key_usage();
  }

  return false;
}

// Adds errors to |errors| if the certificate contains unconsumed _critical_
// extensions.
void VerifyNoUnconsumedCriticalExtensions(const ParsedCertificate &cert,
                                          CertErrors *errors,
                                          bool allow_precertificate) {
  for (const auto &it : cert.extensions()) {
    const ParsedExtension &extension = it.second;
    if (allow_precertificate && extension.oid == der::Input(kCtPoisonOid)) {
      continue;
    }
    if (extension.critical && !IsHandledCriticalExtension(extension, cert)) {
      errors->AddError(cert_errors::kUnconsumedCriticalExtension,
                       CreateCertErrorParams2Der("oid", extension.oid, "value",
                                                 extension.value));
    }
  }
}

// Returns true if |cert| was self-issued. The definition of self-issuance
// comes from RFC 5280 section 6.1:
//
//    A certificate is self-issued if the same DN appears in the subject
//    and issuer fields (the two DNs are the same if they match according
//    to the rules specified in Section 7.1).  In general, the issuer and
//    subject of the certificates that make up a path are different for
//    each certificate.  However, a CA may issue a certificate to itself to
//    support key rollover or changes in certificate policies.  These
//    self-issued certificates are not counted when evaluating path length
//    or name constraints.
[[nodiscard]] bool IsSelfIssued(const ParsedCertificate &cert) {
  return cert.normalized_subject() == cert.normalized_issuer();
}

// Adds errors to |errors| if |cert| is not valid at time |time|.
//
// The certificate's validity requirements are described by RFC 5280 section
// 4.1.2.5:
//
//    The validity period for a certificate is the period of time from
//    notBefore through notAfter, inclusive.
void VerifyTimeValidity(const ParsedCertificate &cert,
                        const der::GeneralizedTime &time, CertErrors *errors) {
  if (time < cert.tbs().validity_not_before) {
    errors->AddError(cert_errors::kValidityFailedNotBefore);
  }

  if (cert.tbs().validity_not_after < time) {
    errors->AddError(cert_errors::kValidityFailedNotAfter);
  }
}

// Adds errors to |errors| if |cert| has internally inconsistent signature
// algorithms.
//
// X.509 certificates contain two different signature algorithms:
//  (1) The signatureAlgorithm field of Certificate
//  (2) The signature field of TBSCertificate
//
// According to RFC 5280 section 4.1.1.2 and 4.1.2.3 these two fields must be
// equal:
//
//     This field MUST contain the same algorithm identifier as the
//     signature field in the sequence tbsCertificate (Section 4.1.2.3).
//
// The spec is not explicit about what "the same algorithm identifier" means.
// Our interpretation is that the two DER-encoded fields must be byte-for-byte
// identical.
//
// In practice however there are certificates which use different encodings for
// specifying RSA with SHA1 (different OIDs). This is special-cased for
// compatibility sake.
bool VerifySignatureAlgorithmsMatch(const ParsedCertificate &cert,
                                    CertErrors *errors) {
  der::Input alg1_tlv = cert.signature_algorithm_tlv();
  der::Input alg2_tlv = cert.tbs().signature_algorithm_tlv;

  // Ensure that the two DER-encoded signature algorithms are byte-for-byte
  // equal.
  if (alg1_tlv == alg2_tlv) {
    return true;
  }

  // But make a compatibility concession if alternate encodings are used
  // TODO(eroman): Turn this warning into an error.
  // TODO(eroman): Add a unit-test that exercises this case.
  std::optional<SignatureAlgorithm> alg1 = ParseSignatureAlgorithm(alg1_tlv);
  if (!alg1) {
    errors->AddError(cert_errors::kUnacceptableSignatureAlgorithm);
    return false;
  }
  std::optional<SignatureAlgorithm> alg2 = ParseSignatureAlgorithm(alg2_tlv);
  if (!alg2) {
    errors->AddError(cert_errors::kUnacceptableSignatureAlgorithm);
    return false;
  }

  if (*alg1 == *alg2) {
    errors->AddWarning(
        cert_errors::kSignatureAlgorithmsDifferentEncoding,
        CreateCertErrorParams2Der("Certificate.algorithm", alg1_tlv,
                                  "TBSCertificate.signature", alg2_tlv));
    return true;
  }

  errors->AddError(
      cert_errors::kSignatureAlgorithmMismatch,
      CreateCertErrorParams2Der("Certificate.algorithm", alg1_tlv,
                                "TBSCertificate.signature", alg2_tlv));
  return false;
}

// Verify that |cert| can be used for |required_key_purpose|.
void VerifyExtendedKeyUsage(const ParsedCertificate &cert,
                            KeyPurpose required_key_purpose, CertErrors *errors,
                            bool is_target_cert, bool is_target_cert_issuer) {
  // We treat a required KeyPurpose of ANY_EKU to mean "Do not check EKU"
  if (required_key_purpose == KeyPurpose::ANY_EKU) {
    return;
  }
  bool has_any_eku = false;
  bool has_server_auth_eku = false;
  bool has_client_auth_eku = false;
  bool has_code_signing_eku = false;
  bool has_time_stamping_eku = false;
  bool has_ocsp_signing_eku = false;
  if (cert.has_extended_key_usage()) {
    for (const auto &key_purpose_oid : cert.extended_key_usage()) {
      if (key_purpose_oid == der::Input(kAnyEKU)) {
        has_any_eku = true;
      }
      if (key_purpose_oid == der::Input(kServerAuth)) {
        has_server_auth_eku = true;
      }
      if (key_purpose_oid == der::Input(kClientAuth)) {
        has_client_auth_eku = true;
      }
      if (key_purpose_oid == der::Input(kCodeSigning)) {
        has_code_signing_eku = true;
      }
      if (key_purpose_oid == der::Input(kTimeStamping)) {
        has_time_stamping_eku = true;
      }
      if (key_purpose_oid == der::Input(kOCSPSigning)) {
        has_ocsp_signing_eku = true;
      }
    }
  }

  auto add_error_if_strict = [&](CertErrorId id) {
    if (required_key_purpose == KeyPurpose::SERVER_AUTH_STRICT ||
        required_key_purpose == KeyPurpose::CLIENT_AUTH_STRICT) {
      errors->AddError(id);
    } else {
      errors->AddWarning(id);
    }
  };
  if (is_target_cert) {
    // Loosely based upon CABF BR version 1.8.4, 7.1.2.3(f).  We are more
    // permissive in that we still allow EKU any to be present in a leaf
    // certificate, but we ignore it for purposes of server or client auth.  We
    // are less permissive in that we prohibit Code Signing, OCSP Signing, and
    // Time Stamping which are currently only a SHOULD NOT. The BR does
    // explicitly allow Email authentication to be present, as this still exists
    // in the wild (2022), so we do not prohibit Email authentication here (and
    // by extension must allow it to be present in the signer, below).
    if (!cert.has_extended_key_usage()) {
      // This is added as a warning, an error will be added in STRICT modes
      // if we then lack client or server auth due to this not being present.
      errors->AddWarning(cert_errors::kEkuNotPresent);
    } else {
      if (has_code_signing_eku) {
        add_error_if_strict(cert_errors::kEkuHasProhibitedCodeSigning);
      }
      if (has_ocsp_signing_eku) {
        add_error_if_strict(cert_errors::kEkuHasProhibitedOCSPSigning);
      }
      if (has_time_stamping_eku) {
        add_error_if_strict(cert_errors::kEkuHasProhibitedTimeStamping);
      }
    }
  } else if (is_target_cert_issuer) {
    // Handle the decision to overload EKU as a constraint on issuers.
    //
    // CABF BR version 1.8.4, 7.1.2.2(g) pertains to the case of "Certs used to
    // issue TLS certificates", While the BR refers to the entire chain of
    // intermediates, there are a number of exceptions regarding CA ownership
    // and cross signing which are impossible for us to know or enforce here.
    // Therefore, we can only enforce at the level of the intermediate that
    // issued our target certificate. This means we we differ in the following
    // ways:
    // - We only enforce at the issuer of the TLS certificate.
    // - We allow email protection to exist in the issuer, since without
    //   this it can not be allowed in the client (other than via EKU any))
    // - As in the leaf certificate case, we allow EKU any to be present, but
    //   we ignore it for the purposes of server or client auth.
    //
    // At this time (until at least 2023) some intermediates are lacking EKU in
    // the world at large from common CA's, so we allow the noEKU case to permit
    // everything.
    // TODO(bbe): enforce requiring EKU in the issuer when we can manage it.
    if (cert.has_extended_key_usage()) {
      if (has_code_signing_eku) {
        add_error_if_strict(cert_errors::kEkuHasProhibitedCodeSigning);
      }
      if (has_time_stamping_eku) {
        add_error_if_strict(cert_errors::kEkuHasProhibitedTimeStamping);
      }
    }
  }
  // Otherwise, we are a parent of an issuer of a TLS certificate.  The CABF
  // BR version 1.8.4, 7.1.2.2(g) goes as far as permitting EKU any in certain
  // cases of Cross Signing and CA Ownership, having permitted cases where EKU
  // is permitted to not be present at all. These cases are not practical to
  // differentiate here and therefore we don't attempt to enforce any further
  // EKU "constraints" on such certificates. Unlike the above cases we also
  // allow the use of EKU any for client or server auth constraint purposes.

  switch (required_key_purpose) {
    case KeyPurpose::ANY_EKU:
      assert(0);  // NOTREACHED
      return;
    case KeyPurpose::SERVER_AUTH:
    case KeyPurpose::SERVER_AUTH_STRICT: {
      if (has_any_eku && !has_server_auth_eku) {
        if (is_target_cert || is_target_cert_issuer) {
          errors->AddWarning(cert_errors::kEkuLacksServerAuthButHasAnyEKU);
        } else {
          // Accept anyEKU for server auth below target issuer.
          has_server_auth_eku = true;
        }
      }
      if (is_target_cert_issuer && !cert.has_extended_key_usage()) {
        // Accept noEKU for server auth in target issuer.
        // TODO(bbe): remove this once BR requirements catch up with CA's.
        has_server_auth_eku = true;
      }
      if (required_key_purpose == KeyPurpose::SERVER_AUTH) {
        // Legacy compatible.
        if (cert.has_extended_key_usage() && !has_server_auth_eku &&
            !has_any_eku) {
          errors->AddError(cert_errors::kEkuLacksServerAuth);
        }
      } else {
        if (!has_server_auth_eku) {
          errors->AddError(cert_errors::kEkuLacksServerAuth);
        }
      }
      break;
    }
    case KeyPurpose::CLIENT_AUTH:
    case KeyPurpose::CLIENT_AUTH_STRICT: {
      if (has_any_eku && !has_client_auth_eku) {
        if (is_target_cert || is_target_cert_issuer) {
          errors->AddWarning(cert_errors::kEkuLacksClientAuthButHasAnyEKU);
        } else {
          // accept anyEKU for client auth.
          has_client_auth_eku = true;
        }
      }
      if (required_key_purpose == KeyPurpose::CLIENT_AUTH) {
        // Legacy-compatible.
        if (cert.has_extended_key_usage() && !has_client_auth_eku &&
            !has_any_eku) {
          errors->AddError(cert_errors::kEkuLacksClientAuth);
        }
      } else {
        if (!has_client_auth_eku) {
          errors->AddError(cert_errors::kEkuLacksClientAuth);
        }
      }
      break;
    }
  }
}

// Representation of RFC 5280's "valid_policy_tree", used to keep track of the
// valid policies and policy re-mappings. This structure is defined in
// section 6.1.2.
//
// ValidPolicyGraph differs from RFC 5280's description in that:
//
//  (1) It does not track "qualifier_set". This is not needed as it is not
//      output by this implementation.
//
//  (2) It builds a directed acyclic graph, rather than a tree. When a given
//      policy matches multiple parents, RFC 5280 makes a separate node for
//      each parent. This representation condenses them into one node with
//      multiple parents.
//
//  (3) It does not track "expected_policy_set" or anyPolicy nodes directly.
//      Rather it maintains, only for the most recent level, whether there is an
//      anyPolicy node and an inverted map of all "expected_policy_set" values.
//
//  (4) Some pruning steps are deferred to when policies are evaluated, as a
//      reachability pass.
class ValidPolicyGraph {
 public:
  ValidPolicyGraph() = default;

  ValidPolicyGraph(const ValidPolicyGraph &) = delete;
  ValidPolicyGraph &operator=(const ValidPolicyGraph &) = delete;

  // A Node is an entry in the policy graph. It contains information about some
  // policy asserted by a certificate in the chain. The policy OID itself is
  // omitted because it is the key in the Level map.
  struct Node {
    // The list of "valid_policy" values for all nodes which are a parent of
    // this node, other than anyPolicy. If empty, this node has a single parent,
    // anyPolicy.
    //
    // Nodes whose parent is anyPolicy are root policies, and may be returned
    // in the authorities-constrained-policy-set. Nodes with a concrete policy
    // as a parent are derived from that policy in the issuer certificate,
    // possibly with a policy mapping applied.
    //
    // Note it is not possible for a policy to have both anyPolicy and a
    // concrete policy as a parent. Section 6.1.3, step d.1.ii only runs if
    // there was no match in step d.1.i.
    std::vector<der::Input> parent_policies;

    // Whether this node matches a policy mapping in the certificate. If true,
    // its "expected_policy_set" comes from the policy mappings extension. If
    // false, its "expected_policy_set" is itself.
    bool mapped = false;

    // Whether this node is reachable from some valid policy in the end-entity
    // certificate. Computed during GetValidRootPolicySet().
    bool reachable = false;
  };

  // The policy graph is organized into "levels", each corresponding to a
  // certificate in the chain. We maintain a map from "valid_policy" to the
  // corresponding Node. This is the set of policies asserted by this
  // certificate. The special anyPolicy OID is handled separately below.
  using Level = std::map<der::Input, Node>;

  // Additional per-level information that only needs to be maintained for the
  // bottom-most level.
  struct LevelDetails {
    // Maintains the "expected_policy_set" values for nodes in a level of the
    // graph, but the map is inverted from RFC 5280's formulation. For a given
    // policy OID P, other than anyPolicy, this map gives the set of nodes where
    // P appears in the node's "expected_policy_set". anyPolicy is handled
    // separately below.
    std::map<der::Input, std::vector<der::Input>> expected_policy_map;

    // Whether there is a node at this level whose "valid_policy" is anyPolicy.
    //
    // Note anyPolicy's "expected_policy_set" always {anyPolicy}, and anyPolicy
    // will never appear in the "expected_policy_set" of any other policy. That
    // means this field also captures how anyPolicy appears in
    // "expected_policy_set".
    bool has_any_policy = false;
  };

  // Initializes the ValidPolicyGraph.
  void Init() {
    SetNull();
    StartLevel();
    AddAnyPolicyNode();
  }

  // In RFC 5280 valid_policy_tree may be set to null. That is represented here
  // by emptiness.
  bool IsNull() const {
    return !current_level_.has_any_policy &&
           (levels_.empty() || levels_.back().empty());
  }
  void SetNull() {
    levels_.clear();
    current_level_ = LevelDetails{};
  }

  // Completes the previous level, returning a corresponding LevelDetails
  // structure, and starts a new level.
  LevelDetails StartLevel() {
    // Finish building expected_policy_map for the previous level.
    if (!levels_.empty()) {
      for (const auto &[policy, node] : levels_.back()) {
        if (!node.mapped) {
          current_level_.expected_policy_map[policy].push_back(policy);
        }
      }
    }

    LevelDetails prev_level = std::move(current_level_);
    levels_.emplace_back();
    current_level_ = LevelDetails{};
    return prev_level;
  }

  // Gets the set of policies (in terms of root authority's policy domain) that
  // are valid at the bottom level of the policy graph, intersected with
  // |user_initial_policy_set|. This is what X.509 calls
  // "user-constrained-policy-set".
  //
  // This method may only be called once, after the policy graph is constructed.
  std::set<der::Input> GetUserConstrainedPolicySet(
      const std::set<der::Input> &user_initial_policy_set) {
    if (levels_.empty()) {
      return {};
    }

    bool user_has_any_policy =
        user_initial_policy_set.count(der::Input(kAnyPolicyOid)) != 0;
    if (current_level_.has_any_policy) {
      if (user_has_any_policy) {
        return {der::Input(kAnyPolicyOid)};
      }
      return user_initial_policy_set;
    }

    // The root's policy domain is determined by nodes with anyPolicy as a
    // parent. However, we must limit to those which are reachable from the
    // end-entity certificate because we defer some pruning steps.
    for (auto &[policy, node] : levels_.back()) {
      // GCC before 8.1 tracks individual unused bindings and does not support
      // marking them [[maybe_unused]].
      (void)policy;
      node.reachable = true;
    }
    std::set<der::Input> policy_set;
    for (size_t i = levels_.size() - 1; i < levels_.size(); i--) {
      for (auto &[policy, node] : levels_[i]) {
        if (!node.reachable) {
          continue;
        }
        if (node.parent_policies.empty()) {
          // |node|'s parent is anyPolicy, so this is in the root policy domain.
          // Add it to the set if it is also in user's list.
          if (user_has_any_policy ||
              user_initial_policy_set.count(policy) > 0) {
            policy_set.insert(policy);
          }
        } else if (i > 0) {
          // Otherwise, continue searching the previous level.
          for (der::Input parent : node.parent_policies) {
            auto iter = levels_[i - 1].find(parent);
            if (iter != levels_[i - 1].end()) {
              iter->second.reachable = true;
            }
          }
        }
      }
    }
    return policy_set;
  }

  // Adds a node with policy anyPolicy to the current level.
  void AddAnyPolicyNode() {
    assert(!levels_.empty());
    current_level_.has_any_policy = true;
  }

  // Adds a node to the current level which is a child of |parent_policies| with
  // the specified policy.
  void AddNode(der::Input policy, std::vector<der::Input> parent_policies) {
    assert(policy != der::Input(kAnyPolicyOid));
    AddNodeReturningIterator(policy, std::move(parent_policies));
  }

  // Adds a node to the current level which is a child of anyPolicy with the
  // specified policy.
  void AddNodeWithParentAnyPolicy(der::Input policy) {
    // An empty parent set represents a node parented by anyPolicy.
    AddNode(policy, {});
  }

  // Maps |issuer_policy| to |subject_policy|, as in RFC 5280, section 6.1.4,
  // step b.1.
  void AddPolicyMapping(der::Input issuer_policy, der::Input subject_policy) {
    assert(issuer_policy != der::Input(kAnyPolicyOid));
    assert(subject_policy != der::Input(kAnyPolicyOid));
    if (levels_.empty()) {
      return;
    }

    // The mapping only applies if |issuer_policy| exists in the current level.
    auto issuer_policy_iter = levels_.back().find(issuer_policy);
    if (issuer_policy_iter == levels_.back().end()) {
      // If there is no match, it can instead match anyPolicy.
      if (!current_level_.has_any_policy) {
        return;
      }

      // From RFC 5280, section 6.1.4, step b.1:
      //
      //    If no node of depth i in the valid_policy_tree has a
      //    valid_policy of ID-P but there is a node of depth i with a
      //    valid_policy of anyPolicy, then generate a child node of
      //    the node of depth i-1 that has a valid_policy of anyPolicy
      //    as follows: [...]
      //
      // The anyPolicy node of depth i-1 is referring to the parent of the
      // anyPolicy node of depth i. The parent of anyPolicy is always anyPolicy.
      issuer_policy_iter = AddNodeReturningIterator(issuer_policy, {});
    }

    // Unmapped nodes have a singleton "expected_policy_set" containing their
    // valid_policy. Track whether nodes have been mapped so this can be filled
    // in at StartLevel().
    issuer_policy_iter->second.mapped = true;

    // Add |subject_policy| to |issuer_policy|'s "expected_policy_set".
    current_level_.expected_policy_map[subject_policy].push_back(issuer_policy);
  }

  // Removes the node with the specified policy from the current level.
  void DeleteNode(der::Input policy) {
    if (!levels_.empty()) {
      levels_.back().erase(policy);
    }
  }

 private:
  Level::iterator AddNodeReturningIterator(
      der::Input policy, std::vector<der::Input> parent_policies) {
    assert(policy != der::Input(kAnyPolicyOid));
    auto [iter, inserted] = levels_.back().insert(
        std::pair{policy, Node{std::move(parent_policies)}});
    // GCC before 8.1 tracks individual unused bindings and does not support
    // marking them [[maybe_unused]].
    (void)inserted;
    assert(inserted);
    return iter;
  }

  // The list of levels, starting from the root.
  std::vector<Level> levels_;
  // Additional information about the current level.
  LevelDetails current_level_;
};

// Class that encapsulates the state variables used by certificate path
// validation.
class PathVerifier {
 public:
  // Same parameters and meaning as VerifyCertificateChain().
  void Run(const ParsedCertificateList &certs,
           const CertificateTrust &last_cert_trust,
           VerifyCertificateChainDelegate *delegate,
           const der::GeneralizedTime &time, KeyPurpose required_key_purpose,
           InitialExplicitPolicy initial_explicit_policy,
           const std::set<der::Input> &user_initial_policy_set,
           InitialPolicyMappingInhibit initial_policy_mapping_inhibit,
           InitialAnyPolicyInhibit initial_any_policy_inhibit,
           std::set<der::Input> *user_constrained_policy_set,
           CertPathErrors *errors);

 private:
  // Verifies and updates the valid policies. This corresponds with RFC 5280
  // section 6.1.3 steps d-f.
  void VerifyPolicies(const ParsedCertificate &cert, bool is_target_cert,
                      CertErrors *errors);

  // Applies the policy mappings. This corresponds with RFC 5280 section 6.1.4
  // steps a-b.
  void VerifyPolicyMappings(const ParsedCertificate &cert, CertErrors *errors);

  // Applies policyConstraints and inhibitAnyPolicy. This corresponds with RFC
  // 5280 section 6.1.4 steps i-j.
  void ApplyPolicyConstraints(const ParsedCertificate &cert);

  // This function corresponds to RFC 5280 section 6.1.3's "Basic Certificate
  // Processing" procedure.
  void BasicCertificateProcessing(const ParsedCertificate &cert,
                                  bool is_target_cert,
                                  bool is_target_cert_issuer,
                                  const der::GeneralizedTime &time,
                                  KeyPurpose required_key_purpose,
                                  CertErrors *errors,
                                  bool *shortcircuit_chain_validation);

  // This function corresponds to RFC 5280 section 6.1.4's "Preparation for
  // Certificate i+1" procedure. |cert| is expected to be an intermediate.
  void PrepareForNextCertificate(const ParsedCertificate &cert,
                                 CertErrors *errors);

  // This function corresponds with RFC 5280 section 6.1.5's "Wrap-Up
  // Procedure". It does processing for the final certificate (the target cert).
  void WrapUp(const ParsedCertificate &cert, KeyPurpose required_key_purpose,
              const std::set<der::Input> &user_initial_policy_set,
              bool allow_precertificate, CertErrors *errors);

  // Enforces trust anchor constraints compatibile with RFC 5937.
  //
  // Note that the anchor constraints are encoded via the attached certificate
  // itself.
  void ApplyTrustAnchorConstraints(const ParsedCertificate &cert,
                                   KeyPurpose required_key_purpose,
                                   CertErrors *errors);

  // Initializes the path validation algorithm given anchor constraints. This
  // follows the description in RFC 5937
  void ProcessRootCertificate(const ParsedCertificate &cert,
                              const CertificateTrust &trust,
                              const der::GeneralizedTime &time,
                              KeyPurpose required_key_purpose,
                              CertErrors *errors,
                              bool *shortcircuit_chain_validation);

  // Processes verification when the input is a single certificate. This is not
  // defined by any standard. We attempt to match the de-facto behaviour of
  // Operating System verifiers.
  void ProcessSingleCertChain(const ParsedCertificate &cert,
                              const CertificateTrust &trust,
                              const der::GeneralizedTime &time,
                              KeyPurpose required_key_purpose,
                              CertErrors *errors);

  // Parses |spki| to an EVP_PKEY and checks whether the public key is accepted
  // by |delegate_|. On failure parsing returns nullptr. If either parsing the
  // key or key policy failed, adds a high-severity error to |errors|.
  bssl::UniquePtr<EVP_PKEY> ParseAndCheckPublicKey(der::Input spki,
                                                   CertErrors *errors);

  ValidPolicyGraph valid_policy_graph_;

  std::set<der::Input> user_constrained_policy_set_;

  // Will contain a NameConstraints for each previous cert in the chain which
  // had nameConstraints. This corresponds to the permitted_subtrees and
  // excluded_subtrees state variables from RFC 5280.
  std::vector<const NameConstraints *> name_constraints_list_;

  // |explicit_policy_| corresponds with the same named variable from RFC 5280
  // section 6.1.2:
  //
  //   explicit_policy:  an integer that indicates if a non-NULL
  //   valid_policy_tree is required.  The integer indicates the
  //   number of non-self-issued certificates to be processed before
  //   this requirement is imposed.  Once set, this variable may be
  //   decreased, but may not be increased.  That is, if a certificate in the
  //   path requires a non-NULL valid_policy_tree, a later certificate cannot
  //   remove this requirement.  If initial-explicit-policy is set, then the
  //   initial value is 0, otherwise the initial value is n+1.
  size_t explicit_policy_;

  // |inhibit_any_policy_| corresponds with the same named variable from RFC
  // 5280 section 6.1.2:
  //
  //   inhibit_anyPolicy:  an integer that indicates whether the
  //   anyPolicy policy identifier is considered a match.  The
  //   integer indicates the number of non-self-issued certificates
  //   to be processed before the anyPolicy OID, if asserted in a
  //   certificate other than an intermediate self-issued
  //   certificate, is ignored.  Once set, this variable may be
  //   decreased, but may not be increased.  That is, if a
  //   certificate in the path inhibits processing of anyPolicy, a
  //   later certificate cannot permit it.  If initial-any-policy-
  //   inhibit is set, then the initial value is 0, otherwise the
  //   initial value is n+1.
  size_t inhibit_any_policy_;

  // |policy_mapping_| corresponds with the same named variable from RFC 5280
  // section 6.1.2:
  //
  //   policy_mapping:  an integer that indicates if policy mapping
  //   is permitted.  The integer indicates the number of non-self-
  //   issued certificates to be processed before policy mapping is
  //   inhibited.  Once set, this variable may be decreased, but may
  //   not be increased.  That is, if a certificate in the path
  //   specifies that policy mapping is not permitted, it cannot be
  //   overridden by a later certificate.  If initial-policy-
  //   mapping-inhibit is set, then the initial value is 0,
  //   otherwise the initial value is n+1.
  size_t policy_mapping_;

  // |working_public_key_| is an amalgamation of 3 separate variables from RFC
  // 5280:
  //    * working_public_key
  //    * working_public_key_algorithm
  //    * working_public_key_parameters
  //
  // They are combined for simplicity since the signature verification takes an
  // EVP_PKEY, and the parameter inheritence is not applicable for the supported
  // key types. |working_public_key_| may be null if parsing failed.
  //
  // An approximate explanation of |working_public_key_| is this description
  // from RFC 5280 section 6.1.2:
  //
  //    working_public_key:  the public key used to verify the
  //    signature of a certificate.
  bssl::UniquePtr<EVP_PKEY> working_public_key_;

  // |working_normalized_issuer_name_| is the normalized value of the
  // working_issuer_name variable in RFC 5280 section 6.1.2:
  //
  //    working_issuer_name:  the issuer distinguished name expected
  //    in the next certificate in the chain.
  der::Input working_normalized_issuer_name_;

  // |max_path_length_| corresponds with the same named variable in RFC 5280
  // section 6.1.2.
  //
  //    max_path_length:  this integer is initialized to n, is
  //    decremented for each non-self-issued certificate in the path,
  //    and may be reduced to the value in the path length constraint
  //    field within the basic constraints extension of a CA
  //    certificate.
  size_t max_path_length_;

  VerifyCertificateChainDelegate *delegate_;
};

void PathVerifier::VerifyPolicies(const ParsedCertificate &cert,
                                  bool is_target_cert, CertErrors *errors) {
  // From RFC 5280 section 6.1.3:
  //
  //  (d)  If the certificate policies extension is present in the
  //       certificate and the valid_policy_tree is not NULL, process
  //       the policy information by performing the following steps in
  //       order:
  if (cert.has_policy_oids() && !valid_policy_graph_.IsNull()) {
    ValidPolicyGraph::LevelDetails previous_level =
        valid_policy_graph_.StartLevel();

    //     (1)  For each policy P not equal to anyPolicy in the
    //          certificate policies extension, let P-OID denote the OID
    //          for policy P and P-Q denote the qualifier set for policy
    //          P.  Perform the following steps in order:
    bool cert_has_any_policy = false;
    for (der::Input p_oid : cert.policy_oids()) {
      if (p_oid == der::Input(kAnyPolicyOid)) {
        cert_has_any_policy = true;
        continue;
      }

      //        (i)   For each node of depth i-1 in the valid_policy_tree
      //              where P-OID is in the expected_policy_set, create a
      //              child node as follows: set the valid_policy to P-OID,
      //              set the qualifier_set to P-Q, and set the
      //              expected_policy_set to {P-OID}.
      auto iter = previous_level.expected_policy_map.find(p_oid);
      if (iter != previous_level.expected_policy_map.end()) {
        valid_policy_graph_.AddNode(
            p_oid, /*parent_policies=*/std::move(iter->second));
        previous_level.expected_policy_map.erase(iter);
      } else if (previous_level.has_any_policy) {
        //      (ii)  If there was no match in step (i) and the
        //            valid_policy_tree includes a node of depth i-1 with
        //            the valid_policy anyPolicy, generate a child node with
        //            the following values: set the valid_policy to P-OID,
        //            set the qualifier_set to P-Q, and set the
        //            expected_policy_set to  {P-OID}.
        valid_policy_graph_.AddNodeWithParentAnyPolicy(p_oid);
      }
    }

    //     (2)  If the certificate policies extension includes the policy
    //          anyPolicy with the qualifier set AP-Q and either (a)
    //          inhibit_anyPolicy is greater than 0 or (b) i<n and the
    //          certificate is self-issued, then:
    //
    //          For each node in the valid_policy_tree of depth i-1, for
    //          each value in the expected_policy_set (including
    //          anyPolicy) that does not appear in a child node, create a
    //          child node with the following values: set the valid_policy
    //          to the value from the expected_policy_set in the parent
    //          node, set the qualifier_set to AP-Q, and set the
    //          expected_policy_set to the value in the valid_policy from
    //          this node.
    if (cert_has_any_policy && ((inhibit_any_policy_ > 0) ||
                                (!is_target_cert && IsSelfIssued(cert)))) {
      for (auto &[p_oid, parent_policies] :
           previous_level.expected_policy_map) {
        valid_policy_graph_.AddNode(p_oid, std::move(parent_policies));
      }
      if (previous_level.has_any_policy) {
        valid_policy_graph_.AddAnyPolicyNode();
      }
    }

    //     (3)  If there is a node in the valid_policy_tree of depth i-1
    //          or less without any child nodes, delete that node.  Repeat
    //          this step until there are no nodes of depth i-1 or less
    //          without children.
    //
    // This implementation does this as part of GetUserConstrainedPolicySet().
    // Only the current level needs to be pruned to compute the policy graph.
  }

  //  (e)  If the certificate policies extension is not present, set the
  //       valid_policy_tree to NULL.
  if (!cert.has_policy_oids()) {
    valid_policy_graph_.SetNull();
  }

  //  (f)  Verify that either explicit_policy is greater than 0 or the
  //       valid_policy_tree is not equal to NULL;
  if (!((explicit_policy_ > 0) || !valid_policy_graph_.IsNull())) {
    errors->AddError(cert_errors::kNoValidPolicy);
  }
}

void PathVerifier::VerifyPolicyMappings(const ParsedCertificate &cert,
                                        CertErrors *errors) {
  if (!cert.has_policy_mappings()) {
    return;
  }

  // From RFC 5280 section 6.1.4:
  //
  //  (a)  If a policy mappings extension is present, verify that the
  //       special value anyPolicy does not appear as an
  //       issuerDomainPolicy or a subjectDomainPolicy.
  for (const ParsedPolicyMapping &mapping : cert.policy_mappings()) {
    if (mapping.issuer_domain_policy == der::Input(kAnyPolicyOid) ||
        mapping.subject_domain_policy == der::Input(kAnyPolicyOid)) {
      // Because this implementation continues processing certificates after
      // this error, clear the valid policy graph to ensure the
      // "user_constrained_policy_set" output upon failure is empty.
      valid_policy_graph_.SetNull();
      errors->AddError(cert_errors::kPolicyMappingAnyPolicy);
      return;
    }
  }

  //  (b)  If a policy mappings extension is present, then for each
  //       issuerDomainPolicy ID-P in the policy mappings extension:
  //
  //     (1)  If the policy_mapping variable is greater than 0, for each
  //          node in the valid_policy_tree of depth i where ID-P is the
  //          valid_policy, set expected_policy_set to the set of
  //          subjectDomainPolicy values that are specified as
  //          equivalent to ID-P by the policy mappings extension.
  //
  //          If no node of depth i in the valid_policy_tree has a
  //          valid_policy of ID-P but there is a node of depth i with a
  //          valid_policy of anyPolicy, then generate a child node of
  //          the node of depth i-1 that has a valid_policy of anyPolicy
  //          as follows:
  //
  //        (i)    set the valid_policy to ID-P;
  //
  //        (ii)   set the qualifier_set to the qualifier set of the
  //               policy anyPolicy in the certificate policies
  //               extension of certificate i; and
  //
  //        (iii)  set the expected_policy_set to the set of
  //               subjectDomainPolicy values that are specified as
  //               equivalent to ID-P by the policy mappings extension.
  //
  if (policy_mapping_ > 0) {
    for (const ParsedPolicyMapping &mapping : cert.policy_mappings()) {
      valid_policy_graph_.AddPolicyMapping(mapping.issuer_domain_policy,
                                           mapping.subject_domain_policy);
    }
  }

  //  (b)  If a policy mappings extension is present, then for each
  //       issuerDomainPolicy ID-P in the policy mappings extension:
  //
  //  ...
  //
  //     (2)  If the policy_mapping variable is equal to 0:
  //
  //        (i)    delete each node of depth i in the valid_policy_tree
  //               where ID-P is the valid_policy.
  //
  //        (ii)   If there is a node in the valid_policy_tree of depth
  //               i-1 or less without any child nodes, delete that
  //               node.  Repeat this step until there are no nodes of
  //               depth i-1 or less without children.
  //
  // Step (ii) is deferred to part of GetUserConstrainedPolicySet().
  if (policy_mapping_ == 0) {
    for (const ParsedPolicyMapping &mapping : cert.policy_mappings()) {
      valid_policy_graph_.DeleteNode(mapping.issuer_domain_policy);
    }
  }
}

void PathVerifier::ApplyPolicyConstraints(const ParsedCertificate &cert) {
  // RFC 5280 section 6.1.4 step i-j:
  //      (i)  If a policy constraints extension is included in the
  //           certificate, modify the explicit_policy and policy_mapping
  //           state variables as follows:
  if (cert.has_policy_constraints()) {
    //         (1)  If requireExplicitPolicy is present and is less than
    //              explicit_policy, set explicit_policy to the value of
    //              requireExplicitPolicy.
    if (cert.policy_constraints().require_explicit_policy &&
        cert.policy_constraints().require_explicit_policy.value() <
            explicit_policy_) {
      explicit_policy_ =
          cert.policy_constraints().require_explicit_policy.value();
    }

    //         (2)  If inhibitPolicyMapping is present and is less than
    //              policy_mapping, set policy_mapping to the value of
    //              inhibitPolicyMapping.
    if (cert.policy_constraints().inhibit_policy_mapping &&
        cert.policy_constraints().inhibit_policy_mapping.value() <
            policy_mapping_) {
      policy_mapping_ =
          cert.policy_constraints().inhibit_policy_mapping.value();
    }
  }

  //      (j)  If the inhibitAnyPolicy extension is included in the
  //           certificate and is less than inhibit_anyPolicy, set
  //           inhibit_anyPolicy to the value of inhibitAnyPolicy.
  if (cert.inhibit_any_policy() &&
      cert.inhibit_any_policy().value() < inhibit_any_policy_) {
    inhibit_any_policy_ = cert.inhibit_any_policy().value();
  }
}

void PathVerifier::BasicCertificateProcessing(
    const ParsedCertificate &cert, bool is_target_cert,
    bool is_target_cert_issuer, const der::GeneralizedTime &time,
    KeyPurpose required_key_purpose, CertErrors *errors,
    bool *shortcircuit_chain_validation) {
  *shortcircuit_chain_validation = false;
  // Check that the signature algorithms in Certificate vs TBSCertificate
  // match. This isn't part of RFC 5280 section 6.1.3, but is mandated by
  // sections 4.1.1.2 and 4.1.2.3.
  if (!VerifySignatureAlgorithmsMatch(cert, errors)) {
    BSSL_CHECK(errors->ContainsAnyErrorWithSeverity(CertError::SEVERITY_HIGH));
    *shortcircuit_chain_validation = true;
  }

  // Check whether this signature algorithm is allowed.
  if (!cert.signature_algorithm().has_value() ||
      !delegate_->IsSignatureAlgorithmAcceptable(*cert.signature_algorithm(),
                                                 errors)) {
    *shortcircuit_chain_validation = true;
    errors->AddError(cert_errors::kUnacceptableSignatureAlgorithm);
    return;
  }

  if (working_public_key_) {
    // Verify the digital signature using the previous certificate's key (RFC
    // 5280 section 6.1.3 step a.1).
    if (!VerifySignedData(*cert.signature_algorithm(),
                          cert.tbs_certificate_tlv(), cert.signature_value(),
                          working_public_key_.get(),
                          delegate_->GetVerifyCache())) {
      *shortcircuit_chain_validation = true;
      errors->AddError(cert_errors::kVerifySignedDataFailed);
    }
  }
  if (*shortcircuit_chain_validation) {
    return;
  }

  // Check the time range for the certificate's validity, ensuring it is valid
  // at |time|.
  // (RFC 5280 section 6.1.3 step a.2)
  VerifyTimeValidity(cert, time, errors);

  // RFC 5280 section 6.1.3 step a.3 calls for checking the certificate's
  // revocation status here. In this implementation revocation checking is
  // implemented separately from path validation.

  // Verify the certificate's issuer name matches the issuing certificate's
  // subject name. (RFC 5280 section 6.1.3 step a.4)
  if (cert.normalized_issuer() != working_normalized_issuer_name_) {
    errors->AddError(cert_errors::kSubjectDoesNotMatchIssuer);
  }

  // Name constraints (RFC 5280 section 6.1.3 step b & c)
  // If certificate i is self-issued and it is not the final certificate in the
  // path, skip this step for certificate i.
  if (!name_constraints_list_.empty() &&
      (!IsSelfIssued(cert) || is_target_cert)) {
    for (const NameConstraints *nc : name_constraints_list_) {
      nc->IsPermittedCert(cert.normalized_subject(), cert.subject_alt_names(),
                          errors);
    }
  }

  // RFC 5280 section 6.1.3 step d - f.
  VerifyPolicies(cert, is_target_cert, errors);

  // The key purpose is checked not just for the end-entity certificate, but
  // also interpreted as a constraint when it appears in intermediates. This
  // goes beyond what RFC 5280 describes, but is the de-facto standard. See
  // https://wiki.mozilla.org/CA:CertificatePolicyV2.1#Frequently_Asked_Questions
  VerifyExtendedKeyUsage(cert, required_key_purpose, errors, is_target_cert,
                         is_target_cert_issuer);
}

void PathVerifier::PrepareForNextCertificate(const ParsedCertificate &cert,
                                             CertErrors *errors) {
  // RFC 5280 section 6.1.4 step a-b
  VerifyPolicyMappings(cert, errors);

  // From RFC 5280 section 6.1.4 step c:
  //
  //    Assign the certificate subject name to working_normalized_issuer_name.
  working_normalized_issuer_name_ = cert.normalized_subject();

  // From RFC 5280 section 6.1.4 step d:
  //
  //    Assign the certificate subjectPublicKey to working_public_key.
  working_public_key_ = ParseAndCheckPublicKey(cert.tbs().spki_tlv, errors);

  // Note that steps e and f are omitted as they are handled by
  // the assignment to |working_spki| above. See the definition
  // of |working_spki|.

  // From RFC 5280 section 6.1.4 step g:
  if (cert.has_name_constraints()) {
    name_constraints_list_.push_back(&cert.name_constraints());
  }

  //     (h)  If certificate i is not self-issued:
  if (!IsSelfIssued(cert)) {
    //         (1)  If explicit_policy is not 0, decrement explicit_policy by
    //              1.
    if (explicit_policy_ > 0) {
      explicit_policy_ -= 1;
    }

    //         (2)  If policy_mapping is not 0, decrement policy_mapping by 1.
    if (policy_mapping_ > 0) {
      policy_mapping_ -= 1;
    }

    //         (3)  If inhibit_anyPolicy is not 0, decrement inhibit_anyPolicy
    //              by 1.
    if (inhibit_any_policy_ > 0) {
      inhibit_any_policy_ -= 1;
    }
  }

  // RFC 5280 section 6.1.4 step i-j:
  ApplyPolicyConstraints(cert);

  // From RFC 5280 section 6.1.4 step k:
  //
  //    If certificate i is a version 3 certificate, verify that the
  //    basicConstraints extension is present and that cA is set to
  //    TRUE.  (If certificate i is a version 1 or version 2
  //    certificate, then the application MUST either verify that
  //    certificate i is a CA certificate through out-of-band means
  //    or reject the certificate.  Conforming implementations may
  //    choose to reject all version 1 and version 2 intermediate
  //    certificates.)
  //
  // This code implicitly rejects non version 3 intermediates, since they
  // can't contain a BasicConstraints extension.
  if (!cert.has_basic_constraints()) {
    errors->AddError(cert_errors::kMissingBasicConstraints);
  } else if (!cert.basic_constraints().is_ca) {
    errors->AddError(cert_errors::kBasicConstraintsIndicatesNotCa);
  }

  // From RFC 5280 section 6.1.4 step l:
  //
  //    If the certificate was not self-issued, verify that
  //    max_path_length is greater than zero and decrement
  //    max_path_length by 1.
  if (!IsSelfIssued(cert)) {
    if (max_path_length_ == 0) {
      errors->AddError(cert_errors::kMaxPathLengthViolated);
    } else {
      --max_path_length_;
    }
  }

  // From RFC 5280 section 6.1.4 step m:
  //
  //    If pathLenConstraint is present in the certificate and is
  //    less than max_path_length, set max_path_length to the value
  //    of pathLenConstraint.
  if (cert.has_basic_constraints() && cert.basic_constraints().has_path_len &&
      cert.basic_constraints().path_len < max_path_length_) {
    max_path_length_ = cert.basic_constraints().path_len;
  }

  // From RFC 5280 section 6.1.4 step n:
  //
  //    If a key usage extension is present, verify that the
  //    keyCertSign bit is set.
  if (cert.has_key_usage() &&
      !cert.key_usage().AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)) {
    errors->AddError(cert_errors::kKeyCertSignBitNotSet);
  }

  // From RFC 5280 section 6.1.4 step o:
  //
  //    Recognize and process any other critical extension present in
  //    the certificate.  Process any other recognized non-critical
  //    extension present in the certificate that is relevant to path
  //    processing.
  VerifyNoUnconsumedCriticalExtensions(cert, errors,
                                       delegate_->AcceptPreCertificates());
}

// Checks if the target certificate has the CA bit set. If it does, add
// the appropriate error or warning to |errors|.
void VerifyTargetCertIsNotCA(const ParsedCertificate &cert,
                             KeyPurpose required_key_purpose,
                             CertErrors *errors) {
  if (cert.has_basic_constraints() && cert.basic_constraints().is_ca) {
    // In spite of RFC 5280 4.2.1.9 which says the CA properties MAY exist in
    // an end entity certificate, the CABF Baseline Requirements version
    // 1.8.4, 7.1.2.3(d) prohibit the CA bit being set in an end entity
    // certificate.
    switch (required_key_purpose) {
      case KeyPurpose::ANY_EKU:
        break;
      case KeyPurpose::SERVER_AUTH:
      case KeyPurpose::CLIENT_AUTH:
        errors->AddWarning(cert_errors::kTargetCertShouldNotBeCa);
        break;
      case KeyPurpose::SERVER_AUTH_STRICT:
      case KeyPurpose::CLIENT_AUTH_STRICT:
        errors->AddError(cert_errors::kTargetCertShouldNotBeCa);
        break;
    }
  }
}

void PathVerifier::WrapUp(const ParsedCertificate &cert,
                          KeyPurpose required_key_purpose,
                          const std::set<der::Input> &user_initial_policy_set,
                          bool allow_precertificate,
                          CertErrors * errors) {
  // From RFC 5280 section 6.1.5:
  //      (a)  If explicit_policy is not 0, decrement explicit_policy by 1.
  if (explicit_policy_ > 0) {
    explicit_policy_ -= 1;
  }

  //      (b)  If a policy constraints extension is included in the
  //           certificate and requireExplicitPolicy is present and has a
  //           value of 0, set the explicit_policy state variable to 0.
  if (cert.has_policy_constraints() &&
      cert.policy_constraints().require_explicit_policy.has_value() &&
      cert.policy_constraints().require_explicit_policy == 0) {
    explicit_policy_ = 0;
  }

  // Note step c-e are omitted as the verification function does
  // not output the working public key.

  // From RFC 5280 section 6.1.5 step f:
  //
  //    Recognize and process any other critical extension present in
  //    the certificate n.  Process any other recognized non-critical
  //    extension present in certificate n that is relevant to path
  //    processing.
  //
  // Note that this is duplicated by PrepareForNextCertificate() so as to
  // directly match the procedures in RFC 5280's section 6.1.
  VerifyNoUnconsumedCriticalExtensions(cert, errors, allow_precertificate);

  // This calculates the intersection from RFC 5280 section 6.1.5 step g, as
  // well as applying the deferred recursive node that were skipped earlier in
  // the process.
  user_constrained_policy_set_ =
      valid_policy_graph_.GetUserConstrainedPolicySet(user_initial_policy_set);

  // From RFC 5280 section 6.1.5 step g:
  //
  //    If either (1) the value of explicit_policy variable is greater than
  //    zero or (2) the valid_policy_tree is not NULL, then path processing
  //    has succeeded.
  if (explicit_policy_ == 0 && user_constrained_policy_set_.empty()) {
    errors->AddError(cert_errors::kNoValidPolicy);
  }

  // The following check is NOT part of RFC 5280 6.1.5's "Wrap-Up Procedure",
  // however is implied by RFC 5280 section 4.2.1.9, as well as CABF Base
  // Requirements.
  VerifyTargetCertIsNotCA(cert, required_key_purpose, errors);

  // Check the public key for the target certificate. The public key for the
  // other certificates is already checked by PrepareForNextCertificate().
  // Note that this step is not part of RFC 5280 6.1.5.
  ParseAndCheckPublicKey(cert.tbs().spki_tlv, errors);
}

void PathVerifier::ApplyTrustAnchorConstraints(const ParsedCertificate &cert,
                                               KeyPurpose required_key_purpose,
                                               CertErrors *errors) {
  // If certificatePolicies is present, process the policies. This matches the
  // handling for intermediates from RFC 5280 section 6.1.3.d (except that for
  // intermediates it is non-optional). It intentionally deviates from RFC 5937
  // section 3.2 which says to intersect with user-initial-policy-set, since
  // processing as part of user-initial-policy-set has subtly different
  // semantics from being handled as part of the chain processing (see
  // https://crbug.com/1403258).
  if (cert.has_policy_oids()) {
    VerifyPolicies(cert, /*is_target_cert=*/false, errors);
  }

  // Process policyMappings, if present. This matches the handling for
  // intermediates from RFC 5280 section 6.1.4 step a-b.
  VerifyPolicyMappings(cert, errors);

  // Process policyConstraints and inhibitAnyPolicy. This matches the
  // handling for intermediates from RFC 5280 section 6.1.4 step i-j.
  // This intentionally deviates from RFC 5937 section 3.2 which says to
  // initialize the initial-any-policy-inhibit, initial-explicit-policy, and/or
  // initial-policy-mapping-inhibit inputs to verification. Those are all
  // bools, so they cannot properly represent the constraints encoded in the
  // policyConstraints and inhibitAnyPolicy extensions.
  ApplyPolicyConstraints(cert);

  // If keyUsage is present, verify that |cert| has correct keyUsage bits for a
  // CA. This matches the handling for intermediates from RFC 5280 section
  // 6.1.4 step n.
  if (cert.has_key_usage() &&
      !cert.key_usage().AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)) {
    errors->AddError(cert_errors::kKeyCertSignBitNotSet);
  }

  // This is not part of RFC 5937 nor RFC 5280, but matches the EKU handling
  // done for intermediates (described in Web PKI's Baseline Requirements).
  VerifyExtendedKeyUsage(cert, required_key_purpose, errors,
                         /*is_target_cert=*/false,
                         /*is_target_cert_issuer=*/false);

  // The following enforcements follow from RFC 5937 (primarily section 3.2):

  // Initialize name constraints initial-permitted/excluded-subtrees.
  if (cert.has_name_constraints()) {
    name_constraints_list_.push_back(&cert.name_constraints());
  }

  if (cert.has_basic_constraints()) {
    // Enforce CA=true if basicConstraints is present. This matches behavior of
    // other verifiers, and seems like a good thing to do to avoid a
    // certificate being used in the wrong context if it was specifically
    // marked as not being a CA.
    if (!cert.basic_constraints().is_ca) {
      errors->AddError(cert_errors::kBasicConstraintsIndicatesNotCa);
    }
    // From RFC 5937 section 3.2:
    //
    //    If a basic constraints extension is associated with the trust
    //    anchor and contains a pathLenConstraint value, set the
    //    max_path_length state variable equal to the pathLenConstraint
    //    value from the basic constraints extension.
    //
    if (cert.basic_constraints().has_path_len) {
      max_path_length_ = cert.basic_constraints().path_len;
    }
  }

  // From RFC 5937 section 2:
  //
  //    Extensions may be marked critical or not critical.  When trust anchor
  //    constraints are enforced, clients MUST reject certification paths
  //    containing a trust anchor with unrecognized critical extensions.
  VerifyNoUnconsumedCriticalExtensions(cert, errors,
                                       /*allow_precertificate=*/false);
}

void PathVerifier::ProcessRootCertificate(const ParsedCertificate &cert,
                                          const CertificateTrust &trust,
                                          const der::GeneralizedTime &time,
                                          KeyPurpose required_key_purpose,
                                          CertErrors *errors,
                                          bool *shortcircuit_chain_validation) {
  *shortcircuit_chain_validation = false;
  switch (trust.type) {
    case CertificateTrustType::UNSPECIFIED:
    case CertificateTrustType::TRUSTED_LEAF:
      // Doesn't chain to a trust anchor - implicitly distrusted
      errors->AddError(cert_errors::kCertIsNotTrustAnchor);
      *shortcircuit_chain_validation = true;
      break;
    case CertificateTrustType::DISTRUSTED:
      // Chains to an actively distrusted certificate.
      errors->AddError(cert_errors::kDistrustedByTrustStore);
      *shortcircuit_chain_validation = true;
      break;
    case CertificateTrustType::TRUSTED_ANCHOR:
    case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
      break;
  }
  if (*shortcircuit_chain_validation) {
    return;
  }

  if (trust.enforce_anchor_expiry) {
    VerifyTimeValidity(cert, time, errors);
  }
  if (trust.enforce_anchor_constraints) {
    if (trust.require_anchor_basic_constraints &&
        !cert.has_basic_constraints()) {
      switch (cert.tbs().version) {
        case CertificateVersion::V1:
        case CertificateVersion::V2:
          break;
        case CertificateVersion::V3:
          errors->AddError(cert_errors::kMissingBasicConstraints);
          break;
      }
    }
    ApplyTrustAnchorConstraints(cert, required_key_purpose, errors);
  }

  // Use the certificate's SPKI and subject when verifying the next certificate.
  working_public_key_ = ParseAndCheckPublicKey(cert.tbs().spki_tlv, errors);
  working_normalized_issuer_name_ = cert.normalized_subject();
}

void PathVerifier::ProcessSingleCertChain(const ParsedCertificate &cert,
                                          const CertificateTrust &trust,
                                          const der::GeneralizedTime &time,
                                          KeyPurpose required_key_purpose,
                                          CertErrors *errors) {
  switch (trust.type) {
    case CertificateTrustType::UNSPECIFIED:
    case CertificateTrustType::TRUSTED_ANCHOR:
      // Target doesn't have a chain and isn't a directly trusted leaf -
      // implicitly distrusted.
      errors->AddError(cert_errors::kCertIsNotTrustAnchor);
      return;
    case CertificateTrustType::DISTRUSTED:
      // Target is directly distrusted.
      errors->AddError(cert_errors::kDistrustedByTrustStore);
      return;
    case CertificateTrustType::TRUSTED_LEAF:
    case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
      break;
  }

  // Check the public key for the target certificate regardless of whether
  // `require_leaf_selfsigned` is true. This matches the check in WrapUp and
  // fulfills the documented behavior of the IsPublicKeyAcceptable delegate.
  ParseAndCheckPublicKey(cert.tbs().spki_tlv, errors);

  if (trust.require_leaf_selfsigned) {
    if (!VerifyCertificateIsSelfSigned(cert, delegate_->GetVerifyCache(),
                                       errors)) {
      // VerifyCertificateIsSelfSigned should have added an error, but just
      // double check to be safe.
      if (!errors->ContainsAnyErrorWithSeverity(CertError::SEVERITY_HIGH)) {
        errors->AddError(cert_errors::kInternalError);
      }
      return;
    }
  }

  // There is no standard for what it means to verify a directly trusted leaf
  // certificate, so this is basically just checking common sense things that
  // also mirror what we observed to be enforced with the Operating System
  // native verifiers.
  VerifyTimeValidity(cert, time, errors);
  VerifyExtendedKeyUsage(cert, required_key_purpose, errors,
                         /*is_target_cert=*/true,
                         /*is_target_cert_issuer=*/false);

  // Checking for unknown critical extensions matches Windows, but is stricter
  // than the Mac verifier.
  VerifyNoUnconsumedCriticalExtensions(cert, errors,
                                       /*allow_precertificate=*/false);
}

bssl::UniquePtr<EVP_PKEY> PathVerifier::ParseAndCheckPublicKey(
    der::Input spki, CertErrors *errors) {
  // Parse the public key.
  bssl::UniquePtr<EVP_PKEY> pkey;
  if (!ParsePublicKey(spki, &pkey)) {
    errors->AddError(cert_errors::kFailedParsingSpki);
    return nullptr;
  }

  // Check if the key is acceptable by the delegate.
  if (!delegate_->IsPublicKeyAcceptable(pkey.get(), errors)) {
    errors->AddError(cert_errors::kUnacceptablePublicKey);
  }

  return pkey;
}

void PathVerifier::Run(
    const ParsedCertificateList &certs, const CertificateTrust &last_cert_trust,
    VerifyCertificateChainDelegate *delegate, const der::GeneralizedTime &time,
    KeyPurpose required_key_purpose,
    InitialExplicitPolicy initial_explicit_policy,
    const std::set<der::Input> &user_initial_policy_set,
    InitialPolicyMappingInhibit initial_policy_mapping_inhibit,
    InitialAnyPolicyInhibit initial_any_policy_inhibit,
    std::set<der::Input> *user_constrained_policy_set, CertPathErrors *errors) {
  // This implementation is structured to mimic the description of certificate
  // path verification given by RFC 5280 section 6.1.
  BSSL_CHECK(delegate);
  BSSL_CHECK(errors);

  delegate_ = delegate;

  // An empty chain is necessarily invalid.
  if (certs.empty()) {
    errors->GetOtherErrors()->AddError(cert_errors::kChainIsEmpty);
    return;
  }

  // Verifying a trusted leaf certificate isn't a well-specified operation, so
  // it's handled separately from the RFC 5280 defined verification process.
  if (certs.size() == 1) {
    ProcessSingleCertChain(*certs.front(), last_cert_trust, time,
                           required_key_purpose, errors->GetErrorsForCert(0));
    return;
  }

  // RFC 5280's "n" variable is the length of the path, which does not count
  // the trust anchor. (Although in practice it doesn't really change behaviors
  // if n is used in place of n+1).
  const size_t n = certs.size() - 1;

  valid_policy_graph_.Init();

  // RFC 5280 section section 6.1.2:
  //
  // If initial-explicit-policy is set, then the initial value
  // [of explicit_policy] is 0, otherwise the initial value is n+1.
  explicit_policy_ =
      initial_explicit_policy == InitialExplicitPolicy::kTrue ? 0 : n + 1;

  // RFC 5280 section section 6.1.2:
  //
  // If initial-any-policy-inhibit is set, then the initial value
  // [of inhibit_anyPolicy] is 0, otherwise the initial value is n+1.
  inhibit_any_policy_ =
      initial_any_policy_inhibit == InitialAnyPolicyInhibit::kTrue ? 0 : n + 1;

  // RFC 5280 section section 6.1.2:
  //
  // If initial-policy-mapping-inhibit is set, then the initial value
  // [of policy_mapping] is 0, otherwise the initial value is n+1.
  policy_mapping_ =
      initial_policy_mapping_inhibit == InitialPolicyMappingInhibit::kTrue
          ? 0
          : n + 1;

  // RFC 5280 section section 6.1.2:
  //
  // max_path_length:  this integer is initialized to n, ...
  max_path_length_ = n;

  // Iterate over all the certificates in the reverse direction: starting from
  // the root certificate and progressing towards the target certificate.
  //
  //   * i=0  :  Root certificate (i.e. trust anchor)
  //   * i=1  :  Certificate issued by root
  //   * i=x  :  Certificate i=x is issued by certificate i=x-1
  //   * i=n  :  Target certificate.
  for (size_t i = 0; i < certs.size(); ++i) {
    const size_t index_into_certs = certs.size() - i - 1;

    // |is_target_cert| is true if the current certificate is the target
    // certificate being verified. The target certificate isn't necessarily an
    // end-entity certificate.
    const bool is_target_cert = index_into_certs == 0;
    const bool is_target_cert_issuer = index_into_certs == 1;
    const bool is_root_cert = i == 0;

    const ParsedCertificate &cert = *certs[index_into_certs];

    // Output errors for the current certificate into an error bucket that is
    // associated with that certificate.
    CertErrors *cert_errors = errors->GetErrorsForCert(index_into_certs);

    if (is_root_cert) {
      bool shortcircuit_chain_validation = false;
      ProcessRootCertificate(cert, last_cert_trust, time, required_key_purpose,
                             cert_errors, &shortcircuit_chain_validation);
      if (shortcircuit_chain_validation) {
        // Chains that don't start from a trusted root should short-circuit the
        // rest of the verification, as accumulating more errors from untrusted
        // certificates would not be meaningful.
        BSSL_CHECK(cert_errors->ContainsAnyErrorWithSeverity(
            CertError::SEVERITY_HIGH));
        return;
      }

      // Don't do any other checks for root certificates.
      continue;
    }

    bool shortcircuit_chain_validation = false;
    // Per RFC 5280 section 6.1:
    //  * Do basic processing for each certificate
    //  * If it is the last certificate in the path (target certificate)
    //     - Then run "Wrap up"
    //     - Otherwise run "Prepare for Next cert"
    BasicCertificateProcessing(cert, is_target_cert, is_target_cert_issuer,
                               time, required_key_purpose, cert_errors,
                               &shortcircuit_chain_validation);
    if (shortcircuit_chain_validation) {
      // Signature errors should short-circuit the rest of the verification, as
      // accumulating more errors from untrusted certificates would not be
      // meaningful.
      BSSL_CHECK(
          cert_errors->ContainsAnyErrorWithSeverity(CertError::SEVERITY_HIGH));
      return;
    }
    if (!is_target_cert) {
      PrepareForNextCertificate(cert, cert_errors);
    } else {
      WrapUp(cert, required_key_purpose, user_initial_policy_set,
             delegate->AcceptPreCertificates(), cert_errors);
    }
  }

  if (user_constrained_policy_set) {
    *user_constrained_policy_set = user_constrained_policy_set_;
  }

  // TODO(eroman): RFC 5280 forbids duplicate certificates per section 6.1:
  //
  //    A certificate MUST NOT appear more than once in a prospective
  //    certification path.
}

}  // namespace

VerifyCertificateChainDelegate::~VerifyCertificateChainDelegate() = default;

void VerifyCertificateChain(
    const ParsedCertificateList &certs, const CertificateTrust &last_cert_trust,
    VerifyCertificateChainDelegate *delegate, const der::GeneralizedTime &time,
    KeyPurpose required_key_purpose,
    InitialExplicitPolicy initial_explicit_policy,
    const std::set<der::Input> &user_initial_policy_set,
    InitialPolicyMappingInhibit initial_policy_mapping_inhibit,
    InitialAnyPolicyInhibit initial_any_policy_inhibit,
    std::set<der::Input> *user_constrained_policy_set, CertPathErrors *errors) {
  PathVerifier verifier;
  verifier.Run(certs, last_cert_trust, delegate, time, required_key_purpose,
               initial_explicit_policy, user_initial_policy_set,
               initial_policy_mapping_inhibit, initial_any_policy_inhibit,
               user_constrained_policy_set, errors);
}

bool VerifyCertificateIsSelfSigned(const ParsedCertificate &cert,
                                   SignatureVerifyCache *cache,
                                   CertErrors *errors) {
  if (cert.normalized_subject() != cert.normalized_issuer()) {
    if (errors) {
      errors->AddError(cert_errors::kSubjectDoesNotMatchIssuer);
    }
    return false;
  }

  // Note that we do not restrict the available algorithms when determining if
  // something is a self-signed cert. The signature isn't very important on a
  // self-signed cert so just allow any supported algorithm here, to avoid
  // breakage.
  if (!cert.signature_algorithm().has_value()) {
    if (errors) {
      errors->AddError(cert_errors::kUnacceptableSignatureAlgorithm);
    }
    return false;
  }

  if (!VerifySignedData(*cert.signature_algorithm(), cert.tbs_certificate_tlv(),
                        cert.signature_value(), cert.tbs().spki_tlv, cache)) {
    if (errors) {
      errors->AddError(cert_errors::kVerifySignedDataFailed);
    }
    return false;
  }

  return true;
}

}  // namespace bssl
