blob: 558814fa126695ebe1136533b2a5d29152063d21 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// 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 "base/types/optional_util.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/crl_set.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_FUCHSIA) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#include "net/cert/cert_verify_proc_builtin.h"
#include "net/cert/internal/system_trust_store.h"
#endif
#if BUILDFLAG(IS_CHROMEOS)
#include "crypto/nss_util_internal.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"
#include "net/cert/internal/trust_store_chrome.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(IS_CHROMEOS)
crypto::ScopedPK11Slot GetUserSlotRestrictionForChromeOSParams(
mojom::CertVerifierCreationParams* creation_params) {
crypto::ScopedPK11Slot public_slot;
#if BUILDFLAG(IS_CHROMEOS_LACROS)
if (creation_params && creation_params->nss_full_path.has_value()) {
public_slot =
crypto::OpenSoftwareNSSDB(creation_params->nss_full_path.value(),
/*description=*/"cert_db");
// `public_slot` can contain important security related settings. Crash if
// failed to load it.
CHECK(public_slot);
}
#elif BUILDFLAG(IS_CHROMEOS_ASH)
if (creation_params && !creation_params->username_hash.empty()) {
// Make sure NSS is initialized for the user.
crypto::InitializeNSSForChromeOSUser(creation_params->username_hash,
creation_params->nss_path.value());
public_slot =
crypto::GetPublicSlotForChromeOSUser(creation_params->username_hash);
}
#else
#error IS_CHROMEOS set without IS_CHROMEOS_LACROS or IS_CHROMEOS_ASH
#endif
return public_slot;
}
#endif // BUILDFLAG(IS_CHROMEOS)
class CertVerifyProcFactoryImpl : public net::CertVerifyProcFactory {
public:
explicit CertVerifyProcFactoryImpl(
mojom::CertVerifierCreationParams* creation_params) {
#if BUILDFLAG(IS_CHROMEOS)
user_slot_restriction_ =
GetUserSlotRestrictionForChromeOSParams(creation_params);
#endif
}
scoped_refptr<net::CertVerifyProc> CreateCertVerifyProc(
scoped_refptr<net::CertNetFetcher> cert_net_fetcher,
const CertVerifyProcFactory::ImplParams& impl_params) override {
#if BUILDFLAG(CHROME_ROOT_STORE_ONLY)
return CreateNewCertVerifyProc(
cert_net_fetcher, impl_params.crl_set,
base::OptionalToPtr(impl_params.root_store_data));
#else
#if BUILDFLAG(CHROME_ROOT_STORE_OPTIONAL)
if (impl_params.use_chrome_root_store) {
return CreateNewCertVerifyProc(
cert_net_fetcher, impl_params.crl_set,
base::OptionalToPtr(impl_params.root_store_data));
}
#endif
return CreateOldCertVerifyProc(cert_net_fetcher, impl_params.crl_set);
#endif
}
protected:
~CertVerifyProcFactoryImpl() override = default;
#if !BUILDFLAG(CHROME_ROOT_STORE_ONLY)
// Factory function that returns a CertVerifyProc that supports the old
// configuration for platforms where we are transitioning from one cert
// configuration to another. If the platform only supports one configuration,
// return a CertVerifyProc that supports that configuration.
scoped_refptr<net::CertVerifyProc> CreateOldCertVerifyProc(
scoped_refptr<net::CertNetFetcher> cert_net_fetcher,
scoped_refptr<net::CRLSet> crl_set) {
#if BUILDFLAG(IS_CHROMEOS)
return net::CreateCertVerifyProcBuiltin(
std::move(cert_net_fetcher), std::move(crl_set),
net::CreateSslSystemTrustStoreNSSWithUserSlotRestriction(
user_slot_restriction_ ? crypto::ScopedPK11Slot(PK11_ReferenceSlot(
user_slot_restriction_.get()))
: nullptr));
#elif BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_LINUX)
return net::CreateCertVerifyProcBuiltin(std::move(cert_net_fetcher),
std::move(crl_set),
net::CreateSslSystemTrustStore());
#else
return net::CertVerifyProc::CreateSystemVerifyProc(
std::move(cert_net_fetcher), std::move(crl_set));
#endif
}
#endif // !BUILDFLAG(CHROME_ROOT_STORE_ONLY)
#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
// CertVerifyProcFactory that returns a CertVerifyProc that uses the
// Chrome Cert Verifier with the Chrome Root Store.
scoped_refptr<net::CertVerifyProc> CreateNewCertVerifyProc(
scoped_refptr<net::CertNetFetcher> cert_net_fetcher,
scoped_refptr<net::CRLSet> crl_set,
const net::ChromeRootStoreData* root_store_data) {
std::unique_ptr<net::TrustStoreChrome> chrome_root =
root_store_data
? std::make_unique<net::TrustStoreChrome>(*root_store_data)
: std::make_unique<net::TrustStoreChrome>();
std::unique_ptr<net::SystemTrustStore> trust_store;
#if BUILDFLAG(IS_CHROMEOS)
trust_store =
net::CreateSslSystemTrustStoreChromeRootWithUserSlotRestriction(
std::move(chrome_root),
user_slot_restriction_ ? crypto::ScopedPK11Slot(PK11_ReferenceSlot(
user_slot_restriction_.get()))
: nullptr);
#else
trust_store =
net::CreateSslSystemTrustStoreChromeRoot(std::move(chrome_root));
#endif
#if BUILDFLAG(IS_WIN)
// Start initialization of TrustStoreWin on a separate thread if it hasn't
// been done already. We do this here instead of in the TrustStoreWin
// constructor to avoid any unnecessary threading in unit tests that don't
// use threads otherwise.
net::InitializeTrustStoreWinSystem();
#endif
#if BUILDFLAG(IS_ANDROID)
// Start initialization of TrustStoreAndroid on a separate thread if it
// hasn't been done already. We do this here instead of in the
// TrustStoreAndroid constructor to avoid any unnecessary threading in unit
// tests that don't use threads otherwise.
net::InitializeTrustStoreAndroid();
#endif
return net::CreateCertVerifyProcBuiltin(std::move(cert_net_fetcher),
std::move(crl_set),
std::move(trust_store));
}
#endif // BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
#if BUILDFLAG(IS_CHROMEOS)
crypto::ScopedPK11Slot user_slot_restriction_;
#endif
};
#if BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED)
// Returns true if creation_params are requesting the creation of a
// TrialComparisonCertVerifier.
bool IsTrialVerificationOn(
const mojom::CertVerifierCreationParams* creation_params) {
// Check to see if we have trial comparison cert verifier params.
return creation_params &&
creation_params->trial_comparison_cert_verifier_params;
}
// Should only be called if IsTrialVerificationOn(creation_params) == true.
std::unique_ptr<net::CertVerifierWithUpdatableProc> CreateTrialCertVerifier(
mojom::CertVerifierCreationParams* creation_params,
scoped_refptr<net::CertNetFetcher> cert_net_fetcher,
const net::CertVerifyProcFactory::ImplParams& impl_params) {
DCHECK(IsTrialVerificationOn(creation_params));
scoped_refptr<net::CertVerifyProcFactory> proc_factory =
base::MakeRefCounted<CertVerifyProcFactoryImpl>(creation_params);
#if !BUILDFLAG(CHROME_ROOT_STORE_OPTIONAL)
#error "CHROME_ROOT_STORE_OPTIONAL must be true"
#endif
return 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),
std::move(proc_factory), cert_net_fetcher, impl_params);
}
#endif // BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED)
} // namespace
bool IsUsingCertNetFetcher() {
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA) || \
BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) || \
BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED) || \
BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
return true;
#else
return false;
#endif
}
std::unique_ptr<net::CertVerifierWithUpdatableProc> CreateCertVerifier(
mojom::CertVerifierCreationParams* creation_params,
scoped_refptr<net::CertNetFetcher> cert_net_fetcher,
const net::CertVerifyProcFactory::ImplParams& impl_params) {
DCHECK(cert_net_fetcher || !IsUsingCertNetFetcher());
#if BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED)
if (IsTrialVerificationOn(creation_params)) {
return CreateTrialCertVerifier(creation_params, cert_net_fetcher,
impl_params);
}
#endif
scoped_refptr<net::CertVerifyProcFactory> proc_factory =
base::MakeRefCounted<CertVerifyProcFactoryImpl>(creation_params);
return std::make_unique<net::MultiThreadedCertVerifier>(
proc_factory->CreateCertVerifyProc(cert_net_fetcher, impl_params),
proc_factory);
}
} // namespace cert_verifier