tpm_manager: add option to disable pre-initialization Before this change, tpm_managerd always performed pre-initialization if it found an unowned TPM upon start. That may not work for special workflows like factory initialization. This CL adds a check for a "no_preinit" flag file in /run/tpm_manager. If that file exists, pre-initialization is not done. Having this flag file in tpmfs allows for various control schemes, including disabling pre-initialization for specific boots only and copying this flag from stateful before starting tpm_managerd for disabling for all boots at image level. BUG=b:68671587 TEST=unit tests; check pre-init with and without the flag file Change-Id: I69991896cc79977694bd328de1e716a54de7ab96 Reviewed-on: https://chromium-review.googlesource.com/756207 Commit-Ready: Andrey Pronin <apronin@chromium.org> Tested-by: Andrey Pronin <apronin@chromium.org> Reviewed-by: Hung-Te Lin <hungte@chromium.org>
diff --git a/tpm_manager/server/main.cc b/tpm_manager/server/main.cc index 88a1bf0..5ededc3 100644 --- a/tpm_manager/server/main.cc +++ b/tpm_manager/server/main.cc
@@ -17,6 +17,8 @@ #include <string> #include <base/command_line.h> +#include <base/files/file_path.h> +#include <base/files/file_util.h> #include <brillo/syslog_logging.h> #if defined(USE_TPM2) #include <trunks/trunks_factory_impl.h> @@ -34,6 +36,7 @@ constexpr char kWaitForOwnershipTriggerSwitch[] = "wait_for_ownership_trigger"; constexpr char kLogToStderrSwitch[] = "log_to_stderr"; +constexpr char kNoPreinitFlagFile[] = "/run/tpm_manager/no_preinit"; } // namespace @@ -46,8 +49,10 @@ } brillo::InitLog(flags); + bool perform_preinit = !base::PathExists(base::FilePath(kNoPreinitFlagFile)); tpm_manager::TpmManagerService tpm_manager_service( - cl->HasSwitch(kWaitForOwnershipTriggerSwitch)); + cl->HasSwitch(kWaitForOwnershipTriggerSwitch), + perform_preinit); #if defined(USE_BINDER_IPC) tpm_manager::BinderService ipc_service(&tpm_manager_service, &tpm_manager_service);
diff --git a/tpm_manager/server/tpm_manager_service.cc b/tpm_manager/server/tpm_manager_service.cc index 8a93732..dc5ab03 100644 --- a/tpm_manager/server/tpm_manager_service.cc +++ b/tpm_manager/server/tpm_manager_service.cc
@@ -49,10 +49,13 @@ namespace tpm_manager { -TpmManagerService::TpmManagerService(bool wait_for_ownership) - : wait_for_ownership_(wait_for_ownership) {} +TpmManagerService::TpmManagerService(bool wait_for_ownership, + bool perform_preinit) + : wait_for_ownership_(wait_for_ownership), + perform_preinit_(perform_preinit) {} TpmManagerService::TpmManagerService(bool wait_for_ownership, + bool perform_preinit, LocalDataStore* local_data_store, TpmStatus* tpm_status, TpmInitializer* tpm_initializer, @@ -61,7 +64,8 @@ tpm_status_(tpm_status), tpm_initializer_(tpm_initializer), tpm_nvram_(tpm_nvram), - wait_for_ownership_(wait_for_ownership) {} + wait_for_ownership_(wait_for_ownership), + perform_preinit_(perform_preinit) {} bool TpmManagerService::Initialize() { worker_thread_.reset(new base::Thread("TpmManager Service Worker")); @@ -117,7 +121,7 @@ LOG(WARNING) << __func__ << ": TPM initialization failed."; return; } - } else { + } else if (perform_preinit_) { VLOG(1) << "Pre-initializing TPM."; tpm_initializer_->PreInitializeTpm(); }
diff --git a/tpm_manager/server/tpm_manager_service.h b/tpm_manager/server/tpm_manager_service.h index d20b6ea..2af5872 100644 --- a/tpm_manager/server/tpm_manager_service.h +++ b/tpm_manager/server/tpm_manager_service.h
@@ -69,13 +69,19 @@ public TpmOwnershipInterface { public: // If |wait_for_ownership| is set, TPM initialization will be postponed until - // an explicit TakeOwnership request is received. - explicit TpmManagerService(bool wait_for_ownership); + // an explicit TakeOwnership request is received. If |perform_preinit| is + // additionally set, TPM pre-initialization will be performed in case TPM + // initialization is postponed. + explicit TpmManagerService(bool wait_for_ownership, bool perform_preinit); // If |wait_for_ownership| is set, TPM initialization will be postponed until - // an explicit TakeOwnership request is received. Does not take ownership of - // |local_data_store|, |tpm_status|, |tpm_initializer|, or |tpm_nvram|. + // an explicit TakeOwnership request is received. If |perform_preinit| is + // additionally set, TPM pre-initialization will be performed in case TPM + // initialization is postponed. + // Does not take ownership of |local_data_store|, |tpm_status|, + // |tpm_initializer|, or |tpm_nvram|. TpmManagerService(bool wait_for_ownership, + bool perform_preinit, LocalDataStore* local_data_store, TpmStatus* tpm_status, TpmInitializer* tpm_initializer, @@ -232,6 +238,9 @@ // Whether to wait for an explicit call to 'TakeOwnership' before initializing // the TPM. Normally tracks the --wait_for_ownership command line option. bool wait_for_ownership_; + // Whether to perform pre-initialization (where available) if initialization + // itself needs to wait for 'TakeOwnership' first. + bool perform_preinit_; // Background thread to allow processing of potentially lengthy TPM requests // in the background. std::unique_ptr<base::Thread> worker_thread_;
diff --git a/tpm_manager/server/tpm_manager_service_test.cc b/tpm_manager/server/tpm_manager_service_test.cc index c04cb0f..abd00d2 100644 --- a/tpm_manager/server/tpm_manager_service_test.cc +++ b/tpm_manager/server/tpm_manager_service_test.cc
@@ -50,8 +50,9 @@ ~TpmManagerServiceTest() override = default; void SetUp() override { service_.reset(new TpmManagerService( - true /*wait_for_ownership*/, &mock_local_data_store_, &mock_tpm_status_, - &mock_tpm_initializer_, &mock_tpm_nvram_)); + true /*wait_for_ownership*/, true /*perform_preinit*/, + &mock_local_data_store_, &mock_tpm_status_, &mock_tpm_initializer_, + &mock_tpm_nvram_)); SetupService(); } @@ -88,8 +89,33 @@ ~TpmManagerServiceTest_NoWaitForOwnership() override = default; void SetUp() override { service_.reset(new TpmManagerService( - false /*wait_for_ownership*/, &mock_local_data_store_, - &mock_tpm_status_, &mock_tpm_initializer_, &mock_tpm_nvram_)); + false /*wait_for_ownership*/, false /*perform_preinit*/, + &mock_local_data_store_, &mock_tpm_status_, &mock_tpm_initializer_, + &mock_tpm_nvram_)); + } +}; + +// Tests must call SetupService(). +class TpmManagerServiceTest_NoPreinit : public TpmManagerServiceTest { + public: + ~TpmManagerServiceTest_NoPreinit() override = default; + void SetUp() override { + service_.reset(new TpmManagerService( + true /*wait_for_ownership*/, false /*perform_preinit*/, + &mock_local_data_store_, &mock_tpm_status_, &mock_tpm_initializer_, + &mock_tpm_nvram_)); + } +}; + +// Tests must call SetupService(). +class TpmManagerServiceTest_Preinit : public TpmManagerServiceTest { + public: + ~TpmManagerServiceTest_Preinit() override = default; + void SetUp() override { + service_.reset(new TpmManagerService( + true /*wait_for_ownership*/, true /*perform_preinit*/, + &mock_local_data_store_, &mock_tpm_status_, &mock_tpm_initializer_, + &mock_tpm_nvram_)); } }; @@ -129,8 +155,17 @@ Run(); } -TEST_F(TpmManagerServiceTest, NoAutoInitialize) { +TEST_F(TpmManagerServiceTest_Preinit, NoAutoInitialize) { EXPECT_CALL(mock_tpm_initializer_, InitializeTpm()).Times(0); + EXPECT_CALL(mock_tpm_initializer_, PreInitializeTpm()).Times(1); + SetupService(); + RunServiceWorkerAndQuit(); +} + +TEST_F(TpmManagerServiceTest_NoPreinit, NoPreInitialize) { + EXPECT_CALL(mock_tpm_initializer_, InitializeTpm()).Times(0); + EXPECT_CALL(mock_tpm_initializer_, PreInitializeTpm()).Times(0); + SetupService(); RunServiceWorkerAndQuit(); }