Commit 4071e6ac authored by tbarzic@chromium.org's avatar tbarzic@chromium.org

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
parent 1f48bda5
...@@ -508,14 +508,16 @@ bool ParallelAuthenticator::VerifyOwner() { ...@@ -508,14 +508,16 @@ bool ParallelAuthenticator::VerifyOwner() {
const std::string& user_id = current_state_->user_context.GetUserID(); const std::string& user_id = current_state_->user_context.GetUserID();
OwnerSettingsServiceFactory::GetInstance()->SetUsername(user_id); OwnerSettingsServiceFactory::GetInstance()->SetUsername(user_id);
// This should trigger certificate loading, which is needed in order to // |IsOwnerForSafeModeAsync| expects logged in state to be
// correctly determine if the current user is the owner. // LOGGED_IN_SAFE_MODE.
if (LoginState::IsInitialized()) { if (LoginState::IsInitialized()) {
LoginState::Get()->SetLoggedInState(LoginState::LOGGED_IN_SAFE_MODE, LoginState::Get()->SetLoggedInState(LoginState::LOGGED_IN_SAFE_MODE,
LoginState::LOGGED_IN_USER_NONE); LoginState::LOGGED_IN_USER_NONE);
} }
OwnerSettingsService::IsPrivateKeyExistAsync( OwnerSettingsService::IsOwnerForSafeModeAsync(
user_id,
current_state_->user_context.GetUserIDHash(),
base::Bind(&ParallelAuthenticator::OnOwnershipChecked, this)); base::Bind(&ParallelAuthenticator::OnOwnershipChecked, this));
return false; return false;
} }
......
...@@ -24,8 +24,11 @@ ...@@ -24,8 +24,11 @@
#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/device_settings_test_helper.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/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.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "chromeos/chromeos_switches.h" #include "chromeos/chromeos_switches.h"
#include "chromeos/cryptohome/mock_async_method_caller.h" #include "chromeos/cryptohome/mock_async_method_caller.h"
#include "chromeos/cryptohome/system_salt_getter.h" #include "chromeos/cryptohome/system_salt_getter.h"
...@@ -34,6 +37,7 @@ ...@@ -34,6 +37,7 @@
#include "chromeos/login/auth/key.h" #include "chromeos/login/auth/key.h"
#include "chromeos/login/auth/user_context.h" #include "chromeos/login/auth/user_context.h"
#include "content/public/test/test_browser_thread_bundle.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 "google_apis/gaia/mock_url_fetcher_factory.h"
#include "net/base/net_errors.h" #include "net/base/net_errors.h"
#include "net/url_request/url_request_status.h" #include "net/url_request/url_request_status.h"
...@@ -54,8 +58,10 @@ class ParallelAuthenticatorTest : public testing::Test { ...@@ -54,8 +58,10 @@ class ParallelAuthenticatorTest : public testing::Test {
: user_context_("me@nowhere.org"), : user_context_("me@nowhere.org"),
user_manager_(new FakeUserManager()), user_manager_(new FakeUserManager()),
user_manager_enabler_(user_manager_), user_manager_enabler_(user_manager_),
mock_caller_(NULL) { mock_caller_(NULL),
owner_key_util_(new MockOwnerKeyUtil) {
user_context_.SetKey(Key("fakepass")); user_context_.SetKey(Key("fakepass"));
user_context_.SetUserIDHash("me_nowhere_com_hash");
const User* user = user_manager_->AddUser(user_context_.GetUserID()); const User* user = user_manager_->AddUser(user_context_.GetUserID());
profile_.set_profile_name(user_context_.GetUserID()); profile_.set_profile_name(user_context_.GetUserID());
...@@ -67,9 +73,7 @@ class ParallelAuthenticatorTest : public testing::Test { ...@@ -67,9 +73,7 @@ class ParallelAuthenticatorTest : public testing::Test {
FakeCryptohomeClient::GetStubSystemSalt())); FakeCryptohomeClient::GetStubSystemSalt()));
} }
virtual ~ParallelAuthenticatorTest() { virtual ~ParallelAuthenticatorTest() {}
DCHECK(!mock_caller_);
}
virtual void SetUp() { virtual void SetUp() {
CommandLine::ForCurrentProcess()->AppendSwitch(switches::kLoginManager); CommandLine::ForCurrentProcess()->AppendSwitch(switches::kLoginManager);
...@@ -85,12 +89,15 @@ class ParallelAuthenticatorTest : public testing::Test { ...@@ -85,12 +89,15 @@ class ParallelAuthenticatorTest : public testing::Test {
SystemSaltGetter::Initialize(); SystemSaltGetter::Initialize();
OwnerSettingsService::SetOwnerKeyUtilForTesting(owner_key_util_);
auth_ = new ParallelAuthenticator(&consumer_); auth_ = new ParallelAuthenticator(&consumer_);
state_.reset(new TestAttemptState(user_context_, false)); state_.reset(new TestAttemptState(user_context_, false));
} }
// Tears down the test fixture. // Tears down the test fixture.
virtual void TearDown() { virtual void TearDown() {
OwnerSettingsService::SetOwnerKeyUtilForTesting(NULL);
SystemSaltGetter::Shutdown(); SystemSaltGetter::Shutdown();
DBusThreadManager::Shutdown(); DBusThreadManager::Shutdown();
...@@ -193,15 +200,20 @@ class ParallelAuthenticatorTest : public testing::Test { ...@@ -193,15 +200,20 @@ class ParallelAuthenticatorTest : public testing::Test {
ScopedTestCrosSettings test_cros_settings_; ScopedTestCrosSettings test_cros_settings_;
TestingProfile profile_; TestingProfile profile_;
scoped_ptr<TestingProfileManager> profile_manager_;
FakeUserManager* user_manager_; FakeUserManager* user_manager_;
ScopedUserManagerEnabler user_manager_enabler_; ScopedUserManagerEnabler user_manager_enabler_;
cryptohome::MockAsyncMethodCaller* mock_caller_; cryptohome::MockAsyncMethodCaller* mock_caller_;
crypto::ScopedTestNSSDB test_nssdb_;
MockConsumer consumer_; MockConsumer consumer_;
scoped_refptr<ParallelAuthenticator> auth_; scoped_refptr<ParallelAuthenticator> auth_;
scoped_ptr<TestAttemptState> state_; scoped_ptr<TestAttemptState> state_;
FakeCryptohomeClient* fake_cryptohome_client_; FakeCryptohomeClient* fake_cryptohome_client_;
scoped_refptr<MockOwnerKeyUtil> owner_key_util_;
}; };
TEST_F(ParallelAuthenticatorTest, OnLoginSuccess) { TEST_F(ParallelAuthenticatorTest, OnLoginSuccess) {
...@@ -276,6 +288,10 @@ TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededMount) { ...@@ -276,6 +288,10 @@ TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededMount) {
} }
TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededFailedMount) { TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededFailedMount) {
profile_manager_.reset(
new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
ASSERT_TRUE(profile_manager_->SetUp());
FailOnLoginSuccess(); // Set failing on success as the default... FailOnLoginSuccess(); // Set failing on success as the default...
LoginFailure failure = LoginFailure(LoginFailure::OWNER_REQUIRED); LoginFailure failure = LoginFailure(LoginFailure::OWNER_REQUIRED);
ExpectLoginFailure(failure); ExpectLoginFailure(failure);
...@@ -305,20 +321,18 @@ TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededFailedMount) { ...@@ -305,20 +321,18 @@ TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededFailedMount) {
SetAndResolveState(auth_.get(), state_.release())); SetAndResolveState(auth_.get(), state_.release()));
EXPECT_TRUE(LoginState::Get()->IsInSafeMode()); 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 // Flush all the pending operations. The operations should induce an owner
// verification. // verification.
device_settings_test_helper_.Flush(); device_settings_test_helper_.Flush();
// Test that the mount has succeeded.
state_.reset(new TestAttemptState(user_context_, false)); state_.reset(new TestAttemptState(user_context_, false));
state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); 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, EXPECT_EQ(ParallelAuthenticator::OWNER_REQUIRED,
SetAndResolveState(auth_.get(), state_.release())); SetAndResolveState(auth_.get(), state_.release()));
EXPECT_TRUE(LoginState::Get()->IsInSafeMode());
// Unset global objects used by this test. // Unset global objects used by this test.
LoginState::Shutdown(); LoginState::Shutdown();
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <string> #include <string>
#include "base/bind.h" #include "base/bind.h"
#include "base/bind_helpers.h"
#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/login/users/user.h" #include "chrome/browser/chromeos/login/users/user.h"
#include "chrome/browser/chromeos/login/users/user_manager.h" #include "chrome/browser/chromeos/login/users/user_manager.h"
...@@ -102,7 +103,7 @@ void LoadPrivateKey( ...@@ -102,7 +103,7 @@ void LoadPrivateKey(
} }
} }
bool IsPrivateKeyExistAsyncHelper( bool DoesPrivateKeyExistAsyncHelper(
const scoped_refptr<OwnerKeyUtil>& owner_key_util) { const scoped_refptr<OwnerKeyUtil>& owner_key_util) {
std::vector<uint8> public_key; std::vector<uint8> public_key;
if (!owner_key_util->ImportPublicKey(&public_key)) if (!owner_key_util->ImportPublicKey(&public_key))
...@@ -113,6 +114,26 @@ bool IsPrivateKeyExistAsyncHelper( ...@@ -113,6 +114,26 @@ bool IsPrivateKeyExistAsyncHelper(
return is_owner; 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 } // namespace
OwnerSettingsService::OwnerSettingsService(Profile* profile) OwnerSettingsService::OwnerSettingsService(Profile* profile)
...@@ -197,22 +218,22 @@ void OwnerSettingsService::OnTPMTokenReady() { ...@@ -197,22 +218,22 @@ void OwnerSettingsService::OnTPMTokenReady() {
} }
// static // static
void OwnerSettingsService::IsPrivateKeyExistAsync( void OwnerSettingsService::IsOwnerForSafeModeAsync(
const std::string& user_id,
const std::string& user_hash,
const IsOwnerCallback& callback) { const IsOwnerCallback& callback) {
scoped_refptr<OwnerKeyUtil> owner_key_util; CHECK(chromeos::LoginState::Get()->IsInSafeMode());
if (g_owner_key_util_for_testing)
owner_key_util = *g_owner_key_util_for_testing; // Make sure NSS is initialized and NSS DB is loaded for the user before
else // searching for the owner key.
owner_key_util = OwnerKeyUtil::Create(); BrowserThread::PostTaskAndReply(
scoped_refptr<base::TaskRunner> task_runner = BrowserThread::IO,
content::BrowserThread::GetBlockingPool()
->GetTaskRunnerWithShutdownBehavior(
base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
base::PostTaskAndReplyWithResult(
task_runner.get(),
FROM_HERE, FROM_HERE,
base::Bind(&IsPrivateKeyExistAsyncHelper, owner_key_util), base::Bind(base::IgnoreResult(&crypto::InitializeNSSForChromeOSUser),
callback); user_id,
user_hash,
ProfileHelper::GetProfilePathByUserIdHash(user_hash)),
base::Bind(&DoesPrivateKeyExistAsync, callback));
} }
// static // static
......
...@@ -52,9 +52,11 @@ class OwnerSettingsService : public DeviceSettingsService::PrivateKeyDelegate, ...@@ -52,9 +52,11 @@ class OwnerSettingsService : public DeviceSettingsService::PrivateKeyDelegate,
// TPMTokenLoader::Observer: // TPMTokenLoader::Observer:
virtual void OnTPMTokenReady() OVERRIDE; virtual void OnTPMTokenReady() OVERRIDE;
// Checks whether NSS slots with private key are mounted or // Checks if the user is the device owner, without the user profile having to
// not. Responds via |callback|. // been initialized. Should be used only if login state is in safe mode.
static void IsPrivateKeyExistAsync(const IsOwnerCallback& callback); static void IsOwnerForSafeModeAsync(const std::string& user_id,
const std::string& user_hash,
const IsOwnerCallback& callback);
static void SetOwnerKeyUtilForTesting( static void SetOwnerKeyUtilForTesting(
const scoped_refptr<OwnerKeyUtil>& owner_key_util); const scoped_refptr<OwnerKeyUtil>& owner_key_util);
......
...@@ -288,20 +288,21 @@ void StartTPMSlotInitializationOnIOThread(const std::string& username, ...@@ -288,20 +288,21 @@ void StartTPMSlotInitializationOnIOThread(const std::string& username,
void StartNSSInitOnIOThread(const std::string& username, void StartNSSInitOnIOThread(const std::string& username,
const std::string& username_hash, const std::string& username_hash,
const base::FilePath& path, const base::FilePath& path) {
bool is_primary_user) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DVLOG(1) << "Starting NSS init for " << username DVLOG(1) << "Starting NSS init for " << username
<< " hash:" << username_hash << " hash:" << username_hash;
<< " is_primary_user:" << is_primary_user;
// Make sure NSS is initialized for the user.
if (!crypto::InitializeNSSForChromeOSUser( crypto::InitializeNSSForChromeOSUser(username, username_hash, path);
username, username_hash, is_primary_user, path)) {
// If the user already exists in nss_util's map, it is already initialized // Check if it's OK to initialize TPM for the user before continuing. This
// or in the process of being initialized. In either case, there's no need // may not be the case if the TPM slot initialization was previously
// to do anything. // requested for the same user.
if (!crypto::ShouldInitializeTPMForChromeOSUser(username_hash))
return; return;
}
crypto::WillInitializeTPMForChromeOSUser(username_hash);
if (crypto::IsTPMTokenEnabledForNSS()) { if (crypto::IsTPMTokenEnabledForNSS()) {
if (crypto::IsTPMTokenReady(base::Bind( if (crypto::IsTPMTokenReady(base::Bind(
...@@ -360,20 +361,22 @@ void ProfileIOData::InitializeOnUIThread(Profile* profile) { ...@@ -360,20 +361,22 @@ void ProfileIOData::InitializeOnUIThread(Profile* profile) {
if (user_manager) { if (user_manager) {
chromeos::User* user = chromeos::User* user =
chromeos::ProfileHelper::Get()->GetUserByProfile(profile); 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(); params->username_hash = user->username_hash();
bool is_primary_user = (user_manager->GetPrimaryUser() == user);
BrowserThread::PostTask(BrowserThread::IO, BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE, FROM_HERE,
base::Bind(&StartNSSInitOnIOThread, base::Bind(&StartNSSInitOnIOThread,
user->email(), user->email(),
user->username_hash(), user->username_hash(),
profile->GetPath(), profile->GetPath()));
is_primary_user));
} }
} }
if (params->username_hash.empty()) if (params->username_hash.empty())
LOG(WARNING) << "no username_hash"; LOG(WARNING) << "No username_hash; skipped NSS initialization.";
#endif #endif
params->profile = profile; params->profile = profile;
......
...@@ -38,16 +38,6 @@ base::TimeDelta GetNextRequestDelayMs(base::TimeDelta last_delay) { ...@@ -38,16 +38,6 @@ base::TimeDelta GetNextRequestDelayMs(base::TimeDelta last_delay) {
return next_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, void PostResultToTaskRunner(scoped_refptr<base::SequencedTaskRunner> runner,
const base::Callback<void(bool)>& callback, const base::Callback<void(bool)>& callback,
bool success) { bool success) {
...@@ -140,8 +130,7 @@ void TPMTokenLoader::MaybeStartTokenInitialization() { ...@@ -140,8 +130,7 @@ void TPMTokenLoader::MaybeStartTokenInitialization() {
if (!LoginState::IsInitialized()) if (!LoginState::IsInitialized())
return; return;
bool start_initialization = LoginState::Get()->IsUserLoggedIn() || bool start_initialization = LoginState::Get()->IsUserLoggedIn();
LoginState::Get()->IsInSafeMode();
VLOG(1) << "StartTokenInitialization: " << start_initialization; VLOG(1) << "StartTokenInitialization: " << start_initialization;
if (!start_initialization) if (!start_initialization)
...@@ -167,8 +156,8 @@ void TPMTokenLoader::ContinueTokenInitialization() { ...@@ -167,8 +156,8 @@ void TPMTokenLoader::ContinueTokenInitialization() {
case TPM_STATE_UNKNOWN: { case TPM_STATE_UNKNOWN: {
crypto_task_runner_->PostTaskAndReply( crypto_task_runner_->PostTaskAndReply(
FROM_HERE, FROM_HERE,
base::Bind(&CallOpenPersistentNSSDB), base::Bind(&crypto::EnableTPMTokenForNSS),
base::Bind(&TPMTokenLoader::OnPersistentNSSDBOpened, base::Bind(&TPMTokenLoader::OnTPMTokenEnabledForNSS,
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr()));
tpm_token_state_ = TPM_INITIALIZATION_STARTED; tpm_token_state_ = TPM_INITIALIZATION_STARTED;
return; return;
...@@ -177,7 +166,7 @@ void TPMTokenLoader::ContinueTokenInitialization() { ...@@ -177,7 +166,7 @@ void TPMTokenLoader::ContinueTokenInitialization() {
NOTREACHED(); NOTREACHED();
return; return;
} }
case TPM_DB_OPENED: { case TPM_TOKEN_ENABLED_FOR_NSS: {
DBusThreadManager::Get()->GetCryptohomeClient()->TpmIsEnabled( DBusThreadManager::Get()->GetCryptohomeClient()->TpmIsEnabled(
base::Bind(&TPMTokenLoader::OnTpmIsEnabled, base::Bind(&TPMTokenLoader::OnTpmIsEnabled,
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr()));
...@@ -232,9 +221,9 @@ void TPMTokenLoader::RetryTokenInitializationLater() { ...@@ -232,9 +221,9 @@ void TPMTokenLoader::RetryTokenInitializationLater() {
tpm_request_delay_ = GetNextRequestDelayMs(tpm_request_delay_); tpm_request_delay_ = GetNextRequestDelayMs(tpm_request_delay_);
} }
void TPMTokenLoader::OnPersistentNSSDBOpened() { void TPMTokenLoader::OnTPMTokenEnabledForNSS() {
VLOG(1) << "PersistentNSSDBOpened"; VLOG(1) << "TPMTokenEnabledForNSS";
tpm_token_state_ = TPM_DB_OPENED; tpm_token_state_ = TPM_TOKEN_ENABLED_FOR_NSS;
ContinueTokenInitialization(); ContinueTokenInitialization();
} }
......
...@@ -81,7 +81,7 @@ class CHROMEOS_EXPORT TPMTokenLoader : public LoginState::Observer { ...@@ -81,7 +81,7 @@ class CHROMEOS_EXPORT TPMTokenLoader : public LoginState::Observer {
// This is the cyclic chain of callbacks to initialize the TPM token. // This is the cyclic chain of callbacks to initialize the TPM token.
void ContinueTokenInitialization(); void ContinueTokenInitialization();
void OnPersistentNSSDBOpened(); void OnTPMTokenEnabledForNSS();
void OnTpmIsEnabled(DBusMethodCallStatus call_status, void OnTpmIsEnabled(DBusMethodCallStatus call_status,
bool tpm_is_enabled); bool tpm_is_enabled);
void OnPkcs11IsTpmTokenReady(DBusMethodCallStatus call_status, void OnPkcs11IsTpmTokenReady(DBusMethodCallStatus call_status,
...@@ -111,7 +111,7 @@ class CHROMEOS_EXPORT TPMTokenLoader : public LoginState::Observer { ...@@ -111,7 +111,7 @@ class CHROMEOS_EXPORT TPMTokenLoader : public LoginState::Observer {
enum TPMTokenState { enum TPMTokenState {
TPM_STATE_UNKNOWN, TPM_STATE_UNKNOWN,
TPM_INITIALIZATION_STARTED, TPM_INITIALIZATION_STARTED,
TPM_DB_OPENED, TPM_TOKEN_ENABLED_FOR_NSS,
TPM_DISABLED, TPM_DISABLED,
TPM_ENABLED, TPM_ENABLED,
TPM_TOKEN_READY, TPM_TOKEN_READY,
......
...@@ -81,6 +81,7 @@ std::string GetNSSErrorMessage() { ...@@ -81,6 +81,7 @@ std::string GetNSSErrorMessage() {
} }
#if defined(USE_NSS) #if defined(USE_NSS)
#if !defined(OS_CHROMEOS)
base::FilePath GetDefaultConfigDirectory() { base::FilePath GetDefaultConfigDirectory() {
base::FilePath dir; base::FilePath dir;
PathService::Get(base::DIR_HOME, &dir); PathService::Get(base::DIR_HOME, &dir);
...@@ -96,6 +97,7 @@ base::FilePath GetDefaultConfigDirectory() { ...@@ -96,6 +97,7 @@ base::FilePath GetDefaultConfigDirectory() {
DVLOG(2) << "DefaultConfigDirectory: " << dir.value(); DVLOG(2) << "DefaultConfigDirectory: " << dir.value();
return dir; return dir;
} }
#endif // !defined(IS_CHROMEOS)
// On non-Chrome OS platforms, return the default config directory. On Chrome OS // 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 // test images, return a read-only directory with fake root CA certs (which are
...@@ -216,11 +218,11 @@ void CrashOnNSSInitFailure() { ...@@ -216,11 +218,11 @@ void CrashOnNSSInitFailure() {
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
class ChromeOSUserData { class ChromeOSUserData {
public: public:
ChromeOSUserData(ScopedPK11Slot public_slot, bool is_primary_user) explicit ChromeOSUserData(ScopedPK11Slot public_slot)
: public_slot_(public_slot.Pass()), : public_slot_(public_slot.Pass()),
is_primary_user_(is_primary_user) {} private_slot_initialization_started_(false) {}
~ChromeOSUserData() { ~ChromeOSUserData() {
if (public_slot_ && !is_primary_user_) { if (public_slot_) {
SECStatus status = SECMOD_CloseUserDB(public_slot_.get()); SECStatus status = SECMOD_CloseUserDB(public_slot_.get());
if (status != SECSuccess) if (status != SECSuccess)
PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError(); PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError();
...@@ -254,10 +256,19 @@ class ChromeOSUserData { ...@@ -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: private:
ScopedPK11Slot public_slot_; ScopedPK11Slot public_slot_;
ScopedPK11Slot private_slot_; ScopedPK11Slot private_slot_;
bool is_primary_user_;
bool private_slot_initialization_started_;
typedef std::vector<base::Callback<void(ScopedPK11Slot)> > typedef std::vector<base::Callback<void(ScopedPK11Slot)> >
SlotReadyCallbackList; SlotReadyCallbackList;
...@@ -276,24 +287,6 @@ class NSSInitSingleton { ...@@ -276,24 +287,6 @@ class NSSInitSingleton {
PK11SlotInfo* tpm_slot; 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) { PK11SlotInfo* OpenPersistentNSSDBForPath(const base::FilePath& path) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
// NSS is allowed to do IO on the current thread since dispatching // NSS is allowed to do IO on the current thread since dispatching
...@@ -459,7 +452,6 @@ class NSSInitSingleton { ...@@ -459,7 +452,6 @@ class NSSInitSingleton {
bool InitializeNSSForChromeOSUser( bool InitializeNSSForChromeOSUser(
const std::string& email, const std::string& email,
const std::string& username_hash, const std::string& username_hash,
bool is_primary_user,
const base::FilePath& path) { const base::FilePath& path) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
if (chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()) { if (chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()) {
...@@ -467,23 +459,42 @@ class NSSInitSingleton { ...@@ -467,23 +459,42 @@ class NSSInitSingleton {
DVLOG(2) << username_hash << " already initialized."; DVLOG(2) << username_hash << " already initialized.";
return false; return false;
} }
ScopedPK11Slot public_slot;
if (is_primary_user) { // If test slot is set, slot getter methods will short circuit
DVLOG(2) << "Primary user, using GetPublicNSSKeySlot()"; // checking |chromeos_user_map_|, so there is nothing left to be
public_slot.reset(GetPublicNSSKeySlot()); // initialized.
} else { if (test_slot_)
DVLOG(2) << "Opening NSS DB " << path.value(); return false;
public_slot.reset(OpenPersistentNSSDBForPath(path));
} DVLOG(2) << "Opening NSS DB " << path.value();
ScopedPK11Slot public_slot(OpenPersistentNSSDBForPath(path));
chromeos_user_map_[username_hash] = chromeos_user_map_[username_hash] =
new ChromeOSUserData(public_slot.Pass(), is_primary_user); new ChromeOSUserData(public_slot.Pass());
return true; 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, void InitializeTPMForChromeOSUser(const std::string& username_hash,
CK_SLOT_ID slot_id) { CK_SLOT_ID slot_id) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
DCHECK(chromeos_user_map_[username_hash]->
private_slot_initialization_started());
if (!chaps_module_) if (!chaps_module_)
return; return;
...@@ -519,6 +530,9 @@ class NSSInitSingleton { ...@@ -519,6 +530,9 @@ class NSSInitSingleton {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
VLOG(1) << "using software private slot for " << username_hash; VLOG(1) << "using software private slot for " << username_hash;
DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); 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]->SetPrivateSlot(
chromeos_user_map_[username_hash]->GetPublicSlot()); chromeos_user_map_[username_hash]->GetPublicSlot());
} }
...@@ -619,8 +633,6 @@ class NSSInitSingleton { ...@@ -619,8 +633,6 @@ class NSSInitSingleton {
if (test_slot_) if (test_slot_)
return PK11_ReferenceSlot(test_slot_); return PK11_ReferenceSlot(test_slot_);
if (software_slot_)
return PK11_ReferenceSlot(software_slot_);
return PK11_GetInternalKeySlot(); return PK11_GetInternalKeySlot();
} }
...@@ -645,10 +657,6 @@ class NSSInitSingleton { ...@@ -645,10 +657,6 @@ class NSSInitSingleton {
} }
} }
#endif #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(); return PK11_GetInternalKeySlot();
} }
...@@ -671,11 +679,9 @@ class NSSInitSingleton { ...@@ -671,11 +679,9 @@ class NSSInitSingleton {
: tpm_token_enabled_for_nss_(false), : tpm_token_enabled_for_nss_(false),
initializing_tpm_token_(false), initializing_tpm_token_(false),
chaps_module_(NULL), chaps_module_(NULL),
software_slot_(NULL),
test_slot_(NULL), test_slot_(NULL),
tpm_slot_(NULL), tpm_slot_(NULL),
root_(NULL), root_(NULL) {
chromeos_user_logged_in_(false) {
base::TimeTicks start_time = base::TimeTicks::Now(); base::TimeTicks start_time = base::TimeTicks::Now();
// It's safe to construct on any thread, since LazyInstance will prevent any // It's safe to construct on any thread, since LazyInstance will prevent any
...@@ -795,11 +801,6 @@ class NSSInitSingleton { ...@@ -795,11 +801,6 @@ class NSSInitSingleton {
PK11_FreeSlot(tpm_slot_); PK11_FreeSlot(tpm_slot_);
tpm_slot_ = NULL; tpm_slot_ = NULL;
} }
if (software_slot_) {
SECMOD_CloseUserDB(software_slot_);
PK11_FreeSlot(software_slot_);
software_slot_ = NULL;
}
CloseTestNSSDB(); CloseTestNSSDB();
if (root_) { if (root_) {
SECMOD_UnloadUserModule(root_); SECMOD_UnloadUserModule(root_);
...@@ -902,11 +903,9 @@ class NSSInitSingleton { ...@@ -902,11 +903,9 @@ class NSSInitSingleton {
typedef std::vector<base::Closure> TPMReadyCallbackList; typedef std::vector<base::Closure> TPMReadyCallbackList;
TPMReadyCallbackList tpm_ready_callback_list_; TPMReadyCallbackList tpm_ready_callback_list_;
SECMODModule* chaps_module_; SECMODModule* chaps_module_;
PK11SlotInfo* software_slot_;
PK11SlotInfo* test_slot_; PK11SlotInfo* test_slot_;
PK11SlotInfo* tpm_slot_; PK11SlotInfo* tpm_slot_;
SECMODModule* root_; SECMODModule* root_;
bool chromeos_user_logged_in_;
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
typedef std::map<std::string, ChromeOSUserData*> ChromeOSUserMap; typedef std::map<std::string, ChromeOSUserData*> ChromeOSUserMap;
ChromeOSUserMap chromeos_user_map_; ChromeOSUserMap chromeos_user_map_;
...@@ -1070,10 +1069,6 @@ AutoSECMODListReadLock::~AutoSECMODListReadLock() { ...@@ -1070,10 +1069,6 @@ AutoSECMODListReadLock::~AutoSECMODListReadLock() {
#endif // defined(USE_NSS) #endif // defined(USE_NSS)
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
void OpenPersistentNSSDB() {
g_nss_singleton.Get().OpenPersistentNSSDB();
}
void EnableTPMTokenForNSS() { void EnableTPMTokenForNSS() {
g_nss_singleton.Get().EnableTPMTokenForNSS(); g_nss_singleton.Get().EnableTPMTokenForNSS();
} }
...@@ -1099,7 +1094,6 @@ ScopedTestNSSChromeOSUser::ScopedTestNSSChromeOSUser( ...@@ -1099,7 +1094,6 @@ ScopedTestNSSChromeOSUser::ScopedTestNSSChromeOSUser(
constructed_successfully_ = constructed_successfully_ =
InitializeNSSForChromeOSUser(username_hash, InitializeNSSForChromeOSUser(username_hash,
username_hash, username_hash,
false /* is_primary_user */,
temp_dir_.path()); temp_dir_.path());
} }
...@@ -1109,17 +1103,30 @@ ScopedTestNSSChromeOSUser::~ScopedTestNSSChromeOSUser() { ...@@ -1109,17 +1103,30 @@ ScopedTestNSSChromeOSUser::~ScopedTestNSSChromeOSUser() {
} }
void ScopedTestNSSChromeOSUser::FinishInit() { void ScopedTestNSSChromeOSUser::FinishInit() {
DCHECK(constructed_successfully_);
if (!ShouldInitializeTPMForChromeOSUser(username_hash_))
return;
WillInitializeTPMForChromeOSUser(username_hash_);
InitializePrivateSoftwareSlotForChromeOSUser(username_hash_); InitializePrivateSoftwareSlotForChromeOSUser(username_hash_);
} }
bool InitializeNSSForChromeOSUser( bool InitializeNSSForChromeOSUser(
const std::string& email, const std::string& email,
const std::string& username_hash, const std::string& username_hash,
bool is_primary_user,
const base::FilePath& path) { const base::FilePath& path) {
return g_nss_singleton.Get().InitializeNSSForChromeOSUser( 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( void InitializeTPMForChromeOSUser(
const std::string& username_hash, const std::string& username_hash,
CK_SLOT_ID slot_id) { CK_SLOT_ID slot_id) {
......
...@@ -95,11 +95,6 @@ CRYPTO_EXPORT void LoadNSSLibraries(); ...@@ -95,11 +95,6 @@ CRYPTO_EXPORT void LoadNSSLibraries();
bool CheckNSSVersion(const char* version); bool CheckNSSVersion(const char* version);
#if defined(OS_CHROMEOS) #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 // Indicates that NSS should load the Chaps library so that we
// can access the TPM through NSS. Once this is called, // can access the TPM through NSS. Once this is called,
// GetPrivateNSSKeySlot() will return the TPM slot if one was found. // GetPrivateNSSKeySlot() will return the TPM slot if one was found.
......
...@@ -51,8 +51,20 @@ class CRYPTO_EXPORT AutoSECMODListReadLock { ...@@ -51,8 +51,20 @@ class CRYPTO_EXPORT AutoSECMODListReadLock {
CRYPTO_EXPORT bool InitializeNSSForChromeOSUser( CRYPTO_EXPORT bool InitializeNSSForChromeOSUser(
const std::string& email, const std::string& email,
const std::string& username_hash, const std::string& username_hash,
bool is_primary_user, const base::FilePath& path);
const base::FilePath& path) WARN_UNUSED_RESULT;
// 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 // Use TPM slot |slot_id| for user. InitializeNSSForChromeOSUser must have been
// called first. // called first.
......
...@@ -18,12 +18,6 @@ class RSAPrivateKeyNSSTest : public testing::Test { ...@@ -18,12 +18,6 @@ class RSAPrivateKeyNSSTest : public testing::Test {
RSAPrivateKeyNSSTest() {} RSAPrivateKeyNSSTest() {}
virtual ~RSAPrivateKeyNSSTest() {} virtual ~RSAPrivateKeyNSSTest() {}
virtual void SetUp() {
#if defined(OS_CHROMEOS)
OpenPersistentNSSDB();
#endif
}
private: private:
ScopedTestNSSDB test_nssdb_; ScopedTestNSSDB test_nssdb_;
......
...@@ -30,11 +30,10 @@ class KeygenHandlerTest : public ::testing::Test { ...@@ -30,11 +30,10 @@ class KeygenHandlerTest : public ::testing::Test {
KeygenHandlerTest() {} KeygenHandlerTest() {}
virtual ~KeygenHandlerTest() {} virtual ~KeygenHandlerTest() {}
virtual void SetUp() { private:
#if defined(OS_CHROMEOS) && defined(USE_NSS) #if defined(OS_CHROMEOS) && defined(USE_NSS)
crypto::OpenPersistentNSSDB(); crypto::ScopedTestNSSDB test_nss_db_;
#endif #endif
}
}; };
// Assert that |result| is a valid output for KeygenHandler given challenge // Assert that |result| is a valid output for KeygenHandler given challenge
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment