summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpneubeck@chromium.org <pneubeck@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-02 07:37:24 +0000
committerpneubeck@chromium.org <pneubeck@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-02 07:37:24 +0000
commit442233d48747e65512b01ee892ba0c3a4eb8935a (patch)
treed48d3a5868e45e14be94cf101dab4c6bdbc4f83c
parenta093e53ac4c5df37c17ee95c1ba456133bd4f013 (diff)
downloadchromium_src-442233d48747e65512b01ee892ba0c3a4eb8935a.zip
chromium_src-442233d48747e65512b01ee892ba0c3a4eb8935a.tar.gz
chromium_src-442233d48747e65512b01ee892ba0c3a4eb8935a.tar.bz2
Enable system NSS key slot.
This only affects users of domains that the device is registered to for policy. All other users are unaffected (EnableNSSSystemKeySlotForResourceContext is only called for USER_AFFILIATION_MANAGED) For the affected users, this enables and uses the slot for - client authentication for TSL (see ClientCertStoreChromeOS) - client authentication for 802.1x networks - listing/removing certificates on the settings page (see CertificateManager) In a follow up, also the enterprise.platformKeys API will be updated. Depends on: https://codereview.chromium.org/426983002/ https://codereview.chromium.org/428933002/ BUG=210525 R=mattm@chromium.org, rsleevi@chromium.org, willchan@chromium.org, xiyuan@chromium.org Review URL: https://codereview.chromium.org/424523002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@287175 0039d316-1c4b-4281-b951-d872f2087c98
-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