// Copyright 2017 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/internal/system_trust_store.h" #include "base/memory/ptr_util.h" #include "build/build_config.h" #include "crypto/crypto_buildflags.h" #if BUILDFLAG(USE_NSS_CERTS) #include "net/cert/internal/system_trust_store_nss.h" #endif // BUILDFLAG(USE_NSS_CERTS) #if BUILDFLAG(USE_NSS_CERTS) #include #include #elif BUILDFLAG(IS_MAC) #include #endif #include #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/logging.h" #include "base/no_destructor.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "build/build_config.h" #include "net/cert/pki/cert_errors.h" #include "net/cert/pki/parsed_certificate.h" #include "net/cert/pki/trust_store_collection.h" #include "net/cert/pki/trust_store_in_memory.h" #include "net/cert/x509_certificate.h" #include "net/cert/x509_util.h" #if BUILDFLAG(USE_NSS_CERTS) #include "crypto/nss_util.h" #include "net/cert/internal/trust_store_nss.h" #include "net/cert/known_roots_nss.h" #include "net/cert/scoped_nss_types.h" #elif BUILDFLAG(IS_MAC) #include "net/base/features.h" #include "net/cert/internal/trust_store_mac.h" #include "net/cert/x509_util_apple.h" #elif BUILDFLAG(IS_FUCHSIA) #include "base/lazy_instance.h" #include "third_party/boringssl/src/include/openssl/pool.h" #elif BUILDFLAG(IS_WIN) #include "net/cert/internal/trust_store_win.h" #elif BUILDFLAG(IS_ANDROID) #include "net/cert/internal/trust_store_android.h" #endif #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) #include "net/cert/internal/trust_store_chrome.h" #endif // CHROME_ROOT_STORE_SUPPORTED namespace net { namespace { class DummySystemTrustStore : public SystemTrustStore { public: TrustStore* GetTrustStore() override { return &trust_store_; } bool UsesSystemTrustStore() const override { return false; } bool IsKnownRoot(const ParsedCertificate* trust_anchor) const override { return false; } #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) int64_t chrome_root_store_version() override { return 0; } #endif private: TrustStoreCollection trust_store_; }; } // namespace #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) class SystemTrustStoreChromeWithUnOwnedSystemStore : public SystemTrustStore { public: // Creates a SystemTrustStore that gets publicly trusted roots from // |trust_store_chrome| and local trust settings from |trust_store_system|. // Does not take ownership of |trust_store_system|, which must outlive this // object. explicit SystemTrustStoreChromeWithUnOwnedSystemStore( std::unique_ptr trust_store_chrome, TrustStore* trust_store_system) : trust_store_chrome_(std::move(trust_store_chrome)) { trust_store_collection_.AddTrustStore(trust_store_system); trust_store_collection_.AddTrustStore(trust_store_chrome_.get()); } TrustStore* GetTrustStore() override { return &trust_store_collection_; } bool UsesSystemTrustStore() const override { return true; } // IsKnownRoot returns true if the given trust anchor is a standard one (as // opposed to a user-installed root) bool IsKnownRoot(const ParsedCertificate* trust_anchor) const override { return trust_store_chrome_->Contains(trust_anchor); } int64_t chrome_root_store_version() override { return trust_store_chrome_->version(); } private: std::unique_ptr trust_store_chrome_; TrustStoreCollection trust_store_collection_; }; class SystemTrustStoreChrome : public SystemTrustStoreChromeWithUnOwnedSystemStore { public: // Creates a SystemTrustStore that gets publicly trusted roots from // |trust_store_chrome| and local trust settings from |trust_store_system|. explicit SystemTrustStoreChrome( std::unique_ptr trust_store_chrome, std::unique_ptr trust_store_system) : SystemTrustStoreChromeWithUnOwnedSystemStore( std::move(trust_store_chrome), trust_store_system.get()), trust_store_system_(std::move(trust_store_system)) {} private: std::unique_ptr trust_store_system_; }; std::unique_ptr CreateSystemTrustStoreChromeForTesting( std::unique_ptr trust_store_chrome, std::unique_ptr trust_store_system) { return std::make_unique( std::move(trust_store_chrome), std::move(trust_store_system)); } #endif // CHROME_ROOT_STORE_SUPPORTED #if BUILDFLAG(USE_NSS_CERTS) namespace { class SystemTrustStoreNSS : public SystemTrustStore { public: explicit SystemTrustStoreNSS(std::unique_ptr trust_store_nss) : trust_store_nss_(std::move(trust_store_nss)) {} TrustStore* GetTrustStore() override { return trust_store_nss_.get(); } bool UsesSystemTrustStore() const override { return true; } // IsKnownRoot returns true if the given trust anchor is a standard one (as // opposed to a user-installed root) bool IsKnownRoot(const ParsedCertificate* trust_anchor) const override { // TODO(eroman): The overall approach of IsKnownRoot() is inefficient -- it // requires searching for the trust anchor by DER in NSS, however path // building already had a handle to it. SECItem der_cert; der_cert.data = const_cast(trust_anchor->der_cert().UnsafeData()); der_cert.len = trust_anchor->der_cert().Length(); der_cert.type = siDERCertBuffer; ScopedCERTCertificate nss_cert( CERT_FindCertByDERCert(CERT_GetDefaultCertDB(), &der_cert)); if (!nss_cert) return false; if (!net::IsKnownRoot(nss_cert.get())) return false; return trust_anchor->der_cert() == der::Input(nss_cert->derCert.data, nss_cert->derCert.len); } #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) int64_t chrome_root_store_version() override { return 0; } #endif private: std::unique_ptr trust_store_nss_; }; } // namespace std::unique_ptr CreateSslSystemTrustStore() { return std::make_unique(std::make_unique( TrustStoreNSS::kUseSystemTrust, TrustStoreNSS::UseTrustFromAllUserSlots())); } #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) std::unique_ptr CreateSslSystemTrustStoreChromeRoot( std::unique_ptr chrome_root) { return std::make_unique( std::move(chrome_root), std::make_unique( TrustStoreNSS::kIgnoreSystemTrust, TrustStoreNSS::UseTrustFromAllUserSlots())); } std::unique_ptr CreateSslSystemTrustStoreChromeRootWithUserSlotRestriction( std::unique_ptr chrome_root, crypto::ScopedPK11Slot user_slot_restriction) { return std::make_unique( std::move(chrome_root), std::make_unique(TrustStoreNSS::kIgnoreSystemTrust, std::move(user_slot_restriction))); } #endif // CHROME_ROOT_STORE_SUPPORTED std::unique_ptr CreateSslSystemTrustStoreNSSWithUserSlotRestriction( crypto::ScopedPK11Slot user_slot_restriction) { return std::make_unique(std::make_unique( TrustStoreNSS::kUseSystemTrust, std::move(user_slot_restriction))); } #elif BUILDFLAG(IS_MAC) // Using the Builtin Verifier w/o the Chrome Root Store is unsupported on // Mac. std::unique_ptr CreateSslSystemTrustStore() { return std::make_unique(); } namespace { TrustStoreMac* GetGlobalTrustStoreMacForCRS() { constexpr TrustStoreMac::TrustImplType kDefaultMacTrustImplForCRS = TrustStoreMac::TrustImplType::kDomainCacheFullCerts; static base::NoDestructor static_trust_store_mac( kSecPolicyAppleSSL, kDefaultMacTrustImplForCRS); return static_trust_store_mac.get(); } void InitializeTrustCacheForCRSOnWorkerThread() { GetGlobalTrustStoreMacForCRS()->InitializeTrustCache(); } } // namespace std::unique_ptr CreateSslSystemTrustStoreChromeRoot( std::unique_ptr chrome_root) { return std::make_unique( std::move(chrome_root), GetGlobalTrustStoreMacForCRS()); } void InitializeTrustStoreMacCache() { base::ThreadPool::PostTask( FROM_HERE, {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, base::BindOnce(&InitializeTrustCacheForCRSOnWorkerThread)); } #elif BUILDFLAG(IS_FUCHSIA) namespace { constexpr char kRootCertsFileFuchsia[] = "/config/ssl/cert.pem"; class FuchsiaSystemCerts { public: FuchsiaSystemCerts() { base::FilePath filename(kRootCertsFileFuchsia); std::string certs_file; if (!base::ReadFileToString(filename, &certs_file)) { LOG(ERROR) << "Can't load root certificates from " << filename; return; } CertificateList certs = X509Certificate::CreateCertificateListFromBytes( base::as_bytes(base::make_span(certs_file)), X509Certificate::FORMAT_AUTO); for (const auto& cert : certs) { CertErrors errors; auto parsed = ParsedCertificate::Create( bssl::UpRef(cert->cert_buffer()), x509_util::DefaultParseCertificateOptions(), &errors); CHECK(parsed) << errors.ToDebugString(); system_trust_store_.AddTrustAnchor(parsed); } } TrustStoreInMemory* system_trust_store() { return &system_trust_store_; } private: TrustStoreInMemory system_trust_store_; }; base::LazyInstance::Leaky g_root_certs_fuchsia = LAZY_INSTANCE_INITIALIZER; } // namespace class SystemTrustStoreFuchsia : public SystemTrustStore { public: SystemTrustStoreFuchsia() = default; TrustStore* GetTrustStore() override { return g_root_certs_fuchsia.Get().system_trust_store(); } bool UsesSystemTrustStore() const override { return true; } bool IsKnownRoot(const ParsedCertificate* trust_anchor) const override { return g_root_certs_fuchsia.Get().system_trust_store()->Contains( trust_anchor); } }; std::unique_ptr CreateSslSystemTrustStore() { return std::make_unique(); } #elif BUILDFLAG(IS_WIN) // Using the Builtin Verifier w/o the Chrome Root Store is unsupported on // Windows. std::unique_ptr CreateSslSystemTrustStore() { return std::make_unique(); } namespace { TrustStoreWin* GetGlobalTrustStoreWinForCRS() { static base::NoDestructor static_trust_store_win; return static_trust_store_win.get(); } void InitializeTrustStoreForCRSOnWorkerThread() { GetGlobalTrustStoreWinForCRS()->InitializeStores(); } } // namespace std::unique_ptr CreateSslSystemTrustStoreChromeRoot( std::unique_ptr chrome_root) { return std::make_unique( std::move(chrome_root), GetGlobalTrustStoreWinForCRS()); } // We do this in a separate thread as loading the Windows Cert Stores can cause // quite a bit of I/O. See crbug.com/1399974 for more context. void InitializeTrustStoreWinSystem() { base::ThreadPool::PostTask( FROM_HERE, {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, base::BindOnce(&InitializeTrustStoreForCRSOnWorkerThread)); } #elif BUILDFLAG(IS_ANDROID) // Using the Builtin Verifier w/o the Chrome Root Store is unsupported on // Android. std::unique_ptr CreateSslSystemTrustStore() { return std::make_unique(); } #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) namespace { TrustStoreAndroid* GetGlobalTrustStoreAndroidForCRS() { static base::NoDestructor static_trust_store_android; return static_trust_store_android.get(); } void InitializeTrustStoreForCRSOnWorkerThread() { GetGlobalTrustStoreAndroidForCRS()->Initialize(); } } // namespace std::unique_ptr CreateSslSystemTrustStoreChromeRoot( std::unique_ptr chrome_root) { return std::make_unique( std::move(chrome_root), GetGlobalTrustStoreAndroidForCRS()); } void InitializeTrustStoreAndroid() { // Start observing DB change before the Trust Store is initialized so we don't // accidentally miss any changes. See https://crrev.com/c/4226436 for context. // // This call is safe here because we're the only callers of // ObserveCertDBChanges on the singleton TrustStoreAndroid. GetGlobalTrustStoreAndroidForCRS()->ObserveCertDBChanges(); base::ThreadPool::PostTask( FROM_HERE, {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, base::BindOnce(&InitializeTrustStoreForCRSOnWorkerThread)); } #else void InitializeTrustStoreAndroid() {} #endif // CHROME_ROOT_STORE_SUPPORTED #else std::unique_ptr CreateSslSystemTrustStore() { return std::make_unique(); } #endif std::unique_ptr CreateEmptySystemTrustStore() { return std::make_unique(); } } // namespace net