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