blob: 27b373351245278b61ebd4c2781fbc31dd7cd15c [file]
// Copyright 2021 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/error/tpm_retry_handler.h"
#include <utility>
#include <base/logging.h>
#include <base/threading/platform_thread.h>
#include <base/time/time.h>
#include "libhwsec/error/tpm_error.h"
#include "libhwsec/middleware/function_name.h"
#include "libhwsec/status.h"
#include "libhwsec/structures/key.h"
namespace {
constexpr int kMaxTryCount = 5;
constexpr base::TimeDelta kInitialRetry = base::Milliseconds(100);
constexpr double kRetryMultiplier = 2.0;
} // namespace
namespace hwsec {
TPMRetryHandler::TPMRetryHandler()
: remaining_try_count_(kMaxTryCount), current_delay_(kInitialRetry) {}
void TPMRetryHandler::DelayAndUpdate() {
#if !USE_FUZZER
base::PlatformThread::Sleep(current_delay_);
#endif
current_delay_ *= kRetryMultiplier;
remaining_try_count_--;
}
template <>
bool TPMRetryHandler::ReloadObject(hwsec::Backend& backend,
Metrics* metrics,
const Key& key) {
auto* key_mgr = backend.Get<Backend::KeyManagement>();
if (key_mgr == nullptr) {
return false;
}
Status status = key_mgr->ReloadIfPossible(key);
if (metrics) {
metrics->SendFuncResultToUMA(
SimplifyFuncName(GetFuncName<&KeyManagement::ReloadIfPossible>()),
status);
}
if (!status.ok()) {
LOG(WARNING) << "Failed to reload key parameter: " << status.status();
return false;
}
return true;
}
bool TPMRetryHandler::FlushInvalidSessions(hwsec::Backend& backend,
Metrics* metrics) {
auto* session_mgr = backend.Get<Backend::SessionManagement>();
if (session_mgr == nullptr) {
return false;
}
Status status = session_mgr->FlushInvalidSessions();
if (metrics) {
metrics->SendFuncResultToUMA(
SimplifyFuncName(
GetFuncName<&SessionManagement::FlushInvalidSessions>()),
status);
}
if (!status.ok()) {
LOG(WARNING) << "Failed to flush invalid sessions: " << status.status();
return false;
}
return true;
}
bool TPMRetryHandler::SyncPinWeaverHashTree(hwsec::Backend& backend,
Metrics* metrics) {
auto* pinweaver_manager = backend.Get<Backend::PinWeaverManager>();
if (pinweaver_manager == nullptr) {
return false;
}
Status status = pinweaver_manager->SyncHashTree();
if (metrics) {
metrics->SendFuncResultToUMA(
SimplifyFuncName(GetFuncName<&PinWeaverManager::SyncHashTree>()),
status);
}
if (!status.ok()) {
LOG(WARNING) << "Failed to sync pinweaver hash tree: "
<< status.err_status();
return false;
}
return true;
}
} // namespace hwsec