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