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