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