| // Copyright 2024 The ChromiumOS Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // vtpm_client is a command line tool that supports various vTPM operations. |
| #include <memory> |
| #include <stdio.h> |
| #include <string> |
| |
| #include <base/command_line.h> |
| #include <base/logging.h> |
| #include <base/strings/string_number_conversions.h> |
| #include <base/timer/elapsed_timer.h> |
| #include <brillo/syslog_logging.h> |
| |
| #include "trunks/error_codes.h" |
| #include "trunks/trunks_factory_impl.h" |
| #include "vtpm/client/vtpm_dbus_proxy.h" |
| |
| namespace { |
| |
| using trunks::AuthorizationDelegate; |
| using trunks::TrunksFactory; |
| using trunks::TrunksFactoryImpl; |
| using vtpm::VtpmDBusProxy; |
| |
| void PrintUsage() { |
| puts("vTPM command options:"); |
| puts(" --index_data --index=<N> - print the data of NV index N in hex"); |
| puts(" format."); |
| } |
| |
| std::string HexEncode(const std::string& bytes) { |
| return base::HexEncode(bytes.data(), bytes.size()); |
| } |
| |
| int PrintIndexDataInHex(const TrunksFactory& factory, int index) { |
| // Mask out the nv index handle so the user can either add or not add it |
| // themselves. |
| index &= trunks::HR_HANDLE_MASK; |
| std::unique_ptr<trunks::TpmUtility> tpm_utility = factory.GetTpmUtility(); |
| trunks::TPMS_NV_PUBLIC nvram_public; |
| trunks::TPM_RC rc = tpm_utility->GetNVSpacePublicArea(index, &nvram_public); |
| if (rc != trunks::TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error reading NV space public area: " |
| << trunks::GetErrorString(rc); |
| return -1; |
| } |
| std::unique_ptr<AuthorizationDelegate> empty_password_authorization = |
| factory.GetPasswordAuthorization(""); |
| std::string nvram_data; |
| rc = |
| tpm_utility->ReadNVSpace(index, /*offset=*/0, nvram_public.data_size, |
| /*using_owner_authorization=*/false, &nvram_data, |
| empty_password_authorization.get()); |
| if (rc != trunks::TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error reading NV space: " << trunks::GetErrorString(rc); |
| return -1; |
| } |
| printf("NV Index data: %s\n", HexEncode(nvram_data).c_str()); |
| return 0; |
| } |
| |
| } // namespace |
| |
| int main(int argc, char** argv) { |
| base::CommandLine::Init(argc, argv); |
| brillo::InitLog(brillo::kLogToStderr); |
| base::CommandLine* cl = base::CommandLine::ForCurrentProcess(); |
| if (cl->HasSwitch("help")) { |
| puts("vTPM Client: A command line tool to access the vTPM."); |
| PrintUsage(); |
| return 0; |
| } |
| |
| std::unique_ptr<VtpmDBusProxy> dbus_proxy = std::make_unique<VtpmDBusProxy>(); |
| |
| CHECK(dbus_proxy->Init()) << "Failed to initialize D-Bus proxy."; |
| |
| TrunksFactoryImpl factory(dbus_proxy.get()); |
| CHECK(factory.Initialize()) << "Failed to initialize trunks factory."; |
| |
| if (cl->HasSwitch("index_data") && cl->HasSwitch("index")) { |
| uint32_t nv_index = |
| std::stoul(cl->GetSwitchValueASCII("index"), nullptr, 16); |
| return PrintIndexDataInHex(factory, nv_index); |
| } |
| |
| puts("Invalid options!"); |
| PrintUsage(); |
| return -1; |
| } |