• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "path_builder.h"
6 
7 #include <cassert>
8 #include <memory>
9 #include <set>
10 #include <unordered_set>
11 
12 #include "fillins/log.h"
13 #include "fillins/net_errors.h"
14 
15 #include "cert_issuer_source.h"
16 #include "certificate_policies.h"
17 #include "common_cert_errors.h"
18 #include "parse_certificate.h"
19 #include "parse_name.h"  // For CertDebugString.
20 #include "string_util.h"
21 #include "trust_store.h"
22 #include "verify_certificate_chain.h"
23 #include "verify_name_match.h"
24 #include "parser.h"
25 #include "tag.h"
26 #include <openssl/base.h>
27 #include <openssl/sha.h>
28 
29 namespace bssl {
30 
31 namespace {
32 
33 using CertIssuerSources = std::vector<CertIssuerSource*>;
34 
35 // Returns a hex-encoded sha256 of the DER-encoding of |cert|.
FingerPrintParsedCertificate(const bssl::ParsedCertificate * cert)36 std::string FingerPrintParsedCertificate(const bssl::ParsedCertificate* cert) {
37   uint8_t digest[SHA256_DIGEST_LENGTH];
38   SHA256(cert->der_cert().UnsafeData(), cert->der_cert().Length(), digest);
39   return bssl::string_util::HexEncode(digest, sizeof(digest));
40 }
41 
42 // TODO(mattm): decide how much debug logging to keep.
CertDebugString(const ParsedCertificate * cert)43 std::string CertDebugString(const ParsedCertificate* cert) {
44   RDNSequence subject;
45   std::string subject_str;
46   if (!ParseName(cert->tbs().subject_tlv, &subject) ||
47       !ConvertToRFC2253(subject, &subject_str))
48     subject_str = "???";
49 
50   return FingerPrintParsedCertificate(cert) + " " + subject_str;
51 }
52 
PathDebugString(const ParsedCertificateList & certs)53 std::string PathDebugString(const ParsedCertificateList& certs) {
54   std::string s;
55   for (const auto& cert : certs) {
56     if (!s.empty())
57       s += "\n";
58     s += " " + CertDebugString(cert.get());
59   }
60   return s;
61 }
62 
63 // This structure describes a certificate and its trust level. Note that |cert|
64 // may be null to indicate an "empty" entry.
65 struct IssuerEntry {
66   std::shared_ptr<const ParsedCertificate> cert;
67   CertificateTrust trust;
68   int trust_and_key_id_match_ordering;
69 };
70 
71 enum KeyIdentifierMatch {
72   // |target| has a keyIdentifier and it matches |issuer|'s
73   // subjectKeyIdentifier.
74   kMatch = 0,
75   // |target| does not have authorityKeyIdentifier or |issuer| does not have
76   // subjectKeyIdentifier.
77   kNoData = 1,
78   // |target|'s authorityKeyIdentifier does not match |issuer|.
79   kMismatch = 2,
80 };
81 
82 // Returns an integer that represents the relative ordering of |issuer| for
83 // prioritizing certificates in path building based on |issuer|'s
84 // subjectKeyIdentifier and |target|'s authorityKeyIdentifier. Lower return
85 // values indicate higer priority.
CalculateKeyIdentifierMatch(const ParsedCertificate * target,const ParsedCertificate * issuer)86 KeyIdentifierMatch CalculateKeyIdentifierMatch(
87     const ParsedCertificate* target,
88     const ParsedCertificate* issuer) {
89   if (!target->authority_key_identifier())
90     return kNoData;
91 
92   // TODO(crbug.com/635205): If issuer does not have a subjectKeyIdentifier,
93   // could try synthesizing one using the standard SHA-1 method. Ideally in a
94   // way where any issuers that do have a matching subjectKeyIdentifier could
95   // be tried first before doing the extra work.
96   if (target->authority_key_identifier()->key_identifier &&
97       issuer->subject_key_identifier()) {
98     if (target->authority_key_identifier()->key_identifier !=
99         issuer->subject_key_identifier().value()) {
100       return kMismatch;
101     }
102     return kMatch;
103   }
104 
105   return kNoData;
106 }
107 
108 // Returns an integer that represents the relative ordering of |issuer| based
109 // on |issuer_trust| and authorityKeyIdentifier matching for prioritizing
110 // certificates in path building. Lower return values indicate higer priority.
TrustAndKeyIdentifierMatchToOrder(const ParsedCertificate * target,const ParsedCertificate * issuer,const CertificateTrust & issuer_trust)111 int TrustAndKeyIdentifierMatchToOrder(const ParsedCertificate* target,
112                                       const ParsedCertificate* issuer,
113                                       const CertificateTrust& issuer_trust) {
114   enum {
115     kTrustedAndKeyIdMatch = 0,
116     kTrustedAndKeyIdNoData = 1,
117     kKeyIdMatch = 2,
118     kKeyIdNoData = 3,
119     kTrustedAndKeyIdMismatch = 4,
120     kKeyIdMismatch = 5,
121     kDistrustedAndKeyIdMatch = 6,
122     kDistrustedAndKeyIdNoData = 7,
123     kDistrustedAndKeyIdMismatch = 8,
124   };
125 
126   KeyIdentifierMatch key_id_match = CalculateKeyIdentifierMatch(target, issuer);
127   switch (issuer_trust.type) {
128     case CertificateTrustType::TRUSTED_ANCHOR:
129     case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
130       switch (key_id_match) {
131         case kMatch:
132           return kTrustedAndKeyIdMatch;
133         case kNoData:
134           return kTrustedAndKeyIdNoData;
135         case kMismatch:
136           return kTrustedAndKeyIdMismatch;
137       }
138       break;
139     case CertificateTrustType::UNSPECIFIED:
140     case CertificateTrustType::TRUSTED_LEAF:
141       switch (key_id_match) {
142         case kMatch:
143           return kKeyIdMatch;
144         case kNoData:
145           return kKeyIdNoData;
146         case kMismatch:
147           return kKeyIdMismatch;
148       }
149       break;
150     case CertificateTrustType::DISTRUSTED:
151       switch (key_id_match) {
152         case kMatch:
153           return kDistrustedAndKeyIdMatch;
154         case kNoData:
155           return kDistrustedAndKeyIdNoData;
156         case kMismatch:
157           return kDistrustedAndKeyIdMismatch;
158       }
159       break;
160   }
161   assert(0);  // NOTREACHED
162   return -1;
163 }
164 
165 // CertIssuersIter iterates through the intermediates from |cert_issuer_sources|
166 // which may be issuers of |cert|.
167 class CertIssuersIter {
168  public:
169   // Constructs the CertIssuersIter. |*cert_issuer_sources|, and
170   // |*trust_store| must be valid for the lifetime of the CertIssuersIter.
171   CertIssuersIter(std::shared_ptr<const ParsedCertificate> cert,
172                   CertIssuerSources* cert_issuer_sources,
173                   TrustStore* trust_store);
174 
175   CertIssuersIter(const CertIssuersIter&) = delete;
176   CertIssuersIter& operator=(const CertIssuersIter&) = delete;
177 
178   // Gets the next candidate issuer, or clears |*out| when all issuers have been
179   // exhausted.
180   void GetNextIssuer(IssuerEntry* out);
181 
182   // Returns true if candidate issuers were found for |cert_|.
had_non_skipped_issuers() const183   bool had_non_skipped_issuers() const {
184     return issuers_.size() > skipped_issuer_count_;
185   }
186 
increment_skipped_issuer_count()187   void increment_skipped_issuer_count() { skipped_issuer_count_++; }
188 
189   // Returns the |cert| for which issuers are being retrieved.
cert() const190   const ParsedCertificate* cert() const { return cert_.get(); }
reference_cert() const191   std::shared_ptr<const ParsedCertificate> reference_cert() const {
192     return cert_;
193   }
194 
195  private:
196   void AddIssuers(ParsedCertificateList issuers);
197   void DoAsyncIssuerQuery();
198 
199   // Returns true if |issuers_| contains unconsumed certificates.
HasCurrentIssuer() const200   bool HasCurrentIssuer() const { return cur_issuer_ < issuers_.size(); }
201 
202   // Sorts the remaining entries in |issuers_| in the preferred order to
203   // explore. Does not change the ordering for indices before cur_issuer_.
204   void SortRemainingIssuers();
205 
206   std::shared_ptr<const ParsedCertificate> cert_;
207   CertIssuerSources* cert_issuer_sources_;
208   TrustStore* trust_store_;
209 
210   // The list of issuers for |cert_|. This is added to incrementally (first
211   // synchronous results, then possibly multiple times as asynchronous results
212   // arrive.) The issuers may be re-sorted each time new issuers are added, but
213   // only the results from |cur_| onwards should be sorted, since the earlier
214   // results were already returned.
215   // Elements should not be removed from |issuers_| once added, since
216   // |present_issuers_| will point to data owned by the certs.
217   std::vector<IssuerEntry> issuers_;
218   // The index of the next cert in |issuers_| to return.
219   size_t cur_issuer_ = 0;
220   // The number of issuers that were skipped due to the loop checker.
221   size_t skipped_issuer_count_ = 0;
222   // Set to true whenever new issuers are appended at the end, to indicate the
223   // ordering needs to be checked.
224   bool issuers_needs_sort_ = false;
225 
226   // Set of DER-encoded values for the certs in |issuers_|. Used to prevent
227   // duplicates. This is based on the full DER of the cert to allow different
228   // versions of the same certificate to be tried in different candidate paths.
229   // This points to data owned by |issuers_|.
230   std::unordered_set<std::string_view> present_issuers_;
231 
232   // Tracks which requests have been made yet.
233   bool did_initial_query_ = false;
234   bool did_async_issuer_query_ = false;
235   // Index into pending_async_requests_ that is the next one to process.
236   size_t cur_async_request_ = 0;
237   // Owns the Request objects for any asynchronous requests so that they will be
238   // cancelled if CertIssuersIter is destroyed.
239   std::vector<std::unique_ptr<CertIssuerSource::Request>>
240       pending_async_requests_;
241 };
242 
CertIssuersIter(std::shared_ptr<const ParsedCertificate> in_cert,CertIssuerSources * cert_issuer_sources,TrustStore * trust_store)243 CertIssuersIter::CertIssuersIter(
244     std::shared_ptr<const ParsedCertificate> in_cert,
245     CertIssuerSources* cert_issuer_sources,
246     TrustStore* trust_store)
247     : cert_(std::move(in_cert)),
248       cert_issuer_sources_(cert_issuer_sources),
249       trust_store_(trust_store) {
250   DVLOG(2) << "CertIssuersIter created for " << CertDebugString(cert());
251 }
252 
GetNextIssuer(IssuerEntry * out)253 void CertIssuersIter::GetNextIssuer(IssuerEntry* out) {
254   if (!did_initial_query_) {
255     did_initial_query_ = true;
256     for (auto* cert_issuer_source : *cert_issuer_sources_) {
257       ParsedCertificateList new_issuers;
258       cert_issuer_source->SyncGetIssuersOf(cert(), &new_issuers);
259       AddIssuers(std::move(new_issuers));
260     }
261   }
262 
263   // If there aren't any issuers, block until async results are ready.
264   if (!HasCurrentIssuer()) {
265     if (!did_async_issuer_query_) {
266       // Now issue request(s) for async ones (AIA, etc).
267       DoAsyncIssuerQuery();
268     }
269 
270     // TODO(eroman): Rather than blocking on the async requests in FIFO order,
271     // consume in the order they become ready.
272     while (!HasCurrentIssuer() &&
273            cur_async_request_ < pending_async_requests_.size()) {
274       ParsedCertificateList new_issuers;
275       pending_async_requests_[cur_async_request_]->GetNext(&new_issuers);
276       if (new_issuers.empty()) {
277         // Request is exhausted, no more results pending from that
278         // CertIssuerSource.
279         pending_async_requests_[cur_async_request_++].reset();
280       } else {
281         AddIssuers(std::move(new_issuers));
282       }
283     }
284   }
285 
286   if (HasCurrentIssuer()) {
287     SortRemainingIssuers();
288 
289     DVLOG(2) << "CertIssuersIter returning issuer " << cur_issuer_ << " of "
290              << issuers_.size() << " for " << CertDebugString(cert());
291     // Still have issuers that haven't been returned yet, return the highest
292     // priority one (head of remaining list). A reference to the returned issuer
293     // is retained, since |present_issuers_| points to data owned by it.
294     *out = issuers_[cur_issuer_++];
295     return;
296   }
297 
298   DVLOG(2) << "CertIssuersIter reached the end of all available issuers for "
299            << CertDebugString(cert());
300   // Reached the end of all available issuers.
301   *out = IssuerEntry();
302 }
303 
AddIssuers(ParsedCertificateList new_issuers)304 void CertIssuersIter::AddIssuers(ParsedCertificateList new_issuers) {
305   for (std::shared_ptr<const ParsedCertificate>& issuer : new_issuers) {
306     if (present_issuers_.find(issuer->der_cert().AsStringView()) !=
307         present_issuers_.end())
308       continue;
309     present_issuers_.insert(issuer->der_cert().AsStringView());
310 
311     // Look up the trust for this issuer.
312     IssuerEntry entry;
313     entry.cert = std::move(issuer);
314     entry.trust = trust_store_->GetTrust(entry.cert.get());
315     entry.trust_and_key_id_match_ordering = TrustAndKeyIdentifierMatchToOrder(
316         cert(), entry.cert.get(), entry.trust);
317 
318     issuers_.push_back(std::move(entry));
319     issuers_needs_sort_ = true;
320   }
321 }
322 
DoAsyncIssuerQuery()323 void CertIssuersIter::DoAsyncIssuerQuery() {
324   BSSL_CHECK(!did_async_issuer_query_);
325   did_async_issuer_query_ = true;
326   cur_async_request_ = 0;
327   for (auto* cert_issuer_source : *cert_issuer_sources_) {
328     std::unique_ptr<CertIssuerSource::Request> request;
329     cert_issuer_source->AsyncGetIssuersOf(cert(), &request);
330     if (request) {
331       DVLOG(1) << "AsyncGetIssuersOf pending for " << CertDebugString(cert());
332       pending_async_requests_.push_back(std::move(request));
333     }
334   }
335 }
336 
SortRemainingIssuers()337 void CertIssuersIter::SortRemainingIssuers() {
338   if (!issuers_needs_sort_)
339     return;
340 
341   std::stable_sort(
342       issuers_.begin() + cur_issuer_, issuers_.end(),
343       [](const IssuerEntry& issuer1, const IssuerEntry& issuer2) {
344         // TODO(crbug.com/635205): Add other prioritization hints. (See big list
345         // of possible sorting hints in RFC 4158.)
346         const bool issuer1_self_issued = issuer1.cert->normalized_subject() ==
347                                          issuer1.cert->normalized_issuer();
348         const bool issuer2_self_issued = issuer2.cert->normalized_subject() ==
349                                          issuer2.cert->normalized_issuer();
350         return std::tie(issuer1.trust_and_key_id_match_ordering,
351                         issuer2_self_issued,
352                         // Newer(larger) notBefore & notAfter dates are
353                         // preferred, hence |issuer2| is on the LHS of
354                         // the comparison and |issuer1| on the RHS.
355                         issuer2.cert->tbs().validity_not_before,
356                         issuer2.cert->tbs().validity_not_after) <
357                std::tie(issuer2.trust_and_key_id_match_ordering,
358                         issuer1_self_issued,
359                         issuer1.cert->tbs().validity_not_before,
360                         issuer1.cert->tbs().validity_not_after);
361       });
362 
363   issuers_needs_sort_ = false;
364 }
365 
366 // CertIssuerIterPath tracks which certs are present in the path and prevents
367 // paths from being built which repeat any certs (including different versions
368 // of the same cert, based on Subject+SubjectAltName+SPKI).
369 // (RFC 5280 forbids duplicate certificates per section 6.1, and RFC 4158
370 // further recommends disallowing the same Subject+SubjectAltName+SPKI in
371 // section 2.4.2.)
372 class CertIssuerIterPath {
373  public:
374   // Returns true if |cert| is already present in the path.
IsPresent(const ParsedCertificate * cert) const375   bool IsPresent(const ParsedCertificate* cert) const {
376     return present_certs_.find(GetKey(cert)) != present_certs_.end();
377   }
378 
379   // Appends |cert_issuers_iter| to the path. The cert referred to by
380   // |cert_issuers_iter| must not be present in the path already.
Append(std::unique_ptr<CertIssuersIter> cert_issuers_iter)381   void Append(std::unique_ptr<CertIssuersIter> cert_issuers_iter) {
382     bool added =
383         present_certs_.insert(GetKey(cert_issuers_iter->cert())).second;
384     BSSL_CHECK(added);
385     cur_path_.push_back(std::move(cert_issuers_iter));
386   }
387 
388   // Pops the last CertIssuersIter off the path.
Pop()389   void Pop() {
390     size_t num_erased = present_certs_.erase(GetKey(cur_path_.back()->cert()));
391     BSSL_CHECK(num_erased == 1U);
392     cur_path_.pop_back();
393   }
394 
395   // Copies the ParsedCertificate elements of the current path to |*out_path|.
CopyPath(ParsedCertificateList * out_path)396   void CopyPath(ParsedCertificateList* out_path) {
397     out_path->clear();
398     for (const auto& node : cur_path_)
399       out_path->push_back(node->reference_cert());
400   }
401 
402   // Returns true if the path is empty.
Empty() const403   bool Empty() const { return cur_path_.empty(); }
404 
405   // Returns the last CertIssuersIter in the path.
back()406   CertIssuersIter* back() { return cur_path_.back().get(); }
407 
408   // Returns the length of the path.
Length() const409   size_t Length() const { return cur_path_.size(); }
410 
PathDebugString()411   std::string PathDebugString() {
412     std::string s;
413     for (const auto& node : cur_path_) {
414       if (!s.empty())
415         s += "\n";
416       s += " " + CertDebugString(node->cert());
417     }
418     return s;
419   }
420 
421  private:
422   using Key = std::tuple<std::string_view, std::string_view, std::string_view>;
423 
GetKey(const ParsedCertificate * cert)424   static Key GetKey(const ParsedCertificate* cert) {
425     // TODO(mattm): ideally this would use a normalized version of
426     // SubjectAltName, but it's not that important just for LoopChecker.
427     //
428     // Note that subject_alt_names_extension().value will be empty if the cert
429     // had no SubjectAltName extension, so there is no need for a condition on
430     // has_subject_alt_names().
431     return Key(cert->normalized_subject().AsStringView(),
432                cert->subject_alt_names_extension().value.AsStringView(),
433                cert->tbs().spki_tlv.AsStringView());
434   }
435 
436   std::vector<std::unique_ptr<CertIssuersIter>> cur_path_;
437 
438   // This refers to data owned by |cur_path_|.
439   // TODO(mattm): use unordered_set. Requires making a hash function for Key.
440   std::set<Key> present_certs_;
441 };
442 
443 }  // namespace
444 
GetTrustedCert() const445 const ParsedCertificate* CertPathBuilderResultPath::GetTrustedCert() const {
446   if (certs.empty())
447     return nullptr;
448 
449   switch (last_cert_trust.type) {
450     case CertificateTrustType::TRUSTED_ANCHOR:
451     case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
452     case CertificateTrustType::TRUSTED_LEAF:
453       return certs.back().get();
454     case CertificateTrustType::UNSPECIFIED:
455     case CertificateTrustType::DISTRUSTED:
456       return nullptr;
457   }
458 
459   assert(0);  // NOTREACHED
460   return nullptr;
461 }
462 
463 // CertPathIter generates possible paths from |cert| to a trust anchor in
464 // |trust_store|, using intermediates from the |cert_issuer_source| objects if
465 // necessary.
466 class CertPathIter {
467  public:
468   CertPathIter(std::shared_ptr<const ParsedCertificate> cert,
469                TrustStore* trust_store);
470 
471   CertPathIter(const CertPathIter&) = delete;
472   CertPathIter& operator=(const CertPathIter&) = delete;
473 
474   // Adds a CertIssuerSource to provide intermediates for use in path building.
475   // The |*cert_issuer_source| must remain valid for the lifetime of the
476   // CertPathIter.
477   void AddCertIssuerSource(CertIssuerSource* cert_issuer_source);
478 
479   // Gets the next candidate path, and fills it into |out_certs| and
480   // |out_last_cert_trust|. Note that the returned path is unverified and must
481   // still be run through a chain validator. If a candidate path could not be
482   // built, a partial path will be returned and |out_errors| will have an error
483   // added.
484   // If the return value is true, GetNextPath may be called again to backtrack
485   // and continue path building. Once all paths have been exhausted returns
486   // false. If deadline or iteration limit is exceeded, sets |out_certs| to the
487   // current path being explored and returns false.
488   bool GetNextPath(ParsedCertificateList* out_certs,
489                    CertificateTrust* out_last_cert_trust,
490                    CertPathErrors* out_errors,
491                    CertPathBuilderDelegate* delegate,
492                    uint32_t* iteration_count,
493                    const uint32_t max_iteration_count,
494                    const uint32_t max_path_building_depth);
495 
496  private:
497   // Stores the next candidate issuer, until it is used during the
498   // STATE_GET_NEXT_ISSUER_COMPLETE step.
499   IssuerEntry next_issuer_;
500   // The current path being explored, made up of CertIssuerIters. Each node
501   // keeps track of the state of searching for issuers of that cert, so that
502   // when backtracking it can resume the search where it left off.
503   CertIssuerIterPath cur_path_;
504   // The CertIssuerSources for retrieving candidate issuers.
505   CertIssuerSources cert_issuer_sources_;
506   // The TrustStore for checking if a path ends in a trust anchor.
507   TrustStore* trust_store_;
508 };
509 
CertPathIter(std::shared_ptr<const ParsedCertificate> cert,TrustStore * trust_store)510 CertPathIter::CertPathIter(std::shared_ptr<const ParsedCertificate> cert,
511                            TrustStore* trust_store)
512     : trust_store_(trust_store) {
513   // Initialize |next_issuer_| to the target certificate.
514   next_issuer_.cert = std::move(cert);
515   next_issuer_.trust = trust_store_->GetTrust(next_issuer_.cert.get());
516 }
517 
AddCertIssuerSource(CertIssuerSource * cert_issuer_source)518 void CertPathIter::AddCertIssuerSource(CertIssuerSource* cert_issuer_source) {
519   cert_issuer_sources_.push_back(cert_issuer_source);
520 }
521 
GetNextPath(ParsedCertificateList * out_certs,CertificateTrust * 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)522 bool CertPathIter::GetNextPath(ParsedCertificateList* out_certs,
523                                CertificateTrust* out_last_cert_trust,
524                                CertPathErrors* out_errors,
525                                CertPathBuilderDelegate* delegate,
526                                uint32_t* iteration_count,
527                                const uint32_t max_iteration_count,
528                                const uint32_t max_path_building_depth) {
529   out_certs->clear();
530   *out_last_cert_trust = CertificateTrust::ForUnspecified();
531 
532   while (true) {
533     if (delegate->IsDeadlineExpired()) {
534       if (cur_path_.Empty()) {
535         // If the deadline is already expired before the first call to
536         // GetNextPath, cur_path_ will be empty. Return the leaf cert in that
537         // case.
538         if (next_issuer_.cert)
539           out_certs->push_back(next_issuer_.cert);
540       } else {
541         cur_path_.CopyPath(out_certs);
542       }
543       out_errors->GetOtherErrors()->AddError(cert_errors::kDeadlineExceeded);
544       return false;
545     }
546 
547     // We are not done yet, so if the current path is at the depth limit then
548     // we must backtrack to find an acceptable solution.
549     if (max_path_building_depth > 0 &&
550         cur_path_.Length() >= max_path_building_depth) {
551       cur_path_.CopyPath(out_certs);
552       out_errors->GetOtherErrors()->AddError(cert_errors::kDepthLimitExceeded);
553       DVLOG(1) << "CertPathIter reached depth limit. Returning partial path "
554                   "and backtracking:\n"
555                << PathDebugString(*out_certs);
556       cur_path_.Pop();
557       return true;
558     }
559 
560     if (!next_issuer_.cert) {
561       if (cur_path_.Empty()) {
562         DVLOG(1) << "CertPathIter exhausted all paths...";
563         return false;
564       }
565 
566       (*iteration_count)++;
567       if (max_iteration_count > 0 && *iteration_count > max_iteration_count) {
568         cur_path_.CopyPath(out_certs);
569         out_errors->GetOtherErrors()->AddError(
570             cert_errors::kIterationLimitExceeded);
571         return false;
572       }
573 
574       cur_path_.back()->GetNextIssuer(&next_issuer_);
575       if (!next_issuer_.cert) {
576         if (!cur_path_.back()->had_non_skipped_issuers()) {
577           // If the end of a path was reached without finding an anchor, return
578           // the partial path before backtracking.
579           cur_path_.CopyPath(out_certs);
580           out_errors->GetErrorsForCert(out_certs->size() - 1)
581               ->AddError(cert_errors::kNoIssuersFound);
582           DVLOG(1) << "CertPathIter returning partial path and backtracking:\n"
583                    << PathDebugString(*out_certs);
584           cur_path_.Pop();
585           return true;
586         } else {
587           // No more issuers for current chain, go back up and see if there are
588           // any more for the previous cert.
589           DVLOG(1) << "CertPathIter backtracking...";
590           cur_path_.Pop();
591           continue;
592         }
593       }
594     }
595 
596     // Overrides for cert with trust appearing in the wrong place for the type
597     // of trust (trusted leaf in non-leaf position, or trust anchor in leaf
598     // position.)
599     switch (next_issuer_.trust.type) {
600       case CertificateTrustType::TRUSTED_ANCHOR:
601         // If the leaf cert is trusted only as an anchor, treat it as having
602         // unspecified trust. This may allow a successful path to be built to a
603         // different root (or to the same cert if it's self-signed).
604         if (cur_path_.Empty()) {
605           DVLOG(1) << "Leaf is a trust anchor, considering as UNSPECIFIED";
606           next_issuer_.trust = CertificateTrust::ForUnspecified();
607         }
608         break;
609       case CertificateTrustType::TRUSTED_LEAF:
610         // If a non-leaf cert is trusted only as a leaf, treat it as having
611         // unspecified trust. This may allow a successful path to be built to a
612         // trusted root.
613         if (!cur_path_.Empty()) {
614           DVLOG(1) << "Issuer is a trust leaf, considering as UNSPECIFIED";
615           next_issuer_.trust = CertificateTrust::ForUnspecified();
616         }
617         break;
618       case CertificateTrustType::DISTRUSTED:
619       case CertificateTrustType::UNSPECIFIED:
620       case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
621         // No override necessary.
622         break;
623     }
624 
625     // Overrides for trusted leaf cert with require_leaf_selfsigned. If the leaf
626     // isn't actually self-signed, treat it as unspecified.
627     switch (next_issuer_.trust.type) {
628       case CertificateTrustType::TRUSTED_LEAF:
629       case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
630         if (cur_path_.Empty() && next_issuer_.trust.require_leaf_selfsigned &&
631             !VerifyCertificateIsSelfSigned(*next_issuer_.cert,
632                                            delegate->GetVerifyCache(),
633                                            /*errors=*/nullptr)) {
634           DVLOG(1) << "Leaf is trusted with require_leaf_selfsigned but is "
635                       "not self-signed, considering as UNSPECIFIED";
636           next_issuer_.trust = CertificateTrust::ForUnspecified();
637         }
638         break;
639       case CertificateTrustType::TRUSTED_ANCHOR:
640       case CertificateTrustType::DISTRUSTED:
641       case CertificateTrustType::UNSPECIFIED:
642         // No override necessary.
643         break;
644     }
645 
646     switch (next_issuer_.trust.type) {
647       // If the trust for this issuer is "known" (either because it is
648       // distrusted, or because it is trusted) then stop building and return the
649       // path.
650       case CertificateTrustType::DISTRUSTED:
651       case CertificateTrustType::TRUSTED_ANCHOR:
652       case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
653       case CertificateTrustType::TRUSTED_LEAF: {
654         // If the issuer has a known trust level, can stop building the path.
655         DVLOG(2) << "CertPathIter got anchor: "
656                  << CertDebugString(next_issuer_.cert.get());
657         cur_path_.CopyPath(out_certs);
658         out_certs->push_back(std::move(next_issuer_.cert));
659         DVLOG(1) << "CertPathIter returning path:\n"
660                  << PathDebugString(*out_certs);
661         *out_last_cert_trust = next_issuer_.trust;
662         next_issuer_ = IssuerEntry();
663         return true;
664       }
665       case CertificateTrustType::UNSPECIFIED: {
666         // Skip this cert if it is already in the chain.
667         if (cur_path_.IsPresent(next_issuer_.cert.get())) {
668           cur_path_.back()->increment_skipped_issuer_count();
669           DVLOG(1) << "CertPathIter skipping dupe cert: "
670                    << CertDebugString(next_issuer_.cert.get());
671           next_issuer_ = IssuerEntry();
672           continue;
673         }
674 
675         cur_path_.Append(std::make_unique<CertIssuersIter>(
676             std::move(next_issuer_.cert), &cert_issuer_sources_, trust_store_));
677         next_issuer_ = IssuerEntry();
678         DVLOG(1) << "CertPathIter cur_path_ =\n" << cur_path_.PathDebugString();
679         // Continue descending the tree.
680         continue;
681       }
682     }
683   }
684 }
685 
686 CertPathBuilderResultPath::CertPathBuilderResultPath() = default;
687 CertPathBuilderResultPath::~CertPathBuilderResultPath() = default;
688 
IsValid() const689 bool CertPathBuilderResultPath::IsValid() const {
690   return GetTrustedCert() && !errors.ContainsHighSeverityErrors();
691 }
692 
693 CertPathBuilder::Result::Result() = default;
694 CertPathBuilder::Result::Result(Result&&) = default;
695 CertPathBuilder::Result::~Result() = default;
696 CertPathBuilder::Result& CertPathBuilder::Result::operator=(Result&&) = default;
697 
HasValidPath() const698 bool CertPathBuilder::Result::HasValidPath() const {
699   return GetBestValidPath() != nullptr;
700 }
701 
AnyPathContainsError(CertErrorId error_id) const702 bool CertPathBuilder::Result::AnyPathContainsError(CertErrorId error_id) const {
703   for (const auto& path : paths) {
704     if (path->errors.ContainsError(error_id))
705       return true;
706   }
707 
708   return false;
709 }
710 
GetBestValidPath() const711 const CertPathBuilderResultPath* CertPathBuilder::Result::GetBestValidPath()
712     const {
713   const CertPathBuilderResultPath* result_path = GetBestPathPossiblyInvalid();
714 
715   if (result_path && result_path->IsValid())
716     return result_path;
717 
718   return nullptr;
719 }
720 
721 const CertPathBuilderResultPath*
GetBestPathPossiblyInvalid() const722 CertPathBuilder::Result::GetBestPathPossiblyInvalid() const {
723   BSSL_CHECK((paths.empty() && best_result_index == 0) ||
724              best_result_index < paths.size());
725 
726   if (best_result_index >= paths.size())
727     return nullptr;
728 
729   return paths[best_result_index].get();
730 }
731 
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)732 CertPathBuilder::CertPathBuilder(
733     std::shared_ptr<const ParsedCertificate> cert,
734     TrustStore* trust_store,
735     CertPathBuilderDelegate* delegate,
736     const der::GeneralizedTime& time,
737     KeyPurpose key_purpose,
738     InitialExplicitPolicy initial_explicit_policy,
739     const std::set<der::Input>& user_initial_policy_set,
740     InitialPolicyMappingInhibit initial_policy_mapping_inhibit,
741     InitialAnyPolicyInhibit initial_any_policy_inhibit)
742     : cert_path_iter_(
743           std::make_unique<CertPathIter>(std::move(cert), trust_store)),
744       delegate_(delegate),
745       time_(time),
746       key_purpose_(key_purpose),
747       initial_explicit_policy_(initial_explicit_policy),
748       user_initial_policy_set_(user_initial_policy_set),
749       initial_policy_mapping_inhibit_(initial_policy_mapping_inhibit),
750       initial_any_policy_inhibit_(initial_any_policy_inhibit) {
751   BSSL_CHECK(delegate);
752   // The TrustStore also implements the CertIssuerSource interface.
753   AddCertIssuerSource(trust_store);
754 }
755 
756 CertPathBuilder::~CertPathBuilder() = default;
757 
AddCertIssuerSource(CertIssuerSource * cert_issuer_source)758 void CertPathBuilder::AddCertIssuerSource(
759     CertIssuerSource* cert_issuer_source) {
760   cert_path_iter_->AddCertIssuerSource(cert_issuer_source);
761 }
762 
SetIterationLimit(uint32_t limit)763 void CertPathBuilder::SetIterationLimit(uint32_t limit) {
764   max_iteration_count_ = limit;
765 }
766 
SetDepthLimit(uint32_t limit)767 void CertPathBuilder::SetDepthLimit(uint32_t limit) {
768   max_path_building_depth_ = limit;
769 }
770 
SetExploreAllPaths(bool explore_all_paths)771 void CertPathBuilder::SetExploreAllPaths(bool explore_all_paths) {
772   explore_all_paths_ = explore_all_paths;
773 }
774 
Run()775 CertPathBuilder::Result CertPathBuilder::Run() {
776   uint32_t iteration_count = 0;
777 
778   while (true) {
779     std::unique_ptr<CertPathBuilderResultPath> result_path =
780         std::make_unique<CertPathBuilderResultPath>();
781 
782     if (!cert_path_iter_->GetNextPath(
783             &result_path->certs, &result_path->last_cert_trust,
784             &result_path->errors, delegate_, &iteration_count,
785             max_iteration_count_, max_path_building_depth_)) {
786       // There are no more paths to check or limits were exceeded.
787       if (result_path->errors.ContainsError(
788               cert_errors::kIterationLimitExceeded)) {
789         out_result_.exceeded_iteration_limit = true;
790       }
791       if (result_path->errors.ContainsError(cert_errors::kDeadlineExceeded)) {
792         out_result_.exceeded_deadline = true;
793       }
794       if (!result_path->certs.empty()) {
795         // It shouldn't be possible to get here without adding one of the
796         // errors above, but just in case, add an error if there isn't one
797         // already.
798         if (!result_path->errors.ContainsHighSeverityErrors()) {
799           result_path->errors.GetOtherErrors()->AddError(
800               cert_errors::kInternalError);
801         }
802         AddResultPath(std::move(result_path));
803       }
804       out_result_.iteration_count = iteration_count;
805       return std::move(out_result_);
806     }
807 
808     if (result_path->last_cert_trust.HasUnspecifiedTrust()) {
809       // Partial path, don't attempt to verify. Just double check that it is
810       // marked with an error, and move on.
811       if (!result_path->errors.ContainsHighSeverityErrors()) {
812         result_path->errors.GetOtherErrors()->AddError(
813             cert_errors::kInternalError);
814       }
815     } else {
816       // Verify the entire certificate chain.
817       VerifyCertificateChain(
818           result_path->certs, result_path->last_cert_trust, delegate_, time_,
819           key_purpose_, initial_explicit_policy_, user_initial_policy_set_,
820           initial_policy_mapping_inhibit_, initial_any_policy_inhibit_,
821           &result_path->user_constrained_policy_set, &result_path->errors);
822     }
823 
824     DVLOG(1) << "CertPathBuilder VerifyCertificateChain errors:\n"
825              << result_path->errors.ToDebugString(result_path->certs);
826 
827     // Give the delegate a chance to add errors to the path.
828     delegate_->CheckPathAfterVerification(*this, result_path.get());
829 
830     bool path_is_good = result_path->IsValid();
831 
832     AddResultPath(std::move(result_path));
833 
834     if (path_is_good && !explore_all_paths_) {
835       out_result_.iteration_count = iteration_count;
836       // Found a valid path, return immediately.
837       return std::move(out_result_);
838     }
839     // Path did not verify. Try more paths.
840   }
841 }
842 
AddResultPath(std::unique_ptr<CertPathBuilderResultPath> result_path)843 void CertPathBuilder::AddResultPath(
844     std::unique_ptr<CertPathBuilderResultPath> result_path) {
845   // TODO(mattm): If there are no valid paths, set best_result_index based on
846   // number or severity of errors. If there are multiple valid paths, could set
847   // best_result_index based on prioritization (since due to AIA and such, the
848   // actual order results were discovered may not match the ideal).
849   if (!out_result_.HasValidPath()) {
850     const CertPathBuilderResultPath* old_best_path =
851         out_result_.GetBestPathPossiblyInvalid();
852     // If |result_path| is a valid path or if the previous best result did not
853     // end in a trust anchor but the |result_path| does, then update the best
854     // result to the new result.
855     if (result_path->IsValid() ||
856         (!result_path->last_cert_trust.HasUnspecifiedTrust() && old_best_path &&
857          old_best_path->last_cert_trust.HasUnspecifiedTrust())) {
858       out_result_.best_result_index = out_result_.paths.size();
859     }
860   }
861   if (result_path->certs.size() > out_result_.max_depth_seen) {
862     out_result_.max_depth_seen = result_path->certs.size();
863   }
864   out_result_.paths.push_back(std::move(result_path));
865 }
866 
867 }  // namespace net
868