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