| // Copyright 2016 The Chromium OS 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 <stdio.h> |
| #include <string> |
| |
| #include <base/logging.h> |
| #include <base/macros.h> |
| #include <base/message_loop/message_loop.h> |
| #include <base/run_loop.h> |
| #include <base/strings/string_number_conversions.h> |
| #include <brillo/bind_lambda.h> |
| #include <brillo/secure_blob.h> |
| |
| #include "attestation/client/dbus_proxy.h" |
| #include "attestation/common/print_interface_proto.h" |
| #include "cryptohome/tpm.h" |
| #include "tpm_manager/client/tpm_ownership_dbus_proxy.h" |
| #include "tpm_manager/common/print_tpm_manager_proto.h" |
| |
| namespace cryptohome { |
| |
| namespace tpm_manager { |
| |
| using attestation::AttestationStatus; |
| |
| template <typename MethodType, typename ReplyProtoType> |
| void SendAndWait(const MethodType& method, |
| ReplyProtoType* reply_proto) { |
| base::RunLoop loop; |
| auto callback = base::Bind( |
| [](ReplyProtoType* reply_proto, base::RunLoop* loop, |
| const ReplyProtoType& reply) { |
| *reply_proto = reply; |
| loop->Quit(); |
| }, |
| reply_proto, &loop); |
| method.Run(callback); |
| loop.Run(); |
| } |
| |
| int TakeOwnership(bool finalize) { |
| base::MessageLoop loop(base::MessageLoop::TYPE_IO); |
| base::Time start_time = base::Time::Now(); |
| ::tpm_manager::TpmOwnershipDBusProxy proxy; |
| if (!proxy.Initialize()) { |
| LOG(ERROR) << "Failed to start tpm ownership proxy"; |
| return -1; |
| } |
| LOG(INFO) << "Initializing TPM."; |
| ::tpm_manager::TakeOwnershipRequest request; |
| auto method = base::Bind(&::tpm_manager::TpmOwnershipDBusProxy::TakeOwnership, |
| base::Unretained(&proxy), request); |
| ::tpm_manager::TakeOwnershipReply reply; |
| SendAndWait(method, &reply); |
| if (reply.status() != ::tpm_manager::STATUS_SUCCESS) { |
| LOG(ERROR) << "Failed to take ownership."; |
| puts(GetProtoDebugString(reply).c_str()); |
| return -1; |
| } |
| if (finalize) { |
| LOG(WARNING) << "Finalization is ignored for TPM2.0"; |
| } |
| base::TimeDelta duration = base::Time::Now() - start_time; |
| LOG(INFO) << "TPM initialization successful (" |
| << duration.InMilliseconds() << " ms)."; |
| return 0; |
| } |
| |
| int VerifyEK(bool is_cros_core) { |
| base::MessageLoop loop(base::MessageLoop::TYPE_IO); |
| attestation::DBusProxy proxy; |
| if (!proxy.Initialize()) { |
| LOG(ERROR) << "Failed to start attestation proxy"; |
| return -1; |
| } |
| attestation::VerifyRequest request; |
| request.set_cros_core(is_cros_core); |
| request.set_ek_only(true); |
| auto method = base::Bind(&attestation::DBusProxy::Verify, |
| base::Unretained(&proxy), request); |
| attestation::VerifyReply reply; |
| SendAndWait(method, &reply); |
| if (reply.status() != AttestationStatus::STATUS_SUCCESS) { |
| LOG(ERROR) << "Failed to verify TPM endorsement."; |
| puts(GetProtoDebugString(reply).c_str()); |
| return -1; |
| } |
| if (!reply.verified()) { |
| LOG(ERROR) << "TPM endorsement verification failed."; |
| return -1; |
| } |
| LOG(INFO) << "TPM endorsement verified successfully."; |
| return 0; |
| } |
| |
| int DumpStatus() { |
| LOG(ERROR) << "Not implemented"; |
| return -1; |
| } |
| |
| int GetRandom(unsigned int random_bytes_count) { |
| cryptohome::Tpm* tpm = cryptohome::Tpm::GetSingleton(); |
| brillo::SecureBlob random_bytes; |
| tpm->GetRandomData(random_bytes_count, &random_bytes); |
| if (random_bytes_count != random_bytes.size()) |
| return -1; |
| |
| std::string hex_bytes = |
| base::HexEncode(random_bytes.data(), random_bytes.size()); |
| puts(hex_bytes.c_str()); |
| return 0; |
| } |
| |
| bool GetVersionInfo(cryptohome::Tpm::TpmVersionInfo* version_info) { |
| base::MessageLoop loop(base::MessageLoop::TYPE_IO); |
| ::tpm_manager::TpmOwnershipDBusProxy proxy; |
| if (!proxy.Initialize()) { |
| LOG(ERROR) << "Failed to start tpm ownership proxy"; |
| return false; |
| } |
| ::tpm_manager::GetTpmStatusRequest request; |
| auto method = base::Bind(&::tpm_manager::TpmOwnershipDBusProxy::GetTpmStatus, |
| base::Unretained(&proxy), request); |
| ::tpm_manager::GetTpmStatusReply reply; |
| SendAndWait(method, &reply); |
| if (reply.status() != ::tpm_manager::STATUS_SUCCESS) { |
| LOG(ERROR) << "Failed to get tpm status."; |
| puts(GetProtoDebugString(reply).c_str()); |
| return false; |
| } |
| |
| if (!reply.has_version_info()) { |
| LOG(ERROR) << "tpm status reply is missing version info."; |
| return false; |
| } |
| |
| version_info->family = reply.version_info().family(); |
| version_info->spec_level = reply.version_info().spec_level(); |
| version_info->manufacturer = reply.version_info().manufacturer(); |
| version_info->tpm_model = reply.version_info().tpm_model(); |
| version_info->firmware_version = reply.version_info().firmware_version(); |
| version_info->vendor_specific = reply.version_info().vendor_specific(); |
| return true; |
| } |
| |
| int GetIFXFieldUpgradeInfo(cryptohome::Tpm::IFXFieldUpgradeInfo* info) { |
| LOG(ERROR) << "Not implemented"; |
| return -1; |
| } |
| |
| } // namespace tpm_manager |
| |
| } // namespace cryptohome |