summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/chromeos/net/cert_verify_proc_chromeos.cc5
-rw-r--r--chrome/browser/net/nss_context.h8
-rw-r--r--chrome/browser/net/nss_context_chromeos.cc65
-rw-r--r--chrome/browser/profiles/profile_io_data.cc22
-rw-r--r--chrome/browser/profiles/profile_io_data.h4
-rw-r--r--crypto/nss_util.cc29
-rw-r--r--crypto/nss_util_internal.h9
-rw-r--r--crypto/scoped_test_nss_db.h4
-rw-r--r--crypto/scoped_test_system_nss_key_slot.cc4
-rw-r--r--crypto/scoped_test_system_nss_key_slot.h14
-rw-r--r--net/cert/nss_cert_database.cc6
-rw-r--r--net/cert/nss_cert_database.h10
-rw-r--r--net/cert/nss_cert_database_chromeos.cc18
-rw-r--r--net/cert/nss_cert_database_chromeos.h6
-rw-r--r--net/cert/nss_profile_filter_chromeos.cc26
-rw-r--r--net/cert/nss_profile_filter_chromeos.h4
-rw-r--r--net/cert/nss_profile_filter_chromeos_unittest.cc33
-rw-r--r--net/ssl/client_cert_store_chromeos.cc70
-rw-r--r--net/ssl/client_cert_store_chromeos.h16
-rw-r--r--net/ssl/client_cert_store_chromeos_unittest.cc149
20 files changed, 415 insertions, 87 deletions
diff --git a/chrome/browser/chromeos/net/cert_verify_proc_chromeos.cc b/chrome/browser/chromeos/net/cert_verify_proc_chromeos.cc
index b99d98c..be4621e 100644
--- a/chrome/browser/chromeos/net/cert_verify_proc_chromeos.cc
+++ b/chrome/browser/chromeos/net/cert_verify_proc_chromeos.cc
@@ -29,7 +29,10 @@ CertVerifyProcChromeOS::CertVerifyProcChromeOS() {}
CertVerifyProcChromeOS::CertVerifyProcChromeOS(
crypto::ScopedPK11Slot public_slot) {
- profile_filter_.Init(public_slot.Pass(), crypto::ScopedPK11Slot());
+ // Only the software slot is passed, since that is the only one where user
+ // trust settings are stored.
+ profile_filter_.Init(
+ public_slot.Pass(), crypto::ScopedPK11Slot(), crypto::ScopedPK11Slot());
}
CertVerifyProcChromeOS::~CertVerifyProcChromeOS() {}
diff --git a/chrome/browser/net/nss_context.h b/chrome/browser/net/nss_context.h
index 33023c0..8212ee1 100644
--- a/chrome/browser/net/nss_context.h
+++ b/chrome/browser/net/nss_context.h
@@ -46,6 +46,14 @@ net::NSSCertDatabase* GetNSSCertDatabaseForResourceContext(
const base::Callback<void(net::NSSCertDatabase*)>& callback)
WARN_UNUSED_RESULT;
+#if defined(OS_CHROMEOS)
+// Enables the system key slot in the NSSCertDatabase for the user associated
+// with |context|.
+// Must be called only on the IO thread.
+void EnableNSSSystemKeySlotForResourceContext(
+ content::ResourceContext* context);
+#endif
+
// Gets a pointer to the NSSCertDatabase for the user associated with |context|.
// It's a wrapper around |GetNSSCertDatabaseForResourceContext| which makes
// sure it's called on IO thread (with |profile|'s resource context). The
diff --git a/chrome/browser/net/nss_context_chromeos.cc b/chrome/browser/net/nss_context_chromeos.cc
index fdd96cf..abac67c 100644
--- a/chrome/browser/net/nss_context_chromeos.cc
+++ b/chrome/browser/net/nss_context_chromeos.cc
@@ -17,6 +17,8 @@ void* kDatabaseManagerKey = &kDatabaseManagerKey;
class NSSCertDatabaseChromeOSManager : public base::SupportsUserData::Data {
public:
+ typedef base::Callback<void(net::NSSCertDatabaseChromeOS*)>
+ GetNSSCertDatabaseCallback;
explicit NSSCertDatabaseChromeOSManager(const std::string& username_hash)
: username_hash_(username_hash), weak_ptr_factory_(this) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
@@ -32,8 +34,8 @@ class NSSCertDatabaseChromeOSManager : public base::SupportsUserData::Data {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
}
- net::NSSCertDatabase* GetNSSCertDatabase(
- const base::Callback<void(net::NSSCertDatabase*)>& callback) {
+ net::NSSCertDatabaseChromeOS* GetNSSCertDatabase(
+ const GetNSSCertDatabaseCallback& callback) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
if (nss_cert_database_)
@@ -44,8 +46,7 @@ class NSSCertDatabaseChromeOSManager : public base::SupportsUserData::Data {
}
private:
- typedef std::vector<base::Callback<void(net::NSSCertDatabase*)> >
- ReadyCallbackList;
+ typedef std::vector<GetNSSCertDatabaseCallback> ReadyCallbackList;
void DidGetPrivateSlot(crypto::ScopedPK11Slot private_slot) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
@@ -74,6 +75,43 @@ std::string GetUsername(content::ResourceContext* context) {
return ProfileIOData::FromResourceContext(context)->username_hash();
}
+net::NSSCertDatabaseChromeOS* GetNSSCertDatabaseChromeOS(
+ content::ResourceContext* context,
+ const NSSCertDatabaseChromeOSManager::GetNSSCertDatabaseCallback&
+ callback) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ NSSCertDatabaseChromeOSManager* manager =
+ static_cast<NSSCertDatabaseChromeOSManager*>(
+ context->GetUserData(kDatabaseManagerKey));
+ if (!manager) {
+ manager = new NSSCertDatabaseChromeOSManager(GetUsername(context));
+ context->SetUserData(kDatabaseManagerKey, manager);
+ }
+ return manager->GetNSSCertDatabase(callback);
+}
+
+void CallWithNSSCertDatabase(
+ const base::Callback<void(net::NSSCertDatabase*)>& callback,
+ net::NSSCertDatabaseChromeOS* db) {
+ callback.Run(db);
+}
+
+void SetSystemSlot(crypto::ScopedPK11Slot system_slot,
+ net::NSSCertDatabaseChromeOS* db) {
+ db->SetSystemSlot(system_slot.Pass());
+}
+
+void SetSystemSlotOfDBForResourceContext(content::ResourceContext* context,
+ crypto::ScopedPK11Slot system_slot) {
+ base::Callback<void(net::NSSCertDatabaseChromeOS*)> callback =
+ base::Bind(&SetSystemSlot, base::Passed(&system_slot));
+
+ net::NSSCertDatabaseChromeOS* db =
+ GetNSSCertDatabaseChromeOS(context, callback);
+ if (db)
+ callback.Run(db);
+}
+
} // namespace
crypto::ScopedPK11Slot GetPublicNSSKeySlotForResourceContext(
@@ -92,13 +130,16 @@ crypto::ScopedPK11Slot GetPrivateNSSKeySlotForResourceContext(
net::NSSCertDatabase* GetNSSCertDatabaseForResourceContext(
content::ResourceContext* context,
const base::Callback<void(net::NSSCertDatabase*)>& callback) {
+ return GetNSSCertDatabaseChromeOS(
+ context, base::Bind(&CallWithNSSCertDatabase, callback));
+}
+
+void EnableNSSSystemKeySlotForResourceContext(
+ content::ResourceContext* context) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
- NSSCertDatabaseChromeOSManager* manager =
- static_cast<NSSCertDatabaseChromeOSManager*>(
- context->GetUserData(kDatabaseManagerKey));
- if (!manager) {
- manager = new NSSCertDatabaseChromeOSManager(GetUsername(context));
- context->SetUserData(kDatabaseManagerKey, manager);
- }
- return manager->GetNSSCertDatabase(callback);
+ base::Callback<void(crypto::ScopedPK11Slot)> callback =
+ base::Bind(&SetSystemSlotOfDBForResourceContext, context);
+ crypto::ScopedPK11Slot system_slot = crypto::GetSystemNSSKeySlot(callback);
+ if (system_slot)
+ callback.Run(system_slot.Pass());
}
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
index 004c35e..b5ced2d 100644
--- a/chrome/browser/profiles/profile_io_data.cc
+++ b/chrome/browser/profiles/profile_io_data.cc
@@ -110,11 +110,13 @@
#include "chrome/browser/chromeos/login/startup_utils.h"
#include "chrome/browser/chromeos/login/users/user_manager.h"
#include "chrome/browser/chromeos/net/cert_verify_proc_chromeos.h"
+#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/policy/policy_cert_service.h"
#include "chrome/browser/chromeos/policy/policy_cert_service_factory.h"
#include "chrome/browser/chromeos/policy/policy_cert_verifier.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
+#include "chrome/browser/net/nss_context.h"
#include "chromeos/dbus/cryptohome_client.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/settings/cros_settings_names.h"
@@ -382,6 +384,15 @@ void ProfileIOData::InitializeOnUIThread(Profile* profile) {
user->email(),
user->username_hash(),
profile->GetPath()));
+
+ // Use the device-wide system key slot only if the user is of the same
+ // domain as the device is registered to.
+ policy::BrowserPolicyConnectorChromeOS* connector =
+ g_browser_process->platform_part()
+ ->browser_policy_connector_chromeos();
+ params->use_system_key_slot =
+ connector->GetUserAffiliation(user->email()) ==
+ policy::USER_AFFILIATION_MANAGED;
}
}
#endif
@@ -577,6 +588,9 @@ ProfileIOData::AppRequestContext::~AppRequestContext() {
ProfileIOData::ProfileParams::ProfileParams()
: io_thread(NULL),
+#if defined(OS_CHROMEOS)
+ use_system_key_slot(false),
+#endif
profile(NULL) {
}
@@ -584,6 +598,9 @@ ProfileIOData::ProfileParams::~ProfileParams() {}
ProfileIOData::ProfileIOData(Profile::ProfileType profile_type)
: initialized_(false),
+#if defined(OS_CHROMEOS)
+ use_system_key_slot_(false),
+#endif
resource_context_(new ResourceContext(this)),
initialized_on_UI_thread_(false),
profile_type_(profile_type) {
@@ -904,6 +921,7 @@ ProfileIOData::ResourceContext::CreateClientCertStore() {
return io_data_->client_cert_store_factory_.Run();
#if defined(OS_CHROMEOS)
return scoped_ptr<net::ClientCertStore>(new net::ClientCertStoreChromeOS(
+ io_data_->use_system_key_slot(),
io_data_->username_hash(),
base::Bind(&CreateCryptoModuleBlockingPasswordDelegate,
chrome::kCryptoModulePasswordClientAuth)));
@@ -1091,6 +1109,10 @@ void ProfileIOData::Init(
#if defined(OS_CHROMEOS)
username_hash_ = profile_params_->username_hash;
+ use_system_key_slot_ = profile_params_->use_system_key_slot;
+ if (use_system_key_slot_)
+ EnableNSSSystemKeySlotForResourceContext(resource_context_.get());
+
scoped_refptr<net::CertVerifyProc> verify_proc;
crypto::ScopedPK11Slot public_slot =
crypto::GetPublicSlotForChromeOSUser(username_hash_);
diff --git a/chrome/browser/profiles/profile_io_data.h b/chrome/browser/profiles/profile_io_data.h
index bc17731..f0d6149 100644
--- a/chrome/browser/profiles/profile_io_data.h
+++ b/chrome/browser/profiles/profile_io_data.h
@@ -213,6 +213,8 @@ class ProfileIOData {
std::string username_hash() const {
return username_hash_;
}
+
+ bool use_system_key_slot() const { return use_system_key_slot_; }
#endif
Profile::ProfileType profile_type() const {
@@ -326,6 +328,7 @@ class ProfileIOData {
#if defined(OS_CHROMEOS)
std::string username_hash;
+ bool use_system_key_slot;
#endif
// The profile this struct was populated from. It's passed as a void* to
@@ -589,6 +592,7 @@ class ProfileIOData {
#if defined(OS_CHROMEOS)
mutable scoped_ptr<policy::PolicyCertVerifier> cert_verifier_;
mutable std::string username_hash_;
+ mutable bool use_system_key_slot_;
#endif
mutable scoped_ptr<net::TransportSecurityPersister>
diff --git a/crypto/nss_util.cc b/crypto/nss_util.cc
index 29a0b66..062bcb5 100644
--- a/crypto/nss_util.cc
+++ b/crypto/nss_util.cc
@@ -394,19 +394,22 @@ class NSSInitSingleton {
}
initializing_tpm_token_ = false;
- if (tpm_slot_) {
- TPMReadyCallbackList callback_list;
- callback_list.swap(tpm_ready_callback_list_);
- for (TPMReadyCallbackList::iterator i = callback_list.begin();
- i != callback_list.end();
- ++i) {
- (*i).Run();
- }
- }
+ if (tpm_slot_)
+ RunAndClearTPMReadyCallbackList();
callback.Run(!!tpm_slot_);
}
+ void RunAndClearTPMReadyCallbackList() {
+ TPMReadyCallbackList callback_list;
+ callback_list.swap(tpm_ready_callback_list_);
+ for (TPMReadyCallbackList::iterator i = callback_list.begin();
+ i != callback_list.end();
+ ++i) {
+ i->Run();
+ }
+ }
+
bool IsTPMTokenReady(const base::Closure& callback) {
if (!callback.is_null()) {
// Cannot DCHECK in the general case yet, but since the callback is
@@ -579,6 +582,12 @@ class NSSInitSingleton {
// Unsetting, i.e. setting a NULL, however is allowed.
DCHECK(!slot || !test_system_slot_);
test_system_slot_ = slot.Pass();
+ if (test_system_slot_) {
+ tpm_slot_.reset(PK11_ReferenceSlot(test_system_slot_.get()));
+ RunAndClearTPMReadyCallbackList();
+ } else {
+ tpm_slot_.reset();
+ }
}
#endif // defined(OS_CHROMEOS)
@@ -1014,7 +1023,7 @@ ScopedPK11Slot GetSystemNSSKeySlot(
}
void SetSystemKeySlotForTesting(ScopedPK11Slot slot) {
- g_nss_singleton.Get().SetSystemKeySlotForTesting(ScopedPK11Slot());
+ g_nss_singleton.Get().SetSystemKeySlotForTesting(slot.Pass());
}
void EnableTPMTokenForNSS() {
diff --git a/crypto/nss_util_internal.h b/crypto/nss_util_internal.h
index cb1b9bd..839d7ba7 100644
--- a/crypto/nss_util_internal.h
+++ b/crypto/nss_util_internal.h
@@ -53,11 +53,10 @@ class CRYPTO_EXPORT AutoSECMODListReadLock {
CRYPTO_EXPORT ScopedPK11Slot GetSystemNSSKeySlot(
const base::Callback<void(ScopedPK11Slot)>& callback) WARN_UNUSED_RESULT;
-// Sets the test system slot. If this was called before
-// InitializeTPMTokenAndSystemSlot and no system token is provided by the Chaps
-// module, then this test slot will be used and the initialization continues as
-// if Chaps had provided this test slot. In particular, |slot| will be exposed
-// by |GetSystemNSSKeySlot| and |IsTPMTokenReady| will return true.
+// Sets the test system slot to |slot|, which means that |slot| will be exposed
+// through |GetSystemNSSKeySlot| and |IsTPMTokenReady| will return true.
+// |InitializeTPMTokenAndSystemSlot|, which triggers the TPM initialization,
+// does not have to be called if the test system slot is set.
// This must must not be called consecutively with a |slot| != NULL. If |slot|
// is NULL, the test system slot is unset.
CRYPTO_EXPORT_PRIVATE void SetSystemKeySlotForTesting(ScopedPK11Slot slot);
diff --git a/crypto/scoped_test_nss_db.h b/crypto/scoped_test_nss_db.h
index cc6996d..88c2d55 100644
--- a/crypto/scoped_test_nss_db.h
+++ b/crypto/scoped_test_nss_db.h
@@ -20,8 +20,8 @@ class CRYPTO_EXPORT_PRIVATE ScopedTestNSSDB {
ScopedTestNSSDB();
~ScopedTestNSSDB();
- bool is_open() { return slot_; }
- PK11SlotInfo* slot() { return slot_.get(); }
+ bool is_open() const { return slot_; }
+ PK11SlotInfo* slot() const { return slot_.get(); }
private:
base::ScopedTempDir temp_dir_;
diff --git a/crypto/scoped_test_system_nss_key_slot.cc b/crypto/scoped_test_system_nss_key_slot.cc
index ee5e1df..53fbbff 100644
--- a/crypto/scoped_test_system_nss_key_slot.cc
+++ b/crypto/scoped_test_system_nss_key_slot.cc
@@ -25,4 +25,8 @@ bool ScopedTestSystemNSSKeySlot::ConstructedSuccessfully() const {
return test_db_->is_open();
}
+PK11SlotInfo* ScopedTestSystemNSSKeySlot::slot() const {
+ return test_db_->slot();
+}
+
} // namespace crypto
diff --git a/crypto/scoped_test_system_nss_key_slot.h b/crypto/scoped_test_system_nss_key_slot.h
index 1565047..ac3b72c 100644
--- a/crypto/scoped_test_system_nss_key_slot.h
+++ b/crypto/scoped_test_system_nss_key_slot.h
@@ -9,17 +9,20 @@
#include "base/memory/scoped_ptr.h"
#include "crypto/crypto_export.h"
+// Forward declaration, from <pk11pub.h>
+typedef struct PK11SlotInfoStr PK11SlotInfo;
+
namespace crypto {
class ScopedTestNSSDB;
// Opens a persistent NSS software database in a temporary directory and sets
// the test system slot to the opened database. This helper should be created in
-// tests where no system token is provided by the Chaps module and before
-// InitializeTPMTokenAndSystemSlot is called. Then the opened test database will
-// be used and the initialization continues as if Chaps had provided this test
-// database. In particular, the DB will be exposed by |GetSystemNSSKeySlot| and
-// |IsTPMTokenReady| will return true.
+// tests to fake the system token that is usually provided by the Chaps module.
+// |slot| is exposed through |GetSystemNSSKeySlot| and |IsTPMTokenReady| will
+// return true.
+// |InitializeTPMTokenAndSystemSlot|, which triggers the TPM initialization,
+// does not have to be called if this helper is used.
// At most one instance of this helper must be used at a time.
class CRYPTO_EXPORT_PRIVATE ScopedTestSystemNSSKeySlot {
public:
@@ -27,6 +30,7 @@ class CRYPTO_EXPORT_PRIVATE ScopedTestSystemNSSKeySlot {
~ScopedTestSystemNSSKeySlot();
bool ConstructedSuccessfully() const;
+ PK11SlotInfo* slot() const;
private:
scoped_ptr<ScopedTestNSSDB> test_db_;
diff --git a/net/cert/nss_cert_database.cc b/net/cert/nss_cert_database.cc
index 8b69ca5..7e6755f 100644
--- a/net/cert/nss_cert_database.cc
+++ b/net/cert/nss_cert_database.cc
@@ -130,6 +130,12 @@ void NSSCertDatabase::ListCertsInSlot(const ListCertsCallback& callback,
base::Bind(callback, base::Passed(&certs)));
}
+#if defined(OS_CHROMEOS)
+crypto::ScopedPK11Slot NSSCertDatabase::GetSystemSlot() const {
+ return crypto::ScopedPK11Slot();
+}
+#endif
+
crypto::ScopedPK11Slot NSSCertDatabase::GetPublicSlot() const {
return crypto::ScopedPK11Slot(PK11_ReferenceSlot(public_slot_.get()));
}
diff --git a/net/cert/nss_cert_database.h b/net/cert/nss_cert_database.h
index 4c47429..f161169 100644
--- a/net/cert/nss_cert_database.h
+++ b/net/cert/nss_cert_database.h
@@ -130,6 +130,16 @@ class NET_EXPORT NSSCertDatabase {
virtual void ListCertsInSlot(const ListCertsCallback& callback,
PK11SlotInfo* slot);
+#if defined(OS_CHROMEOS)
+ // Get the slot for system-wide key data. May be NULL if the system token was
+ // not explicitly set.
+ // Note: The System slot is set after the NSSCertDatabase is constructed and
+ // this call returns synchronously. Thus, it is possible to call this function
+ // before SetSystemSlot is called and get a NULL result.
+ // See https://crbug.com/399554 .
+ virtual crypto::ScopedPK11Slot GetSystemSlot() const;
+#endif
+
// Get the default slot for public key data.
crypto::ScopedPK11Slot GetPublicSlot() const;
diff --git a/net/cert/nss_cert_database_chromeos.cc b/net/cert/nss_cert_database_chromeos.cc
index 60f7f2e..63d969c 100644
--- a/net/cert/nss_cert_database_chromeos.cc
+++ b/net/cert/nss_cert_database_chromeos.cc
@@ -22,11 +22,21 @@ NSSCertDatabaseChromeOS::NSSCertDatabaseChromeOS(
crypto::ScopedPK11Slot public_slot,
crypto::ScopedPK11Slot private_slot)
: NSSCertDatabase(public_slot.Pass(), private_slot.Pass()) {
- profile_filter_.Init(GetPublicSlot(), GetPrivateSlot());
+ // By default, don't use a system slot. Only if explicitly set by
+ // SetSystemSlot, the system slot will be used.
+ profile_filter_.Init(GetPublicSlot(),
+ GetPrivateSlot(),
+ crypto::ScopedPK11Slot() /* no system slot */);
}
NSSCertDatabaseChromeOS::~NSSCertDatabaseChromeOS() {}
+void NSSCertDatabaseChromeOS::SetSystemSlot(
+ crypto::ScopedPK11Slot system_slot) {
+ system_slot_ = system_slot.Pass();
+ profile_filter_.Init(GetPublicSlot(), GetPrivateSlot(), GetSystemSlot());
+}
+
void NSSCertDatabaseChromeOS::ListCertsSync(CertificateList* certs) {
ListCertsImpl(profile_filter_, certs);
}
@@ -45,6 +55,12 @@ void NSSCertDatabaseChromeOS::ListCerts(
base::Bind(callback, base::Passed(&certs)));
}
+crypto::ScopedPK11Slot NSSCertDatabaseChromeOS::GetSystemSlot() const {
+ if (system_slot_)
+ return crypto::ScopedPK11Slot(PK11_ReferenceSlot(system_slot_.get()));
+ return crypto::ScopedPK11Slot();
+}
+
void NSSCertDatabaseChromeOS::ListModules(CryptoModuleList* modules,
bool need_rw) const {
NSSCertDatabase::ListModules(modules, need_rw);
diff --git a/net/cert/nss_cert_database_chromeos.h b/net/cert/nss_cert_database_chromeos.h
index b68f742..dfcefec 100644
--- a/net/cert/nss_cert_database_chromeos.h
+++ b/net/cert/nss_cert_database_chromeos.h
@@ -20,12 +20,17 @@ class NET_EXPORT NSSCertDatabaseChromeOS : public NSSCertDatabase {
crypto::ScopedPK11Slot private_slot);
virtual ~NSSCertDatabaseChromeOS();
+ // |system_slot| is the system TPM slot, which is only enabled for certain
+ // users.
+ void SetSystemSlot(crypto::ScopedPK11Slot system_slot);
+
// NSSCertDatabase implementation.
virtual void ListCertsSync(CertificateList* certs) OVERRIDE;
virtual void ListCerts(const NSSCertDatabase::ListCertsCallback& callback)
OVERRIDE;
virtual void ListModules(CryptoModuleList* modules, bool need_rw) const
OVERRIDE;
+ virtual crypto::ScopedPK11Slot GetSystemSlot() const OVERRIDE;
// TODO(mattm): handle trust setting, deletion, etc correctly when certs exist
// in multiple slots.
@@ -40,6 +45,7 @@ class NET_EXPORT NSSCertDatabaseChromeOS : public NSSCertDatabase {
CertificateList* certs);
NSSProfileFilterChromeOS profile_filter_;
+ crypto::ScopedPK11Slot system_slot_;
DISALLOW_COPY_AND_ASSIGN(NSSCertDatabaseChromeOS);
};
diff --git a/net/cert/nss_profile_filter_chromeos.cc b/net/cert/nss_profile_filter_chromeos.cc
index e555750..8e4167a 100644
--- a/net/cert/nss_profile_filter_chromeos.cc
+++ b/net/cert/nss_profile_filter_chromeos.cc
@@ -43,6 +43,8 @@ NSSProfileFilterChromeOS::NSSProfileFilterChromeOS(
private_slot_.reset(other.private_slot_ ?
PK11_ReferenceSlot(other.private_slot_.get()) :
NULL);
+ system_slot_.reset(
+ other.system_slot_ ? PK11_ReferenceSlot(other.system_slot_.get()) : NULL);
}
NSSProfileFilterChromeOS::~NSSProfileFilterChromeOS() {}
@@ -55,11 +57,14 @@ NSSProfileFilterChromeOS& NSSProfileFilterChromeOS::operator=(
private_slot_.reset(other.private_slot_ ?
PK11_ReferenceSlot(other.private_slot_.get()) :
NULL);
+ system_slot_.reset(
+ other.system_slot_ ? PK11_ReferenceSlot(other.system_slot_.get()) : NULL);
return *this;
}
void NSSProfileFilterChromeOS::Init(crypto::ScopedPK11Slot public_slot,
- crypto::ScopedPK11Slot private_slot) {
+ crypto::ScopedPK11Slot private_slot,
+ crypto::ScopedPK11Slot system_slot) {
// crypto::ScopedPK11Slot actually holds a reference counted object.
// Because scoped_ptr<T> assignment is a no-op if it already points to
// the same pointer, a reference would be leaked because .Pass() does
@@ -69,12 +74,17 @@ void NSSProfileFilterChromeOS::Init(crypto::ScopedPK11Slot public_slot,
public_slot_ = public_slot.Pass();
if (private_slot_.get() != private_slot.get())
private_slot_ = private_slot.Pass();
+ if (system_slot_.get() != system_slot.get())
+ system_slot_ = system_slot.Pass();
}
bool NSSProfileFilterChromeOS::IsModuleAllowed(PK11SlotInfo* slot) const {
- // If this is one of the public/private slots for this profile, allow it.
- if (slot == public_slot_.get() || slot == private_slot_.get())
+ // If this is one of the public/private slots for this profile or the system
+ // slot, allow it.
+ if (slot == public_slot_.get() || slot == private_slot_.get() ||
+ slot == system_slot_.get()) {
return true;
+ }
// Allow the root certs module.
if (PK11_HasRootCerts(slot))
return true;
@@ -86,11 +96,17 @@ bool NSSProfileFilterChromeOS::IsModuleAllowed(PK11SlotInfo* slot) const {
if (!public_slot_.get() || !private_slot_.get())
return false;
// If this is not the internal (file-system) module or the TPM module, allow
- // it.
+ // it. This would allow smartcards/etc, although ChromeOS doesn't currently
+ // support that. (This assumes that private_slot_ and system_slot_ are on the
+ // same module.)
+ DCHECK(!system_slot_.get() ||
+ PK11_GetModule(private_slot_.get()) ==
+ PK11_GetModule(system_slot_.get()));
SECMODModule* module_for_slot = PK11_GetModule(slot);
if (module_for_slot != PK11_GetModule(public_slot_.get()) &&
- module_for_slot != PK11_GetModule(private_slot_.get()))
+ module_for_slot != PK11_GetModule(private_slot_.get())) {
return true;
+ }
return false;
}
diff --git a/net/cert/nss_profile_filter_chromeos.h b/net/cert/nss_profile_filter_chromeos.h
index 4698619..36c42d0 100644
--- a/net/cert/nss_profile_filter_chromeos.h
+++ b/net/cert/nss_profile_filter_chromeos.h
@@ -36,7 +36,8 @@ class NET_EXPORT NSSProfileFilterChromeOS {
// Initialize the filter with the slot handles to allow. This method is not
// thread-safe.
void Init(crypto::ScopedPK11Slot public_slot,
- crypto::ScopedPK11Slot private_slot);
+ crypto::ScopedPK11Slot private_slot,
+ crypto::ScopedPK11Slot system_slot);
bool IsModuleAllowed(PK11SlotInfo* slot) const;
bool IsCertAllowed(CERTCertificate* cert) const;
@@ -64,6 +65,7 @@ class NET_EXPORT NSSProfileFilterChromeOS {
private:
crypto::ScopedPK11Slot public_slot_;
crypto::ScopedPK11Slot private_slot_;
+ crypto::ScopedPK11Slot system_slot_;
};
} // namespace net
diff --git a/net/cert/nss_profile_filter_chromeos_unittest.cc b/net/cert/nss_profile_filter_chromeos_unittest.cc
index b133c33..b48a527 100644
--- a/net/cert/nss_profile_filter_chromeos_unittest.cc
+++ b/net/cert/nss_profile_filter_chromeos_unittest.cc
@@ -11,6 +11,7 @@
#include "crypto/nss_util_internal.h"
#include "crypto/scoped_nss_types.h"
#include "crypto/scoped_test_nss_chromeos_user.h"
+#include "crypto/scoped_test_nss_db.h"
#include "net/base/test_data_directory.h"
#include "net/test/cert_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -58,7 +59,7 @@ class NSSProfileFilterChromeOSTest : public testing::Test {
NSSProfileFilterChromeOSTest() : user_1_("user1"), user_2_("user2") {}
virtual void SetUp() OVERRIDE {
- // Initialize nss_util slots.
+ ASSERT_TRUE(system_slot_user_.is_open());
ASSERT_TRUE(user_1_.constructed_successfully());
ASSERT_TRUE(user_2_.constructed_successfully());
user_1_.FinishInit();
@@ -74,7 +75,8 @@ class NSSProfileFilterChromeOSTest : public testing::Test {
ASSERT_TRUE(private_slot_1.get());
profile_filter_1_.Init(
crypto::GetPublicSlotForChromeOSUser(user_1_.username_hash()),
- private_slot_1.Pass());
+ private_slot_1.Pass(),
+ get_system_slot());
profile_filter_1_copy_ = profile_filter_1_;
@@ -84,7 +86,8 @@ class NSSProfileFilterChromeOSTest : public testing::Test {
ASSERT_TRUE(private_slot_2.get());
profile_filter_2_.Init(
crypto::GetPublicSlotForChromeOSUser(user_2_.username_hash()),
- private_slot_2.Pass());
+ private_slot_2.Pass(),
+ crypto::ScopedPK11Slot() /* no system slot */);
certs_ = CreateCertificateListFromFile(GetTestCertsDirectory(),
"root_ca_cert.pem",
@@ -92,8 +95,13 @@ class NSSProfileFilterChromeOSTest : public testing::Test {
ASSERT_EQ(1U, certs_.size());
}
+ crypto::ScopedPK11Slot get_system_slot() {
+ return crypto::ScopedPK11Slot(PK11_ReferenceSlot(system_slot_user_.slot()));
+ }
+
protected:
CertificateList certs_;
+ crypto::ScopedTestNSSDB system_slot_user_;
crypto::ScopedTestNSSChromeOSUser user_1_;
crypto::ScopedTestNSSChromeOSUser user_2_;
NSSProfileFilterChromeOS no_slots_profile_filter_;
@@ -148,6 +156,7 @@ TEST_F(NSSProfileFilterChromeOSTest, RootCertsAllowed) {
}
TEST_F(NSSProfileFilterChromeOSTest, SoftwareSlots) {
+ crypto::ScopedPK11Slot system_slot(get_system_slot());
crypto::ScopedPK11Slot slot_1(
crypto::GetPublicSlotForChromeOSUser(user_1_.username_hash()));
ASSERT_TRUE(slot_1);
@@ -160,6 +169,12 @@ TEST_F(NSSProfileFilterChromeOSTest, SoftwareSlots) {
GetTestCertsDirectory(), "ok_cert.pem", X509Certificate::FORMAT_AUTO);
ASSERT_EQ(1U, certs_2.size());
scoped_refptr<X509Certificate> cert_2 = certs_2[0];
+ CertificateList system_certs =
+ CreateCertificateListFromFile(GetTestCertsDirectory(),
+ "mit.davidben.der",
+ X509Certificate::FORMAT_AUTO);
+ ASSERT_EQ(1U, system_certs.size());
+ scoped_refptr<X509Certificate> system_cert = system_certs[0];
ASSERT_EQ(SECSuccess,
PK11_ImportCert(slot_1.get(),
@@ -174,19 +189,31 @@ TEST_F(NSSProfileFilterChromeOSTest, SoftwareSlots) {
CK_INVALID_HANDLE,
"cert2",
PR_FALSE /* includeTrust (unused) */));
+ ASSERT_EQ(SECSuccess,
+ PK11_ImportCert(system_slot.get(),
+ system_cert->os_cert_handle(),
+ CK_INVALID_HANDLE,
+ "systemcert",
+ PR_FALSE /* includeTrust (unused) */));
EXPECT_FALSE(
no_slots_profile_filter_.IsCertAllowed(cert_1->os_cert_handle()));
EXPECT_FALSE(
no_slots_profile_filter_.IsCertAllowed(cert_2->os_cert_handle()));
+ EXPECT_FALSE(
+ no_slots_profile_filter_.IsCertAllowed(system_cert->os_cert_handle()));
EXPECT_TRUE(profile_filter_1_.IsCertAllowed(cert_1->os_cert_handle()));
EXPECT_TRUE(profile_filter_1_copy_.IsCertAllowed(cert_1->os_cert_handle()));
EXPECT_FALSE(profile_filter_1_.IsCertAllowed(cert_2->os_cert_handle()));
EXPECT_FALSE(profile_filter_1_copy_.IsCertAllowed(cert_2->os_cert_handle()));
+ EXPECT_TRUE(profile_filter_1_.IsCertAllowed(system_cert->os_cert_handle()));
+ EXPECT_TRUE(
+ profile_filter_1_copy_.IsCertAllowed(system_cert->os_cert_handle()));
EXPECT_FALSE(profile_filter_2_.IsCertAllowed(cert_1->os_cert_handle()));
EXPECT_TRUE(profile_filter_2_.IsCertAllowed(cert_2->os_cert_handle()));
+ EXPECT_FALSE(profile_filter_2_.IsCertAllowed(system_cert->os_cert_handle()));
}
} // namespace net
diff --git a/net/ssl/client_cert_store_chromeos.cc b/net/ssl/client_cert_store_chromeos.cc
index bd4a5c4..6dacd45 100644
--- a/net/ssl/client_cert_store_chromeos.cc
+++ b/net/ssl/client_cert_store_chromeos.cc
@@ -12,11 +12,46 @@
namespace net {
+namespace {
+
+typedef base::Callback<void(crypto::ScopedPK11Slot system_slot,
+ crypto::ScopedPK11Slot private_slot)>
+ GetSystemAndPrivateSlotCallback;
+
+// Gets the private slot for the user with the username hash |username_hash| and
+// calls |callback| with both |system_slot| and the obtained private slot.
+void GetPrivateSlotAndCallBack(const std::string& username_hash,
+ const GetSystemAndPrivateSlotCallback& callback,
+ crypto::ScopedPK11Slot system_slot) {
+ base::Callback<void(crypto::ScopedPK11Slot)> wrapped_callback =
+ base::Bind(callback, base::Passed(&system_slot));
+
+ crypto::ScopedPK11Slot slot(
+ crypto::GetPrivateSlotForChromeOSUser(username_hash, wrapped_callback));
+ if (slot)
+ wrapped_callback.Run(slot.Pass());
+}
+
+// Gets the system slot, then the private slot for the user with the username
+// hash |username_hash|, and finally calls |callback| with both slots.
+void GetSystemAndPrivateSlot(const std::string& username_hash,
+ const GetSystemAndPrivateSlotCallback& callback) {
+ crypto::ScopedPK11Slot system_slot(crypto::GetSystemNSSKeySlot(
+ base::Bind(&GetPrivateSlotAndCallBack, username_hash, callback)));
+ if (system_slot)
+ GetPrivateSlotAndCallBack(username_hash, callback, system_slot.Pass());
+}
+
+} // namespace
+
ClientCertStoreChromeOS::ClientCertStoreChromeOS(
+ bool use_system_slot,
const std::string& username_hash,
const PasswordDelegateFactory& password_delegate_factory)
: ClientCertStoreNSS(password_delegate_factory),
- username_hash_(username_hash) {}
+ use_system_slot_(use_system_slot),
+ username_hash_(username_hash) {
+}
ClientCertStoreChromeOS::~ClientCertStoreChromeOS() {}
@@ -24,24 +59,29 @@ void ClientCertStoreChromeOS::GetClientCerts(
const SSLCertRequestInfo& cert_request_info,
CertificateList* selected_certs,
const base::Closure& callback) {
- crypto::ScopedPK11Slot private_slot(crypto::GetPrivateSlotForChromeOSUser(
- username_hash_,
- base::Bind(&ClientCertStoreChromeOS::DidGetPrivateSlot,
+ GetSystemAndPrivateSlotCallback bound_callback =
+ base::Bind(&ClientCertStoreChromeOS::DidGetSystemAndPrivateSlot,
// Caller is responsible for keeping the ClientCertStore alive
// until the callback is run.
base::Unretained(this),
&cert_request_info,
selected_certs,
- callback)));
- if (private_slot)
- DidGetPrivateSlot(
- &cert_request_info, selected_certs, callback, private_slot.Pass());
+ callback);
+
+ if (use_system_slot_) {
+ GetSystemAndPrivateSlot(username_hash_, bound_callback);
+ } else {
+ // Skip getting the system slot.
+ GetPrivateSlotAndCallBack(
+ username_hash_, bound_callback, crypto::ScopedPK11Slot());
+ }
}
-void ClientCertStoreChromeOS::GetClientCertsImpl(CERTCertList* cert_list,
- const SSLCertRequestInfo& request,
- bool query_nssdb,
- CertificateList* selected_certs) {
+void ClientCertStoreChromeOS::GetClientCertsImpl(
+ CERTCertList* cert_list,
+ const SSLCertRequestInfo& request,
+ bool query_nssdb,
+ CertificateList* selected_certs) {
ClientCertStoreNSS::GetClientCertsImpl(
cert_list, request, query_nssdb, selected_certs);
@@ -57,13 +97,15 @@ void ClientCertStoreChromeOS::GetClientCertsImpl(CERTCertList* cert_list,
<< pre_size << " certs";
}
-void ClientCertStoreChromeOS::DidGetPrivateSlot(
+void ClientCertStoreChromeOS::DidGetSystemAndPrivateSlot(
const SSLCertRequestInfo* request,
CertificateList* selected_certs,
const base::Closure& callback,
+ crypto::ScopedPK11Slot system_slot,
crypto::ScopedPK11Slot private_slot) {
profile_filter_.Init(crypto::GetPublicSlotForChromeOSUser(username_hash_),
- private_slot.Pass());
+ private_slot.Pass(),
+ system_slot.Pass());
ClientCertStoreNSS::GetClientCerts(*request, selected_certs, callback);
}
diff --git a/net/ssl/client_cert_store_chromeos.h b/net/ssl/client_cert_store_chromeos.h
index 087190c..940888d 100644
--- a/net/ssl/client_cert_store_chromeos.h
+++ b/net/ssl/client_cert_store_chromeos.h
@@ -15,7 +15,11 @@ namespace net {
class NET_EXPORT ClientCertStoreChromeOS : public ClientCertStoreNSS {
public:
+ // Constructs a ClientCertStore that will return client certs available on
+ // the user's private and public slots. If |use_system_slot| is true, certs on
+ // the system slot will also be returned.
ClientCertStoreChromeOS(
+ bool use_system_slot,
const std::string& username_hash,
const PasswordDelegateFactory& password_delegate_factory);
virtual ~ClientCertStoreChromeOS();
@@ -33,13 +37,13 @@ class NET_EXPORT ClientCertStoreChromeOS : public ClientCertStoreNSS {
CertificateList* selected_certs) OVERRIDE;
private:
- friend class ClientCertStoreChromeOSTestDelegate;
-
- void DidGetPrivateSlot(const SSLCertRequestInfo* request,
- CertificateList* selected_certs,
- const base::Closure& callback,
- crypto::ScopedPK11Slot private_slot);
+ void DidGetSystemAndPrivateSlot(const SSLCertRequestInfo* request,
+ CertificateList* selected_certs,
+ const base::Closure& callback,
+ crypto::ScopedPK11Slot system_slot,
+ crypto::ScopedPK11Slot private_slot);
+ bool use_system_slot_;
std::string username_hash_;
NSSProfileFilterChromeOS profile_filter_;
diff --git a/net/ssl/client_cert_store_chromeos_unittest.cc b/net/ssl/client_cert_store_chromeos_unittest.cc
index 3bd6d60..12a1b43 100644
--- a/net/ssl/client_cert_store_chromeos_unittest.cc
+++ b/net/ssl/client_cert_store_chromeos_unittest.cc
@@ -14,6 +14,7 @@
#include "crypto/nss_util_internal.h"
#include "crypto/rsa_private_key.h"
#include "crypto/scoped_test_nss_chromeos_user.h"
+#include "crypto/scoped_test_system_nss_key_slot.h"
#include "net/base/test_data_directory.h"
#include "net/cert/cert_type.h"
#include "net/cert/x509_certificate.h"
@@ -42,15 +43,28 @@ bool ImportClientCertToSlot(const scoped_refptr<X509Certificate>& cert,
return true;
}
+enum ReadFromSlot {
+ READ_FROM_SLOT_USER,
+ READ_FROM_SLOT_SYSTEM
+};
+
+enum SystemSlotAvailability {
+ SYSTEM_SLOT_AVAILABILITY_ENABLED,
+ SYSTEM_SLOT_AVAILABILITY_DISABLED
+};
+
} // namespace
// Define a delegate to be used for instantiating the parameterized test set
// ClientCertStoreTest.
+template <ReadFromSlot read_from,
+ SystemSlotAvailability system_slot_availability>
class ClientCertStoreChromeOSTestDelegate {
public:
ClientCertStoreChromeOSTestDelegate()
: user_("scopeduser"),
- store_(user_.username_hash(),
+ store_(system_slot_availability == SYSTEM_SLOT_AVAILABILITY_ENABLED,
+ user_.username_hash(),
ClientCertStoreChromeOS::PasswordDelegateFactory()) {
// Defer futher initialization and checks to SelectClientCerts, because the
// constructor doesn't allow us to return an initialization result. Could be
@@ -72,10 +86,19 @@ class ClientCertStoreChromeOSTestDelegate {
}
user_.FinishInit();
- crypto::ScopedPK11Slot slot(
- crypto::GetPublicSlotForChromeOSUser(user_.username_hash()));
+ crypto::ScopedPK11Slot slot;
+ switch (read_from) {
+ case READ_FROM_SLOT_USER:
+ slot = crypto::GetPublicSlotForChromeOSUser(user_.username_hash());
+ break;
+ case READ_FROM_SLOT_SYSTEM:
+ slot.reset(PK11_ReferenceSlot(system_db_.slot()));
+ break;
+ default:
+ CHECK(false);
+ }
if (!slot) {
- LOG(ERROR) << "Could not get the user's public slot";
+ LOG(ERROR) << "Could not get the NSS key slot";
return false;
}
@@ -104,6 +127,7 @@ class ClientCertStoreChromeOSTestDelegate {
private:
crypto::ScopedTestNSSChromeOSUser user_;
+ crypto::ScopedTestSystemNSSKeySlot system_db_;
ClientCertStoreChromeOS store_;
};
@@ -112,26 +136,43 @@ class ClientCertStoreChromeOSTestDelegate {
// To verify that this delegation is functional, run the same filtering tests as
// for the other implementations. These tests are defined in
// client_cert_store_unittest-inl.h and are instantiated for each platform.
-INSTANTIATE_TYPED_TEST_CASE_P(ChromeOS,
+
+// In this case, all requested certs are read from the user's slot and the
+// system slot is not enabled in the store.
+typedef ClientCertStoreChromeOSTestDelegate<READ_FROM_SLOT_USER,
+ SYSTEM_SLOT_AVAILABILITY_DISABLED>
+ DelegateReadUserDisableSystem;
+INSTANTIATE_TYPED_TEST_CASE_P(ChromeOS_ReadUserDisableSystem,
+ ClientCertStoreTest,
+ DelegateReadUserDisableSystem);
+
+// In this case, all requested certs are read from the user's slot and the
+// system slot is enabled in the store.
+typedef ClientCertStoreChromeOSTestDelegate<READ_FROM_SLOT_USER,
+ SYSTEM_SLOT_AVAILABILITY_ENABLED>
+ DelegateReadUserEnableSystem;
+INSTANTIATE_TYPED_TEST_CASE_P(ChromeOS_ReadUserEnableSystem,
+ ClientCertStoreTest,
+ DelegateReadUserEnableSystem);
+
+// In this case, all requested certs are read from the system slot, therefore
+// the system slot is enabled in the store.
+typedef ClientCertStoreChromeOSTestDelegate<READ_FROM_SLOT_SYSTEM,
+ SYSTEM_SLOT_AVAILABILITY_ENABLED>
+ DelegateReadSystem;
+INSTANTIATE_TYPED_TEST_CASE_P(ChromeOS_ReadSystem,
ClientCertStoreTest,
- ClientCertStoreChromeOSTestDelegate);
+ DelegateReadSystem);
class ClientCertStoreChromeOSTest : public ::testing::Test {
public:
- scoped_refptr<X509Certificate> ImportCertForUser(
- const std::string& username_hash,
+ scoped_refptr<X509Certificate> ImportCertToSlot(
const std::string& cert_filename,
- const std::string& key_filename) {
- crypto::ScopedPK11Slot slot(
- crypto::GetPublicSlotForChromeOSUser(username_hash));
- if (!slot) {
- LOG(ERROR) << "No slot for user " << username_hash;
- return NULL;
- }
-
+ const std::string& key_filename,
+ PK11SlotInfo* slot) {
if (!ImportSensitiveKeyFromFile(
- GetTestCertsDirectory(), key_filename, slot.get())) {
- LOG(ERROR) << "Could not import private key for user " << username_hash;
+ GetTestCertsDirectory(), key_filename, slot)) {
+ LOG(ERROR) << "Could not import private key from file " << key_filename;
return NULL;
}
@@ -143,7 +184,7 @@ class ClientCertStoreChromeOSTest : public ::testing::Test {
return NULL;
}
- if (!ImportClientCertToSlot(cert, slot.get()))
+ if (!ImportClientCertToSlot(cert, slot))
return NULL;
// |cert| continues to point to the original X509Certificate before the
@@ -151,6 +192,21 @@ class ClientCertStoreChromeOSTest : public ::testing::Test {
// test.
return cert;
}
+
+ scoped_refptr<X509Certificate> ImportCertForUser(
+ const std::string& username_hash,
+ const std::string& cert_filename,
+ const std::string& key_filename) {
+ crypto::ScopedPK11Slot slot(
+ crypto::GetPublicSlotForChromeOSUser(username_hash));
+ if (!slot) {
+ LOG(ERROR) << "No slot for user " << username_hash;
+ return NULL;
+ }
+
+ return ImportCertToSlot(cert_filename, key_filename, slot.get());
+ }
+
};
// Ensure that cert requests, that are started before the user's NSS DB is
@@ -158,8 +214,13 @@ class ClientCertStoreChromeOSTest : public ::testing::Test {
TEST_F(ClientCertStoreChromeOSTest, RequestWaitsForNSSInitAndSucceeds) {
crypto::ScopedTestNSSChromeOSUser user("scopeduser");
ASSERT_TRUE(user.constructed_successfully());
+
+ crypto::ScopedTestSystemNSSKeySlot system_slot;
+
ClientCertStoreChromeOS store(
- user.username_hash(), ClientCertStoreChromeOS::PasswordDelegateFactory());
+ true /* use system slot */,
+ user.username_hash(),
+ ClientCertStoreChromeOS::PasswordDelegateFactory());
scoped_refptr<X509Certificate> cert_1(
ImportCertForUser(user.username_hash(), "client_1.pem", "client_1.pk8"));
ASSERT_TRUE(cert_1);
@@ -194,8 +255,12 @@ TEST_F(ClientCertStoreChromeOSTest, RequestsAfterNSSInitSucceed) {
ASSERT_TRUE(user.constructed_successfully());
user.FinishInit();
+ crypto::ScopedTestSystemNSSKeySlot system_slot;
+
ClientCertStoreChromeOS store(
- user.username_hash(), ClientCertStoreChromeOS::PasswordDelegateFactory());
+ true /* use system slot */,
+ user.username_hash(),
+ ClientCertStoreChromeOS::PasswordDelegateFactory());
scoped_refptr<X509Certificate> cert_1(
ImportCertForUser(user.username_hash(), "client_1.pem", "client_1.pk8"));
ASSERT_TRUE(cert_1);
@@ -213,7 +278,7 @@ TEST_F(ClientCertStoreChromeOSTest, RequestsAfterNSSInitSucceed) {
// This verifies that a request in the context of User1 doesn't see certificates
// of User2, and the other way round. We check both directions, to ensure that
// the behavior doesn't depend on initialization order of the DBs, for example.
-TEST_F(ClientCertStoreChromeOSTest, RequestDoesCrossReadSecondDB) {
+TEST_F(ClientCertStoreChromeOSTest, RequestDoesCrossReadOtherUserDB) {
crypto::ScopedTestNSSChromeOSUser user1("scopeduser1");
ASSERT_TRUE(user1.constructed_successfully());
crypto::ScopedTestNSSChromeOSUser user2("scopeduser2");
@@ -222,10 +287,14 @@ TEST_F(ClientCertStoreChromeOSTest, RequestDoesCrossReadSecondDB) {
user1.FinishInit();
user2.FinishInit();
+ crypto::ScopedTestSystemNSSKeySlot system_slot;
+
ClientCertStoreChromeOS store1(
+ true /* use system slot */,
user1.username_hash(),
ClientCertStoreChromeOS::PasswordDelegateFactory());
ClientCertStoreChromeOS store2(
+ true /* use system slot */,
user2.username_hash(),
ClientCertStoreChromeOS::PasswordDelegateFactory());
@@ -259,4 +328,40 @@ TEST_F(ClientCertStoreChromeOSTest, RequestDoesCrossReadSecondDB) {
EXPECT_TRUE(cert_2->Equals(selected_certs2[0]));
}
+// This verifies that a request in the context of User1 doesn't see certificates
+// of the system store if the system store is disabled.
+TEST_F(ClientCertStoreChromeOSTest, RequestDoesCrossReadSystemDB) {
+ crypto::ScopedTestNSSChromeOSUser user1("scopeduser1");
+ ASSERT_TRUE(user1.constructed_successfully());
+
+ user1.FinishInit();
+
+ crypto::ScopedTestSystemNSSKeySlot system_slot;
+
+ ClientCertStoreChromeOS store(
+ false /* do not use system slot */,
+ user1.username_hash(),
+ ClientCertStoreChromeOS::PasswordDelegateFactory());
+
+ scoped_refptr<X509Certificate> cert_1(
+ ImportCertForUser(user1.username_hash(), "client_1.pem", "client_1.pk8"));
+ ASSERT_TRUE(cert_1);
+ scoped_refptr<X509Certificate> cert_2(
+ ImportCertToSlot("client_2.pem", "client_2.pk8", system_slot.slot()));
+ ASSERT_TRUE(cert_2);
+
+ scoped_refptr<SSLCertRequestInfo> request_all(new SSLCertRequestInfo());
+
+ base::RunLoop run_loop;
+
+ CertificateList selected_certs;
+ store.GetClientCerts(*request_all, &selected_certs, run_loop.QuitClosure());
+
+ run_loop.Run();
+
+ // store should only return certs of the user, namely cert_1.
+ ASSERT_EQ(1u, selected_certs.size());
+ EXPECT_TRUE(cert_1->Equals(selected_certs[0]));
+}
+
} // namespace net