// Copyright (c) 2012 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.

// Contains the implementation of class Tpm

#include "cryptohome/tpm_impl.h"

#include <stdio.h>
#include <stdlib.h>

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

#include <arpa/inet.h>
#include <base/check.h>
#include <base/check_op.h>
#include <base/logging.h>
#include <base/memory/free_deleter.h>
#include <base/notreached.h>
#include <base/stl_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/stringprintf.h>
#include <base/threading/platform_thread.h>
#include <base/time/time.h>
#include <base/values.h>
#include <crypto/libcrypto-compat.h>
#include <crypto/scoped_openssl_types.h>
#include <libhwsec/overalls/overalls_api.h>
#include <libhwsec/error/tpm1_error.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 <trousers/scoped_tss_type.h>
#include <trousers/tss.h>
#include <trousers/trousers.h>  // NOLINT(build/include_alpha) - needs tss.h

#include "cryptohome/crypto/aes.h"
#include "cryptohome/crypto/rsa.h"
#include "cryptohome/crypto/secure_blob_util.h"
#include "cryptohome/crypto/sha.h"
#include "cryptohome/cryptohome_metrics.h"
#include "cryptohome/tpm1_static_utils.h"
#include "cryptohome/tpm_metrics.h"

#define TPM_LOG(severity, result) \
  LOG(severity) << ::cryptohome::FormatTrousersErrorCode(result) << ": "

using base::PlatformThread;
using brillo::Blob;
using brillo::BlobFromString;
using brillo::CombineBlobs;
using brillo::SecureBlob;
using hwsec::error::TPM1Error;
using hwsec::error::TPMError;
using hwsec::error::TPMErrorBase;
using hwsec::error::TPMRetryAction;
using hwsec::overalls::GetOveralls;
using hwsec_foundation::error::CreateError;
using hwsec_foundation::error::WrapError;
using trousers::ScopedTssContext;
using trousers::ScopedTssKey;
using trousers::ScopedTssMemory;
using trousers::ScopedTssNvStore;
using trousers::ScopedTssObject;
using trousers::ScopedTssPcrs;
using trousers::ScopedTssPolicy;

namespace cryptohome {

// Returns the corresponding TpmResult enum value to be used to report a
// "Cryptohome.TpmResults" histogram sample.
TpmResult GetTpmResultSample(TSS_RESULT result);

namespace {

typedef std::unique_ptr<BYTE, base::FreeDeleter> ScopedByteArray;

// The DER encoding of SHA-256 DigestInfo as defined in PKCS #1.
const unsigned char kSha256DigestInfo[] = {
    0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
    0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};

// This is the well known UUID present in TPM1.2 implemenations. It is used
// to load the cryptohome key into a TPM1.2 in a legacy path.
const TSS_UUID kCryptohomeWellKnownUuid = {0x0203040b, 0, 0,
                                           0,          0, {0, 9, 8, 1, 0, 3}};

// Creates a DER encoded RSA public key given a serialized TPM_PUBKEY.
//
// Parameters
//   public_key - A serialized TPM_PUBKEY as returned by Tspi_Key_GetPubKey.
//   public_key_der - The same public key in DER encoded form.
bool ConvertPublicKeyToDER(const SecureBlob& public_key,
                           SecureBlob* public_key_der) {
  crypto::ScopedRSA rsa =
      ParseRsaFromTpmPubkeyBlob(Blob(public_key.begin(), public_key.end()));
  if (!rsa) {
    return false;
  }

  int der_length = i2d_RSAPublicKey(rsa.get(), NULL);
  if (der_length < 0) {
    LOG(ERROR) << "Failed to DER-encode public key.";
    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;
  }
  public_key_der->resize(der_length);
  return true;
}

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;
  }
  NOTREACHED() << __func__ << ": Unexpected enum class value: "
               << static_cast<int>(dependency);
  return "";
}

}  // namespace

const unsigned char kDefaultSrkAuth[] = {};
const unsigned int kDefaultTpmRsaKeyFlag = TSS_KEY_SIZE_2048;
const unsigned int kDefaultDiscardableWrapPasswordLength = 32;

const char* kWellKnownSrkTmp = "1234567890";
const unsigned int kTpmConnectRetries = 10;
const unsigned int kTpmConnectIntervalMs = 100;
const unsigned int kTpmPCRLocality = 1;
const int kDelegateSecretSize = 20;
const size_t kPCRExtensionSize = 20;  // SHA-1 digest size.

// This error is returned when an attempt is made to use the SRK but it does not
// yet exist because the TPM has not been owned.
const TSS_RESULT kKeyNotFoundError = (TSS_E_PS_KEY_NOTFOUND | TSS_LAYER_TCS);

TpmImpl::TpmImpl()
    : srk_auth_(kDefaultSrkAuth, kDefaultSrkAuth + sizeof(kDefaultSrkAuth)),
      owner_password_() {
  TSS_HCONTEXT context_handle = ConnectContext();
  if (context_handle) {
    tpm_context_.reset(0, context_handle);
  }
}

TpmImpl::~TpmImpl() {}

void TpmImpl::SetTpmManagerUtilityForTesting(
    tpm_manager::TpmManagerUtility* tpm_manager_utility) {
  tpm_manager_utility_ = tpm_manager_utility;
}

TSS_HCONTEXT TpmImpl::ConnectContext() {
  TSS_HCONTEXT context_handle = 0;
  if (TPM1Error err = OpenAndConnectTpm(&context_handle)) {
    LOG(ERROR) << "Failed to OpenAndConnectTpm: " << *err;
    return 0;
  }
  return context_handle;
}

bool TpmImpl::ConnectContextAsOwner(TSS_HCONTEXT* context, TSS_HTPM* tpm) {
  *context = 0;
  *tpm = 0;
  SecureBlob owner_password;
  if (TPMErrorBase err = GetOwnerPassword(&owner_password)) {
    LOG(ERROR) << "ConnectContextAsOwner requires an owner password: " << *err;
    return false;
  }

  if (!IsOwned()) {
    LOG(ERROR) << "ConnectContextAsOwner: TPM is unowned";
    return false;
  }

  if ((*context = ConnectContext()) == 0) {
    LOG(ERROR) << "ConnectContextAsOwner: Could not open the TPM";
    return false;
  }

  if (!GetTpmWithAuth(*context, owner_password, tpm)) {
    LOG(ERROR) << "ConnectContextAsOwner: failed to authorize as the owner";
    Tspi_Context_Close(*context);
    *context = 0;
    *tpm = 0;
    return false;
  }
  return true;
}

bool TpmImpl::ConnectContextAsUser(TSS_HCONTEXT* context, TSS_HTPM* tpm) {
  *context = 0;
  *tpm = 0;
  if ((*context = ConnectContext()) == 0) {
    LOG(ERROR) << "ConnectContextAsUser: Could not open the TPM";
    return false;
  }
  if (!GetTpm(*context, tpm)) {
    LOG(ERROR) << "ConnectContextAsUser: failed to get a TPM object";
    Tspi_Context_Close(*context);
    *context = 0;
    *tpm = 0;
    return false;
  }
  return true;
}

bool TpmImpl::ConnectContextAsDelegate(const Blob& delegate_blob,
                                       const Blob& delegate_secret,
                                       TSS_HCONTEXT* context,
                                       TSS_HTPM* tpm_handle) {
  *context = 0;
  *tpm_handle = 0;
  if (!IsOwned()) {
    LOG(ERROR) << "ConnectContextAsDelegate: TPM is unowned.";
    return false;
  }
  if ((*context = ConnectContext()) == 0) {
    LOG(ERROR) << "ConnectContextAsDelegate: Could not open the TPM.";
    return false;
  }
  if (!GetTpmWithDelegation(*context, delegate_blob, delegate_secret,
                            tpm_handle)) {
    LOG(ERROR) << "ConnectContextAsDelegate: Failed to authorize.";
    Tspi_Context_Close(*context);
    *context = 0;
    *tpm_handle = 0;
    return false;
  }
  return true;
}

void TpmImpl::GetStatus(base::Optional<TpmKeyHandle> key_handle,
                        TpmStatusInfo* status) {
  memset(status, 0, sizeof(TpmStatusInfo));
  status->this_instance_has_context = (tpm_context_.value() != 0);
  status->this_instance_has_key_handle = key_handle.has_value();
  ScopedTssContext context_handle;
  // Check if we can connect
  if (TPM1Error err = OpenAndConnectTpm(context_handle.ptr())) {
    status->last_tpm_error = err->ErrorCode();
    return;
  }
  status->can_connect = true;

  // Check the Storage Root Key
  ScopedTssKey srk_handle(context_handle);
  if (TPM1Error err = LoadSrk(context_handle, srk_handle.ptr())) {
    status->last_tpm_error = err->ErrorCode();
    return;
  }
  status->can_load_srk = true;

  // Check the SRK public key
  unsigned int public_srk_size;
  ScopedTssMemory public_srk_bytes(context_handle);
  if (auto err = CreateError<TPM1Error>(Tspi_Key_GetPubKey(
          srk_handle, &public_srk_size, public_srk_bytes.ptr()))) {
    LOG(ERROR) << "Failed to get public key: " << *err;
    status->last_tpm_error = err->ErrorCode();
    return;
  }
  status->can_load_srk_public_key = true;

  // Perform ROCA vulnerability check.
  crypto::ScopedRSA public_srk = ParseRsaFromTpmPubkeyBlob(Blob(
      public_srk_bytes.value(), public_srk_bytes.value() + public_srk_size));

  if (public_srk) {
    const BIGNUM* n;
    RSA_get0_key(public_srk.get(), &n, nullptr, nullptr);
    status->srk_vulnerable_roca = TestRocaVulnerable(n);
  } else {
    status->srk_vulnerable_roca = false;
  }

  // Check the Cryptohome key by using what we have been told.
  status->has_cryptohome_key =
      (tpm_context_.value() != 0) && key_handle.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);
    SecureBlob data_out(16);
    memset(data.data(), 'A', data.size());
    memset(password.data(), 'B', password.size());
    memset(salt.data(), 'C', salt.size());
    memset(data_out.data(), 'D', data_out.size());
    SecureBlob key;
    PasskeyToAesKey(password, salt, 13, &key, NULL);
    if (TPMErrorBase err =
            EncryptBlob(key_handle.value(), data, key, &data_out)) {
      LOG(ERROR) << __func__ << ": Failed to encrypt blob: " << *err;
      return;
    }
    status->can_encrypt = true;

    // Check decryption (we don't care about the contents, just whether or not
    // there was an error)
    if (TPMErrorBase err =
            DecryptBlob(key_handle.value(), data_out, key,
                        std::map<uint32_t, std::string>(), &data)) {
      LOG(ERROR) << __func__ << ": Failed to decrypt blob: " << *err;
      return;
    }
    status->can_decrypt = true;
  }
}

TPMErrorBase TpmImpl::IsSrkRocaVulnerable(bool* result) {
  if (!tpm_context_) {
    return CreateError<TPMError>("No TPM context", TPMRetryAction::kNoRetry);
  }
  ScopedTssKey srk_handle(tpm_context_);
  if (TPM1Error err = LoadSrk(tpm_context_, srk_handle.ptr())) {
    return WrapError<TPMError>(std::move(err), "Failed to load SRK");
  }
  unsigned public_srk_size;
  ScopedTssMemory public_srk_bytes(tpm_context_);
  if (auto err = CreateError<TPM1Error>(Tspi_Key_GetPubKey(
          srk_handle, &public_srk_size, public_srk_bytes.ptr()))) {
    return WrapError<TPMError>(std::move(err), "Failed to get SRK public key");
  }
  crypto::ScopedRSA public_srk = ParseRsaFromTpmPubkeyBlob(Blob(
      public_srk_bytes.value(), public_srk_bytes.value() + public_srk_size));
  if (!public_srk) {
    return CreateError<TPMError>("Failed to parse RSA public key",
                                 TPMRetryAction::kNoRetry);
  }

  const BIGNUM* n = nullptr;
  RSA_get0_key(public_srk.get(), &n, nullptr, nullptr);
  *result = TestRocaVulnerable(n);
  return nullptr;
}

bool TpmImpl::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 TpmImpl::ResetDictionaryAttackMitigation(const brillo::Blob&,
                                              const brillo::Blob&) {
  if (!InitializeTpmManagerUtility()) {
    LOG(ERROR) << __func__ << ": failed to initialize |TpmManagerUtility|.";
    return false;
  }
  return tpm_manager_utility_->ResetDictionaryAttackLock();
}

bool TpmImpl::CreatePolicyWithRandomPassword(TSS_HCONTEXT context_handle,
                                             TSS_FLAG policy_type,
                                             TSS_HPOLICY* policy_handle) {
  trousers::ScopedTssPolicy local_policy(context_handle);
  if (auto err = CreateError<TPM1Error>(
          Tspi_Context_CreateObject(context_handle, TSS_OBJECT_TYPE_POLICY,
                                    policy_type, local_policy.ptr()))) {
    LOG(ERROR) << "Error creating policy object: " << *err;
    return false;
  }
  auto migration_password =
      CreateSecureRandomBlob(kDefaultDiscardableWrapPasswordLength);
  if (auto err = CreateError<TPM1Error>(Tspi_Policy_SetSecret(
          local_policy, TSS_SECRET_MODE_PLAIN, migration_password.size(),
          migration_password.data()))) {
    LOG(ERROR) << "Error setting policy password: " << *err;
    return false;
  }
  *policy_handle = local_policy.release();
  return true;
}

bool TpmImpl::CreateRsaPublicKeyObject(TSS_HCONTEXT context_handle,
                                       const Blob& key_modulus,
                                       TSS_FLAG key_flags,
                                       UINT32 signature_scheme,
                                       UINT32 encryption_scheme,
                                       TSS_HKEY* key_handle) {
  ScopedTssKey local_key(context_handle);
  if (auto err = CreateError<TPM1Error>(
          Tspi_Context_CreateObject(context_handle, TSS_OBJECT_TYPE_RSAKEY,
                                    key_flags, local_key.ptr()))) {
    LOG(ERROR) << __func__ << ": Error creating the key object: " << *err;
    return false;
  }

  if (auto err = CreateError<TPM1Error>(Tspi_SetAttribData(
          local_key, TSS_TSPATTRIB_RSAKEY_INFO,
          TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, key_modulus.size(),
          const_cast<BYTE*>(key_modulus.data())))) {
    LOG(ERROR) << __func__ << ": Error setting the key modulus: " << *err;
    return false;
  }
  if (signature_scheme != TSS_SS_NONE) {
    if (auto err = CreateError<TPM1Error>(Tspi_SetAttribUint32(
            local_key, TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_SIGSCHEME,
            signature_scheme))) {
      LOG(ERROR) << __func__
                 << ": Error setting the key signing scheme: " << *err;
      return false;
    }
  }
  if (encryption_scheme != TSS_ES_NONE) {
    if (auto err = CreateError<TPM1Error>(Tspi_SetAttribUint32(
            local_key, TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_ENCSCHEME,
            encryption_scheme))) {
      LOG(ERROR) << __func__
                 << ": Error setting the key encryption scheme: " << *err;
      return false;
    }
  }
  *key_handle = local_key.release();
  return true;
}

TPM1Error TpmImpl::OpenAndConnectTpm(TSS_HCONTEXT* context_handle) {
  ScopedTssContext local_context_handle;
  if (auto err = CreateError<TPM1Error>(
          Tspi_Context_Create(local_context_handle.ptr()))) {
    LOG(ERROR) << "Error calling Tspi_Context_Create: " << *err;
    return err;
  }

  for (unsigned int i = 0; i < kTpmConnectRetries; i++) {
    if (auto err = CreateError<TPM1Error>(
            GetOveralls()->Ospi_Context_Connect(local_context_handle, NULL))) {
      // If there was a communications failure, try sleeping a bit here, it may
      // be that tcsd is still starting.
      if (err->ToTPMRetryAction() == TPMRetryAction::kCommunication &&
          i + 1 != kTpmConnectRetries) {
        PlatformThread::Sleep(
            base::TimeDelta::FromMilliseconds(kTpmConnectIntervalMs));

      } else {
        LOG(ERROR) << "Error calling Tspi_Context_Connect: " << *err;
        return err;
      }
    } else {
      break;
    }
  }

  *context_handle = local_context_handle.release();
  return nullptr;
}

TPMErrorBase TpmImpl::GetPublicKeyHash(TpmKeyHandle key_handle,
                                       SecureBlob* hash) {
  SecureBlob pubkey;
  if (TPM1Error err =
          GetPublicKeyBlob(tpm_context_.value(), key_handle, &pubkey)) {
    return WrapError<TPMError>(std::move(err),
                               "Failed to get TPM public key hash");
  }
  *hash = Sha1(pubkey);
  return nullptr;
}

TPMErrorBase TpmImpl::EncryptBlob(TpmKeyHandle key_handle,
                                  const SecureBlob& plaintext,
                                  const SecureBlob& key,
                                  SecureBlob* ciphertext) {
  TSS_FLAG init_flags = TSS_ENCDATA_SEAL;
  ScopedTssKey enc_handle(tpm_context_.value());
  if (auto err = CreateError<TPM1Error>(Tspi_Context_CreateObject(
          tpm_context_.value(), TSS_OBJECT_TYPE_ENCDATA, init_flags,
          enc_handle.ptr()))) {
    return WrapError<TPMError>(std::move(err),
                               "Error calling Tspi_Context_CreateObject");
  }

  // TODO(fes): Check RSA key modulus size, return an error or block input

  if (auto err = CreateError<TPM1Error>(
          Tspi_Data_Bind(enc_handle, key_handle, plaintext.size(),
                         const_cast<BYTE*>(plaintext.data())))) {
    return WrapError<TPMError>(std::move(err), "Error calling Tspi_Data_Bind");
  }

  SecureBlob enc_data_blob;
  if (TPM1Error err = GetDataAttribute(
          tpm_context_.value(), enc_handle, TSS_TSPATTRIB_ENCDATA_BLOB,
          TSS_TSPATTRIB_ENCDATABLOB_BLOB, &enc_data_blob)) {
    return WrapError<TPMError>(std::move(err), "Failed to read encrypted blob");
  }
  if (!ObscureRsaMessage(enc_data_blob, key, ciphertext)) {
    return CreateError<TPMError>("Error obscuring message",
                                 TPMRetryAction::kNoRetry);
  }
  return nullptr;
}
TPMErrorBase TpmImpl::DecryptBlob(
    TpmKeyHandle key_handle,
    const SecureBlob& ciphertext,
    const SecureBlob& key,
    const std::map<uint32_t, std::string>& pcr_map,
    SecureBlob* plaintext) {
  SecureBlob local_data;
  if (!UnobscureRsaMessage(ciphertext, key, &local_data)) {
    return CreateError<TPMError>("Error unobscureing message",
                                 TPMRetryAction::kNoRetry);
  }

  TSS_FLAG init_flags = TSS_ENCDATA_SEAL;
  ScopedTssKey enc_handle(tpm_context_.value());
  if (auto err = CreateError<TPM1Error>(Tspi_Context_CreateObject(
          tpm_context_.value(), TSS_OBJECT_TYPE_ENCDATA, init_flags,
          enc_handle.ptr()))) {
    return WrapError<TPMError>(std::move(err),
                               "Error calling Tspi_Context_CreateObject");
  }

  if (auto err = CreateError<TPM1Error>(
          Tspi_SetAttribData(enc_handle, TSS_TSPATTRIB_ENCDATA_BLOB,
                             TSS_TSPATTRIB_ENCDATABLOB_BLOB, local_data.size(),
                             local_data.data()))) {
    return WrapError<TPMError>(std::move(err),
                               "Error calling Tspi_SetAttribData");
  }

  ScopedTssMemory dec_data(tpm_context_.value());
  UINT32 dec_data_length = 0;
  if (auto err = CreateError<TPM1Error>(Tspi_Data_Unbind(
          enc_handle, key_handle, &dec_data_length, dec_data.ptr()))) {
    return WrapError<TPMError>(std::move(err),
                               "Error calling Tspi_Data_Unbind");
  }

  plaintext->resize(dec_data_length);
  memcpy(plaintext->data(), dec_data.value(), dec_data_length);
  brillo::SecureClearBytes(dec_data.value(), dec_data_length);

  return nullptr;
}

bool TpmImpl::SetAuthValue(TSS_HCONTEXT context_handle,
                           ScopedTssKey* enc_handle,
                           TSS_HTPM tpm_handle,
                           const SecureBlob& auth_value) {
  // Create the enc_handle.
  if (auto err = CreateError<TPM1Error>(
          Tspi_Context_CreateObject(context_handle, TSS_OBJECT_TYPE_ENCDATA,
                                    TSS_ENCDATA_SEAL, enc_handle->ptr()))) {
    LOG(ERROR) << "Error calling Tspi_Context_CreateObject: " << *err;
    return false;
  }

  // Get the TPM usage policy object and set the auth_value.
  TSS_HPOLICY tpm_usage_policy;
  if (auto err = CreateError<TPM1Error>(Tspi_GetPolicyObject(
          tpm_handle, TSS_POLICY_USAGE, &tpm_usage_policy))) {
    LOG(ERROR) << "Error calling Tspi_GetPolicyObject: " << *err;
    return false;
  }
  if (auto err = CreateError<TPM1Error>(Tspi_Policy_SetSecret(
          tpm_usage_policy, TSS_SECRET_MODE_PLAIN, auth_value.size(),
          const_cast<BYTE*>(auth_value.data())))) {
    LOG(ERROR) << "Error calling Tspi_Policy_SetSecret: " << *err;
    return false;
  }

  if (auto err = CreateError<TPM1Error>(
          Tspi_Policy_AssignToObject(tpm_usage_policy, *enc_handle))) {
    LOG(ERROR) << "Error calling Tspi_Policy_AssignToObject: " << *err;
    return false;
  }

  return true;
}

TPMErrorBase TpmImpl::SealToPcrWithAuthorization(
    const SecureBlob& plaintext,
    const SecureBlob& auth_value,
    const std::map<uint32_t, std::string>& pcr_map,
    SecureBlob* sealed_data) {
  ScopedTssContext context_handle;
  TSS_HTPM tpm_handle;
  if (!ConnectContextAsUser(context_handle.ptr(), &tpm_handle)) {
    return CreateError<TPMError>("Failed to connect to the TPM",
                                 TPMRetryAction::kCommunication);
  }
  // Load the Storage Root Key.
  ScopedTssKey srk_handle(context_handle);
  if (TPM1Error err = LoadSrk(context_handle, srk_handle.ptr())) {
    return WrapError<TPMError>(std::move(err), "Failed to load SRK",
                               TPMRetryAction::kNoRetry);
  }

  // Create a PCRS object.
  ScopedTssPcrs pcrs_handle(context_handle);
  if (auto err = CreateError<TPM1Error>(
          Tspi_Context_CreateObject(context_handle, TSS_OBJECT_TYPE_PCRS,
                                    TSS_PCRS_STRUCT_INFO, pcrs_handle.ptr()))) {
    return WrapError<TPMError>(std::move(err),
                               "Error calling Tspi_Context_CreateObject",
                               TPMRetryAction::kNoRetry);
  }

  // Process the data from pcr_map.
  for (const auto& map_pair : pcr_map) {
    uint32_t pcr_index = map_pair.first;
    const std::string& digest = map_pair.second;
    if (digest.empty()) {
      UINT32 pcr_len = 0;
      ScopedTssMemory pcr_value(context_handle);
      if (auto err = CreateError<TPM1Error>(Tspi_TPM_PcrRead(
              tpm_handle, pcr_index, &pcr_len, pcr_value.ptr()))) {
        return WrapError<TPMError>(std::move(err), "Could not read PCR value");
      }
      Tspi_PcrComposite_SetPcrValue(pcrs_handle, pcr_index, pcr_len,
                                    pcr_value.value());
    } else {
      Tspi_PcrComposite_SetPcrValue(
          pcrs_handle, pcr_index, digest.size(),
          reinterpret_cast<BYTE*>(const_cast<char*>(digest.data())));
    }
  }

  ScopedTssKey enc_handle(context_handle);
  if (!SetAuthValue(context_handle, &enc_handle, tpm_handle, auth_value)) {
    context_handle.reset();
    return CreateError<TPMError>("Failed to SetAuthValue",
                                 TPMRetryAction::kNoRetry);
  }

  // Seal the given value with the SRK.
  if (auto err = CreateError<TPM1Error>(
          Tspi_Data_Seal(enc_handle, srk_handle, plaintext.size(),
                         const_cast<BYTE*>(plaintext.data()), pcrs_handle))) {
    return WrapError<TPMError>(std::move(err), "Error calling Tspi_Data_Seal",
                               TPMRetryAction::kNoRetry);
  }

  // Extract the sealed value.
  ScopedTssMemory enc_data(context_handle);
  UINT32 enc_data_length = 0;
  if (auto err = CreateError<TPM1Error>(Tspi_GetAttribData(
          enc_handle, TSS_TSPATTRIB_ENCDATA_BLOB,
          TSS_TSPATTRIB_ENCDATABLOB_BLOB, &enc_data_length, enc_data.ptr()))) {
    return WrapError<TPMError>(std::move(err),
                               "Error calling Tspi_GetAttribData",
                               TPMRetryAction::kNoRetry);
  }
  sealed_data->assign(&enc_data.value()[0], &enc_data.value()[enc_data_length]);

  return nullptr;
}

TPMErrorBase TpmImpl::PreloadSealedData(const brillo::SecureBlob& sealed_data,
                                        ScopedKeyHandle* preload_handle) {
  // No effect for TPM 1.2.
  return nullptr;
}

TPMErrorBase TpmImpl::UnsealWithAuthorization(
    base::Optional<TpmKeyHandle> preload_handle,
    const SecureBlob& sealed_data,
    const SecureBlob& auth_value,
    const std::map<uint32_t, std::string>& pcr_map,
    SecureBlob* plaintext) {
  if (preload_handle) {
    LOG(DFATAL) << "TPM1.2 doesn't support preload_handle.";
    return CreateError<TPMError>("TPM1.2 doesn't support preload_handle",
                                 TPMRetryAction::kNoRetry);
  }

  ScopedTssContext context_handle;
  TSS_HTPM tpm_handle;
  if (!ConnectContextAsUser(context_handle.ptr(), &tpm_handle)) {
    return CreateError<TPMError>("Failed to connect to the TPM",
                                 TPMRetryAction::kCommunication);
  }
  // Load the Storage Root Key.
  ScopedTssKey srk_handle(context_handle);
  if (TPM1Error err = LoadSrk(context_handle, srk_handle.ptr())) {
    return WrapError<TPMError>(std::move(err), "Failed to load SRK",
                               TPMRetryAction::kNoRetry);
  }

  // Create an ENCDATA object with the sealed value.
  ScopedTssKey enc_handle(context_handle);
  if (!SetAuthValue(context_handle, &enc_handle, tpm_handle, auth_value)) {
    context_handle.reset();
    return CreateError<TPMError>("Failed to SetAuthValue",
                                 TPMRetryAction::kNoRetry);
  }

  if (auto err = CreateError<TPM1Error>(
          Tspi_SetAttribData(enc_handle, TSS_TSPATTRIB_ENCDATA_BLOB,
                             TSS_TSPATTRIB_ENCDATABLOB_BLOB, sealed_data.size(),
                             const_cast<BYTE*>(sealed_data.data())))) {
    return WrapError<TPMError>(std::move(err),
                               "Error calling Tspi_SetAttribData");
  }

  // Unseal using the SRK.
  ScopedTssMemory dec_data(context_handle);
  UINT32 dec_data_length = 0;
  if (auto err = CreateError<TPM1Error>(Tspi_Data_Unseal(
          enc_handle, srk_handle, &dec_data_length, dec_data.ptr()))) {
    return WrapError<TPMError>(std::move(err),
                               "Error calling Tspi_Data_Unseal");
  }
  plaintext->assign(&dec_data.value()[0], &dec_data.value()[dec_data_length]);
  brillo::SecureClearBytes(dec_data.value(), dec_data_length);

  return nullptr;
}

TPM1Error TpmImpl::GetPublicKeyBlob(TSS_HCONTEXT context_handle,
                                    TSS_HKEY key_handle,
                                    SecureBlob* data_out) const {
  ScopedTssMemory blob(context_handle);
  UINT32 blob_size;

  if (auto err = CreateError<TPM1Error>(
          Tspi_Key_GetPubKey(key_handle, &blob_size, blob.ptr()))) {
    LOG(ERROR) << "Error calling Tspi_Key_GetPubKey: " << *err;
    return err;
  }

  SecureBlob local_data(blob_size);
  memcpy(local_data.data(), blob.value(), blob_size);
  brillo::SecureClearBytes(blob.value(), blob_size);
  data_out->swap(local_data);
  return nullptr;
}

TPM1Error TpmImpl::LoadSrk(TSS_HCONTEXT context_handle, TSS_HKEY* srk_handle) {
  // We shouldn't load the SRK if the TPM have been fully owned.
  if (!IsOwned()) {
    return CreateError<TPM1Error>(TSS_LAYER_TCS | TSS_E_FAIL);
  }

  // Load the Storage Root Key
  TSS_UUID SRK_UUID = TSS_UUID_SRK;
  ScopedTssKey local_srk_handle(context_handle);
  if (auto err = CreateError<TPM1Error>(
          Tspi_Context_LoadKeyByUUID(context_handle, TSS_PS_TYPE_SYSTEM,
                                     SRK_UUID, local_srk_handle.ptr()))) {
    return err;
  }

  // Check if the SRK wants a password
  UINT32 srk_authusage;
  if (auto err = CreateError<TPM1Error>(Tspi_GetAttribUint32(
          local_srk_handle, TSS_TSPATTRIB_KEY_INFO,
          TSS_TSPATTRIB_KEYINFO_AUTHUSAGE, &srk_authusage))) {
    return err;
  }

  // Give it the password if needed
  if (srk_authusage) {
    TSS_HPOLICY srk_usage_policy;
    if (auto err = CreateError<TPM1Error>(Tspi_GetPolicyObject(
            local_srk_handle, TSS_POLICY_USAGE, &srk_usage_policy))) {
      return err;
    }

    if (auto err = CreateError<TPM1Error>(Tspi_Policy_SetSecret(
            srk_usage_policy, TSS_SECRET_MODE_PLAIN, srk_auth_.size(),
            const_cast<BYTE*>(srk_auth_.data())))) {
      return err;
    }
  }

  *srk_handle = local_srk_handle.release();
  return nullptr;
}

bool TpmImpl::CreateEndorsementKey() {
  TSS_HTPM tpm_handle;
  if (!GetTpm(tpm_context_.value(), &tpm_handle)) {
    return false;
  }

  ScopedTssKey local_key_handle(tpm_context_.value());
  TSS_FLAG init_flags = TSS_KEY_TYPE_LEGACY | TSS_KEY_SIZE_2048;
  if (auto err = CreateError<TPM1Error>(Tspi_Context_CreateObject(
          tpm_context_.value(), TSS_OBJECT_TYPE_RSAKEY, init_flags,
          local_key_handle.ptr()))) {
    LOG(ERROR) << "Error calling Tspi_Context_CreateObject: " << *err;
    return false;
  }

  if (auto err = CreateError<TPM1Error>(
          Tspi_TPM_CreateEndorsementKey(tpm_handle, local_key_handle, NULL))) {
    LOG(ERROR) << "Error calling Tspi_TPM_CreateEndorsementKey: " << *err;
    return false;
  }

  return true;
}

bool TpmImpl::IsEndorsementKeyAvailable() {
  TSS_HTPM tpm_handle;
  if (!GetTpm(tpm_context_.value(), &tpm_handle)) {
    return false;
  }

  ScopedTssKey local_key_handle(tpm_context_.value());
  if (auto err = CreateError<TPM1Error>(Tspi_TPM_GetPubEndorsementKey(
          tpm_handle, false, NULL, local_key_handle.ptr()))) {
    LOG(ERROR) << "Error calling Tspi_TPM_GetPubEndorsementKey: " << *err;
    return false;
  }

  return true;
}

bool TpmImpl::TakeOwnership(int, const SecureBlob&) {
  if (!InitializeTpmManagerUtility()) {
    LOG(ERROR) << __func__ << ": Failed to initialize |TpmManagerUtility|.";
    return false;
  }
  if (IsOwned()) {
    LOG(INFO) << __func__ << ": TPM is already owned.";
    return true;
  }
  return tpm_manager_utility_->TakeOwnership();
}

bool TpmImpl::GetTpm(TSS_HCONTEXT context_handle, TSS_HTPM* tpm_handle) {
  TSS_HTPM local_tpm_handle;
  if (auto err = CreateError<TPM1Error>(
          Tspi_Context_GetTpmObject(context_handle, &local_tpm_handle))) {
    LOG(ERROR) << "Error calling Tspi_Context_GetTpmObject: " << *err;
    return false;
  }
  *tpm_handle = local_tpm_handle;
  return true;
}

bool TpmImpl::GetTpmWithAuth(TSS_HCONTEXT context_handle,
                             const SecureBlob& owner_password,
                             TSS_HTPM* tpm_handle) {
  TSS_HTPM local_tpm_handle;
  if (!GetTpm(context_handle, &local_tpm_handle)) {
    return false;
  }

  TSS_HPOLICY tpm_usage_policy;
  if (auto err = CreateError<TPM1Error>(Tspi_GetPolicyObject(
          local_tpm_handle, TSS_POLICY_USAGE, &tpm_usage_policy))) {
    LOG(ERROR) << "Error calling Tspi_GetPolicyObject: " << *err;
    return false;
  }

  if (auto err = CreateError<TPM1Error>(Tspi_Policy_SetSecret(
          tpm_usage_policy, TSS_SECRET_MODE_PLAIN, owner_password.size(),
          const_cast<BYTE*>(owner_password.data())))) {
    LOG(ERROR) << "Error calling Tspi_Policy_SetSecret: " << *err;
    return false;
  }

  *tpm_handle = local_tpm_handle;
  return true;
}

bool TpmImpl::GetTpmWithDelegation(TSS_HCONTEXT context_handle,
                                   const brillo::Blob& delegate_blob,
                                   const brillo::Blob& delegate_secret,
                                   TSS_HTPM* tpm_handle) {
  TSS_HTPM local_tpm_handle;
  if (!GetTpm(context_handle, &local_tpm_handle)) {
    return false;
  }

  TSS_HPOLICY tpm_usage_policy;
  if (auto err = CreateError<TPM1Error>(Tspi_GetPolicyObject(
          local_tpm_handle, TSS_POLICY_USAGE, &tpm_usage_policy))) {
    LOG(ERROR) << "Error calling Tspi_GetPolicyObject: " << *err;
    return false;
  }

  BYTE* secret_buffer = const_cast<BYTE*>(delegate_secret.data());
  if (auto err = CreateError<TPM1Error>(
          Tspi_Policy_SetSecret(tpm_usage_policy, TSS_SECRET_MODE_PLAIN,
                                delegate_secret.size(), secret_buffer))) {
    LOG(ERROR) << "Error calling Tspi_Policy_SetSecret: " << *err;
    return false;
  }

  if (auto err = CreateError<TPM1Error>(Tspi_SetAttribData(
          tpm_usage_policy, TSS_TSPATTRIB_POLICY_DELEGATION_INFO,
          TSS_TSPATTRIB_POLDEL_OWNERBLOB, delegate_blob.size(),
          const_cast<BYTE*>(delegate_blob.data())))) {
    LOG(ERROR) << "Error calling Tspi_SetAttribData: " << *err;
    return false;
  }

  *tpm_handle = local_tpm_handle;
  return true;
}

TPMErrorBase TpmImpl::GetOwnerPassword(brillo::SecureBlob* owner_password) {
  if (IsOwned()) {
    *owner_password =
        brillo::SecureBlob(last_tpm_manager_data_.owner_password());
    if (owner_password->empty()) {
      return CreateError<TPMError>(
          "Trying to get owner password after it is cleared",
          TPMRetryAction::kNoRetry);
    }
  } else {
    owner_password->clear();
    return CreateError<TPMError>(
        "Cannot get owner password until TPM is confirmed to be owned",
        TPMRetryAction::kNoRetry);
  }
  if (owner_password->empty()) {
    return CreateError<TPMError>("Empty owner password",
                                 TPMRetryAction::kNoRetry);
  }
  return nullptr;
}

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

TPMErrorBase TpmImpl::GetRandomDataSecureBlob(size_t length,
                                              brillo::SecureBlob* data) {
  ScopedTssContext context_handle;
  if ((*(context_handle.ptr()) = ConnectContext()) == 0) {
    return CreateError<TPMError>("Could not open the TPM",
                                 TPMRetryAction::kNoRetry);
  }

  TSS_HTPM tpm_handle;
  if (!GetTpm(context_handle, &tpm_handle)) {
    return CreateError<TPMError>("Could not get a handle to the TPM",
                                 TPMRetryAction::kNoRetry);
  }

  SecureBlob random(length);
  ScopedTssMemory tpm_data(context_handle);
  if (auto err = CreateError<TPM1Error>(
          Tspi_TPM_GetRandom(tpm_handle, random.size(), tpm_data.ptr()))) {
    return WrapError<TPMError>(std::move(err),
                               "Could not get random data from the TPM");
  }
  memcpy(random.data(), tpm_data.value(), random.size());
  brillo::SecureClearBytes(tpm_data.value(), random.size());
  data->swap(random);
  return nullptr;
}

TPMErrorBase TpmImpl::GetAlertsData(Tpm::AlertsData* alerts) {
  return CreateError<TPMError>("Not supported", TPMRetryAction::kNoRetry);
}

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

bool TpmImpl::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 TpmImpl::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;
}

unsigned int TpmImpl::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 TpmImpl::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 TpmImpl::ReadNvram(uint32_t index, SecureBlob* blob) {
  if (!InitializeTpmManagerUtility()) {
    return false;
  }

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

bool TpmImpl::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 TpmImpl::OwnerWriteNvram(uint32_t index, const SecureBlob& blob) {
  // Not implemented in TPM 1.2.
  // Note that technically the implementation should be the same as
  // `Tpm2Impl::OwnerWriteNvram()`; however, because 1. there is no demand by
  // cryptohome and 2. there is no active consumption of OWNERWRITE case for
  // TPM1.2, it is unnecessary and confusing to implement this block.
  return false;
}

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

bool TpmImpl::SealToPCR0(const brillo::SecureBlob& value,
                         brillo::SecureBlob* sealed_value) {
  CHECK(sealed_value);
  ScopedTssContext context_handle;
  TSS_HTPM tpm_handle;
  if (!ConnectContextAsUser(context_handle.ptr(), &tpm_handle)) {
    LOG(ERROR) << "SealToPCR0: Failed to connect to the TPM.";
    return false;
  }
  // Load the Storage Root Key.
  ScopedTssKey srk_handle(context_handle);
  if (TPM1Error err = LoadSrk(context_handle, srk_handle.ptr())) {
    LOG(ERROR) << __func__ << ": Failed to load SRK: " << *err;
    return false;
  }

  // Check the SRK public key
  unsigned int size_n = 0;
  ScopedTssMemory public_srk(context_handle);
  if (auto err = CreateError<TPM1Error>(
          Tspi_Key_GetPubKey(srk_handle, &size_n, public_srk.ptr()))) {
    LOG(ERROR) << __func__ << ": Unable to get the SRK public key: " << *err;
    return false;
  }

  // Create a PCRS object which holds the value of PCR0.
  ScopedTssPcrs pcrs_handle(context_handle);
  if (auto err = CreateError<TPM1Error>(
          Tspi_Context_CreateObject(context_handle, TSS_OBJECT_TYPE_PCRS,
                                    TSS_PCRS_STRUCT_INFO, pcrs_handle.ptr()))) {
    LOG(ERROR) << __func__
               << ": Error calling Tspi_Context_CreateObject: " << *err;
    return false;
  }

  // Create a ENCDATA object to receive the sealed data.
  UINT32 pcr_len = 0;
  ScopedTssMemory pcr_value(context_handle);
  Tspi_TPM_PcrRead(tpm_handle, 0, &pcr_len, pcr_value.ptr());
  Tspi_PcrComposite_SetPcrValue(pcrs_handle, 0, pcr_len, pcr_value.value());

  ScopedTssKey enc_handle(context_handle);
  if (auto err = CreateError<TPM1Error>(
          Tspi_Context_CreateObject(context_handle, TSS_OBJECT_TYPE_ENCDATA,
                                    TSS_ENCDATA_SEAL, enc_handle.ptr()))) {
    LOG(ERROR) << __func__
               << ": Error calling Tspi_Context_CreateObject: " << *err;
    return false;
  }

  // Seal the given value with the SRK.
  if (auto err = CreateError<TPM1Error>(
          Tspi_Data_Seal(enc_handle, srk_handle, value.size(),
                         const_cast<BYTE*>(value.data()), pcrs_handle))) {
    LOG(ERROR) << __func__ << ": Error calling Tspi_Data_Seal: " << *err;
    return false;
  }

  // Extract the sealed value.
  ScopedTssMemory enc_data(context_handle);
  UINT32 enc_data_length = 0;
  if (auto err = CreateError<TPM1Error>(Tspi_GetAttribData(
          enc_handle, TSS_TSPATTRIB_ENCDATA_BLOB,
          TSS_TSPATTRIB_ENCDATABLOB_BLOB, &enc_data_length, enc_data.ptr()))) {
    LOG(ERROR) << __func__ << ": Error calling Tspi_GetAttribData: " << *err;
    return false;
  }
  sealed_value->assign(&enc_data.value()[0],
                       &enc_data.value()[enc_data_length]);
  return true;
}

bool TpmImpl::Unseal(const brillo::SecureBlob& sealed_value,
                     brillo::SecureBlob* value) {
  CHECK(value);
  ScopedTssContext context_handle;
  TSS_HTPM tpm_handle;
  if (!ConnectContextAsUser(context_handle.ptr(), &tpm_handle)) {
    LOG(ERROR) << "Unseal: Failed to connect to the TPM.";
    return false;
  }
  // Load the Storage Root Key.
  ScopedTssKey srk_handle(context_handle);
  if (TPM1Error err = LoadSrk(context_handle, srk_handle.ptr())) {
    LOG(ERROR) << __func__ << ": Failed to load SRK: " << *err;
    return false;
  }

  // Create an ENCDATA object with the sealed value.
  ScopedTssKey enc_handle(context_handle);
  if (auto err = CreateError<TPM1Error>(
          Tspi_Context_CreateObject(context_handle, TSS_OBJECT_TYPE_ENCDATA,
                                    TSS_ENCDATA_SEAL, enc_handle.ptr()))) {
    LOG(ERROR) << __func__
               << ": Error calling Tspi_Context_CreateObject: " << *err;
    return false;
  }

  if (auto err = CreateError<TPM1Error>(Tspi_SetAttribData(
          enc_handle, TSS_TSPATTRIB_ENCDATA_BLOB,
          TSS_TSPATTRIB_ENCDATABLOB_BLOB, sealed_value.size(),
          const_cast<BYTE*>(sealed_value.data())))) {
    LOG(ERROR) << __func__ << ": Error calling Tspi_SetAttribData: " << *err;
    return false;
  }

  // Unseal using the SRK.
  ScopedTssMemory dec_data(context_handle);
  UINT32 dec_data_length = 0;
  if (auto err = CreateError<TPM1Error>(Tspi_Data_Unseal(
          enc_handle, srk_handle, &dec_data_length, dec_data.ptr()))) {
    LOG(ERROR) << __func__ << ": Error calling Tspi_Data_Unseal: " << *err;
    return false;
  }
  value->assign(&dec_data.value()[0], &dec_data.value()[dec_data_length]);
  brillo::SecureClearBytes(dec_data.value(), dec_data_length);
  return true;
}

bool TpmImpl::CreateDelegate(const std::set<uint32_t>& bound_pcrs,
                             uint8_t delegate_family_label,
                             uint8_t delegate_label,
                             Blob* delegate_blob,
                             Blob* delegate_secret) {
  CHECK(delegate_blob && delegate_secret);

  // Connect to the TPM as the owner.
  ScopedTssContext context_handle;
  TSS_HTPM tpm_handle;
  if (!ConnectContextAsOwner(context_handle.ptr(), &tpm_handle)) {
    LOG(ERROR) << __func__ << ": Could not connect to the TPM.";
    return false;
  }

  // Generate a delegate secret.
  if (TPMErrorBase err =
          GetRandomDataBlob(kDelegateSecretSize, delegate_secret)) {
    LOG(ERROR) << __func__ << ": Failed to get random data blob: " << *err;
    return false;
  }

  // Create an owner delegation policy.
  ScopedTssPolicy policy(context_handle);
  if (auto err = CreateError<TPM1Error>(
          Tspi_Context_CreateObject(context_handle, TSS_OBJECT_TYPE_POLICY,
                                    TSS_POLICY_USAGE, policy.ptr()))) {
    LOG(ERROR) << __func__ << ": Failed to create policy: " << *err;
    return false;
  }
  if (auto err = CreateError<TPM1Error>(Tspi_Policy_SetSecret(
          policy, TSS_SECRET_MODE_PLAIN, delegate_secret->size(),
          delegate_secret->data()))) {
    LOG(ERROR) << __func__ << ": Failed to set policy secret: " << *err;
    return false;
  }
  if (auto err = CreateError<TPM1Error>(Tspi_SetAttribUint32(
          policy, TSS_TSPATTRIB_POLICY_DELEGATION_INFO,
          TSS_TSPATTRIB_POLDEL_TYPE, TSS_DELEGATIONTYPE_OWNER))) {
    LOG(ERROR) << __func__ << ": Failed to set delegation type: " << *err;
    return false;
  }
  // These are the privileged operations we will allow the delegate to perform.
  const UINT32 permissions =
      TPM_DELEGATE_ActivateIdentity | TPM_DELEGATE_DAA_Join |
      TPM_DELEGATE_DAA_Sign | TPM_DELEGATE_ResetLockValue |
      TPM_DELEGATE_OwnerReadInternalPub | TPM_DELEGATE_CMK_ApproveMA |
      TPM_DELEGATE_CMK_CreateTicket | TPM_DELEGATE_AuthorizeMigrationKey;
  if (auto err = CreateError<TPM1Error>(
          Tspi_SetAttribUint32(policy, TSS_TSPATTRIB_POLICY_DELEGATION_INFO,
                               TSS_TSPATTRIB_POLDEL_PER1, permissions))) {
    LOG(ERROR) << __func__ << ": Failed to set permissions: " << *err;
    return false;
  }
  if (auto err = CreateError<TPM1Error>(
          Tspi_SetAttribUint32(policy, TSS_TSPATTRIB_POLICY_DELEGATION_INFO,
                               TSS_TSPATTRIB_POLDEL_PER2, 0))) {
    LOG(ERROR) << __func__ << ": Failed to set permissions: " << *err;
    return false;
  }

  // Bind the delegate to the specified PCRs. Note: it's crucial to pass a null
  // TSS_HPCRS to Tspi_TPM_Delegate_CreateDelegation() when no PCR is selected,
  // otherwise it will fail with TPM_E_BAD_PARAM_SIZE.
  ScopedTssPcrs pcrs_handle(context_handle);
  if (!bound_pcrs.empty()) {
    if (auto err = CreateError<TPM1Error>(Tspi_Context_CreateObject(
            context_handle, TSS_OBJECT_TYPE_PCRS, TSS_PCRS_STRUCT_INFO_SHORT,
            pcrs_handle.ptr()))) {
      LOG(ERROR) << __func__ << ": Failed to create PCRS object: " << *err;
      return false;
    }
    for (auto bound_pcr : bound_pcrs) {
      UINT32 pcr_len = 0;
      ScopedTssMemory pcr_value(context_handle);
      if (auto err = CreateError<TPM1Error>(Tspi_TPM_PcrRead(
              tpm_handle, bound_pcr, &pcr_len, pcr_value.ptr()))) {
        LOG(ERROR) << __func__ << ": Could not read PCR value: " << *err;
        return false;
      }
      if (auto err = CreateError<TPM1Error>(Tspi_PcrComposite_SetPcrValue(
              pcrs_handle, bound_pcr, pcr_len, pcr_value.value()))) {
        LOG(ERROR) << __func__
                   << ": Could not set value for PCR in PCRS handle: " << *err;
        return false;
      }
    }
    if (auto err = CreateError<TPM1Error>(
            Tspi_PcrComposite_SetPcrLocality(pcrs_handle, kTpmPCRLocality))) {
      LOG(ERROR) << __func__
                 << ": Could not set locality for PCRs in PCRS handle: "
                 << *err;
      return false;
    }
  }

  // Create a delegation family.
  ScopedTssObject<TSS_HDELFAMILY> family(context_handle);
  if (auto err = CreateError<TPM1Error>(Tspi_TPM_Delegate_AddFamily(
          tpm_handle, delegate_family_label, family.ptr()))) {
    LOG(ERROR) << __func__ << ": Failed to create family: " << *err;
    return false;
  }

  // Create the delegation.
  if (auto err = CreateError<TPM1Error>(Tspi_TPM_Delegate_CreateDelegation(
          tpm_handle, delegate_label, 0, pcrs_handle, family, policy))) {
    LOG(ERROR) << __func__ << ": Failed to create delegation: " << *err;
    return false;
  }

  // Enable the delegation family.
  if (auto err = CreateError<TPM1Error>(
          Tspi_SetAttribUint32(family, TSS_TSPATTRIB_DELFAMILY_STATE,
                               TSS_TSPATTRIB_DELFAMILYSTATE_ENABLED, TRUE))) {
    LOG(ERROR) << __func__ << ": Failed to enable family: " << *err;
    return false;
  }

  // Save the delegation blob for later.
  SecureBlob delegate;
  if (TPM1Error err = GetDataAttribute(
          context_handle, policy, TSS_TSPATTRIB_POLICY_DELEGATION_INFO,
          TSS_TSPATTRIB_POLDEL_OWNERBLOB, &delegate)) {
    LOG(ERROR) << __func__ << ": Failed to get delegate blob: " << *err;
    return false;
  }
  delegate_blob->assign(delegate.begin(), delegate.end());
  is_delegate_bound_to_pcr_ = !bound_pcrs.empty();
  has_reset_lock_permissions_ = true;

  return true;
}

bool TpmImpl::Sign(const SecureBlob& key_blob,
                   const SecureBlob& input,
                   uint32_t bound_pcr_index,
                   SecureBlob* signature) {
  CHECK(signature);
  ScopedTssContext context_handle;
  TSS_HTPM tpm_handle;
  if (!ConnectContextAsUser(context_handle.ptr(), &tpm_handle)) {
    LOG(ERROR) << __func__ << ": Failed to connect to the TPM.";
    return false;
  }

  // Load the Storage Root Key.
  ScopedTssKey srk_handle(context_handle);
  if (TPM1Error err = LoadSrk(context_handle, srk_handle.ptr())) {
    LOG(ERROR) << __func__ << ": Failed to load SRK: " << *err;
    return false;
  }

  // Load the key (which should be wrapped by the SRK).
  ScopedTssKey key_handle(context_handle);
  if (auto err = CreateError<TPM1Error>(Tspi_Context_LoadKeyByBlob(
          context_handle, srk_handle, key_blob.size(),
          const_cast<BYTE*>(key_blob.data()), key_handle.ptr()))) {
    LOG(ERROR) << __func__ << ": Failed to load key: " << *err;
    return false;
  }

  // Create a hash object to hold the input.
  ScopedTssObject<TSS_HHASH> hash_handle(context_handle);
  if (auto err = CreateError<TPM1Error>(
          Tspi_Context_CreateObject(context_handle, TSS_OBJECT_TYPE_HASH,
                                    TSS_HASH_OTHER, hash_handle.ptr()))) {
    LOG(ERROR) << __func__ << ": Failed to create hash object: " << *err;
    return false;
  }

  // Create the DER encoded input.
  SecureBlob der_header(std::begin(kSha256DigestInfo),
                        std::end(kSha256DigestInfo));
  SecureBlob der_encoded_input = SecureBlob::Combine(der_header, Sha256(input));

  // Don't hash anything, just push the input data into the hash object.
  if (auto err = CreateError<TPM1Error>(Tspi_Hash_SetHashValue(
          hash_handle, der_encoded_input.size(),
          const_cast<BYTE*>(der_encoded_input.data())))) {
    LOG(ERROR) << __func__ << ": Failed to set hash data: " << *err;
    return false;
  }

  UINT32 length = 0;
  ScopedTssMemory buffer(context_handle);
  if (auto err = CreateError<TPM1Error>(
          Tspi_Hash_Sign(hash_handle, key_handle, &length, buffer.ptr()))) {
    LOG(ERROR) << __func__ << ": Failed to generate signature: " << *err;
    return false;
  }
  SecureBlob tmp(buffer.value(), buffer.value() + length);
  brillo::SecureClearBytes(buffer.value(), length);
  signature->swap(tmp);
  return true;
}

bool TpmImpl::CreatePCRBoundKey(const std::map<uint32_t, std::string>& pcr_map,
                                AsymmetricKeyUsage key_type,
                                brillo::SecureBlob* key_blob,
                                brillo::SecureBlob* public_key_der,
                                brillo::SecureBlob* creation_blob) {
  CHECK(creation_blob) << "Error no creation_blob.";
  creation_blob->clear();
  ScopedTssContext context_handle;
  TSS_HTPM tpm_handle;
  if (!ConnectContextAsUser(context_handle.ptr(), &tpm_handle)) {
    LOG(ERROR) << __func__ << ": Failed to connect to the TPM.";
    return false;
  }

  // Load the Storage Root Key.
  ScopedTssKey srk_handle(context_handle);
  if (TPM1Error err = LoadSrk(context_handle, srk_handle.ptr())) {
    LOG(ERROR) << __func__ << ": Failed to load SRK: " << *err;
    return false;
  }

  // Create a PCRS object to hold pcr_index and pcr_value.
  ScopedTssPcrs pcrs(context_handle);
  if (auto err = CreateError<TPM1Error>(
          Tspi_Context_CreateObject(context_handle, TSS_OBJECT_TYPE_PCRS,
                                    TSS_PCRS_STRUCT_INFO, pcrs.ptr()))) {
    LOG(ERROR) << __func__ << ": Failed to create PCRS object: " << *err;
    return false;
  }

  for (const auto& map_pair : pcr_map) {
    uint32_t pcr_index = map_pair.first;
    Blob pcr_value(BlobFromString(map_pair.second));
    if (pcr_value.empty()) {
      if (!ReadPCR(pcr_index, &pcr_value)) {
        LOG(ERROR) << __func__ << ": Failed to read PCR.";
        return false;
      }
    }

    BYTE* pcr_value_buffer = const_cast<BYTE*>(pcr_value.data());
    Tspi_PcrComposite_SetPcrValue(pcrs, pcr_index, pcr_value.size(),
                                  pcr_value_buffer);
  }

  // Create a non-migratable key restricted to |pcrs|.
  ScopedTssKey pcr_bound_key(context_handle);
  TSS_FLAG init_flags =
      TSS_KEY_VOLATILE | TSS_KEY_NOT_MIGRATABLE | kDefaultTpmRsaKeyFlag;
  switch (key_type) {
    case AsymmetricKeyUsage::kDecryptKey:
      // In this case, the key is not decrypt only. It can be used to sign the
      // data too. No easy way to make a decrypt only key here.
      init_flags |= TSS_KEY_TYPE_LEGACY;
      break;
    case AsymmetricKeyUsage::kSignKey:
      init_flags |= TSS_KEY_TYPE_SIGNING;
      break;
    case AsymmetricKeyUsage::kDecryptAndSignKey:
      init_flags |= TSS_KEY_TYPE_LEGACY;
      break;
  }
  if (auto err = CreateError<TPM1Error>(
          Tspi_Context_CreateObject(context_handle, TSS_OBJECT_TYPE_RSAKEY,
                                    init_flags, pcr_bound_key.ptr()))) {
    LOG(ERROR) << __func__ << ": Failed to create object: " << *err;
    return false;
  }

  if (auto err = CreateError<TPM1Error>(Tspi_SetAttribUint32(
          pcr_bound_key, TSS_TSPATTRIB_KEY_INFO,
          TSS_TSPATTRIB_KEYINFO_SIGSCHEME, TSS_SS_RSASSAPKCS1V15_DER))) {
    LOG(ERROR) << __func__ << ": Failed to set signature scheme: " << *err;
    return false;
  }
  if (auto err = CreateError<TPM1Error>(
          Tspi_Key_CreateKey(pcr_bound_key, srk_handle, pcrs))) {
    LOG(ERROR) << __func__ << ": Failed to create key: " << *err;
    return false;
  }
  if (auto err =
          CreateError<TPM1Error>(Tspi_Key_LoadKey(pcr_bound_key, srk_handle))) {
    LOG(ERROR) << __func__ << ": Failed to load key: " << *err;
    return false;
  }

  // Get the public key.
  SecureBlob public_key;
  if (TPM1Error err = GetDataAttribute(
          context_handle, pcr_bound_key, TSS_TSPATTRIB_KEY_BLOB,
          TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, &public_key)) {
    LOG(ERROR) << __func__ << ": Failed to read public key: " << *err;
    return false;
  }
  if (!ConvertPublicKeyToDER(public_key, public_key_der)) {
    return false;
  }

  // Get the key blob so we can load it later.
  if (TPM1Error err = GetDataAttribute(context_handle, pcr_bound_key,
                                       TSS_TSPATTRIB_KEY_BLOB,
                                       TSS_TSPATTRIB_KEYBLOB_BLOB, key_blob)) {
    LOG(ERROR) << __func__ << ": Failed to read key blob: " << *err;
    return false;
  }
  return true;
}

bool TpmImpl::VerifyPCRBoundKey(const std::map<uint32_t, std::string>& pcr_map,
                                const brillo::SecureBlob& key_blob,
                                const brillo::SecureBlob& creation_blob) {
  ScopedTssContext context_handle;
  TSS_HTPM tpm_handle;
  if (!ConnectContextAsUser(context_handle.ptr(), &tpm_handle)) {
    LOG(ERROR) << __func__ << ": Failed to connect to the TPM.";
    return false;
  }

  ScopedTssKey srk_handle(context_handle);
  if (TPM1Error err = LoadSrk(context_handle, srk_handle.ptr())) {
    LOG(ERROR) << __func__ << ": Failed to load SRK: " << *err;
    return false;
  }

  ScopedTssKey key(context_handle);
  if (auto err = CreateError<TPM1Error>(Tspi_Context_LoadKeyByBlob(
          context_handle, srk_handle, key_blob.size(),
          const_cast<BYTE*>(key_blob.data()), key.ptr()))) {
    LOG(ERROR) << __func__ << ": Failed to load key: " << *err;
    return false;
  }

  // Check that |pcr_index| is selected.
  SecureBlob pcr_selection_blob;
  if (TPM1Error err = GetDataAttribute(
          context_handle, key, TSS_TSPATTRIB_KEY_PCR,
          TSS_TSPATTRIB_KEYPCR_SELECTION, &pcr_selection_blob)) {
    LOG(ERROR) << __func__
               << ": Failed to read PCR selection for key: " << *err;
    return false;
  }
  UINT64 trspi_offset = 0;
  TPM_PCR_SELECTION pcr_selection;
  Trspi_UnloadBlob_PCR_SELECTION(&trspi_offset, pcr_selection_blob.data(),
                                 &pcr_selection);
  if (!pcr_selection.pcrSelect) {
    LOG(ERROR) << __func__ << ": No PCR selected.";
    return false;
  }
  const Blob pcr_bitmap(pcr_selection.pcrSelect,
                        pcr_selection.pcrSelect + pcr_selection.sizeOfSelect);
  free(pcr_selection.pcrSelect);
  std::string concatenated_pcr_values;
  for (const auto& map_pair : pcr_map) {
    uint32_t pcr_index = map_pair.first;
    const std::string pcr_value = map_pair.second;
    size_t offset = pcr_index / 8;
    unsigned char mask = 1 << (pcr_index % 8);
    if (pcr_bitmap.size() <= offset || (pcr_bitmap[offset] & mask) == 0) {
      LOG(ERROR) << __func__ << ": Invalid PCR selection.";
      return false;
    }

    concatenated_pcr_values += pcr_value;
  }

  // Compute the PCR composite hash we're expecting. Basically, we want to do
  // the equivalent of hashing a TPM_PCR_COMPOSITE structure.
  trspi_offset = 0;
  UINT32 pcr_value_length = concatenated_pcr_values.size();
  Blob pcr_value_length_blob(sizeof(UINT32));
  Trspi_LoadBlob_UINT32(&trspi_offset, pcr_value_length,
                        pcr_value_length_blob.data());
  const SecureBlob pcr_hash = Sha1ToSecureBlob(CombineBlobs(
      {Blob(pcr_selection_blob.begin(), pcr_selection_blob.end()),
       pcr_value_length_blob, BlobFromString(concatenated_pcr_values)}));

  // Check that the PCR value matches the key creation PCR value.
  SecureBlob pcr_at_creation;
  if (TPM1Error err = GetDataAttribute(
          context_handle, key, TSS_TSPATTRIB_KEY_PCR,
          TSS_TSPATTRIB_KEYPCR_DIGEST_ATCREATION, &pcr_at_creation)) {
    LOG(ERROR) << __func__ << ": Failed to read PCR value at key creation"
               << *err;
    return false;
  }

  if (pcr_at_creation != pcr_hash) {
    LOG(ERROR) << __func__ << ": Invalid key creation PCR.";
    return false;
  }

  // Check that the PCR value matches the PCR value required to use the key.
  SecureBlob pcr_at_release;
  if (TPM1Error err = GetDataAttribute(
          context_handle, key, TSS_TSPATTRIB_KEY_PCR,
          TSS_TSPATTRIB_KEYPCR_DIGEST_ATRELEASE, &pcr_at_release)) {
    LOG(ERROR) << __func__
               << ": Failed to read PCR value for key usage: " << *err;
    return false;
  }
  if (pcr_at_release != pcr_hash) {
    LOG(ERROR) << __func__ << ": Invalid key usage PCR.";
    return false;
  }
  return true;
}

bool TpmImpl::ExtendPCR(uint32_t pcr_index, const brillo::Blob& extension) {
  ScopedTssContext context_handle;
  TSS_HTPM tpm_handle;
  if (!ConnectContextAsUser(context_handle.ptr(), &tpm_handle)) {
    LOG(ERROR) << __func__ << ": Failed to connect to the TPM.";
    return false;
  }
  CHECK_EQ(extension.size(), kPCRExtensionSize);
  Blob mutable_extension = extension;
  UINT32 new_pcr_value_length = 0;
  ScopedTssMemory new_pcr_value(context_handle);
  if (auto err = CreateError<TPM1Error>(Tspi_TPM_PcrExtend(
          tpm_handle, pcr_index, extension.size(), mutable_extension.data(),
          NULL, &new_pcr_value_length, new_pcr_value.ptr()))) {
    LOG(ERROR) << "Failed to extend PCR " << pcr_index << ": " << *err;
    return false;
  }
  return true;
}

bool TpmImpl::ReadPCR(uint32_t pcr_index, brillo::Blob* pcr_value) {
  ScopedTssContext context_handle;
  TSS_HTPM tpm_handle;
  if (!ConnectContextAsUser(context_handle.ptr(), &tpm_handle)) {
    LOG(ERROR) << __func__ << ": Failed to connect to the TPM.";
    return false;
  }
  UINT32 pcr_len = 0;
  ScopedTssMemory pcr_value_buffer(context_handle);
  if (auto err = CreateError<TPM1Error>(Tspi_TPM_PcrRead(
          tpm_handle, pcr_index, &pcr_len, pcr_value_buffer.ptr()))) {
    LOG(ERROR) << "Could not read PCR " << pcr_index << ": " << *err;
    return false;
  }
  pcr_value->assign(pcr_value_buffer.value(),
                    pcr_value_buffer.value() + pcr_len);
  return true;
}

TPM1Error TpmImpl::GetDataAttribute(TSS_HCONTEXT context,
                                    TSS_HOBJECT object,
                                    TSS_FLAG flag,
                                    TSS_FLAG sub_flag,
                                    SecureBlob* data) const {
  UINT32 length = 0;
  ScopedTssMemory buf(context);
  if (auto err = CreateError<TPM1Error>(
          Tspi_GetAttribData(object, flag, sub_flag, &length, buf.ptr()))) {
    LOG(ERROR) << "Failed to read object attribute: " << *err;
    return err;
  }
  SecureBlob tmp(buf.value(), buf.value() + length);
  brillo::SecureClearBytes(buf.value(), length);
  data->swap(tmp);
  return nullptr;
}

bool TpmImpl::IsEnabled() {
  if (!is_enabled_) {
    if (!CacheTpmManagerStatus()) {
      LOG(ERROR) << __func__
                 << ": Failed to update TPM status from tpm manager.";
      return false;
    }
  }
  return is_enabled_;
}

bool TpmImpl::IsOwned() {
  if (!is_owned_) {
    if (!UpdateLocalDataFromTpmManager()) {
      LOG(ERROR) << __func__
                 << ": Failed to call |UpdateLocalDataFromTpmManager|.";
      return false;
    }
  }
  return is_owned_;
}

bool TpmImpl::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 TpmImpl::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;
}

bool TpmImpl::WrapRsaKey(const SecureBlob& public_modulus,
                         const SecureBlob& prime_factor,
                         SecureBlob* wrapped_key) {
  // Load the Storage Root Key
  trousers::ScopedTssKey srk_handle(tpm_context_.value());
  if (TPM1Error err = LoadSrk(tpm_context_.value(), srk_handle.ptr())) {
    if (err->ErrorCode() != kKeyNotFoundError) {
      LOG(ERROR) << __func__ << ": Failed to load SRK: " << *err;
    }
    return false;
  }

  // Make sure we can get the public key for the SRK.  If not, then the TPM
  // is not available.
  unsigned int size_n;
  trousers::ScopedTssMemory public_srk(tpm_context_.value());
  if (auto err = CreateError<TPM1Error>(
          Tspi_Key_GetPubKey(srk_handle, &size_n, public_srk.ptr()))) {
    LOG(ERROR) << __func__ << ": Cannot load SRK pub key: " << *err;
    return false;
  }

  // Create the key object
  TSS_FLAG init_flags = TSS_KEY_TYPE_LEGACY | TSS_KEY_VOLATILE |
                        TSS_KEY_MIGRATABLE | kDefaultTpmRsaKeyFlag;
  trousers::ScopedTssKey local_key_handle(tpm_context_.value());
  if (auto err = CreateError<TPM1Error>(Tspi_Context_CreateObject(
          tpm_context_.value(), TSS_OBJECT_TYPE_RSAKEY, init_flags,
          local_key_handle.ptr()))) {
    LOG(ERROR) << __func__
               << ": Error calling Tspi_Context_CreateObject: " << *err;
    return false;
  }

  // Set the attributes
  UINT32 sig_scheme = TSS_SS_RSASSAPKCS1V15_DER;
  if (auto err = CreateError<TPM1Error>(
          Tspi_SetAttribUint32(local_key_handle, TSS_TSPATTRIB_KEY_INFO,
                               TSS_TSPATTRIB_KEYINFO_SIGSCHEME, sig_scheme))) {
    LOG(ERROR) << __func__ << ": Error calling Tspi_SetAttribUint32: " << *err;
    return false;
  }

  UINT32 enc_scheme = TSS_ES_RSAESPKCSV15;
  if (auto err = CreateError<TPM1Error>(
          Tspi_SetAttribUint32(local_key_handle, TSS_TSPATTRIB_KEY_INFO,
                               TSS_TSPATTRIB_KEYINFO_ENCSCHEME, enc_scheme))) {
    LOG(ERROR) << __func__ << ": Error calling Tspi_SetAttribUint32: " << *err;
    return false;
  }

  // Set a random migration policy password, and discard it.  The key will not
  // be migrated, but to create the key outside of the TPM, we have to do it
  // this way.
  trousers::ScopedTssPolicy policy_handle(tpm_context_);
  if (!CreatePolicyWithRandomPassword(tpm_context_, TSS_POLICY_MIGRATION,
                                      policy_handle.ptr())) {
    LOG(ERROR) << __func__ << ": Error creating policy object";
    return false;
  }
  if (auto err = CreateError<TPM1Error>(
          Tspi_Policy_AssignToObject(policy_handle, local_key_handle))) {
    LOG(ERROR) << __func__ << ": Error assigning migration policy: " << *err;
    return false;
  }

  SecureBlob mutable_modulus(public_modulus.begin(), public_modulus.end());
  BYTE* public_modulus_buffer = static_cast<BYTE*>(mutable_modulus.data());
  if (auto err = CreateError<TPM1Error>(
          Tspi_SetAttribData(local_key_handle, TSS_TSPATTRIB_RSAKEY_INFO,
                             TSS_TSPATTRIB_KEYINFO_RSA_MODULUS,
                             public_modulus.size(), public_modulus_buffer))) {
    LOG(ERROR) << __func__ << ": Error setting RSA modulus: " << *err;
    return false;
  }
  SecureBlob mutable_factor(prime_factor.begin(), prime_factor.end());
  BYTE* prime_factor_buffer = static_cast<BYTE*>(mutable_factor.data());
  if (auto err = CreateError<TPM1Error>(
          Tspi_SetAttribData(local_key_handle, TSS_TSPATTRIB_KEY_BLOB,
                             TSS_TSPATTRIB_KEYBLOB_PRIVATE_KEY,
                             prime_factor.size(), prime_factor_buffer))) {
    LOG(ERROR) << __func__ << ": Error setting private key: " << *err;
    return false;
  }

  if (auto err = CreateError<TPM1Error>(
          Tspi_Key_WrapKey(local_key_handle, srk_handle, 0))) {
    LOG(ERROR) << __func__ << ": Error wrapping RSA key: " << *err;
    return false;
  }

  if (TPM1Error err =
          GetKeyBlob(tpm_context_.value(), local_key_handle, wrapped_key)) {
    LOG(ERROR) << "Failed to GetKeyBlob: " << *err;
    return false;
  }

  return true;
}

TPM1Error TpmImpl::GetKeyBlob(TSS_HCONTEXT context_handle,
                              TSS_HKEY key_handle,
                              SecureBlob* data_out) const {
  if (TPM1Error err =
          GetDataAttribute(context_handle, key_handle, TSS_TSPATTRIB_KEY_BLOB,
                           TSS_TSPATTRIB_KEYBLOB_BLOB, data_out)) {
    LOG(ERROR) << __func__ << ": Failed to get key blob " << *err;
    return err;
  }

  return nullptr;
}

TPMErrorBase TpmImpl::LoadWrappedKey(const brillo::SecureBlob& wrapped_key,
                                     ScopedKeyHandle* key_handle) {
  CHECK(key_handle);
  // Load the Storage Root Key
  trousers::ScopedTssKey srk_handle(tpm_context_.value());
  if (TPM1Error err = LoadSrk(tpm_context_.value(), srk_handle.ptr())) {
    if (err->ErrorCode() != kKeyNotFoundError) {
      ReportCryptohomeError(kCannotLoadTpmSrk);
    }
    return WrapError<TPMError>(std::move(err), "Failed to load SRK");
  }

  // Make sure we can get the public key for the SRK.  If not, then the TPM
  // is not available.
  {
    SecureBlob pubkey;
    if (TPM1Error err =
            GetPublicKeyBlob(tpm_context_.value(), srk_handle, &pubkey)) {
      ReportCryptohomeError(kCannotReadTpmSrkPublic);
      return WrapError<TPMError>(std::move(err), "Cannot load SRK public key");
    }
  }
  TpmKeyHandle local_key_handle;
  if (auto err = CreateError<TPM1Error>(Tspi_Context_LoadKeyByBlob(
          tpm_context_.value(), srk_handle, wrapped_key.size(),
          const_cast<BYTE*>(wrapped_key.data()), &local_key_handle))) {
    ReportCryptohomeError(kCannotLoadTpmKey);
    if (err->ErrorCode() == TPM_E_BAD_KEY_PROPERTY) {
      ReportCryptohomeError(kTpmBadKeyProperty);
    }
    return WrapError<TPMError>(std::move(err), "Cannot load key from blob");
  }

  SecureBlob pub_key;
  // Make sure that we can get the public key
  if (TPM1Error err =
          GetPublicKeyBlob(tpm_context_.value(), local_key_handle, &pub_key)) {
    ReportCryptohomeError(kCannotReadTpmPublicKey);
    Tspi_Context_CloseObject(tpm_context_.value(), local_key_handle);
    return WrapError<TPMError>(std::move(err),
                               "Cannot get public key from blob");
  }
  key_handle->reset(this, local_key_handle);
  return nullptr;
}

bool TpmImpl::LegacyLoadCryptohomeKey(ScopedKeyHandle* key_handle,
                                      brillo::SecureBlob* key_blob) {
  CHECK(key_handle);
  TpmKeyHandle local_key_handle;
  if (auto err = CreateError<TPM1Error>(Tspi_Context_LoadKeyByUUID(
          tpm_context_.value(), TSS_PS_TYPE_SYSTEM, kCryptohomeWellKnownUuid,
          &local_key_handle))) {
    LOG(ERROR) << __func__ << ": failed LoadKeyByUUID: " << *err;
    return false;
  }

  if (key_blob) {
    if (TPM1Error err =
            GetKeyBlob(tpm_context_.value(), local_key_handle, key_blob)) {
      LOG(ERROR) << __func__ << ": failed to GetKeyBlob: " << *err;
      Tspi_Context_CloseObject(tpm_context_.value(), local_key_handle);
      return false;
    }
  }
  key_handle->reset(this, local_key_handle);
  return true;
}

void TpmImpl::CloseHandle(TpmKeyHandle key_handle) {
  Tspi_Context_CloseObject(tpm_context_.value(), key_handle);
}

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

bool TpmImpl::ClearStoredPassword() {
  if (!InitializeTpmManagerUtility()) {
    LOG(ERROR) << __func__ << ": failed to initialize |TpmManagerUtility|.";
    return false;
  }
  return tpm_manager_utility_->ClearStoredOwnerPassword();
}

bool TpmImpl::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;
}

static void ParseIFXFirmwarePackage(
    uint64_t* offset,
    uint8_t* buffer,
    Tpm::IFXFieldUpgradeInfo::FirmwarePackage* firmware_package) {
  Trspi_UnloadBlob_UINT32(offset, &firmware_package->package_id, buffer);
  Trspi_UnloadBlob_UINT32(offset, &firmware_package->version, buffer);
  Trspi_UnloadBlob_UINT32(offset, &firmware_package->stale_version, buffer);
}

bool TpmImpl::GetIFXFieldUpgradeInfo(IFXFieldUpgradeInfo* info) {
  ScopedTssContext context_handle;
  if ((*(context_handle.ptr()) = ConnectContext()) == 0) {
    LOG(ERROR) << "Could not open the TPM";
    return false;
  }

  TSS_HTPM tpm_handle;
  if (!GetTpm(context_handle, &tpm_handle)) {
    LOG(ERROR) << "Could not get a handle to the TPM.";
    return false;
  }

  uint8_t kRequest[] = {0x11, 0x00, 0x00};
  uint32_t response_size;
  ScopedTssMemory response(context_handle);
  if (auto err = CreateError<TPM1Error>(
          Tspi_TPM_FieldUpgrade(tpm_handle, sizeof(kRequest), kRequest,
                                &response_size, response.ptr()))) {
    LOG(ERROR) << "Error calling Tspi_TPM_FieldUpgrade: " << *err;
    return false;
  }

  const uint32_t kFieldUpgradeInfo2Size = 106;
  const uint32_t kFieldUpgradeResponseSize =
      kFieldUpgradeInfo2Size + sizeof(uint16_t);
  if (response_size < kFieldUpgradeResponseSize) {
    LOG(ERROR) << "FieldUpgrade response too short";
    return false;
  }

  // Parse the response.
  uint64_t offset = 0;
  uint16_t size = 0;
  Trspi_UnloadBlob_UINT16(&offset, &size, response.value());

  if (size != kFieldUpgradeInfo2Size) {
    LOG(ERROR) << "FieldUpgrade response size too short";
    return false;
  }

  Trspi_UnloadBlob_UINT16(&offset, NULL, response.value());
  Trspi_UnloadBlob_UINT16(&offset, &info->max_data_size, response.value());
  Trspi_UnloadBlob_UINT16(&offset, NULL, response.value());
  Trspi_UnloadBlob_UINT32(&offset, NULL, response.value());
  offset += 34;
  ParseIFXFirmwarePackage(&offset, response.value(), &info->bootloader);
  Trspi_UnloadBlob_UINT16(&offset, NULL, response.value());
  ParseIFXFirmwarePackage(&offset, response.value(), &info->firmware[0]);
  ParseIFXFirmwarePackage(&offset, response.value(), &info->firmware[1]);
  Trspi_UnloadBlob_UINT16(&offset, &info->status, response.value());
  ParseIFXFirmwarePackage(&offset, response.value(), &info->process_fw);
  Trspi_UnloadBlob_UINT16(&offset, NULL, response.value());
  offset += 6;
  Trspi_UnloadBlob_UINT16(&offset, &info->field_upgrade_counter,
                          response.value());

  CHECK_EQ(offset, kFieldUpgradeResponseSize);

  return true;
}

bool TpmImpl::SetDelegateData(const brillo::Blob& delegate_blob,
                              bool has_reset_lock_permissions) {
  if (delegate_blob.size() == 0) {
    LOG(ERROR) << __func__ << ": Empty blob.";
    return false;
  }

  has_reset_lock_permissions_ = has_reset_lock_permissions;
  UINT64 offset = 0;
  TPM_DELEGATE_OWNER_BLOB ownerBlob;
  // TODO(b/169392230): Fix the potential memory leak while migrating to tpm
  // manager.

  if (auto err =
          CreateError<TPM1Error>(Trspi_UnloadBlob_TPM_DELEGATE_OWNER_BLOB(
              &offset, const_cast<BYTE*>(delegate_blob.data()), &ownerBlob))) {
    LOG(ERROR) << __func__ << ": Failed to unload delegate blob: " << *err;
    return false;
  }

  if (ownerBlob.pub.pcrInfo.pcrSelection.sizeOfSelect > 1 &&
      ownerBlob.pub.pcrInfo.pcrSelection.pcrSelect != nullptr) {
    is_delegate_bound_to_pcr_ =
        (ownerBlob.pub.pcrInfo.pcrSelection.pcrSelect[0] != 0) ||
        (ownerBlob.pub.pcrInfo.pcrSelection.pcrSelect[1] != 0);
  } else {
    LOG(WARNING) << __func__ << ": Unexpected PCR information: "
                 << ownerBlob.pub.pcrInfo.pcrSelection.sizeOfSelect << " (at "
                 << ownerBlob.pub.pcrInfo.pcrSelection.pcrSelect << ").";
    return false;
  }
  return true;
}

TPMErrorBase TpmImpl::IsDelegateBoundToPcr(bool* result) {
  if (!SetDelegateDataFromTpmManager()) {
    LOG(WARNING) << __func__
                 << ": failed to call |SetDelegateDataFromTpmManager|.";
    return CreateError<TPMError>(
        "failed to call |SetDelegateDataFromTpmManager|",
        TPMRetryAction::kNoRetry);
  }
  *result = is_delegate_bound_to_pcr_;
  return nullptr;
}

bool TpmImpl::DelegateCanResetDACounter() {
  if (!SetDelegateDataFromTpmManager()) {
    LOG(WARNING) << __func__
                 << ": failed to call |SetDelegateDataFromTpmManager|.";
  }
  return has_reset_lock_permissions_;
}

bool TpmImpl::GetRsuDeviceId(std::string* device_id) {
  // Not supported for TPM 1.2.
  return false;
}

LECredentialBackend* TpmImpl::GetLECredentialBackend() {
  // Not implemented in TPM 1.2.
  return nullptr;
}

SignatureSealingBackend* TpmImpl::GetSignatureSealingBackend() {
  return &signature_sealing_backend_;
}

bool TpmImpl::GetDelegate(brillo::Blob* blob,
                          brillo::Blob* secret,
                          bool* has_reset_lock_permissions) {
  blob->clear();
  secret->clear();
  if (last_tpm_manager_data_.owner_delegate().blob().empty() ||
      last_tpm_manager_data_.owner_delegate().secret().empty()) {
    if (!CacheTpmManagerStatus()) {
      LOG(ERROR) << __func__
                 << ": Failed to call |UpdateLocalDataFromTpmManager|.";
      return false;
    }
  }
  const auto& owner_delegate = last_tpm_manager_data_.owner_delegate();
  *blob = brillo::BlobFromString(owner_delegate.blob());
  *secret = brillo::BlobFromString(owner_delegate.secret());
  *has_reset_lock_permissions = owner_delegate.has_reset_lock_permissions();
  return !blob->empty() && !secret->empty();
}

std::map<uint32_t, std::string> TpmImpl::GetPcrMap(
    const std::string& obfuscated_username, bool use_extended_pcr) const {
  std::map<uint32_t, std::string> pcr_map;
  if (use_extended_pcr) {
    SecureBlob starting_value(SHA_DIGEST_LENGTH, 0);
    SecureBlob digest_value = Sha1(SecureBlob::Combine(
        starting_value, Sha1(SecureBlob(obfuscated_username))));
    pcr_map[kTpmSingleUserPCR] = digest_value.to_string();
  } else {
    pcr_map[kTpmSingleUserPCR] = std::string(SHA_DIGEST_LENGTH, 0);
  }

  return pcr_map;
}

bool TpmImpl::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 TpmImpl::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 TpmImpl::UpdateLocalDataFromTpmManager() {
  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.
  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 (!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 TpmImpl::SetDelegateDataFromTpmManager() {
  if (has_set_delegate_data_) {
    return true;
  }
  brillo::Blob blob, unused_secret;
  bool has_reset_lock_permissions = false;
  if (GetDelegate(&blob, &unused_secret, &has_reset_lock_permissions)) {
    // Don't log the error at this level but by the called function and the
    // functions that call it.
    has_set_delegate_data_ |= SetDelegateData(blob, has_reset_lock_permissions);
  }
  return has_set_delegate_data_;
}

TPMErrorBase TpmImpl::GetAuthValue(base::Optional<TpmKeyHandle> key_handle,
                                   const SecureBlob& pass_blob,
                                   SecureBlob* auth_value) {
  // For TPM1.2, the |auth_value| should be the same as |pass_blob|.
  *auth_value = pass_blob;
  return nullptr;
}

}  // namespace cryptohome
