| // Copyright 2022 The ChromiumOS Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "libhwsec/backend/tpm1/state.h" | |
| #include <utility> | |
| #include <libhwsec-foundation/status/status_chain_macros.h> | |
| #include <tpm_manager/proto_bindings/tpm_manager.pb.h> | |
| #include <tpm_manager-client/tpm_manager/dbus-proxies.h> | |
| #include "libhwsec/error/tpm_manager_error.h" | |
| #include "libhwsec/status.h" | |
| using hwsec_foundation::status::MakeStatus; | |
| namespace hwsec { | |
| StatusOr<bool> StateTpm1::IsEnabled() { | |
| tpm_manager::GetTpmNonsensitiveStatusRequest request; | |
| tpm_manager::GetTpmNonsensitiveStatusReply reply; | |
| if (brillo::ErrorPtr err; !tpm_manager_.GetTpmNonsensitiveStatus( | |
| request, &reply, &err, Proxy::kDefaultDBusTimeoutMs)) { | |
| return MakeStatus<TPMError>(TPMRetryAction::kCommunication) | |
| .Wrap(std::move(err)); | |
| } | |
| RETURN_IF_ERROR(MakeStatus<TPMManagerError>(reply.status())); | |
| return reply.is_enabled(); | |
| } | |
| StatusOr<bool> StateTpm1::IsReady() { | |
| tpm_manager::GetTpmNonsensitiveStatusRequest request; | |
| tpm_manager::GetTpmNonsensitiveStatusReply reply; | |
| if (brillo::ErrorPtr err; !tpm_manager_.GetTpmNonsensitiveStatus( | |
| request, &reply, &err, Proxy::kDefaultDBusTimeoutMs)) { | |
| return MakeStatus<TPMError>(TPMRetryAction::kCommunication) | |
| .Wrap(std::move(err)); | |
| } | |
| RETURN_IF_ERROR(MakeStatus<TPMManagerError>(reply.status())); | |
| return reply.is_owned(); | |
| } | |
| Status StateTpm1::Prepare() { | |
| tpm_manager::TakeOwnershipRequest request; | |
| tpm_manager::TakeOwnershipReply reply; | |
| if (brillo::ErrorPtr err; !tpm_manager_.TakeOwnership( | |
| request, &reply, &err, Proxy::kDefaultDBusTimeoutMs)) { | |
| return MakeStatus<TPMError>(TPMRetryAction::kCommunication) | |
| .Wrap(std::move(err)); | |
| } | |
| return MakeStatus<TPMManagerError>(reply.status()); | |
| } | |
| void StateTpm1::WaitUntilReady(base::OnceCallback<void(Status)> callback) { | |
| if (!received_ready_signal_.has_value()) { | |
| received_ready_signal_ = false; | |
| tpm_manager_.RegisterSignalOwnershipTakenSignalHandler( | |
| base::IgnoreArgs<const tpm_manager::OwnershipTakenSignal&>( | |
| base::BindRepeating(&StateTpm1::OnReady, | |
| weak_factory_.GetWeakPtr())), | |
| base::DoNothing()); | |
| } | |
| if (received_ready_signal_.value() == false) { | |
| received_ready_signal_ = IsReady().value_or(false); | |
| } | |
| if (received_ready_signal_.value() == true) { | |
| std::move(callback).Run(OkStatus()); | |
| return; | |
| } | |
| ready_callbacks_.push_back(std::move(callback)); | |
| } | |
| void StateTpm1::OnReady() { | |
| received_ready_signal_ = true; | |
| std::vector<base::OnceCallback<void(Status)>> callbacks = | |
| std::move(ready_callbacks_); | |
| ready_callbacks_.clear(); | |
| for (base::OnceCallback<void(Status)>& callback : callbacks) { | |
| std::move(callback).Run(OkStatus()); | |
| } | |
| } | |
| } // namespace hwsec |