summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortbarzic@chromium.org <tbarzic@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-12 12:46:17 +0000
committertbarzic@chromium.org <tbarzic@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-12 12:46:17 +0000
commit4071e6ac6d212ca5cc90cef59ed9f4852cfed50c (patch)
tree405b9842525c655d478f55c689fd6c7a36aeceee
parent1f48bda5498e693e5de11b9c9bb5899f83fa1882 (diff)
downloadchromium_src-4071e6ac6d212ca5cc90cef59ed9f4852cfed50c.zip
chromium_src-4071e6ac6d212ca5cc90cef59ed9f4852cfed50c.tar.gz
chromium_src-4071e6ac6d212ca5cc90cef59ed9f4852cfed50c.tar.bz2
Remove usage of singleton software_slot_ in nss on ChromeOS
Instead of opening primary user's public slot separately, do it like it's done for other users: when InitializeNSSForChromeOSUser is called. This makes primary user's public slot state not dependent on chromeos::TPMTokenLoader. Also, with this, opening primary users public slot is not bound with enabling TPM anymore, so the slot may get open for guest user and on Linux ChromeOS. BUG=383663, 302062 Review URL: https://codereview.chromium.org/317613004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@282817 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chromeos/login/auth/parallel_authenticator.cc8
-rw-r--r--chrome/browser/chromeos/login/auth/parallel_authenticator_unittest.cc36
-rw-r--r--chrome/browser/chromeos/ownership/owner_settings_service.cc51
-rw-r--r--chrome/browser/chromeos/ownership/owner_settings_service.h8
-rw-r--r--chrome/browser/profiles/profile_io_data.cc35
-rw-r--r--chromeos/tpm_token_loader.cc25
-rw-r--r--chromeos/tpm_token_loader.h4
-rw-r--r--crypto/nss_util.cc117
-rw-r--r--crypto/nss_util.h5
-rw-r--r--crypto/nss_util_internal.h16
-rw-r--r--crypto/rsa_private_key_nss_unittest.cc6
-rw-r--r--net/base/keygen_handler_unittest.cc5
12 files changed, 177 insertions, 139 deletions
diff --git a/chrome/browser/chromeos/login/auth/parallel_authenticator.cc b/chrome/browser/chromeos/login/auth/parallel_authenticator.cc
index c729704..c2475e2 100644
--- a/chrome/browser/chromeos/login/auth/parallel_authenticator.cc
+++ b/chrome/browser/chromeos/login/auth/parallel_authenticator.cc
@@ -508,14 +508,16 @@ bool ParallelAuthenticator::VerifyOwner() {
const std::string& user_id = current_state_->user_context.GetUserID();
OwnerSettingsServiceFactory::GetInstance()->SetUsername(user_id);
- // This should trigger certificate loading, which is needed in order to
- // correctly determine if the current user is the owner.
+ // |IsOwnerForSafeModeAsync| expects logged in state to be
+ // LOGGED_IN_SAFE_MODE.
if (LoginState::IsInitialized()) {
LoginState::Get()->SetLoggedInState(LoginState::LOGGED_IN_SAFE_MODE,
LoginState::LOGGED_IN_USER_NONE);
}
- OwnerSettingsService::IsPrivateKeyExistAsync(
+ OwnerSettingsService::IsOwnerForSafeModeAsync(
+ user_id,
+ current_state_->user_context.GetUserIDHash(),
base::Bind(&ParallelAuthenticator::OnOwnershipChecked, this));
return false;
}
diff --git a/chrome/browser/chromeos/login/auth/parallel_authenticator_unittest.cc b/chrome/browser/chromeos/login/auth/parallel_authenticator_unittest.cc
index 37f6005e..7ff4a2c 100644
--- a/chrome/browser/chromeos/login/auth/parallel_authenticator_unittest.cc
+++ b/chrome/browser/chromeos/login/auth/parallel_authenticator_unittest.cc
@@ -24,8 +24,11 @@
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/device_settings_test_helper.h"
+#include "chrome/browser/chromeos/settings/mock_owner_key_util.h"
#include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
+#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/testing_profile_manager.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/cryptohome/mock_async_method_caller.h"
#include "chromeos/cryptohome/system_salt_getter.h"
@@ -34,6 +37,7 @@
#include "chromeos/login/auth/key.h"
#include "chromeos/login/auth/user_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "crypto/nss_util.h"
#include "google_apis/gaia/mock_url_fetcher_factory.h"
#include "net/base/net_errors.h"
#include "net/url_request/url_request_status.h"
@@ -54,8 +58,10 @@ class ParallelAuthenticatorTest : public testing::Test {
: user_context_("me@nowhere.org"),
user_manager_(new FakeUserManager()),
user_manager_enabler_(user_manager_),
- mock_caller_(NULL) {
+ mock_caller_(NULL),
+ owner_key_util_(new MockOwnerKeyUtil) {
user_context_.SetKey(Key("fakepass"));
+ user_context_.SetUserIDHash("me_nowhere_com_hash");
const User* user = user_manager_->AddUser(user_context_.GetUserID());
profile_.set_profile_name(user_context_.GetUserID());
@@ -67,9 +73,7 @@ class ParallelAuthenticatorTest : public testing::Test {
FakeCryptohomeClient::GetStubSystemSalt()));
}
- virtual ~ParallelAuthenticatorTest() {
- DCHECK(!mock_caller_);
- }
+ virtual ~ParallelAuthenticatorTest() {}
virtual void SetUp() {
CommandLine::ForCurrentProcess()->AppendSwitch(switches::kLoginManager);
@@ -85,12 +89,15 @@ class ParallelAuthenticatorTest : public testing::Test {
SystemSaltGetter::Initialize();
+ OwnerSettingsService::SetOwnerKeyUtilForTesting(owner_key_util_);
+
auth_ = new ParallelAuthenticator(&consumer_);
state_.reset(new TestAttemptState(user_context_, false));
}
// Tears down the test fixture.
virtual void TearDown() {
+ OwnerSettingsService::SetOwnerKeyUtilForTesting(NULL);
SystemSaltGetter::Shutdown();
DBusThreadManager::Shutdown();
@@ -193,15 +200,20 @@ class ParallelAuthenticatorTest : public testing::Test {
ScopedTestCrosSettings test_cros_settings_;
TestingProfile profile_;
+ scoped_ptr<TestingProfileManager> profile_manager_;
FakeUserManager* user_manager_;
ScopedUserManagerEnabler user_manager_enabler_;
cryptohome::MockAsyncMethodCaller* mock_caller_;
+ crypto::ScopedTestNSSDB test_nssdb_;
+
MockConsumer consumer_;
scoped_refptr<ParallelAuthenticator> auth_;
scoped_ptr<TestAttemptState> state_;
FakeCryptohomeClient* fake_cryptohome_client_;
+
+ scoped_refptr<MockOwnerKeyUtil> owner_key_util_;
};
TEST_F(ParallelAuthenticatorTest, OnLoginSuccess) {
@@ -276,6 +288,10 @@ TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededMount) {
}
TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededFailedMount) {
+ profile_manager_.reset(
+ new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
+ ASSERT_TRUE(profile_manager_->SetUp());
+
FailOnLoginSuccess(); // Set failing on success as the default...
LoginFailure failure = LoginFailure(LoginFailure::OWNER_REQUIRED);
ExpectLoginFailure(failure);
@@ -305,20 +321,18 @@ TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededFailedMount) {
SetAndResolveState(auth_.get(), state_.release()));
EXPECT_TRUE(LoginState::Get()->IsInSafeMode());
- // Simulate TPM token ready event.
- OwnerSettingsService* service =
- OwnerSettingsServiceFactory::GetForProfile(&profile_);
- ASSERT_TRUE(service);
- service->OnTPMTokenReady();
-
// Flush all the pending operations. The operations should induce an owner
// verification.
device_settings_test_helper_.Flush();
- // Test that the mount has succeeded.
+
state_.reset(new TestAttemptState(user_context_, false));
state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE);
+
+ // The owner key util should not have found the owner key, so login should
+ // not be allowed.
EXPECT_EQ(ParallelAuthenticator::OWNER_REQUIRED,
SetAndResolveState(auth_.get(), state_.release()));
+ EXPECT_TRUE(LoginState::Get()->IsInSafeMode());
// Unset global objects used by this test.
LoginState::Shutdown();
diff --git a/chrome/browser/chromeos/ownership/owner_settings_service.cc b/chrome/browser/chromeos/ownership/owner_settings_service.cc
index cf08b95..81724df 100644
--- a/chrome/browser/chromeos/ownership/owner_settings_service.cc
+++ b/chrome/browser/chromeos/ownership/owner_settings_service.cc
@@ -7,6 +7,7 @@
#include <string>
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/login/users/user.h"
#include "chrome/browser/chromeos/login/users/user_manager.h"
@@ -102,7 +103,7 @@ void LoadPrivateKey(
}
}
-bool IsPrivateKeyExistAsyncHelper(
+bool DoesPrivateKeyExistAsyncHelper(
const scoped_refptr<OwnerKeyUtil>& owner_key_util) {
std::vector<uint8> public_key;
if (!owner_key_util->ImportPublicKey(&public_key))
@@ -113,6 +114,26 @@ bool IsPrivateKeyExistAsyncHelper(
return is_owner;
}
+// Checks whether NSS slots with private key are mounted or
+// not. Responds via |callback|.
+void DoesPrivateKeyExistAsync(
+ const OwnerSettingsService::IsOwnerCallback& callback) {
+ scoped_refptr<OwnerKeyUtil> owner_key_util;
+ if (g_owner_key_util_for_testing)
+ owner_key_util = *g_owner_key_util_for_testing;
+ else
+ owner_key_util = OwnerKeyUtil::Create();
+ scoped_refptr<base::TaskRunner> task_runner =
+ content::BrowserThread::GetBlockingPool()
+ ->GetTaskRunnerWithShutdownBehavior(
+ base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
+ base::PostTaskAndReplyWithResult(
+ task_runner.get(),
+ FROM_HERE,
+ base::Bind(&DoesPrivateKeyExistAsyncHelper, owner_key_util),
+ callback);
+}
+
} // namespace
OwnerSettingsService::OwnerSettingsService(Profile* profile)
@@ -197,22 +218,22 @@ void OwnerSettingsService::OnTPMTokenReady() {
}
// static
-void OwnerSettingsService::IsPrivateKeyExistAsync(
+void OwnerSettingsService::IsOwnerForSafeModeAsync(
+ const std::string& user_id,
+ const std::string& user_hash,
const IsOwnerCallback& callback) {
- scoped_refptr<OwnerKeyUtil> owner_key_util;
- if (g_owner_key_util_for_testing)
- owner_key_util = *g_owner_key_util_for_testing;
- else
- owner_key_util = OwnerKeyUtil::Create();
- scoped_refptr<base::TaskRunner> task_runner =
- content::BrowserThread::GetBlockingPool()
- ->GetTaskRunnerWithShutdownBehavior(
- base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
- base::PostTaskAndReplyWithResult(
- task_runner.get(),
+ CHECK(chromeos::LoginState::Get()->IsInSafeMode());
+
+ // Make sure NSS is initialized and NSS DB is loaded for the user before
+ // searching for the owner key.
+ BrowserThread::PostTaskAndReply(
+ BrowserThread::IO,
FROM_HERE,
- base::Bind(&IsPrivateKeyExistAsyncHelper, owner_key_util),
- callback);
+ base::Bind(base::IgnoreResult(&crypto::InitializeNSSForChromeOSUser),
+ user_id,
+ user_hash,
+ ProfileHelper::GetProfilePathByUserIdHash(user_hash)),
+ base::Bind(&DoesPrivateKeyExistAsync, callback));
}
// static
diff --git a/chrome/browser/chromeos/ownership/owner_settings_service.h b/chrome/browser/chromeos/ownership/owner_settings_service.h
index 23f64dd..b6b507b0 100644
--- a/chrome/browser/chromeos/ownership/owner_settings_service.h
+++ b/chrome/browser/chromeos/ownership/owner_settings_service.h
@@ -52,9 +52,11 @@ class OwnerSettingsService : public DeviceSettingsService::PrivateKeyDelegate,
// TPMTokenLoader::Observer:
virtual void OnTPMTokenReady() OVERRIDE;
- // Checks whether NSS slots with private key are mounted or
- // not. Responds via |callback|.
- static void IsPrivateKeyExistAsync(const IsOwnerCallback& callback);
+ // Checks if the user is the device owner, without the user profile having to
+ // been initialized. Should be used only if login state is in safe mode.
+ static void IsOwnerForSafeModeAsync(const std::string& user_id,
+ const std::string& user_hash,
+ const IsOwnerCallback& callback);
static void SetOwnerKeyUtilForTesting(
const scoped_refptr<OwnerKeyUtil>& owner_key_util);
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
index 1682942..dcf3bcf 100644
--- a/chrome/browser/profiles/profile_io_data.cc
+++ b/chrome/browser/profiles/profile_io_data.cc
@@ -288,20 +288,21 @@ void StartTPMSlotInitializationOnIOThread(const std::string& username,
void StartNSSInitOnIOThread(const std::string& username,
const std::string& username_hash,
- const base::FilePath& path,
- bool is_primary_user) {
+ const base::FilePath& path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DVLOG(1) << "Starting NSS init for " << username
- << " hash:" << username_hash
- << " is_primary_user:" << is_primary_user;
-
- if (!crypto::InitializeNSSForChromeOSUser(
- username, username_hash, is_primary_user, path)) {
- // If the user already exists in nss_util's map, it is already initialized
- // or in the process of being initialized. In either case, there's no need
- // to do anything.
+ << " hash:" << username_hash;
+
+ // Make sure NSS is initialized for the user.
+ crypto::InitializeNSSForChromeOSUser(username, username_hash, path);
+
+ // Check if it's OK to initialize TPM for the user before continuing. This
+ // may not be the case if the TPM slot initialization was previously
+ // requested for the same user.
+ if (!crypto::ShouldInitializeTPMForChromeOSUser(username_hash))
return;
- }
+
+ crypto::WillInitializeTPMForChromeOSUser(username_hash);
if (crypto::IsTPMTokenEnabledForNSS()) {
if (crypto::IsTPMTokenReady(base::Bind(
@@ -360,20 +361,22 @@ void ProfileIOData::InitializeOnUIThread(Profile* profile) {
if (user_manager) {
chromeos::User* user =
chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
- if (user) {
+ // No need to initialize NSS for users with empty username hash:
+ // Getters for a user's NSS slots always return NULL slot if the user's
+ // username hash is empty, even when the NSS is not initialized for the
+ // user.
+ if (user && !user->username_hash().empty()) {
params->username_hash = user->username_hash();
- bool is_primary_user = (user_manager->GetPrimaryUser() == user);
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(&StartNSSInitOnIOThread,
user->email(),
user->username_hash(),
- profile->GetPath(),
- is_primary_user));
+ profile->GetPath()));
}
}
if (params->username_hash.empty())
- LOG(WARNING) << "no username_hash";
+ LOG(WARNING) << "No username_hash; skipped NSS initialization.";
#endif
params->profile = profile;
diff --git a/chromeos/tpm_token_loader.cc b/chromeos/tpm_token_loader.cc
index 7f88581..3ea07fc 100644
--- a/chromeos/tpm_token_loader.cc
+++ b/chromeos/tpm_token_loader.cc
@@ -38,16 +38,6 @@ base::TimeDelta GetNextRequestDelayMs(base::TimeDelta last_delay) {
return next_delay;
}
-void CallOpenPersistentNSSDB() {
- // Called from crypto_task_runner_.
- VLOG(1) << "CallOpenPersistentNSSDB";
-
- // Ensure we've opened the user's key/certificate database.
- if (base::SysInfo::IsRunningOnChromeOS())
- crypto::OpenPersistentNSSDB();
- crypto::EnableTPMTokenForNSS();
-}
-
void PostResultToTaskRunner(scoped_refptr<base::SequencedTaskRunner> runner,
const base::Callback<void(bool)>& callback,
bool success) {
@@ -140,8 +130,7 @@ void TPMTokenLoader::MaybeStartTokenInitialization() {
if (!LoginState::IsInitialized())
return;
- bool start_initialization = LoginState::Get()->IsUserLoggedIn() ||
- LoginState::Get()->IsInSafeMode();
+ bool start_initialization = LoginState::Get()->IsUserLoggedIn();
VLOG(1) << "StartTokenInitialization: " << start_initialization;
if (!start_initialization)
@@ -167,8 +156,8 @@ void TPMTokenLoader::ContinueTokenInitialization() {
case TPM_STATE_UNKNOWN: {
crypto_task_runner_->PostTaskAndReply(
FROM_HERE,
- base::Bind(&CallOpenPersistentNSSDB),
- base::Bind(&TPMTokenLoader::OnPersistentNSSDBOpened,
+ base::Bind(&crypto::EnableTPMTokenForNSS),
+ base::Bind(&TPMTokenLoader::OnTPMTokenEnabledForNSS,
weak_factory_.GetWeakPtr()));
tpm_token_state_ = TPM_INITIALIZATION_STARTED;
return;
@@ -177,7 +166,7 @@ void TPMTokenLoader::ContinueTokenInitialization() {
NOTREACHED();
return;
}
- case TPM_DB_OPENED: {
+ case TPM_TOKEN_ENABLED_FOR_NSS: {
DBusThreadManager::Get()->GetCryptohomeClient()->TpmIsEnabled(
base::Bind(&TPMTokenLoader::OnTpmIsEnabled,
weak_factory_.GetWeakPtr()));
@@ -232,9 +221,9 @@ void TPMTokenLoader::RetryTokenInitializationLater() {
tpm_request_delay_ = GetNextRequestDelayMs(tpm_request_delay_);
}
-void TPMTokenLoader::OnPersistentNSSDBOpened() {
- VLOG(1) << "PersistentNSSDBOpened";
- tpm_token_state_ = TPM_DB_OPENED;
+void TPMTokenLoader::OnTPMTokenEnabledForNSS() {
+ VLOG(1) << "TPMTokenEnabledForNSS";
+ tpm_token_state_ = TPM_TOKEN_ENABLED_FOR_NSS;
ContinueTokenInitialization();
}
diff --git a/chromeos/tpm_token_loader.h b/chromeos/tpm_token_loader.h
index 9ac7a61..8089344 100644
--- a/chromeos/tpm_token_loader.h
+++ b/chromeos/tpm_token_loader.h
@@ -81,7 +81,7 @@ class CHROMEOS_EXPORT TPMTokenLoader : public LoginState::Observer {
// This is the cyclic chain of callbacks to initialize the TPM token.
void ContinueTokenInitialization();
- void OnPersistentNSSDBOpened();
+ void OnTPMTokenEnabledForNSS();
void OnTpmIsEnabled(DBusMethodCallStatus call_status,
bool tpm_is_enabled);
void OnPkcs11IsTpmTokenReady(DBusMethodCallStatus call_status,
@@ -111,7 +111,7 @@ class CHROMEOS_EXPORT TPMTokenLoader : public LoginState::Observer {
enum TPMTokenState {
TPM_STATE_UNKNOWN,
TPM_INITIALIZATION_STARTED,
- TPM_DB_OPENED,
+ TPM_TOKEN_ENABLED_FOR_NSS,
TPM_DISABLED,
TPM_ENABLED,
TPM_TOKEN_READY,
diff --git a/crypto/nss_util.cc b/crypto/nss_util.cc
index 5958ad9..1598ba9 100644
--- a/crypto/nss_util.cc
+++ b/crypto/nss_util.cc
@@ -81,6 +81,7 @@ std::string GetNSSErrorMessage() {
}
#if defined(USE_NSS)
+#if !defined(OS_CHROMEOS)
base::FilePath GetDefaultConfigDirectory() {
base::FilePath dir;
PathService::Get(base::DIR_HOME, &dir);
@@ -96,6 +97,7 @@ base::FilePath GetDefaultConfigDirectory() {
DVLOG(2) << "DefaultConfigDirectory: " << dir.value();
return dir;
}
+#endif // !defined(IS_CHROMEOS)
// On non-Chrome OS platforms, return the default config directory. On Chrome OS
// test images, return a read-only directory with fake root CA certs (which are
@@ -216,11 +218,11 @@ void CrashOnNSSInitFailure() {
#if defined(OS_CHROMEOS)
class ChromeOSUserData {
public:
- ChromeOSUserData(ScopedPK11Slot public_slot, bool is_primary_user)
+ explicit ChromeOSUserData(ScopedPK11Slot public_slot)
: public_slot_(public_slot.Pass()),
- is_primary_user_(is_primary_user) {}
+ private_slot_initialization_started_(false) {}
~ChromeOSUserData() {
- if (public_slot_ && !is_primary_user_) {
+ if (public_slot_) {
SECStatus status = SECMOD_CloseUserDB(public_slot_.get());
if (status != SECSuccess)
PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError();
@@ -254,10 +256,19 @@ class ChromeOSUserData {
}
}
+ bool private_slot_initialization_started() const {
+ return private_slot_initialization_started_;
+ }
+
+ void set_private_slot_initialization_started() {
+ private_slot_initialization_started_ = true;
+ }
+
private:
ScopedPK11Slot public_slot_;
ScopedPK11Slot private_slot_;
- bool is_primary_user_;
+
+ bool private_slot_initialization_started_;
typedef std::vector<base::Callback<void(ScopedPK11Slot)> >
SlotReadyCallbackList;
@@ -276,24 +287,6 @@ class NSSInitSingleton {
PK11SlotInfo* tpm_slot;
};
- void OpenPersistentNSSDB() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (!chromeos_user_logged_in_) {
- // GetDefaultConfigDirectory causes us to do blocking IO on UI thread.
- // Temporarily allow it until we fix http://crbug.com/70119
- base::ThreadRestrictions::ScopedAllowIO allow_io;
- chromeos_user_logged_in_ = true;
-
- // This creates another DB slot in NSS that is read/write, unlike
- // the fake root CA cert DB and the "default" crypto key
- // provider, which are still read-only (because we initialized
- // NSS before we had a cryptohome mounted).
- software_slot_ = OpenUserDB(GetDefaultConfigDirectory(),
- kNSSDatabaseName);
- }
- }
-
PK11SlotInfo* OpenPersistentNSSDBForPath(const base::FilePath& path) {
DCHECK(thread_checker_.CalledOnValidThread());
// NSS is allowed to do IO on the current thread since dispatching
@@ -459,7 +452,6 @@ class NSSInitSingleton {
bool InitializeNSSForChromeOSUser(
const std::string& email,
const std::string& username_hash,
- bool is_primary_user,
const base::FilePath& path) {
DCHECK(thread_checker_.CalledOnValidThread());
if (chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()) {
@@ -467,23 +459,42 @@ class NSSInitSingleton {
DVLOG(2) << username_hash << " already initialized.";
return false;
}
- ScopedPK11Slot public_slot;
- if (is_primary_user) {
- DVLOG(2) << "Primary user, using GetPublicNSSKeySlot()";
- public_slot.reset(GetPublicNSSKeySlot());
- } else {
- DVLOG(2) << "Opening NSS DB " << path.value();
- public_slot.reset(OpenPersistentNSSDBForPath(path));
- }
+
+ // If test slot is set, slot getter methods will short circuit
+ // checking |chromeos_user_map_|, so there is nothing left to be
+ // initialized.
+ if (test_slot_)
+ return false;
+
+ DVLOG(2) << "Opening NSS DB " << path.value();
+ ScopedPK11Slot public_slot(OpenPersistentNSSDBForPath(path));
chromeos_user_map_[username_hash] =
- new ChromeOSUserData(public_slot.Pass(), is_primary_user);
+ new ChromeOSUserData(public_slot.Pass());
return true;
}
+ bool ShouldInitializeTPMForChromeOSUser(const std::string& username_hash) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
+
+ return !chromeos_user_map_[username_hash]
+ ->private_slot_initialization_started();
+ }
+
+ void WillInitializeTPMForChromeOSUser(const std::string& username_hash) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
+
+ chromeos_user_map_[username_hash]
+ ->set_private_slot_initialization_started();
+ }
+
void InitializeTPMForChromeOSUser(const std::string& username_hash,
CK_SLOT_ID slot_id) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
+ DCHECK(chromeos_user_map_[username_hash]->
+ private_slot_initialization_started());
if (!chaps_module_)
return;
@@ -519,6 +530,9 @@ class NSSInitSingleton {
DCHECK(thread_checker_.CalledOnValidThread());
VLOG(1) << "using software private slot for " << username_hash;
DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
+ DCHECK(chromeos_user_map_[username_hash]->
+ private_slot_initialization_started());
+
chromeos_user_map_[username_hash]->SetPrivateSlot(
chromeos_user_map_[username_hash]->GetPublicSlot());
}
@@ -619,8 +633,6 @@ class NSSInitSingleton {
if (test_slot_)
return PK11_ReferenceSlot(test_slot_);
- if (software_slot_)
- return PK11_ReferenceSlot(software_slot_);
return PK11_GetInternalKeySlot();
}
@@ -645,10 +657,6 @@ class NSSInitSingleton {
}
}
#endif
- // If we weren't supposed to enable the TPM for NSS, then return
- // the software slot.
- if (software_slot_)
- return PK11_ReferenceSlot(software_slot_);
return PK11_GetInternalKeySlot();
}
@@ -671,11 +679,9 @@ class NSSInitSingleton {
: tpm_token_enabled_for_nss_(false),
initializing_tpm_token_(false),
chaps_module_(NULL),
- software_slot_(NULL),
test_slot_(NULL),
tpm_slot_(NULL),
- root_(NULL),
- chromeos_user_logged_in_(false) {
+ root_(NULL) {
base::TimeTicks start_time = base::TimeTicks::Now();
// It's safe to construct on any thread, since LazyInstance will prevent any
@@ -795,11 +801,6 @@ class NSSInitSingleton {
PK11_FreeSlot(tpm_slot_);
tpm_slot_ = NULL;
}
- if (software_slot_) {
- SECMOD_CloseUserDB(software_slot_);
- PK11_FreeSlot(software_slot_);
- software_slot_ = NULL;
- }
CloseTestNSSDB();
if (root_) {
SECMOD_UnloadUserModule(root_);
@@ -902,11 +903,9 @@ class NSSInitSingleton {
typedef std::vector<base::Closure> TPMReadyCallbackList;
TPMReadyCallbackList tpm_ready_callback_list_;
SECMODModule* chaps_module_;
- PK11SlotInfo* software_slot_;
PK11SlotInfo* test_slot_;
PK11SlotInfo* tpm_slot_;
SECMODModule* root_;
- bool chromeos_user_logged_in_;
#if defined(OS_CHROMEOS)
typedef std::map<std::string, ChromeOSUserData*> ChromeOSUserMap;
ChromeOSUserMap chromeos_user_map_;
@@ -1070,10 +1069,6 @@ AutoSECMODListReadLock::~AutoSECMODListReadLock() {
#endif // defined(USE_NSS)
#if defined(OS_CHROMEOS)
-void OpenPersistentNSSDB() {
- g_nss_singleton.Get().OpenPersistentNSSDB();
-}
-
void EnableTPMTokenForNSS() {
g_nss_singleton.Get().EnableTPMTokenForNSS();
}
@@ -1099,7 +1094,6 @@ ScopedTestNSSChromeOSUser::ScopedTestNSSChromeOSUser(
constructed_successfully_ =
InitializeNSSForChromeOSUser(username_hash,
username_hash,
- false /* is_primary_user */,
temp_dir_.path());
}
@@ -1109,17 +1103,30 @@ ScopedTestNSSChromeOSUser::~ScopedTestNSSChromeOSUser() {
}
void ScopedTestNSSChromeOSUser::FinishInit() {
+ DCHECK(constructed_successfully_);
+ if (!ShouldInitializeTPMForChromeOSUser(username_hash_))
+ return;
+ WillInitializeTPMForChromeOSUser(username_hash_);
InitializePrivateSoftwareSlotForChromeOSUser(username_hash_);
}
bool InitializeNSSForChromeOSUser(
const std::string& email,
const std::string& username_hash,
- bool is_primary_user,
const base::FilePath& path) {
return g_nss_singleton.Get().InitializeNSSForChromeOSUser(
- email, username_hash, is_primary_user, path);
+ email, username_hash, path);
}
+
+bool ShouldInitializeTPMForChromeOSUser(const std::string& username_hash) {
+ return g_nss_singleton.Get().ShouldInitializeTPMForChromeOSUser(
+ username_hash);
+}
+
+void WillInitializeTPMForChromeOSUser(const std::string& username_hash) {
+ g_nss_singleton.Get().WillInitializeTPMForChromeOSUser(username_hash);
+}
+
void InitializeTPMForChromeOSUser(
const std::string& username_hash,
CK_SLOT_ID slot_id) {
diff --git a/crypto/nss_util.h b/crypto/nss_util.h
index e94c4f6..4f8a1d6 100644
--- a/crypto/nss_util.h
+++ b/crypto/nss_util.h
@@ -95,11 +95,6 @@ CRYPTO_EXPORT void LoadNSSLibraries();
bool CheckNSSVersion(const char* version);
#if defined(OS_CHROMEOS)
-// Open the r/w nssdb that's stored inside the user's encrypted home
-// directory. This is the default slot returned by
-// GetPublicNSSKeySlot().
-CRYPTO_EXPORT void OpenPersistentNSSDB();
-
// Indicates that NSS should load the Chaps library so that we
// can access the TPM through NSS. Once this is called,
// GetPrivateNSSKeySlot() will return the TPM slot if one was found.
diff --git a/crypto/nss_util_internal.h b/crypto/nss_util_internal.h
index 262a59a..8175604 100644
--- a/crypto/nss_util_internal.h
+++ b/crypto/nss_util_internal.h
@@ -51,8 +51,20 @@ class CRYPTO_EXPORT AutoSECMODListReadLock {
CRYPTO_EXPORT bool InitializeNSSForChromeOSUser(
const std::string& email,
const std::string& username_hash,
- bool is_primary_user,
- const base::FilePath& path) WARN_UNUSED_RESULT;
+ const base::FilePath& path);
+
+// Returns whether TPM for ChromeOS user still needs initialization. If
+// true is returned, the caller can proceed to initialize TPM slot for the
+// user, but should call |WillInitializeTPMForChromeOSUser| first.
+// |InitializeNSSForChromeOSUser| must have been called first.
+CRYPTO_EXPORT bool ShouldInitializeTPMForChromeOSUser(
+ const std::string& username_hash) WARN_UNUSED_RESULT;
+
+// Makes |ShouldInitializeTPMForChromeOSUser| start returning false.
+// Should be called before starting TPM initialization for the user.
+// Assumes |InitializeNSSForChromeOSUser| had already been called.
+CRYPTO_EXPORT void WillInitializeTPMForChromeOSUser(
+ const std::string& username_hash);
// Use TPM slot |slot_id| for user. InitializeNSSForChromeOSUser must have been
// called first.
diff --git a/crypto/rsa_private_key_nss_unittest.cc b/crypto/rsa_private_key_nss_unittest.cc
index 66d352a..f376f15 100644
--- a/crypto/rsa_private_key_nss_unittest.cc
+++ b/crypto/rsa_private_key_nss_unittest.cc
@@ -18,12 +18,6 @@ class RSAPrivateKeyNSSTest : public testing::Test {
RSAPrivateKeyNSSTest() {}
virtual ~RSAPrivateKeyNSSTest() {}
- virtual void SetUp() {
-#if defined(OS_CHROMEOS)
- OpenPersistentNSSDB();
-#endif
- }
-
private:
ScopedTestNSSDB test_nssdb_;
diff --git a/net/base/keygen_handler_unittest.cc b/net/base/keygen_handler_unittest.cc
index 85c3844..a868b29 100644
--- a/net/base/keygen_handler_unittest.cc
+++ b/net/base/keygen_handler_unittest.cc
@@ -30,11 +30,10 @@ class KeygenHandlerTest : public ::testing::Test {
KeygenHandlerTest() {}
virtual ~KeygenHandlerTest() {}
- virtual void SetUp() {
+ private:
#if defined(OS_CHROMEOS) && defined(USE_NSS)
- crypto::OpenPersistentNSSDB();
+ crypto::ScopedTestNSSDB test_nss_db_;
#endif
- }
};
// Assert that |result| is a valid output for KeygenHandler given challenge