• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/cert/cert_verify_proc_builtin.h"
6 
7 #include <memory>
8 #include <string>
9 #include <vector>
10 
11 #include "base/feature_list.h"
12 #include "base/logging.h"
13 #include "base/memory/raw_ptr.h"
14 #include "base/metrics/histogram_functions.h"
15 #include "base/strings/string_piece.h"
16 #include "base/values.h"
17 #include "crypto/sha2.h"
18 #include "net/base/features.h"
19 #include "net/base/net_errors.h"
20 #include "net/cert/cert_net_fetcher.h"
21 #include "net/cert/cert_status_flags.h"
22 #include "net/cert/cert_verifier.h"
23 #include "net/cert/cert_verify_proc.h"
24 #include "net/cert/cert_verify_result.h"
25 #include "net/cert/ev_root_ca_metadata.h"
26 #include "net/cert/internal/cert_issuer_source_aia.h"
27 #include "net/cert/internal/revocation_checker.h"
28 #include "net/cert/internal/system_trust_store.h"
29 #include "net/cert/known_roots.h"
30 #include "net/cert/test_root_certs.h"
31 #include "net/cert/time_conversions.h"
32 #include "net/cert/x509_certificate.h"
33 #include "net/cert/x509_util.h"
34 #include "net/log/net_log_values.h"
35 #include "net/log/net_log_with_source.h"
36 #include "third_party/abseil-cpp/absl/types/optional.h"
37 #include "third_party/boringssl/src/pki/cert_errors.h"
38 #include "third_party/boringssl/src/pki/cert_issuer_source_static.h"
39 #include "third_party/boringssl/src/pki/common_cert_errors.h"
40 #include "third_party/boringssl/src/pki/parsed_certificate.h"
41 #include "third_party/boringssl/src/pki/path_builder.h"
42 #include "third_party/boringssl/src/pki/simple_path_builder_delegate.h"
43 #include "third_party/boringssl/src/pki/trust_store_collection.h"
44 #include "third_party/boringssl/src/pki/trust_store_in_memory.h"
45 
46 using bssl::CertErrorId;
47 
48 namespace net {
49 
50 namespace {
51 
52 // Very conservative iteration count limit.
53 // TODO(https://crbug.com/634470): Remove this in favor of
54 // kPathBuilderIterationLimitNew.
55 constexpr uint32_t kPathBuilderIterationLimit = 25000;
56 constexpr uint32_t kPathBuilderIterationLimitNew = 20;
57 
58 constexpr base::TimeDelta kMaxVerificationTime = base::Seconds(60);
59 
60 constexpr base::TimeDelta kPerAttemptMinVerificationTimeLimit =
61     base::Seconds(5);
62 
63 DEFINE_CERT_ERROR_ID(kPathLacksEVPolicy, "Path does not have an EV policy");
64 
NetLogCertParams(const CRYPTO_BUFFER * cert_handle,const bssl::CertErrors & errors)65 base::Value::Dict NetLogCertParams(const CRYPTO_BUFFER* cert_handle,
66                                    const bssl::CertErrors& errors) {
67   base::Value::Dict results;
68 
69   std::string pem_encoded;
70   if (X509Certificate::GetPEMEncodedFromDER(
71           x509_util::CryptoBufferAsStringPiece(cert_handle), &pem_encoded)) {
72     results.Set("certificate", pem_encoded);
73   }
74 
75   std::string errors_string = errors.ToDebugString();
76   if (!errors_string.empty())
77     results.Set("errors", errors_string);
78 
79   return results;
80 }
81 
NetLogAdditionalCert(const CRYPTO_BUFFER * cert_handle,const bssl::CertificateTrust & trust,const bssl::CertErrors & errors)82 base::Value::Dict NetLogAdditionalCert(const CRYPTO_BUFFER* cert_handle,
83                                        const bssl::CertificateTrust& trust,
84                                        const bssl::CertErrors& errors) {
85   base::Value::Dict results = NetLogCertParams(cert_handle, errors);
86   results.Set("trust", trust.ToDebugString());
87   return results;
88 }
89 
90 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
NetLogChromeRootStoreVersion(int64_t chrome_root_store_version)91 base::Value::Dict NetLogChromeRootStoreVersion(
92     int64_t chrome_root_store_version) {
93   base::Value::Dict results;
94   results.Set("version_major", NetLogNumberValue(chrome_root_store_version));
95   return results;
96 }
97 #endif
98 
PEMCertValueList(const bssl::ParsedCertificateList & certs)99 base::Value::List PEMCertValueList(const bssl::ParsedCertificateList& certs) {
100   base::Value::List value;
101   for (const auto& cert : certs) {
102     std::string pem;
103     X509Certificate::GetPEMEncodedFromDER(cert->der_cert().AsStringView(),
104                                           &pem);
105     value.Append(std::move(pem));
106   }
107   return value;
108 }
109 
NetLogPathBuilderResultPath(const bssl::CertPathBuilderResultPath & result_path)110 base::Value::Dict NetLogPathBuilderResultPath(
111     const bssl::CertPathBuilderResultPath& result_path) {
112   base::Value::Dict dict;
113   dict.Set("is_valid", result_path.IsValid());
114   dict.Set("last_cert_trust", result_path.last_cert_trust.ToDebugString());
115   dict.Set("certificates", PEMCertValueList(result_path.certs));
116   // TODO(crbug.com/634484): netlog user_constrained_policy_set.
117   std::string errors_string =
118       result_path.errors.ToDebugString(result_path.certs);
119   if (!errors_string.empty())
120     dict.Set("errors", errors_string);
121   return dict;
122 }
123 
NetLogPathBuilderResult(const bssl::CertPathBuilder::Result & result)124 base::Value::Dict NetLogPathBuilderResult(
125     const bssl::CertPathBuilder::Result& result) {
126   base::Value::Dict dict;
127   // TODO(crbug.com/634484): include debug data (or just have things netlog it
128   // directly).
129   dict.Set("has_valid_path", result.HasValidPath());
130   dict.Set("best_result_index", static_cast<int>(result.best_result_index));
131   if (result.exceeded_iteration_limit)
132     dict.Set("exceeded_iteration_limit", true);
133   if (result.exceeded_deadline)
134     dict.Set("exceeded_deadline", true);
135   return dict;
136 }
137 
NoRevocationChecking()138 RevocationPolicy NoRevocationChecking() {
139   RevocationPolicy policy;
140   policy.check_revocation = false;
141   policy.networking_allowed = false;
142   policy.crl_allowed = false;
143   policy.allow_missing_info = true;
144   policy.allow_unable_to_check = true;
145   policy.enforce_baseline_requirements = false;
146   return policy;
147 }
148 
149 // Gets the set of policy OIDs in |cert| that are recognized as EV OIDs for some
150 // root.
GetEVPolicyOids(const EVRootCAMetadata * ev_metadata,const bssl::ParsedCertificate * cert,std::set<bssl::der::Input> * oids)151 void GetEVPolicyOids(const EVRootCAMetadata* ev_metadata,
152                      const bssl::ParsedCertificate* cert,
153                      std::set<bssl::der::Input>* oids) {
154   oids->clear();
155 
156   if (!cert->has_policy_oids())
157     return;
158 
159   for (const bssl::der::Input& oid : cert->policy_oids()) {
160     if (ev_metadata->IsEVPolicyOID(oid)) {
161       oids->insert(oid);
162     }
163   }
164 }
165 
166 // Returns true if |cert| could be an EV certificate, based on its policies
167 // extension. A return of false means it definitely is not an EV certificate,
168 // whereas a return of true means it could be EV.
IsEVCandidate(const EVRootCAMetadata * ev_metadata,const bssl::ParsedCertificate * cert)169 bool IsEVCandidate(const EVRootCAMetadata* ev_metadata,
170                    const bssl::ParsedCertificate* cert) {
171   std::set<bssl::der::Input> oids;
172   GetEVPolicyOids(ev_metadata, cert, &oids);
173   return !oids.empty();
174 }
175 
176 // CertVerifyProcTrustStore wraps a SystemTrustStore with additional trust
177 // anchors and TestRootCerts.
178 class CertVerifyProcTrustStore {
179  public:
180   // |system_trust_store| must outlive this object.
CertVerifyProcTrustStore(SystemTrustStore * system_trust_store,bssl::TrustStoreInMemory * additional_trust_store)181   explicit CertVerifyProcTrustStore(
182       SystemTrustStore* system_trust_store,
183       bssl::TrustStoreInMemory* additional_trust_store)
184       : system_trust_store_(system_trust_store),
185         additional_trust_store_(additional_trust_store) {
186     trust_store_.AddTrustStore(additional_trust_store_);
187     trust_store_.AddTrustStore(system_trust_store_->GetTrustStore());
188     // When running in test mode, also layer in the test-only root certificates.
189     //
190     // Note that this integration requires TestRootCerts::HasInstance() to be
191     // true by the time CertVerifyProcTrustStore is created - a limitation which
192     // is acceptable for the test-only code that consumes this.
193     if (TestRootCerts::HasInstance()) {
194       trust_store_.AddTrustStore(
195           TestRootCerts::GetInstance()->test_trust_store());
196     }
197   }
198 
trust_store()199   bssl::TrustStore* trust_store() { return &trust_store_; }
200 
IsKnownRoot(const bssl::ParsedCertificate * trust_anchor) const201   bool IsKnownRoot(const bssl::ParsedCertificate* trust_anchor) const {
202     if (TestRootCerts::HasInstance() &&
203         TestRootCerts::GetInstance()->IsKnownRoot(
204             trust_anchor->der_cert().AsSpan())) {
205       return true;
206     }
207     return system_trust_store_->IsKnownRoot(trust_anchor);
208   }
209 
IsAdditionalTrustAnchor(const bssl::ParsedCertificate * trust_anchor) const210   bool IsAdditionalTrustAnchor(
211       const bssl::ParsedCertificate* trust_anchor) const {
212     return additional_trust_store_->Contains(trust_anchor);
213   }
214 
215  private:
216   raw_ptr<SystemTrustStore> system_trust_store_;
217   raw_ptr<bssl::TrustStoreInMemory> additional_trust_store_;
218   bssl::TrustStoreCollection trust_store_;
219 };
220 
221 // Enum for whether path building is attempting to verify a certificate as EV or
222 // as DV.
223 enum class VerificationType {
224   kEV,  // Extended Validation
225   kDV,  // Domain Validation
226 };
227 
228 class PathBuilderDelegateDataImpl : public bssl::CertPathBuilderDelegateData {
229  public:
230   ~PathBuilderDelegateDataImpl() override = default;
231 
Get(const bssl::CertPathBuilderResultPath & path)232   static const PathBuilderDelegateDataImpl* Get(
233       const bssl::CertPathBuilderResultPath& path) {
234     return static_cast<PathBuilderDelegateDataImpl*>(path.delegate_data.get());
235   }
236 
GetOrCreate(bssl::CertPathBuilderResultPath * path)237   static PathBuilderDelegateDataImpl* GetOrCreate(
238       bssl::CertPathBuilderResultPath* path) {
239     if (!path->delegate_data)
240       path->delegate_data = std::make_unique<PathBuilderDelegateDataImpl>();
241     return static_cast<PathBuilderDelegateDataImpl*>(path->delegate_data.get());
242   }
243 
244   bssl::OCSPVerifyResult stapled_ocsp_verify_result;
245 };
246 
247 // TODO(eroman): The path building code in this file enforces its idea of weak
248 // keys, and signature algorithms, but separately cert_verify_proc.cc also
249 // checks the chains with its own policy. These policies must be aligned to
250 // give path building the best chance of finding a good path.
251 class PathBuilderDelegateImpl : public bssl::SimplePathBuilderDelegate {
252  public:
253   // Uses the default policy from bssl::SimplePathBuilderDelegate, which
254   // requires RSA keys to be at least 1024-bits large, and optionally accepts
255   // SHA1 certificates.
PathBuilderDelegateImpl(const CRLSet * crl_set,CertNetFetcher * net_fetcher,VerificationType verification_type,bssl::SimplePathBuilderDelegate::DigestPolicy digest_policy,int flags,const CertVerifyProcTrustStore * trust_store,base::StringPiece stapled_leaf_ocsp_response,const EVRootCAMetadata * ev_metadata,bool * checked_revocation_for_some_path,base::TimeTicks deadline)256   PathBuilderDelegateImpl(
257       const CRLSet* crl_set,
258       CertNetFetcher* net_fetcher,
259       VerificationType verification_type,
260       bssl::SimplePathBuilderDelegate::DigestPolicy digest_policy,
261       int flags,
262       const CertVerifyProcTrustStore* trust_store,
263       base::StringPiece stapled_leaf_ocsp_response,
264       const EVRootCAMetadata* ev_metadata,
265       bool* checked_revocation_for_some_path,
266       base::TimeTicks deadline)
267       : bssl::SimplePathBuilderDelegate(1024, digest_policy),
268         crl_set_(crl_set),
269         net_fetcher_(net_fetcher),
270         verification_type_(verification_type),
271         flags_(flags),
272         trust_store_(trust_store),
273         stapled_leaf_ocsp_response_(stapled_leaf_ocsp_response),
274         ev_metadata_(ev_metadata),
275         checked_revocation_for_some_path_(checked_revocation_for_some_path),
276         deadline_(deadline) {}
277 
278   // This is called for each built chain, including ones which failed. It is
279   // responsible for adding errors to the built chain if it is not acceptable.
CheckPathAfterVerification(const bssl::CertPathBuilder & path_builder,bssl::CertPathBuilderResultPath * path)280   void CheckPathAfterVerification(
281       const bssl::CertPathBuilder& path_builder,
282       bssl::CertPathBuilderResultPath* path) override {
283     // If the path is already invalid, don't check revocation status. The chain
284     // is expected to be valid when doing revocation checks (since for instance
285     // the correct issuer for a certificate may need to be known). Also if
286     // certificates are already expired, obtaining their revocation status may
287     // fail.
288     //
289     // TODO(eroman): When CertVerifyProcBuiltin fails to find a valid path,
290     //               whatever (partial/incomplete) path it does return should
291     //               minimally be checked with the CRLSet.
292     if (!path->IsValid())
293       return;
294 
295     // If EV was requested the certificate must chain to a recognized EV root
296     // and have one of its recognized EV policy OIDs.
297     if (verification_type_ == VerificationType::kEV) {
298       if (!ConformsToEVPolicy(path)) {
299         path->errors.GetErrorsForCert(0)->AddError(kPathLacksEVPolicy);
300         return;
301       }
302     }
303 
304     // Select an appropriate revocation policy for this chain based on the
305     // verifier flags and root.
306     RevocationPolicy policy = ChooseRevocationPolicy(path->certs);
307 
308     // Check for revocations using the CRLSet.
309     switch (
310         CheckChainRevocationUsingCRLSet(crl_set_, path->certs, &path->errors)) {
311       case CRLSet::Result::REVOKED:
312         return;
313       case CRLSet::Result::GOOD:
314         break;
315       case CRLSet::Result::UNKNOWN:
316         // CRLSet was inconclusive.
317         break;
318     }
319 
320     if (policy.check_revocation)
321       *checked_revocation_for_some_path_ = true;
322 
323     // Check the revocation status for each certificate in the chain according
324     // to |policy|. Depending on the policy, errors will be added to the
325     // respective certificates, so |errors->ContainsHighSeverityErrors()| will
326     // reflect the revocation status of the chain after this call.
327     CheckValidatedChainRevocation(
328         path->certs, policy, deadline_, stapled_leaf_ocsp_response_,
329         net_fetcher_, &path->errors,
330         &PathBuilderDelegateDataImpl::GetOrCreate(path)
331              ->stapled_ocsp_verify_result);
332   }
333 
334  private:
335   // Selects a revocation policy based on the CertVerifier flags and the given
336   // certificate chain.
ChooseRevocationPolicy(const bssl::ParsedCertificateList & certs)337   RevocationPolicy ChooseRevocationPolicy(
338       const bssl::ParsedCertificateList& certs) {
339     if (flags_ & CertVerifyProc::VERIFY_DISABLE_NETWORK_FETCHES) {
340       // In theory when network fetches are disabled but revocation is enabled
341       // we could continue with networking_allowed=false (and
342       // VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS would also have to change
343       // allow_missing_info and allow_unable_to_check to true).
344       // That theoretically could allow still consulting any cached CRLs/etc.
345       // However in the way things are currently implemented in the builtin
346       // verifier there really is no point to bothering, just disable
347       // revocation checking if network fetches are disabled.
348       return NoRevocationChecking();
349     }
350 
351     // Use hard-fail revocation checking for local trust anchors, if requested
352     // by the load flag and the chain uses a non-public root.
353     if ((flags_ & CertVerifyProc::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) &&
354         !certs.empty() && !trust_store_->IsKnownRoot(certs.back().get())) {
355       RevocationPolicy policy;
356       policy.check_revocation = true;
357       policy.networking_allowed = true;
358       policy.crl_allowed = true;
359       policy.allow_missing_info = false;
360       policy.allow_unable_to_check = false;
361       policy.enforce_baseline_requirements = false;
362       return policy;
363     }
364 
365     // Use soft-fail revocation checking for VERIFY_REV_CHECKING_ENABLED.
366     if (flags_ & CertVerifyProc::VERIFY_REV_CHECKING_ENABLED) {
367       const bool is_known_root =
368           !certs.empty() && trust_store_->IsKnownRoot(certs.back().get());
369       RevocationPolicy policy;
370       policy.check_revocation = true;
371       policy.networking_allowed = true;
372       // Publicly trusted certs are required to have OCSP by the Baseline
373       // Requirements and CRLs can be quite large, so disable the fallback to
374       // CRLs for chains to known roots.
375       policy.crl_allowed = !is_known_root;
376       policy.allow_missing_info = true;
377       policy.allow_unable_to_check = true;
378       policy.enforce_baseline_requirements = is_known_root;
379       return policy;
380     }
381 
382     return NoRevocationChecking();
383   }
384 
385   // Returns true if |path| chains to an EV root, and the chain conforms to one
386   // of its EV policy OIDs. When building paths all candidate EV policy OIDs
387   // were requested, so it is just a matter of testing each of the policies the
388   // chain conforms to.
ConformsToEVPolicy(const bssl::CertPathBuilderResultPath * path)389   bool ConformsToEVPolicy(const bssl::CertPathBuilderResultPath* path) {
390     const bssl::ParsedCertificate* root = path->GetTrustedCert();
391     if (!root)
392       return false;
393 
394     SHA256HashValue root_fingerprint;
395     crypto::SHA256HashString(root->der_cert().AsStringView(),
396                              root_fingerprint.data,
397                              sizeof(root_fingerprint.data));
398 
399     for (const bssl::der::Input& oid : path->user_constrained_policy_set) {
400       if (ev_metadata_->HasEVPolicyOID(root_fingerprint, oid)) {
401         return true;
402       }
403     }
404 
405     return false;
406   }
407 
IsDeadlineExpired()408   bool IsDeadlineExpired() override {
409     return !deadline_.is_null() && base::TimeTicks::Now() > deadline_;
410   }
411 
412   raw_ptr<const CRLSet> crl_set_;
413   raw_ptr<CertNetFetcher> net_fetcher_;
414   const VerificationType verification_type_;
415   const int flags_;
416   raw_ptr<const CertVerifyProcTrustStore> trust_store_;
417   const base::StringPiece stapled_leaf_ocsp_response_;
418   raw_ptr<const EVRootCAMetadata> ev_metadata_;
419   raw_ptr<bool> checked_revocation_for_some_path_;
420   base::TimeTicks deadline_;
421 };
422 
ParseCertificateFromBuffer(CRYPTO_BUFFER * cert_handle,bssl::CertErrors * errors)423 std::shared_ptr<const bssl::ParsedCertificate> ParseCertificateFromBuffer(
424     CRYPTO_BUFFER* cert_handle,
425     bssl::CertErrors* errors) {
426   return bssl::ParsedCertificate::Create(
427       bssl::UpRef(cert_handle), x509_util::DefaultParseCertificateOptions(),
428       errors);
429 }
430 
431 class CertVerifyProcBuiltin : public CertVerifyProc {
432  public:
433   CertVerifyProcBuiltin(scoped_refptr<CertNetFetcher> net_fetcher,
434                         scoped_refptr<CRLSet> crl_set,
435                         std::unique_ptr<SystemTrustStore> system_trust_store,
436                         const CertVerifyProc::InstanceParams& instance_params);
437 
438  protected:
439   ~CertVerifyProcBuiltin() override;
440 
441  private:
442   int VerifyInternal(X509Certificate* cert,
443                      const std::string& hostname,
444                      const std::string& ocsp_response,
445                      const std::string& sct_list,
446                      int flags,
447                      CertVerifyResult* verify_result,
448                      const NetLogWithSource& net_log) override;
449 
450   const scoped_refptr<CertNetFetcher> net_fetcher_;
451   const std::unique_ptr<SystemTrustStore> system_trust_store_;
452   bssl::TrustStoreInMemory additional_trust_store_;
453 };
454 
CertVerifyProcBuiltin(scoped_refptr<CertNetFetcher> net_fetcher,scoped_refptr<CRLSet> crl_set,std::unique_ptr<SystemTrustStore> system_trust_store,const CertVerifyProc::InstanceParams & instance_params)455 CertVerifyProcBuiltin::CertVerifyProcBuiltin(
456     scoped_refptr<CertNetFetcher> net_fetcher,
457     scoped_refptr<CRLSet> crl_set,
458     std::unique_ptr<SystemTrustStore> system_trust_store,
459     const CertVerifyProc::InstanceParams& instance_params)
460     : CertVerifyProc(std::move(crl_set)),
461       net_fetcher_(std::move(net_fetcher)),
462       system_trust_store_(std::move(system_trust_store)) {
463   DCHECK(system_trust_store_);
464 
465   NetLogWithSource net_log =
466       NetLogWithSource::Make(net::NetLogSourceType::CERT_VERIFY_PROC_CREATED);
467   net_log.BeginEvent(NetLogEventType::CERT_VERIFY_PROC_CREATED);
468 
469   // Parse the additional trust anchors and setup trust store.
470   for (const auto& x509_cert : instance_params.additional_trust_anchors) {
471     bssl::CertErrors parsing_errors;
472     std::shared_ptr<const bssl::ParsedCertificate> cert =
473         ParseCertificateFromBuffer(x509_cert->cert_buffer(), &parsing_errors);
474     if (cert) {
475       additional_trust_store_.AddTrustAnchor(std::move(cert));
476     }
477     net_log.AddEvent(NetLogEventType::CERT_VERIFY_PROC_ADDITIONAL_CERT, [&] {
478       return NetLogAdditionalCert(x509_cert->cert_buffer(),
479                                   bssl::CertificateTrust::ForTrustAnchor(),
480                                   parsing_errors);
481     });
482   }
483 
484   for (const auto& x509_cert :
485        instance_params.additional_untrusted_authorities) {
486     bssl::CertErrors parsing_errors;
487     std::shared_ptr<const bssl::ParsedCertificate> cert =
488         ParseCertificateFromBuffer(x509_cert->cert_buffer(), &parsing_errors);
489     // Only add the untrusted cert if it isn't already present in
490     // `additional_trust_store_`. If the same cert was already added as a
491     // trust anchor then adding it again as an untrusted cert can lead to it
492     // not being treated as a trust anchor since TrustStoreInMemory doesn't
493     // expect to contain duplicates.
494     if (cert && !additional_trust_store_.Contains(cert.get())) {
495       additional_trust_store_.AddCertificateWithUnspecifiedTrust(
496           std::move(cert));
497     }
498     net_log.AddEvent(NetLogEventType::CERT_VERIFY_PROC_ADDITIONAL_CERT, [&] {
499       return NetLogAdditionalCert(x509_cert->cert_buffer(),
500                                   bssl::CertificateTrust::ForUnspecified(),
501                                   parsing_errors);
502     });
503   }
504 
505   net_log.EndEvent(NetLogEventType::CERT_VERIFY_PROC_CREATED);
506 }
507 
508 CertVerifyProcBuiltin::~CertVerifyProcBuiltin() = default;
509 
AddIntermediatesToIssuerSource(X509Certificate * x509_cert,bssl::CertIssuerSourceStatic * intermediates,const NetLogWithSource & net_log)510 void AddIntermediatesToIssuerSource(X509Certificate* x509_cert,
511                                     bssl::CertIssuerSourceStatic* intermediates,
512                                     const NetLogWithSource& net_log) {
513   for (const auto& intermediate : x509_cert->intermediate_buffers()) {
514     bssl::CertErrors errors;
515     std::shared_ptr<const bssl::ParsedCertificate> cert =
516         ParseCertificateFromBuffer(intermediate.get(), &errors);
517     // TODO(crbug.com/634484): this duplicates the logging of the input chain
518     // maybe should only log if there is a parse error/warning?
519     net_log.AddEvent(NetLogEventType::CERT_VERIFY_PROC_INPUT_CERT, [&] {
520       return NetLogCertParams(intermediate.get(), errors);
521     });
522     if (cert) {
523       intermediates->AddCert(std::move(cert));
524     }
525   }
526 }
527 
528 // Appends the SHA256 hashes of |spki_bytes| to |*hashes|.
529 // TODO(eroman): Hashes are also calculated at other times (such as when
530 //               checking CRLSet). Consider caching to avoid recalculating (say
531 //               in the delegate's PathInfo).
AppendPublicKeyHashes(const bssl::der::Input & spki_bytes,HashValueVector * hashes)532 void AppendPublicKeyHashes(const bssl::der::Input& spki_bytes,
533                            HashValueVector* hashes) {
534   HashValue sha256(HASH_VALUE_SHA256);
535   crypto::SHA256HashString(spki_bytes.AsStringView(), sha256.data(),
536                            crypto::kSHA256Length);
537   hashes->push_back(sha256);
538 }
539 
540 // Appends the SubjectPublicKeyInfo hashes for all certificates in
541 // |path| to |*hashes|.
AppendPublicKeyHashes(const bssl::CertPathBuilderResultPath & path,HashValueVector * hashes)542 void AppendPublicKeyHashes(const bssl::CertPathBuilderResultPath& path,
543                            HashValueVector* hashes) {
544   for (const std::shared_ptr<const bssl::ParsedCertificate>& cert :
545        path.certs) {
546     AppendPublicKeyHashes(cert->tbs().spki_tlv, hashes);
547   }
548 }
549 
550 // Sets the bits on |cert_status| for all the errors present in |errors| (the
551 // errors for a particular path).
MapPathBuilderErrorsToCertStatus(const bssl::CertPathErrors & errors,CertStatus * cert_status)552 void MapPathBuilderErrorsToCertStatus(const bssl::CertPathErrors& errors,
553                                       CertStatus* cert_status) {
554   // If there were no errors, nothing to do.
555   if (!errors.ContainsHighSeverityErrors())
556     return;
557 
558   if (errors.ContainsError(bssl::cert_errors::kCertificateRevoked)) {
559     *cert_status |= CERT_STATUS_REVOKED;
560   }
561 
562   if (errors.ContainsError(bssl::cert_errors::kNoRevocationMechanism)) {
563     *cert_status |= CERT_STATUS_NO_REVOCATION_MECHANISM;
564   }
565 
566   if (errors.ContainsError(bssl::cert_errors::kUnableToCheckRevocation)) {
567     *cert_status |= CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
568   }
569 
570   if (errors.ContainsError(bssl::cert_errors::kUnacceptablePublicKey)) {
571     *cert_status |= CERT_STATUS_WEAK_KEY;
572   }
573 
574   if (errors.ContainsError(bssl::cert_errors::kValidityFailedNotAfter) ||
575       errors.ContainsError(bssl::cert_errors::kValidityFailedNotBefore)) {
576     *cert_status |= CERT_STATUS_DATE_INVALID;
577   }
578 
579   if (errors.ContainsError(bssl::cert_errors::kDistrustedByTrustStore) ||
580       errors.ContainsError(bssl::cert_errors::kVerifySignedDataFailed) ||
581       errors.ContainsError(bssl::cert_errors::kNoIssuersFound) ||
582       errors.ContainsError(bssl::cert_errors::kSubjectDoesNotMatchIssuer) ||
583       errors.ContainsError(bssl::cert_errors::kDeadlineExceeded) ||
584       errors.ContainsError(bssl::cert_errors::kIterationLimitExceeded)) {
585     *cert_status |= CERT_STATUS_AUTHORITY_INVALID;
586   }
587 
588   // IMPORTANT: If the path was invalid for a reason that was not
589   // explicity checked above, set a general error. This is important as
590   // |cert_status| is what ultimately indicates whether verification was
591   // successful or not (absence of errors implies success).
592   if (!IsCertStatusError(*cert_status))
593     *cert_status |= CERT_STATUS_INVALID;
594 }
595 
596 // Creates a X509Certificate (chain) to return as the verified result.
597 //
598 //  * |target_cert|: The original X509Certificate that was passed in to
599 //                   VerifyInternal()
600 //  * |path|: The result (possibly failed) from path building.
CreateVerifiedCertChain(X509Certificate * target_cert,const bssl::CertPathBuilderResultPath & path)601 scoped_refptr<X509Certificate> CreateVerifiedCertChain(
602     X509Certificate* target_cert,
603     const bssl::CertPathBuilderResultPath& path) {
604   std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates;
605 
606   // Skip the first certificate in the path as that is the target certificate
607   for (size_t i = 1; i < path.certs.size(); ++i) {
608     intermediates.push_back(bssl::UpRef(path.certs[i]->cert_buffer()));
609   }
610 
611   scoped_refptr<X509Certificate> result =
612       target_cert->CloneWithDifferentIntermediates(std::move(intermediates));
613   DCHECK(result);
614 
615   return result;
616 }
617 
618 // Describes the parameters for a single path building attempt. Path building
619 // may be re-tried with different parameters for EV and for accepting SHA1
620 // certificates.
621 struct BuildPathAttempt {
BuildPathAttemptnet::__anon8ce759310111::BuildPathAttempt622   BuildPathAttempt(VerificationType verification_type,
623                    bssl::SimplePathBuilderDelegate::DigestPolicy digest_policy)
624       : verification_type(verification_type), digest_policy(digest_policy) {}
625 
BuildPathAttemptnet::__anon8ce759310111::BuildPathAttempt626   explicit BuildPathAttempt(VerificationType verification_type)
627       : BuildPathAttempt(
628             verification_type,
629             bssl::SimplePathBuilderDelegate::DigestPolicy::kStrong) {}
630 
631   VerificationType verification_type;
632   bssl::SimplePathBuilderDelegate::DigestPolicy digest_policy;
633 };
634 
TryBuildPath(const std::shared_ptr<const bssl::ParsedCertificate> & target,bssl::CertIssuerSourceStatic * intermediates,CertVerifyProcTrustStore * trust_store,const bssl::der::GeneralizedTime & der_verification_time,base::TimeTicks deadline,VerificationType verification_type,bssl::SimplePathBuilderDelegate::DigestPolicy digest_policy,int flags,const std::string & ocsp_response,const CRLSet * crl_set,CertNetFetcher * net_fetcher,const EVRootCAMetadata * ev_metadata,bool * checked_revocation)635 bssl::CertPathBuilder::Result TryBuildPath(
636     const std::shared_ptr<const bssl::ParsedCertificate>& target,
637     bssl::CertIssuerSourceStatic* intermediates,
638     CertVerifyProcTrustStore* trust_store,
639     const bssl::der::GeneralizedTime& der_verification_time,
640     base::TimeTicks deadline,
641     VerificationType verification_type,
642     bssl::SimplePathBuilderDelegate::DigestPolicy digest_policy,
643     int flags,
644     const std::string& ocsp_response,
645     const CRLSet* crl_set,
646     CertNetFetcher* net_fetcher,
647     const EVRootCAMetadata* ev_metadata,
648     bool* checked_revocation) {
649   // Path building will require candidate paths to conform to at least one of
650   // the policies in |user_initial_policy_set|.
651   std::set<bssl::der::Input> user_initial_policy_set;
652 
653   if (verification_type == VerificationType::kEV) {
654     GetEVPolicyOids(ev_metadata, target.get(), &user_initial_policy_set);
655     // TODO(crbug.com/634484): netlog user_initial_policy_set.
656   } else {
657     user_initial_policy_set = {bssl::der::Input(bssl::kAnyPolicyOid)};
658   }
659 
660   PathBuilderDelegateImpl path_builder_delegate(
661       crl_set, net_fetcher, verification_type, digest_policy, flags,
662       trust_store, ocsp_response, ev_metadata, checked_revocation, deadline);
663 
664   absl::optional<CertIssuerSourceAia> aia_cert_issuer_source;
665 
666   // Initialize the path builder.
667   bssl::CertPathBuilder path_builder(
668       target, trust_store->trust_store(), &path_builder_delegate,
669       der_verification_time, bssl::KeyPurpose::SERVER_AUTH,
670       bssl::InitialExplicitPolicy::kFalse, user_initial_policy_set,
671       bssl::InitialPolicyMappingInhibit::kFalse,
672       bssl::InitialAnyPolicyInhibit::kFalse);
673 
674   // Allow the path builder to discover the explicitly provided intermediates in
675   // |input_cert|.
676   path_builder.AddCertIssuerSource(intermediates);
677 
678   // Allow the path builder to discover intermediates through AIA fetching.
679   // TODO(crbug.com/634484): hook up netlog to AIA.
680   if (!(flags & CertVerifyProc::VERIFY_DISABLE_NETWORK_FETCHES)) {
681     if (net_fetcher) {
682       aia_cert_issuer_source.emplace(net_fetcher);
683       path_builder.AddCertIssuerSource(&aia_cert_issuer_source.value());
684     } else {
685       LOG(ERROR) << "No net_fetcher for performing AIA chasing.";
686     }
687   }
688 
689   if (base::FeatureList::IsEnabled(
690           features::kNewCertPathBuilderIterationLimit)) {
691     path_builder.SetIterationLimit(kPathBuilderIterationLimitNew);
692   } else {
693     path_builder.SetIterationLimit(kPathBuilderIterationLimit);
694   }
695 
696   return path_builder.Run();
697 }
698 
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)699 int AssignVerifyResult(X509Certificate* input_cert,
700                        const std::string& hostname,
701                        bssl::CertPathBuilder::Result& result,
702                        VerificationType verification_type,
703                        bool checked_revocation_for_some_path,
704                        CertVerifyProcTrustStore* trust_store,
705                        CertVerifyResult* verify_result) {
706   const bssl::CertPathBuilderResultPath* best_path_possibly_invalid =
707       result.GetBestPathPossiblyInvalid();
708 
709   if (!best_path_possibly_invalid) {
710     // TODO(crbug.com/634443): What errors to communicate? Maybe the path
711     // builder should always return some partial path (even if just containing
712     // the target), then there is a bssl::CertErrors to test.
713     verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
714     return ERR_CERT_AUTHORITY_INVALID;
715   }
716 
717   const bssl::CertPathBuilderResultPath& partial_path =
718       *best_path_possibly_invalid;
719 
720   AppendPublicKeyHashes(partial_path, &verify_result->public_key_hashes);
721 
722   for (auto it = verify_result->public_key_hashes.rbegin();
723        it != verify_result->public_key_hashes.rend() &&
724        !verify_result->is_issued_by_known_root;
725        ++it) {
726     verify_result->is_issued_by_known_root =
727         GetNetTrustAnchorHistogramIdForSPKI(*it) != 0;
728   }
729 
730   bool path_is_valid = partial_path.IsValid();
731 
732   const bssl::ParsedCertificate* trusted_cert = partial_path.GetTrustedCert();
733   if (trusted_cert) {
734     if (!verify_result->is_issued_by_known_root) {
735       verify_result->is_issued_by_known_root =
736           trust_store->IsKnownRoot(trusted_cert);
737     }
738 
739     verify_result->is_issued_by_additional_trust_anchor =
740         trust_store->IsAdditionalTrustAnchor(trusted_cert);
741   }
742 
743   if (path_is_valid && (verification_type == VerificationType::kEV)) {
744     verify_result->cert_status |= CERT_STATUS_IS_EV;
745   }
746 
747   // TODO(eroman): Add documentation for the meaning of
748   // CERT_STATUS_REV_CHECKING_ENABLED. Based on the current tests it appears to
749   // mean whether revocation checking was attempted during path building,
750   // although does not necessarily mean that revocation checking was done for
751   // the final returned path.
752   if (checked_revocation_for_some_path)
753     verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
754 
755   verify_result->verified_cert =
756       CreateVerifiedCertChain(input_cert, partial_path);
757 
758   MapPathBuilderErrorsToCertStatus(partial_path.errors,
759                                    &verify_result->cert_status);
760 
761   // TODO(eroman): Is it possible that IsValid() fails but no errors were set in
762   // partial_path.errors?
763   CHECK(path_is_valid || IsCertStatusError(verify_result->cert_status));
764 
765   if (!path_is_valid) {
766     LOG(ERROR) << "CertVerifyProcBuiltin for " << hostname << " failed:\n"
767                << partial_path.errors.ToDebugString(partial_path.certs);
768   }
769 
770   const PathBuilderDelegateDataImpl* delegate_data =
771       PathBuilderDelegateDataImpl::Get(partial_path);
772   if (delegate_data)
773     verify_result->ocsp_result = delegate_data->stapled_ocsp_verify_result;
774 
775   return IsCertStatusError(verify_result->cert_status)
776              ? MapCertStatusToNetError(verify_result->cert_status)
777              : OK;
778 }
779 
780 // Returns true if retrying path building with a less stringent signature
781 // algorithm *might* successfully build a path, based on the earlier failed
782 // |result|.
783 //
784 // This implementation is simplistic, and looks only for the presence of the
785 // kUnacceptableSignatureAlgorithm error somewhere among the built paths.
CanTryAgainWithWeakerDigestPolicy(const bssl::CertPathBuilder::Result & result)786 bool CanTryAgainWithWeakerDigestPolicy(
787     const bssl::CertPathBuilder::Result& result) {
788   return result.AnyPathContainsError(
789       bssl::cert_errors::kUnacceptableSignatureAlgorithm);
790 }
791 
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)792 int CertVerifyProcBuiltin::VerifyInternal(
793     X509Certificate* input_cert,
794     const std::string& hostname,
795     const std::string& ocsp_response,
796     const std::string& sct_list,
797     int flags,
798     CertVerifyResult* verify_result,
799     const NetLogWithSource& net_log) {
800   // VerifyInternal() is expected to carry out verifications using the current
801   // time stamp.
802   base::Time verification_time = base::Time::Now();
803   base::TimeTicks deadline = base::TimeTicks::Now() + kMaxVerificationTime;
804   bssl::der::GeneralizedTime der_verification_time;
805   if (!EncodeTimeAsGeneralizedTime(verification_time, &der_verification_time)) {
806     // This shouldn't be possible.
807     // We don't really have a good error code for this type of error.
808     verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
809     return ERR_CERT_AUTHORITY_INVALID;
810   }
811 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
812   int64_t chrome_root_store_version =
813       system_trust_store_->chrome_root_store_version();
814   if (chrome_root_store_version != 0) {
815     net_log.AddEvent(
816         NetLogEventType::CERT_VERIFY_PROC_CHROME_ROOT_STORE_VERSION, [&] {
817           return NetLogChromeRootStoreVersion(chrome_root_store_version);
818         });
819   }
820 #endif
821 
822   // TODO(crbug.com/1477317): Netlog extra configuration information stored
823   // inside CertVerifyProcBuiltin (e.g. certs in additional_trust_store and
824   // system trust store)
825 
826   // Parse the target certificate.
827   std::shared_ptr<const bssl::ParsedCertificate> target;
828   {
829     bssl::CertErrors parsing_errors;
830     target =
831         ParseCertificateFromBuffer(input_cert->cert_buffer(), &parsing_errors);
832     // TODO(crbug.com/634484): this duplicates the logging of the input chain
833     // maybe should only log if there is a parse error/warning?
834     net_log.AddEvent(NetLogEventType::CERT_VERIFY_PROC_TARGET_CERT, [&] {
835       return NetLogCertParams(input_cert->cert_buffer(), parsing_errors);
836     });
837     if (!target) {
838       verify_result->cert_status |= CERT_STATUS_INVALID;
839       return ERR_CERT_INVALID;
840     }
841   }
842 
843   // Parse the provided intermediates.
844   bssl::CertIssuerSourceStatic intermediates;
845   AddIntermediatesToIssuerSource(input_cert, &intermediates, net_log);
846 
847   CertVerifyProcTrustStore trust_store(system_trust_store_.get(),
848                                        &additional_trust_store_);
849 
850   // Get the global dependencies.
851   const EVRootCAMetadata* ev_metadata = EVRootCAMetadata::GetInstance();
852 
853   // This boolean tracks whether online revocation checking was performed for
854   // *any* of the built paths, and not just the final path returned (used for
855   // setting output flag CERT_STATUS_REV_CHECKING_ENABLED).
856   bool checked_revocation_for_some_path = false;
857 
858   // Run path building with the different parameters (attempts) until a valid
859   // path is found. Earlier successful attempts have priority over later
860   // attempts.
861   //
862   // Attempts are enqueued into |attempts| and drained in FIFO order.
863   std::vector<BuildPathAttempt> attempts;
864 
865   // First try EV validation. Can skip this if the leaf certificate has no
866   // chance of verifying as EV (lacks an EV policy).
867   if (IsEVCandidate(ev_metadata, target.get()))
868     attempts.emplace_back(VerificationType::kEV);
869 
870   // Next try DV validation.
871   attempts.emplace_back(VerificationType::kDV);
872 
873   bssl::CertPathBuilder::Result result;
874   VerificationType verification_type = VerificationType::kDV;
875 
876   // Iterate over |attempts| until there are none left to try, or an attempt
877   // succeeded.
878   for (size_t cur_attempt_index = 0; cur_attempt_index < attempts.size();
879        ++cur_attempt_index) {
880     const auto& cur_attempt = attempts[cur_attempt_index];
881     verification_type = cur_attempt.verification_type;
882     net_log.BeginEvent(
883         NetLogEventType::CERT_VERIFY_PROC_PATH_BUILD_ATTEMPT, [&] {
884           base::Value::Dict results;
885           if (verification_type == VerificationType::kEV)
886             results.Set("is_ev_attempt", true);
887           results.Set("digest_policy",
888                       static_cast<int>(cur_attempt.digest_policy));
889           return results;
890         });
891 
892     // If a previous attempt used up most/all of the deadline, extend the
893     // deadline a little bit to give this verification attempt a chance at
894     // success.
895     deadline = std::max(
896         deadline, base::TimeTicks::Now() + kPerAttemptMinVerificationTimeLimit);
897 
898     // Run the attempt through the path builder.
899     result = TryBuildPath(
900         target, &intermediates, &trust_store, der_verification_time, deadline,
901         cur_attempt.verification_type, cur_attempt.digest_policy, flags,
902         ocsp_response, crl_set(), net_fetcher_.get(), ev_metadata,
903         &checked_revocation_for_some_path);
904 
905     base::UmaHistogramCounts10000("Net.CertVerifier.PathBuilderIterationCount",
906                                   result.iteration_count);
907 
908     // TODO(crbug.com/634484): Log these in path_builder.cc so they include
909     // correct timing information.
910     for (const auto& path : result.paths) {
911       net_log.AddEvent(NetLogEventType::CERT_VERIFY_PROC_PATH_BUILT,
912                        [&] { return NetLogPathBuilderResultPath(*path); });
913     }
914 
915     net_log.EndEvent(NetLogEventType::CERT_VERIFY_PROC_PATH_BUILD_ATTEMPT,
916                      [&] { return NetLogPathBuilderResult(result); });
917 
918     if (result.HasValidPath())
919       break;
920 
921     if (result.exceeded_deadline) {
922       // Stop immediately if an attempt exceeds the deadline.
923       break;
924     }
925 
926     // If this path building attempt (may have) failed due to the chain using a
927     // weak signature algorithm, enqueue a similar attempt but with weaker
928     // signature algorithms (SHA1) permitted.
929     //
930     // This fallback is necessary because the CertVerifyProc layer may decide to
931     // allow SHA1 based on its own policy, so path building should return
932     // possibly weak chains too.
933     //
934     // TODO(eroman): Would be better for the SHA1 policy to be part of the
935     // delegate instead so it can interact with path building.
936     if (cur_attempt.digest_policy ==
937             bssl::SimplePathBuilderDelegate::DigestPolicy::kStrong &&
938         CanTryAgainWithWeakerDigestPolicy(result)) {
939       BuildPathAttempt sha1_fallback_attempt = cur_attempt;
940       sha1_fallback_attempt.digest_policy =
941           bssl::SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1;
942       attempts.push_back(sha1_fallback_attempt);
943     }
944   }
945 
946   // Write the results to |*verify_result|.
947   int error = AssignVerifyResult(
948       input_cert, hostname, result, verification_type,
949       checked_revocation_for_some_path, &trust_store, verify_result);
950   if (error == OK) {
951     LogNameNormalizationMetrics(".Builtin", verify_result->verified_cert.get(),
952                                 verify_result->is_issued_by_known_root);
953   }
954   return error;
955 }
956 
957 }  // namespace
958 
CreateCertVerifyProcBuiltin(scoped_refptr<CertNetFetcher> net_fetcher,scoped_refptr<CRLSet> crl_set,std::unique_ptr<SystemTrustStore> system_trust_store,const CertVerifyProc::InstanceParams & instance_params)959 scoped_refptr<CertVerifyProc> CreateCertVerifyProcBuiltin(
960     scoped_refptr<CertNetFetcher> net_fetcher,
961     scoped_refptr<CRLSet> crl_set,
962     std::unique_ptr<SystemTrustStore> system_trust_store,
963     const CertVerifyProc::InstanceParams& instance_params) {
964   return base::MakeRefCounted<CertVerifyProcBuiltin>(
965       std::move(net_fetcher), std::move(crl_set), std::move(system_trust_store),
966       instance_params);
967 }
968 
GetCertVerifyProcBuiltinTimeLimitForTesting()969 base::TimeDelta GetCertVerifyProcBuiltinTimeLimitForTesting() {
970   return kMaxVerificationTime;
971 }
972 
973 }  // namespace net
974