Commit 30a48c04 authored by Leo Lai's avatar Leo Lai Committed by Commit Bot

initial commit of TpmManagerClient.

This is the preparation of the direct communication with tpm manager
daemon.

As patterns commonly adopted in other dbus clients, we also leave
`TestInterface` class for future extension.

To test the CL, a test-only CL is introduced to check if we can get TPM
status using the introduced classes.

BUG=b:172748724
TEST=build ok.
TEST=See above.

Change-Id: I94f2d37b4e03c0219e0463ad58bd05a581233a68
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2537731
Commit-Queue: Leo Lai <cylai@google.com>
Reviewed-by: default avatarRyo Hashimoto <hashimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#829608}
parent 729b5aa3
......@@ -185,6 +185,8 @@ source_set("chromeos") {
"//chromeos/dbus/system_clock",
"//chromeos/dbus/system_proxy",
"//chromeos/dbus/system_proxy:system_proxy_proto",
"//chromeos/dbus/tpm_manager",
"//chromeos/dbus/tpm_manager:tpm_manager_proto",
"//chromeos/dbus/upstart",
"//chromeos/disks",
"//chromeos/geolocation",
......
......@@ -34,6 +34,7 @@
#include "chromeos/dbus/session_manager/session_manager_client.h"
#include "chromeos/dbus/system_clock/system_clock_client.h"
#include "chromeos/dbus/system_proxy/system_proxy_client.h"
#include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
#include "chromeos/dbus/upstart/upstart_client.h"
#include "chromeos/tpm/install_attributes.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h"
......@@ -90,6 +91,7 @@ void InitializeDBus() {
InitializeDBusClient<SessionManagerClient>(bus);
InitializeDBusClient<SystemClockClient>(bus);
InitializeDBusClient<SystemProxyClient>(bus);
InitializeDBusClient<TpmManagerClient>(bus);
InitializeDBusClient<UpstartClient>(bus);
// Initialize the device settings service so that we'll take actions per
......@@ -119,6 +121,7 @@ void ShutdownDBus() {
// Other D-Bus clients are shut down, also in reverse order of initialization.
UpstartClient::Shutdown();
TpmManagerClient::Shutdown();
SystemProxyClient::Shutdown();
SystemClockClient::Shutdown();
SessionManagerClient::Shutdown();
......
......@@ -195,6 +195,8 @@ source_set("unit_tests") {
"//chromeos/dbus/power:test_support",
"//chromeos/dbus/session_manager",
"//chromeos/dbus/shill:test_support",
"//chromeos/dbus/tpm_manager",
"//chromeos/dbus/tpm_manager:tpm_manager_proto",
"//chromeos/tpm:test_support",
"//components/account_id",
"//dbus",
......@@ -220,6 +222,7 @@ source_set("unit_tests") {
"native_timer_unittest.cc",
"oobe_configuration_client_unittest.cc",
"pipe_reader_unittest.cc",
"tpm_manager/tpm_manager_client_unittest.cc",
"update_engine_client_unittest.cc",
"util/version_loader_unittest.cc",
]
......
# Copyright 2020 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.
import("//third_party/protobuf/proto_library.gni")
assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos")
component("tpm_manager") {
output_name = "chromeos_dbus_tpm_manager"
defines = [ "IS_CHROMEOS_DBUS_TPM_MANAGER_IMPL" ]
deps = [
":tpm_manager_proto",
"//base",
"//chromeos/dbus/constants:constants",
"//dbus",
]
sources = [
"fake_tpm_manager_client.cc",
"fake_tpm_manager_client.h",
"tpm_manager_client.cc",
"tpm_manager_client.h",
]
}
proto_library("tpm_manager_proto") {
sources =
[ "//third_party/cros_system_api/dbus/tpm_manager/tpm_manager.proto" ]
proto_out_dir = "chromeos/dbus/tpm_manager"
}
// Copyright 2020 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 "chromeos/dbus/tpm_manager/fake_tpm_manager_client.h"
#include "base/notreached.h"
namespace chromeos {
FakeTpmManagerClient::FakeTpmManagerClient() = default;
FakeTpmManagerClient::~FakeTpmManagerClient() = default;
void FakeTpmManagerClient::GetTpmNonsensitiveStatus(
const ::tpm_manager::GetTpmNonsensitiveStatusRequest& request,
GetTpmNonsensitiveStatusCallback callback) {
NOTIMPLEMENTED();
}
void FakeTpmManagerClient::GetVersionInfo(
const ::tpm_manager::GetVersionInfoRequest& request,
GetVersionInfoCallback callback) {
NOTIMPLEMENTED();
}
void FakeTpmManagerClient::GetDictionaryAttackInfo(
const ::tpm_manager::GetDictionaryAttackInfoRequest& request,
GetDictionaryAttackInfoCallback callback) {
NOTIMPLEMENTED();
}
void FakeTpmManagerClient::TakeOwnership(
const ::tpm_manager::TakeOwnershipRequest& request,
TakeOwnershipCallback callback) {
NOTIMPLEMENTED();
}
void FakeTpmManagerClient::ClearStoredOwnerPassword(
const ::tpm_manager::ClearStoredOwnerPasswordRequest& request,
ClearStoredOwnerPasswordCallback callback) {
NOTIMPLEMENTED();
}
} // namespace chromeos
// Copyright 2020 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.
#ifndef CHROMEOS_DBUS_TPM_MANAGER_FAKE_TPM_MANAGER_CLIENT_H_
#define CHROMEOS_DBUS_TPM_MANAGER_FAKE_TPM_MANAGER_CLIENT_H_
#include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
#include "base/component_export.h"
#include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
namespace chromeos {
class COMPONENT_EXPORT(CHROMEOS_DBUS_TPM_MANAGER) FakeTpmManagerClient
: public TpmManagerClient {
public:
FakeTpmManagerClient();
~FakeTpmManagerClient() override;
// Not copyable or movable.
FakeTpmManagerClient(const FakeTpmManagerClient&) = delete;
FakeTpmManagerClient& operator=(const FakeTpmManagerClient&) = delete;
FakeTpmManagerClient(FakeTpmManagerClient&&) = delete;
FakeTpmManagerClient& operator=(FakeTpmManagerClient&&) = delete;
// TpmManagerClient:
void GetTpmNonsensitiveStatus(
const ::tpm_manager::GetTpmNonsensitiveStatusRequest& request,
GetTpmNonsensitiveStatusCallback callback) override;
void GetVersionInfo(const ::tpm_manager::GetVersionInfoRequest& request,
GetVersionInfoCallback callback) override;
void GetDictionaryAttackInfo(
const ::tpm_manager::GetDictionaryAttackInfoRequest& request,
GetDictionaryAttackInfoCallback callback) override;
void TakeOwnership(const ::tpm_manager::TakeOwnershipRequest& request,
TakeOwnershipCallback callback) override;
void ClearStoredOwnerPassword(
const ::tpm_manager::ClearStoredOwnerPasswordRequest& request,
ClearStoredOwnerPasswordCallback callback) override;
};
} // namespace chromeos
#endif // CHROMEOS_DBUS_TPM_MANAGER_FAKE_TPM_MANAGER_CLIENT_H_
// Copyright 2020 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 "chromeos/dbus/tpm_manager/tpm_manager_client.h"
#include <utility>
#include <google/protobuf/message_lite.h>
#include "base/bind.h"
#include "base/check_op.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "chromeos/dbus/constants/dbus_switches.h"
#include "chromeos/dbus/tpm_manager/fake_tpm_manager_client.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_path.h"
#include "dbus/object_proxy.h"
#include "third_party/cros_system_api/dbus/tpm_manager/dbus-constants.h"
namespace chromeos {
namespace {
// An arbitrary timeout for taking ownership.
constexpr base::TimeDelta kTakeOwnershipTimeout =
base::TimeDelta::FromSeconds(80);
TpmManagerClient* g_instance = nullptr;
// Tries to parse a proto message from |response| into |proto|.
// Returns false if |response| is nullptr or the message cannot be parsed.
bool ParseProto(dbus::Response* response,
google::protobuf::MessageLite* proto) {
if (!response) {
LOG(ERROR) << "Failed to call tpm_managerd";
return false;
}
dbus::MessageReader reader(response);
if (!reader.PopArrayOfBytesAsProto(proto)) {
LOG(ERROR) << "Failed to parse response message from tpm_managerd";
return false;
}
return true;
}
// "Real" implementation of TpmManagerClient taking to the TpmManager daemon
// on the Chrome OS side.
class TpmManagerClientImpl : public TpmManagerClient {
public:
TpmManagerClientImpl() = default;
~TpmManagerClientImpl() override = default;
// Not copyable or movable.
TpmManagerClientImpl(const TpmManagerClientImpl&) = delete;
TpmManagerClientImpl& operator=(const TpmManagerClientImpl&) = delete;
TpmManagerClientImpl(TpmManagerClientImpl&&) = delete;
TpmManagerClientImpl& operator=(TpmManagerClientImpl&&) = delete;
// TpmManagerClient overrides:
void GetTpmNonsensitiveStatus(
const ::tpm_manager::GetTpmNonsensitiveStatusRequest& request,
GetTpmNonsensitiveStatusCallback callback) override {
CallProtoMethod(::tpm_manager::kGetTpmNonsensitiveStatus, request,
std::move(callback));
}
void GetVersionInfo(const ::tpm_manager::GetVersionInfoRequest& request,
GetVersionInfoCallback callback) override {
CallProtoMethod(::tpm_manager::kGetVersionInfo, request,
std::move(callback));
}
void GetDictionaryAttackInfo(
const ::tpm_manager::GetDictionaryAttackInfoRequest& request,
GetDictionaryAttackInfoCallback callback) override {
CallProtoMethod(::tpm_manager::kGetDictionaryAttackInfo, request,
std::move(callback));
}
void TakeOwnership(const ::tpm_manager::TakeOwnershipRequest& request,
TakeOwnershipCallback callback) override {
// Use a longer timeout for TPM ownership operation.
CallProtoMethodWithTimeout(::tpm_manager::kTakeOwnership,
kTakeOwnershipTimeout.InMilliseconds(), request,
std::move(callback));
}
void ClearStoredOwnerPassword(
const ::tpm_manager::ClearStoredOwnerPasswordRequest& request,
ClearStoredOwnerPasswordCallback callback) override {
CallProtoMethod(::tpm_manager::kClearStoredOwnerPassword, request,
std::move(callback));
}
void Init(dbus::Bus* bus) {
proxy_ = bus->GetObjectProxy(
::tpm_manager::kTpmManagerServiceName,
dbus::ObjectPath(::tpm_manager::kTpmManagerServicePath));
}
private:
// Calls tpm_managerd's |method_name| method, passing in |request| as input
// with |timeout_ms|. Once the (asynchronous) call finishes, |callback| is
// called with the response proto.
template <typename RequestType, typename ReplyType>
void CallProtoMethodWithTimeout(
const char* method_name,
int timeout_ms,
const RequestType& request,
base::OnceCallback<void(const ReplyType&)> callback) {
dbus::MethodCall method_call(::tpm_manager::kTpmManagerInterface,
method_name);
dbus::MessageWriter writer(&method_call);
if (!writer.AppendProtoAsArrayOfBytes(request)) {
ReplyType reply;
reply.set_status(::tpm_manager::STATUS_DBUS_ERROR);
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), reply));
return;
}
// Bind with the weak pointer of |this| so the response is not
// handled once |this| is already destroyed.
proxy_->CallMethod(
&method_call, timeout_ms,
base::BindOnce(&TpmManagerClientImpl::HandleResponse<ReplyType>,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
// Calls tpm_managerd's |method_name| method, passing in |request| as input
// with the default timeout. Once the (asynchronous) call finishes, |callback|
// is called with the response proto.
template <typename RequestType, typename ReplyType>
void CallProtoMethod(const char* method_name,
const RequestType& request,
base::OnceCallback<void(const ReplyType&)> callback) {
CallProtoMethodWithTimeout(method_name,
dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, request,
std::move(callback));
}
// Parses the response proto message from |response| and calls |callback| with
// the decoded message. Calls |callback| with an |STATUS_DBUS_ERROR| message
// on error, including timeout.
template <typename ReplyType>
void HandleResponse(base::OnceCallback<void(const ReplyType&)> callback,
dbus::Response* response) {
ReplyType reply_proto;
if (!ParseProto(response, &reply_proto))
reply_proto.set_status(::tpm_manager::STATUS_DBUS_ERROR);
std::move(callback).Run(reply_proto);
}
// D-Bus proxy for the TpmManager daemon, not owned.
dbus::ObjectProxy* proxy_ = nullptr;
base::WeakPtrFactory<TpmManagerClientImpl> weak_factory_{this};
};
} // namespace
TpmManagerClient::TpmManagerClient() {
CHECK(!g_instance);
g_instance = this;
}
TpmManagerClient::~TpmManagerClient() {
CHECK_EQ(this, g_instance);
g_instance = nullptr;
}
// static
void TpmManagerClient::Initialize(dbus::Bus* bus) {
CHECK(bus);
(new TpmManagerClientImpl())->Init(bus);
}
// static
void TpmManagerClient::InitializeFake() {
new FakeTpmManagerClient();
}
// static
void TpmManagerClient::Shutdown() {
CHECK(g_instance);
delete g_instance;
// The destructor resets |g_instance|.
DCHECK(!g_instance);
}
// static
TpmManagerClient* TpmManagerClient::Get() {
return g_instance;
}
} // namespace chromeos
// Copyright 2020 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.
#ifndef CHROMEOS_DBUS_TPM_MANAGER_TPM_MANAGER_CLIENT_H_
#define CHROMEOS_DBUS_TPM_MANAGER_TPM_MANAGER_CLIENT_H_
#include "base/callback.h"
#include "base/component_export.h"
#include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
namespace dbus {
class Bus;
}
namespace chromeos {
// TpmManagerClient is used to communicate with the org.chromium.TpmManager
// service. All method should be called from the origin thread (UI thread) which
// initializes the DBusThreadManager instance.
// For more information, please see
// "chromium/src/third_party/cros_system_api/dbus/tpm_manager" for detailed
// definitions of the D-Bus methods and their arguments.
class COMPONENT_EXPORT(CHROMEOS_DBUS_TPM_MANAGER) TpmManagerClient {
public:
using GetTpmNonsensitiveStatusCallback = base::OnceCallback<void(
const ::tpm_manager::GetTpmNonsensitiveStatusReply&)>;
using GetVersionInfoCallback =
base::OnceCallback<void(const ::tpm_manager::GetVersionInfoReply&)>;
using GetDictionaryAttackInfoCallback = base::OnceCallback<void(
const ::tpm_manager::GetDictionaryAttackInfoReply&)>;
using TakeOwnershipCallback =
base::OnceCallback<void(const ::tpm_manager::TakeOwnershipReply&)>;
using ClearStoredOwnerPasswordCallback = base::OnceCallback<void(
const ::tpm_manager::ClearStoredOwnerPasswordReply&)>;
// Not copyable or movable.
TpmManagerClient(const TpmManagerClient&) = delete;
TpmManagerClient& operator=(const TpmManagerClient&) = delete;
TpmManagerClient(TpmManagerClient&&) = delete;
TpmManagerClient& operator=(TpmManagerClient&&) = delete;
// Creates and initializes the global instance. |bus| must not be null.
static void Initialize(dbus::Bus* bus);
// Creates and initializes a fake global instance if not already created.
static void InitializeFake();
// Destroys the global instance.
static void Shutdown();
// Returns the global instance which may be null if not initialized.
static TpmManagerClient* Get();
// Queries the assorted TPM statuses that tpm manager can tell, e.g., TPM
// ownership status, the presence of the owner password, the capability of
// resetting dictionary attack lockout; for the complete list of the returned
// statuses, see `GetTpmNonsensitiveStatusReply`.
virtual void GetTpmNonsensitiveStatus(
const ::tpm_manager::GetTpmNonsensitiveStatusRequest& request,
GetTpmNonsensitiveStatusCallback callback) = 0;
// Queries the detailed TPM version information; for the complete list of the
// entries, see `GetVersionInfoReply`.
virtual void GetVersionInfo(
const ::tpm_manager::GetVersionInfoRequest& request,
GetVersionInfoCallback callback) = 0;
// Queries the dictionary lockout information of TPM's dictionary attack
// protection, The reply contains the related information, including the
// current dictionary attack counter, and the flag if the TPM is in the
// lockout state.
virtual void GetDictionaryAttackInfo(
const ::tpm_manager::GetDictionaryAttackInfoRequest& request,
GetDictionaryAttackInfoCallback callback) = 0;
// Triggers TPM initialization process by tpm manager.
virtual void TakeOwnership(const ::tpm_manager::TakeOwnershipRequest& request,
TakeOwnershipCallback callback) = 0;
// Requests tpm manager to attempt to wipe the TPM owner password from its
// on-disk database.
virtual void ClearStoredOwnerPassword(
const ::tpm_manager::ClearStoredOwnerPasswordRequest& request,
ClearStoredOwnerPasswordCallback callback) = 0;
protected:
// Initialize/Shutdown should be used instead.
TpmManagerClient();
virtual ~TpmManagerClient();
};
} // namespace chromeos
#endif // CHROMEOS_DBUS_TPM_MANAGER_TPM_MANAGER_CLIENT_H_
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment