| Index: net/cert/known_roots_mac.cc
|
| diff --git a/net/cert/internal/system_trust_store.cc b/net/cert/known_roots_mac.cc
|
| similarity index 4%
|
| copy from net/cert/internal/system_trust_store.cc
|
| copy to net/cert/known_roots_mac.cc
|
| index 64ac20982abdf24a1c9a1b47143a4f6f368e4c1a..475dda6e9cf10ba330a53c8d8b7fd2ae284ffbf2 100644
|
| --- a/net/cert/internal/system_trust_store.cc
|
| +++ b/net/cert/known_roots_mac.cc
|
| @@ -1,171 +1,80 @@
|
| -// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Copyright (c) 2017 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 "net/cert/internal/system_trust_store.h"
|
| +#include "net/cert/known_roots_mac.h"
|
|
|
| -#if defined(USE_NSS_CERTS)
|
| -#include <cert.h>
|
| -#include <pk11pub.h>
|
| -#elif defined(OS_MACOSX) && !defined(OS_IOS)
|
| #include <Security/Security.h>
|
| -#endif
|
|
|
| -#include "base/memory/ptr_util.h"
|
| -#include "net/cert/internal/trust_store_collection.h"
|
| -#include "net/cert/internal/trust_store_in_memory.h"
|
| +#include <set>
|
|
|
| -#if defined(USE_NSS_CERTS)
|
| -#include "crypto/nss_util.h"
|
| -#include "net/cert/internal/cert_issuer_source_nss.h"
|
| -#include "net/cert/internal/trust_store_nss.h"
|
| -#include "net/cert/scoped_nss_types.h"
|
| -#elif defined(OS_MACOSX) && !defined(OS_IOS)
|
| -#include "net/cert/internal/trust_store_mac.h"
|
| -#endif
|
| +#include "base/lazy_instance.h"
|
| +#include "crypto/mac_security_services_lock.h"
|
| +#include "net/cert/x509_util_mac.h"
|
| +
|
| +using base::ScopedCFTypeRef;
|
|
|
| namespace net {
|
|
|
| namespace {
|
|
|
| -// Abstract implementation of SystemTrustStore to be used as a base class.
|
| -// Handles the addition of additional trust anchors.
|
| -class BaseSystemTrustStore : public SystemTrustStore {
|
| +// Helper class for managing the set of OS X Known Roots. This is only safe
|
| +// to initialize while the crypto::GetMacSecurityServicesLock() is held, due
|
| +// to calling into Security.framework functions; however, once initialized,
|
| +// it can be called at any time.
|
| +// In practice, due to lazy initialization, it's best to just always guard
|
| +// accesses with the lock.
|
| +class OSXKnownRootHelper {
|
| public:
|
| - BaseSystemTrustStore() {
|
| - trust_store_.AddTrustStore(&additional_trust_store_);
|
| + bool IsKnownRoot(SecCertificateRef cert) {
|
| + // If there are no known roots, then an API failure occurred. For safety,
|
| + // assume that all certificates are issued by known roots.
|
| + if (known_roots_.empty())
|
| + return true;
|
| +
|
| + SHA256HashValue hash = x509_util::CalculateFingerprint256(cert);
|
| + return known_roots_.find(hash) != known_roots_.end();
|
| }
|
|
|
| - void AddTrustAnchor(const scoped_refptr<TrustAnchor>& trust_anchor) override {
|
| - additional_trust_store_.AddTrustAnchor(trust_anchor);
|
| + private:
|
| + friend struct base::LazyInstanceTraitsBase<OSXKnownRootHelper>;
|
| +
|
| + OSXKnownRootHelper() {
|
| + crypto::GetMacSecurityServicesLock().AssertAcquired();
|
| +
|
| + CFArrayRef cert_array = NULL;
|
| + OSStatus rv = SecTrustSettingsCopyCertificates(
|
| + kSecTrustSettingsDomainSystem, &cert_array);
|
| + if (rv != noErr) {
|
| + LOG(ERROR) << "Unable to determine trusted roots; assuming all roots are "
|
| + << "trusted! Error " << rv;
|
| + return;
|
| + }
|
| + base::ScopedCFTypeRef<CFArrayRef> scoped_array(cert_array);
|
| + for (CFIndex i = 0, size = CFArrayGetCount(cert_array); i < size; ++i) {
|
| + SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(
|
| + const_cast<void*>(CFArrayGetValueAtIndex(cert_array, i)));
|
| + known_roots_.insert(x509_util::CalculateFingerprint256(cert));
|
| + }
|
| }
|
|
|
| - TrustStore* GetTrustStore() override { return &trust_store_; }
|
| -
|
| - CertIssuerSource* GetCertIssuerSource() override { return nullptr; }
|
| -
|
| - bool IsAdditionalTrustAnchor(
|
| - const scoped_refptr<TrustAnchor>& trust_anchor) const override {
|
| - return additional_trust_store_.Contains(trust_anchor.get());
|
| - }
|
| + ~OSXKnownRootHelper() {}
|
|
|
| - protected:
|
| - TrustStoreCollection trust_store_;
|
| - TrustStoreInMemory additional_trust_store_;
|
| + std::set<SHA256HashValue, SHA256HashValueLessThan> known_roots_;
|
| };
|
|
|
| -} // namespace
|
| -
|
| -#if defined(USE_NSS_CERTS)
|
| -namespace {
|
| -
|
| -class SystemTrustStoreNSS : public BaseSystemTrustStore {
|
| - public:
|
| - explicit SystemTrustStoreNSS() : trust_store_nss_(trustSSL) {
|
| - trust_store_.AddTrustStore(&trust_store_nss_);
|
| - }
|
| -
|
| - CertIssuerSource* GetCertIssuerSource() override {
|
| - return &cert_issuer_source_nss_;
|
| - }
|
| -
|
| - 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 scoped_refptr<TrustAnchor>& trust_anchor) const override {
|
| - // TODO(eroman): Based on how the TrustAnchors are created by this
|
| - // integration, there will always be an associated certificate. However this
|
| - // contradicts the API for TrustAnchor that states it is optional.
|
| - DCHECK(trust_anchor->cert());
|
| -
|
| - // 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<uint8_t*>(trust_anchor->cert()->der_cert().UnsafeData());
|
| - der_cert.len = trust_anchor->cert()->der_cert().Length();
|
| - der_cert.type = siDERCertBuffer;
|
| - ScopedCERTCertificate nss_cert(
|
| - CERT_FindCertByDERCert(CERT_GetDefaultCertDB(), &der_cert));
|
| - if (!nss_cert)
|
| - return false;
|
| -
|
| - return IsKnownRoot(nss_cert.get());
|
| - }
|
| -
|
| - private:
|
| - // TODO(eroman): This function was copied verbatim from
|
| - // cert_verify_proc_nss.cc
|
| - //
|
| - // IsKnownRoot returns true if the given certificate is one that we believe
|
| - // is a standard (as opposed to user-installed) root.
|
| - bool IsKnownRoot(CERTCertificate* root) const {
|
| - if (!root || !root->slot)
|
| - return false;
|
| -
|
| - // This magic name is taken from
|
| - // http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/security/nss/lib/ckfw/builtins/constants.c&rev=1.13&mark=86,89#79
|
| - return 0 == strcmp(PK11_GetSlotName(root->slot), "NSS Builtin Objects");
|
| - }
|
| -
|
| - TrustStoreNSS trust_store_nss_;
|
| - CertIssuerSourceNSS cert_issuer_source_nss_;
|
| -};
|
| +base::LazyInstance<OSXKnownRootHelper>::Leaky g_known_roots =
|
| + LAZY_INSTANCE_INITIALIZER;
|
|
|
| } // namespace
|
|
|
| -std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStore() {
|
| - return base::MakeUnique<SystemTrustStoreNSS>();
|
| +bool IsKnownRoot(SecCertificateRef cert) {
|
| + return g_known_roots.Get().IsKnownRoot(cert);
|
| }
|
|
|
| -#elif defined(OS_MACOSX) && !defined(OS_IOS)
|
| -
|
| -class SystemTrustStoreMac : public BaseSystemTrustStore {
|
| - public:
|
| - explicit SystemTrustStoreMac() : trust_store_mac_(kSecPolicyAppleSSL) {
|
| - trust_store_.AddTrustStore(&trust_store_mac_);
|
| - }
|
| -
|
| - CertIssuerSource* GetCertIssuerSource() override {
|
| - // TODO(eroman): Should this return something?
|
| - return nullptr;
|
| - }
|
| -
|
| - 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 scoped_refptr<TrustAnchor>& trust_anchor) const override {
|
| - // TODO(eroman): Implement.
|
| - return false;
|
| - }
|
| -
|
| - private:
|
| - TrustStoreMac trust_store_mac_;
|
| -};
|
| -
|
| -std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStore() {
|
| - return base::MakeUnique<SystemTrustStoreMac>();
|
| -}
|
| -#else
|
| -
|
| -class DummySystemTrustStore : public BaseSystemTrustStore {
|
| - public:
|
| - bool UsesSystemTrustStore() const override { return false; }
|
| -
|
| - bool IsKnownRoot(
|
| - const scoped_refptr<TrustAnchor>& trust_anchor) const override {
|
| - return false;
|
| - }
|
| -};
|
| -
|
| -std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStore() {
|
| - return base::MakeUnique<DummySystemTrustStore>();
|
| +void InitializeKnownRoots() {
|
| + base::AutoLock lock(crypto::GetMacSecurityServicesLock());
|
| + g_known_roots.Get();
|
| }
|
| -#endif
|
|
|
| } // namespace net
|
|
|