• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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/cert_verify_proc_builtin.h"
6 
7 #include <memory>
8 #include <optional>
9 #include <string>
10 #include <string_view>
11 #include <vector>
12 
13 #include "base/feature_list.h"
14 #include "base/logging.h"
15 #include "base/memory/raw_ptr.h"
16 #include "base/time/time.h"
17 #include "base/values.h"
18 #include "components/network_time/time_tracker/time_tracker.h"
19 #include "crypto/sha2.h"
20 #include "net/base/features.h"
21 #include "net/base/ip_address.h"
22 #include "net/base/net_errors.h"
23 #include "net/cert/cert_net_fetcher.h"
24 #include "net/cert/cert_status_flags.h"
25 #include "net/cert/cert_verifier.h"
26 #include "net/cert/cert_verify_proc.h"
27 #include "net/cert/cert_verify_result.h"
28 #include "net/cert/ct_policy_enforcer.h"
29 #include "net/cert/ct_policy_status.h"
30 #include "net/cert/ct_verifier.h"
31 #include "net/cert/ev_root_ca_metadata.h"
32 #include "net/cert/internal/cert_issuer_source_aia.h"
33 #include "net/cert/internal/revocation_checker.h"
34 #include "net/cert/internal/system_trust_store.h"
35 #include "net/cert/signed_certificate_timestamp_and_status.h"
36 #include "net/cert/test_root_certs.h"
37 #include "net/cert/time_conversions.h"
38 #include "net/cert/x509_certificate.h"
39 #include "net/cert/x509_util.h"
40 #include "net/log/net_log_values.h"
41 #include "net/log/net_log_with_source.h"
42 #include "third_party/boringssl/src/pki/cert_errors.h"
43 #include "third_party/boringssl/src/pki/cert_issuer_source_static.h"
44 #include "third_party/boringssl/src/pki/common_cert_errors.h"
45 #include "third_party/boringssl/src/pki/name_constraints.h"
46 #include "third_party/boringssl/src/pki/parsed_certificate.h"
47 #include "third_party/boringssl/src/pki/path_builder.h"
48 #include "third_party/boringssl/src/pki/simple_path_builder_delegate.h"
49 #include "third_party/boringssl/src/pki/trust_store.h"
50 #include "third_party/boringssl/src/pki/trust_store_collection.h"
51 #include "third_party/boringssl/src/pki/trust_store_in_memory.h"
52 
53 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
54 #include "base/version_info/version_info.h"  // nogncheck
55 #include "net/cert/internal/trust_store_chrome.h"
56 #endif
57 
58 using bssl::CertErrorId;
59 
60 namespace net {
61 
62 namespace {
63 
64 // To avoid a denial-of-service risk, cap iterations by the path builder.
65 // Without a limit, path building is potentially exponential. This limit was
66 // set based on UMA histograms in the wild. See https://crrev.com/c/4903550.
67 //
68 // TODO(crbug.com/41267856): Move this limit into BoringSSL as a default.
69 constexpr uint32_t kPathBuilderIterationLimit = 20;
70 
71 constexpr base::TimeDelta kMaxVerificationTime = base::Seconds(60);
72 
73 constexpr base::TimeDelta kPerAttemptMinVerificationTimeLimit =
74     base::Seconds(5);
75 
76 DEFINE_CERT_ERROR_ID(kPathLacksEVPolicy, "Path does not have an EV policy");
77 DEFINE_CERT_ERROR_ID(kChromeRootConstraintsFailed,
78                      "Path does not satisfy CRS constraints");
79 
NetLogCertParams(const CRYPTO_BUFFER * cert_handle,const bssl::CertErrors & errors)80 base::Value::Dict NetLogCertParams(const CRYPTO_BUFFER* cert_handle,
81                                    const bssl::CertErrors& errors) {
82   base::Value::Dict results;
83 
84   std::string pem_encoded;
85   if (X509Certificate::GetPEMEncodedFromDER(
86           x509_util::CryptoBufferAsStringPiece(cert_handle), &pem_encoded)) {
87     results.Set("certificate", pem_encoded);
88   }
89 
90   std::string errors_string = errors.ToDebugString();
91   if (!errors_string.empty())
92     results.Set("errors", errors_string);
93 
94   return results;
95 }
96 
NetLogAdditionalCert(const CRYPTO_BUFFER * cert_handle,const bssl::CertificateTrust & trust,const bssl::CertErrors & errors)97 base::Value::Dict NetLogAdditionalCert(const CRYPTO_BUFFER* cert_handle,
98                                        const bssl::CertificateTrust& trust,
99                                        const bssl::CertErrors& errors) {
100   base::Value::Dict results = NetLogCertParams(cert_handle, errors);
101   results.Set("trust", trust.ToDebugString());
102   return results;
103 }
104 
105 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
NetLogChromeRootStoreVersion(int64_t chrome_root_store_version)106 base::Value::Dict NetLogChromeRootStoreVersion(
107     int64_t chrome_root_store_version) {
108   base::Value::Dict results;
109   results.Set("version_major", NetLogNumberValue(chrome_root_store_version));
110   return results;
111 }
112 #endif
113 
PEMCertValueList(const bssl::ParsedCertificateList & certs)114 base::Value::List PEMCertValueList(const bssl::ParsedCertificateList& certs) {
115   base::Value::List value;
116   for (const auto& cert : certs) {
117     std::string pem;
118     X509Certificate::GetPEMEncodedFromDER(cert->der_cert().AsStringView(),
119                                           &pem);
120     value.Append(std::move(pem));
121   }
122   return value;
123 }
124 
NetLogPathBuilderResultPath(const bssl::CertPathBuilderResultPath & result_path)125 base::Value::Dict NetLogPathBuilderResultPath(
126     const bssl::CertPathBuilderResultPath& result_path) {
127   base::Value::Dict dict;
128   dict.Set("is_valid", result_path.IsValid());
129   dict.Set("last_cert_trust", result_path.last_cert_trust.ToDebugString());
130   dict.Set("certificates", PEMCertValueList(result_path.certs));
131   // TODO(crbug.com/40479281): netlog user_constrained_policy_set.
132   std::string errors_string =
133       result_path.errors.ToDebugString(result_path.certs);
134   if (!errors_string.empty())
135     dict.Set("errors", errors_string);
136   return dict;
137 }
138 
NetLogPathBuilderResult(const bssl::CertPathBuilder::Result & result)139 base::Value::Dict NetLogPathBuilderResult(
140     const bssl::CertPathBuilder::Result& result) {
141   base::Value::Dict dict;
142   // TODO(crbug.com/40479281): include debug data (or just have things netlog it
143   // directly).
144   dict.Set("has_valid_path", result.HasValidPath());
145   dict.Set("best_result_index", static_cast<int>(result.best_result_index));
146   if (result.exceeded_iteration_limit)
147     dict.Set("exceeded_iteration_limit", true);
148   if (result.exceeded_deadline)
149     dict.Set("exceeded_deadline", true);
150   return dict;
151 }
152 
NoRevocationChecking()153 RevocationPolicy NoRevocationChecking() {
154   RevocationPolicy policy;
155   policy.check_revocation = false;
156   policy.networking_allowed = false;
157   policy.crl_allowed = false;
158   policy.allow_missing_info = true;
159   policy.allow_unable_to_check = true;
160   policy.enforce_baseline_requirements = false;
161   return policy;
162 }
163 
164 // Gets the set of policy OIDs in |cert| that are recognized as EV OIDs for some
165 // root.
GetEVPolicyOids(const EVRootCAMetadata * ev_metadata,const bssl::ParsedCertificate * cert,std::set<bssl::der::Input> * oids)166 void GetEVPolicyOids(const EVRootCAMetadata* ev_metadata,
167                      const bssl::ParsedCertificate* cert,
168                      std::set<bssl::der::Input>* oids) {
169   oids->clear();
170 
171   if (!cert->has_policy_oids())
172     return;
173 
174   for (const bssl::der::Input& oid : cert->policy_oids()) {
175     if (ev_metadata->IsEVPolicyOID(oid)) {
176       oids->insert(oid);
177     }
178   }
179 }
180 
181 // Returns true if |cert| could be an EV certificate, based on its policies
182 // extension. A return of false means it definitely is not an EV certificate,
183 // whereas a return of true means it could be EV.
IsEVCandidate(const EVRootCAMetadata * ev_metadata,const bssl::ParsedCertificate * cert)184 bool IsEVCandidate(const EVRootCAMetadata* ev_metadata,
185                    const bssl::ParsedCertificate* cert) {
186   std::set<bssl::der::Input> oids;
187   GetEVPolicyOids(ev_metadata, cert, &oids);
188   return !oids.empty();
189 }
190 
191 // CertVerifyProcTrustStore wraps a SystemTrustStore with additional trust
192 // anchors and TestRootCerts.
193 class CertVerifyProcTrustStore {
194  public:
195   // |system_trust_store| must outlive this object.
CertVerifyProcTrustStore(SystemTrustStore * system_trust_store,bssl::TrustStoreInMemory * additional_trust_store)196   explicit CertVerifyProcTrustStore(
197       SystemTrustStore* system_trust_store,
198       bssl::TrustStoreInMemory* additional_trust_store)
199       : system_trust_store_(system_trust_store),
200         additional_trust_store_(additional_trust_store) {
201     trust_store_.AddTrustStore(additional_trust_store_);
202     trust_store_.AddTrustStore(system_trust_store_->GetTrustStore());
203     // When running in test mode, also layer in the test-only root certificates.
204     //
205     // Note that this integration requires TestRootCerts::HasInstance() to be
206     // true by the time CertVerifyProcTrustStore is created - a limitation which
207     // is acceptable for the test-only code that consumes this.
208     if (TestRootCerts::HasInstance()) {
209       trust_store_.AddTrustStore(
210           TestRootCerts::GetInstance()->test_trust_store());
211     }
212   }
213 
trust_store()214   bssl::TrustStore* trust_store() { return &trust_store_; }
215 
IsKnownRoot(const bssl::ParsedCertificate * trust_anchor) const216   bool IsKnownRoot(const bssl::ParsedCertificate* trust_anchor) const {
217     if (TestRootCerts::HasInstance() &&
218         TestRootCerts::GetInstance()->IsKnownRoot(trust_anchor->der_cert())) {
219       return true;
220     }
221     return system_trust_store_->IsKnownRoot(trust_anchor);
222   }
223 
224 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
GetChromeRootConstraints(const bssl::ParsedCertificate * cert) const225   base::span<const ChromeRootCertConstraints> GetChromeRootConstraints(
226       const bssl::ParsedCertificate* cert) const {
227     return system_trust_store_->GetChromeRootConstraints(cert);
228   }
229 
IsNonChromeRootStoreTrustAnchor(const bssl::ParsedCertificate * trust_anchor) const230   bool IsNonChromeRootStoreTrustAnchor(
231       const bssl::ParsedCertificate* trust_anchor) const {
232     return IsAdditionalTrustAnchor(trust_anchor) ||
233            system_trust_store_->IsLocallyTrustedRoot(trust_anchor);
234   }
235 #endif
236 
IsAdditionalTrustAnchor(const bssl::ParsedCertificate * trust_anchor) const237   bool IsAdditionalTrustAnchor(
238       const bssl::ParsedCertificate* trust_anchor) const {
239     return additional_trust_store_->GetTrust(trust_anchor).IsTrustAnchor();
240   }
241 
242  private:
243   raw_ptr<SystemTrustStore> system_trust_store_;
244   raw_ptr<bssl::TrustStoreInMemory> additional_trust_store_;
245   bssl::TrustStoreCollection trust_store_;
246 };
247 
248 // Enum for whether path building is attempting to verify a certificate as EV or
249 // as DV.
250 enum class VerificationType {
251   kEV,  // Extended Validation
252   kDV,  // Domain Validation
253 };
254 
255 class PathBuilderDelegateDataImpl : public bssl::CertPathBuilderDelegateData {
256  public:
257   ~PathBuilderDelegateDataImpl() override = default;
258 
Get(const bssl::CertPathBuilderResultPath & path)259   static const PathBuilderDelegateDataImpl* Get(
260       const bssl::CertPathBuilderResultPath& path) {
261     return static_cast<PathBuilderDelegateDataImpl*>(path.delegate_data.get());
262   }
263 
GetOrCreate(bssl::CertPathBuilderResultPath * path)264   static PathBuilderDelegateDataImpl* GetOrCreate(
265       bssl::CertPathBuilderResultPath* path) {
266     if (!path->delegate_data)
267       path->delegate_data = std::make_unique<PathBuilderDelegateDataImpl>();
268     return static_cast<PathBuilderDelegateDataImpl*>(path->delegate_data.get());
269   }
270 
271   bssl::OCSPVerifyResult stapled_ocsp_verify_result;
272   SignedCertificateTimestampAndStatusList scts;
273   ct::CTPolicyCompliance ct_policy_compliance;
274 };
275 
276 // TODO(eroman): The path building code in this file enforces its idea of weak
277 // keys, and signature algorithms, but separately cert_verify_proc.cc also
278 // checks the chains with its own policy. These policies must be aligned to
279 // give path building the best chance of finding a good path.
280 class PathBuilderDelegateImpl : public bssl::SimplePathBuilderDelegate {
281  public:
282   // Uses the default policy from bssl::SimplePathBuilderDelegate, which
283   // requires RSA keys to be at least 1024-bits large, and optionally accepts
284   // SHA1 certificates.
PathBuilderDelegateImpl(const CRLSet * crl_set,CTVerifier * ct_verifier,const CTPolicyEnforcer * ct_policy_enforcer,CertNetFetcher * net_fetcher,VerificationType verification_type,bssl::SimplePathBuilderDelegate::DigestPolicy digest_policy,int flags,const CertVerifyProcTrustStore * trust_store,const std::vector<net::CertVerifyProc::CertificateWithConstraints> & additional_constraints,std::string_view stapled_leaf_ocsp_response,std::string_view sct_list_from_tls_extension,const EVRootCAMetadata * ev_metadata,base::TimeTicks deadline,base::Time current_time,bool * checked_revocation_for_some_path,const NetLogWithSource & net_log)285   PathBuilderDelegateImpl(
286       const CRLSet* crl_set,
287       CTVerifier* ct_verifier,
288       const CTPolicyEnforcer* ct_policy_enforcer,
289       CertNetFetcher* net_fetcher,
290       VerificationType verification_type,
291       bssl::SimplePathBuilderDelegate::DigestPolicy digest_policy,
292       int flags,
293       const CertVerifyProcTrustStore* trust_store,
294       const std::vector<net::CertVerifyProc::CertificateWithConstraints>&
295           additional_constraints,
296       std::string_view stapled_leaf_ocsp_response,
297       std::string_view sct_list_from_tls_extension,
298       const EVRootCAMetadata* ev_metadata,
299       base::TimeTicks deadline,
300       base::Time current_time,
301       bool* checked_revocation_for_some_path,
302       const NetLogWithSource& net_log)
303       : bssl::SimplePathBuilderDelegate(1024, digest_policy),
304         crl_set_(crl_set),
305         ct_verifier_(ct_verifier),
306         ct_policy_enforcer_(ct_policy_enforcer),
307         net_fetcher_(net_fetcher),
308         verification_type_(verification_type),
309         flags_(flags),
310         trust_store_(trust_store),
311         additional_constraints_(additional_constraints),
312         stapled_leaf_ocsp_response_(stapled_leaf_ocsp_response),
313         sct_list_from_tls_extension_(sct_list_from_tls_extension),
314         ev_metadata_(ev_metadata),
315         deadline_(deadline),
316         current_time_(current_time),
317         checked_revocation_for_some_path_(checked_revocation_for_some_path),
318         net_log_(net_log) {}
319 
320   // This is called for each built chain, including ones which failed. It is
321   // responsible for adding errors to the built chain if it is not acceptable.
CheckPathAfterVerification(const bssl::CertPathBuilder & path_builder,bssl::CertPathBuilderResultPath * path)322   void CheckPathAfterVerification(
323       const bssl::CertPathBuilder& path_builder,
324       bssl::CertPathBuilderResultPath* path) override {
325     net_log_->BeginEvent(NetLogEventType::CERT_VERIFY_PROC_PATH_BUILT);
326 
327     CheckPathAfterVerificationImpl(path_builder, path);
328 
329     net_log_->EndEvent(NetLogEventType::CERT_VERIFY_PROC_PATH_BUILT,
330                        [&] { return NetLogPathBuilderResultPath(*path); });
331   }
332 
333  private:
CheckPathAfterVerificationImpl(const bssl::CertPathBuilder & path_builder,bssl::CertPathBuilderResultPath * path)334   void CheckPathAfterVerificationImpl(const bssl::CertPathBuilder& path_builder,
335                                       bssl::CertPathBuilderResultPath* path) {
336     PathBuilderDelegateDataImpl* delegate_data =
337         PathBuilderDelegateDataImpl::GetOrCreate(path);
338 
339     // TODO(https://crbug.com/1211074, https://crbug.com/848277): making a
340     // temporary X509Certificate just to pass into CTVerifier and
341     // CTPolicyEnforcer is silly, refactor so they take CRYPTO_BUFFER or
342     // ParsedCertificate or something.
343     std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates;
344     if (path->certs.size() > 1) {
345       intermediates.push_back(bssl::UpRef(path->certs[1]->cert_buffer()));
346     }
347     auto cert_for_ct_verify = X509Certificate::CreateFromBuffer(
348         bssl::UpRef(path->certs[0]->cert_buffer()), std::move(intermediates));
349     ct_verifier_->Verify(cert_for_ct_verify.get(), stapled_leaf_ocsp_response_,
350                          sct_list_from_tls_extension_, current_time_,
351                          &delegate_data->scts, *net_log_);
352 
353     // Check any extra constraints that might exist outside of the certificates.
354     CheckExtraConstraints(path->certs, &path->errors);
355 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
356     CheckChromeRootConstraints(path);
357 #endif
358 
359     // If the path is already invalid, don't check revocation status. The
360     // chain is expected to be valid when doing revocation checks (since for
361     // instance the correct issuer for a certificate may need to be known).
362     // Also if certificates are already expired, obtaining their revocation
363     // status may fail.
364     //
365     // TODO(eroman): When CertVerifyProcBuiltin fails to find a valid path,
366     //               whatever (partial/incomplete) path it does return should
367     //               minimally be checked with the CRLSet.
368     if (!path->IsValid()) {
369       return;
370     }
371 
372     // If EV was requested the certificate must chain to a recognized EV root
373     // and have one of its recognized EV policy OIDs.
374     if (verification_type_ == VerificationType::kEV) {
375       if (!ConformsToEVPolicy(path)) {
376         path->errors.GetErrorsForCert(0)->AddError(kPathLacksEVPolicy);
377         return;
378       }
379     }
380 
381     // Select an appropriate revocation policy for this chain based on the
382     // verifier flags and root.
383     RevocationPolicy policy = ChooseRevocationPolicy(path->certs);
384 
385     // Check for revocations using the CRLSet.
386     switch (
387         CheckChainRevocationUsingCRLSet(crl_set_, path->certs, &path->errors)) {
388       case CRLSet::Result::REVOKED:
389         return;
390       case CRLSet::Result::GOOD:
391         break;
392       case CRLSet::Result::UNKNOWN:
393         // CRLSet was inconclusive.
394         break;
395     }
396 
397     if (policy.check_revocation) {
398       *checked_revocation_for_some_path_ = true;
399     }
400 
401     // Check the revocation status for each certificate in the chain according
402     // to |policy|. Depending on the policy, errors will be added to the
403     // respective certificates, so |errors->ContainsHighSeverityErrors()| will
404     // reflect the revocation status of the chain after this call.
405     CheckValidatedChainRevocation(path->certs, policy, deadline_,
406                                   stapled_leaf_ocsp_response_, current_time_,
407                                   net_fetcher_, &path->errors,
408                                   &delegate_data->stapled_ocsp_verify_result);
409 
410     ct::SCTList verified_scts;
411     for (const auto& sct_and_status : delegate_data->scts) {
412       if (sct_and_status.status == ct::SCT_STATUS_OK) {
413         verified_scts.push_back(sct_and_status.sct);
414       }
415     }
416     delegate_data->ct_policy_compliance = ct_policy_enforcer_->CheckCompliance(
417         cert_for_ct_verify.get(), verified_scts, current_time_, *net_log_);
418   }
419 
420 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
421   // Returns the SCTs from `scts` that are verified successfully and signed by
422   // a log which was not disqualified.
ValidScts(const SignedCertificateTimestampAndStatusList & scts)423   ct::SCTList ValidScts(const SignedCertificateTimestampAndStatusList& scts) {
424     ct::SCTList valid_scts;
425     for (const auto& sct_and_status : scts) {
426       if (sct_and_status.status != ct::SCT_STATUS_OK) {
427         continue;
428       }
429       std::optional<base::Time> disqualification_time =
430           ct_policy_enforcer_->GetLogDisqualificationTime(
431               sct_and_status.sct->log_id);
432       // TODO(https://crbug.com/40840044): use the same time source here as for
433       // the rest of verification.
434       if (disqualification_time && base::Time::Now() >= disqualification_time) {
435         continue;
436       }
437       valid_scts.push_back(sct_and_status.sct);
438     }
439     return valid_scts;
440   }
441 
CheckPathSatisfiesChromeRootConstraint(bssl::CertPathBuilderResultPath * path,const ChromeRootCertConstraints & constraint)442   bool CheckPathSatisfiesChromeRootConstraint(
443       bssl::CertPathBuilderResultPath* path,
444       const ChromeRootCertConstraints& constraint) {
445     PathBuilderDelegateDataImpl* delegate_data =
446         PathBuilderDelegateDataImpl::GetOrCreate(path);
447 
448     // TODO(https://crbug.com/40941039): add more specific netlog or CertError
449     // logs about which constraint failed exactly? (Note that it could be
450     // confusing when there are multiple ChromeRootCertConstraints objects,
451     // would need to clearly distinguish which set of constraints had errors.)
452 
453     if (ct_policy_enforcer_->IsCtEnabled()) {
454       if (constraint.sct_not_after.has_value()) {
455         bool found_matching_sct = false;
456         for (const auto& sct : ValidScts(delegate_data->scts)) {
457           if (sct->timestamp <= constraint.sct_not_after.value()) {
458             found_matching_sct = true;
459             break;
460           }
461         }
462         if (!found_matching_sct) {
463           return false;
464         }
465       }
466 
467       if (constraint.sct_all_after.has_value()) {
468         ct::SCTList valid_scts = ValidScts(delegate_data->scts);
469         if (valid_scts.empty()) {
470           return false;
471         }
472         for (const auto& sct : ValidScts(delegate_data->scts)) {
473           if (sct->timestamp <= constraint.sct_all_after.value()) {
474             return false;
475           }
476         }
477       }
478     }
479 
480     if (!constraint.permitted_dns_names.empty()) {
481       bssl::GeneralNames permitted_names;
482       for (const auto& dns_name : constraint.permitted_dns_names) {
483         permitted_names.dns_names.push_back(dns_name);
484       }
485       permitted_names.present_name_types |=
486           bssl::GeneralNameTypes::GENERAL_NAME_DNS_NAME;
487 
488       std::unique_ptr<bssl::NameConstraints> nc =
489           bssl::NameConstraints::CreateFromPermittedSubtrees(
490               std::move(permitted_names));
491 
492       const std::shared_ptr<const bssl::ParsedCertificate>& leaf_cert =
493           path->certs[0];
494       bssl::CertErrors name_constraint_errors;
495       nc->IsPermittedCert(leaf_cert->normalized_subject(),
496                           leaf_cert->subject_alt_names(),
497                           &name_constraint_errors);
498       if (name_constraint_errors.ContainsAnyErrorWithSeverity(
499               bssl::CertError::SEVERITY_HIGH)) {
500         return false;
501       }
502     }
503 
504     if (constraint.min_version.has_value() &&
505         version_info::GetVersion() < constraint.min_version.value()) {
506       return false;
507     }
508 
509     if (constraint.max_version_exclusive.has_value() &&
510         version_info::GetVersion() >=
511             constraint.max_version_exclusive.value()) {
512       return false;
513     }
514 
515     return true;
516   }
517 
CheckChromeRootConstraints(bssl::CertPathBuilderResultPath * path)518   void CheckChromeRootConstraints(bssl::CertPathBuilderResultPath* path) {
519     // If the root is trusted locally, do not enforce CRS constraints, even if
520     // some exist.
521     if (trust_store_->IsNonChromeRootStoreTrustAnchor(
522             path->certs.back().get())) {
523       return;
524     }
525 
526     if (base::span<const ChromeRootCertConstraints> constraints =
527             trust_store_->GetChromeRootConstraints(path->certs.back().get());
528         !constraints.empty()) {
529       bool found_valid_constraint = false;
530       for (const ChromeRootCertConstraints& constraint : constraints) {
531         found_valid_constraint |=
532             CheckPathSatisfiesChromeRootConstraint(path, constraint);
533       }
534       if (!found_valid_constraint) {
535         path->errors.GetOtherErrors()->AddError(kChromeRootConstraintsFailed);
536       }
537     }
538   }
539 #endif
540 
541   // Check extra constraints that aren't encoded in the certificates themselves.
CheckExtraConstraints(const bssl::ParsedCertificateList & certs,bssl::CertPathErrors * errors)542   void CheckExtraConstraints(const bssl::ParsedCertificateList& certs,
543                              bssl::CertPathErrors* errors) {
544     const std::shared_ptr<const bssl::ParsedCertificate> root_cert =
545         certs.back();
546     // An assumption being made is that there will be at most a few (2-3) certs
547     // in here; if there are more and this ends up being a drag on performance
548     // it may be worth making additional_constraints_ into a map storing certs
549     // by hash.
550     for (const auto& cert_with_constraints : *additional_constraints_) {
551       if (!x509_util::CryptoBufferEqual(
552               root_cert->cert_buffer(),
553               cert_with_constraints.certificate->cert_buffer())) {
554         continue;
555       }
556       // Found the cert, check constraints
557       if (cert_with_constraints.permitted_dns_names.empty() &&
558           cert_with_constraints.permitted_cidrs.empty()) {
559         // No constraints to check.
560         return;
561       }
562 
563       bssl::GeneralNames permitted_names;
564 
565       if (!cert_with_constraints.permitted_dns_names.empty()) {
566         for (const auto& dns_name : cert_with_constraints.permitted_dns_names) {
567           permitted_names.dns_names.push_back(dns_name);
568         }
569         permitted_names.present_name_types |=
570             bssl::GeneralNameTypes::GENERAL_NAME_DNS_NAME;
571       }
572 
573       if (!cert_with_constraints.permitted_cidrs.empty()) {
574         for (const auto& cidr : cert_with_constraints.permitted_cidrs) {
575           permitted_names.ip_address_ranges.emplace_back(cidr.ip.bytes(),
576                                                          cidr.mask.bytes());
577         }
578         permitted_names.present_name_types |=
579             bssl::GeneralNameTypes::GENERAL_NAME_IP_ADDRESS;
580       }
581 
582       std::unique_ptr<bssl::NameConstraints> nc =
583           bssl::NameConstraints::CreateFromPermittedSubtrees(
584               std::move(permitted_names));
585 
586       const std::shared_ptr<const bssl::ParsedCertificate>& leaf_cert =
587           certs[0];
588 
589       nc->IsPermittedCert(leaf_cert->normalized_subject(),
590                           leaf_cert->subject_alt_names(),
591                           errors->GetErrorsForCert(0));
592       return;
593     }
594   }
595 
596   // Selects a revocation policy based on the CertVerifier flags and the given
597   // certificate chain.
ChooseRevocationPolicy(const bssl::ParsedCertificateList & certs)598   RevocationPolicy ChooseRevocationPolicy(
599       const bssl::ParsedCertificateList& certs) {
600     if (flags_ & CertVerifyProc::VERIFY_DISABLE_NETWORK_FETCHES) {
601       // In theory when network fetches are disabled but revocation is enabled
602       // we could continue with networking_allowed=false (and
603       // VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS would also have to change
604       // allow_missing_info and allow_unable_to_check to true).
605       // That theoretically could allow still consulting any cached CRLs/etc.
606       // However in the way things are currently implemented in the builtin
607       // verifier there really is no point to bothering, just disable
608       // revocation checking if network fetches are disabled.
609       return NoRevocationChecking();
610     }
611 
612     // Use hard-fail revocation checking for local trust anchors, if requested
613     // by the load flag and the chain uses a non-public root.
614     if ((flags_ & CertVerifyProc::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) &&
615         !certs.empty() && !trust_store_->IsKnownRoot(certs.back().get())) {
616       RevocationPolicy policy;
617       policy.check_revocation = true;
618       policy.networking_allowed = true;
619       policy.crl_allowed = true;
620       policy.allow_missing_info = false;
621       policy.allow_unable_to_check = false;
622       policy.enforce_baseline_requirements = false;
623       return policy;
624     }
625 
626     // Use soft-fail revocation checking for VERIFY_REV_CHECKING_ENABLED.
627     if (flags_ & CertVerifyProc::VERIFY_REV_CHECKING_ENABLED) {
628       const bool is_known_root =
629           !certs.empty() && trust_store_->IsKnownRoot(certs.back().get());
630       RevocationPolicy policy;
631       policy.check_revocation = true;
632       policy.networking_allowed = true;
633       // Publicly trusted certs are required to have OCSP by the Baseline
634       // Requirements and CRLs can be quite large, so disable the fallback to
635       // CRLs for chains to known roots.
636       policy.crl_allowed = !is_known_root;
637       policy.allow_missing_info = true;
638       policy.allow_unable_to_check = true;
639       policy.enforce_baseline_requirements = is_known_root;
640       return policy;
641     }
642 
643     return NoRevocationChecking();
644   }
645 
646   // Returns true if |path| chains to an EV root, and the chain conforms to
647   // one of its EV policy OIDs. When building paths all candidate EV policy
648   // OIDs were requested, so it is just a matter of testing each of the
649   // policies the chain conforms to.
ConformsToEVPolicy(const bssl::CertPathBuilderResultPath * path)650   bool ConformsToEVPolicy(const bssl::CertPathBuilderResultPath* path) {
651     const bssl::ParsedCertificate* root = path->GetTrustedCert();
652     if (!root) {
653       return false;
654     }
655 
656     SHA256HashValue root_fingerprint;
657     crypto::SHA256HashString(root->der_cert().AsStringView(),
658                              root_fingerprint.data,
659                              sizeof(root_fingerprint.data));
660 
661     for (const bssl::der::Input& oid : path->user_constrained_policy_set) {
662       if (ev_metadata_->HasEVPolicyOID(root_fingerprint, oid)) {
663         return true;
664       }
665     }
666 
667     return false;
668   }
669 
IsDeadlineExpired()670   bool IsDeadlineExpired() override {
671     return !deadline_.is_null() && base::TimeTicks::Now() > deadline_;
672   }
673 
IsDebugLogEnabled()674   bool IsDebugLogEnabled() override { return net_log_->IsCapturing(); }
675 
DebugLog(std::string_view msg)676   void DebugLog(std::string_view msg) override {
677     net_log_->AddEventWithStringParams(
678         NetLogEventType::CERT_VERIFY_PROC_PATH_BUILDER_DEBUG, "debug", msg);
679   }
680 
681   raw_ptr<const CRLSet> crl_set_;
682   raw_ptr<CTVerifier> ct_verifier_;
683   raw_ptr<const CTPolicyEnforcer> ct_policy_enforcer_;
684   raw_ptr<CertNetFetcher> net_fetcher_;
685   const VerificationType verification_type_;
686   const int flags_;
687   raw_ptr<const CertVerifyProcTrustStore> trust_store_;
688   raw_ref<const std::vector<net::CertVerifyProc::CertificateWithConstraints>>
689       additional_constraints_;
690   const std::string_view stapled_leaf_ocsp_response_;
691   const std::string_view sct_list_from_tls_extension_;
692   raw_ptr<const EVRootCAMetadata> ev_metadata_;
693   base::TimeTicks deadline_;
694   base::Time current_time_;
695   raw_ptr<bool> checked_revocation_for_some_path_;
696   raw_ref<const NetLogWithSource> net_log_;
697 };
698 
ParseCertificateFromBuffer(CRYPTO_BUFFER * cert_handle,bssl::CertErrors * errors)699 std::shared_ptr<const bssl::ParsedCertificate> ParseCertificateFromBuffer(
700     CRYPTO_BUFFER* cert_handle,
701     bssl::CertErrors* errors) {
702   return bssl::ParsedCertificate::Create(
703       bssl::UpRef(cert_handle), x509_util::DefaultParseCertificateOptions(),
704       errors);
705 }
706 
707 class CertVerifyProcBuiltin : public CertVerifyProc {
708  public:
709   CertVerifyProcBuiltin(scoped_refptr<CertNetFetcher> net_fetcher,
710                         scoped_refptr<CRLSet> crl_set,
711                         std::unique_ptr<CTVerifier> ct_verifier,
712                         scoped_refptr<CTPolicyEnforcer> ct_policy_enforcer,
713                         std::unique_ptr<SystemTrustStore> system_trust_store,
714                         const CertVerifyProc::InstanceParams& instance_params,
715                         std::optional<network_time::TimeTracker> time_tracker);
716 
717  protected:
718   ~CertVerifyProcBuiltin() override;
719 
720  private:
721   int VerifyInternal(X509Certificate* cert,
722                      const std::string& hostname,
723                      const std::string& ocsp_response,
724                      const std::string& sct_list,
725                      int flags,
726                      CertVerifyResult* verify_result,
727                      const NetLogWithSource& net_log) override;
728 
729   const scoped_refptr<CertNetFetcher> net_fetcher_;
730   const std::unique_ptr<CTVerifier> ct_verifier_;
731   const scoped_refptr<CTPolicyEnforcer> ct_policy_enforcer_;
732   const std::unique_ptr<SystemTrustStore> system_trust_store_;
733   std::vector<net::CertVerifyProc::CertificateWithConstraints>
734       additional_constraints_;
735   bssl::TrustStoreInMemory additional_trust_store_;
736   const std::optional<network_time::TimeTracker> time_tracker_;
737 };
738 
CertVerifyProcBuiltin(scoped_refptr<CertNetFetcher> net_fetcher,scoped_refptr<CRLSet> crl_set,std::unique_ptr<CTVerifier> ct_verifier,scoped_refptr<CTPolicyEnforcer> ct_policy_enforcer,std::unique_ptr<SystemTrustStore> system_trust_store,const CertVerifyProc::InstanceParams & instance_params,std::optional<network_time::TimeTracker> time_tracker)739 CertVerifyProcBuiltin::CertVerifyProcBuiltin(
740     scoped_refptr<CertNetFetcher> net_fetcher,
741     scoped_refptr<CRLSet> crl_set,
742     std::unique_ptr<CTVerifier> ct_verifier,
743     scoped_refptr<CTPolicyEnforcer> ct_policy_enforcer,
744     std::unique_ptr<SystemTrustStore> system_trust_store,
745     const CertVerifyProc::InstanceParams& instance_params,
746     std::optional<network_time::TimeTracker> time_tracker)
747     : CertVerifyProc(std::move(crl_set)),
748       net_fetcher_(std::move(net_fetcher)),
749       ct_verifier_(std::move(ct_verifier)),
750       ct_policy_enforcer_(std::move(ct_policy_enforcer)),
751       system_trust_store_(std::move(system_trust_store)),
752       time_tracker_(std::move(time_tracker)) {
753   DCHECK(system_trust_store_);
754 
755   NetLogWithSource net_log =
756       NetLogWithSource::Make(net::NetLogSourceType::CERT_VERIFY_PROC_CREATED);
757   net_log.BeginEvent(NetLogEventType::CERT_VERIFY_PROC_CREATED);
758 
759   // When adding additional certs from instance params, there needs to be a
760   // priority order if a cert is added with multiple different trust types.
761   //
762   // The priority is as follows:
763   //
764   //  (a) Distrusted SPKIs (though we don't check for SPKI collisions in added
765   //      certs; we rely on that to happen in path building).
766   //  (b) Trusted certs with enforced constraints both in the cert and
767   //      specified externally outside of the cert.
768   //  (c) Trusted certs with enforced constraints only within the cert.
769   //  (d) Trusted certs w/o enforced constraints.
770   //  (e) Unspecified certs.
771   //
772   //  No effort was made to categorize what applies if a cert is specified
773   //  within the same category multiple times.
774 
775   for (const auto& spki : instance_params.additional_distrusted_spkis) {
776     additional_trust_store_.AddDistrustedCertificateBySPKI(
777         std::string(base::as_string_view(spki)));
778     net_log.AddEvent(NetLogEventType::CERT_VERIFY_PROC_ADDITIONAL_CERT, [&] {
779       base::Value::Dict results;
780       results.Set("spki", NetLogBinaryValue(base::span(spki)));
781       results.Set("trust",
782                   bssl::CertificateTrust::ForDistrusted().ToDebugString());
783       return results;
784     });
785   }
786 
787   bssl::CertificateTrust anchor_trust_enforcement =
788       bssl::CertificateTrust::ForTrustAnchor()
789           .WithEnforceAnchorConstraints()
790           .WithEnforceAnchorExpiry();
791 
792   for (const auto& cert_with_constraints :
793        instance_params.additional_trust_anchors_with_constraints) {
794     const std::shared_ptr<const bssl::ParsedCertificate>& cert =
795         cert_with_constraints.certificate;
796     additional_trust_store_.AddCertificate(cert, anchor_trust_enforcement);
797     additional_constraints_.push_back(cert_with_constraints);
798     bssl::CertErrors parsing_errors;
799     net_log.AddEvent(NetLogEventType::CERT_VERIFY_PROC_ADDITIONAL_CERT, [&] {
800       return NetLogAdditionalCert(cert->cert_buffer(),
801                                   bssl::CertificateTrust::ForTrustAnchor(),
802                                   parsing_errors);
803     });
804   }
805 
806   bssl::CertificateTrust leaf_trust = bssl::CertificateTrust::ForTrustedLeaf();
807 
808   for (const auto& cert_with_possible_constraints :
809        instance_params.additional_trust_leafs) {
810     const std::shared_ptr<const bssl::ParsedCertificate>& cert =
811         cert_with_possible_constraints.certificate;
812     if (!additional_trust_store_.Contains(cert.get())) {
813       if (!cert_with_possible_constraints.permitted_dns_names.empty() ||
814           !cert_with_possible_constraints.permitted_cidrs.empty()) {
815         additional_constraints_.push_back(cert_with_possible_constraints);
816       }
817 
818       bssl::CertErrors parsing_errors;
819       additional_trust_store_.AddCertificate(cert, leaf_trust);
820       net_log.AddEvent(NetLogEventType::CERT_VERIFY_PROC_ADDITIONAL_CERT, [&] {
821         return NetLogAdditionalCert(cert->cert_buffer(), leaf_trust,
822                                     parsing_errors);
823       });
824     }
825   }
826 
827   bssl::CertificateTrust anchor_leaf_trust =
828       bssl::CertificateTrust::ForTrustAnchorOrLeaf()
829           .WithEnforceAnchorConstraints()
830           .WithEnforceAnchorExpiry();
831 
832   for (const auto& cert_with_possible_constraints :
833        instance_params.additional_trust_anchors_and_leafs) {
834     const std::shared_ptr<const bssl::ParsedCertificate>& cert =
835         cert_with_possible_constraints.certificate;
836     if (!additional_trust_store_.Contains(cert.get())) {
837       if (!cert_with_possible_constraints.permitted_dns_names.empty() ||
838           !cert_with_possible_constraints.permitted_cidrs.empty()) {
839         additional_constraints_.push_back(cert_with_possible_constraints);
840       }
841 
842       bssl::CertErrors parsing_errors;
843       additional_trust_store_.AddCertificate(cert, anchor_leaf_trust);
844       net_log.AddEvent(NetLogEventType::CERT_VERIFY_PROC_ADDITIONAL_CERT, [&] {
845         return NetLogAdditionalCert(cert->cert_buffer(), anchor_leaf_trust,
846                                     parsing_errors);
847       });
848     }
849   }
850 
851   for (const auto& cert :
852        instance_params.additional_trust_anchors_with_enforced_constraints) {
853     bssl::CertErrors parsing_errors;
854     if (!additional_trust_store_.Contains(cert.get())) {
855       additional_trust_store_.AddCertificate(cert, anchor_trust_enforcement);
856       net_log.AddEvent(NetLogEventType::CERT_VERIFY_PROC_ADDITIONAL_CERT, [&] {
857         return NetLogAdditionalCert(cert->cert_buffer(),
858                                     anchor_trust_enforcement, parsing_errors);
859       });
860     }
861   }
862 
863   for (const auto& cert : instance_params.additional_trust_anchors) {
864     bssl::CertErrors parsing_errors;
865     // Only add if it wasn't already present in `additional_trust_store_`. This
866     // is for two reasons:
867     //   (1) TrustStoreInMemory doesn't expect to contain duplicates
868     //   (2) If the same anchor is added with enforced constraints, that takes
869     //       precedence.
870     if (!additional_trust_store_.Contains(cert.get())) {
871       additional_trust_store_.AddTrustAnchor(cert);
872     }
873     net_log.AddEvent(NetLogEventType::CERT_VERIFY_PROC_ADDITIONAL_CERT, [&] {
874       return NetLogAdditionalCert(cert->cert_buffer(),
875                                   bssl::CertificateTrust::ForTrustAnchor(),
876                                   parsing_errors);
877     });
878   }
879 
880   for (const auto& cert : instance_params.additional_untrusted_authorities) {
881     bssl::CertErrors parsing_errors;
882     // Only add the untrusted cert if it isn't already present in
883     // `additional_trust_store_`. If the same cert was already added as a
884     // trust anchor then adding it again as an untrusted cert can lead to it
885     // not being treated as a trust anchor since TrustStoreInMemory doesn't
886     // expect to contain duplicates.
887     if (!additional_trust_store_.Contains(cert.get())) {
888       additional_trust_store_.AddCertificateWithUnspecifiedTrust(cert);
889     }
890     net_log.AddEvent(NetLogEventType::CERT_VERIFY_PROC_ADDITIONAL_CERT, [&] {
891       return NetLogAdditionalCert(cert->cert_buffer(),
892                                   bssl::CertificateTrust::ForUnspecified(),
893                                   parsing_errors);
894     });
895   }
896 
897   net_log.EndEvent(NetLogEventType::CERT_VERIFY_PROC_CREATED);
898 }
899 
900 CertVerifyProcBuiltin::~CertVerifyProcBuiltin() = default;
901 
AddIntermediatesToIssuerSource(X509Certificate * x509_cert,bssl::CertIssuerSourceStatic * intermediates,const NetLogWithSource & net_log)902 void AddIntermediatesToIssuerSource(X509Certificate* x509_cert,
903                                     bssl::CertIssuerSourceStatic* intermediates,
904                                     const NetLogWithSource& net_log) {
905   for (const auto& intermediate : x509_cert->intermediate_buffers()) {
906     bssl::CertErrors errors;
907     std::shared_ptr<const bssl::ParsedCertificate> cert =
908         ParseCertificateFromBuffer(intermediate.get(), &errors);
909     // TODO(crbug.com/40479281): this duplicates the logging of the input chain
910     // maybe should only log if there is a parse error/warning?
911     net_log.AddEvent(NetLogEventType::CERT_VERIFY_PROC_INPUT_CERT, [&] {
912       return NetLogCertParams(intermediate.get(), errors);
913     });
914     if (cert) {
915       intermediates->AddCert(std::move(cert));
916     }
917   }
918 }
919 
920 // Appends the SHA256 hashes of |spki_bytes| to |*hashes|.
921 // TODO(eroman): Hashes are also calculated at other times (such as when
922 //               checking CRLSet). Consider caching to avoid recalculating (say
923 //               in the delegate's PathInfo).
AppendPublicKeyHashes(const bssl::der::Input & spki_bytes,HashValueVector * hashes)924 void AppendPublicKeyHashes(const bssl::der::Input& spki_bytes,
925                            HashValueVector* hashes) {
926   HashValue sha256(HASH_VALUE_SHA256);
927   crypto::SHA256HashString(spki_bytes.AsStringView(), sha256.data(),
928                            crypto::kSHA256Length);
929   hashes->push_back(sha256);
930 }
931 
932 // Appends the SubjectPublicKeyInfo hashes for all certificates in
933 // |path| to |*hashes|.
AppendPublicKeyHashes(const bssl::CertPathBuilderResultPath & path,HashValueVector * hashes)934 void AppendPublicKeyHashes(const bssl::CertPathBuilderResultPath& path,
935                            HashValueVector* hashes) {
936   for (const std::shared_ptr<const bssl::ParsedCertificate>& cert :
937        path.certs) {
938     AppendPublicKeyHashes(cert->tbs().spki_tlv, hashes);
939   }
940 }
941 
942 // Sets the bits on |cert_status| for all the errors present in |errors| (the
943 // errors for a particular path).
MapPathBuilderErrorsToCertStatus(const bssl::CertPathErrors & errors,CertStatus * cert_status)944 void MapPathBuilderErrorsToCertStatus(const bssl::CertPathErrors& errors,
945                                       CertStatus* cert_status) {
946   // If there were no errors, nothing to do.
947   if (!errors.ContainsHighSeverityErrors())
948     return;
949 
950   if (errors.ContainsError(bssl::cert_errors::kCertificateRevoked)) {
951     *cert_status |= CERT_STATUS_REVOKED;
952   }
953 
954   if (errors.ContainsError(bssl::cert_errors::kNoRevocationMechanism)) {
955     *cert_status |= CERT_STATUS_NO_REVOCATION_MECHANISM;
956   }
957 
958   if (errors.ContainsError(bssl::cert_errors::kUnableToCheckRevocation)) {
959     *cert_status |= CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
960   }
961 
962   if (errors.ContainsError(bssl::cert_errors::kUnacceptablePublicKey)) {
963     *cert_status |= CERT_STATUS_WEAK_KEY;
964   }
965 
966   if (errors.ContainsError(bssl::cert_errors::kValidityFailedNotAfter) ||
967       errors.ContainsError(bssl::cert_errors::kValidityFailedNotBefore)) {
968     *cert_status |= CERT_STATUS_DATE_INVALID;
969   }
970 
971   if (errors.ContainsError(bssl::cert_errors::kDistrustedByTrustStore) ||
972       errors.ContainsError(bssl::cert_errors::kVerifySignedDataFailed) ||
973       errors.ContainsError(bssl::cert_errors::kNoIssuersFound) ||
974       errors.ContainsError(bssl::cert_errors::kSubjectDoesNotMatchIssuer) ||
975       errors.ContainsError(bssl::cert_errors::kDeadlineExceeded) ||
976       errors.ContainsError(bssl::cert_errors::kIterationLimitExceeded) ||
977       errors.ContainsError(kChromeRootConstraintsFailed)) {
978     *cert_status |= CERT_STATUS_AUTHORITY_INVALID;
979   }
980 
981   // IMPORTANT: If the path was invalid for a reason that was not
982   // explicity checked above, set a general error. This is important as
983   // |cert_status| is what ultimately indicates whether verification was
984   // successful or not (absence of errors implies success).
985   if (!IsCertStatusError(*cert_status))
986     *cert_status |= CERT_STATUS_INVALID;
987 }
988 
989 // Creates a X509Certificate (chain) to return as the verified result.
990 //
991 //  * |target_cert|: The original X509Certificate that was passed in to
992 //                   VerifyInternal()
993 //  * |path|: The result (possibly failed) from path building.
CreateVerifiedCertChain(X509Certificate * target_cert,const bssl::CertPathBuilderResultPath & path)994 scoped_refptr<X509Certificate> CreateVerifiedCertChain(
995     X509Certificate* target_cert,
996     const bssl::CertPathBuilderResultPath& path) {
997   std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates;
998 
999   // Skip the first certificate in the path as that is the target certificate
1000   for (size_t i = 1; i < path.certs.size(); ++i) {
1001     intermediates.push_back(bssl::UpRef(path.certs[i]->cert_buffer()));
1002   }
1003 
1004   scoped_refptr<X509Certificate> result =
1005       target_cert->CloneWithDifferentIntermediates(std::move(intermediates));
1006   DCHECK(result);
1007 
1008   return result;
1009 }
1010 
1011 // Describes the parameters for a single path building attempt. Path building
1012 // may be re-tried with different parameters for EV and for accepting SHA1
1013 // certificates.
1014 struct BuildPathAttempt {
BuildPathAttemptnet::__anonb619077d0111::BuildPathAttempt1015   BuildPathAttempt(VerificationType verification_type,
1016                    bssl::SimplePathBuilderDelegate::DigestPolicy digest_policy,
1017                    bool use_system_time)
1018       : verification_type(verification_type),
1019         digest_policy(digest_policy),
1020         use_system_time(use_system_time) {}
1021 
BuildPathAttemptnet::__anonb619077d0111::BuildPathAttempt1022   BuildPathAttempt(VerificationType verification_type, bool use_system_time)
1023       : BuildPathAttempt(verification_type,
1024                          bssl::SimplePathBuilderDelegate::DigestPolicy::kStrong,
1025                          use_system_time) {}
1026 
1027   VerificationType verification_type;
1028   bssl::SimplePathBuilderDelegate::DigestPolicy digest_policy;
1029   bool use_system_time;
1030 };
1031 
TryBuildPath(const std::shared_ptr<const bssl::ParsedCertificate> & target,bssl::CertIssuerSourceStatic * intermediates,CertVerifyProcTrustStore * trust_store,const std::vector<net::CertVerifyProc::CertificateWithConstraints> & additional_constraints,const bssl::der::GeneralizedTime & der_verification_time,base::Time current_time,base::TimeTicks deadline,VerificationType verification_type,bssl::SimplePathBuilderDelegate::DigestPolicy digest_policy,int flags,std::string_view ocsp_response,std::string_view sct_list,const CRLSet * crl_set,CTVerifier * ct_verifier,const CTPolicyEnforcer * ct_policy_enforcer,CertNetFetcher * net_fetcher,const EVRootCAMetadata * ev_metadata,bool * checked_revocation,const NetLogWithSource & net_log)1032 bssl::CertPathBuilder::Result TryBuildPath(
1033     const std::shared_ptr<const bssl::ParsedCertificate>& target,
1034     bssl::CertIssuerSourceStatic* intermediates,
1035     CertVerifyProcTrustStore* trust_store,
1036     const std::vector<net::CertVerifyProc::CertificateWithConstraints>&
1037         additional_constraints,
1038     const bssl::der::GeneralizedTime& der_verification_time,
1039     base::Time current_time,
1040     base::TimeTicks deadline,
1041     VerificationType verification_type,
1042     bssl::SimplePathBuilderDelegate::DigestPolicy digest_policy,
1043     int flags,
1044     std::string_view ocsp_response,
1045     std::string_view sct_list,
1046     const CRLSet* crl_set,
1047     CTVerifier* ct_verifier,
1048     const CTPolicyEnforcer* ct_policy_enforcer,
1049     CertNetFetcher* net_fetcher,
1050     const EVRootCAMetadata* ev_metadata,
1051     bool* checked_revocation,
1052     const NetLogWithSource& net_log) {
1053   // Path building will require candidate paths to conform to at least one of
1054   // the policies in |user_initial_policy_set|.
1055   std::set<bssl::der::Input> user_initial_policy_set;
1056 
1057   if (verification_type == VerificationType::kEV) {
1058     GetEVPolicyOids(ev_metadata, target.get(), &user_initial_policy_set);
1059     // TODO(crbug.com/40479281): netlog user_initial_policy_set.
1060   } else {
1061     user_initial_policy_set = {bssl::der::Input(bssl::kAnyPolicyOid)};
1062   }
1063 
1064   PathBuilderDelegateImpl path_builder_delegate(
1065       crl_set, ct_verifier, ct_policy_enforcer, net_fetcher, verification_type,
1066       digest_policy, flags, trust_store, additional_constraints, ocsp_response,
1067       sct_list, ev_metadata, deadline, current_time, checked_revocation,
1068       net_log);
1069 
1070   std::optional<CertIssuerSourceAia> aia_cert_issuer_source;
1071 
1072   // Initialize the path builder.
1073   bssl::CertPathBuilder path_builder(
1074       target, trust_store->trust_store(), &path_builder_delegate,
1075       der_verification_time, bssl::KeyPurpose::SERVER_AUTH,
1076       bssl::InitialExplicitPolicy::kFalse, user_initial_policy_set,
1077       bssl::InitialPolicyMappingInhibit::kFalse,
1078       bssl::InitialAnyPolicyInhibit::kFalse);
1079 
1080   // Allow the path builder to discover the explicitly provided intermediates in
1081   // |input_cert|.
1082   path_builder.AddCertIssuerSource(intermediates);
1083 
1084   // Allow the path builder to discover intermediates through AIA fetching.
1085   // TODO(crbug.com/40479281): hook up netlog to AIA.
1086   if (!(flags & CertVerifyProc::VERIFY_DISABLE_NETWORK_FETCHES)) {
1087     if (net_fetcher) {
1088       aia_cert_issuer_source.emplace(net_fetcher);
1089       path_builder.AddCertIssuerSource(&aia_cert_issuer_source.value());
1090     } else {
1091       VLOG(1) << "No net_fetcher for performing AIA chasing.";
1092     }
1093   }
1094 
1095   path_builder.SetIterationLimit(kPathBuilderIterationLimit);
1096 
1097   return path_builder.Run();
1098 }
1099 
AssignVerifyResult(X509Certificate * input_cert,const std::string & hostname,bssl::CertPathBuilder::Result & result,VerificationType verification_type,bool checked_revocation_for_some_path,CertVerifyProcTrustStore * trust_store,CertVerifyResult * verify_result)1100 int AssignVerifyResult(X509Certificate* input_cert,
1101                        const std::string& hostname,
1102                        bssl::CertPathBuilder::Result& result,
1103                        VerificationType verification_type,
1104                        bool checked_revocation_for_some_path,
1105                        CertVerifyProcTrustStore* trust_store,
1106                        CertVerifyResult* verify_result) {
1107   const bssl::CertPathBuilderResultPath* best_path_possibly_invalid =
1108       result.GetBestPathPossiblyInvalid();
1109 
1110   if (!best_path_possibly_invalid) {
1111     // TODO(crbug.com/41267838): What errors to communicate? Maybe the path
1112     // builder should always return some partial path (even if just containing
1113     // the target), then there is a bssl::CertErrors to test.
1114     verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
1115     return ERR_CERT_AUTHORITY_INVALID;
1116   }
1117 
1118   const bssl::CertPathBuilderResultPath& partial_path =
1119       *best_path_possibly_invalid;
1120 
1121   AppendPublicKeyHashes(partial_path, &verify_result->public_key_hashes);
1122 
1123   bool path_is_valid = partial_path.IsValid();
1124 
1125   const bssl::ParsedCertificate* trusted_cert = partial_path.GetTrustedCert();
1126   if (trusted_cert) {
1127     verify_result->is_issued_by_known_root =
1128         trust_store->IsKnownRoot(trusted_cert);
1129 
1130     verify_result->is_issued_by_additional_trust_anchor =
1131         trust_store->IsAdditionalTrustAnchor(trusted_cert);
1132   }
1133 
1134   if (path_is_valid && (verification_type == VerificationType::kEV)) {
1135     verify_result->cert_status |= CERT_STATUS_IS_EV;
1136   }
1137 
1138   // TODO(eroman): Add documentation for the meaning of
1139   // CERT_STATUS_REV_CHECKING_ENABLED. Based on the current tests it appears to
1140   // mean whether revocation checking was attempted during path building,
1141   // although does not necessarily mean that revocation checking was done for
1142   // the final returned path.
1143   if (checked_revocation_for_some_path)
1144     verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
1145 
1146   verify_result->verified_cert =
1147       CreateVerifiedCertChain(input_cert, partial_path);
1148 
1149   MapPathBuilderErrorsToCertStatus(partial_path.errors,
1150                                    &verify_result->cert_status);
1151 
1152   // TODO(eroman): Is it possible that IsValid() fails but no errors were set in
1153   // partial_path.errors?
1154   CHECK(path_is_valid || IsCertStatusError(verify_result->cert_status));
1155 
1156   if (!path_is_valid) {
1157     VLOG(1) << "CertVerifyProcBuiltin for " << hostname << " failed:\n"
1158             << partial_path.errors.ToDebugString(partial_path.certs);
1159   }
1160 
1161   const PathBuilderDelegateDataImpl* delegate_data =
1162       PathBuilderDelegateDataImpl::Get(partial_path);
1163   if (delegate_data) {
1164     verify_result->ocsp_result = delegate_data->stapled_ocsp_verify_result;
1165     verify_result->scts = std::move(delegate_data->scts);
1166     verify_result->policy_compliance = delegate_data->ct_policy_compliance;
1167   }
1168 
1169   return IsCertStatusError(verify_result->cert_status)
1170              ? MapCertStatusToNetError(verify_result->cert_status)
1171              : OK;
1172 }
1173 
1174 // Returns true if retrying path building with a less stringent signature
1175 // algorithm *might* successfully build a path, based on the earlier failed
1176 // |result|.
1177 //
1178 // This implementation is simplistic, and looks only for the presence of the
1179 // kUnacceptableSignatureAlgorithm error somewhere among the built paths.
CanTryAgainWithWeakerDigestPolicy(const bssl::CertPathBuilder::Result & result)1180 bool CanTryAgainWithWeakerDigestPolicy(
1181     const bssl::CertPathBuilder::Result& result) {
1182   return result.AnyPathContainsError(
1183       bssl::cert_errors::kUnacceptableSignatureAlgorithm);
1184 }
1185 
1186 // Returns true if retrying with the system time as the verification time might
1187 // successfully build a path, based on the earlier failed |result|.
CanTryAgainWithSystemTime(const bssl::CertPathBuilder::Result & result)1188 bool CanTryAgainWithSystemTime(const bssl::CertPathBuilder::Result& result) {
1189   // TODO(crbug.com/363034686): Retries should also be triggered for CT
1190   // failures.
1191   return result.AnyPathContainsError(
1192              bssl::cert_errors::kValidityFailedNotAfter) ||
1193          result.AnyPathContainsError(
1194              bssl::cert_errors::kValidityFailedNotBefore) ||
1195          result.AnyPathContainsError(bssl::cert_errors::kCertificateRevoked) ||
1196          result.AnyPathContainsError(
1197              bssl::cert_errors::kUnableToCheckRevocation);
1198 }
1199 
VerifyInternal(X509Certificate * input_cert,const std::string & hostname,const std::string & ocsp_response,const std::string & sct_list,int flags,CertVerifyResult * verify_result,const NetLogWithSource & net_log)1200 int CertVerifyProcBuiltin::VerifyInternal(X509Certificate* input_cert,
1201                                           const std::string& hostname,
1202                                           const std::string& ocsp_response,
1203                                           const std::string& sct_list,
1204                                           int flags,
1205                                           CertVerifyResult* verify_result,
1206                                           const NetLogWithSource& net_log) {
1207   base::TimeTicks deadline = base::TimeTicks::Now() + kMaxVerificationTime;
1208   bssl::der::GeneralizedTime der_verification_system_time;
1209   bssl::der::GeneralizedTime der_verification_custom_time;
1210   if (!EncodeTimeAsGeneralizedTime(base::Time::Now(),
1211                                    &der_verification_system_time)) {
1212     // This shouldn't be possible.
1213     // We don't really have a good error code for this type of error.
1214     verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
1215     return ERR_CERT_AUTHORITY_INVALID;
1216   }
1217   bool custom_time_available = false;
1218   base::Time custom_time;
1219   if (time_tracker_.has_value()) {
1220     custom_time_available = time_tracker_->GetTime(
1221         base::Time::Now(), base::TimeTicks::Now(), &custom_time, nullptr);
1222     if (custom_time_available &&
1223         !EncodeTimeAsGeneralizedTime(custom_time,
1224                                      &der_verification_custom_time)) {
1225       // This shouldn't be possible, but if it somehow happens, just use system
1226       // time.
1227       custom_time_available = false;
1228     }
1229   }
1230 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
1231   int64_t chrome_root_store_version =
1232       system_trust_store_->chrome_root_store_version();
1233   if (chrome_root_store_version != 0) {
1234     net_log.AddEvent(
1235         NetLogEventType::CERT_VERIFY_PROC_CHROME_ROOT_STORE_VERSION, [&] {
1236           return NetLogChromeRootStoreVersion(chrome_root_store_version);
1237         });
1238   }
1239 #endif
1240 
1241   // TODO(crbug.com/40928765): Netlog extra configuration information stored
1242   // inside CertVerifyProcBuiltin (e.g. certs in additional_trust_store and
1243   // system trust store)
1244 
1245   // Parse the target certificate.
1246   std::shared_ptr<const bssl::ParsedCertificate> target;
1247   {
1248     bssl::CertErrors parsing_errors;
1249     target =
1250         ParseCertificateFromBuffer(input_cert->cert_buffer(), &parsing_errors);
1251     // TODO(crbug.com/40479281): this duplicates the logging of the input chain
1252     // maybe should only log if there is a parse error/warning?
1253     net_log.AddEvent(NetLogEventType::CERT_VERIFY_PROC_TARGET_CERT, [&] {
1254       return NetLogCertParams(input_cert->cert_buffer(), parsing_errors);
1255     });
1256     if (!target) {
1257       verify_result->cert_status |= CERT_STATUS_INVALID;
1258       return ERR_CERT_INVALID;
1259     }
1260   }
1261 
1262   // Parse the provided intermediates.
1263   bssl::CertIssuerSourceStatic intermediates;
1264   AddIntermediatesToIssuerSource(input_cert, &intermediates, net_log);
1265 
1266   CertVerifyProcTrustStore trust_store(system_trust_store_.get(),
1267                                        &additional_trust_store_);
1268 
1269   // Get the global dependencies.
1270   const EVRootCAMetadata* ev_metadata = EVRootCAMetadata::GetInstance();
1271 
1272   // This boolean tracks whether online revocation checking was performed for
1273   // *any* of the built paths, and not just the final path returned (used for
1274   // setting output flag CERT_STATUS_REV_CHECKING_ENABLED).
1275   bool checked_revocation_for_some_path = false;
1276 
1277   // Run path building with the different parameters (attempts) until a valid
1278   // path is found. Earlier successful attempts have priority over later
1279   // attempts.
1280   //
1281   // Attempts are enqueued into |attempts| and drained in FIFO order.
1282   std::vector<BuildPathAttempt> attempts;
1283 
1284   // First try EV validation. Can skip this if the leaf certificate has no
1285   // chance of verifying as EV (lacks an EV policy).
1286   if (IsEVCandidate(ev_metadata, target.get()))
1287     attempts.emplace_back(VerificationType::kEV, !custom_time_available);
1288 
1289   // Next try DV validation.
1290   attempts.emplace_back(VerificationType::kDV, !custom_time_available);
1291 
1292   bssl::CertPathBuilder::Result result;
1293   VerificationType verification_type = VerificationType::kDV;
1294 
1295   // Iterate over |attempts| until there are none left to try, or an attempt
1296   // succeeded.
1297   for (size_t cur_attempt_index = 0; cur_attempt_index < attempts.size();
1298        ++cur_attempt_index) {
1299     const auto& cur_attempt = attempts[cur_attempt_index];
1300     verification_type = cur_attempt.verification_type;
1301     net_log.BeginEvent(
1302         NetLogEventType::CERT_VERIFY_PROC_PATH_BUILD_ATTEMPT, [&] {
1303           base::Value::Dict results;
1304           if (verification_type == VerificationType::kEV)
1305             results.Set("is_ev_attempt", true);
1306           results.Set("is_network_time_attempt", !cur_attempt.use_system_time);
1307           if (!cur_attempt.use_system_time) {
1308             results.Set(
1309                 "network_time_value",
1310                 NetLogNumberValue(custom_time.InMillisecondsSinceUnixEpoch()));
1311           }
1312           results.Set("digest_policy",
1313                       static_cast<int>(cur_attempt.digest_policy));
1314           return results;
1315         });
1316 
1317     // If a previous attempt used up most/all of the deadline, extend the
1318     // deadline a little bit to give this verification attempt a chance at
1319     // success.
1320     deadline = std::max(
1321         deadline, base::TimeTicks::Now() + kPerAttemptMinVerificationTimeLimit);
1322 
1323     // Run the attempt through the path builder.
1324     result = TryBuildPath(
1325         target, &intermediates, &trust_store, additional_constraints_,
1326         cur_attempt.use_system_time ? der_verification_system_time
1327                                     : der_verification_custom_time,
1328         cur_attempt.use_system_time ? base::Time::Now() : custom_time, deadline,
1329         cur_attempt.verification_type, cur_attempt.digest_policy, flags,
1330         ocsp_response, sct_list, crl_set(), ct_verifier_.get(),
1331         ct_policy_enforcer_.get(), net_fetcher_.get(), ev_metadata,
1332         &checked_revocation_for_some_path, net_log);
1333 
1334     net_log.EndEvent(NetLogEventType::CERT_VERIFY_PROC_PATH_BUILD_ATTEMPT,
1335                      [&] { return NetLogPathBuilderResult(result); });
1336 
1337     if (result.HasValidPath())
1338       break;
1339 
1340     if (result.exceeded_deadline) {
1341       // Stop immediately if an attempt exceeds the deadline.
1342       break;
1343     }
1344 
1345     if (!cur_attempt.use_system_time && CanTryAgainWithSystemTime(result)) {
1346       BuildPathAttempt system_time_attempt = cur_attempt;
1347       system_time_attempt.use_system_time = true;
1348       attempts.push_back(system_time_attempt);
1349     } else if (cur_attempt.digest_policy ==
1350                    bssl::SimplePathBuilderDelegate::DigestPolicy::kStrong &&
1351                CanTryAgainWithWeakerDigestPolicy(result)) {
1352       // If this path building attempt (may have) failed due to the chain using
1353       // a
1354       // weak signature algorithm, enqueue a similar attempt but with weaker
1355       // signature algorithms (SHA1) permitted.
1356       //
1357       // This fallback is necessary because the CertVerifyProc layer may decide
1358       // to allow SHA1 based on its own policy, so path building should return
1359       // possibly weak chains too.
1360       //
1361       // TODO(eroman): Would be better for the SHA1 policy to be part of the
1362       // delegate instead so it can interact with path building.
1363       BuildPathAttempt sha1_fallback_attempt = cur_attempt;
1364       sha1_fallback_attempt.digest_policy =
1365           bssl::SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1;
1366       attempts.push_back(sha1_fallback_attempt);
1367     }
1368   }
1369 
1370   // Write the results to |*verify_result|.
1371   int error = AssignVerifyResult(
1372       input_cert, hostname, result, verification_type,
1373       checked_revocation_for_some_path, &trust_store, verify_result);
1374   if (error == OK) {
1375     LogNameNormalizationMetrics(".Builtin", verify_result->verified_cert.get(),
1376                                 verify_result->is_issued_by_known_root);
1377   }
1378   return error;
1379 }
1380 
1381 }  // namespace
1382 
CreateCertVerifyProcBuiltin(scoped_refptr<CertNetFetcher> net_fetcher,scoped_refptr<CRLSet> crl_set,std::unique_ptr<CTVerifier> ct_verifier,scoped_refptr<CTPolicyEnforcer> ct_policy_enforcer,std::unique_ptr<SystemTrustStore> system_trust_store,const CertVerifyProc::InstanceParams & instance_params,std::optional<network_time::TimeTracker> time_tracker)1383 scoped_refptr<CertVerifyProc> CreateCertVerifyProcBuiltin(
1384     scoped_refptr<CertNetFetcher> net_fetcher,
1385     scoped_refptr<CRLSet> crl_set,
1386     std::unique_ptr<CTVerifier> ct_verifier,
1387     scoped_refptr<CTPolicyEnforcer> ct_policy_enforcer,
1388     std::unique_ptr<SystemTrustStore> system_trust_store,
1389     const CertVerifyProc::InstanceParams& instance_params,
1390     std::optional<network_time::TimeTracker> time_tracker) {
1391   return base::MakeRefCounted<CertVerifyProcBuiltin>(
1392       std::move(net_fetcher), std::move(crl_set), std::move(ct_verifier),
1393       std::move(ct_policy_enforcer), std::move(system_trust_store),
1394       instance_params, std::move(time_tracker));
1395 }
1396 
GetCertVerifyProcBuiltinTimeLimitForTesting()1397 base::TimeDelta GetCertVerifyProcBuiltinTimeLimitForTesting() {
1398   return kMaxVerificationTime;
1399 }
1400 
1401 }  // namespace net
1402