Commit 442233d4 authored by pneubeck@chromium.org's avatar pneubeck@chromium.org

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
parent a093e53a
......@@ -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() {}
......
......@@ -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
......
......@@ -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());
}
......@@ -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_);
......
......@@ -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>
......
......@@ -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() {
......
......@@ -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);
......
......@@ -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_;
......
......@@ -25,4 +25,8 @@ bool ScopedTestSystemNSSKeySlot::ConstructedSuccessfully() const {
return test_db_->is_open();
}
PK11SlotInfo* ScopedTestSystemNSSKeySlot::slot() const {
return test_db_->slot();
}
} // namespace crypto
......@@ -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_;
......
......@@ -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()));
}
......
......@@ -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;
......
......@@ -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);
......
......@@ -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);
};
......
......@@ -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;
}
......
......@@ -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
......
......@@ -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()));