diff options
author | tbarzic@chromium.org <tbarzic@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-12 12:46:17 +0000 |
---|---|---|
committer | tbarzic@chromium.org <tbarzic@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-12 12:46:17 +0000 |
commit | 4071e6ac6d212ca5cc90cef59ed9f4852cfed50c (patch) | |
tree | 405b9842525c655d478f55c689fd6c7a36aeceee | |
parent | 1f48bda5498e693e5de11b9c9bb5899f83fa1882 (diff) | |
download | chromium_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.cc | 8 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/auth/parallel_authenticator_unittest.cc | 36 | ||||
-rw-r--r-- | chrome/browser/chromeos/ownership/owner_settings_service.cc | 51 | ||||
-rw-r--r-- | chrome/browser/chromeos/ownership/owner_settings_service.h | 8 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_io_data.cc | 35 | ||||
-rw-r--r-- | chromeos/tpm_token_loader.cc | 25 | ||||
-rw-r--r-- | chromeos/tpm_token_loader.h | 4 | ||||
-rw-r--r-- | crypto/nss_util.cc | 117 | ||||
-rw-r--r-- | crypto/nss_util.h | 5 | ||||
-rw-r--r-- | crypto/nss_util_internal.h | 16 | ||||
-rw-r--r-- | crypto/rsa_private_key_nss_unittest.cc | 6 | ||||
-rw-r--r-- | net/base/keygen_handler_unittest.cc | 5 |
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 |