chromium/net/cert/cert_verify_proc.cc

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/cert/cert_verify_proc.h"

#include <stdint.h>

#include <algorithm>
#include <optional>
#include <string_view>

#include "base/containers/flat_set.h"
#include "base/containers/span.h"
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "crypto/crypto_buildflags.h"
#include "crypto/sha2.h"
#include "net/base/cronet_buildflags.h"
#include "net/base/features.h"
#include "net/base/net_errors.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/base/url_util.h"
#include "net/cert/asn1_util.h"
#include "net/cert/cert_net_fetcher.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/cert_verify_result.h"
#include "net/cert/crl_set.h"
#include "net/cert/internal/revocation_checker.h"
#include "net/cert/internal/system_trust_store.h"
#include "net/cert/known_roots.h"
#include "net/cert/symantec_certs.h"
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_certificate_net_log_param.h"
#include "net/cert/x509_util.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_values.h"
#include "net/log/net_log_with_source.h"
#include "third_party/boringssl/src/include/openssl/pool.h"
#include "third_party/boringssl/src/pki/encode_values.h"
#include "third_party/boringssl/src/pki/extended_key_usage.h"
#include "third_party/boringssl/src/pki/ocsp.h"
#include "third_party/boringssl/src/pki/ocsp_revocation_status.h"
#include "third_party/boringssl/src/pki/parse_certificate.h"
#include "third_party/boringssl/src/pki/pem.h"
#include "third_party/boringssl/src/pki/signature_algorithm.h"
#include "url/url_canon.h"

#if BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
#include "net/cert/cert_verify_proc_builtin.h"
#endif

#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
#include "net/cert/internal/trust_store_chrome.h"
#endif  // CHROME_ROOT_STORE_SUPPORTED

#if BUILDFLAG(IS_ANDROID)
#include "net/cert/cert_verify_proc_android.h"
#elif BUILDFLAG(IS_IOS)
#include "net/cert/cert_verify_proc_ios.h"
#endif

namespace net {

namespace {

// Constants used to build histogram names
const char kLeafCert[] =;
const char kIntermediateCert[] =;
const char kRootCert[] =;

// Histogram buckets for RSA key sizes, as well as unknown key types. RSA key
// sizes < 1024 bits should cause errors, while key sizes > 16K are not
// supported by BoringSSL.
const int kRsaKeySizes[] =;
// Histogram buckets for ECDSA key sizes. The list was historically based upon
// FIPS 186-4 approved curves, but most are impossible. BoringSSL will only ever
// return P-224, P-256, P-384, or P-521, and the verifier will reject P-224.
const int kEcdsaKeySizes[] =;

const char* CertTypeToString(X509Certificate::PublicKeyType cert_type) {}

void RecordPublicKeyHistogram(const char* chain_position,
                              bool baseline_keysize_applies,
                              size_t size_bits,
                              X509Certificate::PublicKeyType cert_type) {}

// Returns true if |type| is |kPublicKeyTypeRSA| and if |size_bits| is < 1024.
// Note that this means there may be false negatives: keys for other algorithms
// and which are weak will pass this test.
bool IsWeakKey(X509Certificate::PublicKeyType type, size_t size_bits) {}

// Returns true if |cert| contains a known-weak key. Additionally, histograms
// the observed keys for future tightening of the definition of what
// constitutes a weak key.
bool ExaminePublicKeys(const scoped_refptr<X509Certificate>& cert,
                       bool should_histogram) {}

void BestEffortCheckOCSP(const std::string& raw_response,
                         const X509Certificate& certificate,
                         bssl::OCSPVerifyResult* verify_result) {}

// Records details about the most-specific trust anchor in |hashes|, which is
// expected to be ordered with the leaf cert first and the root cert last.
// "Most-specific" refers to the case that it is not uncommon to have multiple
// potential trust anchors present in a chain, depending on the client trust
// store. For example, '1999-Root' cross-signing '2005-Root' cross-signing
// '2012-Root' cross-signing '2017-Root', then followed by intermediate and
// leaf. For purposes of assessing impact of, say, removing 1999-Root, while
// including 2017-Root as a trust anchor, then the validation should be
// counted as 2017-Root, rather than 1999-Root.
//
// This also accounts for situations in which a new CA is introduced, and
// has been cross-signed by an existing CA. Assessing impact should use the
// most-specific trust anchor, when possible.
//
// This also histograms for divergence between the root store and
// |spki_hashes| - that is, situations in which the OS methods of detecting
// a known root flag a certificate as known, but its hash is not known as part
// of the built-in list.
void RecordTrustAnchorHistogram(const HashValueVector& spki_hashes,
                                bool is_issued_by_known_root) {}

// Inspects the signature algorithms in a single certificate |cert|.
//
//   * Sets |verify_result->has_sha1| to true if the certificate uses SHA1.
//
// Returns false if the signature algorithm was unknown or mismatched.
[[nodiscard]] bool InspectSignatureAlgorithmForCert(
    const CRYPTO_BUFFER* cert,
    CertVerifyResult* verify_result) {}

// InspectSignatureAlgorithmsInChain() sets |verify_result->has_*| based on
// the signature algorithms used in the chain, and also checks that certificates
// don't have contradictory signature algorithms.
//
// Returns false if any signature algorithm in the chain is unknown or
// mismatched.
//
// Background:
//
// X.509 certificates contain two redundant descriptors for the signature
// algorithm; one is covered by the signature, but in order to verify the
// signature, the other signature algorithm is untrusted.
//
// RFC 5280 states that the two should be equal, in order to mitigate risk of
// signature substitution attacks, but also discourages verifiers from enforcing
// the profile of RFC 5280.
//
// System verifiers are inconsistent - some use the unsigned signature, some use
// the signed signature, and they generally do not enforce that both match. This
// creates confusion, as it's possible that the signature itself may be checked
// using algorithm A, but if subsequent consumers report the certificate
// algorithm, they may end up reporting algorithm B, which was not used to
// verify the certificate. This function enforces that the two signatures match
// in order to prevent such confusion.
[[nodiscard]] bool InspectSignatureAlgorithmsInChain(
    CertVerifyResult* verify_result) {}

base::Value::Dict CertVerifyParams(X509Certificate* cert,
                                   const std::string& hostname,
                                   const std::string& ocsp_response,
                                   const std::string& sct_list,
                                   int flags,
                                   CRLSet* crl_set) {}

}  // namespace

#if !(BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(CHROME_ROOT_STORE_ONLY))
// static
scoped_refptr<CertVerifyProc> CertVerifyProc::CreateSystemVerifyProc(
    scoped_refptr<CertNetFetcher> cert_net_fetcher,
    scoped_refptr<CRLSet> crl_set) {
#if BUILDFLAG(IS_ANDROID)
  return base::MakeRefCounted<CertVerifyProcAndroid>(
      std::move(cert_net_fetcher), std::move(crl_set));
#elif BUILDFLAG(IS_IOS)
  return base::MakeRefCounted<CertVerifyProcIOS>(std::move(crl_set));
#else
#error Unsupported platform
#endif
}
#endif

#if BUILDFLAG(IS_FUCHSIA)
// static
scoped_refptr<CertVerifyProc> CertVerifyProc::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) {
  return CreateCertVerifyProcBuiltin(
      std::move(cert_net_fetcher), std::move(crl_set), std::move(ct_verifier),
      std::move(ct_policy_enforcer), CreateSslSystemTrustStore(),
      instance_params, std::move(time_tracker));
}
#endif

#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
// static
scoped_refptr<CertVerifyProc> CertVerifyProc::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) {}
#endif

CertVerifyProc::CertVerifyProc(scoped_refptr<CRLSet> crl_set)
    :{}

CertVerifyProc::~CertVerifyProc() = default;

int CertVerifyProc::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) {}

// static
void CertVerifyProc::LogNameNormalizationResult(
    const std::string& histogram_suffix,
    NameNormalizationResult result) {}

// static
void CertVerifyProc::LogNameNormalizationMetrics(
    const std::string& histogram_suffix,
    X509Certificate* verified_cert,
    bool is_issued_by_known_root) {}

// CheckNameConstraints verifies that every name in |dns_names| is in one of
// the domains specified by |domains|.
static bool CheckNameConstraints(const std::vector<std::string>& dns_names,
                                 base::span<const std::string_view> domains) {}

// static
bool CertVerifyProc::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) {}

// static
bool CertVerifyProc::HasTooLongValidity(const X509Certificate& cert) {}

CertVerifyProc::ImplParams::ImplParams() {}

CertVerifyProc::ImplParams::~ImplParams() = default;

CertVerifyProc::ImplParams::ImplParams(const ImplParams&) = default;
CertVerifyProc::ImplParams& CertVerifyProc::ImplParams::operator=(
    const ImplParams& other) = default;
CertVerifyProc::ImplParams::ImplParams(ImplParams&&) = default;
CertVerifyProc::ImplParams& CertVerifyProc::ImplParams::operator=(
    ImplParams&& other) = default;

CertVerifyProc::InstanceParams::InstanceParams() = default;
CertVerifyProc::InstanceParams::~InstanceParams() = default;

CertVerifyProc::InstanceParams::InstanceParams(const InstanceParams&) = default;
CertVerifyProc::InstanceParams& CertVerifyProc::InstanceParams::operator=(
    const InstanceParams& other) = default;
CertVerifyProc::InstanceParams::InstanceParams(InstanceParams&&) = default;
CertVerifyProc::InstanceParams& CertVerifyProc::InstanceParams::operator=(
    InstanceParams&& other) = default;

CertVerifyProc::CertificateWithConstraints::CertificateWithConstraints() =
    default;
CertVerifyProc::CertificateWithConstraints::~CertificateWithConstraints() =
    default;

CertVerifyProc::CertificateWithConstraints::CertificateWithConstraints(
    const CertificateWithConstraints&) = default;
CertVerifyProc::CertificateWithConstraints&
CertVerifyProc::CertificateWithConstraints::operator=(
    const CertificateWithConstraints& other) = default;
CertVerifyProc::CertificateWithConstraints::CertificateWithConstraints(
    CertificateWithConstraints&&) = default;
CertVerifyProc::CertificateWithConstraints&
CertVerifyProc::CertificateWithConstraints::operator=(
    CertificateWithConstraints&& other) = default;

}  // namespace net