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