1 // Copyright 2016 The Chromium Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "path_builder.h"
16 
17 #include <cassert>
18 #include <memory>
19 #include <set>
20 #include <unordered_set>
21 
22 #include <openssl/base.h>
23 #include <openssl/pki/verify_error.h>
24 #include <openssl/sha2.h>
25 
26 #include "cert_issuer_source.h"
27 #include "certificate_policies.h"
28 #include "common_cert_errors.h"
29 #include "parse_certificate.h"
30 #include "parse_name.h"  // For CertDebugString.
31 #include "parser.h"
32 #include "string_util.h"
33 #include "trust_store.h"
34 #include "verify_certificate_chain.h"
35 #include "verify_name_match.h"
36 
37 BSSL_NAMESPACE_BEGIN
38 
39 namespace {
40 
41 using CertIssuerSources = std::vector<CertIssuerSource *>;
42 
43 // Returns a hex-encoded sha256 of the DER-encoding of |cert|.
FingerPrintParsedCertificate(const bssl::ParsedCertificate * cert)44 std::string FingerPrintParsedCertificate(const bssl::ParsedCertificate *cert) {
45   uint8_t digest[SHA256_DIGEST_LENGTH];
46   SHA256(cert->der_cert().data(), cert->der_cert().size(), digest);
47   return bssl::string_util::HexEncode(digest);
48 }
49 
50 // TODO(mattm): decide how much debug logging to keep.
CertDebugString(const ParsedCertificate * cert)51 std::string CertDebugString(const ParsedCertificate *cert) {
52   RDNSequence subject;
53   std::string subject_str;
54   if (!ParseName(cert->tbs().subject_tlv, &subject) ||
55       !ConvertToRFC2253(subject, &subject_str)) {
56     subject_str = "???";
57   }
58 
59   return FingerPrintParsedCertificate(cert) + " " + subject_str;
60 }
61 
PathDebugString(const ParsedCertificateList & certs)62 std::string PathDebugString(const ParsedCertificateList &certs) {
63   std::string s;
64   for (const auto &cert : certs) {
65     if (!s.empty()) {
66       s += "\n";
67     }
68     s += " " + CertDebugString(cert.get());
69   }
70   return s;
71 }
72 
73 // This structure describes a certificate and its trust level. Note that |cert|
74 // may be null to indicate an "empty" entry.
75 struct IssuerEntry {
76   std::shared_ptr<const ParsedCertificate> cert;
77   CertificateTrust trust;
78   int trust_and_key_id_match_ordering;
79 };
80 
81 enum KeyIdentifierMatch {
82   // |target| has a keyIdentifier and it matches |issuer|'s
83   // subjectKeyIdentifier.
84   kMatch = 0,
85   // |target| does not have authorityKeyIdentifier or |issuer| does not have
86   // subjectKeyIdentifier.
87   kNoData = 1,
88   // |target|'s authorityKeyIdentifier does not match |issuer|.
89   kMismatch = 2,
90 };
91 
92 // Returns an integer that represents the relative ordering of |issuer| for
93 // prioritizing certificates in path building based on |issuer|'s
94 // subjectKeyIdentifier and |target|'s authorityKeyIdentifier. Lower return
95 // values indicate higer priority.
CalculateKeyIdentifierMatch(const ParsedCertificate * target,const ParsedCertificate * issuer)96 KeyIdentifierMatch CalculateKeyIdentifierMatch(
97     const ParsedCertificate *target, const ParsedCertificate *issuer) {
98   if (!target->authority_key_identifier()) {
99     return kNoData;
100   }
101 
102   // TODO(crbug.com/635205): If issuer does not have a subjectKeyIdentifier,
103   // could try synthesizing one using the standard SHA-1 method. Ideally in a
104   // way where any issuers that do have a matching subjectKeyIdentifier could
105   // be tried first before doing the extra work.
106   if (target->authority_key_identifier()->key_identifier &&
107       issuer->subject_key_identifier()) {
108     if (target->authority_key_identifier()->key_identifier !=
109         issuer->subject_key_identifier().value()) {
110       return kMismatch;
111     }
112     return kMatch;
113   }
114 
115   return kNoData;
116 }
117 
118 // Returns an integer that represents the relative ordering of |issuer| based
119 // on |issuer_trust| and authorityKeyIdentifier matching for prioritizing
120 // certificates in path building. Lower return values indicate higer priority.
TrustAndKeyIdentifierMatchToOrder(const ParsedCertificate * target,const ParsedCertificate * issuer,const CertificateTrust & issuer_trust)121 int TrustAndKeyIdentifierMatchToOrder(const ParsedCertificate *target,
122                                       const ParsedCertificate *issuer,
123                                       const CertificateTrust &issuer_trust) {
124   enum {
125     kTrustedAndKeyIdMatch = 0,
126     kTrustedAndKeyIdNoData = 1,
127     kKeyIdMatch = 2,
128     kKeyIdNoData = 3,
129     kTrustedAndKeyIdMismatch = 4,
130     kKeyIdMismatch = 5,
131     kDistrustedAndKeyIdMatch = 6,
132     kDistrustedAndKeyIdNoData = 7,
133     kDistrustedAndKeyIdMismatch = 8,
134   };
135 
136   KeyIdentifierMatch key_id_match = CalculateKeyIdentifierMatch(target, issuer);
137   switch (issuer_trust.type) {
138     case CertificateTrustType::TRUSTED_ANCHOR:
139     case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
140       switch (key_id_match) {
141         case kMatch:
142           return kTrustedAndKeyIdMatch;
143         case kNoData:
144           return kTrustedAndKeyIdNoData;
145         case kMismatch:
146           return kTrustedAndKeyIdMismatch;
147       }
148       break;
149     case CertificateTrustType::UNSPECIFIED:
150     case CertificateTrustType::TRUSTED_LEAF:
151       switch (key_id_match) {
152         case kMatch:
153           return kKeyIdMatch;
154         case kNoData:
155           return kKeyIdNoData;
156         case kMismatch:
157           return kKeyIdMismatch;
158       }
159       break;
160     case CertificateTrustType::DISTRUSTED:
161       switch (key_id_match) {
162         case kMatch:
163           return kDistrustedAndKeyIdMatch;
164         case kNoData:
165           return kDistrustedAndKeyIdNoData;
166         case kMismatch:
167           return kDistrustedAndKeyIdMismatch;
168       }
169       break;
170   }
171   assert(0);  // NOTREACHED
172   return -1;
173 }
174 
175 // CertIssuersIter iterates through the intermediates from |cert_issuer_sources|
176 // which may be issuers of |cert|.
177 class CertIssuersIter {
178  public:
179   // Constructs the CertIssuersIter. |*cert_issuer_sources|, and
180   // |*trust_store| must be valid for the lifetime of the CertIssuersIter.
181   CertIssuersIter(std::shared_ptr<const ParsedCertificate> cert,
182                   CertIssuerSources *cert_issuer_sources,
183                   TrustStore *trust_store);
184 
185   CertIssuersIter(const CertIssuersIter &) = delete;
186   CertIssuersIter &operator=(const CertIssuersIter &) = delete;
187 
188   // Gets the next candidate issuer, or clears |*out| when all issuers have been
189   // exhausted.
190   void GetNextIssuer(IssuerEntry *out);
191 
192   // Returns true if candidate issuers were found for |cert_|.
had_non_skipped_issuers() const193   bool had_non_skipped_issuers() const {
194     return issuers_.size() > skipped_issuer_count_;
195   }
196 
increment_skipped_issuer_count()197   void increment_skipped_issuer_count() { skipped_issuer_count_++; }
198 
199   // Returns the |cert| for which issuers are being retrieved.
cert() const200   const ParsedCertificate *cert() const { return cert_.get(); }
reference_cert() const201   std::shared_ptr<const ParsedCertificate> reference_cert() const {
202     return cert_;
203   }
204 
205  private:
206   void AddIssuers(ParsedCertificateList issuers);
207   void DoAsyncIssuerQuery();
208 
209   // Returns true if |issuers_| contains unconsumed certificates.
HasCurrentIssuer() const210   bool HasCurrentIssuer() const { return cur_issuer_ < issuers_.size(); }
211 
212   // Sorts the remaining entries in |issuers_| in the preferred order to
213   // explore. Does not change the ordering for indices before cur_issuer_.
214   void SortRemainingIssuers();
215 
216   std::shared_ptr<const ParsedCertificate> cert_;
217   CertIssuerSources *cert_issuer_sources_;
218   TrustStore *trust_store_;
219 
220   // The list of issuers for |cert_|. This is added to incrementally (first
221   // synchronous results, then possibly multiple times as asynchronous results
222   // arrive.) The issuers may be re-sorted each time new issuers are added, but
223   // only the results from |cur_| onwards should be sorted, since the earlier
224   // results were already returned.
225   // Elements should not be removed from |issuers_| once added, since
226   // |present_issuers_| will point to data owned by the certs.
227   std::vector<IssuerEntry> issuers_;
228   // The index of the next cert in |issuers_| to return.
229   size_t cur_issuer_ = 0;
230   // The number of issuers that were skipped due to the loop checker.
231   size_t skipped_issuer_count_ = 0;
232   // Set to true whenever new issuers are appended at the end, to indicate the
233   // ordering needs to be checked.
234   bool issuers_needs_sort_ = false;
235 
236   // Set of DER-encoded values for the certs in |issuers_|. Used to prevent
237   // duplicates. This is based on the full DER of the cert to allow different
238   // versions of the same certificate to be tried in different candidate paths.
239   // This points to data owned by |issuers_|.
240   std::unordered_set<std::string_view> present_issuers_;
241 
242   // Tracks which requests have been made yet.
243   bool did_initial_query_ = false;
244   bool did_async_issuer_query_ = false;
245   // Index into pending_async_requests_ that is the next one to process.
246   size_t cur_async_request_ = 0;
247   // Owns the Request objects for any asynchronous requests so that they will be
248   // cancelled if CertIssuersIter is destroyed.
249   std::vector<std::unique_ptr<CertIssuerSource::Request>>
250       pending_async_requests_;
251 };
252 
CertIssuersIter(std::shared_ptr<const ParsedCertificate> in_cert,CertIssuerSources * cert_issuer_sources,TrustStore * trust_store)253 CertIssuersIter::CertIssuersIter(
254     std::shared_ptr<const ParsedCertificate> in_cert,
255     CertIssuerSources *cert_issuer_sources, TrustStore *trust_store)
256     : cert_(std::move(in_cert)),
257       cert_issuer_sources_(cert_issuer_sources),
258       trust_store_(trust_store) {}
259 
GetNextIssuer(IssuerEntry * out)260 void CertIssuersIter::GetNextIssuer(IssuerEntry *out) {
261   if (!did_initial_query_) {
262     did_initial_query_ = true;
263     for (auto *cert_issuer_source : *cert_issuer_sources_) {
264       ParsedCertificateList new_issuers;
265       cert_issuer_source->SyncGetIssuersOf(cert(), &new_issuers);
266       AddIssuers(std::move(new_issuers));
267     }
268   }
269 
270   // If there aren't any issuers, block until async results are ready.
271   if (!HasCurrentIssuer()) {
272     if (!did_async_issuer_query_) {
273       // Now issue request(s) for async ones (AIA, etc).
274       DoAsyncIssuerQuery();
275     }
276 
277     // TODO(eroman): Rather than blocking on the async requests in FIFO order,
278     // consume in the order they become ready.
279     while (!HasCurrentIssuer() &&
280            cur_async_request_ < pending_async_requests_.size()) {
281       ParsedCertificateList new_issuers;
282       pending_async_requests_[cur_async_request_]->GetNext(&new_issuers);
283       if (new_issuers.empty()) {
284         // Request is exhausted, no more results pending from that
285         // CertIssuerSource.
286         pending_async_requests_[cur_async_request_++].reset();
287       } else {
288         AddIssuers(std::move(new_issuers));
289       }
290     }
291   }
292 
293   if (HasCurrentIssuer()) {
294     SortRemainingIssuers();
295 
296     // Still have issuers that haven't been returned yet, return the highest
297     // priority one (head of remaining list). A reference to the returned issuer
298     // is retained, since |present_issuers_| points to data owned by it.
299     *out = issuers_[cur_issuer_++];
300     return;
301   }
302 
303   // Reached the end of all available issuers.
304   *out = IssuerEntry();
305 }
306 
AddIssuers(ParsedCertificateList new_issuers)307 void CertIssuersIter::AddIssuers(ParsedCertificateList new_issuers) {
308   for (std::shared_ptr<const ParsedCertificate> &issuer : new_issuers) {
309     if (present_issuers_.find(BytesAsStringView(issuer->der_cert())) !=
310         present_issuers_.end()) {
311       continue;
312     }
313     present_issuers_.insert(BytesAsStringView(issuer->der_cert()));
314 
315     // Look up the trust for this issuer.
316     IssuerEntry entry;
317     entry.cert = std::move(issuer);
318     entry.trust = trust_store_->GetTrust(entry.cert.get());
319     entry.trust_and_key_id_match_ordering = TrustAndKeyIdentifierMatchToOrder(
320         cert(), entry.cert.get(), entry.trust);
321 
322     issuers_.push_back(std::move(entry));
323     issuers_needs_sort_ = true;
324   }
325 }
326 
DoAsyncIssuerQuery()327 void CertIssuersIter::DoAsyncIssuerQuery() {
328   BSSL_CHECK(!did_async_issuer_query_);
329   did_async_issuer_query_ = true;
330   cur_async_request_ = 0;
331   for (auto *cert_issuer_source : *cert_issuer_sources_) {
332     std::unique_ptr<CertIssuerSource::Request> request;
333     cert_issuer_source->AsyncGetIssuersOf(cert(), &request);
334     if (request) {
335       pending_async_requests_.push_back(std::move(request));
336     }
337   }
338 }
339 
SortRemainingIssuers()340 void CertIssuersIter::SortRemainingIssuers() {
341   if (!issuers_needs_sort_) {
342     return;
343   }
344 
345   std::stable_sort(
346       issuers_.begin() + cur_issuer_, issuers_.end(),
347       [](const IssuerEntry &issuer1, const IssuerEntry &issuer2) {
348         // TODO(crbug.com/635205): Add other prioritization hints. (See big list
349         // of possible sorting hints in RFC 4158.)
350         const bool issuer1_self_issued = issuer1.cert->normalized_subject() ==
351                                          issuer1.cert->normalized_issuer();
352         const bool issuer2_self_issued = issuer2.cert->normalized_subject() ==
353                                          issuer2.cert->normalized_issuer();
354         return std::tie(issuer1.trust_and_key_id_match_ordering,
355                         issuer2_self_issued,
356                         // Newer(larger) notBefore & notAfter dates are
357                         // preferred, hence |issuer2| is on the LHS of
358                         // the comparison and |issuer1| on the RHS.
359                         issuer2.cert->tbs().validity_not_before,
360                         issuer2.cert->tbs().validity_not_after) <
361                std::tie(issuer2.trust_and_key_id_match_ordering,
362                         issuer1_self_issued,
363                         issuer1.cert->tbs().validity_not_before,
364                         issuer1.cert->tbs().validity_not_after);
365       });
366 
367   issuers_needs_sort_ = false;
368 }
369 
370 // CertIssuerIterPath tracks which certs are present in the path and prevents
371 // paths from being built which repeat any certs (including different versions
372 // of the same cert, based on Subject+SubjectAltName+SPKI).
373 // (RFC 5280 forbids duplicate certificates per section 6.1, and RFC 4158
374 // further recommends disallowing the same Subject+SubjectAltName+SPKI in
375 // section 2.4.2.)
376 class CertIssuerIterPath {
377  public:
378   // Returns true if |cert| is already present in the path.
IsPresent(const ParsedCertificate * cert) const379   bool IsPresent(const ParsedCertificate *cert) const {
380     return present_certs_.find(GetKey(cert)) != present_certs_.end();
381   }
382 
383   // Appends |cert_issuers_iter| to the path. The cert referred to by
384   // |cert_issuers_iter| must not be present in the path already.
Append(std::unique_ptr<CertIssuersIter> cert_issuers_iter)385   void Append(std::unique_ptr<CertIssuersIter> cert_issuers_iter) {
386     bool added =
387         present_certs_.insert(GetKey(cert_issuers_iter->cert())).second;
388     BSSL_CHECK(added);
389     cur_path_.push_back(std::move(cert_issuers_iter));
390   }
391 
392   // Pops the last CertIssuersIter off the path.
Pop()393   void Pop() {
394     size_t num_erased = present_certs_.erase(GetKey(cur_path_.back()->cert()));
395     BSSL_CHECK(num_erased == 1U);
396     cur_path_.pop_back();
397   }
398 
399   // Copies the ParsedCertificate elements of the current path to |*out_path|.
CopyPath(ParsedCertificateList * out_path)400   void CopyPath(ParsedCertificateList *out_path) {
401     out_path->clear();
402     for (const auto &node : cur_path_) {
403       out_path->push_back(node->reference_cert());
404     }
405   }
406 
407   // Returns true if the path is empty.
Empty() const408   bool Empty() const { return cur_path_.empty(); }
409 
410   // Returns the last CertIssuersIter in the path.
back()411   CertIssuersIter *back() { return cur_path_.back().get(); }
412 
413   // Returns the length of the path.
Length() const414   size_t Length() const { return cur_path_.size(); }
415 
PathDebugString()416   std::string PathDebugString() {
417     std::string s;
418     for (const auto &node : cur_path_) {
419       if (!s.empty()) {
420         s += "\n";
421       }
422       s += " " + CertDebugString(node->cert());
423     }
424     return s;
425   }
426 
427  private:
428   using Key = std::tuple<std::string_view, std::string_view, std::string_view>;
429 
GetKey(const ParsedCertificate * cert)430   static Key GetKey(const ParsedCertificate *cert) {
431     // TODO(mattm): ideally this would use a normalized version of
432     // SubjectAltName, but it's not that important just for LoopChecker.
433     //
434     // Note that subject_alt_names_extension().value will be empty if the cert
435     // had no SubjectAltName extension, so there is no need for a condition on
436     // has_subject_alt_names().
437     return Key(BytesAsStringView(cert->normalized_subject()),
438                BytesAsStringView(cert->subject_alt_names_extension().value),
439                BytesAsStringView(cert->tbs().spki_tlv));
440   }
441 
442   std::vector<std::unique_ptr<CertIssuersIter>> cur_path_;
443 
444   // This refers to data owned by |cur_path_|.
445   // TODO(mattm): use unordered_set. Requires making a hash function for Key.
446   std::set<Key> present_certs_;
447 };
448 
449 }  // namespace
450 
GetTrustedCert() const451 const ParsedCertificate *CertPathBuilderResultPath::GetTrustedCert() const {
452   if (certs.empty()) {
453     return nullptr;
454   }
455 
456   switch (last_cert_trust.type) {
457     case CertificateTrustType::TRUSTED_ANCHOR:
458     case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
459     case CertificateTrustType::TRUSTED_LEAF:
460       return certs.back().get();
461     case CertificateTrustType::UNSPECIFIED:
462     case CertificateTrustType::DISTRUSTED:
463       return nullptr;
464   }
465 
466   assert(0);  // NOTREACHED
467   return nullptr;
468 }
469 
470 // CertPathIter generates possible paths from |cert| to a trust anchor in
471 // |trust_store|, using intermediates from the |cert_issuer_source| objects if
472 // necessary.
473 class CertPathIter {
474  public:
475   CertPathIter(std::shared_ptr<const ParsedCertificate> cert,
476                TrustStore *trust_store);
477 
478   CertPathIter(const CertPathIter &) = delete;
479   CertPathIter &operator=(const CertPathIter &) = delete;
480 
481   // Adds a CertIssuerSource to provide intermediates for use in path building.
482   // The |*cert_issuer_source| must remain valid for the lifetime of the
483   // CertPathIter.
484   void AddCertIssuerSource(CertIssuerSource *cert_issuer_source);
485 
486   // Gets the next candidate path, and fills it into |out_certs| and
487   // |out_last_cert_trust|. Note that the returned path is unverified and must
488   // still be run through a chain validator. If a candidate path could not be
489   // built, a partial path will be returned and |out_errors| will have an error
490   // added.
491   // If the return value is true, GetNextPath may be called again to backtrack
492   // and continue path building. Once all paths have been exhausted returns
493   // false. If deadline or iteration limit is exceeded, sets |out_certs| to the
494   // current path being explored and returns false.
495   bool GetNextPath(ParsedCertificateList *out_certs,
496                    CertificateTrust *out_last_cert_trust,
497                    CertPathErrors *out_errors,
498                    CertPathBuilderDelegate *delegate, uint32_t *iteration_count,
499                    const uint32_t max_iteration_count,
500                    const uint32_t max_path_building_depth);
501 
502  private:
503   // Stores the next candidate issuer, until it is used during the
504   // STATE_GET_NEXT_ISSUER_COMPLETE step.
505   IssuerEntry next_issuer_;
506   // The current path being explored, made up of CertIssuerIters. Each node
507   // keeps track of the state of searching for issuers of that cert, so that
508   // when backtracking it can resume the search where it left off.
509   CertIssuerIterPath cur_path_;
510   // The CertIssuerSources for retrieving candidate issuers.
511   CertIssuerSources cert_issuer_sources_;
512   // The TrustStore for checking if a path ends in a trust anchor.
513   TrustStore *trust_store_;
514 };
515 
CertPathIter(std::shared_ptr<const ParsedCertificate> cert,TrustStore * trust_store)516 CertPathIter::CertPathIter(std::shared_ptr<const ParsedCertificate> cert,
517                            TrustStore *trust_store)
518     : trust_store_(trust_store) {
519   // Initialize |next_issuer_| to the target certificate.
520   next_issuer_.cert = std::move(cert);
521   next_issuer_.trust = trust_store_->GetTrust(next_issuer_.cert.get());
522 }
523 
AddCertIssuerSource(CertIssuerSource * cert_issuer_source)524 void CertPathIter::AddCertIssuerSource(CertIssuerSource *cert_issuer_source) {
525   cert_issuer_sources_.push_back(cert_issuer_source);
526 }
527 
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)528 bool CertPathIter::GetNextPath(ParsedCertificateList *out_certs,
529                                CertificateTrust *out_last_cert_trust,
530                                CertPathErrors *out_errors,
531                                CertPathBuilderDelegate *delegate,
532                                uint32_t *iteration_count,
533                                const uint32_t max_iteration_count,
534                                const uint32_t max_path_building_depth) {
535   out_certs->clear();
536   *out_last_cert_trust = CertificateTrust::ForUnspecified();
537 
538   while (true) {
539     if (delegate->IsDeadlineExpired()) {
540       if (cur_path_.Empty()) {
541         // If the deadline is already expired before the first call to
542         // GetNextPath, cur_path_ will be empty. Return the leaf cert in that
543         // case.
544         if (next_issuer_.cert) {
545           out_certs->push_back(next_issuer_.cert);
546         }
547       } else {
548         cur_path_.CopyPath(out_certs);
549       }
550       out_errors->GetOtherErrors()->AddError(cert_errors::kDeadlineExceeded);
551       return false;
552     }
553 
554     // We are not done yet, so if the current path is at the depth limit then
555     // we must backtrack to find an acceptable solution.
556     if (max_path_building_depth > 0 &&
557         cur_path_.Length() >= max_path_building_depth) {
558       cur_path_.CopyPath(out_certs);
559       out_errors->GetOtherErrors()->AddError(cert_errors::kDepthLimitExceeded);
560       if (delegate->IsDebugLogEnabled()) {
561         delegate->DebugLog(
562             "CertPathIter reached depth limit. Returning "
563             "partial path and backtracking:\n" +
564             PathDebugString(*out_certs));
565       }
566       cur_path_.Pop();
567       return true;
568     }
569 
570     if (!next_issuer_.cert) {
571       if (cur_path_.Empty()) {
572         if (delegate->IsDebugLogEnabled()) {
573           delegate->DebugLog("CertPathIter exhausted all paths...");
574         }
575         return false;
576       }
577 
578       (*iteration_count)++;
579       if (max_iteration_count > 0 && *iteration_count > max_iteration_count) {
580         cur_path_.CopyPath(out_certs);
581         out_errors->GetOtherErrors()->AddError(
582             cert_errors::kIterationLimitExceeded);
583         return false;
584       }
585 
586       cur_path_.back()->GetNextIssuer(&next_issuer_);
587       if (!next_issuer_.cert) {
588         if (!cur_path_.back()->had_non_skipped_issuers()) {
589           // If the end of a path was reached without finding an anchor, return
590           // the partial path before backtracking.
591           cur_path_.CopyPath(out_certs);
592           out_errors->GetErrorsForCert(out_certs->size() - 1)
593               ->AddError(cert_errors::kNoIssuersFound);
594           if (delegate->IsDebugLogEnabled()) {
595             delegate->DebugLog(
596                 "CertPathIter returning partial path and backtracking:\n" +
597                 PathDebugString(*out_certs));
598           }
599           cur_path_.Pop();
600           return true;
601         } else {
602           // No more issuers for current chain, go back up and see if there are
603           // any more for the previous cert.
604           if (delegate->IsDebugLogEnabled()) {
605             delegate->DebugLog("CertPathIter backtracking...");
606           }
607           cur_path_.Pop();
608           continue;
609         }
610       }
611     }
612 
613     // Overrides for cert with trust appearing in the wrong place for the type
614     // of trust (trusted leaf in non-leaf position, or trust anchor in leaf
615     // position.)
616     switch (next_issuer_.trust.type) {
617       case CertificateTrustType::TRUSTED_ANCHOR:
618         // If the leaf cert is trusted only as an anchor, treat it as having
619         // unspecified trust. This may allow a successful path to be built to a
620         // different root (or to the same cert if it's self-signed).
621         if (cur_path_.Empty()) {
622           if (delegate->IsDebugLogEnabled()) {
623             delegate->DebugLog(
624                 "Leaf is a trust anchor, considering as UNSPECIFIED");
625           }
626           next_issuer_.trust = CertificateTrust::ForUnspecified();
627         }
628         break;
629       case CertificateTrustType::TRUSTED_LEAF:
630         // If a non-leaf cert is trusted only as a leaf, treat it as having
631         // unspecified trust. This may allow a successful path to be built to a
632         // trusted root.
633         if (!cur_path_.Empty()) {
634           if (delegate->IsDebugLogEnabled()) {
635             delegate->DebugLog(
636                 "Issuer is a trust leaf, considering as UNSPECIFIED");
637           }
638           next_issuer_.trust = CertificateTrust::ForUnspecified();
639         }
640         break;
641       case CertificateTrustType::DISTRUSTED:
642       case CertificateTrustType::UNSPECIFIED:
643       case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
644         // No override necessary.
645         break;
646     }
647 
648     // Overrides for trusted leaf cert with require_leaf_selfsigned. If the leaf
649     // isn't actually self-signed, treat it as unspecified.
650     switch (next_issuer_.trust.type) {
651       case CertificateTrustType::TRUSTED_LEAF:
652       case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
653         if (cur_path_.Empty() && next_issuer_.trust.require_leaf_selfsigned &&
654             !VerifyCertificateIsSelfSigned(*next_issuer_.cert,
655                                            delegate->GetVerifyCache(),
656                                            /*errors=*/nullptr)) {
657           if (delegate->IsDebugLogEnabled()) {
658             delegate->DebugLog(
659                 "Leaf is trusted with require_leaf_selfsigned but is "
660                 "not self-signed, considering as UNSPECIFIED");
661           }
662           next_issuer_.trust = CertificateTrust::ForUnspecified();
663         }
664         break;
665       case CertificateTrustType::TRUSTED_ANCHOR:
666       case CertificateTrustType::DISTRUSTED:
667       case CertificateTrustType::UNSPECIFIED:
668         // No override necessary.
669         break;
670     }
671 
672     switch (next_issuer_.trust.type) {
673       // If the trust for this issuer is "known" (either because it is
674       // distrusted, or because it is trusted) then stop building and return the
675       // path.
676       case CertificateTrustType::DISTRUSTED:
677       case CertificateTrustType::TRUSTED_ANCHOR:
678       case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
679       case CertificateTrustType::TRUSTED_LEAF: {
680         // If the issuer has a known trust level, can stop building the path.
681         cur_path_.CopyPath(out_certs);
682         out_certs->push_back(std::move(next_issuer_.cert));
683         if (delegate->IsDebugLogEnabled()) {
684           delegate->DebugLog("CertPathIter returning path:\n" +
685                              PathDebugString(*out_certs));
686         }
687         *out_last_cert_trust = next_issuer_.trust;
688         next_issuer_ = IssuerEntry();
689         return true;
690       }
691       case CertificateTrustType::UNSPECIFIED: {
692         // Skip this cert if it is already in the chain.
693         if (cur_path_.IsPresent(next_issuer_.cert.get())) {
694           cur_path_.back()->increment_skipped_issuer_count();
695           if (delegate->IsDebugLogEnabled()) {
696             delegate->DebugLog("CertPathIter skipping dupe cert: " +
697                                CertDebugString(next_issuer_.cert.get()));
698           }
699           next_issuer_ = IssuerEntry();
700           continue;
701         }
702 
703         cur_path_.Append(std::make_unique<CertIssuersIter>(
704             std::move(next_issuer_.cert), &cert_issuer_sources_, trust_store_));
705         next_issuer_ = IssuerEntry();
706         if (delegate->IsDebugLogEnabled()) {
707           delegate->DebugLog("CertPathIter cur_path_ =\n" +
708                              cur_path_.PathDebugString());
709         }
710         // Continue descending the tree.
711         continue;
712       }
713     }
714   }
715 }
716 
717 CertPathBuilderResultPath::CertPathBuilderResultPath() = default;
718 CertPathBuilderResultPath::~CertPathBuilderResultPath() = default;
719 
IsValid() const720 bool CertPathBuilderResultPath::IsValid() const {
721   return GetTrustedCert() && !errors.ContainsHighSeverityErrors();
722 }
723 
GetVerifyError() const724 VerifyError CertPathBuilderResultPath::GetVerifyError() const {
725   // Diagnostic string is always "everything" about the path.
726   std::string diagnostic = errors.ToDebugString(certs);
727   if (!errors.ContainsHighSeverityErrors()) {
728     // TODO(bbe3): Having to check this after seems awkward: crbug.com/boringssl/713
729     if (GetTrustedCert()) {
730       return VerifyError(VerifyError::StatusCode::PATH_VERIFIED, 0,
731                          std::move(diagnostic));
732     } else {
733       return VerifyError(VerifyError::StatusCode::VERIFICATION_FAILURE, -1,
734                          std::move(diagnostic));
735     }
736   }
737 
738   // Check for the presence of things that amount to Internal errors in the
739   // verification code. We deliberately prioritize this to not hide it in
740   // multiple error cases.
741   if (errors.ContainsError(cert_errors::kInternalError) ||
742       errors.ContainsError(cert_errors::kChainIsEmpty)) {
743     return VerifyError(VerifyError::StatusCode::VERIFICATION_FAILURE, -1,
744                        std::move(diagnostic));
745   }
746 
747   // Similarly, for the deadline and limit cases, there will often be other
748   // errors that we probably do not care about, since path building was
749   // aborted. Surface these errors instead of having them hidden in the multiple
750   // error case.
751   //
752   // Normally callers should check for these in the path builder result before
753   // calling this on a single path, but this is here in case they do not and
754   // these errors are actually present on this path.
755   if (errors.ContainsError(cert_errors::kDeadlineExceeded)) {
756     return VerifyError(VerifyError::StatusCode::PATH_DEADLINE_EXCEEDED, -1,
757                        std::move(diagnostic));
758   }
759   if (errors.ContainsError(cert_errors::kIterationLimitExceeded)) {
760     return VerifyError(VerifyError::StatusCode::PATH_ITERATION_COUNT_EXCEEDED,
761                        -1, std::move(diagnostic));
762   }
763   if (errors.ContainsError(cert_errors::kDepthLimitExceeded)) {
764     return VerifyError(VerifyError::StatusCode::PATH_DEPTH_LIMIT_REACHED, -1,
765                        std::move(diagnostic));
766   }
767 
768   // If the chain has multiple high severity errors, indicate that.
769   ptrdiff_t depth = -1;
770   std::optional<CertErrorId> single_error =
771       errors.FindSingleHighSeverityError(depth);
772   if (!single_error.has_value()) {
773     return VerifyError(VerifyError::StatusCode::PATH_MULTIPLE_ERRORS, -1,
774                        std::move(diagnostic));
775   }
776 
777   // Otherwise it has a single error, map it appropriately at the
778   // depth it first occurs.
779   if (single_error.value() == cert_errors::kValidityFailedNotAfter) {
780     return VerifyError(VerifyError::StatusCode::CERTIFICATE_EXPIRED, depth,
781                        std::move(diagnostic));
782   }
783   if (single_error.value() == cert_errors::kValidityFailedNotBefore) {
784     return VerifyError(VerifyError::StatusCode::CERTIFICATE_NOT_YET_VALID,
785                        depth, std::move(diagnostic));
786   }
787   if (single_error.value() == cert_errors::kDistrustedByTrustStore ||
788       single_error.value() == cert_errors::kCertIsNotTrustAnchor ||
789       single_error.value() == cert_errors::kMaxPathLengthViolated ||
790       single_error.value() == cert_errors::kSubjectDoesNotMatchIssuer ||
791       single_error.value() == cert_errors::kNoIssuersFound) {
792     return VerifyError(VerifyError::StatusCode::PATH_NOT_FOUND, depth,
793                        std::move(diagnostic));
794   }
795   if (single_error.value() == cert_errors::kVerifySignedDataFailed) {
796     return VerifyError(VerifyError::StatusCode::CERTIFICATE_INVALID_SIGNATURE,
797                        depth, std::move(diagnostic));
798   }
799   if (single_error.value() == cert_errors::kUnacceptableSignatureAlgorithm) {
800     return VerifyError(
801         VerifyError::StatusCode::CERTIFICATE_UNSUPPORTED_SIGNATURE_ALGORITHM,
802         depth, std::move(diagnostic));
803   }
804   if (single_error.value() == cert_errors::kUnacceptablePublicKey) {
805     return VerifyError(VerifyError::StatusCode::CERTIFICATE_UNSUPPORTED_KEY,
806                        depth, std::move(diagnostic));
807   }
808   if (single_error.value() == cert_errors::kEkuLacksServerAuth ||
809       single_error.value() == cert_errors::kEkuLacksServerAuthButHasAnyEKU ||
810       single_error.value() == cert_errors::kEkuLacksClientAuth ||
811       single_error.value() == cert_errors::kEkuLacksClientAuthButHasAnyEKU ||
812       single_error.value() == cert_errors::kEkuLacksClientAuthOrServerAuth) {
813     return VerifyError(VerifyError::StatusCode::CERTIFICATE_NO_MATCHING_EKU,
814                        depth, std::move(diagnostic));
815   }
816   if (single_error.value() == cert_errors::kCertificateRevoked) {
817     return VerifyError(VerifyError::StatusCode::CERTIFICATE_REVOKED, depth,
818                        std::move(diagnostic));
819   }
820   if (single_error.value() == cert_errors::kNoRevocationMechanism) {
821     return VerifyError(
822         VerifyError::StatusCode::CERTIFICATE_NO_REVOCATION_MECHANISM, depth,
823         std::move(diagnostic));
824   }
825   if (single_error.value() == cert_errors::kUnableToCheckRevocation) {
826     return VerifyError(
827         VerifyError::StatusCode::CERTIFICATE_UNABLE_TO_CHECK_REVOCATION, depth,
828         std::move(diagnostic));
829   }
830   // All other High severity errors map to CERTIFICATE_INVALID if associated
831   // to a certificate, or VERIFICATION_FAILURE if not associated to a
832   // certificate.
833   return VerifyError((depth < 0) ? VerifyError::StatusCode::VERIFICATION_FAILURE
834                                  : VerifyError::StatusCode::CERTIFICATE_INVALID,
835                      depth, std::move(diagnostic));
836 }
837 
838 
839 CertPathBuilder::Result::Result() = default;
840 CertPathBuilder::Result::Result(Result &&) = default;
841 CertPathBuilder::Result::~Result() = default;
842 CertPathBuilder::Result &CertPathBuilder::Result::operator=(Result &&) =
843     default;
844 
HasValidPath() const845 bool CertPathBuilder::Result::HasValidPath() const {
846   return GetBestValidPath() != nullptr;
847 }
848 
AnyPathContainsError(CertErrorId error_id) const849 bool CertPathBuilder::Result::AnyPathContainsError(CertErrorId error_id) const {
850   for (const auto &path : paths) {
851     if (path->errors.ContainsError(error_id)) {
852       return true;
853     }
854   }
855 
856   return false;
857 }
858 
GetBestPathVerifyError() const859 const VerifyError CertPathBuilder::Result::GetBestPathVerifyError() const {
860   if (HasValidPath()) {
861     return GetBestValidPath()->GetVerifyError();
862   }
863   // We can only return one error. Returning the errors corresponding to the
864   // limits if they they appear on any path will make this error prominent even
865   // if there are other paths with different or multiple errors.
866   if (exceeded_iteration_limit) {
867     return VerifyError(
868         VerifyError::StatusCode::PATH_ITERATION_COUNT_EXCEEDED, -1,
869         "Iteration count exceeded, could not find a trusted path.");
870   }
871   if (exceeded_deadline) {
872     return VerifyError(VerifyError::StatusCode::PATH_DEADLINE_EXCEEDED, -1,
873                        "Deadline exceeded. Could not find a trusted path.");
874   }
875   if (AnyPathContainsError(cert_errors::kDepthLimitExceeded)) {
876     return VerifyError(VerifyError::StatusCode::PATH_DEPTH_LIMIT_REACHED, -1,
877                        "Depth limit reached. Could not find a trusted path.");
878   }
879 
880   // If there are no paths to report an error on, this probably indicates
881   // something is wrong with this path builder result.
882   if (paths.empty()) {
883     return VerifyError(VerifyError::StatusCode::VERIFICATION_FAILURE, -1,
884                        "No paths in path builder result.");
885   }
886 
887   // If there are paths, report the VerifyError from the best path.
888   CertPathBuilderResultPath *path = paths[best_result_index].get();
889   return path->GetVerifyError();
890 }
891 
GetBestValidPath() const892 const CertPathBuilderResultPath *CertPathBuilder::Result::GetBestValidPath()
893     const {
894   const CertPathBuilderResultPath *result_path = GetBestPathPossiblyInvalid();
895 
896   if (result_path && result_path->IsValid()) {
897     return result_path;
898   }
899 
900   return nullptr;
901 }
902 
903 const CertPathBuilderResultPath *
GetBestPathPossiblyInvalid() const904 CertPathBuilder::Result::GetBestPathPossiblyInvalid() const {
905   BSSL_CHECK((paths.empty() && best_result_index == 0) ||
906              best_result_index < paths.size());
907 
908   if (best_result_index >= paths.size()) {
909     return nullptr;
910   }
911 
912   return paths[best_result_index].get();
913 }
914 
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)915 CertPathBuilder::CertPathBuilder(
916     std::shared_ptr<const ParsedCertificate> cert, TrustStore *trust_store,
917     CertPathBuilderDelegate *delegate, const der::GeneralizedTime &time,
918     KeyPurpose key_purpose, InitialExplicitPolicy initial_explicit_policy,
919     const std::set<der::Input> &user_initial_policy_set,
920     InitialPolicyMappingInhibit initial_policy_mapping_inhibit,
921     InitialAnyPolicyInhibit initial_any_policy_inhibit)
922     : cert_path_iter_(
923           std::make_unique<CertPathIter>(std::move(cert), trust_store)),
924       delegate_(delegate),
925       time_(time),
926       key_purpose_(key_purpose),
927       initial_explicit_policy_(initial_explicit_policy),
928       user_initial_policy_set_(user_initial_policy_set),
929       initial_policy_mapping_inhibit_(initial_policy_mapping_inhibit),
930       initial_any_policy_inhibit_(initial_any_policy_inhibit) {
931   BSSL_CHECK(delegate);
932   // The TrustStore also implements the CertIssuerSource interface.
933   AddCertIssuerSource(trust_store);
934 }
935 
936 CertPathBuilder::~CertPathBuilder() = default;
937 
AddCertIssuerSource(CertIssuerSource * cert_issuer_source)938 void CertPathBuilder::AddCertIssuerSource(
939     CertIssuerSource *cert_issuer_source) {
940   cert_path_iter_->AddCertIssuerSource(cert_issuer_source);
941 }
942 
SetIterationLimit(uint32_t limit)943 void CertPathBuilder::SetIterationLimit(uint32_t limit) {
944   max_iteration_count_ = limit;
945 }
946 
SetDepthLimit(uint32_t limit)947 void CertPathBuilder::SetDepthLimit(uint32_t limit) {
948   max_path_building_depth_ = limit;
949 }
950 
SetValidPathLimit(size_t limit)951 void CertPathBuilder::SetValidPathLimit(size_t limit) {
952   valid_path_limit_ = limit;
953 }
954 
SetExploreAllPaths(bool explore_all_paths)955 void CertPathBuilder::SetExploreAllPaths(bool explore_all_paths) {
956   valid_path_limit_ = explore_all_paths ? 0 : 1;
957 }
958 
Run()959 CertPathBuilder::Result CertPathBuilder::Run() {
960   uint32_t iteration_count = 0;
961 
962   while (true) {
963     std::unique_ptr<CertPathBuilderResultPath> result_path =
964         std::make_unique<CertPathBuilderResultPath>();
965 
966     if (!cert_path_iter_->GetNextPath(
967             &result_path->certs, &result_path->last_cert_trust,
968             &result_path->errors, delegate_, &iteration_count,
969             max_iteration_count_, max_path_building_depth_)) {
970       // There are no more paths to check or limits were exceeded.
971       if (result_path->errors.ContainsError(
972               cert_errors::kIterationLimitExceeded)) {
973         out_result_.exceeded_iteration_limit = true;
974       }
975       if (result_path->errors.ContainsError(cert_errors::kDeadlineExceeded)) {
976         out_result_.exceeded_deadline = true;
977       }
978       if (!result_path->certs.empty()) {
979         // It shouldn't be possible to get here without adding one of the
980         // errors above, but just in case, add an error if there isn't one
981         // already.
982         if (!result_path->errors.ContainsHighSeverityErrors()) {
983           result_path->errors.GetOtherErrors()->AddError(
984               cert_errors::kInternalError);
985         }
986 
987         // Allow the delegate to do any processing or logging of the partial
988         // path. (This is for symmetry for the other CheckPathAfterVerification
989         // which also gets called on partial paths.)
990         delegate_->CheckPathAfterVerification(*this, result_path.get());
991 
992         AddResultPath(std::move(result_path));
993       }
994       out_result_.iteration_count = iteration_count;
995       return std::move(out_result_);
996     }
997 
998     if (result_path->last_cert_trust.HasUnspecifiedTrust()) {
999       // Partial path, don't attempt to verify. Just double check that it is
1000       // marked with an error, and move on.
1001       if (!result_path->errors.ContainsHighSeverityErrors()) {
1002         result_path->errors.GetOtherErrors()->AddError(
1003             cert_errors::kInternalError);
1004       }
1005     } else {
1006       // Verify the entire certificate chain.
1007       VerifyCertificateChain(
1008           result_path->certs, result_path->last_cert_trust, delegate_, time_,
1009           key_purpose_, initial_explicit_policy_, user_initial_policy_set_,
1010           initial_policy_mapping_inhibit_, initial_any_policy_inhibit_,
1011           &result_path->user_constrained_policy_set, &result_path->errors);
1012     }
1013 
1014     // Give the delegate a chance to add errors to the path.
1015     delegate_->CheckPathAfterVerification(*this, result_path.get());
1016 
1017     bool path_is_good = result_path->IsValid();
1018 
1019     AddResultPath(std::move(result_path));
1020 
1021     if (path_is_good) {
1022       valid_path_count_++;
1023       if (valid_path_limit_ > 0 && valid_path_count_ == valid_path_limit_) {
1024         out_result_.iteration_count = iteration_count;
1025         // Found enough paths, return immediately.
1026         return std::move(out_result_);
1027       }
1028     }
1029     // Path did not verify. Try more paths.
1030   }
1031 }
1032 
AddResultPath(std::unique_ptr<CertPathBuilderResultPath> result_path)1033 void CertPathBuilder::AddResultPath(
1034     std::unique_ptr<CertPathBuilderResultPath> result_path) {
1035   // TODO(mattm): If there are no valid paths, set best_result_index based on
1036   // number or severity of errors. If there are multiple valid paths, could set
1037   // best_result_index based on prioritization (since due to AIA and such, the
1038   // actual order results were discovered may not match the ideal).
1039   if (!out_result_.HasValidPath()) {
1040     const CertPathBuilderResultPath *old_best_path =
1041         out_result_.GetBestPathPossiblyInvalid();
1042     // If |result_path| is a valid path or if the previous best result did not
1043     // end in a trust anchor but the |result_path| does, then update the best
1044     // result to the new result.
1045     if (result_path->IsValid() ||
1046         (!result_path->last_cert_trust.HasUnspecifiedTrust() && old_best_path &&
1047          old_best_path->last_cert_trust.HasUnspecifiedTrust())) {
1048       out_result_.best_result_index = out_result_.paths.size();
1049     }
1050   }
1051   if (result_path->certs.size() > out_result_.max_depth_seen) {
1052     out_result_.max_depth_seen = result_path->certs.size();
1053   }
1054   out_result_.paths.push_back(std::move(result_path));
1055 }
1056 
1057 BSSL_NAMESPACE_END
1058