Commit 15d43aa6 authored by Leo Lai's avatar Leo Lai Committed by Chromium LUCI CQ

UserSessionManager use TpmmanagerClient to prepare TPM device.

We are replacing tpm status APis by cryptohome with tpm manager service.

Though the change to the workflow is implemented UserSessionManager is
supposed to operate almost the same way, before and after this CL.
Below the behavioral changes are highlighted:

1. TpmIsBeingOwned is removed as a factor from the state machine.
TpmIsBeingOwned is no longer supported and always returns `false` now.
Removing it is a trivial change.
2. As for execution order, `PrepareFinalizeProfile()` is separated
totally from the preparation of TPM device. The justification comes from
the fact that `CryptohomeClient::CanAttemptOwnership()` only triggers
TPM initialization by tpm manager w/o waiting for it to complete; it
doesn't make sense to just wait for a trigger w/o checking its result.
Clearing owner password is in best effort and the result is not checked
even in cases where any remaining owner password dependencies stops the
password from being cleared.
3. TPM status checking is made asynchronous after this CL to make sure
UI thread doesn't get blocked.
4. Upon failure of calling tpm_manager, `DCHECK` is replaced by logging
error message. It doesn't make sense to just crash upon the error, and
in production it doesn't make any difference anyway.

BUG=b:172748724
BUG=b:172775884
TEST=unit_tests (filter: *UserSessionManager*)
TEST=browser_tests (filter: *ExistingUserController*)
TEST=asan + msan builder trybot passes.
TEST= perform first login, check if the password exists/gets wiped
before/after the login.

Change-Id: I66c5ef3faae8c78d9f2cb304ccf59ca7a8f80c01
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2560087
Commit-Queue: Leo Lai <cylai@google.com>
Reviewed-by: default avatarAchuith Bhandarkar <achuith@chromium.org>
Cr-Commit-Position: refs/heads/master@{#836026}
parent 5fa11e54
...@@ -115,12 +115,15 @@ ...@@ -115,12 +115,15 @@
#include "chromeos/dbus/cryptohome/tpm_util.h" #include "chromeos/dbus/cryptohome/tpm_util.h"
#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/session_manager/session_manager_client.h" #include "chromeos/dbus/session_manager/session_manager_client.h"
#include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
#include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
#include "chromeos/login/auth/challenge_response/known_user_pref_utils.h" #include "chromeos/login/auth/challenge_response/known_user_pref_utils.h"
#include "chromeos/login/auth/stub_authenticator_builder.h" #include "chromeos/login/auth/stub_authenticator_builder.h"
#include "chromeos/login/session/session_termination_manager.h" #include "chromeos/login/session/session_termination_manager.h"
#include "chromeos/network/portal_detector/network_portal_detector.h" #include "chromeos/network/portal_detector/network_portal_detector.h"
#include "chromeos/network/portal_detector/network_portal_detector_strategy.h" #include "chromeos/network/portal_detector/network_portal_detector_strategy.h"
#include "chromeos/settings/cros_settings_names.h" #include "chromeos/settings/cros_settings_names.h"
#include "chromeos/tpm/prepare_tpm.h"
#include "chromeos/ui/vector_icons/vector_icons.h" #include "chromeos/ui/vector_icons/vector_icons.h"
#include "components/account_id/account_id.h" #include "components/account_id/account_id.h"
#include "components/account_manager_core/account.h" #include "components/account_manager_core/account.h"
...@@ -384,6 +387,10 @@ policy::MinimumVersionPolicyHandler* GetMinimumVersionPolicyHandler() { ...@@ -384,6 +387,10 @@ policy::MinimumVersionPolicyHandler* GetMinimumVersionPolicyHandler() {
->GetMinimumVersionPolicyHandler(); ->GetMinimumVersionPolicyHandler();
} }
void OnPrepareTpmDeviceFinished() {
BootTimesRecorder::Get()->AddLoginTimeMarker("TPMOwn-End", false);
}
} // namespace } // namespace
UserSessionManagerDelegate::~UserSessionManagerDelegate() {} UserSessionManagerDelegate::~UserSessionManagerDelegate() {}
...@@ -1518,51 +1525,20 @@ void UserSessionManager::UserProfileInitialized(Profile* profile, ...@@ -1518,51 +1525,20 @@ void UserSessionManager::UserProfileInitialized(Profile* profile,
return; return;
} }
PrepareTpmDeviceAndFinalizeProfile(profile); BootTimesRecorder::Get()->AddLoginTimeMarker("TPMOwn-Start", false);
PrepareTpm(base::BindOnce(OnPrepareTpmDeviceFinished));
FinalizePrepareProfile(profile);
} }
void UserSessionManager::CompleteProfileCreateAfterAuthTransfer( void UserSessionManager::CompleteProfileCreateAfterAuthTransfer(
Profile* profile) { Profile* profile) {
RestoreAuthSessionImpl(profile, has_auth_cookies_); RestoreAuthSessionImpl(profile, has_auth_cookies_);
PrepareTpmDeviceAndFinalizeProfile(profile);
}
void UserSessionManager::PrepareTpmDeviceAndFinalizeProfile(Profile* profile) {
BootTimesRecorder::Get()->AddLoginTimeMarker("TPMOwn-Start", false); BootTimesRecorder::Get()->AddLoginTimeMarker("TPMOwn-Start", false);
PrepareTpm(base::BindOnce(OnPrepareTpmDeviceFinished));
if (!tpm_util::TpmIsEnabled() || tpm_util::TpmIsBeingOwned()) {
FinalizePrepareProfile(profile);
return;
}
// Make sure TPM ownership gets established and the owner password cleared
// (if no longer needed) whenever a user logs in. This is so the TPM is in
// locked down state after initial setup, which ensures that some decisions
// (e.g. NVRAM spaces) are unchangeable until next hardware reset (powerwash,
// recovery, etc.).
//
// Ownership is normally taken when showing the EULA screen, but in case
// this gets interrupted TPM ownership might not be established yet. The code
// here runs on every login and ensures that the TPM gets into the desired
// state eventually.
auto callback =
base::BindOnce(&UserSessionManager::OnCryptohomeOperationCompleted,
AsWeakPtr(), profile);
CryptohomeClient* client = CryptohomeClient::Get();
if (tpm_util::TpmIsOwned())
client->TpmClearStoredPassword(std::move(callback));
else
client->TpmCanAttemptOwnership(std::move(callback));
}
void UserSessionManager::OnCryptohomeOperationCompleted(Profile* profile,
bool result) {
DCHECK(result);
FinalizePrepareProfile(profile); FinalizePrepareProfile(profile);
} }
void UserSessionManager::FinalizePrepareProfile(Profile* profile) { void UserSessionManager::FinalizePrepareProfile(Profile* profile) {
BootTimesRecorder::Get()->AddLoginTimeMarker("TPMOwn-End", false);
user_manager::UserManager* user_manager = user_manager::UserManager::Get(); user_manager::UserManager* user_manager = user_manager::UserManager::Get();
if (user_manager->IsLoggedInAsUserWithGaiaAccount()) { if (user_manager->IsLoggedInAsUserWithGaiaAccount()) {
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/u2f_notification.h" #include "chrome/browser/chromeos/u2f_notification.h"
#include "chromeos/dbus/session_manager/session_manager_client.h" #include "chromeos/dbus/session_manager/session_manager_client.h"
#include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
#include "chromeos/login/auth/authenticator.h" #include "chromeos/login/auth/authenticator.h"
#include "chromeos/login/auth/user_context.h" #include "chromeos/login/auth/user_context.h"
#include "components/arc/net/always_on_vpn_manager.h" #include "components/arc/net/always_on_vpn_manager.h"
...@@ -419,13 +420,6 @@ class UserSessionManager ...@@ -419,13 +420,6 @@ class UserSessionManager
// the authentication profile. // the authentication profile.
void CompleteProfileCreateAfterAuthTransfer(Profile* profile); void CompleteProfileCreateAfterAuthTransfer(Profile* profile);
// Asynchronously prepares TPM devices and calls FinalizePrepareProfile on UI
// thread.
void PrepareTpmDeviceAndFinalizeProfile(Profile* profile);
// Called on UI thread once Cryptohome operation completes.
void OnCryptohomeOperationCompleted(Profile* profile, bool result);
// Finalized profile preparation. // Finalized profile preparation.
void FinalizePrepareProfile(Profile* profile); void FinalizePrepareProfile(Profile* profile);
......
...@@ -62,7 +62,8 @@ void FakeTpmManagerClient::GetDictionaryAttackInfo( ...@@ -62,7 +62,8 @@ void FakeTpmManagerClient::GetDictionaryAttackInfo(
void FakeTpmManagerClient::TakeOwnership( void FakeTpmManagerClient::TakeOwnership(
const ::tpm_manager::TakeOwnershipRequest& request, const ::tpm_manager::TakeOwnershipRequest& request,
TakeOwnershipCallback callback) { TakeOwnershipCallback callback) {
NOTIMPLEMENTED(); ++take_ownership_count_;
PostProtoResponse(std::move(callback), ::tpm_manager::TakeOwnershipReply());
} }
void FakeTpmManagerClient::ClearStoredOwnerPassword( void FakeTpmManagerClient::ClearStoredOwnerPassword(
...@@ -105,6 +106,10 @@ FakeTpmManagerClient::mutable_dictionary_attack_info_reply() { ...@@ -105,6 +106,10 @@ FakeTpmManagerClient::mutable_dictionary_attack_info_reply() {
return &dictionary_attack_info_reply_; return &dictionary_attack_info_reply_;
} }
int FakeTpmManagerClient::take_ownership_count() const {
return take_ownership_count_;
}
int FakeTpmManagerClient::clear_stored_owner_password_count() const { int FakeTpmManagerClient::clear_stored_owner_password_count() const {
return clear_stored_owner_password_count_; return clear_stored_owner_password_count_;
} }
......
...@@ -52,6 +52,7 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_TPM_MANAGER) FakeTpmManagerClient ...@@ -52,6 +52,7 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_TPM_MANAGER) FakeTpmManagerClient
::tpm_manager::GetVersionInfoReply* mutable_version_info_reply() override; ::tpm_manager::GetVersionInfoReply* mutable_version_info_reply() override;
::tpm_manager::GetDictionaryAttackInfoReply* ::tpm_manager::GetDictionaryAttackInfoReply*
mutable_dictionary_attack_info_reply() override; mutable_dictionary_attack_info_reply() override;
int take_ownership_count() const override;
int clear_stored_owner_password_count() const override; int clear_stored_owner_password_count() const override;
void EmitOwnershipTakenSignal() override; void EmitOwnershipTakenSignal() override;
...@@ -60,6 +61,7 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_TPM_MANAGER) FakeTpmManagerClient ...@@ -60,6 +61,7 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_TPM_MANAGER) FakeTpmManagerClient
int nonsensitive_status_dbus_error_count_ = 0; int nonsensitive_status_dbus_error_count_ = 0;
::tpm_manager::GetVersionInfoReply version_info_reply_; ::tpm_manager::GetVersionInfoReply version_info_reply_;
::tpm_manager::GetDictionaryAttackInfoReply dictionary_attack_info_reply_; ::tpm_manager::GetDictionaryAttackInfoReply dictionary_attack_info_reply_;
int take_ownership_count_ = 0;
int clear_stored_owner_password_count_ = 0; int clear_stored_owner_password_count_ = 0;
// The observer list of ownership taken signal. // The observer list of ownership taken signal.
......
...@@ -60,6 +60,8 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_TPM_MANAGER) TpmManagerClient { ...@@ -60,6 +60,8 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_TPM_MANAGER) TpmManagerClient {
// called. // called.
virtual ::tpm_manager::GetDictionaryAttackInfoReply* virtual ::tpm_manager::GetDictionaryAttackInfoReply*
mutable_dictionary_attack_info_reply() = 0; mutable_dictionary_attack_info_reply() = 0;
// Gets the count of `TakeOwnership()` being called.
virtual int take_ownership_count() const = 0;
// Gets the count of `ClearStoredOwnerPassword()` being called. // Gets the count of `ClearStoredOwnerPassword()` being called.
virtual int clear_stored_owner_password_count() const = 0; virtual int clear_stored_owner_password_count() const = 0;
// Emits ownership taken signal. // Emits ownership taken signal.
......
...@@ -34,6 +34,8 @@ component("tpm") { ...@@ -34,6 +34,8 @@ component("tpm") {
sources = [ sources = [
"install_attributes.cc", "install_attributes.cc",
"install_attributes.h", "install_attributes.h",
"prepare_tpm.cc",
"prepare_tpm.h",
"tpm_token_info_getter.cc", "tpm_token_info_getter.cc",
"tpm_token_info_getter.h", "tpm_token_info_getter.h",
"tpm_token_loader.cc", "tpm_token_loader.cc",
...@@ -65,13 +67,15 @@ source_set("unit_tests") { ...@@ -65,13 +67,15 @@ source_set("unit_tests") {
"//chromeos/dbus/constants", "//chromeos/dbus/constants",
"//chromeos/dbus/cryptohome", "//chromeos/dbus/cryptohome",
"//chromeos/dbus/cryptohome:cryptohome_proto", "//chromeos/dbus/cryptohome:cryptohome_proto",
"//chromeos/dbus/tpm_manager:tpm_manager", "//chromeos/dbus/tpm_manager",
"//chromeos/dbus/tpm_manager:tpm_manager_proto",
"//components/policy/proto", "//components/policy/proto",
"//google_apis", "//google_apis",
"//testing/gtest", "//testing/gtest",
] ]
sources = [ sources = [
"install_attributes_unittest.cc", "install_attributes_unittest.cc",
"prepare_tpm_unittest.cc",
"tpm_token_info_getter_unittest.cc", "tpm_token_info_getter_unittest.cc",
] ]
} }
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/tpm/prepare_tpm.h"
#include <utility>
#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
#include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
#include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
namespace chromeos {
namespace {
void OnClearStoredOwnerPassword(
base::OnceClosure preparation_finished_callback,
const ::tpm_manager::ClearStoredOwnerPasswordReply& reply) {
LOG_IF(ERROR, reply.status() != ::tpm_manager::STATUS_SUCCESS)
<< "Failed to call ClearStoredOwnerPassword; status: " << reply.status();
std::move(preparation_finished_callback).Run();
}
void OnTakeOwnership(base::OnceClosure preparation_finished_callback,
const ::tpm_manager::TakeOwnershipReply& reply) {
LOG_IF(ERROR, reply.status() != ::tpm_manager::STATUS_SUCCESS)
<< "Failed to call TakeOwnership; status: " << reply.status();
std::move(preparation_finished_callback).Run();
}
void OnGetTpmStatus(base::OnceClosure preparation_finished_callback,
const ::tpm_manager::GetTpmNonsensitiveStatusReply& reply) {
if (reply.status() != ::tpm_manager::STATUS_SUCCESS) {
LOG(WARNING) << " Failed to get tpm status; status: " << reply.status();
}
if (reply.status() != ::tpm_manager::STATUS_SUCCESS || !reply.is_enabled()) {
LOG_IF(WARNING, !reply.is_enabled()) << "TPM is reportedly disabled.";
std::move(preparation_finished_callback).Run();
return;
}
if (reply.is_owned()) {
TpmManagerClient::Get()->ClearStoredOwnerPassword(
::tpm_manager::ClearStoredOwnerPasswordRequest(),
base::BindOnce(OnClearStoredOwnerPassword,
std::move(preparation_finished_callback)));
} else {
TpmManagerClient::Get()->TakeOwnership(
::tpm_manager::TakeOwnershipRequest(),
base::BindOnce(OnTakeOwnership,
std::move(preparation_finished_callback)));
}
}
} // namespace
void PrepareTpm(base::OnceClosure preparation_finished_callback) {
TpmManagerClient::Get()->GetTpmNonsensitiveStatus(
::tpm_manager::GetTpmNonsensitiveStatusRequest(),
base::BindOnce(OnGetTpmStatus, std::move(preparation_finished_callback)));
}
} // namespace chromeos
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_TPM_PREPARE_TPM_H_
#define CHROMEOS_TPM_PREPARE_TPM_H_
#include "base/callback.h"
#include "base/component_export.h"
namespace chromeos {
// Asynchronously prepares TPM. To be specific, attempts to clear owner
// password if TPM is owned to make sure the owner password is cleared if no
// longer needed; otherwise if TPM is not owned, which can happen due to
// interrupted TPM initialization triggered upon showing EULA screen, triggers
// TPM initialization process. When the preparation process is done, invoke
// `preparation_finished_callback`.
void COMPONENT_EXPORT(CHROMEOS_TPM)
PrepareTpm(base::OnceClosure preparation_finished_callback);
} // namespace chromeos
#endif // CHROMEOS_TPM_PREPARE_TPM_H_
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/tpm/prepare_tpm.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
#include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace {
class PrepareTpmTest : public ::testing::Test {
public:
PrepareTpmTest() { TpmManagerClient::InitializeFake(); }
~PrepareTpmTest() override { TpmManagerClient::Shutdown(); }
private:
base::test::SingleThreadTaskEnvironment task_environment;
};
} // namespace
// Tests if the password is getting cleared when TPM is owned.
TEST_F(PrepareTpmTest, PrepareTpmOwned) {
TpmManagerClient::Get()
->GetTestInterface()
->mutable_nonsensitive_status_reply()
->set_is_owned(true);
base::RunLoop run_loop;
auto on_finished = base::BindOnce(
[](base::RunLoop* run_loop) { run_loop->Quit(); }, &run_loop);
PrepareTpm(std::move(on_finished));
run_loop.Run();
EXPECT_EQ(TpmManagerClient::Get()
->GetTestInterface()
->clear_stored_owner_password_count(),
1);
}
// Tests if the ownership process is triggered if TPM is not owned yet.
TEST_F(PrepareTpmTest, PrepareTpmNotOwned) {
TpmManagerClient::Get()
->GetTestInterface()
->mutable_nonsensitive_status_reply()
->set_is_owned(false);
base::RunLoop run_loop;
auto on_finished = base::BindOnce(
[](base::RunLoop* run_loop) { run_loop->Quit(); }, &run_loop);
PrepareTpm(std::move(on_finished));
run_loop.Run();
EXPECT_EQ(TpmManagerClient::Get()->GetTestInterface()->take_ownership_count(),
1);
}
// Tests the program flow doesn't fall through and execute any unexpected
// follow-up action if tpm manager reports error.
TEST_F(PrepareTpmTest, PrepareTpmFailedToGetStatus) {
TpmManagerClient::Get()
->GetTestInterface()
->mutable_nonsensitive_status_reply()
->set_status(::tpm_manager::STATUS_DBUS_ERROR);
base::RunLoop run_loop;
auto on_finished = base::BindOnce(
[](base::RunLoop* run_loop) { run_loop->Quit(); }, &run_loop);
PrepareTpm(std::move(on_finished));
run_loop.Run();
EXPECT_EQ(TpmManagerClient::Get()
->GetTestInterface()
->clear_stored_owner_password_count(),
0);
EXPECT_EQ(TpmManagerClient::Get()->GetTestInterface()->take_ownership_count(),
0);
}
} // namespace chromeos
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