// Copyright 2016 The Chromium Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "path_builder.h"

#include <cassert>
#include <cstddef>
#include <memory>
#include <set>
#include <unordered_set>

#include <openssl/base.h>
#include <openssl/pki/verify_error.h>
#include <openssl/sha2.h>
#include <openssl/span.h>

#include "cert_issuer_source.h"
#include "certificate_policies.h"
#include "common_cert_errors.h"
#include "parse_certificate.h"
#include "parse_name.h"  // For CertDebugString.
#include "parsed_certificate.h"
#include "parser.h"
#include "string_util.h"
#include "trust_store.h"
#include "verify_certificate_chain.h"
#include "verify_name_match.h"

BSSL_NAMESPACE_BEGIN

namespace {

using CertIssuerSources = std::vector<CertIssuerSource *>;

// Returns a hex-encoded sha256 of the DER-encoding of `cert`.
std::string FingerPrintParsedCertificate(const bssl::ParsedCertificate *cert) {
  uint8_t digest[SHA256_DIGEST_LENGTH];
  SHA256(cert->der_cert().data(), cert->der_cert().size(), digest);
  return bssl::string_util::HexEncode(digest);
}

// TODO(mattm): decide how much debug logging to keep.
std::string CertDebugString(const ParsedCertificate *cert) {
  RDNSequence subject;
  std::string subject_str;
  if (!ParseName(cert->tbs().subject_tlv, &subject) ||
      !ConvertToRFC2253(subject, &subject_str)) {
    subject_str = "???";
  }

  return FingerPrintParsedCertificate(cert) + " " + subject_str;
}

std::string PathDebugString(const ParsedCertificateList &certs) {
  std::string s;
  for (const auto &cert : certs) {
    if (!s.empty()) {
      s += "\n";
    }
    s += " " + CertDebugString(cert.get());
  }
  return s;
}

// This structure describes a certificate and its trust level. Note that `cert`
// may be null to indicate an "empty" entry.
struct IssuerEntry {
  std::shared_ptr<const ParsedCertificate> cert;
  TrustAnchor trust;
  int trust_and_key_id_match_ordering;
};

enum KeyIdentifierMatch {
  // `target` has a keyIdentifier and it matches `issuer`'s
  // subjectKeyIdentifier.
  kMatch = 0,
  // `target` does not have authorityKeyIdentifier or `issuer` does not have
  // subjectKeyIdentifier.
  kNoData = 1,
  // `target`'s authorityKeyIdentifier does not match `issuer`.
  kMismatch = 2,
};

// Returns an integer that represents the relative ordering of `issuer` for
// prioritizing certificates in path building based on `issuer`'s
// subjectKeyIdentifier and `target`'s authorityKeyIdentifier. Lower return
// values indicate higher priority.
KeyIdentifierMatch CalculateKeyIdentifierMatch(
    const ParsedCertificate *target, const ParsedCertificate *issuer) {
  if (!target->authority_key_identifier()) {
    return kNoData;
  }

  // TODO(crbug.com/635205): If issuer does not have a subjectKeyIdentifier,
  // could try synthesizing one using the standard SHA-1 method. Ideally in a
  // way where any issuers that do have a matching subjectKeyIdentifier could
  // be tried first before doing the extra work.
  if (target->authority_key_identifier()->key_identifier &&
      issuer->subject_key_identifier()) {
    if (target->authority_key_identifier()->key_identifier !=
        issuer->subject_key_identifier().value()) {
      return kMismatch;
    }
    return kMatch;
  }

  return kNoData;
}

// Returns an integer that represents the relative ordering of `issuer` based
// on `issuer_trust` and authorityKeyIdentifier matching for prioritizing
// certificates in path building. Lower return values indicate higher priority.
int TrustAndKeyIdentifierMatchToOrder(const ParsedCertificate *target,
                                      const ParsedCertificate *issuer,
                                      const CertificateTrust &issuer_trust) {
  enum {
    kTrustedAndKeyIdMatch = 0,
    kTrustedAndKeyIdNoData = 1,
    kKeyIdMatch = 2,
    kKeyIdNoData = 3,
    kTrustedAndKeyIdMismatch = 4,
    kKeyIdMismatch = 5,
    kDistrustedAndKeyIdMatch = 6,
    kDistrustedAndKeyIdNoData = 7,
    kDistrustedAndKeyIdMismatch = 8,
  };

  KeyIdentifierMatch key_id_match = CalculateKeyIdentifierMatch(target, issuer);
  switch (issuer_trust.type) {
    case CertificateTrustType::TRUSTED_ANCHOR:
    case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
      switch (key_id_match) {
        case kMatch:
          return kTrustedAndKeyIdMatch;
        case kNoData:
          return kTrustedAndKeyIdNoData;
        case kMismatch:
          return kTrustedAndKeyIdMismatch;
      }
      break;
    case CertificateTrustType::UNSPECIFIED:
    case CertificateTrustType::TRUSTED_LEAF:
      switch (key_id_match) {
        case kMatch:
          return kKeyIdMatch;
        case kNoData:
          return kKeyIdNoData;
        case kMismatch:
          return kKeyIdMismatch;
      }
      break;
    case CertificateTrustType::DISTRUSTED:
      switch (key_id_match) {
        case kMatch:
          return kDistrustedAndKeyIdMatch;
        case kNoData:
          return kDistrustedAndKeyIdNoData;
        case kMismatch:
          return kDistrustedAndKeyIdMismatch;
      }
      break;
  }
  assert(0);  // NOTREACHED
  return -1;
}

// CertIssuersIter iterates through the intermediates from `cert_issuer_sources`
// which may be issuers of `cert`.
class CertIssuersIter {
 public:
  // Constructs the CertIssuersIter. `*cert_issuer_sources`, and
  // `*trust_store` must be valid for the lifetime of the CertIssuersIter.
  CertIssuersIter(std::shared_ptr<const ParsedCertificate> cert,
                  CertIssuerSources *cert_issuer_sources,
                  TrustStore *trust_store);

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

  // Gets the next candidate issuer, or clears `*out` when all issuers have been
  // exhausted.
  void GetNextIssuer(IssuerEntry *out);

  // Returns true if candidate issuers were found for `cert_`.
  bool had_non_skipped_issuers() const {
    return issuers_.size() > skipped_issuer_count_;
  }

  void increment_skipped_issuer_count() { skipped_issuer_count_++; }

  // Returns the `cert` for which issuers are being retrieved.
  const ParsedCertificate *cert() const { return cert_.get(); }
  std::shared_ptr<const ParsedCertificate> reference_cert() const {
    return cert_;
  }

 private:
  void AddIssuers(ParsedCertificateList issuers);
  void MaybeAddMTCIssuer();
  void DoAsyncIssuerQuery();

  // Returns true if `issuers_` contains unconsumed certificates.
  bool HasCurrentIssuer() const { return cur_issuer_ < issuers_.size(); }

  // Sorts the remaining entries in `issuers_` in the preferred order to
  // explore. Does not change the ordering for indices before cur_issuer_.
  void SortRemainingIssuers();

  std::shared_ptr<const ParsedCertificate> cert_;
  CertIssuerSources *cert_issuer_sources_;
  TrustStore *trust_store_;

  // The list of issuers for `cert_`. This is added to incrementally (first
  // synchronous results, then possibly multiple times as asynchronous results
  // arrive.) The issuers may be re-sorted each time new issuers are added, but
  // only the results from `cur_` onwards should be sorted, since the earlier
  // results were already returned.
  // Elements should not be removed from `issuers_` once added, since
  // `present_issuers_` will point to data owned by the certs.
  std::vector<IssuerEntry> issuers_;
  // The index of the next cert in `issuers_` to return.
  size_t cur_issuer_ = 0;
  // The number of issuers that were skipped due to the loop checker.
  size_t skipped_issuer_count_ = 0;
  // Set to true whenever new issuers are appended at the end, to indicate the
  // ordering needs to be checked.
  bool issuers_needs_sort_ = false;

  // Set of DER-encoded values for the certs in `issuers_`. Used to prevent
  // duplicates. This is based on the full DER of the cert to allow different
  // versions of the same certificate to be tried in different candidate paths.
  // This points to data owned by `issuers_`.
  std::unordered_set<std::string_view> present_issuers_;

  // Tracks which requests have been made yet.
  bool did_initial_query_ = false;
  bool did_async_issuer_query_ = false;
  // Index into pending_async_requests_ that is the next one to process.
  size_t cur_async_request_ = 0;
  // Owns the Request objects for any asynchronous requests so that they will be
  // cancelled if CertIssuersIter is destroyed.
  std::vector<std::unique_ptr<CertIssuerSource::Request>>
      pending_async_requests_;
};

CertIssuersIter::CertIssuersIter(
    std::shared_ptr<const ParsedCertificate> in_cert,
    CertIssuerSources *cert_issuer_sources, TrustStore *trust_store)
    : cert_(std::move(in_cert)),
      cert_issuer_sources_(cert_issuer_sources),
      trust_store_(trust_store) {}

void CertIssuersIter::GetNextIssuer(IssuerEntry *out) {
  if (!did_initial_query_) {
    did_initial_query_ = true;
    for (auto *cert_issuer_source : *cert_issuer_sources_) {
      ParsedCertificateList new_issuers;
      cert_issuer_source->SyncGetIssuersOf(cert(), &new_issuers);
      AddIssuers(std::move(new_issuers));
    }
    MaybeAddMTCIssuer();
  }

  // If there aren't any issuers, block until async results are ready.
  if (!HasCurrentIssuer()) {
    if (!did_async_issuer_query_) {
      // Now issue request(s) for async ones (AIA, etc).
      DoAsyncIssuerQuery();
    }

    // TODO(eroman): Rather than blocking on the async requests in FIFO order,
    // consume in the order they become ready.
    while (!HasCurrentIssuer() &&
           cur_async_request_ < pending_async_requests_.size()) {
      ParsedCertificateList new_issuers;
      pending_async_requests_[cur_async_request_]->GetNext(&new_issuers);
      if (new_issuers.empty()) {
        // Request is exhausted, no more results pending from that
        // CertIssuerSource.
        pending_async_requests_[cur_async_request_++].reset();
      } else {
        AddIssuers(std::move(new_issuers));
      }
    }
  }

  if (HasCurrentIssuer()) {
    SortRemainingIssuers();

    // Still have issuers that haven't been returned yet, return the highest
    // priority one (head of remaining list). A reference to the returned issuer
    // is retained, since `present_issuers_` points to data owned by it.
    *out = issuers_[cur_issuer_++];
    return;
  }

  // Reached the end of all available issuers.
  *out = IssuerEntry();
}

void CertIssuersIter::AddIssuers(ParsedCertificateList new_issuers) {
  for (std::shared_ptr<const ParsedCertificate> &issuer : new_issuers) {
    if (present_issuers_.find(BytesAsStringView(issuer->der_cert())) !=
        present_issuers_.end()) {
      continue;
    }
    present_issuers_.insert(BytesAsStringView(issuer->der_cert()));

    // Look up the trust for this issuer.
    IssuerEntry entry;
    entry.cert = std::move(issuer);
    entry.trust = TrustAnchor(trust_store_->GetTrust(entry.cert.get()));
    entry.trust_and_key_id_match_ordering = TrustAndKeyIdentifierMatchToOrder(
        cert(), entry.cert.get(), entry.trust.CertTrust());

    issuers_.push_back(std::move(entry));
    issuers_needs_sort_ = true;
  }
}

void CertIssuersIter::MaybeAddMTCIssuer() {
  std::shared_ptr<const MTCAnchor> mtc_trust_anchor =
      trust_store_->GetTrustedMTCIssuerOf(cert_.get());
  if (!mtc_trust_anchor) {
    return;
  }
  std::shared_ptr<const ParsedCertificate> trust_anchor_cert =
      mtc_trust_anchor->AsCert();
  // Add one issuer for the mtc_trust_anchor.
  present_issuers_.insert(BytesAsStringView(trust_anchor_cert->der_cert()));
  IssuerEntry entry;
  entry.cert = std::move(trust_anchor_cert);
  entry.trust = TrustAnchor(mtc_trust_anchor->CertTrust(), mtc_trust_anchor);
  entry.trust_and_key_id_match_ordering = 0; /* kTrustedAndKeyIdMatch */
  issuers_.push_back(std::move(entry));
  issuers_needs_sort_ = true;
}

void CertIssuersIter::DoAsyncIssuerQuery() {
  BSSL_CHECK(!did_async_issuer_query_);
  did_async_issuer_query_ = true;
  cur_async_request_ = 0;
  for (auto *cert_issuer_source : *cert_issuer_sources_) {
    std::unique_ptr<CertIssuerSource::Request> request;
    cert_issuer_source->AsyncGetIssuersOf(cert(), &request);
    if (request) {
      pending_async_requests_.push_back(std::move(request));
    }
  }
}

void CertIssuersIter::SortRemainingIssuers() {
  if (!issuers_needs_sort_) {
    return;
  }

  std::stable_sort(
      issuers_.begin() + cur_issuer_, issuers_.end(),
      [](const IssuerEntry &issuer1, const IssuerEntry &issuer2) {
        // TODO(crbug.com/635205): Add other prioritization hints. (See big list
        // of possible sorting hints in RFC 4158.)
        const bool issuer1_self_issued = issuer1.cert->normalized_subject() ==
                                         issuer1.cert->normalized_issuer();
        const bool issuer2_self_issued = issuer2.cert->normalized_subject() ==
                                         issuer2.cert->normalized_issuer();
        return std::tie(issuer1.trust_and_key_id_match_ordering,
                        issuer2_self_issued,
                        // Newer(larger) notBefore & notAfter dates are
                        // preferred, hence `issuer2` is on the LHS of
                        // the comparison and `issuer1` on the RHS.
                        issuer2.cert->tbs().validity_not_before,
                        issuer2.cert->tbs().validity_not_after) <
               std::tie(issuer2.trust_and_key_id_match_ordering,
                        issuer1_self_issued,
                        issuer1.cert->tbs().validity_not_before,
                        issuer1.cert->tbs().validity_not_after);
      });

  issuers_needs_sort_ = false;
}

// CertIssuerIterPath tracks which certs are present in the path and prevents
// paths from being built which repeat any certs (including different versions
// of the same cert, based on Subject+SubjectAltName+SPKI).
// (RFC 5280 forbids duplicate certificates per section 6.1, and RFC 4158
// further recommends disallowing the same Subject+SubjectAltName+SPKI in
// section 2.4.2.)
class CertIssuerIterPath {
 public:
  // Returns true if `cert` is already present in the path.
  bool IsPresent(const ParsedCertificate *cert) const {
    return present_certs_.find(GetKey(cert)) != present_certs_.end();
  }

  // Appends `cert_issuers_iter` to the path. The cert referred to by
  // `cert_issuers_iter` must not be present in the path already.
  void Append(std::unique_ptr<CertIssuersIter> cert_issuers_iter) {
    bool added =
        present_certs_.insert(GetKey(cert_issuers_iter->cert())).second;
    BSSL_CHECK(added);
    cur_path_.push_back(std::move(cert_issuers_iter));
  }

  // Pops the last CertIssuersIter off the path.
  void Pop() {
    size_t num_erased = present_certs_.erase(GetKey(cur_path_.back()->cert()));
    BSSL_CHECK(num_erased == 1U);
    cur_path_.pop_back();
  }

  // Copies the ParsedCertificate elements of the current path to `*out_path`.
  void CopyPath(ParsedCertificateList *out_path) {
    out_path->clear();
    for (const auto &node : cur_path_) {
      out_path->push_back(node->reference_cert());
    }
  }

  // Returns true if the path is empty.
  bool Empty() const { return cur_path_.empty(); }

  // Returns the last CertIssuersIter in the path.
  CertIssuersIter *back() { return cur_path_.back().get(); }

  // Returns the length of the path.
  size_t Length() const { return cur_path_.size(); }

  std::string PathDebugString() {
    std::string s;
    for (const auto &node : cur_path_) {
      if (!s.empty()) {
        s += "\n";
      }
      s += " " + CertDebugString(node->cert());
    }
    return s;
  }

 private:
  using Key = std::tuple<std::string_view, std::string_view, std::string_view>;

  static Key GetKey(const ParsedCertificate *cert) {
    // TODO(mattm): ideally this would use a normalized version of
    // SubjectAltName, but it's not that important just for LoopChecker.
    //
    // Note that subject_alt_names_extension().value will be empty if the cert
    // had no SubjectAltName extension, so there is no need for a condition on
    // has_subject_alt_names().
    return Key(BytesAsStringView(cert->normalized_subject()),
               BytesAsStringView(cert->subject_alt_names_extension().value),
               BytesAsStringView(cert->tbs().spki_tlv));
  }

  std::vector<std::unique_ptr<CertIssuersIter>> cur_path_;

  // This refers to data owned by `cur_path_`.
  // TODO(mattm): use unordered_set. Requires making a hash function for Key.
  std::set<Key> present_certs_;
};

}  // namespace

const ParsedCertificate *CertPathBuilderResultPath::GetTrustedCert() const {
  if (certs.empty()) {
    return nullptr;
  }

  switch (last_cert_trust.type) {
    case CertificateTrustType::TRUSTED_ANCHOR:
    case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
    case CertificateTrustType::TRUSTED_LEAF:
      return certs.back().get();
    case CertificateTrustType::UNSPECIFIED:
    case CertificateTrustType::DISTRUSTED:
      return nullptr;
  }

  assert(0);  // NOTREACHED
  return nullptr;
}

// CertPathIter generates possible paths from `cert` to a trust anchor in
// `trust_store`, using intermediates from the `cert_issuer_source` objects if
// necessary.
class CertPathIter {
 public:
  CertPathIter(std::shared_ptr<const ParsedCertificate> cert,
               TrustStore *trust_store);

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

  // Adds a CertIssuerSource to provide intermediates for use in path building.
  // The `*cert_issuer_source` must remain valid for the lifetime of the
  // CertPathIter.
  void AddCertIssuerSource(CertIssuerSource *cert_issuer_source);

  // Gets the next candidate path, and fills it into `out_certs` and
  // `out_last_cert_trust`. Note that the returned path is unverified and must
  // still be run through a chain validator. If a candidate path could not be
  // built, a partial path will be returned and `out_errors` will have an error
  // added.
  // If the return value is true, GetNextPath may be called again to backtrack
  // and continue path building. Once all paths have been exhausted returns
  // false. If deadline or iteration limit is exceeded, sets `out_certs` to the
  // current path being explored and returns false.
  bool GetNextPath(ParsedCertificateList *out_certs,
                   TrustAnchor *out_last_cert_trust, CertPathErrors *out_errors,
                   CertPathBuilderDelegate *delegate, uint32_t *iteration_count,
                   const uint32_t max_iteration_count,
                   const uint32_t max_path_building_depth);

 private:
  // Stores the next candidate issuer, until it is used during the
  // STATE_GET_NEXT_ISSUER_COMPLETE step.
  IssuerEntry next_issuer_;
  // The current path being explored, made up of CertIssuerIters. Each node
  // keeps track of the state of searching for issuers of that cert, so that
  // when backtracking it can resume the search where it left off.
  CertIssuerIterPath cur_path_;
  // The CertIssuerSources for retrieving candidate issuers.
  CertIssuerSources cert_issuer_sources_;
  // The TrustStore for checking if a path ends in a trust anchor.
  TrustStore *trust_store_;
};

CertPathIter::CertPathIter(std::shared_ptr<const ParsedCertificate> cert,
                           TrustStore *trust_store)
    : trust_store_(trust_store) {
  // Initialize `next_issuer_` to the target certificate.
  next_issuer_.cert = std::move(cert);
  next_issuer_.trust =
      TrustAnchor(trust_store_->GetTrust(next_issuer_.cert.get()));
}

void CertPathIter::AddCertIssuerSource(CertIssuerSource *cert_issuer_source) {
  cert_issuer_sources_.push_back(cert_issuer_source);
}

bool CertPathIter::GetNextPath(ParsedCertificateList *out_certs,
                               TrustAnchor *out_last_cert_trust,
                               CertPathErrors *out_errors,
                               CertPathBuilderDelegate *delegate,
                               uint32_t *iteration_count,
                               const uint32_t max_iteration_count,
                               const uint32_t max_path_building_depth) {
  out_certs->clear();
  *out_last_cert_trust = TrustAnchor();

  while (true) {
    if (delegate->IsDeadlineExpired()) {
      if (cur_path_.Empty()) {
        // If the deadline is already expired before the first call to
        // GetNextPath, cur_path_ will be empty. Return the leaf cert in that
        // case.
        if (next_issuer_.cert) {
          out_certs->push_back(next_issuer_.cert);
        }
      } else {
        cur_path_.CopyPath(out_certs);
      }
      out_errors->GetOtherErrors()->AddError(cert_errors::kDeadlineExceeded);
      return false;
    }

    // We are not done yet, so if the current path is at the depth limit then
    // we must backtrack to find an acceptable solution.
    if (max_path_building_depth > 0 &&
        cur_path_.Length() >= max_path_building_depth) {
      cur_path_.CopyPath(out_certs);
      out_errors->GetOtherErrors()->AddError(cert_errors::kDepthLimitExceeded);
      if (delegate->IsDebugLogEnabled()) {
        delegate->DebugLog(
            "CertPathIter reached depth limit. Returning "
            "partial path and backtracking:\n" +
            PathDebugString(*out_certs));
      }
      cur_path_.Pop();
      return true;
    }

    if (!next_issuer_.cert) {
      if (cur_path_.Empty()) {
        if (delegate->IsDebugLogEnabled()) {
          delegate->DebugLog("CertPathIter exhausted all paths...");
        }
        return false;
      }

      (*iteration_count)++;
      if (max_iteration_count > 0 && *iteration_count > max_iteration_count) {
        cur_path_.CopyPath(out_certs);
        out_errors->GetOtherErrors()->AddError(
            cert_errors::kIterationLimitExceeded);
        return false;
      }

      cur_path_.back()->GetNextIssuer(&next_issuer_);
      if (!next_issuer_.cert) {
        if (!cur_path_.back()->had_non_skipped_issuers()) {
          // If the end of a path was reached without finding an anchor, return
          // the partial path before backtracking.
          cur_path_.CopyPath(out_certs);
          out_errors->GetErrorsForCert(out_certs->size() - 1)
              ->AddError(cert_errors::kNoIssuersFound);
          if (delegate->IsDebugLogEnabled()) {
            delegate->DebugLog(
                "CertPathIter returning partial path and backtracking:\n" +
                PathDebugString(*out_certs));
          }
          cur_path_.Pop();
          return true;
        } else {
          // No more issuers for current chain, go back up and see if there are
          // any more for the previous cert.
          if (delegate->IsDebugLogEnabled()) {
            delegate->DebugLog("CertPathIter backtracking...");
          }
          cur_path_.Pop();
          continue;
        }
      }
    }

    // Overrides for cert with trust appearing in the wrong place for the type
    // of trust (trusted leaf in non-leaf position, or trust anchor in leaf
    // position.)
    switch (next_issuer_.trust.CertTrust().type) {
      case CertificateTrustType::TRUSTED_ANCHOR:
        // If the leaf cert is trusted only as an anchor, treat it as having
        // unspecified trust. This may allow a successful path to be built to a
        // different root (or to the same cert if it's self-signed).
        if (cur_path_.Empty()) {
          if (delegate->IsDebugLogEnabled()) {
            delegate->DebugLog(
                "Leaf is a trust anchor, considering as UNSPECIFIED");
          }
          next_issuer_.trust.OverrideCertTrust(
              CertificateTrust::ForUnspecified());
        }
        break;
      case CertificateTrustType::TRUSTED_LEAF:
        // If a non-leaf cert is trusted only as a leaf, treat it as having
        // unspecified trust. This may allow a successful path to be built to a
        // trusted root.
        if (!cur_path_.Empty()) {
          if (delegate->IsDebugLogEnabled()) {
            delegate->DebugLog(
                "Issuer is a trust leaf, considering as UNSPECIFIED");
          }
          next_issuer_.trust.OverrideCertTrust(
              CertificateTrust::ForUnspecified());
        }
        break;
      case CertificateTrustType::DISTRUSTED:
      case CertificateTrustType::UNSPECIFIED:
      case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
        // No override necessary.
        break;
    }

    // Overrides for trusted leaf cert with require_leaf_selfsigned. If the leaf
    // isn't actually self-signed, treat it as unspecified.
    switch (next_issuer_.trust.CertTrust().type) {
      case CertificateTrustType::TRUSTED_LEAF:
      case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
        if (cur_path_.Empty() &&
            next_issuer_.trust.CertTrust().require_leaf_selfsigned &&
            !VerifyCertificateIsSelfSigned(*next_issuer_.cert,
                                           delegate->GetVerifyCache(),
                                           /*errors=*/nullptr)) {
          if (delegate->IsDebugLogEnabled()) {
            delegate->DebugLog(
                "Leaf is trusted with require_leaf_selfsigned but is "
                "not self-signed, considering as UNSPECIFIED");
          }
          next_issuer_.trust.OverrideCertTrust(
              CertificateTrust::ForUnspecified());
        }
        break;
      case CertificateTrustType::TRUSTED_ANCHOR:
      case CertificateTrustType::DISTRUSTED:
      case CertificateTrustType::UNSPECIFIED:
        // No override necessary.
        break;
    }

    switch (next_issuer_.trust.CertTrust().type) {
      // If the trust for this issuer is "known" (either because it is
      // distrusted, or because it is trusted) then stop building and return the
      // path.
      case CertificateTrustType::DISTRUSTED:
      case CertificateTrustType::TRUSTED_ANCHOR:
      case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
      case CertificateTrustType::TRUSTED_LEAF: {
        // If the issuer has a known trust level, can stop building the path.
        cur_path_.CopyPath(out_certs);
        out_certs->push_back(std::move(next_issuer_.cert));
        if (delegate->IsDebugLogEnabled()) {
          delegate->DebugLog("CertPathIter returning path:\n" +
                             PathDebugString(*out_certs));
        }
        *out_last_cert_trust = next_issuer_.trust;
        next_issuer_ = IssuerEntry();
        return true;
      }
      case CertificateTrustType::UNSPECIFIED: {
        // Skip this cert if it is already in the chain.
        if (cur_path_.IsPresent(next_issuer_.cert.get())) {
          cur_path_.back()->increment_skipped_issuer_count();
          if (delegate->IsDebugLogEnabled()) {
            delegate->DebugLog("CertPathIter skipping dupe cert: " +
                               CertDebugString(next_issuer_.cert.get()));
          }
          next_issuer_ = IssuerEntry();
          continue;
        }

        cur_path_.Append(std::make_unique<CertIssuersIter>(
            std::move(next_issuer_.cert), &cert_issuer_sources_, trust_store_));
        next_issuer_ = IssuerEntry();
        if (delegate->IsDebugLogEnabled()) {
          delegate->DebugLog("CertPathIter cur_path_ =\n" +
                             cur_path_.PathDebugString());
        }
        // Continue descending the tree.
        continue;
      }
    }
  }
}

CertPathBuilderResultPath::CertPathBuilderResultPath() = default;
CertPathBuilderResultPath::~CertPathBuilderResultPath() = default;

bool CertPathBuilderResultPath::IsValid() const {
  return GetTrustedCert() && !errors.ContainsHighSeverityErrors();
}

VerifyError CertPathBuilderResultPath::GetVerifyError() const {
  // Diagnostic string is always "everything" about the path.
  std::string diagnostic = errors.ToDebugString(certs);
  if (!errors.ContainsHighSeverityErrors()) {
    // TODO(bbe3): Having to check this after seems awkward:
    // crbug.com/boringssl/713
    if (GetTrustedCert()) {
      return VerifyError(VerifyError::StatusCode::PATH_VERIFIED, 0,
                         std::move(diagnostic));
    } else {
      return VerifyError(VerifyError::StatusCode::VERIFICATION_FAILURE, -1,
                         std::move(diagnostic));
    }
  }

  // Check for the presence of things that amount to Internal errors in the
  // verification code. We deliberately prioritize this to not hide it in
  // multiple error cases.
  if (errors.ContainsError(cert_errors::kInternalError) ||
      errors.ContainsError(cert_errors::kChainIsEmpty)) {
    return VerifyError(VerifyError::StatusCode::VERIFICATION_FAILURE, -1,
                       std::move(diagnostic));
  }

  // Similarly, for the deadline and limit cases, there will often be other
  // errors that we probably do not care about, since path building was
  // aborted. Surface these errors instead of having them hidden in the multiple
  // error case.
  //
  // Normally callers should check for these in the path builder result before
  // calling this on a single path, but this is here in case they do not and
  // these errors are actually present on this path.
  if (errors.ContainsError(cert_errors::kDeadlineExceeded)) {
    return VerifyError(VerifyError::StatusCode::PATH_DEADLINE_EXCEEDED, -1,
                       std::move(diagnostic));
  }
  if (errors.ContainsError(cert_errors::kIterationLimitExceeded)) {
    return VerifyError(VerifyError::StatusCode::PATH_ITERATION_COUNT_EXCEEDED,
                       -1, std::move(diagnostic));
  }
  if (errors.ContainsError(cert_errors::kDepthLimitExceeded)) {
    return VerifyError(VerifyError::StatusCode::PATH_DEPTH_LIMIT_REACHED, -1,
                       std::move(diagnostic));
  }

  // If the chain has multiple high severity errors, indicate that.
  ptrdiff_t depth = -1;
  std::optional<CertErrorId> single_error =
      errors.FindSingleHighSeverityError(depth);
  if (!single_error.has_value()) {
    return VerifyError(VerifyError::StatusCode::PATH_MULTIPLE_ERRORS, -1,
                       std::move(diagnostic));
  }

  // Otherwise it has a single error, map it appropriately at the
  // depth it first occurs.
  if (single_error.value() == cert_errors::kValidityFailedNotAfter) {
    return VerifyError(VerifyError::StatusCode::CERTIFICATE_EXPIRED, depth,
                       std::move(diagnostic));
  }
  if (single_error.value() == cert_errors::kValidityFailedNotBefore) {
    return VerifyError(VerifyError::StatusCode::CERTIFICATE_NOT_YET_VALID,
                       depth, std::move(diagnostic));
  }
  if (single_error.value() == cert_errors::kDistrustedByTrustStore ||
      single_error.value() == cert_errors::kCertIsNotTrustAnchor ||
      single_error.value() == cert_errors::kMaxPathLengthViolated ||
      single_error.value() == cert_errors::kSubjectDoesNotMatchIssuer ||
      single_error.value() == cert_errors::kNoIssuersFound) {
    return VerifyError(VerifyError::StatusCode::PATH_NOT_FOUND, depth,
                       std::move(diagnostic));
  }
  if (single_error.value() == cert_errors::kVerifySignedDataFailed) {
    return VerifyError(VerifyError::StatusCode::CERTIFICATE_INVALID_SIGNATURE,
                       depth, std::move(diagnostic));
  }
  if (single_error.value() == cert_errors::kUnacceptableSignatureAlgorithm) {
    return VerifyError(
        VerifyError::StatusCode::CERTIFICATE_UNSUPPORTED_SIGNATURE_ALGORITHM,
        depth, std::move(diagnostic));
  }
  if (single_error.value() == cert_errors::kUnacceptablePublicKey) {
    return VerifyError(VerifyError::StatusCode::CERTIFICATE_UNSUPPORTED_KEY,
                       depth, std::move(diagnostic));
  }
  if (single_error.value() == cert_errors::kEkuLacksServerAuth ||
      single_error.value() == cert_errors::kEkuLacksServerAuthButHasAnyEKU ||
      single_error.value() == cert_errors::kEkuLacksClientAuth ||
      single_error.value() == cert_errors::kEkuLacksClientAuthButHasAnyEKU ||
      single_error.value() == cert_errors::kEkuLacksClientAuthOrServerAuth) {
    return VerifyError(VerifyError::StatusCode::CERTIFICATE_NO_MATCHING_EKU,
                       depth, std::move(diagnostic));
  }
  if (single_error.value() == cert_errors::kCertificateRevoked) {
    return VerifyError(VerifyError::StatusCode::CERTIFICATE_REVOKED, depth,
                       std::move(diagnostic));
  }
  if (single_error.value() == cert_errors::kNoRevocationMechanism) {
    return VerifyError(
        VerifyError::StatusCode::CERTIFICATE_NO_REVOCATION_MECHANISM, depth,
        std::move(diagnostic));
  }
  if (single_error.value() == cert_errors::kUnableToCheckRevocation) {
    return VerifyError(
        VerifyError::StatusCode::CERTIFICATE_UNABLE_TO_CHECK_REVOCATION, depth,
        std::move(diagnostic));
  }
  // All other High severity errors map to CERTIFICATE_INVALID if associated
  // to a certificate, or VERIFICATION_FAILURE if not associated to a
  // certificate.
  return VerifyError((depth < 0) ? VerifyError::StatusCode::VERIFICATION_FAILURE
                                 : VerifyError::StatusCode::CERTIFICATE_INVALID,
                     depth, std::move(diagnostic));
}


CertPathBuilder::Result::Result() = default;
CertPathBuilder::Result::Result(Result &&) = default;
CertPathBuilder::Result::~Result() = default;
CertPathBuilder::Result &CertPathBuilder::Result::operator=(Result &&) =
    default;

bool CertPathBuilder::Result::HasValidPath() const {
  return GetBestValidPath() != nullptr;
}

bool CertPathBuilder::Result::AnyPathContainsError(CertErrorId error_id) const {
  for (const auto &path : paths) {
    if (path->errors.ContainsError(error_id)) {
      return true;
    }
  }

  return false;
}

const VerifyError CertPathBuilder::Result::GetBestPathVerifyError() const {
  if (HasValidPath()) {
    return GetBestValidPath()->GetVerifyError();
  }
  // We can only return one error. Returning the errors corresponding to the
  // limits if they appear on any path will make this error prominent even
  // if there are other paths with different or multiple errors.
  if (exceeded_iteration_limit) {
    return VerifyError(
        VerifyError::StatusCode::PATH_ITERATION_COUNT_EXCEEDED, -1,
        "Iteration count exceeded, could not find a trusted path.");
  }
  if (exceeded_deadline) {
    return VerifyError(VerifyError::StatusCode::PATH_DEADLINE_EXCEEDED, -1,
                       "Deadline exceeded. Could not find a trusted path.");
  }
  if (AnyPathContainsError(cert_errors::kDepthLimitExceeded)) {
    return VerifyError(VerifyError::StatusCode::PATH_DEPTH_LIMIT_REACHED, -1,
                       "Depth limit reached. Could not find a trusted path.");
  }

  // If there are no paths to report an error on, this probably indicates
  // something is wrong with this path builder result.
  if (paths.empty()) {
    return VerifyError(VerifyError::StatusCode::VERIFICATION_FAILURE, -1,
                       "No paths in path builder result.");
  }

  // If there are paths, report the VerifyError from the best path.
  CertPathBuilderResultPath *path = paths[best_result_index].get();
  return path->GetVerifyError();
}

const CertPathBuilderResultPath *CertPathBuilder::Result::GetBestValidPath()
    const {
  const CertPathBuilderResultPath *result_path = GetBestPathPossiblyInvalid();

  if (result_path && result_path->IsValid()) {
    return result_path;
  }

  return nullptr;
}

const CertPathBuilderResultPath *
CertPathBuilder::Result::GetBestPathPossiblyInvalid() const {
  BSSL_CHECK((paths.empty() && best_result_index == 0) ||
             best_result_index < paths.size());

  if (best_result_index >= paths.size()) {
    return nullptr;
  }

  return paths[best_result_index].get();
}

CertPathBuilder::CertPathBuilder(
    std::shared_ptr<const ParsedCertificate> cert, TrustStore *trust_store,
    CertPathBuilderDelegate *delegate, const der::GeneralizedTime &time,
    KeyPurpose 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)
    : cert_path_iter_(
          std::make_unique<CertPathIter>(std::move(cert), trust_store)),
      delegate_(delegate),
      time_(time),
      key_purpose_(key_purpose),
      initial_explicit_policy_(initial_explicit_policy),
      user_initial_policy_set_(user_initial_policy_set),
      initial_policy_mapping_inhibit_(initial_policy_mapping_inhibit),
      initial_any_policy_inhibit_(initial_any_policy_inhibit) {
  BSSL_CHECK(delegate);
  // The TrustStore also implements the CertIssuerSource interface.
  AddCertIssuerSource(trust_store);
}

CertPathBuilder::~CertPathBuilder() = default;

void CertPathBuilder::AddCertIssuerSource(
    CertIssuerSource *cert_issuer_source) {
  cert_path_iter_->AddCertIssuerSource(cert_issuer_source);
}

void CertPathBuilder::SetIterationLimit(uint32_t limit) {
  max_iteration_count_ = limit;
}

void CertPathBuilder::SetDepthLimit(uint32_t limit) {
  max_path_building_depth_ = limit;
}

void CertPathBuilder::SetValidPathLimit(size_t limit) {
  valid_path_limit_ = limit;
}

void CertPathBuilder::SetExploreAllPaths(bool explore_all_paths) {
  valid_path_limit_ = explore_all_paths ? 0 : 1;
}

CertPathBuilder::Result CertPathBuilder::Run() {
  uint32_t iteration_count = 0;

  while (true) {
    std::unique_ptr<CertPathBuilderResultPath> result_path =
        std::make_unique<CertPathBuilderResultPath>();

    if (!cert_path_iter_->GetNextPath(
            &result_path->certs, &result_path->trust_anchor,
            &result_path->errors, delegate_, &iteration_count,
            max_iteration_count_, max_path_building_depth_)) {
      result_path->last_cert_trust = result_path->trust_anchor.CertTrust();
      // There are no more paths to check or limits were exceeded.
      if (result_path->errors.ContainsError(
              cert_errors::kIterationLimitExceeded)) {
        out_result_.exceeded_iteration_limit = true;
      }
      if (result_path->errors.ContainsError(cert_errors::kDeadlineExceeded)) {
        out_result_.exceeded_deadline = true;
      }
      if (!result_path->certs.empty()) {
        // It shouldn't be possible to get here without adding one of the
        // errors above, but just in case, add an error if there isn't one
        // already.
        if (!result_path->errors.ContainsHighSeverityErrors()) {
          result_path->errors.GetOtherErrors()->AddError(
              cert_errors::kInternalError);
        }

        // Allow the delegate to do any processing or logging of the partial
        // path. (This is for symmetry for the other CheckPathAfterVerification
        // which also gets called on partial paths.)
        delegate_->CheckPathAfterVerification(*this, result_path.get());

        AddResultPath(std::move(result_path));
      }
      out_result_.iteration_count = iteration_count;
      return std::move(out_result_);
    }
    result_path->last_cert_trust = result_path->trust_anchor.CertTrust();

    if (result_path->last_cert_trust.HasUnspecifiedTrust()) {
      // Partial path, don't attempt to verify. Just double check that it is
      // marked with an error, and move on.
      if (!result_path->errors.ContainsHighSeverityErrors()) {
        result_path->errors.GetOtherErrors()->AddError(
            cert_errors::kInternalError);
      }
    } else {
      // Verify the entire certificate chain.
      VerifyCertificateChain(
          result_path->certs, result_path->trust_anchor, delegate_, time_,
          key_purpose_, initial_explicit_policy_, user_initial_policy_set_,
          initial_policy_mapping_inhibit_, initial_any_policy_inhibit_,
          &result_path->user_constrained_policy_set, &result_path->errors);
    }

    // Give the delegate a chance to add errors to the path.
    delegate_->CheckPathAfterVerification(*this, result_path.get());

    bool path_is_good = result_path->IsValid();

    AddResultPath(std::move(result_path));

    if (path_is_good) {
      valid_path_count_++;
      if (valid_path_limit_ > 0 && valid_path_count_ == valid_path_limit_) {
        out_result_.iteration_count = iteration_count;
        // Found enough paths, return immediately.
        return std::move(out_result_);
      }
    }
    // Path did not verify. Try more paths.
  }
}

void CertPathBuilder::AddResultPath(
    std::unique_ptr<CertPathBuilderResultPath> result_path) {
  // TODO(mattm): If there are no valid paths, set best_result_index based on
  // number or severity of errors. If there are multiple valid paths, could set
  // best_result_index based on prioritization (since due to AIA and such, the
  // actual order results were discovered may not match the ideal).
  if (!out_result_.HasValidPath()) {
    const CertPathBuilderResultPath *old_best_path =
        out_result_.GetBestPathPossiblyInvalid();
    // If `result_path` is a valid path or if the previous best result did not
    // end in a trust anchor but the `result_path` does, then update the best
    // result to the new result.
    if (result_path->IsValid() ||
        (!result_path->last_cert_trust.HasUnspecifiedTrust() && old_best_path &&
         old_best_path->last_cert_trust.HasUnspecifiedTrust())) {
      out_result_.best_result_index = out_result_.paths.size();
    }
  }
  if (result_path->certs.size() > out_result_.max_depth_seen) {
    out_result_.max_depth_seen = result_path->certs.size();
  }
  out_result_.paths.push_back(std::move(result_path));
}

BSSL_NAMESPACE_END
