blob: 962046b075e816307fde6b7696cb01a127f5c263 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/cert_verifier/cert_verifier_creation.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "net/base/features.h"
#include "net/cert/cert_verify_proc.h"
#include "net/cert/multi_threaded_cert_verifier.h"
#include "net/cert_net/cert_net_fetcher_url_request.h"
#include "net/net_buildflags.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "crypto/nss_util_internal.h"
#include "net/cert/cert_verify_proc_builtin.h"
#include "net/cert/internal/system_trust_store.h"
#include "net/cert/internal/system_trust_store_nss.h"
#endif
#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
#include "net/cert/cert_verify_proc_builtin.h"
#include "net/cert/internal/system_trust_store.h"
#endif
#if BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED)
#include "services/cert_verifier/trial_comparison_cert_verifier_mojo.h"
#endif
namespace cert_verifier {
namespace {
#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
bool UsingBuiltinCertVerifier(
mojom::CertVerifierCreationParams::CertVerifierImpl mode) {
switch (mode) {
case mojom::CertVerifierCreationParams::CertVerifierImpl::kDefault:
return base::FeatureList::IsEnabled(
net::features::kCertVerifierBuiltinFeature);
case mojom::CertVerifierCreationParams::CertVerifierImpl::kBuiltin:
return true;
case mojom::CertVerifierCreationParams::CertVerifierImpl::kSystem:
return false;
}
}
#endif
#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
bool UsingChromeRootStore(
mojom::CertVerifierCreationParams::ChromeRootImpl mode) {
switch (mode) {
case mojom::CertVerifierCreationParams::ChromeRootImpl::kRootDefault:
return base::FeatureList::IsEnabled(net::features::kChromeRootStoreUsed);
case mojom::CertVerifierCreationParams::ChromeRootImpl::kRootChrome:
return true;
case mojom::CertVerifierCreationParams::ChromeRootImpl::kRootSystem:
return false;
}
}
#endif // BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
#if BUILDFLAG(IS_CHROMEOS_ASH)
scoped_refptr<net::CertVerifyProc> CreateCertVerifyProcForUser(
scoped_refptr<net::CertNetFetcher> net_fetcher,
crypto::ScopedPK11Slot user_public_slot) {
return net::CreateCertVerifyProcBuiltin(
std::move(net_fetcher),
net::CreateSslSystemTrustStoreNSSWithUserSlotRestriction(
std::move(user_public_slot)));
}
scoped_refptr<net::CertVerifyProc> CreateCertVerifyProcWithoutUserSlots(
scoped_refptr<net::CertNetFetcher> net_fetcher) {
return net::CreateCertVerifyProcBuiltin(
std::move(net_fetcher),
net::CreateSslSystemTrustStoreNSSWithNoUserSlots());
}
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
// Create the CertVerifyProc that is well-tested and stable for the platform in
// question.
scoped_refptr<net::CertVerifyProc> CreateOldDefaultWithoutCaching(
scoped_refptr<net::CertNetFetcher> cert_net_fetcher) {
scoped_refptr<net::CertVerifyProc> verify_proc;
#if BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
verify_proc =
net::CertVerifyProc::CreateBuiltinVerifyProc(std::move(cert_net_fetcher));
#else
verify_proc =
net::CertVerifyProc::CreateSystemVerifyProc(std::move(cert_net_fetcher));
#endif
return verify_proc;
}
// In certain instances/platforms, we are trying to roll out a new
// CertVerifyProc (or a CertVerifyProc with different arguments). Create this
// new version, if one exists. Otherwise, we will defer to
// CreateOldDefaultWithoutCaching().
scoped_refptr<net::CertVerifyProc> CreateNewDefaultWithoutCaching(
scoped_refptr<net::CertNetFetcher> cert_net_fetcher) {
scoped_refptr<net::CertVerifyProc> verify_proc;
#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) && \
(BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN))
verify_proc = net::CreateCertVerifyProcBuiltin(
std::move(cert_net_fetcher), net::CreateSslSystemTrustStoreChromeRoot());
#elif BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
verify_proc =
net::CertVerifyProc::CreateBuiltinVerifyProc(std::move(cert_net_fetcher));
#else
verify_proc = CreateOldDefaultWithoutCaching(std::move(cert_net_fetcher));
#endif
return verify_proc;
}
} // namespace
bool IsUsingCertNetFetcher() {
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA) || \
BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) || \
BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED) || \
BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
return true;
#else
return false;
#endif
}
std::unique_ptr<net::CertVerifier> CreateCertVerifier(
mojom::CertVerifierCreationParams* creation_params,
scoped_refptr<net::CertNetFetcher> cert_net_fetcher) {
DCHECK(cert_net_fetcher || !IsUsingCertNetFetcher());
std::unique_ptr<net::CertVerifier> cert_verifier;
#if BUILDFLAG(IS_CHROMEOS_ASH)
// CHROMEOS_ASH does something special, so we do this first before we do
// anything else. If the trial comparisons feature ever gets supported in
// CHROMEOS_ASH we'll need to fix this.
if (!cert_verifier) {
scoped_refptr<net::CertVerifyProc> verify_proc;
if (!creation_params || creation_params->username_hash.empty()) {
verify_proc =
CreateCertVerifyProcWithoutUserSlots(std::move(cert_net_fetcher));
} else {
// Make sure NSS is initialized for the user.
crypto::InitializeNSSForChromeOSUser(creation_params->username_hash,
creation_params->nss_path.value());
crypto::ScopedPK11Slot public_slot =
crypto::GetPublicSlotForChromeOSUser(creation_params->username_hash);
verify_proc = CreateCertVerifyProcForUser(std::move(cert_net_fetcher),
std::move(public_slot));
}
cert_verifier = std::make_unique<net::MultiThreadedCertVerifier>(
std::move(verify_proc));
}
#endif
#if BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED)
// If we're doing trial verification, we always do it between the old default
// and the proposed new default, giving the user the value computed by the old
// default.
if (!cert_verifier && creation_params &&
creation_params->trial_comparison_cert_verifier_params) {
scoped_refptr<net::CertVerifyProc> primary =
CreateOldDefaultWithoutCaching(cert_net_fetcher);
scoped_refptr<net::CertVerifyProc> trial =
CreateNewDefaultWithoutCaching(cert_net_fetcher);
cert_verifier = std::make_unique<TrialComparisonCertVerifierMojo>(
creation_params->trial_comparison_cert_verifier_params->initial_allowed,
std::move(creation_params->trial_comparison_cert_verifier_params
->config_client_receiver),
std::move(creation_params->trial_comparison_cert_verifier_params
->report_client),
primary, trial);
}
#endif
bool use_new_default_for_platform = true;
#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
use_new_default_for_platform &=
creation_params
? UsingBuiltinCertVerifier(creation_params->use_builtin_cert_verifier)
: UsingBuiltinCertVerifier(
mojom::CertVerifierCreationParams::CertVerifierImpl::kDefault);
#endif
#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
use_new_default_for_platform &=
creation_params
? UsingChromeRootStore(creation_params->use_chrome_root_store)
: UsingChromeRootStore(mojom::CertVerifierCreationParams::
ChromeRootImpl::kRootDefault);
#endif
if (!cert_verifier) {
scoped_refptr<net::CertVerifyProc> verify_proc;
// If we're trying to use the new cert verifier for the platform (either the
// builtin_verifier, or the Chrome Root Store, or both at the same time),
// use the new default. Otherwise use the old default.
if (use_new_default_for_platform) {
verify_proc = CreateNewDefaultWithoutCaching(std::move(cert_net_fetcher));
} else {
verify_proc = CreateOldDefaultWithoutCaching(std::move(cert_net_fetcher));
}
cert_verifier =
std::make_unique<net::MultiThreadedCertVerifier>(verify_proc);
}
return cert_verifier;
}
} // namespace cert_verifier