// Copyright 2019 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/client/tpm_manager_utility.h"

#include <string>

#include <base/bind.h>
#include <base/logging.h>
#include <base/message_loop/message_pump_type.h>

namespace tpm_manager {

namespace {
// Singleton and lock for TpmManagerUtility.
TpmManagerUtility* singleton;
base::Lock singleton_lock;
}  // namespace

TpmManagerUtility::TpmManagerUtility(
    tpm_manager::TpmOwnershipInterface* tpm_owner,
    tpm_manager::TpmNvramInterface* tpm_nvram)
    : tpm_owner_(tpm_owner), tpm_nvram_(tpm_nvram) {}

bool TpmManagerUtility::Initialize() {
  if (!tpm_manager_thread_.IsRunning() &&
      !tpm_manager_thread_.StartWithOptions(base::Thread::Options(
          base::MessagePumpType::IO, 0 /* Uses default stack size. */))) {
    LOG(ERROR) << "Failed to start tpm_manager thread.";
    return false;
  }
  if (!tpm_owner_ || !tpm_nvram_) {
    base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
                              base::WaitableEvent::InitialState::NOT_SIGNALED);
    tpm_manager_thread_.task_runner()->PostTask(
        FROM_HERE, base::Bind(&TpmManagerUtility::InitializationTask,
                              base::Unretained(this), &event));
    event.Wait();
  }
  if (!tpm_owner_ || !tpm_nvram_) {
    LOG(ERROR) << "Failed to initialize tpm_managerd clients.";
    return false;
  }

  return true;
}

bool TpmManagerUtility::TakeOwnership() {
  tpm_manager::TakeOwnershipRequest request;
  tpm_manager::TakeOwnershipReply reply;
  SendTpmOwnerRequestAndWait(&tpm_manager::TpmOwnershipInterface::TakeOwnership,
                             request, &reply);
  if (reply.status() != tpm_manager::STATUS_SUCCESS) {
    LOG(ERROR) << __func__ << ": Failed to take ownership.";
    return false;
  }
  return true;
}

bool TpmManagerUtility::GetTpmStatus(bool* is_enabled,
                                     bool* is_owned,
                                     LocalData* local_data) {
  tpm_manager::GetTpmStatusReply tpm_status;
  SendTpmOwnerRequestAndWait(&tpm_manager::TpmOwnershipInterface::GetTpmStatus,
                             tpm_manager::GetTpmStatusRequest(), &tpm_status);
  if (tpm_status.status() != tpm_manager::STATUS_SUCCESS) {
    LOG(ERROR) << __func__ << ": Failed to read TPM state from tpm_managerd.";
    return false;
  }
  *is_enabled = tpm_status.enabled();
  *is_owned = tpm_status.owned();
  tpm_status.mutable_local_data()->Swap(local_data);
  return true;
}

bool TpmManagerUtility::GetVersionInfo(uint32_t* family,
                                       uint64_t* spec_level,
                                       uint32_t* manufacturer,
                                       uint32_t* tpm_model,
                                       uint64_t* firmware_version,
                                       std::string* vendor_specific) {
  if (!family || !spec_level || !manufacturer || !tpm_model ||
      !firmware_version || !vendor_specific) {
    LOG(ERROR) << __func__ << ": some input args are not initialized.";
    return false;
  }

  tpm_manager::GetVersionInfoReply version_info;
  SendTpmOwnerRequestAndWait(
      &tpm_manager::TpmOwnershipInterface::GetVersionInfo,
      tpm_manager::GetVersionInfoRequest(), &version_info);
  if (version_info.status() != tpm_manager::STATUS_SUCCESS) {
    LOG(ERROR) << __func__ << ": failed to get version info from tpm_managerd.";
    return false;
  }

  *family = version_info.family();
  *spec_level = version_info.spec_level();
  *manufacturer = version_info.manufacturer();
  *tpm_model = version_info.tpm_model();
  *firmware_version = version_info.firmware_version();
  *vendor_specific = version_info.vendor_specific();
  return true;
}

bool TpmManagerUtility::RemoveOwnerDependency(const std::string& dependency) {
  tpm_manager::RemoveOwnerDependencyRequest request;
  tpm_manager::RemoveOwnerDependencyReply reply;
  request.set_owner_dependency(dependency);
  SendTpmOwnerRequestAndWait(
      &tpm_manager::TpmOwnershipInterface::RemoveOwnerDependency, request,
      &reply);
  if (reply.status() != tpm_manager::STATUS_SUCCESS) {
    LOG(ERROR) << __func__ << ": Failed to remove the dependency of "
               << dependency << ".";
    return false;
  }
  return true;
}

bool TpmManagerUtility::ClearStoredOwnerPassword() {
  tpm_manager::ClearStoredOwnerPasswordRequest request;
  tpm_manager::ClearStoredOwnerPasswordReply reply;
  SendTpmOwnerRequestAndWait(
      &tpm_manager::TpmOwnershipInterface::ClearStoredOwnerPassword, request,
      &reply);
  if (reply.status() != tpm_manager::STATUS_SUCCESS) {
    LOG(ERROR) << __func__ << ": Failed to clear owner password. ";
    return false;
  }
  return true;
}

void TpmManagerUtility::InitializationTask(base::WaitableEvent* completion) {
  CHECK(completion);
  CHECK(tpm_manager_thread_.task_runner()->BelongsToCurrentThread());

  default_tpm_owner_ = std::make_unique<tpm_manager::TpmOwnershipDBusProxy>();
  default_tpm_nvram_ = std::make_unique<tpm_manager::TpmNvramDBusProxy>();
  if (default_tpm_owner_->Initialize()) {
    default_tpm_owner_->ConnectToSignal(this);
    tpm_owner_ = default_tpm_owner_.get();
  }
  if (default_tpm_nvram_->Initialize()) {
    tpm_nvram_ = default_tpm_nvram_.get();
  }
  completion->Signal();
}

template <typename ReplyProtoType, typename MethodType>
void TpmManagerUtility::SendTpmManagerRequestAndWait(
    const MethodType& method, ReplyProtoType* reply_proto) {
  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
                            base::WaitableEvent::InitialState::NOT_SIGNALED);
  auto callback = base::Bind(
      [](ReplyProtoType* target, base::WaitableEvent* completion,
         const ReplyProtoType& reply) {
        *target = reply;
        completion->Signal();
      },
      reply_proto, &event);
  tpm_manager_thread_.task_runner()->PostTask(FROM_HERE,
                                              base::Bind(method, callback));
  event.Wait();
}

template <typename ReplyProtoType,
          typename RequestProtoType,
          typename MethodType>
void TpmManagerUtility::SendTpmOwnerRequestAndWait(
    const MethodType& method,
    const RequestProtoType& request_proto,
    ReplyProtoType* reply_proto) {
  SendTpmManagerRequestAndWait(
      base::Bind(method, base::Unretained(tpm_owner_), request_proto),
      reply_proto);
}

template <typename ReplyProtoType,
          typename RequestProtoType,
          typename MethodType>
void TpmManagerUtility::SendTpmNvramRequestAndWait(
    const MethodType& method,
    const RequestProtoType& request_proto,
    ReplyProtoType* reply_proto) {
  SendTpmManagerRequestAndWait(
      base::Bind(method, base::Unretained(tpm_nvram_), request_proto),
      reply_proto);
}

void TpmManagerUtility::ShutdownTask() {
  tpm_owner_ = nullptr;
  tpm_nvram_ = nullptr;
  default_tpm_owner_.reset(nullptr);
  default_tpm_nvram_.reset(nullptr);
}

bool TpmManagerUtility::GetDictionaryAttackInfo(int* counter,
                                                int* threshold,
                                                bool* lockout,
                                                int* seconds_remaining) {
  tpm_manager::GetDictionaryAttackInfoRequest request;
  tpm_manager::GetDictionaryAttackInfoReply reply;
  SendTpmOwnerRequestAndWait(
      &tpm_manager::TpmOwnershipInterface::GetDictionaryAttackInfo, request,
      &reply);
  if (reply.status() != tpm_manager::STATUS_SUCCESS) {
    LOG(ERROR) << __func__
               << ": Failed to retreive the dictionary attack information.";
    return false;
  }

  *counter = reply.dictionary_attack_counter();
  *threshold = reply.dictionary_attack_threshold();
  *lockout = reply.dictionary_attack_lockout_in_effect();
  *seconds_remaining = reply.dictionary_attack_lockout_seconds_remaining();

  return true;
}

bool TpmManagerUtility::ResetDictionaryAttackLock() {
  tpm_manager::ResetDictionaryAttackLockRequest request;
  tpm_manager::ResetDictionaryAttackLockReply reply;
  SendTpmOwnerRequestAndWait(
      &tpm_manager::TpmOwnershipInterface::ResetDictionaryAttackLock, request,
      &reply);
  if (reply.status() != tpm_manager::STATUS_SUCCESS) {
    LOG(ERROR) << __func__ << ": Failed to reset DA lock.";
    return false;
  }
  return true;
}

bool TpmManagerUtility::DefineSpace(uint32_t index,
                                    size_t size,
                                    bool write_define,
                                    bool bind_to_pcr0,
                                    bool firmware_readable) {
  tpm_manager::DefineSpaceRequest request;
  request.set_index(index);
  request.set_size(size);
  if (write_define) {
    request.add_attributes(tpm_manager::NVRAM_PERSISTENT_WRITE_LOCK);
  }
  if (bind_to_pcr0) {
    request.set_policy(tpm_manager::NVRAM_POLICY_PCR0);
  }
  if (firmware_readable) {
    request.add_attributes(tpm_manager::NVRAM_PLATFORM_READ);
  }
  tpm_manager::DefineSpaceReply reply;
  SendTpmNvramRequestAndWait(&tpm_manager::TpmNvramInterface::DefineSpace,
                             request, &reply);
  if (reply.result() != tpm_manager::NVRAM_RESULT_SUCCESS) {
    LOG(ERROR) << __func__
               << "Failed to define nvram space: " << reply.result();
    return false;
  }
  return true;
}

bool TpmManagerUtility::DestroySpace(uint32_t index) {
  tpm_manager::DestroySpaceRequest request;
  request.set_index(index);
  tpm_manager::DestroySpaceReply reply;
  SendTpmNvramRequestAndWait(&tpm_manager::TpmNvramInterface::DestroySpace,
                             request, &reply);
  if (reply.result() != tpm_manager::NVRAM_RESULT_SUCCESS) {
    LOG(ERROR) << __func__
               << "Failed to destroy nvram space: " << reply.result();
    return false;
  }
  return true;
}

bool TpmManagerUtility::WriteSpace(uint32_t index,
                                   const std::string& data,
                                   bool use_owner_auth) {
  tpm_manager::WriteSpaceRequest request;
  request.set_index(index);
  request.set_data(data);
  request.set_use_owner_authorization(use_owner_auth);
  tpm_manager::WriteSpaceReply reply;
  SendTpmNvramRequestAndWait(&tpm_manager::TpmNvramInterface::WriteSpace,
                             request, &reply);
  if (reply.result() == tpm_manager::NVRAM_RESULT_SPACE_DOES_NOT_EXIST) {
    LOG(ERROR) << __func__ << ": NV Index [" << index << "] does not exist.";
    return false;
  }
  if (reply.result() != tpm_manager::NVRAM_RESULT_SUCCESS) {
    LOG(ERROR) << __func__ << ": Failed to write NV index [" << index << "]"
               << reply.result();
    return false;
  }
  return true;
}

bool TpmManagerUtility::ReadSpace(uint32_t index,
                                  bool use_owner_auth,
                                  std::string* output) {
  tpm_manager::ReadSpaceRequest request;
  request.set_index(index);
  request.set_use_owner_authorization(use_owner_auth);
  tpm_manager::ReadSpaceReply reply;
  SendTpmNvramRequestAndWait(&tpm_manager::TpmNvramInterface::ReadSpace,
                             request, &reply);
  if (reply.result() == tpm_manager::NVRAM_RESULT_SPACE_DOES_NOT_EXIST) {
    LOG(ERROR) << __func__ << ": NV Index [" << index << "] does not exist.";
    return false;
  }
  if (reply.result() != tpm_manager::NVRAM_RESULT_SUCCESS) {
    LOG(ERROR) << __func__ << ": Failed to read NV index [" << index << "]"
               << reply.result();
    return false;
  }
  *output = reply.data();
  return true;
}

bool TpmManagerUtility::ListSpaces(std::vector<uint32_t>* spaces) {
  tpm_manager::ListSpacesRequest request;
  tpm_manager::ListSpacesReply reply;
  SendTpmNvramRequestAndWait(&tpm_manager::TpmNvramInterface::ListSpaces,
                             request, &reply);
  if (reply.result() != tpm_manager::NVRAM_RESULT_SUCCESS) {
    LOG(ERROR) << __func__ << "Failed to list nvram spaces: " << reply.result();
    return false;
  }
  spaces->clear();
  spaces->reserve(reply.index_list_size());
  for (int i = 0; i < reply.index_list_size(); ++i) {
    spaces->push_back(reply.index_list(i));
  }
  return true;
}

bool TpmManagerUtility::GetSpaceInfo(uint32_t index,
                                     uint32_t* size,
                                     bool* is_read_locked,
                                     bool* is_write_locked) {
  tpm_manager::GetSpaceInfoRequest request;
  request.set_index(index);
  tpm_manager::GetSpaceInfoReply reply;
  SendTpmNvramRequestAndWait(&tpm_manager::TpmNvramInterface::GetSpaceInfo,
                             request, &reply);
  if (reply.result() != tpm_manager::NVRAM_RESULT_SUCCESS) {
    LOG(ERROR) << __func__ << "Failed to get space info for space " << index
               << ": " << reply.result();
    return false;
  }
  *size = reply.size();
  *is_read_locked = reply.is_read_locked();
  *is_write_locked = reply.is_write_locked();
  return true;
}

bool TpmManagerUtility::LockSpace(uint32_t index) {
  tpm_manager::LockSpaceRequest request;
  request.set_index(index);
  request.set_lock_write(true);
  tpm_manager::LockSpaceReply reply;
  SendTpmNvramRequestAndWait(&tpm_manager::TpmNvramInterface::LockSpace,
                             request, &reply);
  if (reply.result() != tpm_manager::NVRAM_RESULT_SUCCESS) {
    LOG(ERROR) << __func__ << "Failed to lock nvram space: " << reply.result();
    return false;
  }
  return true;
}

bool TpmManagerUtility::GetOwnershipTakenSignalStatus(bool* is_successful,
                                                      bool* has_received,
                                                      LocalData* local_data) {
  base::AutoLock lock(ownership_signal_lock_);
  if (!is_connected_) {
    return false;
  }
  if (is_successful) {
    *is_successful = is_connection_successful_;
  }
  if (has_received) {
    *has_received = static_cast<bool>(ownership_taken_signal_);
  }
  // Copies |LocalData| when both the data source and destination is ready.
  if (ownership_taken_signal_ && local_data) {
    *local_data = ownership_taken_signal_->local_data();
  }
  return true;
}

void TpmManagerUtility::AddOwnershipCallback(
    OwnershipCallback ownership_callback) {
  base::AutoLock lock(ownership_callback_lock_);
  ownership_callbacks_.push_back(ownership_callback);
}

void TpmManagerUtility::OnOwnershipTaken(const OwnershipTakenSignal& signal) {
  LOG(INFO) << __func__ << ": Received |OwnershipTakenSignal|.";
  {
    base::AutoLock lock(ownership_signal_lock_);
    ownership_taken_signal_ = signal;
  }
  base::AutoLock lock(ownership_callback_lock_);
  for (auto& callback : ownership_callbacks_) {
    callback.Run();
  }
}

void TpmManagerUtility::OnSignalConnected(const std::string& /*interface_name*/,
                                          const std::string& /*signal_name*/,
                                          bool is_successful) {
  if (!is_successful) {
    LOG(ERROR) << __func__ << ": Failed to connect dbus signal.";
  } else {
    LOG(INFO) << __func__ << ": Connected dbus signal successfully.";
  }
  base::AutoLock lock(ownership_signal_lock_);
  is_connected_ = true;
  is_connection_successful_ = is_successful;
}

TpmManagerUtility* TpmManagerUtility::GetSingleton() {
  base::AutoLock lock(singleton_lock);
  if (!singleton) {
    singleton = new TpmManagerUtility();
    if (!singleton->Initialize()) {
      delete singleton;
      singleton = nullptr;
    }
  }
  return singleton;
}

}  // namespace tpm_manager
