123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- // Copyright 2014 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 "ash/components/tpm/tpm_token_loader.h"
- #include <algorithm>
- #include "ash/components/tpm/tpm_token_info_getter.h"
- #include "base/bind.h"
- #include "base/location.h"
- #include "base/logging.h"
- #include "base/notreached.h"
- #include "base/system/sys_info.h"
- #include "base/task/sequenced_task_runner.h"
- #include "base/task/single_thread_task_runner.h"
- #include "base/task/task_runner_util.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "crypto/nss_util.h"
- namespace ash {
- namespace {
- void PostResultToTaskRunner(scoped_refptr<base::SequencedTaskRunner> runner,
- base::OnceCallback<void(bool)> callback,
- bool success) {
- runner->PostTask(FROM_HERE, base::BindOnce(std::move(callback), success));
- }
- } // namespace
- static TPMTokenLoader* g_tpm_token_loader = NULL;
- // static
- void TPMTokenLoader::Initialize() {
- CHECK(!g_tpm_token_loader);
- g_tpm_token_loader = new TPMTokenLoader(/*initialized_for_test=*/false);
- }
- // static
- void TPMTokenLoader::InitializeForTest() {
- CHECK(!g_tpm_token_loader);
- g_tpm_token_loader = new TPMTokenLoader(/*initialized_for_test=*/true);
- }
- // static
- void TPMTokenLoader::Shutdown() {
- CHECK(g_tpm_token_loader);
- delete g_tpm_token_loader;
- g_tpm_token_loader = NULL;
- }
- // static
- TPMTokenLoader* TPMTokenLoader::Get() {
- CHECK(g_tpm_token_loader)
- << "TPMTokenLoader::Get() called before Initialize()";
- return g_tpm_token_loader;
- }
- // static
- bool TPMTokenLoader::IsInitialized() {
- return g_tpm_token_loader;
- }
- TPMTokenLoader::TPMTokenLoader(bool initialized_for_test)
- : initialized_for_test_(initialized_for_test),
- tpm_token_state_(TPM_STATE_UNKNOWN),
- tpm_token_info_getter_(TPMTokenInfoGetter::CreateForSystemToken(
- CryptohomePkcs11Client::Get(),
- base::ThreadTaskRunnerHandle::Get())),
- tpm_token_slot_id_(-1),
- can_start_before_login_(false) {
- if (!initialized_for_test_ && LoginState::IsInitialized())
- LoginState::Get()->AddObserver(this);
- if (initialized_for_test_) {
- tpm_token_state_ = TPM_TOKEN_INITIALIZED;
- tpm_user_pin_ = "111111";
- }
- }
- void TPMTokenLoader::SetCryptoTaskRunner(
- const scoped_refptr<base::SequencedTaskRunner>& crypto_task_runner) {
- crypto_task_runner_ = crypto_task_runner;
- MaybeStartTokenInitialization();
- }
- void TPMTokenLoader::EnsureStarted() {
- if (can_start_before_login_)
- return;
- can_start_before_login_ = true;
- MaybeStartTokenInitialization();
- }
- TPMTokenLoader::~TPMTokenLoader() {
- if (!initialized_for_test_ && LoginState::IsInitialized())
- LoginState::Get()->RemoveObserver(this);
- }
- bool TPMTokenLoader::IsTPMLoadingEnabled() const {
- // TPM loading is enabled on non-ChromeOS environments, e.g. when running
- // tests on Linux.
- // Treat TPM as disabled for guest users since they do not store certs.
- return initialized_for_test_ || enable_tpm_loading_for_testing_ ||
- (base::SysInfo::IsRunningOnChromeOS() &&
- !LoginState::Get()->IsGuestSessionUser());
- }
- void TPMTokenLoader::MaybeStartTokenInitialization() {
- CHECK(thread_checker_.CalledOnValidThread());
- // This is the entry point to the TPM token initialization process,
- // which we should do at most once.
- if (tpm_token_state_ != TPM_STATE_UNKNOWN || !crypto_task_runner_.get())
- return;
- bool start_initialization =
- (LoginState::IsInitialized() && LoginState::Get()->IsUserLoggedIn()) ||
- can_start_before_login_;
- VLOG(1) << "StartTokenInitialization: " << start_initialization;
- if (!start_initialization)
- return;
- if (!IsTPMLoadingEnabled())
- tpm_token_state_ = TPM_DISABLED;
- ContinueTokenInitialization();
- DCHECK_NE(tpm_token_state_, TPM_STATE_UNKNOWN);
- }
- void TPMTokenLoader::ContinueTokenInitialization() {
- CHECK(thread_checker_.CalledOnValidThread());
- VLOG(1) << "ContinueTokenInitialization: " << tpm_token_state_;
- switch (tpm_token_state_) {
- case TPM_STATE_UNKNOWN: {
- tpm_token_state_ = TPM_INITIALIZATION_STARTED;
- tpm_token_info_getter_->Start(base::BindOnce(
- &TPMTokenLoader::OnGotTpmTokenInfo, weak_factory_.GetWeakPtr()));
- return;
- }
- case TPM_INITIALIZATION_STARTED: {
- NOTREACHED();
- return;
- }
- case TPM_TOKEN_INFO_RECEIVED: {
- crypto_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &crypto::InitializeTPMTokenAndSystemSlot, tpm_token_slot_id_,
- base::BindOnce(
- &PostResultToTaskRunner, base::ThreadTaskRunnerHandle::Get(),
- base::BindOnce(&TPMTokenLoader::OnTPMTokenInitialized,
- weak_factory_.GetWeakPtr()))));
- return;
- }
- case TPM_TOKEN_INITIALIZED:
- case TPM_DISABLED: {
- NotifyTPMTokenReady();
- return;
- }
- }
- }
- void TPMTokenLoader::OnGotTpmTokenInfo(
- absl::optional<user_data_auth::TpmTokenInfo> token_info) {
- if (!token_info.has_value()) {
- tpm_token_state_ = TPM_DISABLED;
- ContinueTokenInitialization();
- return;
- }
- tpm_token_slot_id_ = token_info->slot();
- tpm_user_pin_ = token_info->user_pin();
- tpm_token_state_ = TPM_TOKEN_INFO_RECEIVED;
- ContinueTokenInitialization();
- }
- void TPMTokenLoader::OnTPMTokenInitialized(bool success) {
- VLOG(1) << "OnTPMTokenInitialized: " << success;
- tpm_token_state_ = success ? TPM_TOKEN_INITIALIZED : TPM_DISABLED;
- ContinueTokenInitialization();
- }
- void TPMTokenLoader::NotifyTPMTokenReady() {
- crypto_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&crypto::FinishInitializingTPMTokenAndSystemSlot));
- }
- void TPMTokenLoader::LoggedInStateChanged() {
- VLOG(1) << "LoggedInStateChanged";
- MaybeStartTokenInitialization();
- }
- } // namespace ash
|