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

#include "attestation/common/tpm_utility_v1.h"

#include <arpa/inet.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/hash/sha1.h>
#include <base/logging.h>
#include <base/memory/free_deleter.h>
#include <base/stl_util.h>
#include <brillo/secure_blob.h>
#include <crypto/libcrypto-compat.h>
#include <crypto/scoped_openssl_types.h>
#include <crypto/sha2.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include <trousers/scoped_tss_type.h>
#include <trousers/trousers.h>
#include <trousers/tss.h>

#include <algorithm>
#include <cstdint>
#include <memory>
#include <vector>

#define TPM_LOG(severity, result)                               \
  LOG(severity) << "TPM error 0x" << std::hex << result << " (" \
                << Trspi_Error_String(result) << "): "

using trousers::ScopedTssContext;
using trousers::ScopedTssKey;
using trousers::ScopedTssMemory;
using trousers::ScopedTssPcrs;
using trousers::ScopedTssPolicy;
namespace {

using ScopedByteArray = std::unique_ptr<BYTE, base::FreeDeleter>;
using ScopedTssEncryptedData = trousers::ScopedTssObject<TSS_HENCDATA>;
using ScopedTssHash = trousers::ScopedTssObject<TSS_HHASH>;

constexpr unsigned int kDigestSize = sizeof(TPM_DIGEST);
constexpr unsigned int kDefaultTpmRsaKeyBits = 2048;
constexpr unsigned int kDefaultTpmRsaKeyFlag = TSS_KEY_SIZE_2048;
constexpr unsigned int kWellKnownExponent = 65537;
constexpr unsigned char kSha256DigestInfo[] = {
    0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
    0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
constexpr size_t kSelectBitmapSize = 2;

BYTE* StringAsTSSBuffer(std::string* s) {
  return reinterpret_cast<BYTE*>(base::data(*s));
}

BYTE* StringAsTSSBuffer(const std::string* s) {
  return StringAsTSSBuffer(const_cast<std::string*>(s));
}

std::string TSSBufferAsString(const BYTE* buffer, size_t length) {
  return std::string(reinterpret_cast<const char*>(buffer), length);
}

// Builds the seciralized TPM_PCR_COMPOSITE stream, where |pcr_index| is the PCR
// index, and |quoted_pcr_value| is the value of the register.
std::string buildPcrComposite(uint32_t pcr_index,
                              const std::string& quoted_pcr_value) {
  CHECK_LT(pcr_index, kSelectBitmapSize * 8);
  struct __attribute__((packed)) {
    // Corresponding to TPM_PCR_SELECTION.sizeOfSelect.
    uint16_t select_size;
    // Corresponding to TPM_PCR_SELECTION.pcrSelect.
    uint8_t select_bitmap[kSelectBitmapSize];
    // Corresponding to  TPM_PCR_COMPOSITE.valueSize.
    uint32_t value_size;
  } composite_header = {0};
  static_assert(sizeof(composite_header) ==
                    sizeof(uint16_t) + kSelectBitmapSize + sizeof(uint32_t),
                "Expect no padding between composite struct.");
  // Sets to 2 bytes.
  composite_header.select_size = (htons(2u));
  composite_header.select_bitmap[pcr_index / 8] = 1 << (pcr_index % 8);
  composite_header.value_size = htonl(quoted_pcr_value.length());
  const char* composite_header_buffer =
      reinterpret_cast<const char*>(&composite_header);
  return std::string(composite_header_buffer, sizeof(composite_header)) +
         quoted_pcr_value;
}

// Checks if `delegate_blob`'s flag `TPM_DELEGATE_OwnerReadInternalPub` is set.
// In case of empty input or failed parsing, returns `false`; otherwise, set
// `can_read` and returns `true`.
bool CanDelegateReadInternalPub(const std::string& delegate_blob,
                                bool* can_read) {
  if (delegate_blob.empty()) {
    LOG(ERROR) << __func__ << ": Empty blob.";
    return false;
  }
  UINT64 offset = 0;
  // Make sure the parsing will be successful first.
  TSS_RESULT result = Trspi_UnloadBlob_TPM_DELEGATE_OWNER_BLOB(
      &offset,
      const_cast<BYTE*>(reinterpret_cast<const BYTE*>(delegate_blob.data())),
      nullptr);
  if (offset != delegate_blob.size()) {
    TPM_LOG(ERROR, result) << __func__ << ": Bad delegate blob.";
    return false;
  }
  offset = 0;

  TPM_DELEGATE_OWNER_BLOB ownerBlob = {};

  // TODO(b/169392230): Fix the potential memory leak while migrating to tpm
  // manager.
  result = Trspi_UnloadBlob_TPM_DELEGATE_OWNER_BLOB(
      &offset,
      const_cast<BYTE*>(reinterpret_cast<const BYTE*>(delegate_blob.data())),
      &ownerBlob);

  if (result != TSS_SUCCESS) {
    TPM_LOG(ERROR, result) << __func__ << ": Failed to unload delegate blob.";
    return false;
  }

  *can_read =
      ownerBlob.pub.permissions.per1 & TPM_DELEGATE_OwnerReadInternalPub;
  return true;
}

}  // namespace

namespace attestation {

TpmUtilityV1::~TpmUtilityV1() {}

bool TpmUtilityV1::Initialize() {
  if (!TpmUtilityCommon::Initialize()) {
    LOG(ERROR) << __func__ << ": Cannot initialize TpmUtilityCommon.";
    return false;
  }
  if (!InitializeContextHandle(__func__)) {
    LOG(WARNING) << __func__
                 << ": Failed to connect to the TPM during initialization.";
  }
  if (!IsTpmReady()) {
    LOG(WARNING) << __func__ << ": TPM is not owned; attestation services will "
                 << "not be available until ownership is taken.";
  }
  return true;
}

bool TpmUtilityV1::ActivateIdentity(const std::string& identity_key_blob,
                                    const std::string& asym_ca_contents,
                                    const std::string& sym_ca_attestation,
                                    std::string* credential) {
  CHECK(credential);
  if (!SetupSrk()) {
    LOG(ERROR) << "SRK is not ready.";
    return false;
  }

  // Connect to the TPM as the owner delegate.
  ScopedTssContext context_handle;
  TSS_HTPM tpm_handle;
  if (!ConnectContextAsDelegate(delegate_blob_, delegate_secret_,
                                &context_handle, &tpm_handle)) {
    LOG(ERROR) << __func__ << ": Could not connect to the TPM.";
    return false;
  }
  // Load the Storage Root Key.
  TSS_RESULT result;
  ScopedTssKey srk_handle(context_handle);
  if (!LoadSrk(context_handle, &srk_handle)) {
    LOG(ERROR) << __func__ << ": Failed to load SRK.";
    return false;
  }
  // Load the AIK (which is wrapped by the SRK).
  std::string mutable_identity_key_blob(identity_key_blob);
  BYTE* identity_key_blob_buffer =
      StringAsTSSBuffer(&mutable_identity_key_blob);
  ScopedTssKey identity_key(context_handle);
  result = Tspi_Context_LoadKeyByBlob(
      context_handle, srk_handle, identity_key_blob.size(),
      identity_key_blob_buffer, identity_key.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << __func__ << ": Failed to load AIK.";
    return false;
  }
  std::string mutable_asym_ca_contents(asym_ca_contents);
  BYTE* asym_ca_contents_buffer = StringAsTSSBuffer(&mutable_asym_ca_contents);
  std::string mutable_sym_ca_attestation(sym_ca_attestation);
  BYTE* sym_ca_attestation_buffer =
      StringAsTSSBuffer(&mutable_sym_ca_attestation);
  UINT32 credential_length = 0;
  ScopedTssMemory credential_buffer(context_handle);
  result = Tspi_TPM_ActivateIdentity(
      tpm_handle, identity_key, asym_ca_contents.size(),
      asym_ca_contents_buffer, sym_ca_attestation.size(),
      sym_ca_attestation_buffer, &credential_length, credential_buffer.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << __func__ << ": Failed to activate identity.";
    return false;
  }
  credential->assign(
      TSSBufferAsString(credential_buffer.value(), credential_length));
  return true;
}

bool TpmUtilityV1::ActivateIdentityForTpm2(
    KeyType key_type,
    const std::string& identity_key_blob,
    const std::string& encrypted_seed,
    const std::string& credential_mac,
    const std::string& wrapped_credential,
    std::string* credential) {
  LOG(ERROR) << __func__ << ": Not implemented.";
  return false;
}

bool TpmUtilityV1::CreateCertifiedKey(KeyType key_type,
                                      KeyUsage key_usage,
                                      const std::string& identity_key_blob,
                                      const std::string& external_data,
                                      std::string* key_blob,
                                      std::string* public_key,
                                      std::string* public_key_tpm_format,
                                      std::string* key_info,
                                      std::string* proof) {
  CHECK(key_blob && public_key && public_key_tpm_format && key_info && proof);
  if (!InitializeContextHandle(__func__)) {
    return false;
  }
  if (!SetupSrk()) {
    LOG(ERROR) << "SRK is not ready.";
    return false;
  }
  if (key_type != KEY_TYPE_RSA) {
    LOG(ERROR) << "Only RSA supported on TPM v1.2.";
    return false;
  }

  // Load the AIK (which is wrapped by the SRK).
  ScopedTssKey identity_key(context_handle_);
  if (!LoadKeyFromBlob(identity_key_blob, context_handle_, srk_handle_,
                       &identity_key)) {
    LOG(ERROR) << __func__ << "Failed to load AIK.";
    return false;
  }

  // Create a non-migratable RSA key.
  ScopedTssKey key(context_handle_);
  UINT32 tss_key_type =
      (key_usage == KEY_USAGE_SIGN) ? TSS_KEY_TYPE_SIGNING : TSS_KEY_TYPE_BIND;
  UINT32 init_flags = tss_key_type | TSS_KEY_NOT_MIGRATABLE | TSS_KEY_VOLATILE |
                      TSS_KEY_NO_AUTHORIZATION | TSS_KEY_SIZE_2048;
  TSS_RESULT result = Tspi_Context_CreateObject(
      context_handle_, TSS_OBJECT_TYPE_RSAKEY, init_flags, key.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << __func__ << ": Failed to create object.";
    return false;
  }
  if (key_usage == KEY_USAGE_SIGN) {
    result = Tspi_SetAttribUint32(key, TSS_TSPATTRIB_KEY_INFO,
                                  TSS_TSPATTRIB_KEYINFO_SIGSCHEME,
                                  TSS_SS_RSASSAPKCS1V15_DER);
  } else {
    result = Tspi_SetAttribUint32(key, TSS_TSPATTRIB_KEY_INFO,
                                  TSS_TSPATTRIB_KEYINFO_ENCSCHEME,
                                  TSS_ES_RSAESOAEP_SHA1_MGF1);
  }
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << __func__ << ": Failed to set scheme.";
    return false;
  }
  result = Tspi_Key_CreateKey(key, srk_handle_, 0);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << __func__ << ": Failed to create key.";
    return false;
  }
  result = Tspi_Key_LoadKey(key, srk_handle_);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << __func__ << ": Failed to load key.";
    return false;
  }

  // Certify the key.
  TSS_VALIDATION validation;
  memset(&validation, 0, sizeof(validation));
  validation.ulExternalDataLength = external_data.size();
  std::string mutable_external_data(external_data);
  validation.rgbExternalData = StringAsTSSBuffer(&mutable_external_data);
  result = Tspi_Key_CertifyKey(key, identity_key, &validation);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << __func__ << ": Failed to certify key.";
    return false;
  }
  ScopedTssMemory scoped_certified_data(context_handle_, validation.rgbData);
  ScopedTssMemory scoped_proof(context_handle_, validation.rgbValidationData);

  // Get the certified public key.
  if (!GetDataAttribute(context_handle_, key, TSS_TSPATTRIB_KEY_BLOB,
                        TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY,
                        public_key_tpm_format)) {
    LOG(ERROR) << __func__ << ": Failed to read public key.";
    return false;
  }
  if (!GetRSAPublicKeyFromTpmPublicKey(*public_key_tpm_format, public_key)) {
    return false;
  }

  // Get the certified key blob so we can load it later.
  if (!GetDataAttribute(context_handle_, key, TSS_TSPATTRIB_KEY_BLOB,
                        TSS_TSPATTRIB_KEYBLOB_BLOB, key_blob)) {
    LOG(ERROR) << __func__ << ": Failed to read key blob.";
    return false;
  }

  // Get the data that was certified.
  key_info->assign(
      TSSBufferAsString(validation.rgbData, validation.ulDataLength));

  // Get the certification proof.
  proof->assign(TSSBufferAsString(validation.rgbValidationData,
                                  validation.ulValidationDataLength));
  return true;
}

bool TpmUtilityV1::SealToPCR0(const std::string& data,
                              std::string* sealed_data) {
  CHECK(sealed_data);
  if (!InitializeContextHandle(__func__)) {
    return false;
  }
  if (!SetupSrk()) {
    LOG(ERROR) << "SRK is not ready.";
    return false;
  }
  // Create a PCRS object which holds the value of PCR0.
  ScopedTssPcrs pcrs_handle(context_handle_);
  TSS_RESULT result;
  if (TPM_ERROR(result = Tspi_Context_CreateObject(
                    context_handle_, TSS_OBJECT_TYPE_PCRS, TSS_PCRS_STRUCT_INFO,
                    pcrs_handle.ptr()))) {
    TPM_LOG(ERROR, result) << __func__
                           << ": Error calling Tspi_Context_CreateObject";
    return false;
  }
  UINT32 pcr_length = 0;
  ScopedTssMemory pcr_value(context_handle_);
  Tspi_TPM_PcrRead(tpm_handle_, 0, &pcr_length, pcr_value.ptr());
  Tspi_PcrComposite_SetPcrValue(pcrs_handle, 0, pcr_length, pcr_value.value());

  // Create a ENCDATA object to receive the sealed data.
  ScopedTssKey encrypted_data_handle(context_handle_);
  if (TPM_ERROR(result = Tspi_Context_CreateObject(
                    context_handle_, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_SEAL,
                    encrypted_data_handle.ptr()))) {
    TPM_LOG(ERROR, result) << __func__
                           << ": Error calling Tspi_Context_CreateObject";
    return false;
  }

  // Seal the given value with the SRK.
  std::string mutable_data(data);
  BYTE* data_buffer = StringAsTSSBuffer(&mutable_data);
  if (TPM_ERROR(result =
                    Tspi_Data_Seal(encrypted_data_handle, srk_handle_,
                                   data.size(), data_buffer, pcrs_handle))) {
    TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_Data_Seal";
    return false;
  }

  // Extract the sealed value.
  ScopedTssMemory encrypted_data(context_handle_);
  UINT32 encrypted_data_length = 0;
  if (TPM_ERROR(result = Tspi_GetAttribData(
                    encrypted_data_handle, TSS_TSPATTRIB_ENCDATA_BLOB,
                    TSS_TSPATTRIB_ENCDATABLOB_BLOB, &encrypted_data_length,
                    encrypted_data.ptr()))) {
    TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_GetAttribData";
    return false;
  }
  sealed_data->assign(
      TSSBufferAsString(encrypted_data.value(), encrypted_data_length));
  return true;
}

bool TpmUtilityV1::Unseal(const std::string& sealed_data, std::string* data) {
  CHECK(data);
  if (!SetupSrk()) {
    LOG(ERROR) << "SRK is not ready.";
    return false;
  }

  // Create an ENCDATA object with the sealed value.
  ScopedTssKey encrypted_data_handle(context_handle_);
  TSS_RESULT result;
  if (TPM_ERROR(result = Tspi_Context_CreateObject(
                    context_handle_, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_SEAL,
                    encrypted_data_handle.ptr()))) {
    TPM_LOG(ERROR, result) << __func__
                           << ": Error calling Tspi_Context_CreateObject";
    return false;
  }

  std::string mutable_sealed_data(sealed_data);
  BYTE* sealed_data_buffer = StringAsTSSBuffer(&mutable_sealed_data);
  if (TPM_ERROR(result = Tspi_SetAttribData(
                    encrypted_data_handle, TSS_TSPATTRIB_ENCDATA_BLOB,
                    TSS_TSPATTRIB_ENCDATABLOB_BLOB, sealed_data.size(),
                    sealed_data_buffer))) {
    TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_SetAttribData";
    return false;
  }

  // Unseal using the SRK.
  ScopedTssMemory decrypted_data(context_handle_);
  UINT32 decrypted_data_length = 0;
  if (TPM_ERROR(result = Tspi_Data_Unseal(encrypted_data_handle, srk_handle_,
                                          &decrypted_data_length,
                                          decrypted_data.ptr()))) {
    TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_Data_Unseal";
    return false;
  }
  data->assign(
      TSSBufferAsString(decrypted_data.value(), decrypted_data_length));
  return true;
}

bool TpmUtilityV1::GetEndorsementPublicKey(KeyType key_type,
                                           std::string* public_key_der) {
  if (key_type != KEY_TYPE_RSA) {
    return false;
  }
  ScopedTssContext context_handle;
  TSS_HTPM tpm_handle;
  bool is_ready = IsTpmReady();
  bool can_read_ek = false;
  if (!CanDelegateReadInternalPub(delegate_blob_, &can_read_ek)) {
    LOG(ERROR) << __func__ << ": Cannot check permission.";
  }
  LOG_IF(WARNING, !can_read_ek)
      << __func__ << ": owner delegate cannot read ek.";

  // Rationality check of auth values, if necessary.
  if (is_ready && !can_read_ek && owner_password_.empty()) {
    LOG(ERROR) << __func__ << ": No valid auth.";
    return false;
  }

  if (!is_ready) {
    if (!ConnectContextAsUser(&context_handle, &tpm_handle)) {
      LOG(ERROR) << __func__ << ": Could not connect to the TPM as user.";
      return false;
    }
  } else if (can_read_ek) {
    if (!ConnectContextAsDelegate(delegate_blob_, delegate_secret_,
                                  &context_handle, &tpm_handle)) {
      LOG(ERROR) << __func__ << ": Could not connect to the TPM as delegate.";
      return false;
    }
  } else if (!owner_password_.empty()) {
    if (!ConnectContextAsOwner(owner_password_, &context_handle, &tpm_handle)) {
      LOG(ERROR) << __func__ << ": Could not connect to the TPM as owner.";
      return false;
    }
  } else {
    NOTREACHED();
    return false;
  }

  // Get a handle to the EK public key.
  ScopedTssKey ek_public_key_object(context_handle);
  TSS_RESULT result = Tspi_TPM_GetPubEndorsementKey(
      tpm_handle, is_ready, nullptr, ek_public_key_object.ptr());
  if (TPM_ERROR(result)) {
    if (!is_ready && IsTpmReady()) {
      LOG(INFO) << " ownership taken during retrieval of EK. Retry.";
      return GetEndorsementPublicKey(key_type, public_key_der);
    }
    TPM_LOG(ERROR, result) << __func__ << ": Failed to get key.";
    return false;
  }
  // Get the public key in TPM_PUBKEY form.
  std::string ek_public_key_blob;
  if (!GetDataAttribute(
          context_handle, ek_public_key_object, TSS_TSPATTRIB_KEY_BLOB,
          TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, &ek_public_key_blob)) {
    LOG(ERROR) << __func__ << ": Failed to read public key.";
    return false;
  }
  // Get the public key in DER encoded form.
  if (!GetRSAPublicKeyFromTpmPublicKey(ek_public_key_blob, public_key_der)) {
    return false;
  }
  return true;
}

bool TpmUtilityV1::GetEndorsementCertificate(KeyType key_type,
                                             std::string* certificate) {
  // Connect to the TPM as the owner.
  ScopedTssContext context_handle;
  TSS_HTPM tpm_handle;
  if (!ConnectContextAsOwner(owner_password_, &context_handle, &tpm_handle)) {
    LOG(ERROR) << __func__ << " Could not connect to the TPM.";
    return false;
  }

  // Use the owner secret to authorize reading the blob.
  ScopedTssPolicy policy_handle(context_handle);
  TSS_RESULT result;
  result = Tspi_Context_CreateObject(context_handle, TSS_OBJECT_TYPE_POLICY,
                                     TSS_POLICY_USAGE, policy_handle.ptr());
  if (TPM_ERROR(result)) {
    LOG(ERROR) << __func__ << " Could not create policy.";
    return false;
  }
  result = Tspi_Policy_SetSecret(
      policy_handle, TSS_SECRET_MODE_PLAIN, owner_password_.size(),
      reinterpret_cast<BYTE*>(
          const_cast<std::string::value_type*>(owner_password_.data())));
  if (TPM_ERROR(result)) {
    LOG(ERROR) << __func__ << " Could not set owner secret.";
    return false;
  }

  // Read the EK cert from NVRAM.
  std::string nvram_value;
  if (!ReadNvram(context_handle, tpm_handle, policy_handle,
                 TSS_NV_DEFINED | TPM_NV_INDEX_EKCert, &nvram_value)) {
    LOG(ERROR) << __func__ << " Failed to read NVRAM.";
    return false;
  }

  // Sanity check the contents of the data and extract the X.509 certificate.
  // We are expecting data in the form of a TCG_PCCLIENT_STORED_CERT with an
  // embedded TCG_FULL_CERT. Details can be found in the TCG PC Specific
  // Implementation Specification v1.21 section 7.4.
  constexpr uint8_t kStoredCertHeader[] = {0x10, 0x01, 0x00};
  constexpr uint8_t kFullCertHeader[] = {0x10, 0x02};
  constexpr size_t kTotalHeaderBytes = 7;
  constexpr size_t kStoredCertHeaderOffset = 0;
  constexpr size_t kFullCertLengthOffset = 3;
  constexpr size_t kFullCertHeaderOffset = 5;
  if (nvram_value.size() < kTotalHeaderBytes) {
    LOG(ERROR) << "Malformed EK certificate: Bad header.";
    return false;
  }
  if (memcmp(kStoredCertHeader, &nvram_value[kStoredCertHeaderOffset],
             base::size(kStoredCertHeader)) != 0) {
    LOG(ERROR) << "Malformed EK certificate: Bad PCCLIENT_STORED_CERT.";
    return false;
  }
  if (memcmp(kFullCertHeader, &nvram_value[kFullCertHeaderOffset],
             base::size(kFullCertHeader)) != 0) {
    LOG(ERROR) << "Malformed EK certificate: Bad PCCLIENT_FULL_CERT.";
    return false;
  }
  // The size value is represented by two bytes in network order.
  size_t full_cert_size =
      (size_t(uint8_t(nvram_value[kFullCertLengthOffset])) << 8) |
      uint8_t(nvram_value[kFullCertLengthOffset + 1]);
  if (full_cert_size + kFullCertHeaderOffset > nvram_value.size()) {
    LOG(ERROR) << "Malformed EK certificate: Bad size.";
    return false;
  }
  // The X.509 certificate follows the header bytes.
  size_t full_cert_end =
      kTotalHeaderBytes + full_cert_size - base::size(kFullCertHeader);
  certificate->assign(nvram_value.begin() + kTotalHeaderBytes,
                      nvram_value.begin() + full_cert_end);
  return true;
}

bool TpmUtilityV1::Unbind(const std::string& key_blob,
                          const std::string& bound_data,
                          std::string* data) {
  CHECK(data);
  if (!InitializeContextHandle(__func__)) {
    return false;
  }
  if (!SetupSrk()) {
    LOG(ERROR) << "SRK is not ready.";
    return false;
  }
  ScopedTssKey key_handle(context_handle_);
  if (!LoadKeyFromBlob(key_blob, context_handle_, srk_handle_, &key_handle)) {
    return false;
  }
  TSS_RESULT result;
  ScopedTssEncryptedData data_handle(context_handle_);
  if (TPM_ERROR(result = Tspi_Context_CreateObject(
                    context_handle_, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND,
                    data_handle.ptr()))) {
    TPM_LOG(ERROR, result) << __func__ << ": Tspi_Context_CreateObject failed.";
    return false;
  }
  std::string mutable_bound_data(bound_data);
  if (TPM_ERROR(result = Tspi_SetAttribData(
                    data_handle, TSS_TSPATTRIB_ENCDATA_BLOB,
                    TSS_TSPATTRIB_ENCDATABLOB_BLOB, bound_data.size(),
                    StringAsTSSBuffer(&mutable_bound_data)))) {
    TPM_LOG(ERROR, result) << __func__ << ": Tspi_SetAttribData failed.";
    return false;
  }

  ScopedTssMemory decrypted_data(context_handle_);
  UINT32 length = 0;
  if (TPM_ERROR(result = Tspi_Data_Unbind(data_handle, key_handle, &length,
                                          decrypted_data.ptr()))) {
    TPM_LOG(ERROR, result) << __func__ << ": Tspi_Data_Unbind failed.";
    return false;
  }
  data->assign(TSSBufferAsString(decrypted_data.value(), length));
  return true;
}

bool TpmUtilityV1::Sign(const std::string& key_blob,
                        const std::string& data_to_sign,
                        std::string* signature) {
  CHECK(signature);
  if (!InitializeContextHandle(__func__)) {
    return false;
  }
  if (!SetupSrk()) {
    LOG(ERROR) << "SRK is not ready.";
    return false;
  }
  ScopedTssKey key_handle(context_handle_);
  if (!LoadKeyFromBlob(key_blob, context_handle_, srk_handle_, &key_handle)) {
    return false;
  }
  // Construct an ASN.1 DER DigestInfo.
  std::string digest_to_sign(std::begin(kSha256DigestInfo),
                             std::end(kSha256DigestInfo));
  digest_to_sign += crypto::SHA256HashString(data_to_sign);
  // Create a hash object to hold the digest.
  ScopedTssHash hash_handle(context_handle_);
  TSS_RESULT result = Tspi_Context_CreateObject(
      context_handle_, TSS_OBJECT_TYPE_HASH, TSS_HASH_OTHER, hash_handle.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << __func__ << ": Failed to create hash object.";
    return false;
  }
  result = Tspi_Hash_SetHashValue(hash_handle, digest_to_sign.size(),
                                  StringAsTSSBuffer(&digest_to_sign));
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << __func__ << ": Failed to set hash data.";
    return false;
  }
  UINT32 length = 0;
  ScopedTssMemory buffer(context_handle_);
  result = Tspi_Hash_Sign(hash_handle, key_handle, &length, buffer.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << __func__ << ": Failed to generate signature.";
    return false;
  }
  signature->assign(TSSBufferAsString(buffer.value(), length));
  return true;
}

bool TpmUtilityV1::QuotePCR(uint32_t pcr_index,
                            const std::string& key_blob,
                            std::string* quoted_pcr_value,
                            std::string* quoted_data,
                            std::string* quote) {
  if (!InitializeContextHandle(__func__)) {
    return false;
  }
  // Load the Storage Root Key.
  TSS_RESULT result;
  if (!SetupSrk()) {
    LOG(ERROR) << __func__ << ": Failed to setup SRK.";
    return false;
  }
  // Load the AIK (which is wrapped by the SRK).
  ScopedTssKey identity_key(context_handle_);
  BYTE* key_blob_ptr = StringAsTSSBuffer(&key_blob);
  result =
      Tspi_Context_LoadKeyByBlob(context_handle_, srk_handle_, key_blob.size(),
                                 key_blob_ptr, identity_key.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << __func__ << ": Failed to load AIK.";
    return false;
  }

  // Create a PCRS object and select the index.
  ScopedTssPcrs pcrs(context_handle_);
  result = Tspi_Context_CreateObject(context_handle_, TSS_OBJECT_TYPE_PCRS,
                                     TSS_PCRS_STRUCT_INFO, pcrs.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << __func__ << ": Failed to create PCRS object.";
    return false;
  }
  result = Tspi_PcrComposite_SelectPcrIndex(pcrs, pcr_index);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << __func__ << ": Failed to select PCR.";
    return false;
  }
  // Generate the quote.
  TSS_VALIDATION validation = {};
  // it's a difference from |TpmImpl| in |cryptohomed|, which uses OpenSSL to
  // generate the random number. Here we use well-known string value for
  // consistency with |TpmUtilityV2|, which doesn't supply any qualifying data
  // from caller while in TPM 1.2 it's required to have non-empty external data.
  BYTE well_known_external_data[kDigestSize] = {};
  validation.ulExternalDataLength = kDigestSize;
  validation.rgbExternalData = well_known_external_data;
  result = Tspi_TPM_Quote(tpm_handle_, identity_key, pcrs, &validation);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << __func__ << ": Failed to generate quote.";
    return false;
  }
  ScopedTssMemory scoped_quoted_data(context_handle_, validation.rgbData);
  ScopedTssMemory scoped_quote(context_handle_, validation.rgbValidationData);

  // Get the PCR value that was quoted.
  ScopedTssMemory pcr_value_buffer(context_handle_);
  UINT32 pcr_value_length = 0;
  result = Tspi_PcrComposite_GetPcrValue(pcrs, pcr_index, &pcr_value_length,
                                         pcr_value_buffer.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << __func__ << ": Failed to get PCR value.";
    return false;
  }
  *quoted_pcr_value =
      TSSBufferAsString(pcr_value_buffer.value(), pcr_value_length);
  // Get the data that was quoted.
  *quoted_data = TSSBufferAsString(validation.rgbData, validation.ulDataLength);
  // Get the quote.
  *quote = TSSBufferAsString(validation.rgbValidationData,
                             validation.ulValidationDataLength);
  return true;
}

bool TpmUtilityV1::IsQuoteForPCR(const std::string& quoted_pcr_value,
                                 const std::string& quoted_data,
                                 const std::string& quote,
                                 uint32_t pcr_index) const {
  // Checks that the quoted value matches the given PCR value by reconstructing
  // the TPM_PCR_COMPOSITE structure the TPM would create.
  const std::string pcr_digest =
      base::SHA1HashString(buildPcrComposite(pcr_index, quoted_pcr_value));

  // The PCR digest should appear starting at 8th byte of the quoted data. See
  // the TPM_QUOTE_INFO structure.
  if (quoted_data.length() < pcr_digest.length() + 8) {
    LOG(ERROR) << __func__ << ": Quoted data too short.";
    return false;
  }
  if (!std::equal(pcr_digest.begin(), pcr_digest.end(),
                  quoted_data.begin() + 8)) {
    LOG(ERROR) << __func__ << "PCR value mismatch.";
    return false;
  }
  return true;
}

bool TpmUtilityV1::ReadPCR(uint32_t pcr_index, std::string* pcr_value) {
  if (!InitializeContextHandle(__func__)) {
    return false;
  }
  UINT32 pcr_len = 0;
  ScopedTssMemory pcr_value_buffer(context_handle_);
  TSS_RESULT result = Tspi_TPM_PcrRead(tpm_handle_, pcr_index, &pcr_len,
                                       pcr_value_buffer.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Could not read PCR " << pcr_index << " value";
    return false;
  }
  pcr_value->assign(pcr_value_buffer.value(),
                    pcr_value_buffer.value() + pcr_len);
  return true;
}

bool TpmUtilityV1::GetNVDataSize(uint32_t nv_index, uint16_t* nv_size) const {
  LOG(ERROR) << __func__ << ": Not implemented.";
  return false;
}

bool TpmUtilityV1::CertifyNV(uint32_t nv_index,
                             int nv_size,
                             const std::string& key_blob,
                             std::string* quoted_data,
                             std::string* quote) {
  LOG(ERROR) << __func__ << ": Not implemented.";
  return false;
}

bool TpmUtilityV1::ConnectContextAsUser(ScopedTssContext* context,
                                        TSS_HTPM* tpm) {
  *tpm = 0;
  TSS_RESULT result;
  if (TPM_ERROR(result = Tspi_Context_Create(context->ptr()))) {
    TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_Context_Create";
    return false;
  }
  if (TPM_ERROR(result = Tspi_Context_Connect(*context, nullptr))) {
    TPM_LOG(ERROR, result) << __func__
                           << ": Error calling Tspi_Context_Connect";
    return false;
  }
  if (TPM_ERROR(result = Tspi_Context_GetTpmObject(*context, tpm))) {
    TPM_LOG(ERROR, result) << __func__
                           << ": Error calling Tspi_Context_GetTpmObject";
    return false;
  }
  return true;
}
bool TpmUtilityV1::ConnectContextAsOwner(const std::string& owner_password,
                                         trousers::ScopedTssContext* context,
                                         TSS_HTPM* tpm) {
  *tpm = 0;
  if (owner_password.empty()) {
    LOG(ERROR) << __func__ << ": requires an owner password";
    return false;
  }

  if (!ConnectContextAsUser(context, tpm)) {
    LOG(ERROR) << __func__ << ": Could not open the TPM";
    return false;
  }

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

bool TpmUtilityV1::ConnectContextAsDelegate(const std::string& delegate_blob,
                                            const std::string& delegate_secret,
                                            ScopedTssContext* context,
                                            TSS_HTPM* tpm) {
  if (delegate_blob.empty() || delegate_secret.empty()) {
    LOG(ERROR) << __func__
               << ": requires a delegate blob and a delegate secret.";
    return false;
  }
  *tpm = 0;
  if (!ConnectContextAsUser(context, tpm)) {
    return false;
  }
  TSS_RESULT result;
  TSS_HPOLICY tpm_usage_policy;
  if (TPM_ERROR(result = Tspi_GetPolicyObject(*tpm, TSS_POLICY_USAGE,
                                              &tpm_usage_policy))) {
    TPM_LOG(ERROR, result) << __func__
                           << ": Error calling Tspi_GetPolicyObject";
    return false;
  }
  std::string mutable_delegate_secret(delegate_secret);
  BYTE* secret_buffer = StringAsTSSBuffer(&mutable_delegate_secret);
  if (TPM_ERROR(result = Tspi_Policy_SetSecret(
                    tpm_usage_policy, TSS_SECRET_MODE_PLAIN,
                    delegate_secret.size(), secret_buffer))) {
    TPM_LOG(ERROR, result) << __func__
                           << ": Error calling Tspi_Policy_SetSecret";
    return false;
  }
  std::string mutable_delegate_blob(delegate_blob);
  BYTE* blob_buffer = StringAsTSSBuffer(&mutable_delegate_blob);
  if (TPM_ERROR(result = Tspi_SetAttribData(
                    tpm_usage_policy, TSS_TSPATTRIB_POLICY_DELEGATION_INFO,
                    TSS_TSPATTRIB_POLDEL_OWNERBLOB, delegate_blob.size(),
                    blob_buffer))) {
    TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_SetAttribData";
    return false;
  }
  return true;
}

bool TpmUtilityV1::SetTpmOwnerAuth(const std::string& owner_password,
                                   TSS_HCONTEXT context_handle,
                                   TSS_HTPM tpm_handle) {
  TSS_RESULT result;
  TSS_HPOLICY tpm_usage_policy;
  if (TPM_ERROR(result = Tspi_GetPolicyObject(tpm_handle, TSS_POLICY_USAGE,
                                              &tpm_usage_policy))) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_GetPolicyObject";
    return false;
  }
  BYTE* owner_password_buffer = StringAsTSSBuffer(&owner_password);
  if (TPM_ERROR(result = Tspi_Policy_SetSecret(
                    tpm_usage_policy, TSS_SECRET_MODE_PLAIN,
                    owner_password.size(), owner_password_buffer))) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
    return false;
  }

  return true;
}

bool TpmUtilityV1::ReadNvram(TSS_HCONTEXT context_handle,
                             TSS_HTPM tpm_handle,
                             TSS_HPOLICY policy_handle,
                             uint32_t index,
                             std::string* blob) {
  UINT32 size = GetNvramSize(context_handle, tpm_handle, index);
  if (size == 0) {
    if (!IsNvramDefined(context_handle, tpm_handle, index)) {
      LOG(ERROR) << "Cannot read from non-existent NVRAM space.";
    } else {
      LOG(ERROR) << "Cannot get nvram size.";
    }
    return false;
  }
  blob->resize(size);

  // Create an NVRAM store object handle.
  TSS_RESULT result;
  trousers::ScopedTssNvStore nv_handle(context_handle);
  result = Tspi_Context_CreateObject(context_handle, TSS_OBJECT_TYPE_NV, 0,
                                     nv_handle.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Could not acquire an NVRAM object handle";
    return false;
  }
  result = Tspi_SetAttribUint32(nv_handle, TSS_TSPATTRIB_NV_INDEX, 0, index);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Could not set index on NVRAM object: " << index;
    return false;
  }

  if (policy_handle) {
    result = Tspi_Policy_AssignToObject(policy_handle, nv_handle);
    if (TPM_ERROR(result)) {
      TPM_LOG(ERROR, result) << "Could not set NVRAM object policy.";
      return false;
    }
  }

  // Read from NVRAM in conservatively small chunks. This is a limitation of
  // the TPM that is left for the application layer to deal with. The maximum
  // size that is supported here can vary between vendors / models, so we'll
  // be conservative. FWIW, the Infineon chips seem to handle up to 1024.
  const UINT32 kMaxDataSize = 128;
  UINT32 offset = 0;
  while (offset < size) {
    UINT32 chunk_size = size - offset;
    if (chunk_size > kMaxDataSize)
      chunk_size = kMaxDataSize;
    trousers::ScopedTssMemory space_data(context_handle);
    if ((result = Tspi_NV_ReadValue(nv_handle, offset, &chunk_size,
                                    space_data.ptr()))) {
      TPM_LOG(ERROR, result) << "Could not read from NVRAM space: " << index;
      return false;
    }
    if (!space_data.value()) {
      LOG(ERROR) << "No data read from NVRAM space: " << index;
      return false;
    }
    CHECK(offset + chunk_size <= blob->size());
    // not for TSS APIs but BYTE* is also suitable here.
    BYTE* buffer = StringAsTSSBuffer(blob) + offset;
    memcpy(buffer, space_data.value(), chunk_size);
    offset += chunk_size;
  }
  return true;
}

bool TpmUtilityV1::IsNvramDefined(TSS_HCONTEXT context_handle,
                                  TSS_HTPM tpm_handle,
                                  uint32_t index) {
  TSS_RESULT result;
  UINT32 nv_list_data_length = 0;
  trousers::ScopedTssMemory nv_list_data(context_handle);
  if (TPM_ERROR(result = Tspi_TPM_GetCapability(tpm_handle, TSS_TPMCAP_NV_LIST,
                                                0, NULL, &nv_list_data_length,
                                                nv_list_data.ptr()))) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetCapability";
    return false;
  }

  // Walk the list and check if the index exists.
  UINT32* nv_list = reinterpret_cast<UINT32*>(nv_list_data.value());
  UINT32 nv_list_length = nv_list_data_length / sizeof(UINT32);
  index = htonl(index);  // TPM data is network byte order.
  for (UINT32 i = 0; i < nv_list_length; ++i) {
    // TODO(wad) add a NvramList method.
    if (index == nv_list[i])
      return true;
  }
  return false;
}

unsigned int TpmUtilityV1::GetNvramSize(TSS_HCONTEXT context_handle,
                                        TSS_HTPM tpm_handle,
                                        uint32_t index) {
  TSS_RESULT result;

  UINT32 nv_index_data_length = 0;
  trousers::ScopedTssMemory nv_index_data(context_handle);
  if (TPM_ERROR(result = Tspi_TPM_GetCapability(
                    tpm_handle, TSS_TPMCAP_NV_INDEX, sizeof(index),
                    reinterpret_cast<BYTE*>(&index), &nv_index_data_length,
                    nv_index_data.ptr()))) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetCapability";
    return 0u;
  }
  if (nv_index_data_length == 0) {
    return 0u;
  }
  // TPM_NV_DATA_PUBLIC->dataSize is the last element in the struct.
  // Since packing the struct still doesn't eliminate inconsistencies between
  // the API and the hardware, this is the safest way to extract the data.
  uint32_t* nv_data_public = reinterpret_cast<uint32_t*>(
      nv_index_data.value() + nv_index_data_length - sizeof(UINT32));
  return htonl(*nv_data_public);
}

bool TpmUtilityV1::SetupSrk() {
  if (!IsTpmReady()) {
    return false;
  }
  if (srk_handle_) {
    return true;
  }
  if (!InitializeContextHandle(__func__)) {
    return false;
  }
  srk_handle_.reset(context_handle_, 0);
  if (!LoadSrk(context_handle_, &srk_handle_)) {
    LOG(ERROR) << __func__ << ": Failed to load SRK.";
    return false;
  }
  // In order to wrap a key with the SRK we need access to the SRK public key
  // and we need to get it manually. Once it's in the key object, we don't need
  // to do this again.
  UINT32 length = 0;
  ScopedTssMemory buffer(context_handle_);
  TSS_RESULT result;
  result = Tspi_Key_GetPubKey(srk_handle_, &length, buffer.ptr());
  if (result != TSS_SUCCESS) {
    TPM_LOG(INFO, result) << __func__ << ": Failed to read SRK public key.";
    return false;
  }
  return true;
}

bool TpmUtilityV1::LoadSrk(TSS_HCONTEXT context_handle,
                           ScopedTssKey* srk_handle) {
  TSS_RESULT result;
  TSS_UUID uuid = TSS_UUID_SRK;
  if (TPM_ERROR(result = Tspi_Context_LoadKeyByUUID(context_handle,
                                                    TSS_PS_TYPE_SYSTEM, uuid,
                                                    srk_handle->ptr()))) {
    TPM_LOG(ERROR, result) << __func__
                           << ": Error calling Tspi_Context_LoadKeyByUUID";
    return false;
  }
  // Check if the SRK wants a password.
  UINT32 auth_usage;
  if (TPM_ERROR(result = Tspi_GetAttribUint32(
                    *srk_handle, TSS_TSPATTRIB_KEY_INFO,
                    TSS_TSPATTRIB_KEYINFO_AUTHUSAGE, &auth_usage))) {
    TPM_LOG(ERROR, result) << __func__
                           << ": Error calling Tspi_GetAttribUint32";
    return false;
  }
  if (auth_usage) {
    // Give it an empty password if needed.
    TSS_HPOLICY usage_policy;
    if (TPM_ERROR(result = Tspi_GetPolicyObject(*srk_handle, TSS_POLICY_USAGE,
                                                &usage_policy))) {
      TPM_LOG(ERROR, result)
          << __func__ << ": Error calling Tspi_GetPolicyObject";
      return false;
    }

    BYTE empty_password[] = {};
    if (TPM_ERROR(result =
                      Tspi_Policy_SetSecret(usage_policy, TSS_SECRET_MODE_PLAIN,
                                            0, empty_password))) {
      TPM_LOG(ERROR, result)
          << __func__ << ": Error calling Tspi_Policy_SetSecret";
      return false;
    }
  }
  return true;
}

bool TpmUtilityV1::LoadKeyFromBlob(const std::string& key_blob,
                                   TSS_HCONTEXT context_handle,
                                   TSS_HKEY parent_key_handle,
                                   ScopedTssKey* key_handle) {
  std::string mutable_key_blob(key_blob);
  BYTE* key_blob_buffer = StringAsTSSBuffer(&mutable_key_blob);
  TSS_RESULT result = Tspi_Context_LoadKeyByBlob(
      context_handle, parent_key_handle, key_blob.size(), key_blob_buffer,
      key_handle->ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << __func__ << ": Failed to load key by blob.";
    return false;
  }
  return true;
}

bool TpmUtilityV1::GetDataAttribute(TSS_HCONTEXT context,
                                    TSS_HOBJECT object,
                                    TSS_FLAG flag,
                                    TSS_FLAG sub_flag,
                                    std::string* data) {
  UINT32 length = 0;
  ScopedTssMemory buffer(context);
  TSS_RESULT result =
      Tspi_GetAttribData(object, flag, sub_flag, &length, buffer.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << __func__ << "Failed to read object attribute.";
    return false;
  }
  data->assign(TSSBufferAsString(buffer.value(), length));
  return true;
}

bool TpmUtilityV1::DecryptIdentityRequest(RSA* pca_key,
                                          const std::string& request,
                                          std::string* identity_binding) {
  // Parse the serialized TPM_IDENTITY_REQ structure.
  UINT64 offset = 0;
  BYTE* buffer = reinterpret_cast<BYTE*>(
      const_cast<typename std::string::value_type*>(request.data()));
  TPM_IDENTITY_REQ request_parsed;
  TSS_RESULT result =
      Trspi_UnloadBlob_IDENTITY_REQ(&offset, buffer, &request_parsed);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Failed to parse identity request.";
    return false;
  }
  ScopedByteArray scoped_asym_blob(request_parsed.asymBlob);
  ScopedByteArray scoped_sym_blob(request_parsed.symBlob);

  // Decrypt the symmetric key.
  unsigned char key_buffer[kDefaultTpmRsaKeyBits / 8];
  int key_length =
      RSA_private_decrypt(request_parsed.asymSize, request_parsed.asymBlob,
                          key_buffer, pca_key, RSA_PKCS1_PADDING);
  if (key_length == -1) {
    LOG(ERROR) << "Failed to decrypt identity request key.";
    return false;
  }
  TPM_SYMMETRIC_KEY symmetric_key;
  offset = 0;
  result = Trspi_UnloadBlob_SYMMETRIC_KEY(&offset, key_buffer, &symmetric_key);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Failed to parse symmetric key.";
    return false;
  }
  ScopedByteArray scoped_sym_key(symmetric_key.data);

  // Decrypt the request with the symmetric key.
  brillo::SecureBlob proof_serial;
  proof_serial.resize(request_parsed.symSize);
  UINT32 proof_serial_length = proof_serial.size();
  result = Trspi_SymDecrypt(symmetric_key.algId, TPM_ES_SYM_CBC_PKCS5PAD,
                            symmetric_key.data, NULL, request_parsed.symBlob,
                            request_parsed.symSize, proof_serial.data(),
                            &proof_serial_length);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Failed to decrypt identity request.";
    return false;
  }

  // Parse the serialized TPM_IDENTITY_PROOF structure.
  TPM_IDENTITY_PROOF proof;
  offset = 0;
  result =
      Trspi_UnloadBlob_IDENTITY_PROOF(&offset, proof_serial.data(), &proof);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Failed to parse identity proof.";
    return false;
  }
  ScopedByteArray scoped_label(proof.labelArea);
  ScopedByteArray scoped_binding(proof.identityBinding);
  ScopedByteArray scoped_endorsement(proof.endorsementCredential);
  ScopedByteArray scoped_platform(proof.platformCredential);
  ScopedByteArray scoped_conformance(proof.conformanceCredential);
  ScopedByteArray scoped_key(proof.identityKey.pubKey.key);
  ScopedByteArray scoped_parms(proof.identityKey.algorithmParms.parms);

  identity_binding->assign(&proof.identityBinding[0],
                           &proof.identityBinding[proof.identityBindingSize]);
  brillo::SecureClear(proof.identityBinding, proof.identityBindingSize);
  return true;
}

bool TpmUtilityV1::GetRSAPublicKeyFromTpmPublicKey(
    const std::string& tpm_public_key_object, std::string* public_key_der) {
  // Parse the serialized TPM_PUBKEY.
  UINT64 offset = 0;
  std::string mutable_public_key(tpm_public_key_object);
  BYTE* buffer = StringAsTSSBuffer(&mutable_public_key);
  TPM_PUBKEY parsed;
  TSS_RESULT result = Trspi_UnloadBlob_PUBKEY_s(
      &offset, buffer, mutable_public_key.length(), &parsed);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Failed to parse TPM_PUBKEY.";
    return false;
  }
  ScopedByteArray scoped_key(parsed.pubKey.key);
  ScopedByteArray scoped_parms(parsed.algorithmParms.parms);
  if (offset != mutable_public_key.length()) {
    LOG(ERROR) << "Found garbage data after the TPM_PUBKEY.";
    return false;
  }
  TPM_RSA_KEY_PARMS parms;
  UINT64 parms_offset = 0;
  result = Trspi_UnloadBlob_RSA_KEY_PARMS_s(
      &parms_offset, parsed.algorithmParms.parms,
      parsed.algorithmParms.parmSize, &parms);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Failed to parse RSA_KEY_PARMS.";
    return false;
  }
  if (parms_offset != parsed.algorithmParms.parmSize) {
    LOG(ERROR) << "Find garbage data after the TPM_PUBKEY.";
    return false;
  }
  ScopedByteArray scoped_exponent(parms.exponent);
  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.";
    return false;
  }
  // Get the public exponent.
  if (parms.exponentSize == 0) {
    if (!BN_set_word(e.get(), kWellKnownExponent)) {
      LOG(ERROR) << "Failed to set exponent to WellKnownExponent.";
      return false;
    }
  } else {
    if (!BN_bin2bn(parms.exponent, parms.exponentSize, e.get())) {
      LOG(ERROR) << "Failed to convert exponent to BIGNUM.";
      return false;
    }
  }
  // Get the modulus.
  if (!BN_bin2bn(parsed.pubKey.key, parsed.pubKey.keyLength, n.get())) {
    LOG(ERROR) << "Failed to convert public key to BIGNUM.";
    return false;
  }
  if (!RSA_set0_key(rsa.get(), n.release(), e.release(), nullptr)) {
    LOG(ERROR) << ": Failed to set exponent or modulus.";
    return false;
  }

  // DER encode.
  int der_length = i2d_RSAPublicKey(rsa.get(), nullptr);
  if (der_length < 0) {
    LOG(ERROR) << "Failed to DER-encode public key.";
    return false;
  }
  public_key_der->resize(der_length);
  unsigned char* der_buffer =
      reinterpret_cast<unsigned char*>(base::data(*public_key_der));
  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;
}

bool TpmUtilityV1::GetEndorsementPublicKeyModulus(KeyType key_type,
                                                  std::string* ekm) {
  if (key_type != KEY_TYPE_RSA) {
    LOG(ERROR) << __func__ << ": Only RSA supported on TPM1.2.";
    return false;
  }
  std::string ek_public_key;
  if (!GetEndorsementPublicKey(key_type, &ek_public_key)) {
    LOG(ERROR) << __func__ << ": Failed to get EK public key.";
    return false;
  }

  // Extracts the modulus from the public key.
  const unsigned char* asn1_ptr =
      reinterpret_cast<const unsigned char*>(ek_public_key.data());
  crypto::ScopedRSA public_key(
      d2i_RSAPublicKey(nullptr, &asn1_ptr, ek_public_key.size()));
  if (!public_key.get()) {
    LOG(ERROR) << __func__ << ": Failed to decode public endorsement key.";
    return false;
  }
  int modulus_bytes_length = RSA_size(public_key.get());
  if (modulus_bytes_length <= 0) {
    LOG(ERROR) << __func__
               << ": Failed to get public endorsement key modulus length.";
    return false;
  }
  std::vector<uint8_t> modulus_bytes(modulus_bytes_length);
  const BIGNUM* n;
  RSA_get0_key(public_key.get(), &n, nullptr, nullptr);
  int output_length = BN_bn2bin(n, modulus_bytes.data());
  if (output_length != modulus_bytes_length) {
    LOG(ERROR) << __func__ << ": Bad length returned by BN_bn2bin: got "
               << output_length << " while it should be "
               << modulus_bytes_length;
    return false;
  }
  ekm->assign(modulus_bytes.begin(), modulus_bytes.end());
  return true;
}

bool TpmUtilityV1::CreateIdentity(KeyType key_type,
                                  AttestationDatabase::Identity* identity) {
  if (KEY_TYPE_RSA != key_type) {
    LOG(ERROR) << __func__ << ": Identity key only supports RSA key type.";
    return false;
  }
  // fill the fields in identity
  auto binding_pb = identity->mutable_identity_binding();
  auto key_pb = identity->mutable_identity_key();
  if (!MakeIdentity(key_pb->mutable_identity_public_key_der(),
                    binding_pb->mutable_identity_public_key_tpm_format(),
                    key_pb->mutable_identity_key_blob(),
                    binding_pb->mutable_identity_binding(),
                    binding_pb->mutable_identity_label(),
                    binding_pb->mutable_pca_public_key())) {
    LOG(ERROR) << __func__ << ": Failed to make identity.";
    return false;
  }
  key_pb->set_identity_key_type(key_type);
  binding_pb->set_identity_public_key_der(key_pb->identity_public_key_der());
  return true;
}

bool TpmUtilityV1::MakeIdentity(std::string* identity_public_key_der,
                                std::string* identity_public_key,
                                std::string* identity_key_blob,
                                std::string* identity_binding,
                                std::string* identity_label,
                                std::string* pca_public_key) {
  CHECK(identity_public_key_der && identity_public_key && identity_key_blob &&
        identity_binding && identity_label && pca_public_key);
  // Connect to the TPM as the owner.
  ScopedTssContext context_handle;
  TSS_HTPM tpm_handle;
  if (!ConnectContextAsOwner(owner_password_, &context_handle, &tpm_handle)) {
    LOG(ERROR) << __func__ << " Could not connect to the TPM.";
    return false;
  }

  // Load the Storage Root Key.
  TSS_RESULT result;
  ScopedTssKey srk_handle(context_handle);
  if (!LoadSrk(context_handle, &srk_handle)) {
    LOG(ERROR) << "MakeIdentity: Cannot load SRK.";
    return false;
  }

  crypto::ScopedRSA fake_pca_key(RSA_new());
  crypto::ScopedBIGNUM e(BN_new());
  if (!fake_pca_key || !e) {
    LOG(ERROR) << "MakeIdentity: Failed to allocate RSA or BIGNUM.";
    return false;
  }

  if (!BN_set_word(e.get(), kWellKnownExponent) ||
      !RSA_generate_key_ex(fake_pca_key.get(), kDefaultTpmRsaKeyBits, e.get(),
                           nullptr)) {
    LOG(ERROR) << "MakeIdentity: Failed to generate local key pair.";
    return false;
  }
  unsigned char modulus_buffer[kDefaultTpmRsaKeyBits / 8];
  const BIGNUM* n;
  RSA_get0_key(fake_pca_key.get(), &n, NULL, NULL);
  if (BN_bn2bin(n, modulus_buffer) != RSA_size(fake_pca_key.get())) {
    LOG(ERROR) << "MakeIdentity: Failed to convert modulus from BIGNUM.";
    return false;
  }

  // Create a TSS object for the fake PCA public key.
  ScopedTssKey pca_public_key_object(context_handle);
  constexpr UINT32 kPcaKeyFlags =
      kDefaultTpmRsaKeyFlag | TSS_KEY_TYPE_LEGACY | TSS_KEY_MIGRATABLE;
  result = Tspi_Context_CreateObject(context_handle, TSS_OBJECT_TYPE_RSAKEY,
                                     kPcaKeyFlags, pca_public_key_object.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "MakeIdentity: Cannot create PCA public key.";
    return false;
  }
  result = Tspi_SetAttribData(pca_public_key_object, TSS_TSPATTRIB_RSAKEY_INFO,
                              TSS_TSPATTRIB_KEYINFO_RSA_MODULUS,
                              base::size(modulus_buffer), modulus_buffer);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result)
        << "MakeIdentity: Cannot set modulus to PCA public key.";
    return false;
  }
  result = Tspi_SetAttribUint32(pca_public_key_object, TSS_TSPATTRIB_KEY_INFO,
                                TSS_TSPATTRIB_KEYINFO_ENCSCHEME,
                                TSS_ES_RSAESPKCSV15);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "MakeIdentity: Cannot set encoding scheme "
                              "attribute to PCA public key.";
    return false;
  }

  // Get the fake PCA public key in serialized TPM_PUBKEY form.
  if (!GetDataAttribute(context_handle, pca_public_key_object,
                        TSS_TSPATTRIB_KEY_BLOB,
                        TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, pca_public_key)) {
    LOG(ERROR) << __func__ << ": Failed to read public key.";
    return false;
  }

  // Construct an arbitrary unicode label.
  const char* label_text = "ChromeOS_AIK_1BJNAMQDR4RH44F4ET2KPAOMJMO043K1";
  BYTE* label_ascii =
      const_cast<BYTE*>(reinterpret_cast<const BYTE*>(label_text));
  unsigned int label_size = strlen(label_text);
  ScopedByteArray label(Trspi_Native_To_UNICODE(label_ascii, &label_size));
  if (!label.get()) {
    LOG(ERROR) << "MakeIdentity: Failed to create AIK label.";
    return false;
  }
  identity_label->assign(&label.get()[0], &label.get()[label_size]);

  // Initialize a key object to hold the new identity key.
  ScopedTssKey identity_key(context_handle);
  constexpr UINT32 kIdentityKeyFlags =
      kDefaultTpmRsaKeyFlag | TSS_KEY_TYPE_IDENTITY | TSS_KEY_VOLATILE |
      TSS_KEY_NOT_MIGRATABLE;
  result = Tspi_Context_CreateObject(context_handle, TSS_OBJECT_TYPE_RSAKEY,
                                     kIdentityKeyFlags, identity_key.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "MakeIdentity: Failed to create key object.";
    return false;
  }

  // Create the identity and receive the request intended for the PCA.
  UINT32 request_length = 0;
  ScopedTssMemory request(context_handle);
  result = Tspi_TPM_CollateIdentityRequest(
      tpm_handle, srk_handle, pca_public_key_object, label_size, label.get(),
      identity_key, TSS_ALG_3DES, &request_length, request.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "MakeIdentity: Failed to make identity.";
    return false;
  }

  // Decrypt and parse the identity request.
  std::string request_blob(request.value(), request.value() + request_length);
  if (!DecryptIdentityRequest(fake_pca_key.get(), request_blob,
                              identity_binding)) {
    LOG(ERROR) << "MakeIdentity: Failed to decrypt the identity request.";
    return false;
  }
  brillo::SecureClear(request.value(), request_length);

  // Get the AIK public key.
  if (!GetDataAttribute(context_handle, identity_key, TSS_TSPATTRIB_KEY_BLOB,
                        TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY,
                        identity_public_key)) {
    LOG(ERROR) << __func__ << ": Failed to read public key.";
    return false;
  }
  if (!GetRSAPublicKeyFromTpmPublicKey(*identity_public_key,
                                       identity_public_key_der)) {
    return false;
  }

  // Get the AIK blob so we can load it later.
  if (!GetDataAttribute(context_handle, identity_key, TSS_TSPATTRIB_KEY_BLOB,
                        TSS_TSPATTRIB_KEYBLOB_BLOB, identity_key_blob)) {
    LOG(ERROR) << __func__ << ": Failed to read key blob.";
    return false;
  }
  return true;
}

bool TpmUtilityV1::GetRsuDeviceId(std::string* rsu_device_id) {
  LOG(ERROR) << __func__ << ": Not implemented.";
  return false;
}

std::string TpmUtilityV1::GetPCRValueForMode(const std::string& mode) {
  const std::string mode_digest = base::SHA1HashString(mode);

  // PCR0 value immediately after power on.
  const std::string pcr_initial_value(base::kSHA1Length, 0);

  return base::SHA1HashString(pcr_initial_value + mode_digest);
}

bool TpmUtilityV1::InitializeContextHandle(const std::string& consumer_name) {
  if (!static_cast<TSS_HCONTEXT>(context_handle_) || !tpm_handle_) {
    context_handle_.reset();
    if (!ConnectContextAsUser(&context_handle_, &tpm_handle_)) {
      LOG(ERROR) << __func__ << ": Failed to connect to the TPM.";
      return false;
    }
  }
  return true;
}

}  // namespace attestation
