xref: /aosp_15_r20/external/cronet/third_party/boringssl/src/pki/path_builder.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 <openssl/base.h>
13 #include <openssl/pki/verify_error.h>
14 #include <openssl/sha.h>
15 
16 #include "cert_issuer_source.h"
17 #include "certificate_policies.h"
18 #include "common_cert_errors.h"
19 #include "parse_certificate.h"
20 #include "parse_name.h"  // For CertDebugString.
21 #include "parser.h"
22 #include "string_util.h"
23 #include "trust_store.h"
24 #include "verify_certificate_chain.h"
25 #include "verify_name_match.h"
26 
27 namespace bssl {
28 
29 namespace {
30 
31 using CertIssuerSources = std::vector<CertIssuerSource *>;
32 
33 // Returns a hex-encoded sha256 of the DER-encoding of |cert|.
FingerPrintParsedCertificate(const bssl::ParsedCertificate * cert)34 std::string FingerPrintParsedCertificate(const bssl::ParsedCertificate *cert) {
35   uint8_t digest[SHA256_DIGEST_LENGTH];
36   SHA256(cert->der_cert().data(), cert->der_cert().size(), digest);
37   return bssl::string_util::HexEncode(digest);
38 }
39 
40 // TODO(mattm): decide how much debug logging to keep.
CertDebugString(const ParsedCertificate * cert)41 std::string CertDebugString(const ParsedCertificate *cert) {
42   RDNSequence subject;
43   std::string subject_str;
44   if (!ParseName(cert->tbs().subject_tlv, &subject) ||
45       !ConvertToRFC2253(subject, &subject_str)) {
46     subject_str = "???";
47   }
48 
49   return FingerPrintParsedCertificate(cert) + " " + subject_str;
50 }
51 
PathDebugString(const ParsedCertificateList & certs)52 std::string PathDebugString(const ParsedCertificateList &certs) {
53   std::string s;
54   for (const auto &cert : certs) {
55     if (!s.empty()) {
56       s += "\n";
57     }
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, const ParsedCertificate *issuer) {
88   if (!target->authority_key_identifier()) {
89     return kNoData;
90   }
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, TrustStore *trust_store)
246     : cert_(std::move(in_cert)),
247       cert_issuer_sources_(cert_issuer_sources),
248       trust_store_(trust_store) {}
249 
GetNextIssuer(IssuerEntry * out)250 void CertIssuersIter::GetNextIssuer(IssuerEntry *out) {
251   if (!did_initial_query_) {
252     did_initial_query_ = true;
253     for (auto *cert_issuer_source : *cert_issuer_sources_) {
254       ParsedCertificateList new_issuers;
255       cert_issuer_source->SyncGetIssuersOf(cert(), &new_issuers);
256       AddIssuers(std::move(new_issuers));
257     }
258   }
259 
260   // If there aren't any issuers, block until async results are ready.
261   if (!HasCurrentIssuer()) {
262     if (!did_async_issuer_query_) {
263       // Now issue request(s) for async ones (AIA, etc).
264       DoAsyncIssuerQuery();
265     }
266 
267     // TODO(eroman): Rather than blocking on the async requests in FIFO order,
268     // consume in the order they become ready.
269     while (!HasCurrentIssuer() &&
270            cur_async_request_ < pending_async_requests_.size()) {
271       ParsedCertificateList new_issuers;
272       pending_async_requests_[cur_async_request_]->GetNext(&new_issuers);
273       if (new_issuers.empty()) {
274         // Request is exhausted, no more results pending from that
275         // CertIssuerSource.
276         pending_async_requests_[cur_async_request_++].reset();
277       } else {
278         AddIssuers(std::move(new_issuers));
279       }
280     }
281   }
282 
283   if (HasCurrentIssuer()) {
284     SortRemainingIssuers();
285 
286     // Still have issuers that haven't been returned yet, return the highest
287     // priority one (head of remaining list). A reference to the returned issuer
288     // is retained, since |present_issuers_| points to data owned by it.
289     *out = issuers_[cur_issuer_++];
290     return;
291   }
292 
293   // Reached the end of all available issuers.
294   *out = IssuerEntry();
295 }
296 
AddIssuers(ParsedCertificateList new_issuers)297 void CertIssuersIter::AddIssuers(ParsedCertificateList new_issuers) {
298   for (std::shared_ptr<const ParsedCertificate> &issuer : new_issuers) {
299     if (present_issuers_.find(BytesAsStringView(issuer->der_cert())) !=
300         present_issuers_.end()) {
301       continue;
302     }
303     present_issuers_.insert(BytesAsStringView(issuer->der_cert()));
304 
305     // Look up the trust for this issuer.
306     IssuerEntry entry;
307     entry.cert = std::move(issuer);
308     entry.trust = trust_store_->GetTrust(entry.cert.get());
309     entry.trust_and_key_id_match_ordering = TrustAndKeyIdentifierMatchToOrder(
310         cert(), entry.cert.get(), entry.trust);
311 
312     issuers_.push_back(std::move(entry));
313     issuers_needs_sort_ = true;
314   }
315 }
316 
DoAsyncIssuerQuery()317 void CertIssuersIter::DoAsyncIssuerQuery() {
318   BSSL_CHECK(!did_async_issuer_query_);
319   did_async_issuer_query_ = true;
320   cur_async_request_ = 0;
321   for (auto *cert_issuer_source : *cert_issuer_sources_) {
322     std::unique_ptr<CertIssuerSource::Request> request;
323     cert_issuer_source->AsyncGetIssuersOf(cert(), &request);
324     if (request) {
325       pending_async_requests_.push_back(std::move(request));
326     }
327   }
328 }
329 
SortRemainingIssuers()330 void CertIssuersIter::SortRemainingIssuers() {
331   if (!issuers_needs_sort_) {
332     return;
333   }
334 
335   std::stable_sort(
336       issuers_.begin() + cur_issuer_, issuers_.end(),
337       [](const IssuerEntry &issuer1, const IssuerEntry &issuer2) {
338         // TODO(crbug.com/635205): Add other prioritization hints. (See big list
339         // of possible sorting hints in RFC 4158.)
340         const bool issuer1_self_issued = issuer1.cert->normalized_subject() ==
341                                          issuer1.cert->normalized_issuer();
342         const bool issuer2_self_issued = issuer2.cert->normalized_subject() ==
343                                          issuer2.cert->normalized_issuer();
344         return std::tie(issuer1.trust_and_key_id_match_ordering,
345                         issuer2_self_issued,
346                         // Newer(larger) notBefore & notAfter dates are
347                         // preferred, hence |issuer2| is on the LHS of
348                         // the comparison and |issuer1| on the RHS.
349                         issuer2.cert->tbs().validity_not_before,
350                         issuer2.cert->tbs().validity_not_after) <
351                std::tie(issuer2.trust_and_key_id_match_ordering,
352                         issuer1_self_issued,
353                         issuer1.cert->tbs().validity_not_before,
354                         issuer1.cert->tbs().validity_not_after);
355       });
356 
357   issuers_needs_sort_ = false;
358 }
359 
360 // CertIssuerIterPath tracks which certs are present in the path and prevents
361 // paths from being built which repeat any certs (including different versions
362 // of the same cert, based on Subject+SubjectAltName+SPKI).
363 // (RFC 5280 forbids duplicate certificates per section 6.1, and RFC 4158
364 // further recommends disallowing the same Subject+SubjectAltName+SPKI in
365 // section 2.4.2.)
366 class CertIssuerIterPath {
367  public:
368   // Returns true if |cert| is already present in the path.
IsPresent(const ParsedCertificate * cert) const369   bool IsPresent(const ParsedCertificate *cert) const {
370     return present_certs_.find(GetKey(cert)) != present_certs_.end();
371   }
372 
373   // Appends |cert_issuers_iter| to the path. The cert referred to by
374   // |cert_issuers_iter| must not be present in the path already.
Append(std::unique_ptr<CertIssuersIter> cert_issuers_iter)375   void Append(std::unique_ptr<CertIssuersIter> cert_issuers_iter) {
376     bool added =
377         present_certs_.insert(GetKey(cert_issuers_iter->cert())).second;
378     BSSL_CHECK(added);
379     cur_path_.push_back(std::move(cert_issuers_iter));
380   }
381 
382   // Pops the last CertIssuersIter off the path.
Pop()383   void Pop() {
384     size_t num_erased = present_certs_.erase(GetKey(cur_path_.back()->cert()));
385     BSSL_CHECK(num_erased == 1U);
386     cur_path_.pop_back();
387   }
388 
389   // Copies the ParsedCertificate elements of the current path to |*out_path|.
CopyPath(ParsedCertificateList * out_path)390   void CopyPath(ParsedCertificateList *out_path) {
391     out_path->clear();
392     for (const auto &node : cur_path_) {
393       out_path->push_back(node->reference_cert());
394     }
395   }
396 
397   // Returns true if the path is empty.
Empty() const398   bool Empty() const { return cur_path_.empty(); }
399 
400   // Returns the last CertIssuersIter in the path.
back()401   CertIssuersIter *back() { return cur_path_.back().get(); }
402 
403   // Returns the length of the path.
Length() const404   size_t Length() const { return cur_path_.size(); }
405 
PathDebugString()406   std::string PathDebugString() {
407     std::string s;
408     for (const auto &node : cur_path_) {
409       if (!s.empty()) {
410         s += "\n";
411       }
412       s += " " + CertDebugString(node->cert());
413     }
414     return s;
415   }
416 
417  private:
418   using Key = std::tuple<std::string_view, std::string_view, std::string_view>;
419 
GetKey(const ParsedCertificate * cert)420   static Key GetKey(const ParsedCertificate *cert) {
421     // TODO(mattm): ideally this would use a normalized version of
422     // SubjectAltName, but it's not that important just for LoopChecker.
423     //
424     // Note that subject_alt_names_extension().value will be empty if the cert
425     // had no SubjectAltName extension, so there is no need for a condition on
426     // has_subject_alt_names().
427     return Key(BytesAsStringView(cert->normalized_subject()),
428                BytesAsStringView(cert->subject_alt_names_extension().value),
429                BytesAsStringView(cert->tbs().spki_tlv));
430   }
431 
432   std::vector<std::unique_ptr<CertIssuersIter>> cur_path_;
433 
434   // This refers to data owned by |cur_path_|.
435   // TODO(mattm): use unordered_set. Requires making a hash function for Key.
436   std::set<Key> present_certs_;
437 };
438 
439 }  // namespace
440 
GetTrustedCert() const441 const ParsedCertificate *CertPathBuilderResultPath::GetTrustedCert() const {
442   if (certs.empty()) {
443     return nullptr;
444   }
445 
446   switch (last_cert_trust.type) {
447     case CertificateTrustType::TRUSTED_ANCHOR:
448     case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
449     case CertificateTrustType::TRUSTED_LEAF:
450       return certs.back().get();
451     case CertificateTrustType::UNSPECIFIED:
452     case CertificateTrustType::DISTRUSTED:
453       return nullptr;
454   }
455 
456   assert(0);  // NOTREACHED
457   return nullptr;
458 }
459 
460 // CertPathIter generates possible paths from |cert| to a trust anchor in
461 // |trust_store|, using intermediates from the |cert_issuer_source| objects if
462 // necessary.
463 class CertPathIter {
464  public:
465   CertPathIter(std::shared_ptr<const ParsedCertificate> cert,
466                TrustStore *trust_store);
467 
468   CertPathIter(const CertPathIter &) = delete;
469   CertPathIter &operator=(const CertPathIter &) = delete;
470 
471   // Adds a CertIssuerSource to provide intermediates for use in path building.
472   // The |*cert_issuer_source| must remain valid for the lifetime of the
473   // CertPathIter.
474   void AddCertIssuerSource(CertIssuerSource *cert_issuer_source);
475 
476   // Gets the next candidate path, and fills it into |out_certs| and
477   // |out_last_cert_trust|. Note that the returned path is unverified and must
478   // still be run through a chain validator. If a candidate path could not be
479   // built, a partial path will be returned and |out_errors| will have an error
480   // added.
481   // If the return value is true, GetNextPath may be called again to backtrack
482   // and continue path building. Once all paths have been exhausted returns
483   // false. If deadline or iteration limit is exceeded, sets |out_certs| to the
484   // current path being explored and returns false.
485   bool GetNextPath(ParsedCertificateList *out_certs,
486                    CertificateTrust *out_last_cert_trust,
487                    CertPathErrors *out_errors,
488                    CertPathBuilderDelegate *delegate, uint32_t *iteration_count,
489                    const uint32_t max_iteration_count,
490                    const uint32_t max_path_building_depth);
491 
492  private:
493   // Stores the next candidate issuer, until it is used during the
494   // STATE_GET_NEXT_ISSUER_COMPLETE step.
495   IssuerEntry next_issuer_;
496   // The current path being explored, made up of CertIssuerIters. Each node
497   // keeps track of the state of searching for issuers of that cert, so that
498   // when backtracking it can resume the search where it left off.
499   CertIssuerIterPath cur_path_;
500   // The CertIssuerSources for retrieving candidate issuers.
501   CertIssuerSources cert_issuer_sources_;
502   // The TrustStore for checking if a path ends in a trust anchor.
503   TrustStore *trust_store_;
504 };
505 
CertPathIter(std::shared_ptr<const ParsedCertificate> cert,TrustStore * trust_store)506 CertPathIter::CertPathIter(std::shared_ptr<const ParsedCertificate> cert,
507                            TrustStore *trust_store)
508     : trust_store_(trust_store) {
509   // Initialize |next_issuer_| to the target certificate.
510   next_issuer_.cert = std::move(cert);
511   next_issuer_.trust = trust_store_->GetTrust(next_issuer_.cert.get());
512 }
513 
AddCertIssuerSource(CertIssuerSource * cert_issuer_source)514 void CertPathIter::AddCertIssuerSource(CertIssuerSource *cert_issuer_source) {
515   cert_issuer_sources_.push_back(cert_issuer_source);
516 }
517 
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)518 bool CertPathIter::GetNextPath(ParsedCertificateList *out_certs,
519                                CertificateTrust *out_last_cert_trust,
520                                CertPathErrors *out_errors,
521                                CertPathBuilderDelegate *delegate,
522                                uint32_t *iteration_count,
523                                const uint32_t max_iteration_count,
524                                const uint32_t max_path_building_depth) {
525   out_certs->clear();
526   *out_last_cert_trust = CertificateTrust::ForUnspecified();
527 
528   while (true) {
529     if (delegate->IsDeadlineExpired()) {
530       if (cur_path_.Empty()) {
531         // If the deadline is already expired before the first call to
532         // GetNextPath, cur_path_ will be empty. Return the leaf cert in that
533         // case.
534         if (next_issuer_.cert) {
535           out_certs->push_back(next_issuer_.cert);
536         }
537       } else {
538         cur_path_.CopyPath(out_certs);
539       }
540       out_errors->GetOtherErrors()->AddError(cert_errors::kDeadlineExceeded);
541       return false;
542     }
543 
544     // We are not done yet, so if the current path is at the depth limit then
545     // we must backtrack to find an acceptable solution.
546     if (max_path_building_depth > 0 &&
547         cur_path_.Length() >= max_path_building_depth) {
548       cur_path_.CopyPath(out_certs);
549       out_errors->GetOtherErrors()->AddError(cert_errors::kDepthLimitExceeded);
550       if (delegate->IsDebugLogEnabled()) {
551         delegate->DebugLog(
552             "CertPathIter reached depth limit. Returning "
553             "partial path and backtracking:\n" +
554             PathDebugString(*out_certs));
555       }
556       cur_path_.Pop();
557       return true;
558     }
559 
560     if (!next_issuer_.cert) {
561       if (cur_path_.Empty()) {
562         if (delegate->IsDebugLogEnabled()) {
563           delegate->DebugLog("CertPathIter exhausted all paths...");
564         }
565         return false;
566       }
567 
568       (*iteration_count)++;
569       if (max_iteration_count > 0 && *iteration_count > max_iteration_count) {
570         cur_path_.CopyPath(out_certs);
571         out_errors->GetOtherErrors()->AddError(
572             cert_errors::kIterationLimitExceeded);
573         return false;
574       }
575 
576       cur_path_.back()->GetNextIssuer(&next_issuer_);
577       if (!next_issuer_.cert) {
578         if (!cur_path_.back()->had_non_skipped_issuers()) {
579           // If the end of a path was reached without finding an anchor, return
580           // the partial path before backtracking.
581           cur_path_.CopyPath(out_certs);
582           out_errors->GetErrorsForCert(out_certs->size() - 1)
583               ->AddError(cert_errors::kNoIssuersFound);
584           if (delegate->IsDebugLogEnabled()) {
585             delegate->DebugLog(
586                 "CertPathIter returning partial path and backtracking:\n" +
587                 PathDebugString(*out_certs));
588           }
589           cur_path_.Pop();
590           return true;
591         } else {
592           // No more issuers for current chain, go back up and see if there are
593           // any more for the previous cert.
594           if (delegate->IsDebugLogEnabled()) {
595             delegate->DebugLog("CertPathIter backtracking...");
596           }
597           cur_path_.Pop();
598           continue;
599         }
600       }
601     }
602 
603     // Overrides for cert with trust appearing in the wrong place for the type
604     // of trust (trusted leaf in non-leaf position, or trust anchor in leaf
605     // position.)
606     switch (next_issuer_.trust.type) {
607       case CertificateTrustType::TRUSTED_ANCHOR:
608         // If the leaf cert is trusted only as an anchor, treat it as having
609         // unspecified trust. This may allow a successful path to be built to a
610         // different root (or to the same cert if it's self-signed).
611         if (cur_path_.Empty()) {
612           if (delegate->IsDebugLogEnabled()) {
613             delegate->DebugLog(
614                 "Leaf is a trust anchor, considering as UNSPECIFIED");
615           }
616           next_issuer_.trust = CertificateTrust::ForUnspecified();
617         }
618         break;
619       case CertificateTrustType::TRUSTED_LEAF:
620         // If a non-leaf cert is trusted only as a leaf, treat it as having
621         // unspecified trust. This may allow a successful path to be built to a
622         // trusted root.
623         if (!cur_path_.Empty()) {
624           if (delegate->IsDebugLogEnabled()) {
625             delegate->DebugLog(
626                 "Issuer is a trust leaf, considering as UNSPECIFIED");
627           }
628           next_issuer_.trust = CertificateTrust::ForUnspecified();
629         }
630         break;
631       case CertificateTrustType::DISTRUSTED:
632       case CertificateTrustType::UNSPECIFIED:
633       case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
634         // No override necessary.
635         break;
636     }
637 
638     // Overrides for trusted leaf cert with require_leaf_selfsigned. If the leaf
639     // isn't actually self-signed, treat it as unspecified.
640     switch (next_issuer_.trust.type) {
641       case CertificateTrustType::TRUSTED_LEAF:
642       case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
643         if (cur_path_.Empty() && next_issuer_.trust.require_leaf_selfsigned &&
644             !VerifyCertificateIsSelfSigned(*next_issuer_.cert,
645                                            delegate->GetVerifyCache(),
646                                            /*errors=*/nullptr)) {
647           if (delegate->IsDebugLogEnabled()) {
648             delegate->DebugLog(
649                 "Leaf is trusted with require_leaf_selfsigned but is "
650                 "not self-signed, considering as UNSPECIFIED");
651           }
652           next_issuer_.trust = CertificateTrust::ForUnspecified();
653         }
654         break;
655       case CertificateTrustType::TRUSTED_ANCHOR:
656       case CertificateTrustType::DISTRUSTED:
657       case CertificateTrustType::UNSPECIFIED:
658         // No override necessary.
659         break;
660     }
661 
662     switch (next_issuer_.trust.type) {
663       // If the trust for this issuer is "known" (either because it is
664       // distrusted, or because it is trusted) then stop building and return the
665       // path.
666       case CertificateTrustType::DISTRUSTED:
667       case CertificateTrustType::TRUSTED_ANCHOR:
668       case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
669       case CertificateTrustType::TRUSTED_LEAF: {
670         // If the issuer has a known trust level, can stop building the path.
671         cur_path_.CopyPath(out_certs);
672         out_certs->push_back(std::move(next_issuer_.cert));
673         if (delegate->IsDebugLogEnabled()) {
674           delegate->DebugLog("CertPathIter returning path:\n" +
675                              PathDebugString(*out_certs));
676         }
677         *out_last_cert_trust = next_issuer_.trust;
678         next_issuer_ = IssuerEntry();
679         return true;
680       }
681       case CertificateTrustType::UNSPECIFIED: {
682         // Skip this cert if it is already in the chain.
683         if (cur_path_.IsPresent(next_issuer_.cert.get())) {
684           cur_path_.back()->increment_skipped_issuer_count();
685           if (delegate->IsDebugLogEnabled()) {
686             delegate->DebugLog("CertPathIter skipping dupe cert: " +
687                                CertDebugString(next_issuer_.cert.get()));
688           }
689           next_issuer_ = IssuerEntry();
690           continue;
691         }
692 
693         cur_path_.Append(std::make_unique<CertIssuersIter>(
694             std::move(next_issuer_.cert), &cert_issuer_sources_, trust_store_));
695         next_issuer_ = IssuerEntry();
696         if (delegate->IsDebugLogEnabled()) {
697           delegate->DebugLog("CertPathIter cur_path_ =\n" +
698                              cur_path_.PathDebugString());
699         }
700         // Continue descending the tree.
701         continue;
702       }
703     }
704   }
705 }
706 
707 CertPathBuilderResultPath::CertPathBuilderResultPath() = default;
708 CertPathBuilderResultPath::~CertPathBuilderResultPath() = default;
709 
IsValid() const710 bool CertPathBuilderResultPath::IsValid() const {
711   return GetTrustedCert() && !errors.ContainsHighSeverityErrors();
712 }
713 
GetVerifyError() const714 VerifyError CertPathBuilderResultPath::GetVerifyError() const {
715   // Diagnostic string is always "everything" about the path.
716   std::string diagnostic = errors.ToDebugString(certs);
717   if (!errors.ContainsHighSeverityErrors()) {
718     // TODO(bbe3): Having to check this after seems awkward: crbug.com/boringssl/713
719     if (GetTrustedCert()) {
720       return VerifyError(VerifyError::StatusCode::PATH_VERIFIED, 0,
721                          std::move(diagnostic));
722     } else {
723       return VerifyError(VerifyError::StatusCode::VERIFICATION_FAILURE, -1,
724                          std::move(diagnostic));
725     }
726   }
727 
728   // Check for the presence of things that amount to Internal errors in the
729   // verification code. We deliberately prioritize this to not hide it in
730   // multiple error cases.
731   if (errors.ContainsError(cert_errors::kInternalError) ||
732       errors.ContainsError(cert_errors::kChainIsEmpty)) {
733     return VerifyError(VerifyError::StatusCode::VERIFICATION_FAILURE, -1,
734                        std::move(diagnostic));
735   }
736 
737   // Similarly, for the deadline and limit cases, there will often be other
738   // errors that we probably do not care about, since path building was
739   // aborted. Surface these errors instead of having them hidden in the multiple
740   // error case.
741   //
742   // Normally callers should check for these in the path builder result before
743   // calling this on a single path, but this is here in case they do not and
744   // these errors are actually present on this path.
745   if (errors.ContainsError(cert_errors::kDeadlineExceeded)) {
746     return VerifyError(VerifyError::StatusCode::PATH_DEADLINE_EXCEEDED, -1,
747                        std::move(diagnostic));
748   }
749   if (errors.ContainsError(cert_errors::kIterationLimitExceeded)) {
750     return VerifyError(VerifyError::StatusCode::PATH_ITERATION_COUNT_EXCEEDED,
751                        -1, std::move(diagnostic));
752   }
753   if (errors.ContainsError(cert_errors::kDepthLimitExceeded)) {
754     return VerifyError(VerifyError::StatusCode::PATH_DEPTH_LIMIT_REACHED, -1,
755                        std::move(diagnostic));
756   }
757 
758   // If the chain has multiple high severity errors, indicate that.
759   ptrdiff_t depth = -1;
760   std::optional<CertErrorId> single_error =
761       errors.FindSingleHighSeverityError(depth);
762   if (!single_error.has_value()) {
763     return VerifyError(VerifyError::StatusCode::PATH_MULTIPLE_ERRORS, -1,
764                        std::move(diagnostic));
765   }
766 
767   // Otherwise it has a single error, map it appropriately at the
768   // depth it first occurs.
769   if (single_error.value() == cert_errors::kValidityFailedNotAfter) {
770     return VerifyError(VerifyError::StatusCode::CERTIFICATE_EXPIRED, depth,
771                        std::move(diagnostic));
772   }
773   if (single_error.value() == cert_errors::kValidityFailedNotBefore) {
774     return VerifyError(VerifyError::StatusCode::CERTIFICATE_NOT_YET_VALID,
775                        depth, std::move(diagnostic));
776   }
777   if (single_error.value() == cert_errors::kDistrustedByTrustStore ||
778       single_error.value() == cert_errors::kCertIsNotTrustAnchor ||
779       single_error.value() == cert_errors::kMaxPathLengthViolated ||
780       single_error.value() == cert_errors::kSubjectDoesNotMatchIssuer ||
781       single_error.value() == cert_errors::kNoIssuersFound) {
782     return VerifyError(VerifyError::StatusCode::PATH_NOT_FOUND, depth,
783                        std::move(diagnostic));
784   }
785   if (single_error.value() == cert_errors::kVerifySignedDataFailed) {
786     return VerifyError(VerifyError::StatusCode::CERTIFICATE_INVALID_SIGNATURE,
787                        depth, std::move(diagnostic));
788   }
789   if (single_error.value() == cert_errors::kUnacceptableSignatureAlgorithm) {
790     return VerifyError(
791         VerifyError::StatusCode::CERTIFICATE_UNSUPPORTED_SIGNATURE_ALGORITHM,
792         depth, std::move(diagnostic));
793   }
794   if (single_error.value() == cert_errors::kUnacceptablePublicKey) {
795     return VerifyError(VerifyError::StatusCode::CERTIFICATE_UNSUPPORTED_KEY,
796                        depth, std::move(diagnostic));
797   }
798   if (single_error.value() == cert_errors::kEkuLacksServerAuth ||
799       single_error.value() == cert_errors::kEkuLacksServerAuthButHasAnyEKU ||
800       single_error.value() == cert_errors::kEkuLacksClientAuth ||
801       single_error.value() == cert_errors::kEkuLacksClientAuthButHasAnyEKU ||
802       single_error.value() == cert_errors::kEkuLacksClientAuthOrServerAuth) {
803     return VerifyError(VerifyError::StatusCode::CERTIFICATE_NO_MATCHING_EKU,
804                        depth, std::move(diagnostic));
805   }
806   if (single_error.value() == cert_errors::kCertificateRevoked) {
807     return VerifyError(VerifyError::StatusCode::CERTIFICATE_REVOKED, depth,
808                        std::move(diagnostic));
809   }
810   if (single_error.value() == cert_errors::kNoRevocationMechanism) {
811     return VerifyError(
812         VerifyError::StatusCode::CERTIFICATE_NO_REVOCATION_MECHANISM, depth,
813         std::move(diagnostic));
814   }
815   if (single_error.value() == cert_errors::kUnableToCheckRevocation) {
816     return VerifyError(
817         VerifyError::StatusCode::CERTIFICATE_UNABLE_TO_CHECK_REVOCATION, depth,
818         std::move(diagnostic));
819   }
820   // All other High severity errors map to CERTIFICATE_INVALID if associated
821   // to a certificate, or VERIFICATION_FAILURE if not associated to a
822   // certificate.
823   return VerifyError((depth < 0) ? VerifyError::StatusCode::VERIFICATION_FAILURE
824                                  : VerifyError::StatusCode::CERTIFICATE_INVALID,
825                      depth, std::move(diagnostic));
826 }
827 
828 
829 CertPathBuilder::Result::Result() = default;
830 CertPathBuilder::Result::Result(Result &&) = default;
831 CertPathBuilder::Result::~Result() = default;
832 CertPathBuilder::Result &CertPathBuilder::Result::operator=(Result &&) =
833     default;
834 
HasValidPath() const835 bool CertPathBuilder::Result::HasValidPath() const {
836   return GetBestValidPath() != nullptr;
837 }
838 
AnyPathContainsError(CertErrorId error_id) const839 bool CertPathBuilder::Result::AnyPathContainsError(CertErrorId error_id) const {
840   for (const auto &path : paths) {
841     if (path->errors.ContainsError(error_id)) {
842       return true;
843     }
844   }
845 
846   return false;
847 }
848 
GetBestPathVerifyError() const849 const VerifyError CertPathBuilder::Result::GetBestPathVerifyError() const {
850   if (HasValidPath()) {
851     return GetBestValidPath()->GetVerifyError();
852   }
853   // We can only return one error. Returning the errors corresponding to the
854   // limits if they they appear on any path will make this error prominent even
855   // if there are other paths with different or multiple errors.
856   if (exceeded_iteration_limit) {
857     return VerifyError(
858         VerifyError::StatusCode::PATH_ITERATION_COUNT_EXCEEDED, -1,
859         "Iteration count exceeded, could not find a trusted path.");
860   }
861   if (exceeded_deadline) {
862     return VerifyError(VerifyError::StatusCode::PATH_DEADLINE_EXCEEDED, -1,
863                        "Deadline exceeded. Could not find a trusted path.");
864   }
865   if (AnyPathContainsError(cert_errors::kDepthLimitExceeded)) {
866     return VerifyError(VerifyError::StatusCode::PATH_DEPTH_LIMIT_REACHED, -1,
867                        "Depth limit reached. Could not find a trusted path.");
868   }
869 
870   // If there are no paths to report an error on, this probably indicates
871   // something is wrong with this path builder result.
872   if (paths.empty()) {
873     return VerifyError(VerifyError::StatusCode::VERIFICATION_FAILURE, -1,
874                        "No paths in path builder result.");
875   }
876 
877   // If there are paths, report the VerifyError from the best path.
878   CertPathBuilderResultPath *path = paths[best_result_index].get();
879   return path->GetVerifyError();
880 }
881 
GetBestValidPath() const882 const CertPathBuilderResultPath *CertPathBuilder::Result::GetBestValidPath()
883     const {
884   const CertPathBuilderResultPath *result_path = GetBestPathPossiblyInvalid();
885 
886   if (result_path && result_path->IsValid()) {
887     return result_path;
888   }
889 
890   return nullptr;
891 }
892 
893 const CertPathBuilderResultPath *
GetBestPathPossiblyInvalid() const894 CertPathBuilder::Result::GetBestPathPossiblyInvalid() const {
895   BSSL_CHECK((paths.empty() && best_result_index == 0) ||
896              best_result_index < paths.size());
897 
898   if (best_result_index >= paths.size()) {
899     return nullptr;
900   }
901 
902   return paths[best_result_index].get();
903 }
904 
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)905 CertPathBuilder::CertPathBuilder(
906     std::shared_ptr<const ParsedCertificate> cert, TrustStore *trust_store,
907     CertPathBuilderDelegate *delegate, const der::GeneralizedTime &time,
908     KeyPurpose key_purpose, InitialExplicitPolicy initial_explicit_policy,
909     const std::set<der::Input> &user_initial_policy_set,
910     InitialPolicyMappingInhibit initial_policy_mapping_inhibit,
911     InitialAnyPolicyInhibit initial_any_policy_inhibit)
912     : cert_path_iter_(
913           std::make_unique<CertPathIter>(std::move(cert), trust_store)),
914       delegate_(delegate),
915       time_(time),
916       key_purpose_(key_purpose),
917       initial_explicit_policy_(initial_explicit_policy),
918       user_initial_policy_set_(user_initial_policy_set),
919       initial_policy_mapping_inhibit_(initial_policy_mapping_inhibit),
920       initial_any_policy_inhibit_(initial_any_policy_inhibit) {
921   BSSL_CHECK(delegate);
922   // The TrustStore also implements the CertIssuerSource interface.
923   AddCertIssuerSource(trust_store);
924 }
925 
926 CertPathBuilder::~CertPathBuilder() = default;
927 
AddCertIssuerSource(CertIssuerSource * cert_issuer_source)928 void CertPathBuilder::AddCertIssuerSource(
929     CertIssuerSource *cert_issuer_source) {
930   cert_path_iter_->AddCertIssuerSource(cert_issuer_source);
931 }
932 
SetIterationLimit(uint32_t limit)933 void CertPathBuilder::SetIterationLimit(uint32_t limit) {
934   max_iteration_count_ = limit;
935 }
936 
SetDepthLimit(uint32_t limit)937 void CertPathBuilder::SetDepthLimit(uint32_t limit) {
938   max_path_building_depth_ = limit;
939 }
940 
SetValidPathLimit(size_t limit)941 void CertPathBuilder::SetValidPathLimit(size_t limit) {
942   valid_path_limit_ = limit;
943 }
944 
SetExploreAllPaths(bool explore_all_paths)945 void CertPathBuilder::SetExploreAllPaths(bool explore_all_paths) {
946   valid_path_limit_ = explore_all_paths ? 0 : 1;
947 }
948 
Run()949 CertPathBuilder::Result CertPathBuilder::Run() {
950   uint32_t iteration_count = 0;
951 
952   while (true) {
953     std::unique_ptr<CertPathBuilderResultPath> result_path =
954         std::make_unique<CertPathBuilderResultPath>();
955 
956     if (!cert_path_iter_->GetNextPath(
957             &result_path->certs, &result_path->last_cert_trust,
958             &result_path->errors, delegate_, &iteration_count,
959             max_iteration_count_, max_path_building_depth_)) {
960       // There are no more paths to check or limits were exceeded.
961       if (result_path->errors.ContainsError(
962               cert_errors::kIterationLimitExceeded)) {
963         out_result_.exceeded_iteration_limit = true;
964       }
965       if (result_path->errors.ContainsError(cert_errors::kDeadlineExceeded)) {
966         out_result_.exceeded_deadline = true;
967       }
968       if (!result_path->certs.empty()) {
969         // It shouldn't be possible to get here without adding one of the
970         // errors above, but just in case, add an error if there isn't one
971         // already.
972         if (!result_path->errors.ContainsHighSeverityErrors()) {
973           result_path->errors.GetOtherErrors()->AddError(
974               cert_errors::kInternalError);
975         }
976 
977         // Allow the delegate to do any processing or logging of the partial
978         // path. (This is for symmetry for the other CheckPathAfterVerification
979         // which also gets called on partial paths.)
980         delegate_->CheckPathAfterVerification(*this, result_path.get());
981 
982         AddResultPath(std::move(result_path));
983       }
984       out_result_.iteration_count = iteration_count;
985       return std::move(out_result_);
986     }
987 
988     if (result_path->last_cert_trust.HasUnspecifiedTrust()) {
989       // Partial path, don't attempt to verify. Just double check that it is
990       // marked with an error, and move on.
991       if (!result_path->errors.ContainsHighSeverityErrors()) {
992         result_path->errors.GetOtherErrors()->AddError(
993             cert_errors::kInternalError);
994       }
995     } else {
996       // Verify the entire certificate chain.
997       VerifyCertificateChain(
998           result_path->certs, result_path->last_cert_trust, delegate_, time_,
999           key_purpose_, initial_explicit_policy_, user_initial_policy_set_,
1000           initial_policy_mapping_inhibit_, initial_any_policy_inhibit_,
1001           &result_path->user_constrained_policy_set, &result_path->errors);
1002     }
1003 
1004     // Give the delegate a chance to add errors to the path.
1005     delegate_->CheckPathAfterVerification(*this, result_path.get());
1006 
1007     bool path_is_good = result_path->IsValid();
1008 
1009     AddResultPath(std::move(result_path));
1010 
1011     if (path_is_good) {
1012       valid_path_count_++;
1013       if (valid_path_limit_ > 0 && valid_path_count_ == valid_path_limit_) {
1014         out_result_.iteration_count = iteration_count;
1015         // Found enough paths, return immediately.
1016         return std::move(out_result_);
1017       }
1018     }
1019     // Path did not verify. Try more paths.
1020   }
1021 }
1022 
AddResultPath(std::unique_ptr<CertPathBuilderResultPath> result_path)1023 void CertPathBuilder::AddResultPath(
1024     std::unique_ptr<CertPathBuilderResultPath> result_path) {
1025   // TODO(mattm): If there are no valid paths, set best_result_index based on
1026   // number or severity of errors. If there are multiple valid paths, could set
1027   // best_result_index based on prioritization (since due to AIA and such, the
1028   // actual order results were discovered may not match the ideal).
1029   if (!out_result_.HasValidPath()) {
1030     const CertPathBuilderResultPath *old_best_path =
1031         out_result_.GetBestPathPossiblyInvalid();
1032     // If |result_path| is a valid path or if the previous best result did not
1033     // end in a trust anchor but the |result_path| does, then update the best
1034     // result to the new result.
1035     if (result_path->IsValid() ||
1036         (!result_path->last_cert_trust.HasUnspecifiedTrust() && old_best_path &&
1037          old_best_path->last_cert_trust.HasUnspecifiedTrust())) {
1038       out_result_.best_result_index = out_result_.paths.size();
1039     }
1040   }
1041   if (result_path->certs.size() > out_result_.max_depth_seen) {
1042     out_result_.max_depth_seen = result_path->certs.size();
1043   }
1044   out_result_.paths.push_back(std::move(result_path));
1045 }
1046 
1047 }  // namespace bssl
1048