• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 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.h"
6 
7 #include <stdint.h>
8 
9 #include <algorithm>
10 #include <optional>
11 #include <string_view>
12 
13 #include "base/containers/flat_set.h"
14 #include "base/containers/span.h"
15 #include "base/memory/raw_span.h"
16 #include "base/metrics/histogram.h"
17 #include "base/metrics/histogram_functions.h"
18 #include "base/metrics/histogram_macros.h"
19 #include "base/notreached.h"
20 #include "base/strings/strcat.h"
21 #include "base/strings/string_util.h"
22 #include "base/strings/stringprintf.h"
23 #include "base/threading/scoped_blocking_call.h"
24 #include "base/time/time.h"
25 #include "build/build_config.h"
26 #include "crypto/crypto_buildflags.h"
27 #include "crypto/sha2.h"
28 #include "net/base/cronet_buildflags.h"
29 #include "net/base/features.h"
30 #include "net/base/net_errors.h"
31 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
32 #include "net/base/url_util.h"
33 #include "net/cert/asn1_util.h"
34 #include "net/cert/cert_net_fetcher.h"
35 #include "net/cert/cert_status_flags.h"
36 #include "net/cert/cert_verifier.h"
37 #include "net/cert/cert_verify_result.h"
38 #include "net/cert/crl_set.h"
39 #include "net/cert/internal/revocation_checker.h"
40 #include "net/cert/internal/system_trust_store.h"
41 #include "net/cert/known_roots.h"
42 #include "net/cert/symantec_certs.h"
43 #include "net/cert/x509_certificate.h"
44 #include "net/cert/x509_certificate_net_log_param.h"
45 #include "net/cert/x509_util.h"
46 #include "net/log/net_log_event_type.h"
47 #include "net/log/net_log_values.h"
48 #include "net/log/net_log_with_source.h"
49 #include "third_party/boringssl/src/include/openssl/pool.h"
50 #include "third_party/boringssl/src/pki/encode_values.h"
51 #include "third_party/boringssl/src/pki/extended_key_usage.h"
52 #include "third_party/boringssl/src/pki/ocsp.h"
53 #include "third_party/boringssl/src/pki/ocsp_revocation_status.h"
54 #include "third_party/boringssl/src/pki/parse_certificate.h"
55 #include "third_party/boringssl/src/pki/pem.h"
56 #include "third_party/boringssl/src/pki/signature_algorithm.h"
57 #include "url/url_canon.h"
58 
59 #if BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
60 #include "net/cert/cert_verify_proc_builtin.h"
61 #endif
62 
63 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
64 #include "net/cert/internal/trust_store_chrome.h"
65 #endif  // CHROME_ROOT_STORE_SUPPORTED
66 
67 #if BUILDFLAG(IS_ANDROID)
68 #include "net/cert/cert_verify_proc_android.h"
69 #elif BUILDFLAG(IS_IOS)
70 #include "net/cert/cert_verify_proc_ios.h"
71 #endif
72 
73 namespace net {
74 
75 namespace {
76 
77 // Constants used to build histogram names
78 const char kLeafCert[] = "Leaf";
79 const char kIntermediateCert[] = "Intermediate";
80 const char kRootCert[] = "Root";
81 
82 // Histogram buckets for RSA key sizes, as well as unknown key types. RSA key
83 // sizes < 1024 bits should cause errors, while key sizes > 16K are not
84 // supported by BoringSSL.
85 const int kRsaKeySizes[] = {512,  768,  1024, 1536, 2048,
86                             3072, 4096, 8192, 16384};
87 // Histogram buckets for ECDSA key sizes. The list was historically based upon
88 // FIPS 186-4 approved curves, but most are impossible. BoringSSL will only ever
89 // return P-224, P-256, P-384, or P-521, and the verifier will reject P-224.
90 const int kEcdsaKeySizes[] = {163, 192, 224, 233, 256, 283, 384, 409, 521, 571};
91 
CertTypeToString(X509Certificate::PublicKeyType cert_type)92 const char* CertTypeToString(X509Certificate::PublicKeyType cert_type) {
93   switch (cert_type) {
94     case X509Certificate::kPublicKeyTypeUnknown:
95       return "Unknown";
96     case X509Certificate::kPublicKeyTypeRSA:
97       return "RSA";
98     case X509Certificate::kPublicKeyTypeECDSA:
99       return "ECDSA";
100   }
101   NOTREACHED();
102 }
103 
RecordPublicKeyHistogram(const char * chain_position,bool baseline_keysize_applies,size_t size_bits,X509Certificate::PublicKeyType cert_type)104 void RecordPublicKeyHistogram(const char* chain_position,
105                               bool baseline_keysize_applies,
106                               size_t size_bits,
107                               X509Certificate::PublicKeyType cert_type) {
108   std::string histogram_name =
109       base::StringPrintf("CertificateType2.%s.%s.%s",
110                          baseline_keysize_applies ? "BR" : "NonBR",
111                          chain_position,
112                          CertTypeToString(cert_type));
113   // Do not use UMA_HISTOGRAM_... macros here, as it caches the Histogram
114   // instance and thus only works if |histogram_name| is constant.
115   base::HistogramBase* counter = nullptr;
116 
117   // Histogram buckets are contingent upon the underlying algorithm being used.
118   switch (cert_type) {
119     case X509Certificate::kPublicKeyTypeECDSA:
120       counter = base::CustomHistogram::FactoryGet(
121           histogram_name,
122           base::CustomHistogram::ArrayToCustomEnumRanges(kEcdsaKeySizes),
123           base::HistogramBase::kUmaTargetedHistogramFlag);
124       break;
125     case X509Certificate::kPublicKeyTypeRSA:
126     case X509Certificate::kPublicKeyTypeUnknown:
127       counter = base::CustomHistogram::FactoryGet(
128           histogram_name,
129           base::CustomHistogram::ArrayToCustomEnumRanges(kRsaKeySizes),
130           base::HistogramBase::kUmaTargetedHistogramFlag);
131       break;
132   }
133   counter->Add(size_bits);
134 }
135 
136 // Returns true if |type| is |kPublicKeyTypeRSA| and if |size_bits| is < 1024.
137 // Note that this means there may be false negatives: keys for other algorithms
138 // and which are weak will pass this test.
IsWeakKey(X509Certificate::PublicKeyType type,size_t size_bits)139 bool IsWeakKey(X509Certificate::PublicKeyType type, size_t size_bits) {
140   switch (type) {
141     case X509Certificate::kPublicKeyTypeRSA:
142       return size_bits < 1024;
143     default:
144       return false;
145   }
146 }
147 
148 // Returns true if |cert| contains a known-weak key. Additionally, histograms
149 // the observed keys for future tightening of the definition of what
150 // constitutes a weak key.
ExaminePublicKeys(const scoped_refptr<X509Certificate> & cert,bool should_histogram)151 bool ExaminePublicKeys(const scoped_refptr<X509Certificate>& cert,
152                        bool should_histogram) {
153   // The effective date of the CA/Browser Forum's Baseline Requirements -
154   // 2012-07-01 00:00:00 UTC.
155   const base::Time kBaselineEffectiveDate =
156       base::Time::FromInternalValue(INT64_C(12985574400000000));
157   // The effective date of the key size requirements from Appendix A, v1.1.5
158   // 2014-01-01 00:00:00 UTC.
159   const base::Time kBaselineKeysizeEffectiveDate =
160       base::Time::FromInternalValue(INT64_C(13033008000000000));
161 
162   size_t size_bits = 0;
163   X509Certificate::PublicKeyType type = X509Certificate::kPublicKeyTypeUnknown;
164   bool weak_key = false;
165   bool baseline_keysize_applies =
166       cert->valid_start() >= kBaselineEffectiveDate &&
167       cert->valid_expiry() >= kBaselineKeysizeEffectiveDate;
168 
169   X509Certificate::GetPublicKeyInfo(cert->cert_buffer(), &size_bits, &type);
170   if (should_histogram) {
171     RecordPublicKeyHistogram(kLeafCert, baseline_keysize_applies, size_bits,
172                              type);
173   }
174   if (IsWeakKey(type, size_bits))
175     weak_key = true;
176 
177   const std::vector<bssl::UniquePtr<CRYPTO_BUFFER>>& intermediates =
178       cert->intermediate_buffers();
179   for (size_t i = 0; i < intermediates.size(); ++i) {
180     X509Certificate::GetPublicKeyInfo(intermediates[i].get(), &size_bits,
181                                       &type);
182     if (should_histogram) {
183       RecordPublicKeyHistogram(
184           (i < intermediates.size() - 1) ? kIntermediateCert : kRootCert,
185           baseline_keysize_applies,
186           size_bits,
187           type);
188     }
189     if (!weak_key && IsWeakKey(type, size_bits))
190       weak_key = true;
191   }
192 
193   return weak_key;
194 }
195 
BestEffortCheckOCSP(const std::string & raw_response,const X509Certificate & certificate,bssl::OCSPVerifyResult * verify_result)196 void BestEffortCheckOCSP(const std::string& raw_response,
197                          const X509Certificate& certificate,
198                          bssl::OCSPVerifyResult* verify_result) {
199   if (raw_response.empty()) {
200     *verify_result = bssl::OCSPVerifyResult();
201     verify_result->response_status = bssl::OCSPVerifyResult::MISSING;
202     return;
203   }
204 
205   std::string_view cert_der =
206       x509_util::CryptoBufferAsStringPiece(certificate.cert_buffer());
207 
208   // Try to get the certificate that signed |certificate|. This will run into
209   // problems if the CertVerifyProc implementation doesn't return the ordered
210   // certificates. If that happens the OCSP verification may be incorrect.
211   std::string_view issuer_der;
212   if (certificate.intermediate_buffers().empty()) {
213     if (X509Certificate::IsSelfSigned(certificate.cert_buffer())) {
214       issuer_der = cert_der;
215     } else {
216       // A valid cert chain wasn't provided.
217       *verify_result = bssl::OCSPVerifyResult();
218       return;
219     }
220   } else {
221     issuer_der = x509_util::CryptoBufferAsStringPiece(
222         certificate.intermediate_buffers().front().get());
223   }
224 
225   verify_result->revocation_status = bssl::CheckOCSP(
226       raw_response, cert_der, issuer_der, base::Time::Now().ToTimeT(),
227       kMaxRevocationLeafUpdateAge.InSeconds(), &verify_result->response_status);
228 }
229 
230 // Records details about the most-specific trust anchor in |hashes|, which is
231 // expected to be ordered with the leaf cert first and the root cert last.
232 // "Most-specific" refers to the case that it is not uncommon to have multiple
233 // potential trust anchors present in a chain, depending on the client trust
234 // store. For example, '1999-Root' cross-signing '2005-Root' cross-signing
235 // '2012-Root' cross-signing '2017-Root', then followed by intermediate and
236 // leaf. For purposes of assessing impact of, say, removing 1999-Root, while
237 // including 2017-Root as a trust anchor, then the validation should be
238 // counted as 2017-Root, rather than 1999-Root.
239 //
240 // This also accounts for situations in which a new CA is introduced, and
241 // has been cross-signed by an existing CA. Assessing impact should use the
242 // most-specific trust anchor, when possible.
243 //
244 // This also histograms for divergence between the root store and
245 // |spki_hashes| - that is, situations in which the OS methods of detecting
246 // a known root flag a certificate as known, but its hash is not known as part
247 // of the built-in list.
RecordTrustAnchorHistogram(const HashValueVector & spki_hashes,bool is_issued_by_known_root)248 void RecordTrustAnchorHistogram(const HashValueVector& spki_hashes,
249                                 bool is_issued_by_known_root) {
250   int32_t id = 0;
251   for (const auto& hash : spki_hashes) {
252     id = GetNetTrustAnchorHistogramIdForSPKI(hash);
253     if (id != 0)
254       break;
255   }
256   base::UmaHistogramSparse("Net.Certificate.TrustAnchor.Verify", id);
257 
258   // Record when a known trust anchor is not found within the chain, but the
259   // certificate is flagged as being from a known root (meaning a fallback to
260   // OS-based methods of determination).
261   if (id == 0) {
262     UMA_HISTOGRAM_BOOLEAN("Net.Certificate.TrustAnchor.VerifyOutOfDate",
263                           is_issued_by_known_root);
264   }
265 }
266 
267 // Inspects the signature algorithms in a single certificate |cert|.
268 //
269 //   * Sets |verify_result->has_sha1| to true if the certificate uses SHA1.
270 //
271 // Returns false if the signature algorithm was unknown or mismatched.
InspectSignatureAlgorithmForCert(const CRYPTO_BUFFER * cert,CertVerifyResult * verify_result)272 [[nodiscard]] bool InspectSignatureAlgorithmForCert(
273     const CRYPTO_BUFFER* cert,
274     CertVerifyResult* verify_result) {
275   std::string_view cert_algorithm_sequence;
276   std::string_view tbs_algorithm_sequence;
277 
278   // Extract the AlgorithmIdentifier SEQUENCEs
279   if (!asn1::ExtractSignatureAlgorithmsFromDERCert(
280           x509_util::CryptoBufferAsStringPiece(cert), &cert_algorithm_sequence,
281           &tbs_algorithm_sequence)) {
282     return false;
283   }
284 
285   std::optional<bssl::SignatureAlgorithm> cert_algorithm =
286       bssl::ParseSignatureAlgorithm(bssl::der::Input(cert_algorithm_sequence));
287   std::optional<bssl::SignatureAlgorithm> tbs_algorithm =
288       bssl::ParseSignatureAlgorithm(bssl::der::Input(tbs_algorithm_sequence));
289   if (!cert_algorithm || !tbs_algorithm || *cert_algorithm != *tbs_algorithm) {
290     return false;
291   }
292 
293   switch (*cert_algorithm) {
294     case bssl::SignatureAlgorithm::kRsaPkcs1Sha1:
295     case bssl::SignatureAlgorithm::kEcdsaSha1:
296       verify_result->has_sha1 = true;
297       return true;  // For now.
298 
299     case bssl::SignatureAlgorithm::kRsaPkcs1Sha256:
300     case bssl::SignatureAlgorithm::kRsaPkcs1Sha384:
301     case bssl::SignatureAlgorithm::kRsaPkcs1Sha512:
302     case bssl::SignatureAlgorithm::kEcdsaSha256:
303     case bssl::SignatureAlgorithm::kEcdsaSha384:
304     case bssl::SignatureAlgorithm::kEcdsaSha512:
305     case bssl::SignatureAlgorithm::kRsaPssSha256:
306     case bssl::SignatureAlgorithm::kRsaPssSha384:
307     case bssl::SignatureAlgorithm::kRsaPssSha512:
308       return true;
309   }
310 
311   NOTREACHED();
312 }
313 
314 // InspectSignatureAlgorithmsInChain() sets |verify_result->has_*| based on
315 // the signature algorithms used in the chain, and also checks that certificates
316 // don't have contradictory signature algorithms.
317 //
318 // Returns false if any signature algorithm in the chain is unknown or
319 // mismatched.
320 //
321 // Background:
322 //
323 // X.509 certificates contain two redundant descriptors for the signature
324 // algorithm; one is covered by the signature, but in order to verify the
325 // signature, the other signature algorithm is untrusted.
326 //
327 // RFC 5280 states that the two should be equal, in order to mitigate risk of
328 // signature substitution attacks, but also discourages verifiers from enforcing
329 // the profile of RFC 5280.
330 //
331 // System verifiers are inconsistent - some use the unsigned signature, some use
332 // the signed signature, and they generally do not enforce that both match. This
333 // creates confusion, as it's possible that the signature itself may be checked
334 // using algorithm A, but if subsequent consumers report the certificate
335 // algorithm, they may end up reporting algorithm B, which was not used to
336 // verify the certificate. This function enforces that the two signatures match
337 // in order to prevent such confusion.
InspectSignatureAlgorithmsInChain(CertVerifyResult * verify_result)338 [[nodiscard]] bool InspectSignatureAlgorithmsInChain(
339     CertVerifyResult* verify_result) {
340   const std::vector<bssl::UniquePtr<CRYPTO_BUFFER>>& intermediates =
341       verify_result->verified_cert->intermediate_buffers();
342 
343   // If there are no intermediates, then the leaf is trusted or verification
344   // failed.
345   if (intermediates.empty())
346     return true;
347 
348   DCHECK(!verify_result->has_sha1);
349 
350   // Fill in hash algorithms for the leaf certificate.
351   if (!InspectSignatureAlgorithmForCert(
352           verify_result->verified_cert->cert_buffer(), verify_result)) {
353     return false;
354   }
355 
356   // Fill in hash algorithms for the intermediate cerificates, excluding the
357   // final one (which is presumably the trust anchor; may be incorrect for
358   // partial chains).
359   for (size_t i = 0; i + 1 < intermediates.size(); ++i) {
360     if (!InspectSignatureAlgorithmForCert(intermediates[i].get(),
361                                           verify_result))
362       return false;
363   }
364 
365   return true;
366 }
367 
CertVerifyParams(X509Certificate * cert,const std::string & hostname,const std::string & ocsp_response,const std::string & sct_list,int flags,CRLSet * crl_set)368 base::Value::Dict CertVerifyParams(X509Certificate* cert,
369                                    const std::string& hostname,
370                                    const std::string& ocsp_response,
371                                    const std::string& sct_list,
372                                    int flags,
373                                    CRLSet* crl_set) {
374   base::Value::Dict dict;
375   dict.Set("certificates", NetLogX509CertificateList(cert));
376   if (!ocsp_response.empty()) {
377     dict.Set("ocsp_response",
378              bssl::PEMEncode(ocsp_response, "NETLOG OCSP RESPONSE"));
379   }
380   if (!sct_list.empty()) {
381     dict.Set("sct_list", bssl::PEMEncode(sct_list, "NETLOG SCT LIST"));
382   }
383   dict.Set("host", NetLogStringValue(hostname));
384   dict.Set("verify_flags", flags);
385   dict.Set("crlset_sequence", NetLogNumberValue(crl_set->sequence()));
386   if (crl_set->IsExpired())
387     dict.Set("crlset_is_expired", true);
388 
389   return dict;
390 }
391 
392 }  // namespace
393 
394 #if !(BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(CHROME_ROOT_STORE_ONLY))
395 // static
CreateSystemVerifyProc(scoped_refptr<CertNetFetcher> cert_net_fetcher,scoped_refptr<CRLSet> crl_set)396 scoped_refptr<CertVerifyProc> CertVerifyProc::CreateSystemVerifyProc(
397     scoped_refptr<CertNetFetcher> cert_net_fetcher,
398     scoped_refptr<CRLSet> crl_set) {
399 #if BUILDFLAG(IS_ANDROID)
400   return base::MakeRefCounted<CertVerifyProcAndroid>(
401       std::move(cert_net_fetcher), std::move(crl_set));
402 #elif BUILDFLAG(IS_IOS)
403   return base::MakeRefCounted<CertVerifyProcIOS>(std::move(crl_set));
404 #else
405 #error Unsupported platform
406 #endif
407 }
408 #endif
409 
410 #if BUILDFLAG(IS_FUCHSIA)
411 // static
CreateBuiltinVerifyProc(scoped_refptr<CertNetFetcher> cert_net_fetcher,scoped_refptr<CRLSet> crl_set,std::unique_ptr<CTVerifier> ct_verifier,scoped_refptr<CTPolicyEnforcer> ct_policy_enforcer,const InstanceParams instance_params,std::optional<network_time::TimeTracker> time_tracker)412 scoped_refptr<CertVerifyProc> CertVerifyProc::CreateBuiltinVerifyProc(
413     scoped_refptr<CertNetFetcher> cert_net_fetcher,
414     scoped_refptr<CRLSet> crl_set,
415     std::unique_ptr<CTVerifier> ct_verifier,
416     scoped_refptr<CTPolicyEnforcer> ct_policy_enforcer,
417     const InstanceParams instance_params,
418     std::optional<network_time::TimeTracker> time_tracker) {
419   return CreateCertVerifyProcBuiltin(
420       std::move(cert_net_fetcher), std::move(crl_set), std::move(ct_verifier),
421       std::move(ct_policy_enforcer), CreateSslSystemTrustStore(),
422       instance_params, std::move(time_tracker));
423 }
424 #endif
425 
426 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
427 // static
CreateBuiltinWithChromeRootStore(scoped_refptr<CertNetFetcher> cert_net_fetcher,scoped_refptr<CRLSet> crl_set,std::unique_ptr<CTVerifier> ct_verifier,scoped_refptr<CTPolicyEnforcer> ct_policy_enforcer,const ChromeRootStoreData * root_store_data,const InstanceParams instance_params,std::optional<network_time::TimeTracker> time_tracker)428 scoped_refptr<CertVerifyProc> CertVerifyProc::CreateBuiltinWithChromeRootStore(
429     scoped_refptr<CertNetFetcher> cert_net_fetcher,
430     scoped_refptr<CRLSet> crl_set,
431     std::unique_ptr<CTVerifier> ct_verifier,
432     scoped_refptr<CTPolicyEnforcer> ct_policy_enforcer,
433     const ChromeRootStoreData* root_store_data,
434     const InstanceParams instance_params,
435     std::optional<network_time::TimeTracker> time_tracker) {
436   std::unique_ptr<TrustStoreChrome> chrome_root =
437       root_store_data ? std::make_unique<TrustStoreChrome>(*root_store_data)
438                       : std::make_unique<TrustStoreChrome>();
439   return CreateCertVerifyProcBuiltin(
440       std::move(cert_net_fetcher), std::move(crl_set), std::move(ct_verifier),
441       std::move(ct_policy_enforcer),
442       CreateSslSystemTrustStoreChromeRoot(std::move(chrome_root)),
443       instance_params, std::move(time_tracker));
444 }
445 #endif
446 
CertVerifyProc(scoped_refptr<CRLSet> crl_set)447 CertVerifyProc::CertVerifyProc(scoped_refptr<CRLSet> crl_set)
448     : crl_set_(std::move(crl_set)) {
449   CHECK(crl_set_);
450 }
451 
452 CertVerifyProc::~CertVerifyProc() = default;
453 
Verify(X509Certificate * cert,const std::string & hostname,const std::string & ocsp_response,const std::string & sct_list,int flags,CertVerifyResult * verify_result,const NetLogWithSource & net_log)454 int CertVerifyProc::Verify(X509Certificate* cert,
455                            const std::string& hostname,
456                            const std::string& ocsp_response,
457                            const std::string& sct_list,
458                            int flags,
459                            CertVerifyResult* verify_result,
460                            const NetLogWithSource& net_log) {
461   CHECK(cert);
462   CHECK(verify_result);
463 
464   net_log.BeginEvent(NetLogEventType::CERT_VERIFY_PROC, [&] {
465     return CertVerifyParams(cert, hostname, ocsp_response, sct_list, flags,
466                             crl_set());
467   });
468   // CertVerifyProc's contract allows ::VerifyInternal() to wait on File I/O
469   // (such as the Windows registry or smart cards on all platforms) or may re-
470   // enter this code via extension hooks (such as smart card UI). To ensure
471   // threads are not starved or deadlocked, the base::ScopedBlockingCall below
472   // increments the thread pool capacity when this method takes too much time to
473   // run.
474   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
475                                                 base::BlockingType::MAY_BLOCK);
476 
477   verify_result->Reset();
478   verify_result->verified_cert = cert;
479 
480   int rv = VerifyInternal(cert, hostname, ocsp_response, sct_list, flags,
481                           verify_result, net_log);
482 
483   CHECK(verify_result->verified_cert);
484 
485   // Check for mismatched signature algorithms and unknown signature algorithms
486   // in the chain. Also fills in the has_* booleans for the digest algorithms
487   // present in the chain.
488   if (!InspectSignatureAlgorithmsInChain(verify_result)) {
489     verify_result->cert_status |= CERT_STATUS_INVALID;
490     rv = MapCertStatusToNetError(verify_result->cert_status);
491   }
492 
493   if (!cert->VerifyNameMatch(hostname)) {
494     verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
495     rv = MapCertStatusToNetError(verify_result->cert_status);
496   }
497 
498   if (verify_result->ocsp_result.response_status ==
499       bssl::OCSPVerifyResult::NOT_CHECKED) {
500     // If VerifyInternal did not record the result of checking stapled OCSP,
501     // do it now.
502     BestEffortCheckOCSP(ocsp_response, *verify_result->verified_cert,
503                         &verify_result->ocsp_result);
504   }
505 
506   // Check to see if the connection is being intercepted.
507   for (const auto& hash : verify_result->public_key_hashes) {
508     if (hash.tag() != HASH_VALUE_SHA256) {
509       continue;
510     }
511     if (!crl_set()->IsKnownInterceptionKey(std::string_view(
512             reinterpret_cast<const char*>(hash.data()), hash.size()))) {
513       continue;
514     }
515 
516     if (verify_result->cert_status & CERT_STATUS_REVOKED) {
517       // If the chain was revoked, and a known MITM was present, signal that
518       // with a more meaningful error message.
519       verify_result->cert_status |= CERT_STATUS_KNOWN_INTERCEPTION_BLOCKED;
520       rv = MapCertStatusToNetError(verify_result->cert_status);
521     } else {
522       // Otherwise, simply signal informatively. Both statuses are not set
523       // simultaneously.
524       verify_result->cert_status |= CERT_STATUS_KNOWN_INTERCEPTION_DETECTED;
525     }
526     break;
527   }
528 
529   std::vector<std::string> dns_names, ip_addrs;
530   cert->GetSubjectAltName(&dns_names, &ip_addrs);
531   if (HasNameConstraintsViolation(verify_result->public_key_hashes,
532                                   cert->subject().common_name,
533                                   dns_names,
534                                   ip_addrs)) {
535     verify_result->cert_status |= CERT_STATUS_NAME_CONSTRAINT_VIOLATION;
536     rv = MapCertStatusToNetError(verify_result->cert_status);
537   }
538 
539   // Check for weak keys in the entire verified chain.
540   bool weak_key = ExaminePublicKeys(verify_result->verified_cert,
541                                     verify_result->is_issued_by_known_root);
542 
543   if (weak_key) {
544     verify_result->cert_status |= CERT_STATUS_WEAK_KEY;
545     // Avoid replacing a more serious error, such as an OS/library failure,
546     // by ensuring that if verification failed, it failed with a certificate
547     // error.
548     if (rv == OK || IsCertificateError(rv))
549       rv = MapCertStatusToNetError(verify_result->cert_status);
550   }
551 
552   if (verify_result->has_sha1)
553     verify_result->cert_status |= CERT_STATUS_SHA1_SIGNATURE_PRESENT;
554 
555   // Flag certificates using weak signature algorithms.
556   bool sha1_allowed = (flags & VERIFY_ENABLE_SHA1_LOCAL_ANCHORS) &&
557                       !verify_result->is_issued_by_known_root;
558   if (!sha1_allowed && verify_result->has_sha1) {
559     verify_result->cert_status |= CERT_STATUS_WEAK_SIGNATURE_ALGORITHM;
560     // Avoid replacing a more serious error, such as an OS/library failure,
561     // by ensuring that if verification failed, it failed with a certificate
562     // error.
563     if (rv == OK || IsCertificateError(rv))
564       rv = MapCertStatusToNetError(verify_result->cert_status);
565   }
566 
567   // Distrust Symantec-issued certificates, as described at
568   // https://security.googleblog.com/2017/09/chromes-plan-to-distrust-symantec.html
569   if (!(flags & VERIFY_DISABLE_SYMANTEC_ENFORCEMENT) &&
570       IsLegacySymantecCert(verify_result->public_key_hashes)) {
571     verify_result->cert_status |= CERT_STATUS_SYMANTEC_LEGACY;
572     if (rv == OK || IsCertificateError(rv))
573       rv = MapCertStatusToNetError(verify_result->cert_status);
574   }
575 
576   // Flag certificates using too long validity periods.
577   if (verify_result->is_issued_by_known_root && HasTooLongValidity(*cert)) {
578     verify_result->cert_status |= CERT_STATUS_VALIDITY_TOO_LONG;
579     if (rv == OK)
580       rv = MapCertStatusToNetError(verify_result->cert_status);
581   }
582 
583   // Flag certificates from publicly-trusted CAs that are issued to intranet
584   // hosts. These are not allowed per the CA/Browser Forum requirements.
585   //
586   // Validity period is checked first just for testing convenience; there's not
587   // a strong security reason to let validity period vs non-unique names take
588   // precedence.
589   if (verify_result->is_issued_by_known_root && IsHostnameNonUnique(hostname)) {
590     verify_result->cert_status |= CERT_STATUS_NON_UNIQUE_NAME;
591     // On Cronet, CERT_STATUS_NON_UNIQUE_NAME is recorded as a warning but not
592     // treated as an error, because consumers have tests that use certs with
593     // non-unique names. See b/337196170 (Google-internal).
594 #if !BUILDFLAG(CRONET_BUILD)
595     if (rv == OK) {
596       rv = MapCertStatusToNetError(verify_result->cert_status);
597     }
598 #endif  // !BUILDFLAG(CRONET_BUILD)
599   }
600 
601   // Record a histogram for per-verification usage of root certs.
602   if (rv == OK) {
603     RecordTrustAnchorHistogram(verify_result->public_key_hashes,
604                                verify_result->is_issued_by_known_root);
605   }
606 
607   net_log.EndEvent(NetLogEventType::CERT_VERIFY_PROC,
608                    [&] { return verify_result->NetLogParams(rv); });
609   return rv;
610 }
611 
612 // static
LogNameNormalizationResult(const std::string & histogram_suffix,NameNormalizationResult result)613 void CertVerifyProc::LogNameNormalizationResult(
614     const std::string& histogram_suffix,
615     NameNormalizationResult result) {
616   base::UmaHistogramEnumeration(
617       std::string("Net.CertVerifier.NameNormalizationPrivateRoots") +
618           histogram_suffix,
619       result);
620 }
621 
622 // static
LogNameNormalizationMetrics(const std::string & histogram_suffix,X509Certificate * verified_cert,bool is_issued_by_known_root)623 void CertVerifyProc::LogNameNormalizationMetrics(
624     const std::string& histogram_suffix,
625     X509Certificate* verified_cert,
626     bool is_issued_by_known_root) {
627   if (is_issued_by_known_root)
628     return;
629 
630   if (verified_cert->intermediate_buffers().empty()) {
631     LogNameNormalizationResult(histogram_suffix,
632                                NameNormalizationResult::kChainLengthOne);
633     return;
634   }
635 
636   std::vector<CRYPTO_BUFFER*> der_certs;
637   der_certs.push_back(verified_cert->cert_buffer());
638   for (const auto& buf : verified_cert->intermediate_buffers())
639     der_certs.push_back(buf.get());
640 
641   bssl::ParseCertificateOptions options;
642   options.allow_invalid_serial_numbers = true;
643 
644   std::vector<bssl::der::Input> subjects;
645   std::vector<bssl::der::Input> issuers;
646 
647   for (auto* buf : der_certs) {
648     bssl::der::Input tbs_certificate_tlv;
649     bssl::der::Input signature_algorithm_tlv;
650     bssl::der::BitString signature_value;
651     bssl::ParsedTbsCertificate tbs;
652     if (!bssl::ParseCertificate(
653             bssl::der::Input(CRYPTO_BUFFER_data(buf), CRYPTO_BUFFER_len(buf)),
654             &tbs_certificate_tlv, &signature_algorithm_tlv, &signature_value,
655             nullptr /* errors*/) ||
656         !ParseTbsCertificate(tbs_certificate_tlv, options, &tbs,
657                              nullptr /*errors*/)) {
658       LogNameNormalizationResult(histogram_suffix,
659                                  NameNormalizationResult::kError);
660       return;
661     }
662     subjects.push_back(tbs.subject_tlv);
663     issuers.push_back(tbs.issuer_tlv);
664   }
665 
666   for (size_t i = 0; i < subjects.size() - 1; ++i) {
667     if (issuers[i] != subjects[i + 1]) {
668       LogNameNormalizationResult(histogram_suffix,
669                                  NameNormalizationResult::kNormalized);
670       return;
671     }
672   }
673 
674   LogNameNormalizationResult(histogram_suffix,
675                              NameNormalizationResult::kByteEqual);
676 }
677 
678 // CheckNameConstraints verifies that every name in |dns_names| is in one of
679 // the domains specified by |domains|.
CheckNameConstraints(const std::vector<std::string> & dns_names,base::span<const std::string_view> domains)680 static bool CheckNameConstraints(const std::vector<std::string>& dns_names,
681                                  base::span<const std::string_view> domains) {
682   for (const auto& host : dns_names) {
683     bool ok = false;
684     url::CanonHostInfo host_info;
685     const std::string dns_name = CanonicalizeHost(host, &host_info);
686     if (host_info.IsIPAddress())
687       continue;
688 
689     // If the name is not in a known TLD, ignore it. This permits internal
690     // server names.
691     if (!registry_controlled_domains::HostHasRegistryControlledDomain(
692             dns_name, registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
693             registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
694       continue;
695     }
696 
697     for (const auto& domain : domains) {
698       // The |domain| must be of ".somesuffix" form, and |dns_name| must
699       // have |domain| as a suffix.
700       DCHECK_EQ('.', domain[0]);
701       if (dns_name.size() <= domain.size())
702         continue;
703       std::string_view suffix =
704           std::string_view(dns_name).substr(dns_name.size() - domain.size());
705       if (!base::EqualsCaseInsensitiveASCII(suffix, domain))
706         continue;
707       ok = true;
708       break;
709     }
710 
711     if (!ok)
712       return false;
713   }
714 
715   return true;
716 }
717 
718 // static
HasNameConstraintsViolation(const HashValueVector & public_key_hashes,const std::string & common_name,const std::vector<std::string> & dns_names,const std::vector<std::string> & ip_addrs)719 bool CertVerifyProc::HasNameConstraintsViolation(
720     const HashValueVector& public_key_hashes,
721     const std::string& common_name,
722     const std::vector<std::string>& dns_names,
723     const std::vector<std::string>& ip_addrs) {
724   static constexpr std::string_view kDomainsANSSI[] = {
725       ".fr",  // France
726       ".gp",  // Guadeloupe
727       ".gf",  // Guyane
728       ".mq",  // Martinique
729       ".re",  // Réunion
730       ".yt",  // Mayotte
731       ".pm",  // Saint-Pierre et Miquelon
732       ".bl",  // Saint Barthélemy
733       ".mf",  // Saint Martin
734       ".wf",  // Wallis et Futuna
735       ".pf",  // Polynésie française
736       ".nc",  // Nouvelle Calédonie
737       ".tf",  // Terres australes et antarctiques françaises
738   };
739 
740   static constexpr std::string_view kDomainsTest[] = {
741       ".example.com",
742   };
743 
744   // PublicKeyDomainLimitation contains SHA-256(SPKI) and a pointer to an array
745   // of fixed-length strings that contain the domains that the SPKI is allowed
746   // to issue for.
747   //
748   // A public key hash can be generated with the following command:
749   // openssl x509 -noout -in <cert>.pem -pubkey | \
750   //   openssl asn1parse -noout -inform pem -out - | \
751   //   openssl dgst -sha256 -binary | xxd -i
752   static const struct PublicKeyDomainLimitation {
753     SHA256HashValue public_key_hash;
754     base::raw_span<const std::string_view> domains;
755   } kLimits[] = {
756       // C=FR, ST=France, L=Paris, O=PM/SGDN, OU=DCSSI,
757       // CN=IGC/A/emailAddress=igca@sgdn.pm.gouv.fr
758       //
759       // net/data/ssl/name_constrained/b9bea7860a962ea3611dab97ab6da3e21c1068b97d55575ed0e11279c11c8932.pem
760       {
761           {{0x86, 0xc1, 0x3a, 0x34, 0x08, 0xdd, 0x1a, 0xa7, 0x7e, 0xe8, 0xb6,
762             0x94, 0x7c, 0x03, 0x95, 0x87, 0x72, 0xf5, 0x31, 0x24, 0x8c, 0x16,
763             0x27, 0xbe, 0xfb, 0x2c, 0x4f, 0x4b, 0x04, 0xd0, 0x44, 0x96}},
764           kDomainsANSSI,
765       },
766       // Not a real certificate - just for testing.
767       // net/data/ssl/certificates/name_constrained_key.pem
768       {
769           {{0xa2, 0x2a, 0x88, 0x82, 0xba, 0x0c, 0xae, 0x9d, 0xf2, 0xc4, 0x5b,
770             0x15, 0xa6, 0x1e, 0xfd, 0xfd, 0x19, 0x6b, 0xb1, 0x09, 0x19, 0xfd,
771             0xac, 0x77, 0x9b, 0xd6, 0x08, 0x66, 0xda, 0xa8, 0xd2, 0x88}},
772           kDomainsTest,
773       },
774   };
775 
776   for (const auto& limit : kLimits) {
777     for (const auto& hash : public_key_hashes) {
778       if (hash.tag() != HASH_VALUE_SHA256)
779         continue;
780       if (memcmp(hash.data(), limit.public_key_hash.data, hash.size()) != 0)
781         continue;
782       if (dns_names.empty() && ip_addrs.empty()) {
783         std::vector<std::string> names;
784         names.push_back(common_name);
785         if (!CheckNameConstraints(names, limit.domains))
786           return true;
787       } else {
788         if (!CheckNameConstraints(dns_names, limit.domains))
789           return true;
790       }
791     }
792   }
793 
794   return false;
795 }
796 
797 // static
HasTooLongValidity(const X509Certificate & cert)798 bool CertVerifyProc::HasTooLongValidity(const X509Certificate& cert) {
799   const base::Time& start = cert.valid_start();
800   const base::Time& expiry = cert.valid_expiry();
801   if (start.is_max() || start.is_null() || expiry.is_max() ||
802       expiry.is_null() || start > expiry) {
803     return true;
804   }
805 
806   // The maximum lifetime of publicly trusted certificates has reduced
807   // gradually over time. These dates are derived from the transitions noted in
808   // Section 1.2.2 (Relevant Dates) of the Baseline Requirements.
809   //
810   // * Certificates issued before BRs took effect, Chrome limited to max of ten
811   // years validity and a max notAfter date of 2019-07-01.
812   //   * Last possible expiry: 2019-07-01.
813   //
814   // * Cerificates issued on-or-after the BR effective date of 1 July 2012: 60
815   // months.
816   //   * Last possible expiry: 1 April 2015 + 60 months = 2020-04-01
817   //
818   // * Certificates issued on-or-after 1 April 2015: 39 months.
819   //   * Last possible expiry: 1 March 2018 + 39 months = 2021-06-01
820   //
821   // * Certificates issued on-or-after 1 March 2018: 825 days.
822   //   * Last possible expiry: 1 September 2020 + 825 days = 2022-12-05
823   //
824   // The current limit, from Chrome Root Certificate Policy:
825   // * Certificates issued on-or-after 1 September 2020: 398 days.
826 
827   base::TimeDelta validity_duration = cert.valid_expiry() - cert.valid_start();
828 
829   // No certificates issued before the latest lifetime requirement was enacted
830   // could possibly still be accepted, so we don't need to check the older
831   // limits explicitly.
832   return validity_duration > base::Days(398);
833 }
834 
ImplParams()835 CertVerifyProc::ImplParams::ImplParams() {
836   crl_set = net::CRLSet::BuiltinCRLSet();
837 #if BUILDFLAG(CHROME_ROOT_STORE_OPTIONAL)
838   // Defaults to using Chrome Root Store, though we have to keep this option in
839   // here to allow WebView to turn this option off.
840   use_chrome_root_store = true;
841 #endif
842 }
843 
844 CertVerifyProc::ImplParams::~ImplParams() = default;
845 
846 CertVerifyProc::ImplParams::ImplParams(const ImplParams&) = default;
847 CertVerifyProc::ImplParams& CertVerifyProc::ImplParams::operator=(
848     const ImplParams& other) = default;
849 CertVerifyProc::ImplParams::ImplParams(ImplParams&&) = default;
850 CertVerifyProc::ImplParams& CertVerifyProc::ImplParams::operator=(
851     ImplParams&& other) = default;
852 
853 CertVerifyProc::InstanceParams::InstanceParams() = default;
854 CertVerifyProc::InstanceParams::~InstanceParams() = default;
855 
856 CertVerifyProc::InstanceParams::InstanceParams(const InstanceParams&) = default;
857 CertVerifyProc::InstanceParams& CertVerifyProc::InstanceParams::operator=(
858     const InstanceParams& other) = default;
859 CertVerifyProc::InstanceParams::InstanceParams(InstanceParams&&) = default;
860 CertVerifyProc::InstanceParams& CertVerifyProc::InstanceParams::operator=(
861     InstanceParams&& other) = default;
862 
863 CertVerifyProc::CertificateWithConstraints::CertificateWithConstraints() =
864     default;
865 CertVerifyProc::CertificateWithConstraints::~CertificateWithConstraints() =
866     default;
867 
868 CertVerifyProc::CertificateWithConstraints::CertificateWithConstraints(
869     const CertificateWithConstraints&) = default;
870 CertVerifyProc::CertificateWithConstraints&
871 CertVerifyProc::CertificateWithConstraints::operator=(
872     const CertificateWithConstraints& other) = default;
873 CertVerifyProc::CertificateWithConstraints::CertificateWithConstraints(
874     CertificateWithConstraints&&) = default;
875 CertVerifyProc::CertificateWithConstraints&
876 CertVerifyProc::CertificateWithConstraints::operator=(
877     CertificateWithConstraints&& other) = default;
878 
879 }  // namespace net
880