// Copyright 2015 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Contains the implementation of class Tpm

#include "cryptohome/tpm2_impl.h"

#include <cinttypes>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/check.h>
#include <base/logging.h>
#include <base/message_loop/message_pump_type.h>
#include <base/notreached.h>
#include <base/numerics/safe_conversions.h>
#include <base/strings/stringprintf.h>
#include <crypto/libcrypto-compat.h>
#include <crypto/scoped_openssl_types.h>
#include <libhwsec/error/tpm_retry_handler.h>
#include <libhwsec/error/tpm2_error.h>
#include <libhwsec/status.h>
#include <libhwsec/factory/factory_impl.h>
#include <libhwsec-foundation/crypto/aes.h>
#include <libhwsec-foundation/crypto/big_num_util.h>
#include <libhwsec-foundation/crypto/elliptic_curve.h>
#include <libhwsec-foundation/crypto/rsa.h>
#include <libhwsec-foundation/crypto/sha.h>
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>
#include <tpm_manager-client/tpm_manager/dbus-constants.h>
#include <trunks/authorization_delegate.h>
#include <trunks/blob_parser.h>
#include <trunks/error_codes.h>
#include <trunks/openssl_utility.h>
#include <trunks/policy_session.h>
#include <trunks/tpm_alerts.h>
#include <trunks/tpm_constants.h>
#include <trunks/trunks_dbus_proxy.h>
#include <trunks/trunks_factory.h>
#include <trunks/trunks_factory_impl.h>

using brillo::Blob;
using brillo::BlobFromString;
using brillo::BlobToString;
using brillo::SecureBlob;
using hwsec::TPM2Error;
using hwsec::TPMError;
using hwsec::TPMErrorBase;
using hwsec::TPMRetryAction;
using hwsec_foundation::CreateBigNumContext;
using hwsec_foundation::EllipticCurve;
using hwsec_foundation::ObscureRsaMessage;
using hwsec_foundation::PasskeyToAesKey;
using hwsec_foundation::ScopedBN_CTX;
using hwsec_foundation::SecureBlobToBigNum;
using hwsec_foundation::Sha256;
using hwsec_foundation::UnobscureRsaMessage;
using hwsec_foundation::error::CreateError;
using hwsec_foundation::error::WrapError;
using trunks::GetErrorString;
using trunks::TPM_RC_SUCCESS;
using trunks::TrunksFactory;

namespace cryptohome {

namespace {

constexpr trunks::TPMI_ECC_CURVE kDefaultTpmCurveId = trunks::TPM_ECC_NIST_P256;

constexpr EllipticCurve::CurveType kDefaultCurve =
    EllipticCurve::CurveType::kPrime256;

constexpr int kMinPassBlobSize = 32;

// Returns the total number of bits set in the first |size| elements from
// |array|.
int CountSetBits(const uint8_t* array, size_t size) {
  int res = 0;
  for (size_t i = 0; i < size; ++i) {
    for (int bit_position = 0; bit_position < 8; ++bit_position) {
      if ((array[i] & (1 << bit_position)) != 0) {
        ++res;
      }
    }
  }
  return res;
}

std::string OwnerDependencyEnumClassToString(
    Tpm::TpmOwnerDependency dependency) {
  switch (dependency) {
    case Tpm::TpmOwnerDependency::kInstallAttributes:
      return tpm_manager::kTpmOwnerDependency_Nvram;
    case Tpm::TpmOwnerDependency::kAttestation:
      return tpm_manager::kTpmOwnerDependency_Attestation;
    default:
      NOTREACHED() << __func__ << ": Unexpected enum class value: "
                   << static_cast<int>(dependency);
      return "";
  }
}

trunks::TpmUtility::AsymmetricKeyUsage ConvertAsymmetricKeyUsage(
    AsymmetricKeyUsage usage) {
  switch (usage) {
    case AsymmetricKeyUsage::kDecryptKey:
      return trunks::TpmUtility::AsymmetricKeyUsage::kDecryptKey;
    case AsymmetricKeyUsage::kSignKey:
      return trunks::TpmUtility::AsymmetricKeyUsage::kSignKey;
    case AsymmetricKeyUsage::kDecryptAndSignKey:
      return trunks::TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey;
    default:
      NOTREACHED() << __func__ << ": Unexpected enum class value: "
                   << static_cast<int>(usage);
      return trunks::TpmUtility::AsymmetricKeyUsage::kDecryptKey;
  }
}

hwsec::Status DeriveTpmEccPointFromSeed(const SecureBlob& seed,
                                        trunks::TPMS_ECC_POINT* out_point) {
  // Generate an ECC private key (scalar) based on the seed.
  crypto::ScopedBIGNUM private_key = SecureBlobToBigNum(Sha256(seed));

  ScopedBN_CTX context = CreateBigNumContext();
  if (!context.get()) {
    return CreateError<TPMError>("Failed to allocate BN_CTX structure",
                                 TPMRetryAction::kNoRetry);
  }

  std::optional<EllipticCurve> ec =
      EllipticCurve::Create(kDefaultCurve, context.get());
  if (!ec) {
    return CreateError<TPMError>("Failed to create EllipticCurve",
                                 TPMRetryAction::kNoRetry);
  }

  if (!ec->IsScalarValid(*private_key)) {
    // Generate another pass_blob may resolve this issue.
    return CreateError<TPMError>(
        "ECC scalar out of range",
        TPMRetryAction::kEllipticCurveScalarOutOfRange);
  }

  crypto::ScopedEC_POINT public_point =
      ec->MultiplyWithGenerator(*private_key, context.get());

  if (!public_point) {
    return CreateError<TPMError>("Failed to multiply with generator",
                                 TPMRetryAction::kNoRetry);
  }

  if (!trunks::OpensslToTpmEccPoint(*ec->GetGroup(), *public_point,
                                    ec->AffineCoordinateSizeInBytes(),
                                    out_point)) {
    return CreateError<TPMError>("Error converting OpenSSL to TPM ECC point",
                                 TPMRetryAction::kNoRetry);
  }

  return nullptr;
}

std::map<uint32_t, std::string> ToStrPcrMap(
    const std::map<uint32_t, brillo::Blob>& pcr_map) {
  std::map<uint32_t, std::string> str_pcr_map;
  for (const auto& [index, value] : pcr_map) {
    str_pcr_map[index] = brillo::BlobToString(value);
  }
  return str_pcr_map;
}
}  // namespace

Tpm2Impl::Tpm2Impl()
    : hwsec_factory_(std::make_unique<hwsec::FactoryImpl>()),
      hwsec_(hwsec_factory_->GetCryptohomeFrontend()),
      pinweaver_(hwsec_factory_->GetPinWeaverFrontend()),
      recovery_crypto_(hwsec_factory_->GetRecoveryCryptoFrontend()) {}

Tpm2Impl::Tpm2Impl(std::unique_ptr<hwsec::CryptohomeFrontend> hwsec,
                   trunks::TrunksFactory* factory,
                   tpm_manager::TpmManagerUtility* tpm_manager_utility)
    : tpm_manager_utility_(tpm_manager_utility),
      has_external_trunks_context_(true),
      hwsec_(std::move(hwsec)) {
  external_trunks_context_.factory = factory;
  external_trunks_context_.tpm_state = factory->GetTpmState();
  external_trunks_context_.tpm_utility = factory->GetTpmUtility();
}

bool Tpm2Impl::InitializeTpmManagerUtility() {
  if (!tpm_manager_utility_) {
    tpm_manager_utility_ = tpm_manager::TpmManagerUtility::GetSingleton();
    if (!tpm_manager_utility_) {
      LOG(ERROR) << __func__ << ": Failed to get TpmManagerUtility singleton!";
    }
  }
  return tpm_manager_utility_ && tpm_manager_utility_->Initialize();
}

bool Tpm2Impl::CacheTpmManagerStatus() {
  if (!InitializeTpmManagerUtility()) {
    LOG(ERROR) << __func__ << ": Failed to initialize |TpmManagerUtility|.";
    return false;
  }
  return tpm_manager_utility_->GetTpmStatus(&is_enabled_, &is_owned_,
                                            &last_tpm_manager_data_);
}

bool Tpm2Impl::IsEnabled() {
  if (!is_enabled_) {
    if (!CacheTpmManagerStatus()) {
      LOG(ERROR) << __func__ << ": Failed to call |UpdateTpmStatus|.";
      return false;
    }
  }
  return is_enabled_;
}

bool Tpm2Impl::IsOwned() {
  if (!is_owned_) {
    if (!UpdateTpmStatus(RefreshType::REFRESH_IF_NEEDED)) {
      LOG(ERROR) << __func__ << ": Failed to call |UpdateTpmStatus|.";
      return false;
    }
  }
  return is_owned_;
}

bool Tpm2Impl::IsOwnerPasswordPresent() {
  if (!InitializeTpmManagerUtility()) {
    LOG(ERROR) << __func__ << ": failed to initialize |TpmManagerUtility|.";
    return false;
  }
  bool is_owner_password_present = false;
  if (!tpm_manager_utility_->GetTpmNonsensitiveStatus(
          nullptr, nullptr, &is_owner_password_present, nullptr)) {
    LOG(ERROR) << __func__ << ": Failed to get |is_owner_password_present|.";
    return false;
  }
  return is_owner_password_present;
}

bool Tpm2Impl::HasResetLockPermissions() {
  if (!InitializeTpmManagerUtility()) {
    LOG(ERROR) << __func__ << ": failed to initialize |TpmManagerUtility|.";
    return false;
  }
  bool has_reset_lock_permissions = false;
  if (!tpm_manager_utility_->GetTpmNonsensitiveStatus(
          nullptr, nullptr, nullptr, &has_reset_lock_permissions)) {
    LOG(ERROR) << __func__ << ": Failed to get |has_reset_lock_permissions|.";
    return false;
  }
  return has_reset_lock_permissions;
}

hwsec::Status Tpm2Impl::GetRandomDataBlob(size_t length, brillo::Blob* data) {
  brillo::SecureBlob blob(length);
  if (hwsec::Status err = GetRandomDataSecureBlob(length, &blob); !err.ok()) {
    return WrapError<TPMError>(std::move(err), "GetRandomDataBlob failed");
  }
  data->assign(blob.begin(), blob.end());
  return nullptr;
}

hwsec::Status Tpm2Impl::GetRandomDataSecureBlob(size_t length,
                                                brillo::SecureBlob* data) {
  CHECK(data);
  TrunksClientContext* trunks;
  if (!GetTrunksContext(&trunks)) {
    return CreateError<TPMError>("Failed to get trunks context",
                                 TPMRetryAction::kNoRetry);
  }
  std::string random_data;
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(trunks->tpm_utility->GenerateRandom(
              length, /* delegate */ nullptr, &random_data)));
      !err.ok()) {
    return WrapError<TPMError>(std::move(err), "Error getting random data");
  }
  if (random_data.size() != length) {
    return CreateError<TPMError>(
        base::StringPrintf("Error getting random data: requested length %zu"
                           ", received length %zu",
                           length, random_data.size()),
        TPMRetryAction::kNoRetry);
  }
  data->assign(random_data.begin(), random_data.end());
  return nullptr;
}

bool Tpm2Impl::DefineNvram(uint32_t index, size_t length, uint32_t flags) {
  if (!InitializeTpmManagerUtility()) {
    LOG(ERROR) << __func__ << ": Failed to initialize |TpmManagerUtility|.";
    return false;
  }
  const bool write_define = flags & Tpm::kTpmNvramWriteDefine;
  const bool bind_to_pcr0 = flags & Tpm::kTpmNvramBindToPCR0;
  const bool firmware_readable = flags & Tpm::kTpmNvramFirmwareReadable;

  return tpm_manager_utility_->DefineSpace(index, length, write_define,
                                           bind_to_pcr0, firmware_readable);
}

bool Tpm2Impl::DestroyNvram(uint32_t index) {
  if (!InitializeTpmManagerUtility()) {
    LOG(ERROR) << __func__ << ": Failed to initialize |TpmManagerUtility|.";
    return false;
  }
  return tpm_manager_utility_->DestroySpace(index);
}

bool Tpm2Impl::WriteNvram(uint32_t index, const SecureBlob& blob) {
  if (!InitializeTpmManagerUtility()) {
    LOG(ERROR) << __func__ << ": Failed to initialize |TpmManagerUtility|.";
    return false;
  }
  return tpm_manager_utility_->WriteSpace(index, blob.to_string(),
                                          /*use_owner_auth=*/false);
}

bool Tpm2Impl::OwnerWriteNvram(uint32_t index, const SecureBlob& blob) {
  if (!InitializeTpmManagerUtility()) {
    LOG(ERROR) << __func__ << ": Failed to initialize |TpmManagerUtility|.";
    return false;
  }
  return tpm_manager_utility_->WriteSpace(index, blob.to_string(),
                                          /*use_owner_auth=*/true);
}

bool Tpm2Impl::ReadNvram(uint32_t index, SecureBlob* blob) {
  if (!InitializeTpmManagerUtility()) {
    return false;
  }

  std::string output;
  const bool result = tpm_manager_utility_->ReadSpace(index, false, &output);
  SecureBlob tmp(output);
  blob->swap(tmp);
  return result;
}

bool Tpm2Impl::IsNvramDefined(uint32_t index) {
  if (!InitializeTpmManagerUtility()) {
    LOG(ERROR) << __func__ << ": Failed to initialize |TpmManagerUtility|.";
    return false;
  }
  std::vector<uint32_t> spaces;
  if (!tpm_manager_utility_->ListSpaces(&spaces)) {
    return false;
  }
  for (uint32_t space : spaces) {
    if (index == space) {
      return true;
    }
  }
  return false;
}

bool Tpm2Impl::IsNvramLocked(uint32_t index) {
  if (!InitializeTpmManagerUtility()) {
    LOG(ERROR) << __func__ << ": Failed to initialize |TpmManagerUtility|.";
    return false;
  }
  uint32_t size;
  bool is_read_locked;
  bool is_write_locked;
  if (!tpm_manager_utility_->GetSpaceInfo(index, &size, &is_read_locked,
                                          &is_write_locked,
                                          /*attributes=*/nullptr)) {
    return false;
  }
  return is_write_locked;
}

bool Tpm2Impl::WriteLockNvram(uint32_t index) {
  if (!InitializeTpmManagerUtility()) {
    LOG(ERROR) << __func__ << ": Failed to initialize |TpmManagerUtility|.";
    return false;
  }
  return tpm_manager_utility_->LockSpace(index);
}

unsigned int Tpm2Impl::GetNvramSize(uint32_t index) {
  if (!InitializeTpmManagerUtility()) {
    LOG(ERROR) << __func__ << ": Failed to initialize |TpmManagerUtility|.";
    return false;
  }
  uint32_t size;
  bool is_read_locked;
  bool is_write_locked;
  if (!tpm_manager_utility_->GetSpaceInfo(index, &size, &is_read_locked,
                                          &is_write_locked,
                                          /*attributes=*/nullptr)) {
    return 0;
  }
  return size;
}

bool Tpm2Impl::Sign(const SecureBlob& key_blob,
                    const SecureBlob& input,
                    uint32_t bound_pcr_index,
                    SecureBlob* signature) {
  TrunksClientContext* trunks;
  if (!GetTrunksContext(&trunks)) {
    return false;
  }
  trunks::AuthorizationDelegate* delegate;
  std::unique_ptr<trunks::PolicySession> policy_session;
  std::unique_ptr<trunks::HmacSession> hmac_session;
  if (bound_pcr_index != kNotBoundToPCR) {
    policy_session = trunks->factory->GetPolicySession();
    if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(CreateError<TPM2Error>(
            policy_session->StartUnboundSession(true, false)));
        !err.ok()) {
      LOG(ERROR) << "Error starting policy session: " << err;
      return false;
    }
    if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
            CreateError<TPM2Error>(policy_session->PolicyPCR(
                std::map<uint32_t, std::string>({{bound_pcr_index, ""}}))));
        !err.ok()) {
      LOG(ERROR) << "Error creating PCR policy: " << err;
      return false;
    }
    delegate = policy_session->GetDelegate();
  } else {
    hmac_session = trunks->factory->GetHmacSession();
    if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(CreateError<TPM2Error>(
            hmac_session->StartUnboundSession(true, true)));
        !err.ok()) {
      LOG(ERROR) << "Error starting hmac session: " << err;
      return false;
    }
    hmac_session->SetEntityAuthorizationValue("");
    delegate = hmac_session->GetDelegate();
  }

  ScopedKeyHandle handle;
  if (hwsec::Status err = LoadWrappedKey(key_blob, &handle); !err.ok()) {
    LOG(ERROR) << "Error loading pcr bound key: " << err;
    return false;
  }
  std::string tpm_signature;
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(trunks->tpm_utility->Sign(
              handle.value(), trunks::TPM_ALG_RSASSA, trunks::TPM_ALG_SHA256,
              input.to_string(), true /* generate_hash */, delegate,
              &tpm_signature)));
      !err.ok()) {
    LOG(ERROR) << "Error signing: " << err;
    return false;
  }
  signature->assign(tpm_signature.begin(), tpm_signature.end());
  return true;
}

bool Tpm2Impl::CreatePCRBoundKey(
    const std::map<uint32_t, brillo::Blob>& pcr_map,
    AsymmetricKeyUsage key_type,
    SecureBlob* key_blob,
    SecureBlob* public_key_der,
    SecureBlob* creation_blob) {
  CHECK(key_blob) << "No key blob argument provided.";
  CHECK(creation_blob) << "No creation blob argument provided.";
  TrunksClientContext* trunks;
  if (!GetTrunksContext(&trunks)) {
    return false;
  }
  std::string policy_digest;
  std::map<uint32_t, std::string> str_pcr_map = ToStrPcrMap(pcr_map);
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(CreateError<TPM2Error>(
          trunks->tpm_utility->GetPolicyDigestForPcrValues(
              str_pcr_map, false /* use_auth_value */, &policy_digest)));
      !err.ok()) {
    LOG(ERROR) << "Error getting policy digest: " << err;
    return false;
  }
  std::vector<uint32_t> pcr_list;
  for (const auto& map_pair : pcr_map) {
    pcr_list.push_back(map_pair.first);
  }
  std::string tpm_key_blob;
  std::string tpm_creation_blob;
  std::unique_ptr<trunks::AuthorizationDelegate> delegate =
      trunks->factory->GetPasswordAuthorization("");
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(trunks->tpm_utility->CreateRSAKeyPair(
              ConvertAsymmetricKeyUsage(key_type), kDefaultTpmRsaModulusSize,
              kDefaultTpmPublicExponent,
              "",  // No authorization
              policy_digest,
              true,  // use_only_policy_authorization
              pcr_list, delegate.get(), &tpm_key_blob,
              &tpm_creation_blob /* No creation_blob */)));
      !err.ok()) {
    LOG(ERROR) << "Error creating a pcr bound key: " << err;
    return false;
  }
  key_blob->assign(tpm_key_blob.begin(), tpm_key_blob.end());
  creation_blob->assign(tpm_creation_blob.begin(), tpm_creation_blob.end());

  // if |public_key_der| is present, create and assign it.
  if (public_key_der) {
    trunks::TPM2B_PUBLIC public_data;
    trunks::TPM2B_PRIVATE private_data;
    if (!trunks->factory->GetBlobParser()->ParseKeyBlob(
            key_blob->to_string(), &public_data, &private_data)) {
      return false;
    }
    if (!PublicAreaToPublicKeyDER(public_data.public_area, public_key_der)) {
      return false;
    }
  }
  return true;
}

bool Tpm2Impl::VerifyPCRBoundKey(
    const std::map<uint32_t, brillo::Blob>& pcr_map,
    const SecureBlob& key_blob,
    const SecureBlob& creation_blob) {
  TrunksClientContext* trunks;
  if (!GetTrunksContext(&trunks)) {
    return false;
  }
  // First we verify that the PCR were in a known good state at the time of
  // Key creation.
  trunks::TPM2B_CREATION_DATA creation_data;
  trunks::TPM2B_DIGEST creation_hash;
  trunks::TPMT_TK_CREATION creation_ticket;
  if (!trunks->factory->GetBlobParser()->ParseCreationBlob(
          creation_blob.to_string(), &creation_data, &creation_hash,
          &creation_ticket)) {
    LOG(ERROR) << "Error parsing creation_blob.";
    return false;
  }
  trunks::TPML_PCR_SELECTION& pcr_select =
      creation_data.creation_data.pcr_select;
  if (pcr_select.count != 1) {
    LOG(ERROR) << "Creation data missing creation PCR value.";
    return false;
  }
  if (pcr_select.pcr_selections[0].hash != trunks::TPM_ALG_SHA256) {
    LOG(ERROR) << "Creation PCR extended with wrong hash algorithm.";
    return false;
  }
  uint8_t* pcr_selections = pcr_select.pcr_selections[0].pcr_select;
  if (pcr_map.size() != CountSetBits(pcr_selections, PCR_SELECT_MIN)) {
    LOG(ERROR) << "Incorrect creation PCR specified.";
    return false;
  }
  brillo::Blob concatenated_pcr_values;
  for (const auto& map_pair : pcr_map) {
    uint32_t pcr_index = map_pair.first;
    const brillo::Blob& pcr_value = map_pair.second;
    if (pcr_index >= 8 * PCR_SELECT_MIN ||
        (pcr_selections[pcr_index / 8] & (1 << (pcr_index % 8))) == 0) {
      LOG(ERROR) << "Incorrect creation PCR specified.";
      return false;
    }
    concatenated_pcr_values.insert(concatenated_pcr_values.end(),
                                   pcr_value.begin(), pcr_value.end());
  }
  Blob expected_pcr_digest = Sha256(concatenated_pcr_values);
  if (creation_data.creation_data.pcr_digest.size !=
      expected_pcr_digest.size()) {
    LOG(ERROR) << "Incorrect PCR digest size.";
    return false;
  }
  if (memcmp(creation_data.creation_data.pcr_digest.buffer,
             expected_pcr_digest.data(), expected_pcr_digest.size()) != 0) {
    LOG(ERROR) << "Incorrect PCR digest value.";
    return false;
  }
  // Then we certify that the key was created by the TPM.
  ScopedKeyHandle scoped_handle;
  if (hwsec::Status err = LoadWrappedKey(key_blob, &scoped_handle); !err.ok()) {
    LOG(ERROR) << "Failed to load wrapped key: " << err;
    return false;
  }
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(trunks->tpm_utility->CertifyCreation(
              scoped_handle.value(), creation_blob.to_string())));
      !err.ok()) {
    LOG(ERROR) << "Error certifying that key was created by TPM: " << err;
    return false;
  }
  // Finally we verify that the key's policy_digest is the expected value.
  std::unique_ptr<trunks::PolicySession> trial_session =
      trunks->factory->GetTrialSession();
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(CreateError<TPM2Error>(
          trial_session->StartUnboundSession(true, true)));
      !err.ok()) {
    LOG(ERROR) << "Error starting a trial session: " << err;
    return false;
  }
  std::map<uint32_t, std::string> str_pcr_map = ToStrPcrMap(pcr_map);
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(trial_session->PolicyPCR(str_pcr_map)));
      !err.ok()) {
    LOG(ERROR) << "Error restricting trial policy to pcr value: " << err;
    return false;
  }
  std::string policy_digest;
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(trial_session->GetDigest(&policy_digest)));
      !err.ok()) {
    LOG(ERROR) << "Error getting policy digest: " << err;
    return false;
  }
  trunks::TPMT_PUBLIC public_area;
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(trunks->tpm_utility->GetKeyPublicArea(
              scoped_handle.value(), &public_area)));
      !err.ok()) {
    LOG(ERROR) << "Error getting key public area: " << err;
    return false;
  }
  if (public_area.auth_policy.size != policy_digest.size()) {
    LOG(ERROR) << "Key auth policy and policy digest are of different length."
               << public_area.auth_policy.size << "," << policy_digest.size();
    return false;
  } else if (memcmp(public_area.auth_policy.buffer, policy_digest.data(),
                    policy_digest.size()) != 0) {
    LOG(ERROR) << "Key auth policy is different from policy digest.";
    return false;
  } else if (public_area.object_attributes & trunks::kUserWithAuth) {
    LOG(ERROR) << "Key authorization is not restricted to policy.";
    return false;
  }
  return true;
}

bool Tpm2Impl::ExtendPCR(uint32_t pcr_index, const Blob& extension) {
  TrunksClientContext* trunks;
  if (!GetTrunksContext(&trunks)) {
    return false;
  }
  std::unique_ptr<trunks::AuthorizationDelegate> delegate =
      trunks->factory->GetPasswordAuthorization("");
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(trunks->tpm_utility->ExtendPCR(
              pcr_index, BlobToString(extension), delegate.get())));
      !err.ok()) {
    LOG(ERROR) << "Error extending PCR: " << err;
    return false;
  }
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(trunks->tpm_utility->ExtendPCRForCSME(
              pcr_index, BlobToString(extension))));
      !err.ok()) {
    LOG(ERROR) << "Error extending PCR for CSME: " << err;
    return false;
  }
  return true;
}

bool Tpm2Impl::ReadPCR(uint32_t pcr_index, Blob* pcr_value) {
  CHECK(pcr_value);
  TrunksClientContext* trunks;
  if (!GetTrunksContext(&trunks)) {
    return false;
  }
  std::string pcr_digest;
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(CreateError<TPM2Error>(
          trunks->tpm_utility->ReadPCR(pcr_index, &pcr_digest)));
      !err.ok()) {
    LOG(ERROR) << "Error reading from PCR: " << err;
    return false;
  }
  *pcr_value = BlobFromString(pcr_digest);
  return true;
}

bool Tpm2Impl::WrapRsaKey(const SecureBlob& public_modulus,
                          const SecureBlob& prime_factor,
                          SecureBlob* wrapped_key) {
  TrunksClientContext* trunks;
  if (!GetTrunksContext(&trunks)) {
    return false;
  }
  std::string key_blob;
  std::unique_ptr<trunks::AuthorizationDelegate> delegate =
      trunks->factory->GetPasswordAuthorization("");
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(trunks->tpm_utility->ImportRSAKey(
              trunks::TpmUtility::AsymmetricKeyUsage::kDecryptKey,
              public_modulus.to_string(), kDefaultTpmPublicExponent,
              prime_factor.to_string(),
              "",  // No authorization,
              delegate.get(), &key_blob)));
      !err.ok()) {
    LOG(ERROR) << "Error creating SRK wrapped key: " << err;
    return false;
  }
  wrapped_key->assign(key_blob.begin(), key_blob.end());
  return true;
}

bool Tpm2Impl::CreateWrappedEccKey(SecureBlob* wrapped_key) {
  CHECK(wrapped_key) << "No key blob argument provided.";
  TrunksClientContext* trunks;
  if (!GetTrunksContext(&trunks)) {
    return false;
  }
  std::vector<uint32_t> pcr_list;
  std::string tpm_key_blob;
  std::string tpm_creation_blob;
  std::unique_ptr<trunks::AuthorizationDelegate> delegate =
      trunks->factory->GetPasswordAuthorization("");
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(trunks->tpm_utility->CreateECCKeyPair(
              trunks::TpmUtility::kDecryptKey, kDefaultTpmCurveId,
              "",     // No authorization
              "",     // No policy digest
              false,  // use_only_policy_authorization
              pcr_list, delegate.get(), &tpm_key_blob,
              &tpm_creation_blob /* No creation_blob */)));
      !err.ok()) {
    LOG(ERROR) << "Error creating a pcr bound key: " << err;
    return false;
  }
  wrapped_key->assign(tpm_key_blob.begin(), tpm_key_blob.end());

  return true;
}

hwsec::Status Tpm2Impl::LoadWrappedKey(const SecureBlob& wrapped_key,
                                       ScopedKeyHandle* key_handle) {
  CHECK(key_handle);
  TrunksClientContext* trunks;
  if (!GetTrunksContext(&trunks)) {
    return CreateError<TPMError>("Failed to get trunks context",
                                 TPMRetryAction::kNoRetry);
  }
  trunks::TPM_HANDLE handle;
  std::unique_ptr<trunks::AuthorizationDelegate> delegate =
      trunks->factory->GetPasswordAuthorization("");
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(trunks->tpm_utility->LoadKey(
              wrapped_key.to_string(), delegate.get(), &handle)));
      !err.ok()) {
    return WrapError<TPMError>(std::move(err), "Error loading SRK wrapped key");
  }
  key_handle->reset(this, handle);
  return nullptr;
}

void Tpm2Impl::CloseHandle(TpmKeyHandle key_handle) {
  TrunksClientContext* trunks;
  if (!GetTrunksContext(&trunks)) {
    return;
  }
  trunks->factory->GetTpm()->FlushContext(
      key_handle, nullptr,
      base::BindRepeating(
          [](TpmKeyHandle key_handle, trunks::TPM_RC result) {
            if (hwsec::Status err = CreateError<TPM2Error>(result); !err.ok()) {
              LOG(WARNING) << "Error flushing tpm handle " << key_handle << ": "
                           << err;
            }
          },
          key_handle));
}

hwsec::Status Tpm2Impl::EncryptBlob(TpmKeyHandle key_handle,
                                    const SecureBlob& plaintext,
                                    const SecureBlob& key,
                                    SecureBlob* ciphertext) {
  CHECK(ciphertext);
  TrunksClientContext* trunks;
  if (!GetTrunksContext(&trunks)) {
    return CreateError<TPMError>("Failed to get trunks context",
                                 TPMRetryAction::kNoRetry);
  }
  std::string tpm_ciphertext;
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(trunks->tpm_utility->AsymmetricEncrypt(
              key_handle, trunks::TPM_ALG_OAEP, trunks::TPM_ALG_SHA256,
              plaintext.to_string(), nullptr, &tpm_ciphertext)));
      !err.ok()) {
    return WrapError<TPMError>(std::move(err), "Error encrypting plaintext");
  }
  if (!ObscureRsaMessage(SecureBlob(tpm_ciphertext), key, ciphertext)) {
    return CreateError<TPMError>("Error obscuring tpm encrypted blob",
                                 TPMRetryAction::kNoRetry);
  }
  return nullptr;
}

hwsec::Status Tpm2Impl::DecryptBlob(TpmKeyHandle key_handle,
                                    const SecureBlob& ciphertext,
                                    const SecureBlob& key,
                                    SecureBlob* plaintext) {
  CHECK(plaintext);
  TrunksClientContext* trunks;
  if (!GetTrunksContext(&trunks)) {
    return CreateError<TPMError>("Failed to get trunks context",
                                 TPMRetryAction::kNoRetry);
  }
  SecureBlob local_data;
  if (!UnobscureRsaMessage(ciphertext, key, &local_data)) {
    return CreateError<TPMError>("Error unobscureing message",
                                 TPMRetryAction::kNoRetry);
  }

  std::unique_ptr<trunks::AuthorizationDelegate> delegate =
      trunks->factory->GetPasswordAuthorization("");

  std::string tpm_plaintext;
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(trunks->tpm_utility->AsymmetricDecrypt(
              key_handle, trunks::TPM_ALG_OAEP, trunks::TPM_ALG_SHA256,
              local_data.to_string(), delegate.get(), &tpm_plaintext)));
      !err.ok()) {
    return WrapError<TPMError>(std::move(err), "Error decrypting plaintext");
  }
  plaintext->assign(tpm_plaintext.begin(), tpm_plaintext.end());
  return nullptr;
}

hwsec::Status Tpm2Impl::SealToPcrWithAuthorization(
    const SecureBlob& plaintext,
    const SecureBlob& auth_value,
    const std::map<uint32_t, brillo::Blob>& pcr_map,
    SecureBlob* sealed_data) {
  TrunksClientContext* trunks;
  if (!GetTrunksContext(&trunks)) {
    return CreateError<TPMError>("Failed to get trunks context",
                                 TPMRetryAction::kNoRetry);
  }

  std::map<uint32_t, std::string> str_pcr_map = ToStrPcrMap(pcr_map);

  // Get the policy digest for PCR.
  std::string policy_digest;
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(CreateError<TPM2Error>(
          trunks->tpm_utility->GetPolicyDigestForPcrValues(
              str_pcr_map, true /* use_auth_value */, &policy_digest)));
      !err.ok()) {
    return WrapError<TPMError>(std::move(err), "Error getting policy digest");
  }

  std::unique_ptr<trunks::HmacSession> session =
      trunks->factory->GetHmacSession();
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(session->StartUnboundSession(true, true)));
      !err.ok()) {
    return WrapError<TPMError>(std::move(err), "Error starting hmac session");
  }

  std::string sealed_str;
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(trunks->tpm_utility->SealData(
              plaintext.to_string(), policy_digest, auth_value.to_string(),
              /*require_admin_with_policy=*/true, session->GetDelegate(),
              &sealed_str)));
      !err.ok()) {
    return WrapError<TPMError>(std::move(err),
                               "Error sealing data to PCR with authorization");
  }
  sealed_data->assign(sealed_str.begin(), sealed_str.end());

  return nullptr;
}

hwsec::Status Tpm2Impl::PreloadSealedData(const brillo::SecureBlob& sealed_data,
                                          ScopedKeyHandle* preload_handle) {
  if (hwsec::Status err = LoadWrappedKey(sealed_data, preload_handle);
      !err.ok()) {
    return WrapError<TPMError>(std::move(err), "Failed to load sealed data");
  }
  return nullptr;
}

hwsec::Status Tpm2Impl::UnsealWithAuthorization(
    std::optional<TpmKeyHandle> preload_handle,
    const SecureBlob& sealed_data,
    const SecureBlob& auth_value,
    const std::map<uint32_t, brillo::Blob>& pcr_map,
    SecureBlob* plaintext) {
  TrunksClientContext* trunks;
  if (!GetTrunksContext(&trunks)) {
    return CreateError<TPMError>("Failed to get trunks context",
                                 TPMRetryAction::kNoRetry);
  }

  std::unique_ptr<trunks::PolicySession> policy_session =
      trunks->factory->GetPolicySession();
  // Use unsalted session here, to unseal faster.
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(CreateError<TPM2Error>(
          policy_session->StartUnboundSession(false, false)));
      !err.ok()) {
    return WrapError<TPMError>(std::move(err), "Error starting policy session");
  }
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(policy_session->PolicyAuthValue()));
      !err.ok()) {
    return WrapError<TPMError>(std::move(err),
                               "Error setting session to use auth_value");
  }

  std::map<uint32_t, std::string> str_pcr_map = ToStrPcrMap(pcr_map);
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(policy_session->PolicyPCR(str_pcr_map)));
      !err.ok()) {
    return WrapError<TPMError>(std::move(err), "Error in PolicyPCR");
  }
  policy_session->SetEntityAuthorizationValue(auth_value.to_string());
  std::string unsealed_data;
  if (preload_handle) {
    if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
            CreateError<TPM2Error>(trunks->tpm_utility->UnsealDataWithHandle(
                *preload_handle, policy_session->GetDelegate(),
                &unsealed_data)));
        !err.ok()) {
      return WrapError<TPMError>(std::move(err),
                                 "Error unsealing data with authorization");
    }
  } else {
    if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
            CreateError<TPM2Error>(trunks->tpm_utility->UnsealData(
                sealed_data.to_string(), policy_session->GetDelegate(),
                &unsealed_data)));
        !err.ok()) {
      return WrapError<TPMError>(std::move(err),
                                 "Error unsealing data with authorization");
    }
  }
  plaintext->assign(unsealed_data.begin(), unsealed_data.end());

  return nullptr;
}

hwsec::Status Tpm2Impl::GetPublicKeyHash(TpmKeyHandle key_handle,
                                         SecureBlob* hash) {
  CHECK(hash);
  TrunksClientContext* trunks;
  if (!GetTrunksContext(&trunks)) {
    return CreateError<TPMError>("Failed to get trunks context",
                                 TPMRetryAction::kNoRetry);
  }
  trunks::TPMT_PUBLIC public_data;
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(CreateError<TPM2Error>(
          trunks->tpm_utility->GetKeyPublicArea(key_handle, &public_data)));
      !err.ok()) {
    return WrapError<TPMError>(std::move(err), "Error getting key public area");
  }
  std::string public_modulus =
      trunks::StringFrom_TPM2B_PUBLIC_KEY_RSA(public_data.unique.rsa);
  *hash = Sha256(SecureBlob(public_modulus));
  return nullptr;
}

void Tpm2Impl::GetStatus(std::optional<hwsec::Key> key, TpmStatusInfo* status) {
  memset(status, 0, sizeof(TpmStatusInfo));
  TrunksClientContext* trunks;
  if (!GetTrunksContext(&trunks)) {
    return;
  }
  status->this_instance_has_context = true;
  status->this_instance_has_key_handle = key.has_value();
  status->last_tpm_error = trunks->tpm_state->Initialize();
  if (status->last_tpm_error != TPM_RC_SUCCESS) {
    return;
  }
  status->can_connect = true;
  trunks::TPMT_PUBLIC public_srk;
  status->last_tpm_error = trunks->tpm_utility->GetKeyPublicArea(
      trunks::kStorageRootKey, &public_srk);
  if (status->last_tpm_error != TPM_RC_SUCCESS) {
    return;
  }
  status->can_load_srk = true;
  status->can_load_srk_public_key = true;
  status->srk_vulnerable_roca = false;

  // Check the Cryptohome key by using what we have been told.
  status->has_cryptohome_key = key.has_value();

  if (status->has_cryptohome_key) {
    // Check encryption (we don't care about the contents, just whether or not
    // there was an error)
    SecureBlob data(16);
    SecureBlob password(16);
    SecureBlob salt(8);
    memset(data.data(), 'A', data.size());
    memset(password.data(), 'B', password.size());
    memset(salt.data(), 'C', salt.size());

    hwsec::StatusOr<brillo::Blob> data_out =
        GetHwsec()->Encrypt(key.value(), data);
    if (!data_out.ok()) {
      LOG(ERROR) << __func__
                 << ": Failed to encrypt blob: " << data_out.status();
      return;
    }
    status->can_encrypt = true;

    // Check decryption (we don't care about the contents, just whether or not
    // there was an error)
    hwsec::StatusOr<brillo::SecureBlob> data_final =
        GetHwsec()->Decrypt(key.value(), *data_out);
    if (!data_final.ok()) {
      LOG(ERROR) << __func__
                 << ": Failed to decrypt blob: " << data_final.status();
      return;
    }
    status->can_decrypt = true;
  }
}

hwsec::Status Tpm2Impl::IsSrkRocaVulnerable(bool* result) {
  // This doesn't apply to devices with TPM 2.0.
  *result = false;
  return nullptr;
}

bool Tpm2Impl::GetDictionaryAttackInfo(int* counter,
                                       int* threshold,
                                       bool* lockout,
                                       int* seconds_remaining) {
  if (!InitializeTpmManagerUtility()) {
    LOG(ERROR) << __func__ << ": Failed to initialize |TpmManagerUtility|.";
    return false;
  }
  return tpm_manager_utility_->GetDictionaryAttackInfo(
      counter, threshold, lockout, seconds_remaining);
}

bool Tpm2Impl::ResetDictionaryAttackMitigation() {
  if (!InitializeTpmManagerUtility()) {
    LOG(ERROR) << __func__ << ": Failed to initialize |TpmManagerUtility|.";
    return false;
  }
  return tpm_manager_utility_->ResetDictionaryAttackLock();
}

void Tpm2Impl::DeclareTpmFirmwareStable() {
  TrunksClientContext* trunks;
  if (!fw_declared_stable_ && GetTrunksContext(&trunks)) {
    hwsec::Status err = HANDLE_TPM_COMM_ERROR(CreateError<TPM2Error>(
        trunks->tpm_utility->DeclareTpmFirmwareStable()));
    fw_declared_stable_ = err.ok();
  }
}

bool Tpm2Impl::GetTrunksContext(TrunksClientContext** trunks) {
  if (has_external_trunks_context_) {
    *trunks = &external_trunks_context_;
    return true;
  }
  base::PlatformThreadId thread_id = base::PlatformThread::CurrentId();
  std::map<base::PlatformThreadId,
           std::unique_ptr<Tpm2Impl::TrunksClientContext>>::iterator iter;
  {
    base::AutoLock lock(trunks_contexts_lock_);
    iter = trunks_contexts_.find(thread_id);
    if (iter == trunks_contexts_.end()) {
      auto result = trunks_contexts_.emplace(thread_id, nullptr);
      iter = std::move(result.first);
    }
  }

  // Different elements in the same container can be modified concurrently by
  // different threads, so we don't need to lock this block.
  if (!iter->second) {
    std::unique_ptr<TrunksClientContext> new_context(new TrunksClientContext);
    new_context->factory_impl = std::make_unique<trunks::TrunksFactoryImpl>();
    if (!new_context->factory_impl->Initialize()) {
      LOG(ERROR) << "Failed to initialize trunks factory.";
      return false;
    }
    new_context->factory = new_context->factory_impl.get();
    new_context->tpm_state = new_context->factory->GetTpmState();
    new_context->tpm_utility = new_context->factory->GetTpmUtility();
    iter->second = std::move(new_context);
  }
  *trunks = iter->second.get();
  return true;
}

bool Tpm2Impl::LoadPublicKeyFromSpki(
    const Blob& public_key_spki_der,
    AsymmetricKeyUsage key_type,
    trunks::TPM_ALG_ID scheme,
    trunks::TPM_ALG_ID hash_alg,
    trunks::AuthorizationDelegate* session_delegate,
    ScopedKeyHandle* key_handle) {
  // Parse the SPKI.
  const unsigned char* asn1_ptr = public_key_spki_der.data();
  const crypto::ScopedEVP_PKEY pkey(
      d2i_PUBKEY(nullptr, &asn1_ptr, public_key_spki_der.size()));
  if (!pkey) {
    LOG(ERROR) << "Error parsing Subject Public Key Info DER";
    return false;
  }
  const crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey.get()));
  if (!rsa) {
    LOG(ERROR) << "Error: non-RSA key was supplied";
    return false;
  }
  SecureBlob key_modulus(RSA_size(rsa.get()));
  const BIGNUM* n;
  const BIGNUM* e;
  RSA_get0_key(rsa.get(), &n, &e, nullptr);
  if (BN_bn2bin(n, key_modulus.data()) != key_modulus.size()) {
    LOG(ERROR) << "Error extracting public key modulus";
    return false;
  }
  constexpr BN_ULONG kInvalidBnWord = ~static_cast<BN_ULONG>(0);
  const BN_ULONG exponent_word = BN_get_word(e);
  if (exponent_word == kInvalidBnWord ||
      !base::IsValueInRangeForNumericType<uint32_t>(exponent_word)) {
    LOG(ERROR) << "Error extracting public key exponent";
    return false;
  }
  const uint32_t key_exponent = static_cast<uint32_t>(exponent_word);
  // Load the key into the TPM.
  TrunksClientContext* trunks;
  if (!GetTrunksContext(&trunks))
    return false;
  trunks::TPM_HANDLE key_handle_raw = 0;
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(trunks->tpm_utility->LoadRSAPublicKey(
              ConvertAsymmetricKeyUsage(key_type), scheme, hash_alg,
              key_modulus.to_string(), key_exponent, session_delegate,
              &key_handle_raw)));
      !err.ok()) {
    LOG(ERROR) << "Error loading public key: " << err;
    return false;
  }
  key_handle->reset(this, key_handle_raw);
  return true;
}

bool Tpm2Impl::PublicAreaToPublicKeyDER(const trunks::TPMT_PUBLIC& public_area,
                                        brillo::SecureBlob* public_key_der) {
  crypto::ScopedRSA rsa(RSA_new());
  crypto::ScopedBIGNUM e(BN_new()), n(BN_new());
  if (!rsa || !e || !n) {
    LOG(ERROR) << "Failed to allocate RSA or BIGNUM for public key.";
    return false;
  }
  if (!BN_set_word(e.get(), kDefaultTpmPublicExponent) ||
      !BN_bin2bn(public_area.unique.rsa.buffer, public_area.unique.rsa.size,
                 n.get()) ||
      !RSA_set0_key(rsa.get(), n.release(), e.release(), nullptr)) {
    LOG(ERROR) << "Failed to set up RSA.";
    return false;
  }
  int der_length = i2d_RSAPublicKey(rsa.get(), nullptr);
  if (der_length < 0) {
    LOG(ERROR) << "Failed to get DER-encoded public key length.";
    return false;
  }
  public_key_der->resize(der_length);
  unsigned char* der_buffer = public_key_der->data();
  der_length = i2d_RSAPublicKey(rsa.get(), &der_buffer);
  if (der_length < 0) {
    LOG(ERROR) << "Failed to DER-encode public key.";
    return false;
  }
  return true;
}

hwsec::Status Tpm2Impl::GetAuthValue(std::optional<TpmKeyHandle> key_handle,
                                     const SecureBlob& pass_blob,
                                     SecureBlob* auth_value) {
  if (!key_handle) {
    LOG(DFATAL) << "TPM2.0 needs a key_handle to get auth value.";
    return CreateError<TPMError>("TPM2.0 needs a key_handle to get auth value",
                                 TPMRetryAction::kNoRetry);
  }
  if (pass_blob.size() != kDefaultTpmRsaModulusSize / 8) {
    return CreateError<TPMError>(
        "Unexpected pass_blob size: " + std::to_string(pass_blob.size()),
        TPMRetryAction::kNoRetry);
  }

  TrunksClientContext* trunks;
  if (!GetTrunksContext(&trunks)) {
    return CreateError<TPMError>("Failed to get trunks context",
                                 TPMRetryAction::kNoRetry);
  }

  // To guarantee that pass_blob is lower that public key modulus, just set the
  // first byte to 0.
  std::string value_to_decrypt = pass_blob.to_string();
  value_to_decrypt[0] = 0;
  std::string decrypted_value;
  std::unique_ptr<trunks::AuthorizationDelegate> delegate =
      trunks->factory->GetPasswordAuthorization("");
  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(trunks->tpm_utility->AsymmetricDecrypt(
              key_handle.value(), trunks::TPM_ALG_NULL, trunks::TPM_ALG_NULL,
              value_to_decrypt, delegate.get(), &decrypted_value)));
      !err.ok()) {
    return WrapError<TPMError>(std::move(err), "Error decrypting pass_blob");
  }
  *auth_value = Sha256(SecureBlob(decrypted_value));

  return nullptr;
}

hwsec::Status Tpm2Impl::GetEccAuthValue(std::optional<TpmKeyHandle> key_handle,
                                        const SecureBlob& pass_blob,
                                        SecureBlob* auth_value) {
  if (!key_handle) {
    LOG(DFATAL) << "TPM2.0 needs a key_handle to get ECC auth value.";
    return CreateError<TPMError>(
        "TPM2.0 needs a key_handle to get ECC auth value",
        TPMRetryAction::kNoRetry);
  }

  if (pass_blob.size() < kMinPassBlobSize) {
    return CreateError<TPMError>(
        "Unexpected pass_blob size: " + std::to_string(pass_blob.size()),
        TPMRetryAction::kNoRetry);
  }

  TrunksClientContext* trunks;
  if (!GetTrunksContext(&trunks)) {
    return CreateError<TPMError>("Failed to get trunks context",
                                 TPMRetryAction::kCommunication);
  }

  trunks::TPMS_ECC_POINT ecc_point;
  if (hwsec::Status err = DeriveTpmEccPointFromSeed(pass_blob, &ecc_point);
      !err.ok()) {
    return WrapError<TPMError>(std::move(err),
                               "Failed to derive TPM ECC point from ");
  }

  trunks::TPM2B_ECC_POINT in_point = trunks::Make_TPM2B_ECC_POINT(ecc_point);
  trunks::TPM2B_ECC_POINT z_point;

  std::unique_ptr<trunks::AuthorizationDelegate> delegate =
      trunks->factory->GetPasswordAuthorization("");

  if (hwsec::Status err = HANDLE_TPM_COMM_ERROR(
          CreateError<TPM2Error>(trunks->tpm_utility->ECDHZGen(
              key_handle.value(), in_point, delegate.get(), &z_point)));
      !err.ok()) {
    return WrapError<TPMError>(std::move(err), "Error doing ECDH ZGen");
  }

  *auth_value =
      Sha256(SecureBlob(StringFrom_TPM2B_ECC_PARAMETER(z_point.point.x)));

  return nullptr;
}

bool Tpm2Impl::UpdateTpmStatus(RefreshType refresh_type) {
  if (!InitializeTpmManagerUtility()) {
    LOG(ERROR) << __func__ << ": Failed to initialize |TpmManagerUtility|.";
    return false;
  }

  bool is_successful = false;
  bool has_received = false;

  // Repeats data copy into |last_tpm_manager_data_|; reasonable trade-off due
  // to low ROI to avoid that.
  const bool is_connected = tpm_manager_utility_->GetOwnershipTakenSignalStatus(
      &is_successful, &has_received, &last_tpm_manager_data_);

  // When we need explicitly query tpm status either because the signal is not
  // ready for any reason, or because the signal is not received yet so we need
  // to run it once in case the signal is sent by tpm_manager before already.
  if (refresh_type == RefreshType::FORCE_REFRESH || !is_connected ||
      !is_successful || (!has_received && shall_cache_tpm_manager_status_)) {
    // Retains |shall_cache_tpm_manager_status_| to be |true| if the signal
    // cannot be relied on (yet). Actually |!is_successful| suffices to update
    // |shall_cache_tpm_manager_status_|; by design, uses the redundancy just to
    // avoid confusion.
    shall_cache_tpm_manager_status_ &= (!is_connected || !is_successful);
    return CacheTpmManagerStatus();
  } else if (has_received) {
    is_enabled_ = true;
    is_owned_ = true;
  }
  return true;
}

bool Tpm2Impl::RemoveOwnerDependency(Tpm::TpmOwnerDependency dependency) {
  if (!InitializeTpmManagerUtility()) {
    LOG(ERROR) << __func__ << ": Failed to initialize |TpmManagerUtility|.";
    return false;
  }
  return tpm_manager_utility_->RemoveOwnerDependency(
      OwnerDependencyEnumClassToString(dependency));
}

bool Tpm2Impl::GetVersionInfo(TpmVersionInfo* version_info) {
  if (!version_info) {
    LOG(ERROR) << __func__ << "version_info is not initialized.";
    return false;
  }

  // Version info on a device never changes. Returns from cache directly if we
  // have the cache.
  if (version_info_) {
    *version_info = *version_info_;
    return true;
  }

  if (!InitializeTpmManagerUtility()) {
    LOG(ERROR) << __func__ << ": failed to initialize |TpmManagerUtility|.";
    return false;
  }

  if (!tpm_manager_utility_->GetVersionInfo(
          &version_info->family, &version_info->spec_level,
          &version_info->manufacturer, &version_info->tpm_model,
          &version_info->firmware_version, &version_info->vendor_specific)) {
    LOG(ERROR) << __func__ << ": failed to get version info from tpm_manager.";
    return false;
  }

  version_info_ = *version_info;
  return true;
}

bool Tpm2Impl::GetIFXFieldUpgradeInfo(IFXFieldUpgradeInfo* info) {
  return false;
}

bool Tpm2Impl::GetRsuDeviceId(std::string* device_id) {
  TrunksClientContext* trunks;
  if (!GetTrunksContext(&trunks)) {
    return false;
  }
  return trunks->tpm_utility->GetRsuDeviceId(device_id) == TPM_RC_SUCCESS;
}

hwsec::RecoveryCryptoFrontend* Tpm2Impl::GetRecoveryCrypto() {
  return recovery_crypto_.get();
}

bool Tpm2Impl::GetDelegate(brillo::Blob* /*blob*/,
                           brillo::Blob* /*secret*/,
                           bool* has_reset_lock_permissions) {
  LOG(WARNING) << __func__ << ": No-ops to |blob| and |secret|.";
  *has_reset_lock_permissions = true;
  return true;
}

hwsec::Status Tpm2Impl::IsDelegateBoundToPcr(bool* result) {
  *result = false;
  return nullptr;
}

bool Tpm2Impl::DelegateCanResetDACounter() {
  return true;
}

std::map<uint32_t, brillo::Blob> Tpm2Impl::GetPcrMap(
    const std::string& obfuscated_username, bool use_extended_pcr) const {
  std::map<uint32_t, brillo::Blob> pcr_map;
  if (use_extended_pcr) {
    brillo::Blob starting_value(SHA256_DIGEST_LENGTH, 0);
    brillo::Blob digest_value = Sha256(brillo::CombineBlobs(
        {starting_value, Sha256(brillo::BlobFromString(obfuscated_username))}));
    pcr_map[kTpmSingleUserPCR] = digest_value;
  } else {
    pcr_map[kTpmSingleUserPCR] = brillo::Blob(SHA256_DIGEST_LENGTH, 0);
  }

  return pcr_map;
}

hwsec::CryptohomeFrontend* Tpm2Impl::GetHwsec() {
  return hwsec_.get();
}

hwsec::PinWeaverFrontend* Tpm2Impl::GetPinWeaver() {
  return pinweaver_.get();
}

}  // namespace cryptohome
