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