// Copyright 2015 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 "tpm_manager/server/tpm_manager_service.h"

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/callback.h>
#include <base/command_line.h>
#include <base/message_loop/message_pump_type.h>
#include <base/strings/stringprintf.h>
#include <base/synchronization/lock.h>
#include <crypto/sha2.h>
#include <inttypes.h>

namespace {

constexpr int kDictionaryAttackResetPeriodInHours = 1;

#if USE_TPM2
// Timeout waiting for Trunks daemon readiness.
constexpr base::TimeDelta kTrunksDaemonTimeout =
    base::TimeDelta::FromSeconds(30);
// Delay between subsequent attempts to initialize connection to Trunks daemon.
constexpr base::TimeDelta kTrunksDaemonInitAttemptDelay =
    base::TimeDelta::FromMicroseconds(300);
#endif

// Clears owner password in |local_data| if all dependencies have been removed
// and it has not yet been cleared.
// Returns true if |local_data| has been modified, false otherwise.
bool ClearOwnerPasswordIfPossible(tpm_manager::LocalData* local_data) {
  if (local_data->has_owner_password() &&
      local_data->owner_dependency().empty()) {
    local_data->clear_owner_password();
    return true;
  }
  return false;
}

int GetFingerprint(uint32_t family,
                   uint64_t spec_level,
                   uint32_t manufacturer,
                   uint32_t tpm_model,
                   uint64_t firmware_version,
                   std::string vendor_specific) {
  // The exact encoding doesn't matter as long as its unambiguous, stable and
  // contains all information present in the version fields.
  std::string encoded_parameters =
      base::StringPrintf("%08" PRIx32 "%016" PRIx64 "%08" PRIx32 "%08" PRIx32
                         "%016" PRIx64 "%016zx",
                         family, spec_level, manufacturer, tpm_model,
                         firmware_version, vendor_specific.size());
  encoded_parameters.append(vendor_specific);
  std::string hash = crypto::SHA256HashString(encoded_parameters);

  // Return the first 31 bits from |hash|.
  int result =
      static_cast<uint8_t>(hash[0]) | static_cast<uint8_t>(hash[1]) << 8 |
      static_cast<uint8_t>(hash[2]) << 16 | static_cast<uint8_t>(hash[3]) << 24;
  return result & 0x7fffffff;
}

}  // namespace

namespace tpm_manager {

namespace {

GetTpmNonsensitiveStatusReply ToGetTpmNonSensitiveStatusReply(
    const GetTpmStatusReply& from) {
  GetTpmNonsensitiveStatusReply to;
  to.set_is_owned(from.owned());
  to.set_is_enabled(from.enabled());
  const LocalData& sensitive = from.local_data();
  to.set_is_owner_password_present(!sensitive.owner_password().empty());
  // This works regardless of TPM version.
  to.set_has_reset_lock_permissions(
      !sensitive.lockout_password().empty() ||
      sensitive.owner_delegate().has_reset_lock_permissions());
  return to;
}

}  // namespace

TpmManagerService::TpmManagerService(bool wait_for_ownership,
                                     bool perform_preinit,
                                     LocalDataStore* local_data_store)
    : TpmManagerService(wait_for_ownership,
                        perform_preinit,
                        local_data_store,
                        nullptr,
                        nullptr,
                        nullptr,
                        &default_tpm_manager_metrics_) {
  CHECK(local_data_store_);
}

TpmManagerService::TpmManagerService(bool wait_for_ownership,
                                     bool perform_preinit,
                                     LocalDataStore* local_data_store,
                                     TpmStatus* tpm_status,
                                     TpmInitializer* tpm_initializer,
                                     TpmNvram* tpm_nvram,
                                     TpmManagerMetrics* tpm_manager_metrics)
    : dictionary_attack_timer_(
          base::TimeDelta::FromHours(kDictionaryAttackResetPeriodInHours)),
      local_data_store_(local_data_store),
      tpm_status_(tpm_status),
      tpm_initializer_(tpm_initializer),
      tpm_nvram_(tpm_nvram),
      tpm_manager_metrics_(tpm_manager_metrics),
      update_tpm_status_pending_(false),
      update_tpm_status_cache_dirty_(true),
      wait_for_ownership_(wait_for_ownership),
      perform_preinit_(perform_preinit) {}

TpmManagerService::~TpmManagerService() {
  worker_thread_->Stop();
}

bool TpmManagerService::Initialize() {
  origin_task_runner_ = base::ThreadTaskRunnerHandle::Get();
  worker_thread_.reset(
      new ServiceWorkerThread("TpmManager Service Worker", this));
  worker_thread_->StartWithOptions(
      base::Thread::Options(base::MessagePumpType::IO, 0));

  update_tpm_status_pending_ = true;

  PostTaskToWorkerThreadWithoutRequest<GetTpmStatusReply>(
      base::Bind(&TpmManagerService::UpdateTpmStatusCallback,
                 base::Unretained(this)),
      &TpmManagerService::InitializeTask);

  ReportVersionFingerprint();
  VLOG(1) << "Worker thread started.";
  return true;
}

void TpmManagerService::ReportVersionFingerprint() {
  auto callback = base::Bind(
      [](tpm_manager::TpmManagerMetrics* tpm_manager_metrics,
         const tpm_manager::GetVersionInfoReply& reply) {
        if (reply.status() == STATUS_SUCCESS) {
          uint32_t family = reply.family();
          uint64_t spec_level = reply.spec_level();
          uint32_t manufacturer = reply.manufacturer();
          uint32_t tpm_model = reply.tpm_model();
          uint64_t firmware_version = reply.firmware_version();
          std::string vendor_specific = reply.vendor_specific();
          tpm_manager_metrics->ReportVersionFingerprint(
              GetFingerprint(family, spec_level, manufacturer, tpm_model,
                             firmware_version, vendor_specific));
        }
      },
      base::Unretained(tpm_manager_metrics_));
  GetVersionInfo(tpm_manager::GetVersionInfoRequest(), callback);
}

void TpmManagerService::InitializeTask(
    const std::shared_ptr<GetTpmStatusReply>& reply) {
  VLOG(1) << "Initializing service...";

  if (!tpm_status_ || !tpm_initializer_ || !tpm_nvram_) {
    // Setup default objects.
#if USE_TPM2
    default_trunks_factory_ = std::make_unique<trunks::TrunksFactoryImpl>();
    // Tolerate some delay in trunksd being up and ready.
    base::TimeTicks deadline = base::TimeTicks::Now() + kTrunksDaemonTimeout;
    while (!default_trunks_factory_->Initialize() &&
           base::TimeTicks::Now() < deadline) {
      base::PlatformThread::Sleep(kTrunksDaemonInitAttemptDelay);
    }
    default_tpm_status_ =
        std::make_unique<Tpm2StatusImpl>(*default_trunks_factory_);
    tpm_status_ = default_tpm_status_.get();
    default_tpm_initializer_ = std::make_unique<Tpm2InitializerImpl>(
        *default_trunks_factory_, local_data_store_, tpm_status_);
    tpm_initializer_ = default_tpm_initializer_.get();
    default_tpm_nvram_ = std::make_unique<Tpm2NvramImpl>(
        *default_trunks_factory_, local_data_store_, tpm_status_);
    tpm_nvram_ = default_tpm_nvram_.get();
#else
    default_tpm_status_ = std::make_unique<TpmStatusImpl>();
    tpm_status_ = default_tpm_status_.get();
    default_tpm_initializer_ =
        std::make_unique<TpmInitializerImpl>(local_data_store_, tpm_status_);
    tpm_initializer_ = default_tpm_initializer_.get();
    default_tpm_nvram_ = std::make_unique<TpmNvramImpl>(local_data_store_);
    tpm_nvram_ = default_tpm_nvram_.get();
#endif
  }
  if (!tpm_status_->IsTpmEnabled()) {
    LOG(WARNING) << __func__ << ": TPM is disabled.";
    reply->set_enabled(false);
    reply->set_status(STATUS_SUCCESS);
    return;
  }
  reply->set_enabled(true);
  tpm_initializer_->VerifiedBootHelper();

  TpmStatus::TpmOwnershipStatus ownership_status;
  if (!tpm_status_->GetTpmOwned(&ownership_status)) {
    LOG(ERROR) << __func__
               << ": failed to get tpm ownership status, maybe it's the "
                  "dictionary attack lockout.";
    // GetStatus could fail because the TPM is under DA lockout, so we'll try to
    // reset lockout then try again.
    ResetDictionaryAttackCounterIfNeeded();
    if (!tpm_status_->GetTpmOwned(&ownership_status)) {
      LOG(ERROR) << __func__
                 << ": get tpm ownership status still failed. Giving up.";
      reply->set_status(STATUS_DEVICE_ERROR);
      return;
    }
    LOG(INFO) << __func__
              << ": get tpm ownership status suceeded after dictionary attack "
                 "lockout reset.";
  }

  // The precondition of DA reset is not satisfied; resets the timer so it
  // doesn't get triggered immediately.
  if (ownership_status != TpmStatus::kTpmOwned && wait_for_ownership_) {
    dictionary_attack_timer_.Reset();
  }
  worker_thread_->task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&TpmManagerService::PeriodicResetDictionaryAttackCounterTask,
                 base::Unretained(this)));

  reply->set_owned(TpmStatus::kTpmOwned == ownership_status);
  if (ownership_status == TpmStatus::kTpmOwned) {
    VLOG(1) << "Tpm is already owned.";
    if (!tpm_initializer_->EnsurePersistentOwnerDelegate()) {
      // Only treat the failure as a warning because the daemon can be partly
      // operational still.
      LOG(WARNING)
          << __func__
          << ": Failed to ensure owner delegate is ready with ownership taken.";
    }
    LocalData local_data;
    if (local_data_store_ && local_data_store_->Read(&local_data)) {
      *(reply->mutable_local_data()) = std::move(local_data);
    }
    reply->set_status(STATUS_SUCCESS);
    NotifyTpmIsOwned();
    return;
  }

  // TPM is not fully owned yet. There might be stale data in the local data
  // store. Checks and removes them if needed.
  tpm_initializer_->PruneStoredPasswords();
  tpm_nvram_->PrunePolicies();

  if (!wait_for_ownership_) {
    VLOG(1) << "Initializing TPM.";
    if (!tpm_initializer_->InitializeTpm()) {
      LOG(WARNING) << __func__ << ": TPM initialization failed.";
      dictionary_attack_timer_.Reset();
      reply->set_status(STATUS_NOT_AVAILABLE);
      return;
    }
    reply->set_owned(true);
  } else if (perform_preinit_) {
    VLOG(1) << "Pre-initializing TPM.";
    tpm_initializer_->PreInitializeTpm();
  }
  LocalData local_data;
  if (local_data_store_ && local_data_store_->Read(&local_data)) {
    *(reply->mutable_local_data()) = std::move(local_data);
  }
  reply->set_status(STATUS_SUCCESS);
  if (reply->owned()) {
    NotifyTpmIsOwned();
  }
}

void TpmManagerService::NotifyTpmIsOwned() {
  DCHECK_EQ(base::PlatformThread::CurrentId(), worker_thread_->GetThreadId());
  if (!ownership_taken_callback_.is_null()) {
    ownership_taken_callback_.Run();
    ownership_taken_callback_.Reset();
  }
}

void TpmManagerService::MarkTpmStatusCacheDirty() {
  if (base::PlatformThread::CurrentId() == worker_thread_->GetThreadId()) {
    // This should run on origin thread
    origin_task_runner_->PostTask(
        FROM_HERE, base::Bind(&TpmManagerService::MarkTpmStatusCacheDirty,
                              base::Unretained(this)));
    return;
  }

  CHECK_NE(base::PlatformThread::CurrentId(), worker_thread_->GetThreadId());

  update_tpm_status_cache_dirty_ = true;
}

void TpmManagerService::GetTpmStatus(const GetTpmStatusRequest& request,
                                     const GetTpmStatusCallback& callback) {
  if (update_tpm_status_cache_dirty_) {
    get_tpm_status_waiting_callbacks_.emplace_back(std::move(callback));
  } else {
    callback.Run(get_tpm_status_cache_);
    return;
  }
  if (update_tpm_status_pending_) {
    return;
  }
  update_tpm_status_pending_ = true;
  PostTaskToWorkerThread<GetTpmStatusReply>(
      request,
      base::Bind(&TpmManagerService::UpdateTpmStatusCallback,
                 base::Unretained(this)),
      &TpmManagerService::GetTpmStatusTask);
}

void TpmManagerService::GetTpmNonsensitiveStatus(
    const GetTpmNonsensitiveStatusRequest& request,
    const GetTpmNonsensitiveStatusCallback& callback) {
  // This function has a different way to proceed the request from other
  // request; the callback is wrapped to `GetTpmStatusCallback` followed by a
  // handle of `GetTpmStatus()`. Before sending the response,
  // `ToGetTpmNonSensitiveStatusReply()` absracts the sensitive secret in
  // `GetTpmStatusReply` away.
  GetTpmStatusCallback wrapped_callback = base::Bind(
      [](const GetTpmNonsensitiveStatusCallback& cb,
         const GetTpmStatusReply& reply) {
        cb.Run(ToGetTpmNonSensitiveStatusReply(reply));
      },
      callback);

  GetTpmStatus(GetTpmStatusRequest(), wrapped_callback);
}

void TpmManagerService::UpdateTpmStatusCallback(
    const GetTpmStatusReply& reply) {
  DCHECK_NE(base::PlatformThread::CurrentId(), worker_thread_->GetThreadId());
  update_tpm_status_cache_dirty_ = reply.status() != STATUS_SUCCESS;
  update_tpm_status_pending_ = false;
  get_tpm_status_cache_ = reply;
  std::vector<GetTpmStatusCallback> callbacks;
  callbacks.swap(get_tpm_status_waiting_callbacks_);
  for (const auto& callback : callbacks) {
    callback.Run(reply);
  }
}

void TpmManagerService::GetTpmStatusTask(
    const GetTpmStatusRequest& request,
    const std::shared_ptr<GetTpmStatusReply>& reply) {
  VLOG(1) << __func__;

  if (!tpm_status_) {
    LOG(ERROR) << __func__ << ": tpm status is uninitialized.";
    reply->set_status(STATUS_NOT_AVAILABLE);
    return;
  }

  reply->set_enabled(tpm_status_->IsTpmEnabled());

  TpmStatus::TpmOwnershipStatus ownership_status;
  if (!tpm_status_->GetTpmOwned(&ownership_status)) {
    LOG(ERROR) << __func__ << ": failed to get tpm ownership status";
    reply->set_status(STATUS_DEVICE_ERROR);
    return;
  }
  reply->set_owned(TpmStatus::kTpmOwned == ownership_status);

  LocalData local_data;
  if (local_data_store_ && local_data_store_->Read(&local_data)) {
    *reply->mutable_local_data() = local_data;
  }

  reply->set_status(STATUS_SUCCESS);
}

void TpmManagerService::GetVersionInfo(const GetVersionInfoRequest& request,
                                       const GetVersionInfoCallback& callback) {
  {
    base::AutoLock lock(version_info_cache_lock_);
    if (version_info_cache_) {
      callback.Run(*version_info_cache_);
      return;
    }
  }

  PostTaskToWorkerThread<GetVersionInfoReply>(
      request, callback, &TpmManagerService::GetVersionInfoTask);
}

void TpmManagerService::GetVersionInfoTask(
    const GetVersionInfoRequest& request,
    const std::shared_ptr<GetVersionInfoReply>& reply) {
  VLOG(1) << __func__;

  // It's possible that cache was not available when the request came to the
  // main thread but became available when the task is being processed here.
  // Checks the cache again to save one TPM call.
  if (version_info_cache_) {
    *reply = *version_info_cache_;
    return;
  }

  if (!tpm_status_) {
    LOG(ERROR) << __func__ << ": tpm status is uninitialized.";
    reply->set_status(STATUS_NOT_AVAILABLE);
    return;
  }

  uint32_t family;
  uint64_t spec_level;
  uint32_t manufacturer;
  uint32_t tpm_model;
  uint64_t firmware_version;
  std::vector<uint8_t> vendor_specific;
  if (!tpm_status_->GetVersionInfo(&family, &spec_level, &manufacturer,
                                   &tpm_model, &firmware_version,
                                   &vendor_specific)) {
    LOG(ERROR) << __func__ << ": failed to get version info from tpm status.";
    reply->set_status(STATUS_DEVICE_ERROR);
    return;
  }

  reply->set_family(family);
  reply->set_spec_level(spec_level);
  reply->set_manufacturer(manufacturer);
  reply->set_tpm_model(tpm_model);
  reply->set_firmware_version(firmware_version);
  reply->set_vendor_specific(reinterpret_cast<char*>(vendor_specific.data()),
                             vendor_specific.size());
  reply->set_status(STATUS_SUCCESS);

  {
    base::AutoLock lock(version_info_cache_lock_);
    version_info_cache_ = *reply;
  }
}

void TpmManagerService::GetDictionaryAttackInfo(
    const GetDictionaryAttackInfoRequest& request,
    const GetDictionaryAttackInfoCallback& callback) {
  PostTaskToWorkerThread<GetDictionaryAttackInfoReply>(
      request, callback, &TpmManagerService::GetDictionaryAttackInfoTask);
}

void TpmManagerService::GetDictionaryAttackInfoTask(
    const GetDictionaryAttackInfoRequest& request,
    const std::shared_ptr<GetDictionaryAttackInfoReply>& reply) {
  VLOG(1) << __func__;

  if (!tpm_status_) {
    LOG(ERROR) << __func__ << ": tpm status is uninitialized.";
    reply->set_status(STATUS_NOT_AVAILABLE);
    return;
  }

  uint32_t counter;
  uint32_t threshold;
  bool lockout;
  uint32_t lockout_time_remaining;
  if (!tpm_status_->GetDictionaryAttackInfo(&counter, &threshold, &lockout,
                                            &lockout_time_remaining)) {
    LOG(ERROR) << __func__ << ": failed to get DA info";
    reply->set_status(STATUS_DEVICE_ERROR);
    return;
  }

  reply->set_dictionary_attack_counter(counter);
  reply->set_dictionary_attack_threshold(threshold);
  reply->set_dictionary_attack_lockout_in_effect(lockout);
  reply->set_dictionary_attack_lockout_seconds_remaining(
      lockout_time_remaining);
  reply->set_status(STATUS_SUCCESS);
}

void TpmManagerService::ResetDictionaryAttackLock(
    const ResetDictionaryAttackLockRequest& request,
    const ResetDictionaryAttackLockCallback& callback) {
  PostTaskToWorkerThread<ResetDictionaryAttackLockReply>(
      request, callback, &TpmManagerService::ResetDictionaryAttackLockTask);
}

void TpmManagerService::ResetDictionaryAttackLockTask(
    const ResetDictionaryAttackLockRequest& request,
    const std::shared_ptr<ResetDictionaryAttackLockReply>& reply) {
  VLOG(1) << __func__;

  if (!tpm_initializer_) {
    LOG(ERROR) << __func__ << ": request received before tpm manager service "
               << "is initialized.";
    reply->set_status(STATUS_NOT_AVAILABLE);
    return;
  }
  if (!ResetDictionaryAttackCounterIfNeeded()) {
    LOG(ERROR) << __func__ << ": failed to reset DA lock.";
    reply->set_status(STATUS_DEVICE_ERROR);
  } else {
    reply->set_status(STATUS_SUCCESS);
  }
  dictionary_attack_timer_.Reset();
}

void TpmManagerService::TakeOwnership(const TakeOwnershipRequest& request,
                                      const TakeOwnershipCallback& callback) {
  PostTaskToWorkerThread<TakeOwnershipReply>(
      request, callback, &TpmManagerService::TakeOwnershipTask);
}

void TpmManagerService::TakeOwnershipTask(
    const TakeOwnershipRequest& request,
    const std::shared_ptr<TakeOwnershipReply>& reply) {
  VLOG(1) << __func__;
  if (!tpm_status_->IsTpmEnabled()) {
    reply->set_status(STATUS_NOT_AVAILABLE);
    return;
  }
  if (!tpm_initializer_->InitializeTpm()) {
    reply->set_status(STATUS_DEVICE_ERROR);
    return;
  }
  MarkTpmStatusCacheDirty();
  NotifyTpmIsOwned();
  if (!ResetDictionaryAttackCounterIfNeeded()) {
    LOG(WARNING) << __func__ << ": DA reset failed after taking ownership.";
  }
  dictionary_attack_timer_.Reset();
  reply->set_status(STATUS_SUCCESS);
}

void TpmManagerService::RemoveOwnerDependency(
    const RemoveOwnerDependencyRequest& request,
    const RemoveOwnerDependencyCallback& callback) {
  PostTaskToWorkerThread<RemoveOwnerDependencyReply>(
      request, callback, &TpmManagerService::RemoveOwnerDependencyTask);
}

void TpmManagerService::RemoveOwnerDependencyTask(
    const RemoveOwnerDependencyRequest& request,
    const std::shared_ptr<RemoveOwnerDependencyReply>& reply) {
  VLOG(1) << __func__;
  LocalData local_data;
  if (!local_data_store_->Read(&local_data)) {
    reply->set_status(STATUS_DEVICE_ERROR);
    return;
  }
  RemoveOwnerDependencyFromLocalData(request.owner_dependency(), &local_data);
  if (auto_clear_stored_owner_password_) {
    ClearOwnerPasswordIfPossible(&local_data);
  }
  if (!local_data_store_->Write(local_data)) {
    reply->set_status(STATUS_DEVICE_ERROR);
    return;
  }
  reply->set_status(STATUS_SUCCESS);
  MarkTpmStatusCacheDirty();
}

void TpmManagerService::RemoveOwnerDependencyFromLocalData(
    const std::string& owner_dependency, LocalData* local_data) {
  google::protobuf::RepeatedPtrField<std::string>* dependencies =
      local_data->mutable_owner_dependency();
  for (int i = 0; i < dependencies->size(); i++) {
    if (dependencies->Get(i) == owner_dependency) {
      dependencies->SwapElements(i, (dependencies->size() - 1));
      dependencies->RemoveLast();
      break;
    }
  }
}

void TpmManagerService::ClearStoredOwnerPassword(
    const ClearStoredOwnerPasswordRequest& request,
    const ClearStoredOwnerPasswordCallback& callback) {
  PostTaskToWorkerThread<ClearStoredOwnerPasswordReply>(
      request, callback, &TpmManagerService::ClearStoredOwnerPasswordTask);
}

void TpmManagerService::ClearStoredOwnerPasswordTask(
    const ClearStoredOwnerPasswordRequest& request,
    const std::shared_ptr<ClearStoredOwnerPasswordReply>& reply) {
  VLOG(1) << __func__;
  LocalData local_data;
  if (!local_data_store_->Read(&local_data)) {
    reply->set_status(STATUS_DEVICE_ERROR);
    return;
  }
  if (ClearOwnerPasswordIfPossible(&local_data)) {
    if (!local_data_store_->Write(local_data)) {
      reply->set_status(STATUS_DEVICE_ERROR);
      return;
    }
  }
  reply->set_status(STATUS_SUCCESS);
  MarkTpmStatusCacheDirty();
}

void TpmManagerService::DefineSpace(const DefineSpaceRequest& request,
                                    const DefineSpaceCallback& callback) {
  PostTaskToWorkerThread<DefineSpaceReply>(request, callback,
                                           &TpmManagerService::DefineSpaceTask);
}

void TpmManagerService::DefineSpaceTask(
    const DefineSpaceRequest& request,
    const std::shared_ptr<DefineSpaceReply>& reply) {
  VLOG(1) << __func__;
  std::vector<NvramSpaceAttribute> attributes;
  for (int i = 0; i < request.attributes_size(); ++i) {
    attributes.push_back(request.attributes(i));
  }
  reply->set_result(
      tpm_nvram_->DefineSpace(request.index(), request.size(), attributes,
                              request.authorization_value(), request.policy()));
  MarkTpmStatusCacheDirty();
}

void TpmManagerService::DestroySpace(const DestroySpaceRequest& request,
                                     const DestroySpaceCallback& callback) {
  PostTaskToWorkerThread<DestroySpaceReply>(
      request, callback, &TpmManagerService::DestroySpaceTask);
}

void TpmManagerService::DestroySpaceTask(
    const DestroySpaceRequest& request,
    const std::shared_ptr<DestroySpaceReply>& reply) {
  VLOG(1) << __func__;
  reply->set_result(tpm_nvram_->DestroySpace(request.index()));
  MarkTpmStatusCacheDirty();
}

void TpmManagerService::WriteSpace(const WriteSpaceRequest& request,
                                   const WriteSpaceCallback& callback) {
  PostTaskToWorkerThread<WriteSpaceReply>(request, callback,
                                          &TpmManagerService::WriteSpaceTask);
}

void TpmManagerService::WriteSpaceTask(
    const WriteSpaceRequest& request,
    const std::shared_ptr<WriteSpaceReply>& reply) {
  VLOG(1) << __func__;
  std::string authorization_value = request.authorization_value();
  if (request.use_owner_authorization()) {
    authorization_value = GetOwnerPassword();
    if (authorization_value.empty()) {
      reply->set_result(NVRAM_RESULT_ACCESS_DENIED);
      return;
    }
  }
  reply->set_result(tpm_nvram_->WriteSpace(request.index(), request.data(),
                                           authorization_value));
}

void TpmManagerService::ReadSpace(const ReadSpaceRequest& request,
                                  const ReadSpaceCallback& callback) {
  PostTaskToWorkerThread<ReadSpaceReply>(request, callback,
                                         &TpmManagerService::ReadSpaceTask);
}

void TpmManagerService::ReadSpaceTask(
    const ReadSpaceRequest& request,
    const std::shared_ptr<ReadSpaceReply>& reply) {
  VLOG(1) << __func__;
  std::string authorization_value = request.authorization_value();
  if (request.use_owner_authorization()) {
    authorization_value = GetOwnerPassword();
    if (authorization_value.empty()) {
      reply->set_result(NVRAM_RESULT_ACCESS_DENIED);
      return;
    }
  }
  reply->set_result(tpm_nvram_->ReadSpace(
      request.index(), reply->mutable_data(), authorization_value));
}

void TpmManagerService::LockSpace(const LockSpaceRequest& request,
                                  const LockSpaceCallback& callback) {
  PostTaskToWorkerThread<LockSpaceReply>(request, callback,
                                         &TpmManagerService::LockSpaceTask);
}

void TpmManagerService::LockSpaceTask(
    const LockSpaceRequest& request,
    const std::shared_ptr<LockSpaceReply>& reply) {
  VLOG(1) << __func__;
  std::string authorization_value = request.authorization_value();
  if (request.use_owner_authorization()) {
    authorization_value = GetOwnerPassword();
    if (authorization_value.empty()) {
      reply->set_result(NVRAM_RESULT_ACCESS_DENIED);
      return;
    }
  }
  reply->set_result(tpm_nvram_->LockSpace(request.index(), request.lock_read(),
                                          request.lock_write(),
                                          authorization_value));
}

void TpmManagerService::ListSpaces(const ListSpacesRequest& request,
                                   const ListSpacesCallback& callback) {
  PostTaskToWorkerThread<ListSpacesReply>(request, callback,
                                          &TpmManagerService::ListSpacesTask);
}

void TpmManagerService::ListSpacesTask(
    const ListSpacesRequest& request,
    const std::shared_ptr<ListSpacesReply>& reply) {
  VLOG(1) << __func__;
  std::vector<uint32_t> index_list;
  reply->set_result(tpm_nvram_->ListSpaces(&index_list));
  if (reply->result() == NVRAM_RESULT_SUCCESS) {
    for (auto index : index_list) {
      reply->add_index_list(index);
    }
  }
}

void TpmManagerService::GetSpaceInfo(const GetSpaceInfoRequest& request,
                                     const GetSpaceInfoCallback& callback) {
  PostTaskToWorkerThread<GetSpaceInfoReply>(
      request, callback, &TpmManagerService::GetSpaceInfoTask);
}

void TpmManagerService::GetSpaceInfoTask(
    const GetSpaceInfoRequest& request,
    const std::shared_ptr<GetSpaceInfoReply>& reply) {
  VLOG(1) << __func__;
  std::vector<NvramSpaceAttribute> attributes;
  uint32_t size = 0;
  bool is_read_locked = false;
  bool is_write_locked = false;
  NvramSpacePolicy policy = NVRAM_POLICY_NONE;
  reply->set_result(tpm_nvram_->GetSpaceInfo(request.index(), &size,
                                             &is_read_locked, &is_write_locked,
                                             &attributes, &policy));
  if (reply->result() == NVRAM_RESULT_SUCCESS) {
    reply->set_size(size);
    reply->set_is_read_locked(is_read_locked);
    reply->set_is_write_locked(is_write_locked);
    for (auto attribute : attributes) {
      reply->add_attributes(attribute);
    }
    reply->set_policy(policy);
  }
}

std::string TpmManagerService::GetOwnerPassword() {
  LocalData local_data;
  if (local_data_store_->Read(&local_data)) {
    return local_data.owner_password();
  }
  LOG(ERROR) << "TPM owner password requested but not available.";
  return std::string();
}

bool TpmManagerService::ResetDictionaryAttackCounterIfNeeded() {
  uint32_t counter = 0;
  uint32_t threshold = 0;
  bool lockout = false;
  uint32_t time_remaining = 0;
  if (!tpm_status_->GetDictionaryAttackInfo(&counter, &threshold, &lockout,
                                            &time_remaining)) {
    // Reports the metrics but no early return since reset itself might work.
    tpm_manager_metrics_->ReportDictionaryAttackResetStatus(
        DictionaryAttackResetStatus::kCounterQueryFailed);
  } else {
    tpm_manager_metrics_->ReportDictionaryAttackCounter(counter);
    if (counter == 0) {
      tpm_manager_metrics_->ReportDictionaryAttackResetStatus(
          DictionaryAttackResetStatus::kResetNotNecessary);
      return true;
    }
  }
  auto status = tpm_initializer_->ResetDictionaryAttackLock();
  tpm_manager_metrics_->ReportDictionaryAttackResetStatus(status);
  return status == DictionaryAttackResetStatus::kResetAttemptSucceeded;
}

void TpmManagerService::PeriodicResetDictionaryAttackCounterTask() {
  VLOG(1) << __func__;
  base::TimeDelta time_remaining = dictionary_attack_timer_.TimeRemaining();
  // if the timer is up, run the task and reset the timer.
  if (time_remaining.is_zero()) {
    if (!ResetDictionaryAttackCounterIfNeeded()) {
      LOG(WARNING) << __func__ << ": DA reset failed.";
    } else {
      LOG(INFO) << __func__ << ": DA reset succeeded.";
    }
    dictionary_attack_timer_.Reset();
    time_remaining = dictionary_attack_timer_.TimeRemaining();
  } else {
    LOG(INFO) << __func__ << ": Time is not up yet.";
  }
  worker_thread_->task_runner()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&TpmManagerService::PeriodicResetDictionaryAttackCounterTask,
                 base::Unretained(this)),
      time_remaining);
}

void TpmManagerService::ShutdownTask() {
  default_tpm_status_.reset();
  default_tpm_initializer_.reset();
  default_tpm_nvram_.reset();
#if USE_TPM2
  // Resets |default_trunks_factory_| last because other components hold its
  // reference.
  default_trunks_factory_.reset();
#endif
}

template <typename ReplyProtobufType>
void TpmManagerService::TaskRelayCallback(
    const base::Callback<void(const ReplyProtobufType&)> callback,
    const std::shared_ptr<ReplyProtobufType>& reply) {
  callback.Run(*reply);
}

template <typename ReplyProtobufType,
          typename RequestProtobufType,
          typename ReplyCallbackType,
          typename TaskType>
void TpmManagerService::PostTaskToWorkerThread(
    const RequestProtobufType& request,
    const ReplyCallbackType& callback,
    TaskType task) {
  auto result = std::make_shared<ReplyProtobufType>();
  base::Closure background_task =
      base::Bind(task, base::Unretained(this), request, result);
  base::Closure reply =
      base::Bind(&TpmManagerService::TaskRelayCallback<ReplyProtobufType>,
                 weak_factory_.GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, background_task,
                                                  reply);
}

template <typename ReplyProtobufType,
          typename ReplyCallbackType,
          typename TaskType>
void TpmManagerService::PostTaskToWorkerThreadWithoutRequest(
    const ReplyCallbackType& callback, TaskType task) {
  auto result = std::make_shared<ReplyProtobufType>();
  base::Closure background_task =
      base::Bind(task, base::Unretained(this), result);
  base::Closure reply =
      base::Bind(&TpmManagerService::TaskRelayCallback<ReplyProtobufType>,
                 weak_factory_.GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, background_task,
                                                  reply);
}

}  // namespace tpm_manager
