Support Chrome Root Store on Mac.
Adds option to TrustStoreMac for whether to check certs from the system domain, and updates SystemTrustStore to make use of it. Add param to dual verifier trial to choose CRS or not. Bug: 1327433 Change-Id: I7d4204bc266b67530b6b6602e8ee42b7060df28d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3699218 Auto-Submit: Matt Mueller <mattm@chromium.org> Commit-Queue: Avi Drissman <avi@chromium.org> Reviewed-by: Hubert Chao <hchao@chromium.org> Reviewed-by: Avi Drissman <avi@chromium.org> Cr-Commit-Position: refs/heads/main@{#1014145}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
0ed181313f
commit
cc72adf124
@ -37,7 +37,6 @@
|
||||
#include "components/version_info/channel.h"
|
||||
#include "content/public/common/main_function_params.h"
|
||||
#include "content/public/common/result_codes.h"
|
||||
#include "net/base/features.h"
|
||||
#include "net/cert/internal/system_trust_store.h"
|
||||
#include "services/network/public/cpp/features.h"
|
||||
#include "ui/base/cocoa/permissions_utils.h"
|
||||
@ -139,10 +138,7 @@ void ChromeBrowserMainPartsMac::PostCreateMainMessageLoop() {
|
||||
MacStartupProfiler::POST_MAIN_MESSAGE_LOOP_START);
|
||||
ChromeBrowserMainPartsPosix::PostCreateMainMessageLoop();
|
||||
|
||||
if (base::FeatureList::IsEnabled(
|
||||
net::features::kCertVerifierBuiltinFeature)) {
|
||||
net::InitializeTrustStoreMacCache();
|
||||
}
|
||||
net::InitializeTrustStoreMacCache();
|
||||
}
|
||||
|
||||
void ChromeBrowserMainPartsMac::PreProfileInit() {
|
||||
|
@ -212,6 +212,11 @@ const base::FeatureParam<int> kCertDualVerificationTrialImpl{
|
||||
const base::FeatureParam<int> kCertDualVerificationTrialCacheSize{
|
||||
&kCertDualVerificationTrialFeature, "cachesize", 0};
|
||||
#endif /* BUILDFLAG(IS_MAC) */
|
||||
#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED) && \
|
||||
BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
|
||||
const base::FeatureParam<bool> kCertDualVerificationTrialUseCrs{
|
||||
&kCertDualVerificationTrialFeature, "use_crs", false};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
|
||||
|
@ -314,6 +314,14 @@ NET_EXPORT extern const base::FeatureParam<int> kCertDualVerificationTrialImpl;
|
||||
NET_EXPORT extern const base::FeatureParam<int>
|
||||
kCertDualVerificationTrialCacheSize;
|
||||
#endif /* BUILDFLAG(IS_MAC) */
|
||||
#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED) && \
|
||||
BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
|
||||
// If both builtin verifier+system roots and builtin verifier+CRS flags are
|
||||
// supported in the same build, this param can be used to choose which to test
|
||||
// in the trial.
|
||||
NET_EXPORT extern const base::FeatureParam<bool>
|
||||
kCertDualVerificationTrialUseCrs;
|
||||
#endif
|
||||
#endif /* BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED) */
|
||||
|
||||
#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
|
||||
|
@ -229,7 +229,8 @@ const std::vector<CertVerifyProcType> kAllCertVerifiers = {
|
||||
#elif BUILDFLAG(IS_IOS)
|
||||
CERT_VERIFY_PROC_IOS
|
||||
#elif BUILDFLAG(IS_MAC)
|
||||
CERT_VERIFY_PROC_MAC, CERT_VERIFY_PROC_BUILTIN
|
||||
CERT_VERIFY_PROC_MAC, CERT_VERIFY_PROC_BUILTIN,
|
||||
CERT_VERIFY_PROC_BUILTIN_CHROME_ROOTS
|
||||
#elif BUILDFLAG(IS_WIN)
|
||||
CERT_VERIFY_PROC_WIN, CERT_VERIFY_PROC_BUILTIN_CHROME_ROOTS
|
||||
#elif BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
|
||||
@ -1621,7 +1622,7 @@ TEST_P(CertVerifyProcInternalTest, TestKnownRoot) {
|
||||
<< "against mattm.";
|
||||
EXPECT_TRUE(verify_result.is_issued_by_known_root);
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
if (VerifyProcTypeIsBuiltin()) {
|
||||
if (verify_proc_type() == CERT_VERIFY_PROC_BUILTIN) {
|
||||
auto* mac_trust_debug_info =
|
||||
net::TrustStoreMac::ResultDebugData::Get(&verify_result);
|
||||
ASSERT_TRUE(mac_trust_debug_info);
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "net/cert/internal/system_trust_store.h"
|
||||
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "build/build_config.h"
|
||||
#include "crypto/crypto_buildflags.h"
|
||||
|
||||
@ -78,15 +79,18 @@ class DummySystemTrustStore : public SystemTrustStore {
|
||||
} // namespace
|
||||
|
||||
#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
|
||||
class SystemTrustStoreChrome : public SystemTrustStore {
|
||||
class SystemTrustStoreChromeWithUnOwnedSystemStore : public SystemTrustStore {
|
||||
public:
|
||||
explicit SystemTrustStoreChrome(
|
||||
// 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<TrustStoreChrome> trust_store_chrome,
|
||||
std::unique_ptr<TrustStore> trust_store_system)
|
||||
: trust_store_chrome_(std::move(trust_store_chrome)),
|
||||
trust_store_system_(std::move(trust_store_system)) {
|
||||
TrustStore* trust_store_system)
|
||||
: trust_store_chrome_(std::move(trust_store_chrome)) {
|
||||
trust_store_collection_.AddTrustStore(trust_store_chrome_.get());
|
||||
trust_store_collection_.AddTrustStore(trust_store_system_.get());
|
||||
trust_store_collection_.AddTrustStore(trust_store_system);
|
||||
}
|
||||
|
||||
TrustStore* GetTrustStore() override { return &trust_store_collection_; }
|
||||
@ -105,17 +109,32 @@ class SystemTrustStoreChrome : public SystemTrustStore {
|
||||
|
||||
private:
|
||||
std::unique_ptr<TrustStoreChrome> trust_store_chrome_;
|
||||
std::unique_ptr<TrustStore> trust_store_system_;
|
||||
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<TrustStoreChrome> trust_store_chrome,
|
||||
std::unique_ptr<TrustStore> 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<TrustStore> trust_store_system_;
|
||||
};
|
||||
|
||||
std::unique_ptr<SystemTrustStore> CreateSystemTrustStoreChromeForTesting(
|
||||
std::unique_ptr<TrustStoreChrome> trust_store_chrome,
|
||||
std::unique_ptr<TrustStore> trust_store_system) {
|
||||
return std::make_unique<SystemTrustStoreChrome>(
|
||||
std::move(trust_store_chrome), std::move(trust_store_system));
|
||||
}
|
||||
|
||||
#endif // CHROME_ROOT_STORE_SUPPORTED
|
||||
|
||||
#if BUILDFLAG(USE_NSS_CERTS)
|
||||
@ -193,6 +212,61 @@ CreateSslSystemTrustStoreNSSWithNoUserSlots() {
|
||||
|
||||
#elif BUILDFLAG(IS_MAC)
|
||||
|
||||
namespace {
|
||||
|
||||
TrustStoreMac::TrustImplType ParamToTrustImplType(
|
||||
int param,
|
||||
TrustStoreMac::TrustImplType default_impl) {
|
||||
switch (param) {
|
||||
case 1:
|
||||
return TrustStoreMac::TrustImplType::kDomainCache;
|
||||
case 2:
|
||||
return TrustStoreMac::TrustImplType::kSimple;
|
||||
case 3:
|
||||
return TrustStoreMac::TrustImplType::kLruCache;
|
||||
default:
|
||||
return default_impl;
|
||||
}
|
||||
}
|
||||
|
||||
TrustStoreMac::TrustImplType GetTrustStoreImplParam(
|
||||
TrustStoreMac::TrustImplType default_impl) {
|
||||
// TODO(https://crbug.com/1327433): A limitation of this approach is that if
|
||||
// the primary verifier is being set to use the builtin verifier via a
|
||||
// feature flag, it isn't possible to run dual verifier trial comparing that
|
||||
// to the builtin verifier with different flags, since this method can't tell
|
||||
// which flags to use for which verifier.
|
||||
// If handling that becomes necessary, the flags should be checked in the
|
||||
// higher level code (maybe in cert_verifier_creation.cc) so that each
|
||||
// type of CertVerifyProc could be created with the appropriate flags.
|
||||
if (base::FeatureList::IsEnabled(features::kCertVerifierBuiltinFeature)) {
|
||||
return ParamToTrustImplType(features::kCertVerifierBuiltinImpl.Get(),
|
||||
default_impl);
|
||||
}
|
||||
if (base::FeatureList::IsEnabled(
|
||||
features::kCertDualVerificationTrialFeature)) {
|
||||
return ParamToTrustImplType(features::kCertDualVerificationTrialImpl.Get(),
|
||||
default_impl);
|
||||
}
|
||||
return default_impl;
|
||||
}
|
||||
|
||||
size_t GetTrustStoreCacheSize() {
|
||||
if (base::FeatureList::IsEnabled(features::kCertVerifierBuiltinFeature) &&
|
||||
features::kCertVerifierBuiltinCacheSize.Get() > 0) {
|
||||
return features::kCertVerifierBuiltinCacheSize.Get();
|
||||
}
|
||||
if (base::FeatureList::IsEnabled(
|
||||
features::kCertDualVerificationTrialFeature) &&
|
||||
features::kCertDualVerificationTrialCacheSize.Get() > 0) {
|
||||
return features::kCertDualVerificationTrialCacheSize.Get();
|
||||
}
|
||||
constexpr size_t kDefaultCacheSize = 512;
|
||||
return kDefaultCacheSize;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class SystemTrustStoreMac : public SystemTrustStore {
|
||||
public:
|
||||
SystemTrustStoreMac() = default;
|
||||
@ -211,50 +285,18 @@ class SystemTrustStoreMac : public SystemTrustStore {
|
||||
GetGlobalTrustStoreMac()->InitializeTrustCache();
|
||||
}
|
||||
|
||||
#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
|
||||
int64_t chrome_root_store_version() override { return 0; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
static constexpr TrustStoreMac::TrustImplType kDefaultTrustImpl =
|
||||
TrustStoreMac::TrustImplType::kLruCache;
|
||||
|
||||
static TrustStoreMac::TrustImplType ParamToTrustImplType(int param) {
|
||||
switch (param) {
|
||||
case 1:
|
||||
return TrustStoreMac::TrustImplType::kDomainCache;
|
||||
case 2:
|
||||
return TrustStoreMac::TrustImplType::kSimple;
|
||||
case 3:
|
||||
return TrustStoreMac::TrustImplType::kLruCache;
|
||||
default:
|
||||
return kDefaultTrustImpl;
|
||||
}
|
||||
}
|
||||
|
||||
static TrustStoreMac::TrustImplType GetTrustStoreImplParam() {
|
||||
if (base::FeatureList::IsEnabled(features::kCertVerifierBuiltinFeature))
|
||||
return ParamToTrustImplType(features::kCertVerifierBuiltinImpl.Get());
|
||||
if (base::FeatureList::IsEnabled(
|
||||
features::kCertDualVerificationTrialFeature))
|
||||
return ParamToTrustImplType(
|
||||
features::kCertDualVerificationTrialImpl.Get());
|
||||
return kDefaultTrustImpl;
|
||||
}
|
||||
|
||||
static size_t GetTrustStoreCacheSize() {
|
||||
if (base::FeatureList::IsEnabled(features::kCertVerifierBuiltinFeature) &&
|
||||
features::kCertVerifierBuiltinCacheSize.Get() > 0) {
|
||||
return features::kCertVerifierBuiltinCacheSize.Get();
|
||||
}
|
||||
if (base::FeatureList::IsEnabled(
|
||||
features::kCertDualVerificationTrialFeature) &&
|
||||
features::kCertDualVerificationTrialCacheSize.Get() > 0) {
|
||||
return features::kCertDualVerificationTrialCacheSize.Get();
|
||||
}
|
||||
constexpr size_t kDefaultCacheSize = 512;
|
||||
return kDefaultCacheSize;
|
||||
}
|
||||
|
||||
static TrustStoreMac* GetGlobalTrustStoreMac() {
|
||||
static base::NoDestructor<TrustStoreMac> static_trust_store_mac(
|
||||
kSecPolicyAppleSSL, GetTrustStoreImplParam(), GetTrustStoreCacheSize());
|
||||
kSecPolicyAppleSSL, GetTrustStoreImplParam(kDefaultTrustImpl),
|
||||
GetTrustStoreCacheSize(), TrustStoreMac::TrustDomains::kAll);
|
||||
return static_trust_store_mac.get();
|
||||
}
|
||||
};
|
||||
@ -263,11 +305,45 @@ std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStore() {
|
||||
return std::make_unique<SystemTrustStoreMac>();
|
||||
}
|
||||
|
||||
#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
|
||||
namespace {
|
||||
|
||||
TrustStoreMac* GetGlobalTrustStoreMacForCRS() {
|
||||
constexpr TrustStoreMac::TrustImplType kDefaultMacTrustImplForCRS =
|
||||
TrustStoreMac::TrustImplType::kDomainCache;
|
||||
static base::NoDestructor<TrustStoreMac> static_trust_store_mac(
|
||||
kSecPolicyAppleSSL, GetTrustStoreImplParam(kDefaultMacTrustImplForCRS),
|
||||
GetTrustStoreCacheSize(), TrustStoreMac::TrustDomains::kUserAndAdmin);
|
||||
return static_trust_store_mac.get();
|
||||
}
|
||||
|
||||
void InitializeTrustCacheForCRSOnWorkerThread() {
|
||||
GetGlobalTrustStoreMacForCRS()->InitializeTrustCache();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStoreChromeRoot(
|
||||
std::unique_ptr<TrustStoreChrome> chrome_root) {
|
||||
return std::make_unique<SystemTrustStoreChromeWithUnOwnedSystemStore>(
|
||||
std::move(chrome_root), GetGlobalTrustStoreMacForCRS());
|
||||
}
|
||||
#endif // CHROME_ROOT_STORE_SUPPORTED
|
||||
|
||||
void InitializeTrustStoreMacCache() {
|
||||
base::ThreadPool::PostTask(
|
||||
FROM_HERE,
|
||||
{base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
|
||||
base::BindOnce(&SystemTrustStoreMac::InitializeTrustCacheOnWorkerThread));
|
||||
if (base::FeatureList::IsEnabled(net::features::kChromeRootStoreUsed)) {
|
||||
base::ThreadPool::PostTask(
|
||||
FROM_HERE,
|
||||
{base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
|
||||
base::BindOnce(&InitializeTrustCacheForCRSOnWorkerThread));
|
||||
} else if (base::FeatureList::IsEnabled(
|
||||
net::features::kCertVerifierBuiltinFeature)) {
|
||||
base::ThreadPool::PostTask(
|
||||
FROM_HERE,
|
||||
{base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
|
||||
base::BindOnce(
|
||||
&SystemTrustStoreMac::InitializeTrustCacheOnWorkerThread));
|
||||
}
|
||||
}
|
||||
|
||||
#elif BUILDFLAG(IS_FUCHSIA)
|
||||
|
@ -99,7 +99,8 @@ CreateSystemTrustStoreChromeForTesting(
|
||||
NET_EXPORT std::unique_ptr<SystemTrustStore> CreateEmptySystemTrustStore();
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
// Initializes trust cache on a worker thread.
|
||||
// Initializes trust cache on a worker thread, if the builtin verifier is
|
||||
// enabled.
|
||||
NET_EXPORT void InitializeTrustStoreMacCache();
|
||||
#endif
|
||||
|
||||
|
@ -288,6 +288,7 @@ KnownRootStatus IsCertificateKnownRoot(const ParsedCertificate* cert) {
|
||||
|
||||
TrustStatus IsCertificateTrustedForPolicy(const ParsedCertificate* cert,
|
||||
const CFStringRef policy_oid,
|
||||
TrustStoreMac::TrustDomains domains,
|
||||
int* debug_info,
|
||||
KnownRootStatus* out_is_known_root) {
|
||||
// |*out_is_known_root| is intentionally not cleared before starting, as
|
||||
@ -309,6 +310,10 @@ TrustStatus IsCertificateTrustedForPolicy(const ParsedCertificate* cert,
|
||||
for (const auto& trust_domain :
|
||||
{kSecTrustSettingsDomainUser, kSecTrustSettingsDomainAdmin,
|
||||
kSecTrustSettingsDomainSystem}) {
|
||||
if (domains == TrustStoreMac::TrustDomains::kUserAndAdmin &&
|
||||
trust_domain == kSecTrustSettingsDomainSystem) {
|
||||
continue;
|
||||
}
|
||||
base::ScopedCFTypeRef<CFArrayRef> trust_settings;
|
||||
OSStatus err;
|
||||
{
|
||||
@ -596,10 +601,14 @@ class TrustStoreMac::TrustImpl {
|
||||
// modified.
|
||||
class TrustStoreMac::TrustImplDomainCache : public TrustStoreMac::TrustImpl {
|
||||
public:
|
||||
explicit TrustImplDomainCache(CFStringRef policy_oid)
|
||||
: system_domain_cache_(kSecTrustSettingsDomainSystem, policy_oid),
|
||||
explicit TrustImplDomainCache(CFStringRef policy_oid, TrustDomains domains)
|
||||
: use_system_domain_cache_(domains == TrustDomains::kAll),
|
||||
admin_domain_cache_(kSecTrustSettingsDomainAdmin, policy_oid),
|
||||
user_domain_cache_(kSecTrustSettingsDomainUser, policy_oid) {
|
||||
if (use_system_domain_cache_) {
|
||||
system_domain_cache_ = std::make_unique<TrustDomainCache>(
|
||||
kSecTrustSettingsDomainSystem, policy_oid);
|
||||
}
|
||||
keychain_observer_ = std::make_unique<KeychainTrustObserver>();
|
||||
}
|
||||
|
||||
@ -613,11 +622,13 @@ class TrustStoreMac::TrustImplDomainCache : public TrustStoreMac::TrustImpl {
|
||||
|
||||
// Returns true if |cert| is present in kSecTrustSettingsDomainSystem.
|
||||
bool IsKnownRoot(const ParsedCertificate* cert) override {
|
||||
if (!use_system_domain_cache_)
|
||||
return false;
|
||||
SHA256HashValue cert_hash = CalculateFingerprint256(cert->der_cert());
|
||||
|
||||
base::AutoLock lock(cache_lock_);
|
||||
MaybeInitializeCache();
|
||||
return system_domain_cache_.ContainsCert(cert_hash);
|
||||
return system_domain_cache_->ContainsCert(cert_hash);
|
||||
}
|
||||
|
||||
// Returns the trust status for |cert|.
|
||||
@ -632,12 +643,15 @@ class TrustStoreMac::TrustImplDomainCache : public TrustStoreMac::TrustImpl {
|
||||
// override system ones, and user settings can override both admin and
|
||||
// system.
|
||||
for (TrustDomainCache* trust_domain_cache :
|
||||
{&user_domain_cache_, &admin_domain_cache_, &system_domain_cache_}) {
|
||||
{&user_domain_cache_, &admin_domain_cache_}) {
|
||||
TrustStatus ts =
|
||||
trust_domain_cache->IsCertTrusted(cert, cert_hash, debug_data);
|
||||
if (ts != TrustStatus::UNSPECIFIED)
|
||||
return ts;
|
||||
}
|
||||
if (use_system_domain_cache_) {
|
||||
return system_domain_cache_->IsCertTrusted(cert, cert_hash, debug_data);
|
||||
}
|
||||
|
||||
// Cert did not have trust settings in any domain.
|
||||
return TrustStatus::UNSPECIFIED;
|
||||
@ -661,22 +675,26 @@ class TrustStoreMac::TrustImplDomainCache : public TrustStoreMac::TrustImpl {
|
||||
iteration_ = keychain_iteration;
|
||||
user_domain_cache_.Initialize();
|
||||
admin_domain_cache_.Initialize();
|
||||
if (!system_domain_initialized_) {
|
||||
if (use_system_domain_cache_ && !system_domain_initialized_) {
|
||||
// In practice, the system trust domain does not change during runtime,
|
||||
// and SecTrustSettingsCopyCertificates on the system domain is quite
|
||||
// slow, so the system domain cache is not reset on keychain changes.
|
||||
system_domain_cache_.Initialize();
|
||||
system_domain_cache_->Initialize();
|
||||
system_domain_initialized_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<KeychainTrustObserver> keychain_observer_;
|
||||
// Store whether to use the system domain in a const bool that is initialized
|
||||
// in constructor so it is safe to read without having to lock first.
|
||||
const bool use_system_domain_cache_;
|
||||
|
||||
base::Lock cache_lock_;
|
||||
// |cache_lock_| must be held while accessing any following members.
|
||||
int64_t iteration_ GUARDED_BY(cache_lock_) = -1;
|
||||
bool system_domain_initialized_ GUARDED_BY(cache_lock_) = false;
|
||||
TrustDomainCache system_domain_cache_ GUARDED_BY(cache_lock_);
|
||||
std::unique_ptr<TrustDomainCache> system_domain_cache_
|
||||
GUARDED_BY(cache_lock_);
|
||||
TrustDomainCache admin_domain_cache_ GUARDED_BY(cache_lock_);
|
||||
TrustDomainCache user_domain_cache_ GUARDED_BY(cache_lock_);
|
||||
};
|
||||
@ -685,7 +703,8 @@ class TrustStoreMac::TrustImplDomainCache : public TrustStoreMac::TrustImpl {
|
||||
// SecTrustSettingsCopyTrustSettings on every cert checked, with no caching.
|
||||
class TrustStoreMac::TrustImplNoCache : public TrustStoreMac::TrustImpl {
|
||||
public:
|
||||
explicit TrustImplNoCache(CFStringRef policy_oid) : policy_oid_(policy_oid) {}
|
||||
explicit TrustImplNoCache(CFStringRef policy_oid, TrustDomains domains)
|
||||
: policy_oid_(policy_oid), domains_(domains) {}
|
||||
|
||||
TrustImplNoCache(const TrustImplNoCache&) = delete;
|
||||
TrustImplNoCache& operator=(const TrustImplNoCache&) = delete;
|
||||
@ -694,6 +713,8 @@ class TrustStoreMac::TrustImplNoCache : public TrustStoreMac::TrustImpl {
|
||||
|
||||
// Returns true if |cert| is present in kSecTrustSettingsDomainSystem.
|
||||
bool IsKnownRoot(const ParsedCertificate* cert) override {
|
||||
if (domains_ == TrustDomains::kUserAndAdmin)
|
||||
return false;
|
||||
HashValue cert_hash(CalculateFingerprint256(cert->der_cert()));
|
||||
base::AutoLock lock(crypto::GetMacSecurityServicesLock());
|
||||
return net::IsKnownRoot(cert_hash);
|
||||
@ -703,8 +724,9 @@ class TrustStoreMac::TrustImplNoCache : public TrustStoreMac::TrustImpl {
|
||||
TrustStatus IsCertTrusted(const ParsedCertificate* cert,
|
||||
base::SupportsUserData* debug_data) override {
|
||||
int debug_info = 0;
|
||||
TrustStatus result = IsCertificateTrustedForPolicy(
|
||||
cert, policy_oid_, &debug_info, /*out_is_known_root=*/nullptr);
|
||||
TrustStatus result =
|
||||
IsCertificateTrustedForPolicy(cert, policy_oid_, domains_, &debug_info,
|
||||
/*out_is_known_root=*/nullptr);
|
||||
UpdateUserData(debug_info, debug_data,
|
||||
TrustStoreMac::TrustImplType::kSimple);
|
||||
return result;
|
||||
@ -716,6 +738,7 @@ class TrustStoreMac::TrustImplNoCache : public TrustStoreMac::TrustImpl {
|
||||
|
||||
private:
|
||||
const CFStringRef policy_oid_;
|
||||
const TrustDomains domains_;
|
||||
};
|
||||
|
||||
// TrustImplLRUCache is calls SecTrustSettingsCopyTrustSettings on every cert
|
||||
@ -723,8 +746,12 @@ class TrustStoreMac::TrustImplNoCache : public TrustStoreMac::TrustImpl {
|
||||
// keychain updates.
|
||||
class TrustStoreMac::TrustImplLRUCache : public TrustStoreMac::TrustImpl {
|
||||
public:
|
||||
TrustImplLRUCache(CFStringRef policy_oid, size_t cache_size)
|
||||
: policy_oid_(policy_oid), trust_status_cache_(cache_size) {
|
||||
TrustImplLRUCache(CFStringRef policy_oid,
|
||||
size_t cache_size,
|
||||
TrustDomains domains)
|
||||
: policy_oid_(policy_oid),
|
||||
domains_(domains),
|
||||
trust_status_cache_(cache_size) {
|
||||
keychain_observer_ = std::make_unique<KeychainTrustObserver>();
|
||||
}
|
||||
|
||||
@ -738,6 +765,8 @@ class TrustStoreMac::TrustImplLRUCache : public TrustStoreMac::TrustImpl {
|
||||
|
||||
// Returns true if |cert| has trust settings in kSecTrustSettingsDomainSystem.
|
||||
bool IsKnownRoot(const ParsedCertificate* cert) override {
|
||||
if (domains_ == TrustDomains::kUserAndAdmin)
|
||||
return false;
|
||||
return GetKnownRootStatus(cert) == KnownRootStatus::IS_KNOWN_ROOT;
|
||||
}
|
||||
|
||||
@ -818,7 +847,7 @@ class TrustStoreMac::TrustImplLRUCache : public TrustStoreMac::TrustImpl {
|
||||
}
|
||||
|
||||
trust_details.trust_status = IsCertificateTrustedForPolicy(
|
||||
cert, policy_oid_, &trust_details.debug_info,
|
||||
cert, policy_oid_, domains_, &trust_details.debug_info,
|
||||
&trust_details.is_known_root);
|
||||
|
||||
{
|
||||
@ -841,6 +870,7 @@ class TrustStoreMac::TrustImplLRUCache : public TrustStoreMac::TrustImpl {
|
||||
}
|
||||
|
||||
const CFStringRef policy_oid_;
|
||||
const TrustDomains domains_;
|
||||
std::unique_ptr<KeychainTrustObserver> keychain_observer_;
|
||||
|
||||
base::Lock cache_lock_;
|
||||
@ -858,20 +888,23 @@ class TrustStoreMac::TrustImplLRUCache : public TrustStoreMac::TrustImpl {
|
||||
|
||||
TrustStoreMac::TrustStoreMac(CFStringRef policy_oid,
|
||||
TrustImplType impl,
|
||||
size_t cache_size) {
|
||||
size_t cache_size,
|
||||
TrustDomains domains)
|
||||
: domains_(domains) {
|
||||
switch (impl) {
|
||||
case TrustImplType::kUnknown:
|
||||
DCHECK(false);
|
||||
break;
|
||||
case TrustImplType::kDomainCache:
|
||||
trust_cache_ = std::make_unique<TrustImplDomainCache>(policy_oid);
|
||||
trust_cache_ =
|
||||
std::make_unique<TrustImplDomainCache>(policy_oid, domains);
|
||||
break;
|
||||
case TrustImplType::kSimple:
|
||||
trust_cache_ = std::make_unique<TrustImplNoCache>(policy_oid);
|
||||
trust_cache_ = std::make_unique<TrustImplNoCache>(policy_oid, domains);
|
||||
break;
|
||||
case TrustImplType::kLruCache:
|
||||
trust_cache_ =
|
||||
std::make_unique<TrustImplLRUCache>(policy_oid, cache_size);
|
||||
std::make_unique<TrustImplLRUCache>(policy_oid, cache_size, domains);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -893,7 +926,7 @@ void TrustStoreMac::SyncGetIssuersOf(const ParsedCertificate* cert,
|
||||
return;
|
||||
|
||||
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> matching_cert_buffers =
|
||||
FindMatchingCertificatesForMacNormalizedSubject(name_data);
|
||||
FindMatchingCertificatesForMacNormalizedSubject(name_data, domains_);
|
||||
|
||||
// Convert to ParsedCertificate.
|
||||
for (auto& buffer : matching_cert_buffers) {
|
||||
@ -937,7 +970,8 @@ CertificateTrust TrustStoreMac::GetTrust(
|
||||
// static
|
||||
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>>
|
||||
TrustStoreMac::FindMatchingCertificatesForMacNormalizedSubject(
|
||||
CFDataRef name_data) {
|
||||
CFDataRef name_data,
|
||||
TrustDomains domains) {
|
||||
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> matching_cert_buffers;
|
||||
base::ScopedCFTypeRef<CFMutableDictionaryRef> query(
|
||||
CFDictionaryCreateMutable(nullptr, 0, &kCFTypeDictionaryKeyCallBacks,
|
||||
@ -961,43 +995,48 @@ TrustStoreMac::FindMatchingCertificatesForMacNormalizedSubject(
|
||||
}
|
||||
}
|
||||
|
||||
// If a TestKeychainSearchList is present, it will have already set
|
||||
// |scoped_alternate_keychain_search_list|, which will be used as the
|
||||
// basis for reordering the keychain. Otherwise, get the current keychain
|
||||
// search list and use that.
|
||||
if (!scoped_alternate_keychain_search_list) {
|
||||
OSStatus status = SecKeychainCopySearchList(
|
||||
scoped_alternate_keychain_search_list.InitializeInto());
|
||||
if (status) {
|
||||
OSSTATUS_LOG(ERROR, status) << "SecKeychainCopySearchList error";
|
||||
if (domains == TrustDomains::kAll) {
|
||||
// If a TestKeychainSearchList is present, it will have already set
|
||||
// |scoped_alternate_keychain_search_list|, which will be used as the
|
||||
// basis for reordering the keychain. Otherwise, get the current keychain
|
||||
// search list and use that.
|
||||
if (!scoped_alternate_keychain_search_list) {
|
||||
OSStatus status = SecKeychainCopySearchList(
|
||||
scoped_alternate_keychain_search_list.InitializeInto());
|
||||
if (status) {
|
||||
OSSTATUS_LOG(ERROR, status) << "SecKeychainCopySearchList error";
|
||||
return matching_cert_buffers;
|
||||
}
|
||||
}
|
||||
|
||||
CFMutableArrayRef mutable_keychain_search_list = CFArrayCreateMutableCopy(
|
||||
kCFAllocatorDefault,
|
||||
CFArrayGetCount(scoped_alternate_keychain_search_list.get()) + 1,
|
||||
scoped_alternate_keychain_search_list.get());
|
||||
if (!mutable_keychain_search_list) {
|
||||
LOG(ERROR) << "CFArrayCreateMutableCopy";
|
||||
return matching_cert_buffers;
|
||||
}
|
||||
scoped_alternate_keychain_search_list.reset(mutable_keychain_search_list);
|
||||
|
||||
base::ScopedCFTypeRef<SecKeychainRef> roots_keychain;
|
||||
// The System Roots keychain is not normally searched by
|
||||
// SecItemCopyMatching. Get a reference to it and include in the keychain
|
||||
// search list.
|
||||
OSStatus status = SecKeychainOpen(
|
||||
"/System/Library/Keychains/SystemRootCertificates.keychain",
|
||||
roots_keychain.InitializeInto());
|
||||
if (status) {
|
||||
OSSTATUS_LOG(ERROR, status) << "SecKeychainOpen error";
|
||||
return matching_cert_buffers;
|
||||
}
|
||||
CFArrayAppendValue(mutable_keychain_search_list, roots_keychain);
|
||||
}
|
||||
|
||||
CFMutableArrayRef mutable_keychain_search_list = CFArrayCreateMutableCopy(
|
||||
kCFAllocatorDefault,
|
||||
CFArrayGetCount(scoped_alternate_keychain_search_list.get()) + 1,
|
||||
scoped_alternate_keychain_search_list.get());
|
||||
if (!mutable_keychain_search_list) {
|
||||
LOG(ERROR) << "CFArrayCreateMutableCopy";
|
||||
return matching_cert_buffers;
|
||||
if (scoped_alternate_keychain_search_list) {
|
||||
CFDictionarySetValue(query, kSecMatchSearchList,
|
||||
scoped_alternate_keychain_search_list.get());
|
||||
}
|
||||
scoped_alternate_keychain_search_list.reset(mutable_keychain_search_list);
|
||||
|
||||
base::ScopedCFTypeRef<SecKeychainRef> roots_keychain;
|
||||
// The System Roots keychain is not normally searched by SecItemCopyMatching.
|
||||
// Get a reference to it and include in the keychain search list.
|
||||
OSStatus status = SecKeychainOpen(
|
||||
"/System/Library/Keychains/SystemRootCertificates.keychain",
|
||||
roots_keychain.InitializeInto());
|
||||
if (status) {
|
||||
OSSTATUS_LOG(ERROR, status) << "SecKeychainOpen error";
|
||||
return matching_cert_buffers;
|
||||
}
|
||||
CFArrayAppendValue(mutable_keychain_search_list, roots_keychain);
|
||||
|
||||
CFDictionarySetValue(query, kSecMatchSearchList,
|
||||
scoped_alternate_keychain_search_list.get());
|
||||
|
||||
base::ScopedCFTypeRef<CFArrayRef> matching_items;
|
||||
OSStatus err = SecItemCopyMatching(
|
||||
|
@ -81,6 +81,17 @@ class NET_EXPORT TrustStoreMac : public TrustStore {
|
||||
kLruCache = 3,
|
||||
};
|
||||
|
||||
enum class TrustDomains {
|
||||
// Load trust settings and certificates from all three trust domains
|
||||
// (user, admin, system).
|
||||
kAll = 0,
|
||||
|
||||
// Load trust settings and certificates from only the user and admin trust
|
||||
// domains. This will find trust settings that have been set locally or by
|
||||
// an enterprise, but not those distributed with the OS.
|
||||
kUserAndAdmin = 1,
|
||||
};
|
||||
|
||||
class ResultDebugData : public base::SupportsUserData::Data {
|
||||
public:
|
||||
static const ResultDebugData* Get(const base::SupportsUserData* debug_data);
|
||||
@ -111,7 +122,10 @@ class NET_EXPORT TrustStoreMac : public TrustStore {
|
||||
// |impl| selects which internal implementation is used for checking trust
|
||||
// settings, and the interpretation of |cache_size| varies depending on
|
||||
// |impl|.
|
||||
TrustStoreMac(CFStringRef policy_oid, TrustImplType impl, size_t cache_size);
|
||||
TrustStoreMac(CFStringRef policy_oid,
|
||||
TrustImplType impl,
|
||||
size_t cache_size,
|
||||
TrustDomains domains);
|
||||
|
||||
TrustStoreMac(const TrustStoreMac&) = delete;
|
||||
TrustStoreMac& operator=(const TrustStoreMac&) = delete;
|
||||
@ -143,7 +157,8 @@ class NET_EXPORT TrustStoreMac : public TrustStore {
|
||||
// The result is an array of CRYPTO_BUFFERs containing the DER certificate
|
||||
// data.
|
||||
static std::vector<bssl::UniquePtr<CRYPTO_BUFFER>>
|
||||
FindMatchingCertificatesForMacNormalizedSubject(CFDataRef name_data);
|
||||
FindMatchingCertificatesForMacNormalizedSubject(CFDataRef name_data,
|
||||
TrustDomains domains);
|
||||
|
||||
// Returns the OS-normalized issuer of |cert|.
|
||||
// macOS internally uses a normalized form of subject/issuer names for
|
||||
@ -152,6 +167,7 @@ class NET_EXPORT TrustStoreMac : public TrustStore {
|
||||
static base::ScopedCFTypeRef<CFDataRef> GetMacNormalizedIssuer(
|
||||
const ParsedCertificate* cert);
|
||||
|
||||
TrustDomains domains_;
|
||||
std::unique_ptr<TrustImpl> trust_cache_;
|
||||
};
|
||||
|
||||
|
@ -4,15 +4,20 @@
|
||||
|
||||
#include "net/cert/internal/trust_store_mac.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
|
||||
#include "base/base_paths.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/files/scoped_temp_dir.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/process/launch.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_split.h"
|
||||
#include "base/synchronization/lock.h"
|
||||
#include "crypto/mac_security_services_lock.h"
|
||||
#include "crypto/sha2.h"
|
||||
#include "net/cert/internal/cert_errors.h"
|
||||
#include "net/cert/internal/test_helpers.h"
|
||||
#include "net/cert/known_roots_mac.h"
|
||||
@ -83,6 +88,28 @@ std::vector<std::string> ParsedCertificateListAsDER(
|
||||
return result;
|
||||
}
|
||||
|
||||
std::set<std::string> ParseFindCertificateOutputToDerCerts(std::string output) {
|
||||
std::set<std::string> certs;
|
||||
for (const std::string& hash_and_pem_partial : base::SplitStringUsingSubstr(
|
||||
output, "-----END CERTIFICATE-----", base::TRIM_WHITESPACE,
|
||||
base::SPLIT_WANT_NONEMPTY)) {
|
||||
// Re-add the PEM ending mark, since SplitStringUsingSubstr eats it.
|
||||
const std::string hash_and_pem =
|
||||
hash_and_pem_partial + "\n-----END CERTIFICATE-----\n";
|
||||
|
||||
// Parse the PEM encoded text to DER bytes.
|
||||
PEMTokenizer pem_tokenizer(hash_and_pem, {kCertificateHeader});
|
||||
if (!pem_tokenizer.GetNext()) {
|
||||
ADD_FAILURE() << "!pem_tokenizer.GetNext()";
|
||||
continue;
|
||||
}
|
||||
std::string cert_der(pem_tokenizer.data());
|
||||
EXPECT_FALSE(pem_tokenizer.GetNext());
|
||||
certs.insert(cert_der);
|
||||
}
|
||||
return certs;
|
||||
}
|
||||
|
||||
class DebugData : public base::SupportsUserData {
|
||||
public:
|
||||
~DebugData() override = default;
|
||||
@ -96,8 +123,9 @@ enum IsKnownRootTestOrder {
|
||||
} // namespace
|
||||
|
||||
class TrustStoreMacImplTest
|
||||
: public testing::TestWithParam<
|
||||
std::tuple<TrustStoreMac::TrustImplType, IsKnownRootTestOrder>> {};
|
||||
: public testing::TestWithParam<std::tuple<TrustStoreMac::TrustImplType,
|
||||
IsKnownRootTestOrder,
|
||||
TrustStoreMac::TrustDomains>> {};
|
||||
|
||||
// Test the trust store using known test certificates in a keychain. Tests
|
||||
// that issuer searching returns the expected certificates, and that none of
|
||||
@ -120,7 +148,9 @@ TEST_P(TrustStoreMacImplTest, MultiRootNotTrusted) {
|
||||
|
||||
const TrustStoreMac::TrustImplType trust_impl = std::get<0>(GetParam());
|
||||
const IsKnownRootTestOrder is_known_root_test_order = std::get<1>(GetParam());
|
||||
TrustStoreMac trust_store(kSecPolicyAppleSSL, trust_impl, kDefaultCacheSize);
|
||||
const TrustStoreMac::TrustDomains trust_domains = std::get<2>(GetParam());
|
||||
TrustStoreMac trust_store(kSecPolicyAppleSSL, trust_impl, kDefaultCacheSize,
|
||||
trust_domains);
|
||||
|
||||
scoped_refptr<ParsedCertificate> a_by_b, b_by_c, b_by_f, c_by_d, c_by_e,
|
||||
f_by_e, d_by_d, e_by_e;
|
||||
@ -155,7 +185,7 @@ TEST_P(TrustStoreMacImplTest, MultiRootNotTrusted) {
|
||||
{
|
||||
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> scoped_matching_items =
|
||||
TrustStoreMac::FindMatchingCertificatesForMacNormalizedSubject(
|
||||
normalized_name_b.get());
|
||||
normalized_name_b.get(), trust_domains);
|
||||
|
||||
EXPECT_THAT(CryptoBufferVectorAsStringVector(scoped_matching_items),
|
||||
UnorderedElementsAreArray(
|
||||
@ -165,7 +195,7 @@ TEST_P(TrustStoreMacImplTest, MultiRootNotTrusted) {
|
||||
{
|
||||
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> scoped_matching_items =
|
||||
TrustStoreMac::FindMatchingCertificatesForMacNormalizedSubject(
|
||||
normalized_name_c.get());
|
||||
normalized_name_c.get(), trust_domains);
|
||||
EXPECT_THAT(CryptoBufferVectorAsStringVector(scoped_matching_items),
|
||||
UnorderedElementsAreArray(
|
||||
ParsedCertificateListAsDER({c_by_d, c_by_e})));
|
||||
@ -174,7 +204,7 @@ TEST_P(TrustStoreMacImplTest, MultiRootNotTrusted) {
|
||||
{
|
||||
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> scoped_matching_items =
|
||||
TrustStoreMac::FindMatchingCertificatesForMacNormalizedSubject(
|
||||
normalized_name_f.get());
|
||||
normalized_name_f.get(), trust_domains);
|
||||
EXPECT_THAT(
|
||||
CryptoBufferVectorAsStringVector(scoped_matching_items),
|
||||
UnorderedElementsAreArray(ParsedCertificateListAsDER({f_by_e})));
|
||||
@ -183,7 +213,7 @@ TEST_P(TrustStoreMacImplTest, MultiRootNotTrusted) {
|
||||
{
|
||||
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> scoped_matching_items =
|
||||
TrustStoreMac::FindMatchingCertificatesForMacNormalizedSubject(
|
||||
normalized_name_d.get());
|
||||
normalized_name_d.get(), trust_domains);
|
||||
EXPECT_THAT(
|
||||
CryptoBufferVectorAsStringVector(scoped_matching_items),
|
||||
UnorderedElementsAreArray(ParsedCertificateListAsDER({d_by_d})));
|
||||
@ -192,7 +222,7 @@ TEST_P(TrustStoreMacImplTest, MultiRootNotTrusted) {
|
||||
{
|
||||
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> scoped_matching_items =
|
||||
TrustStoreMac::FindMatchingCertificatesForMacNormalizedSubject(
|
||||
normalized_name_e.get());
|
||||
normalized_name_e.get(), trust_domains);
|
||||
EXPECT_THAT(
|
||||
CryptoBufferVectorAsStringVector(scoped_matching_items),
|
||||
UnorderedElementsAreArray(ParsedCertificateListAsDER({e_by_e})));
|
||||
@ -242,43 +272,31 @@ TEST_P(TrustStoreMacImplTest, SystemCerts) {
|
||||
"/System/Library/Keychains/SystemRootCertificates.keychain"},
|
||||
&find_certificate_system_roots_output));
|
||||
|
||||
std::set<std::string> find_certificate_default_search_list_certs =
|
||||
ParseFindCertificateOutputToDerCerts(
|
||||
find_certificate_default_search_list_output);
|
||||
std::set<std::string> find_certificate_system_roots_certs =
|
||||
ParseFindCertificateOutputToDerCerts(
|
||||
find_certificate_system_roots_output);
|
||||
|
||||
const TrustStoreMac::TrustImplType trust_impl = std::get<0>(GetParam());
|
||||
const IsKnownRootTestOrder is_known_root_test_order = std::get<1>(GetParam());
|
||||
const TrustStoreMac::TrustDomains trust_domains = std::get<2>(GetParam());
|
||||
TrustStoreMac trust_store(kSecPolicyAppleX509Basic, trust_impl,
|
||||
kDefaultCacheSize);
|
||||
kDefaultCacheSize, trust_domains);
|
||||
|
||||
base::ScopedCFTypeRef<SecPolicyRef> sec_policy(SecPolicyCreateBasicX509());
|
||||
ASSERT_TRUE(sec_policy);
|
||||
for (const std::string& hash_and_pem_partial : base::SplitStringUsingSubstr(
|
||||
find_certificate_system_roots_output +
|
||||
find_certificate_default_search_list_output,
|
||||
"-----END CERTIFICATE-----", base::TRIM_WHITESPACE,
|
||||
base::SPLIT_WANT_NONEMPTY)) {
|
||||
// Re-add the PEM ending mark, since SplitStringUsingSubstr eats it.
|
||||
const std::string hash_and_pem =
|
||||
hash_and_pem_partial + "\n-----END CERTIFICATE-----\n";
|
||||
|
||||
// Use the first hash value found in the text. This might be SHA-256 or
|
||||
// SHA-1, but it's only for debugging purposes so it doesn't matter as long
|
||||
// as one exists.
|
||||
std::string::size_type hash_pos = hash_and_pem.find("hash: ");
|
||||
ASSERT_NE(std::string::npos, hash_pos);
|
||||
hash_pos += 6;
|
||||
std::string::size_type eol_pos = hash_and_pem.find_first_of("\r\n");
|
||||
ASSERT_NE(std::string::npos, eol_pos);
|
||||
// Extract the hash of the certificate. This isn't necessary for the
|
||||
// test, but is a convenient identifier to use in any error messages.
|
||||
std::string hash_text = hash_and_pem.substr(hash_pos, eol_pos - hash_pos);
|
||||
|
||||
std::vector<std::string> all_certs;
|
||||
std::set_union(find_certificate_default_search_list_certs.begin(),
|
||||
find_certificate_default_search_list_certs.end(),
|
||||
find_certificate_system_roots_certs.begin(),
|
||||
find_certificate_system_roots_certs.end(),
|
||||
std::back_inserter(all_certs));
|
||||
for (const std::string& cert_der : all_certs) {
|
||||
std::string hash = crypto::SHA256HashString(cert_der);
|
||||
std::string hash_text = base::HexEncode(hash.data(), hash.size());
|
||||
SCOPED_TRACE(hash_text);
|
||||
// TODO(mattm): The same cert might exist in both lists, could de-dupe
|
||||
// before testing?
|
||||
|
||||
// Parse the PEM encoded text to DER bytes.
|
||||
PEMTokenizer pem_tokenizer(hash_and_pem, {kCertificateHeader});
|
||||
ASSERT_TRUE(pem_tokenizer.GetNext());
|
||||
std::string cert_der(pem_tokenizer.data());
|
||||
ASSERT_FALSE(pem_tokenizer.GetNext());
|
||||
|
||||
CertErrors errors;
|
||||
// Note: don't actually need to make a ParsedCertificate here, just need
|
||||
@ -307,9 +325,11 @@ TEST_P(TrustStoreMacImplTest, SystemCerts) {
|
||||
|
||||
if (is_known_root_test_order == TEST_IS_KNOWN_ROOT_BEFORE) {
|
||||
bool trust_store_is_known_root = trust_store.IsKnownRoot(cert.get());
|
||||
{
|
||||
if (trust_domains == TrustStoreMac::TrustDomains::kAll) {
|
||||
base::AutoLock lock(crypto::GetMacSecurityServicesLock());
|
||||
EXPECT_EQ(net::IsKnownRoot(cert_handle), trust_store_is_known_root);
|
||||
} else {
|
||||
EXPECT_FALSE(trust_store_is_known_root);
|
||||
}
|
||||
}
|
||||
|
||||
@ -334,13 +354,18 @@ TEST_P(TrustStoreMacImplTest, SystemCerts) {
|
||||
kSecTrustOptionAllowExpired |
|
||||
kSecTrustOptionAllowExpiredRoot));
|
||||
|
||||
SecTrustResultType trust_result;
|
||||
ASSERT_EQ(noErr, SecTrustEvaluate(trust, &trust_result));
|
||||
bool expected_trust_anchor =
|
||||
((trust_result == kSecTrustResultProceed) ||
|
||||
(trust_result == kSecTrustResultUnspecified)) &&
|
||||
(SecTrustGetCertificateCount(trust) == 1);
|
||||
EXPECT_EQ(expected_trust_anchor, is_trust_anchor);
|
||||
if (trust_domains == TrustStoreMac::TrustDomains::kUserAndAdmin &&
|
||||
!find_certificate_default_search_list_certs.count(cert_der)) {
|
||||
EXPECT_FALSE(is_trust_anchor);
|
||||
} else {
|
||||
SecTrustResultType trust_result;
|
||||
ASSERT_EQ(noErr, SecTrustEvaluate(trust, &trust_result));
|
||||
bool expected_trust_anchor =
|
||||
((trust_result == kSecTrustResultProceed) ||
|
||||
(trust_result == kSecTrustResultUnspecified)) &&
|
||||
(SecTrustGetCertificateCount(trust) == 1);
|
||||
EXPECT_EQ(expected_trust_anchor, is_trust_anchor);
|
||||
}
|
||||
auto* trust_debug_data = TrustStoreMac::ResultDebugData::Get(&debug_data);
|
||||
ASSERT_TRUE(trust_debug_data);
|
||||
if (is_trust_anchor) {
|
||||
@ -355,9 +380,11 @@ TEST_P(TrustStoreMacImplTest, SystemCerts) {
|
||||
|
||||
if (is_known_root_test_order == TEST_IS_KNOWN_ROOT_AFTER) {
|
||||
bool trust_store_is_known_root = trust_store.IsKnownRoot(cert.get());
|
||||
{
|
||||
if (trust_domains == TrustStoreMac::TrustDomains::kAll) {
|
||||
base::AutoLock lock(crypto::GetMacSecurityServicesLock());
|
||||
EXPECT_EQ(net::IsKnownRoot(cert_handle), trust_store_is_known_root);
|
||||
} else {
|
||||
EXPECT_FALSE(trust_store_is_known_root);
|
||||
}
|
||||
}
|
||||
|
||||
@ -388,6 +415,8 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
// values independently, so test with calling IsKnownRoot both before
|
||||
// and after GetTrust to try to ensure there is no ordering issue with
|
||||
// which one initializes the cache first.
|
||||
testing::Values(TEST_IS_KNOWN_ROOT_BEFORE, TEST_IS_KNOWN_ROOT_AFTER)));
|
||||
testing::Values(TEST_IS_KNOWN_ROOT_BEFORE, TEST_IS_KNOWN_ROOT_AFTER),
|
||||
testing::Values(TrustStoreMac::TrustDomains::kAll,
|
||||
TrustStoreMac::TrustDomains::kUserAndAdmin)));
|
||||
|
||||
} // namespace net
|
||||
|
@ -47,5 +47,5 @@ declare_args() {
|
||||
|
||||
# Platforms for which the builtin cert verifier can use the Chrome Root Store.
|
||||
# See https://crbug.com/1216547 for status.
|
||||
chrome_root_store_supported = is_win
|
||||
chrome_root_store_supported = is_win || is_mac
|
||||
}
|
||||
|
@ -191,7 +191,17 @@ std::unique_ptr<net::CertVerifierWithUpdatableProc> CreateTrialCertVerifier(
|
||||
primary_proc_factory->CreateCertVerifyProc(cert_net_fetcher,
|
||||
root_store_data);
|
||||
|
||||
#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
|
||||
#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED) && \
|
||||
BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
|
||||
scoped_refptr<net::CertVerifyProcFactory> trial_proc_factory;
|
||||
if (net::features::kCertDualVerificationTrialUseCrs.Get()) {
|
||||
trial_proc_factory =
|
||||
base::MakeRefCounted<NewCertVerifyProcChromeRootStoreFactory>();
|
||||
} else {
|
||||
trial_proc_factory =
|
||||
base::MakeRefCounted<NewCertVerifyProcBuiltinFactory>();
|
||||
}
|
||||
#elif BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
|
||||
auto trial_proc_factory =
|
||||
base::MakeRefCounted<NewCertVerifyProcChromeRootStoreFactory>();
|
||||
#else
|
||||
|
Reference in New Issue
Block a user