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
This commit is contained in:
chrome/browser
chromeos
login
ownership
profiles
chromeos
crypto
net/base
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
<< " hash:" << username_hash;
|
||||
|
||||
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.
|
||||
// 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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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_;
|
||||
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user