123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- // 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/raw_ptr.h"
- #include "base/memory/weak_ptr.h"
- #include "base/observer_list.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::Seconds(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;
- }
- void OnSignalConnected(const std::string& interface_name,
- const std::string& signal_name,
- bool success) {
- DCHECK_EQ(interface_name, ::tpm_manager::kTpmManagerInterface);
- LOG_IF(DFATAL, !success) << "Failed to connect to D-Bus signal; interface: "
- << interface_name << "; signal: " << signal_name;
- }
- // "Real" implementation of TpmManagerClient talking 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 GetSupportedFeatures(
- const ::tpm_manager::GetSupportedFeaturesRequest& request,
- GetSupportedFeaturesCallback callback) override {
- CallProtoMethod(::tpm_manager::kGetSupportedFeatures, 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 AddObserver(Observer* observer) override {
- observer_list_.AddObserver(observer);
- }
- void RemoveObserver(Observer* observer) override {
- observer_list_.RemoveObserver(observer);
- }
- void Init(dbus::Bus* bus) {
- proxy_ = bus->GetObjectProxy(
- ::tpm_manager::kTpmManagerServiceName,
- dbus::ObjectPath(::tpm_manager::kTpmManagerServicePath));
- ConnectToOwnershipTakenSignal();
- }
- private:
- TestInterface* GetTestInterface() override { return nullptr; }
- // 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);
- }
- // Called when receiving ownership taken signal.
- void OnOwnershipTakenSignal(dbus::Signal*) {
- for (auto& observer : observer_list_) {
- observer.OnOwnershipTaken();
- }
- }
- // Connects to ownership taken signal.
- void ConnectToOwnershipTakenSignal() {
- proxy_->ConnectToSignal(
- ::tpm_manager::kTpmManagerInterface,
- ::tpm_manager::kOwnershipTakenSignal,
- base::BindRepeating(&TpmManagerClientImpl::OnOwnershipTakenSignal,
- weak_factory_.GetWeakPtr()),
- base::BindOnce(&OnSignalConnected));
- }
- // D-Bus proxy for the TpmManager daemon, not owned.
- raw_ptr<dbus::ObjectProxy> proxy_ = nullptr;
- // The observer list of ownership taken signal.
- base::ObserverList<Observer> observer_list_;
- 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() {
- // Do not create a new instance if it was initialized early in a browser test
- // (for early setup calls dependent on TpmManagerClient).
- if (!FakeTpmManagerClient::Get())
- 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
|