tpm_token_loader.cc 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/components/tpm/tpm_token_loader.h"
  5. #include <algorithm>
  6. #include "ash/components/tpm/tpm_token_info_getter.h"
  7. #include "base/bind.h"
  8. #include "base/location.h"
  9. #include "base/logging.h"
  10. #include "base/notreached.h"
  11. #include "base/system/sys_info.h"
  12. #include "base/task/sequenced_task_runner.h"
  13. #include "base/task/single_thread_task_runner.h"
  14. #include "base/task/task_runner_util.h"
  15. #include "base/threading/thread_task_runner_handle.h"
  16. #include "crypto/nss_util.h"
  17. namespace ash {
  18. namespace {
  19. void PostResultToTaskRunner(scoped_refptr<base::SequencedTaskRunner> runner,
  20. base::OnceCallback<void(bool)> callback,
  21. bool success) {
  22. runner->PostTask(FROM_HERE, base::BindOnce(std::move(callback), success));
  23. }
  24. } // namespace
  25. static TPMTokenLoader* g_tpm_token_loader = NULL;
  26. // static
  27. void TPMTokenLoader::Initialize() {
  28. CHECK(!g_tpm_token_loader);
  29. g_tpm_token_loader = new TPMTokenLoader(/*initialized_for_test=*/false);
  30. }
  31. // static
  32. void TPMTokenLoader::InitializeForTest() {
  33. CHECK(!g_tpm_token_loader);
  34. g_tpm_token_loader = new TPMTokenLoader(/*initialized_for_test=*/true);
  35. }
  36. // static
  37. void TPMTokenLoader::Shutdown() {
  38. CHECK(g_tpm_token_loader);
  39. delete g_tpm_token_loader;
  40. g_tpm_token_loader = NULL;
  41. }
  42. // static
  43. TPMTokenLoader* TPMTokenLoader::Get() {
  44. CHECK(g_tpm_token_loader)
  45. << "TPMTokenLoader::Get() called before Initialize()";
  46. return g_tpm_token_loader;
  47. }
  48. // static
  49. bool TPMTokenLoader::IsInitialized() {
  50. return g_tpm_token_loader;
  51. }
  52. TPMTokenLoader::TPMTokenLoader(bool initialized_for_test)
  53. : initialized_for_test_(initialized_for_test),
  54. tpm_token_state_(TPM_STATE_UNKNOWN),
  55. tpm_token_info_getter_(TPMTokenInfoGetter::CreateForSystemToken(
  56. CryptohomePkcs11Client::Get(),
  57. base::ThreadTaskRunnerHandle::Get())),
  58. tpm_token_slot_id_(-1),
  59. can_start_before_login_(false) {
  60. if (!initialized_for_test_ && LoginState::IsInitialized())
  61. LoginState::Get()->AddObserver(this);
  62. if (initialized_for_test_) {
  63. tpm_token_state_ = TPM_TOKEN_INITIALIZED;
  64. tpm_user_pin_ = "111111";
  65. }
  66. }
  67. void TPMTokenLoader::SetCryptoTaskRunner(
  68. const scoped_refptr<base::SequencedTaskRunner>& crypto_task_runner) {
  69. crypto_task_runner_ = crypto_task_runner;
  70. MaybeStartTokenInitialization();
  71. }
  72. void TPMTokenLoader::EnsureStarted() {
  73. if (can_start_before_login_)
  74. return;
  75. can_start_before_login_ = true;
  76. MaybeStartTokenInitialization();
  77. }
  78. TPMTokenLoader::~TPMTokenLoader() {
  79. if (!initialized_for_test_ && LoginState::IsInitialized())
  80. LoginState::Get()->RemoveObserver(this);
  81. }
  82. bool TPMTokenLoader::IsTPMLoadingEnabled() const {
  83. // TPM loading is enabled on non-ChromeOS environments, e.g. when running
  84. // tests on Linux.
  85. // Treat TPM as disabled for guest users since they do not store certs.
  86. return initialized_for_test_ || enable_tpm_loading_for_testing_ ||
  87. (base::SysInfo::IsRunningOnChromeOS() &&
  88. !LoginState::Get()->IsGuestSessionUser());
  89. }
  90. void TPMTokenLoader::MaybeStartTokenInitialization() {
  91. CHECK(thread_checker_.CalledOnValidThread());
  92. // This is the entry point to the TPM token initialization process,
  93. // which we should do at most once.
  94. if (tpm_token_state_ != TPM_STATE_UNKNOWN || !crypto_task_runner_.get())
  95. return;
  96. bool start_initialization =
  97. (LoginState::IsInitialized() && LoginState::Get()->IsUserLoggedIn()) ||
  98. can_start_before_login_;
  99. VLOG(1) << "StartTokenInitialization: " << start_initialization;
  100. if (!start_initialization)
  101. return;
  102. if (!IsTPMLoadingEnabled())
  103. tpm_token_state_ = TPM_DISABLED;
  104. ContinueTokenInitialization();
  105. DCHECK_NE(tpm_token_state_, TPM_STATE_UNKNOWN);
  106. }
  107. void TPMTokenLoader::ContinueTokenInitialization() {
  108. CHECK(thread_checker_.CalledOnValidThread());
  109. VLOG(1) << "ContinueTokenInitialization: " << tpm_token_state_;
  110. switch (tpm_token_state_) {
  111. case TPM_STATE_UNKNOWN: {
  112. tpm_token_state_ = TPM_INITIALIZATION_STARTED;
  113. tpm_token_info_getter_->Start(base::BindOnce(
  114. &TPMTokenLoader::OnGotTpmTokenInfo, weak_factory_.GetWeakPtr()));
  115. return;
  116. }
  117. case TPM_INITIALIZATION_STARTED: {
  118. NOTREACHED();
  119. return;
  120. }
  121. case TPM_TOKEN_INFO_RECEIVED: {
  122. crypto_task_runner_->PostTask(
  123. FROM_HERE,
  124. base::BindOnce(
  125. &crypto::InitializeTPMTokenAndSystemSlot, tpm_token_slot_id_,
  126. base::BindOnce(
  127. &PostResultToTaskRunner, base::ThreadTaskRunnerHandle::Get(),
  128. base::BindOnce(&TPMTokenLoader::OnTPMTokenInitialized,
  129. weak_factory_.GetWeakPtr()))));
  130. return;
  131. }
  132. case TPM_TOKEN_INITIALIZED:
  133. case TPM_DISABLED: {
  134. NotifyTPMTokenReady();
  135. return;
  136. }
  137. }
  138. }
  139. void TPMTokenLoader::OnGotTpmTokenInfo(
  140. absl::optional<user_data_auth::TpmTokenInfo> token_info) {
  141. if (!token_info.has_value()) {
  142. tpm_token_state_ = TPM_DISABLED;
  143. ContinueTokenInitialization();
  144. return;
  145. }
  146. tpm_token_slot_id_ = token_info->slot();
  147. tpm_user_pin_ = token_info->user_pin();
  148. tpm_token_state_ = TPM_TOKEN_INFO_RECEIVED;
  149. ContinueTokenInitialization();
  150. }
  151. void TPMTokenLoader::OnTPMTokenInitialized(bool success) {
  152. VLOG(1) << "OnTPMTokenInitialized: " << success;
  153. tpm_token_state_ = success ? TPM_TOKEN_INITIALIZED : TPM_DISABLED;
  154. ContinueTokenInitialization();
  155. }
  156. void TPMTokenLoader::NotifyTPMTokenReady() {
  157. crypto_task_runner_->PostTask(
  158. FROM_HERE,
  159. base::BindOnce(&crypto::FinishInitializingTPMTokenAndSystemSlot));
  160. }
  161. void TPMTokenLoader::LoggedInStateChanged() {
  162. VLOG(1) << "LoggedInStateChanged";
  163. MaybeStartTokenInitialization();
  164. }
  165. } // namespace ash