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

#include "tpm_manager/server/tpm_initializer_impl.h"

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

#include <base/check.h>
#include <base/logging.h>
#include <base/stl_util.h>
#include <base/strings/string_number_conversions.h>
#include <libhwsec/overalls/overalls_api.h>
#include <tpm_manager-client/tpm_manager/dbus-constants.h>
#include <trousers/scoped_tss_type.h>
#include <trousers/trousers.h>
#include <trousers/tss.h>

#include "tpm_manager/server/local_data_store.h"
#include "tpm_manager/server/tpm_connection.h"
#include "tpm_manager/server/tpm_status.h"
#include "tpm_manager/server/tpm_util.h"

using ::hwsec::overalls::GetOveralls;

namespace {

constexpr int kMaxOwnershipTimeoutRetries = 5;
constexpr char kWellKnownSrkSecret[] = "well_known_srk_secret";
constexpr int kDelegateSecretSize = 20;
constexpr uint8_t kDefaultDelegateLabel = 2;
constexpr uint8_t kDefaultDelegateFamilyLabel = 1;

}  // namespace

namespace tpm_manager {

TpmInitializerImpl::TpmInitializerImpl(LocalDataStore* local_data_store,
                                       TpmStatus* tpm_status)
    : local_data_store_(local_data_store), tpm_status_(tpm_status) {}

bool TpmInitializerImpl::PreInitializeTpm() {
  // No pre-initialization steps are performed for 1.2.
  return true;
}

bool TpmInitializerImpl::InitializeTpm() {
  TpmStatus::TpmOwnershipStatus ownership_status;
  if (!tpm_status_->GetTpmOwned(&ownership_status)) {
    LOG(ERROR) << __func__ << ": failed to get tpm ownership status";
    return false;
  }
  if (ownership_status == TpmStatus::kTpmOwned) {
    // Tpm is already owned, so we do not need to do anything.
    VLOG(1) << "Tpm already owned.";
    return true;
  }
  // Makes sure EK is there when unowned.
  if (ownership_status != TpmStatus::kTpmUnowned) {
    LOG(INFO) << __func__
              << ": TPM ownership is taken already; skip initializing EK.";
  } else if (!InitializeEndorsementKey()) {
    LOG(ERROR) << __func__ << ": failed to initialize endorsement key";
    return false;
  }
  TpmConnection connection(GetDefaultOwnerPassword());
  if (ownership_status != TpmStatus::kTpmUnowned) {
    LOG(INFO) << __func__
              << ": TPM ownership is taken already; skip taking ownership.";
  } else if (!TakeOwnership(&connection)) {
    LOG(ERROR) << __func__ << ": failed to take TPM ownership";
    return false;
  }
  // TPM ownership is taken; now the status is pre-owned.
  if (!InitializeSrk(&connection)) {
    LOG(ERROR) << __func__ << ": failed to initialize SRK";
    return false;
  }
  std::string owner_password;
  std::string random_bytes;
  if (!openssl_util_.GetRandomBytes(kOwnerPasswordRandomBytes, &random_bytes)) {
    return false;
  }
  owner_password = base::HexEncode(random_bytes.data(), random_bytes.size());
  LocalData local_data;
  local_data.clear_owner_dependency();
  for (auto value : kInitialTpmOwnerDependencies) {
    local_data.add_owner_dependency(value);
  }
  local_data.set_owner_password(owner_password);
  if (!local_data_store_->Write(local_data)) {
    LOG(ERROR) << ": Error saving local data after |set_owner_password|.";
    return false;
  }
  if (!ChangeOwnerPassword(&connection, owner_password)) {
    return false;
  }
  tpm_status_->MarkRandomOwnerPasswordSet();

  // for performance sake, continue using the same |local_data| so we don't need
  // to read the data from file once again.
  AuthDelegate owner_delegate;
  if (CreateDelegateWithDefaultLabel(&owner_delegate)) {
    local_data.mutable_owner_delegate()->Swap(&owner_delegate);
    if (!local_data_store_->Write(local_data)) {
      LOG(ERROR) << ": Cannot persist delegate.";
      return false;
    }
  } else {
    LOG(ERROR) << __func__ << ": Cannot create delegate.";
    return false;
  }

  reset_da_lock_auth_failed_ = false;
  return true;
}

void TpmInitializerImpl::VerifiedBootHelper() {
  // Nothing to do.
}

DictionaryAttackResetStatus TpmInitializerImpl::ResetDictionaryAttackLock() {
  if (reset_da_lock_auth_failed_) {
    // An auth error was encountered in a previous attempt, and there was no
    // auth update after the attempt. Skips the request to avoid further
    // increasing the counter.
    LOG(ERROR) << __func__
               << ": skipped the request to avoid repeating a "
                  "previous auth error.";
    return DictionaryAttackResetStatus::kResetAttemptFailed;
  }

  TpmStatus::TpmOwnershipStatus ownership_status;
  if (!tpm_status_->GetTpmOwned(&ownership_status)) {
    // Can't tell if we really can't get tpm ownership status or lockout is in
    // our way, so let's still go ahead.
    LOG(WARNING) << __func__
                 << ": failed to get tpm ownership status, but that could be "
                    "caused by a locked out TPM, so proceeding anyway.";
  } else {
    if (ownership_status != TpmStatus::kTpmOwned) {
      LOG(ERROR) << __func__ << ": TPM is not initialized yet.";
      return DictionaryAttackResetStatus::kResetAttemptFailed;
    }
  }

  std::string owner_password;
  AuthDelegate owner_delegate;
  if (!ReadOwnerAuthFromLocalData(&owner_password, &owner_delegate)) {
    // Note that if it failed here, it could be because the TPM is not owned,
    // but we tried anyway because we can't get the TPM status. See comments
    // above on GetTpmOwned().
    LOG(ERROR) << __func__ << ": failed to get owner auth.";
    return DictionaryAttackResetStatus::kResetAttemptFailed;
  }

  std::unique_ptr<TpmConnection> connection;
  if (!owner_password.empty()) {
    connection = std::make_unique<TpmConnection>(owner_password);
  } else if (!owner_delegate.blob().empty() &&
             !owner_delegate.secret().empty()) {
    if (!owner_delegate.has_reset_lock_permissions()) {
      return DictionaryAttackResetStatus::kDelegateNotAllowed;
    }
    connection = std::make_unique<TpmConnection>(owner_delegate);
  } else {
    LOG(ERROR) << __func__ << ": available owner auth not found.";
    return DictionaryAttackResetStatus::kDelegateNotAvailable;
  }

  TSS_HTPM tpm_handle = connection->GetTpm();
  if (!tpm_handle) {
    LOG(ERROR) << __func__ << ": Error getting a TPM handle.";
    return DictionaryAttackResetStatus::kResetAttemptFailed;
  }

  TSS_RESULT result = GetOveralls()->Ospi_TPM_SetStatus(
      tpm_handle, TSS_TPMSTATUS_RESETLOCK, true /* value will be ignored */);
  if (result != TSS_SUCCESS) {
    TPM_LOG(ERROR, result) << __func__ << ": failed to reset DA lock.";
    if (TPM_ERROR(TPM_E_AUTHFAIL) == result ||
        TPM_ERROR(TPM_E_AUTH2FAIL) == result) {
      reset_da_lock_auth_failed_ = true;
    }

    return result == TPM_ERROR(TPM_E_WRONGPCRVAL)
               ? DictionaryAttackResetStatus::kInvalidPcr0State
               : DictionaryAttackResetStatus::kResetAttemptFailed;
  }

  LOG(INFO) << __func__ << ": dictionary attack counter has been reset.";
  return DictionaryAttackResetStatus::kResetAttemptSucceeded;
}

TpmInitializerStatus TpmInitializerImpl::DisableDictionaryAttackMitigation() {
  return TpmInitializerStatus::kNotSupport;
}

void TpmInitializerImpl::PruneStoredPasswords() {
  TpmStatus::TpmOwnershipStatus ownership_status;
  if (!tpm_status_->GetTpmOwned(&ownership_status)) {
    LOG(ERROR) << __func__ << ": failed to get tpm ownership status";
    return;
  }

  if (ownership_status == TpmStatus::kTpmOwned) {
    LOG(WARNING) << __func__
                 << ": TPM is already owned. Local data won't be touched.";
    return;
  }

  LocalData local_data;
  if (!local_data_store_->Read(&local_data)) {
    LOG(ERROR) << __func__ << ": failed to read local data.";
    return;
  }

  local_data.clear_owner_password();
  local_data.clear_owner_delegate();
  local_data.clear_owner_dependency();

  if (!local_data_store_->Write(local_data)) {
    LOG(ERROR) << __func__ << ": failed to write local data.";
  }
}

bool TpmInitializerImpl::InitializeEndorsementKey() {
  TpmConnection connection;
  trousers::ScopedTssKey local_key_handle(connection.GetContext());
  TSS_RESULT result = Tspi_TPM_GetPubEndorsementKey(
      connection.GetTpm(), false, nullptr, local_key_handle.ptr());
  if (TPM_ERROR(result) == TPM_SUCCESS) {
    // In this case the EK already exists, so we can return true here.
    VLOG(1) << "EK already exists.";
    return true;
  } else if (TPM_ERROR(result) != TPM_E_NO_ENDORSEMENT) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetPubEndorsementKey";
    return false;
  }
  TPM_LOG(INFO, result) << "No EK is present; creating it.";
  TSS_FLAG init_flags = TSS_KEY_TYPE_LEGACY | TSS_KEY_SIZE_2048;
  if (TPM_ERROR(result = Tspi_Context_CreateObject(
                    connection.GetContext(), TSS_OBJECT_TYPE_RSAKEY, init_flags,
                    local_key_handle.ptr()))) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
    return false;
  }
  if (TPM_ERROR(result = Tspi_TPM_CreateEndorsementKey(
                    connection.GetTpm(), local_key_handle, NULL))) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_CreateEndorsementKey";
    return false;
  }
  return true;
}

bool TpmInitializerImpl::TakeOwnership(TpmConnection* connection) {
  TSS_RESULT result;
  trousers::ScopedTssKey srk_handle(connection->GetContext());
  TSS_FLAG init_flags = TSS_KEY_TSP_SRK | TSS_KEY_AUTHORIZATION;
  if (TPM_ERROR(result = Tspi_Context_CreateObject(
                    connection->GetContext(), TSS_OBJECT_TYPE_RSAKEY,
                    init_flags, srk_handle.ptr()))) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
    return false;
  }
  TSS_HPOLICY srk_usage_policy;
  if (TPM_ERROR(result = Tspi_GetPolicyObject(srk_handle, TSS_POLICY_USAGE,
                                              &srk_usage_policy))) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_GetPolicyObject";
    return false;
  }
  if (TPM_ERROR(result = Tspi_Policy_SetSecret(
                    srk_usage_policy, TSS_SECRET_MODE_PLAIN,
                    strlen(kWellKnownSrkSecret),
                    const_cast<BYTE*>(
                        reinterpret_cast<const BYTE*>(kWellKnownSrkSecret))))) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
    return false;
  }
  // Tspi_TPM_TakeOwnership can potentially take a long time to complete,
  // so we retry if there is a timeout in any layer. I chose 5, because the
  // longest TakeOwnership call that I have seen took ~2min, and the default
  // TSS timeout is 30s. This means that after 5 calls, it is quite likely that
  // this call will succeed.
  int retry_count = 0;
  do {
    result = Tspi_TPM_TakeOwnership(connection->GetTpm(), srk_handle, 0);
    retry_count++;
  } while (((result == TDDL_E_TIMEOUT) ||
            (result == (TSS_LAYER_TDDL | TDDL_E_TIMEOUT)) ||
            (result == (TSS_LAYER_TDDL | TDDL_E_IOERROR))) &&
           (retry_count < kMaxOwnershipTimeoutRetries));
  if (result) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_TakeOwnership, attempts: "
                           << retry_count;
    return false;
  }

  return true;
}

bool TpmInitializerImpl::InitializeSrk(TpmConnection* connection) {
  TSS_RESULT result;
  trousers::ScopedTssKey srk_handle(connection->GetContext());
  TSS_UUID SRK_UUID = TSS_UUID_SRK;
  if (TPM_ERROR(result = Tspi_Context_LoadKeyByUUID(
                    connection->GetContext(), TSS_PS_TYPE_SYSTEM, SRK_UUID,
                    srk_handle.ptr()))) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_Context_LoadKeyByUUID";
    return false;
  }

  trousers::ScopedTssPolicy policy_handle(connection->GetContext());
  if (TPM_ERROR(result = Tspi_Context_CreateObject(
                    connection->GetContext(), TSS_OBJECT_TYPE_POLICY,
                    TSS_POLICY_USAGE, policy_handle.ptr()))) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
    return false;
  }
  BYTE new_password[0];
  if (TPM_ERROR(result = Tspi_Policy_SetSecret(
                    policy_handle, TSS_SECRET_MODE_PLAIN, 0, new_password))) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
    return false;
  }

  if (TPM_ERROR(result = Tspi_ChangeAuth(srk_handle, connection->GetTpm(),
                                         policy_handle))) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_ChangeAuth";
    return false;
  }
  TSS_BOOL is_srk_restricted = false;
  if (TPM_ERROR(result = Tspi_TPM_GetStatus(connection->GetTpm(),
                                            TSS_TPMSTATUS_DISABLEPUBSRKREAD,
                                            &is_srk_restricted))) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetStatus";
    return false;
  }
  // If the SRK is restricted, we unrestrict it.
  if (is_srk_restricted) {
    if (TPM_ERROR(result = Tspi_TPM_SetStatus(connection->GetTpm(),
                                              TSS_TPMSTATUS_DISABLEPUBSRKREAD,
                                              false))) {
      TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_SetStatus";
      return false;
    }
  }
  return true;
}

bool TpmInitializerImpl::ChangeOwnerPassword(
    TpmConnection* connection, const std::string& owner_password) {
  TSS_RESULT result;
  trousers::ScopedTssPolicy policy_handle(connection->GetContext());
  if (TPM_ERROR(result = Tspi_Context_CreateObject(
                    connection->GetContext(), TSS_OBJECT_TYPE_POLICY,
                    TSS_POLICY_USAGE, policy_handle.ptr()))) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
    return false;
  }
  std::string mutable_owner_password(owner_password);
  if (TPM_ERROR(
          result = Tspi_Policy_SetSecret(
              policy_handle, TSS_SECRET_MODE_PLAIN, owner_password.size(),
              reinterpret_cast<BYTE*>(base::data(mutable_owner_password))))) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
    return false;
  }

  if (TPM_ERROR(result =
                    Tspi_ChangeAuth(connection->GetTpm(), 0, policy_handle))) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_ChangeAuth";
    return false;
  }

  return true;
}

bool TpmInitializerImpl::ReadOwnerAuthFromLocalData(
    std::string* owner_password, AuthDelegate* owner_delegate) {
  LocalData local_data;
  if (!local_data_store_->Read(&local_data)) {
    LOG(ERROR) << __func__ << ": Failed to read local data.";
    return false;
  }

  if (owner_password) {
    *owner_password = local_data.owner_password();
  }

  if (owner_delegate) {
    *owner_delegate = local_data.owner_delegate();
  }

  return true;
}

bool TpmInitializerImpl::CreateDelegateWithDefaultLabel(
    AuthDelegate* delegate) {
  std::string delegate_blob;
  std::string delegate_secret;
  // No PCR value bound to the delegate by default (crbug/990322, b/139099154).
  if (!CreateAuthDelegate(/*bound_pcrs=*/{}, kDefaultDelegateFamilyLabel,
                          kDefaultDelegateLabel, &delegate_blob,
                          &delegate_secret)) {
    LOG(ERROR) << __func__ << ": Failed to create delegate.";
    return false;
  }
  delegate->set_blob(delegate_blob);
  delegate->set_secret(delegate_secret);
  delegate->set_has_reset_lock_permissions(true);
  return true;
}

bool TpmInitializerImpl::EnsurePersistentOwnerDelegate() {
  LocalData local_data;
  if (!local_data_store_->Read(&local_data)) {
    LOG(ERROR) << __func__ << ": Failed to read local data.";
    return false;
  }
  auto owner_delegate = local_data.mutable_owner_delegate();
  if (!owner_delegate->blob().empty() && !owner_delegate->secret().empty()) {
    return true;
  }
  LOG(WARNING) << __func__ << ": Owner delegate is missing; re-creating.";
  if (!CreateDelegateWithDefaultLabel(owner_delegate)) {
    LOG(ERROR) << __func__ << ": Failed to create owner delegate.";
    return false;
  }
  if (!local_data_store_->Write(local_data)) {
    LOG(ERROR) << __func__ << ": Failed to write local data change.";
    return false;
  }
  return true;
}

bool TpmInitializerImpl::CreateAuthDelegate(
    const std::vector<uint32_t>& bound_pcrs,
    uint8_t delegate_family_label,
    uint8_t delegate_label,
    std::string* delegate_blob,
    std::string* delegate_secret) {
  CHECK(delegate_blob && delegate_secret);

  // Connects to the TPM as the owner.

  // read the owner password.
  // TODO(cylai): provide a clean way to retrieve owner password for this class.
  std::string owner_password;
  if (!ReadOwnerAuthFromLocalData(&owner_password, nullptr) ||
      owner_password.empty()) {
    LOG(ERROR) << __func__ << ": couldn't get owner password.";
    return false;
  }

  TpmConnection connection(owner_password);
  TSS_HCONTEXT context_handle = connection.GetContext();
  TSS_HTPM tpm_handle = connection.GetTpm();
  if (!context_handle || !tpm_handle) {
    LOG(ERROR) << __func__ << "TPM connection error.";
    return false;
  }

  // Generate a delegate secret.
  if (!openssl_util_.GetRandomBytes(kDelegateSecretSize, delegate_secret)) {
    return false;
  }

  // Create an owner delegation policy.
  trousers::ScopedTssPolicy policy(context_handle);
  TSS_RESULT result;
  result = Tspi_Context_CreateObject(context_handle, TSS_OBJECT_TYPE_POLICY,
                                     TSS_POLICY_USAGE, policy.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "CreateDelegate: Failed to create policy.";
    return false;
  }
  result = Tspi_Policy_SetSecret(
      policy, TSS_SECRET_MODE_PLAIN, delegate_secret->size(),
      reinterpret_cast<BYTE*>(const_cast<char*>(delegate_secret->data())));
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "CreateDelegate: Failed to set policy secret.";
    return false;
  }
  result =
      Tspi_SetAttribUint32(policy, TSS_TSPATTRIB_POLICY_DELEGATION_INFO,
                           TSS_TSPATTRIB_POLDEL_TYPE, TSS_DELEGATIONTYPE_OWNER);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "CreateDelegate: Failed to set delegation type.";
    return false;
  }
  // These are the privileged operations we will allow the delegate to perform.
  constexpr 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;
  result = Tspi_SetAttribUint32(policy, TSS_TSPATTRIB_POLICY_DELEGATION_INFO,
                                TSS_TSPATTRIB_POLDEL_PER1, permissions);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "CreateDelegate: Failed to set permissions.";
    return false;
  }
  result = Tspi_SetAttribUint32(policy, TSS_TSPATTRIB_POLICY_DELEGATION_INFO,
                                TSS_TSPATTRIB_POLDEL_PER2, 0);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "CreateDelegate: Failed to set permissions.";
    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.
  trousers::ScopedTssPcrs pcrs_handle(context_handle);
  if (!bound_pcrs.empty()) {
    result = Tspi_Context_CreateObject(context_handle, TSS_OBJECT_TYPE_PCRS,
                                       TSS_PCRS_STRUCT_INFO_SHORT,
                                       pcrs_handle.ptr());
    if (TPM_ERROR(result)) {
      TPM_LOG(ERROR, result) << "CreateDelegate: Failed to create PCRS object.";
      return false;
    }
    for (auto bound_pcr : bound_pcrs) {
      UINT32 pcr_len = 0;
      trousers::ScopedTssMemory pcr_value(context_handle);
      if (TPM_ERROR(result = Tspi_TPM_PcrRead(tpm_handle, bound_pcr, &pcr_len,
                                              pcr_value.ptr()))) {
        TPM_LOG(ERROR, result) << "Could not read PCR value";
        return false;
      }
      result = Tspi_PcrComposite_SetPcrValue(pcrs_handle, bound_pcr, pcr_len,
                                             pcr_value.value());
      if (TPM_ERROR(result)) {
        TPM_LOG(ERROR, result) << "Could not set value for PCR in PCRS handle";
        return false;
      }
    }
    constexpr unsigned int kTpmPCRLocality = 1;
    result = Tspi_PcrComposite_SetPcrLocality(pcrs_handle, kTpmPCRLocality);
    if (TPM_ERROR(result)) {
      TPM_LOG(ERROR, result)
          << "Could not set locality for PCRs in PCRS handle";
      return false;
    }
  }

  // Create a delegation family.
  trousers::ScopedTssObject<TSS_HDELFAMILY> family(context_handle);
  result = Tspi_TPM_Delegate_AddFamily(tpm_handle, delegate_family_label,
                                       family.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "CreateDelegate: Failed to create family.";
    return false;
  }

  // Create the delegation.
  result = Tspi_TPM_Delegate_CreateDelegation(tpm_handle, delegate_label, 0,
                                              pcrs_handle, family, policy);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "CreateDelegate: Failed to create delegation.";
    return false;
  }

  // Enable the delegation family.
  result = Tspi_SetAttribUint32(family, TSS_TSPATTRIB_DELFAMILY_STATE,
                                TSS_TSPATTRIB_DELFAMILYSTATE_ENABLED, TRUE);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "CreateDelegate: Failed to enable family.";
    return false;
  }

  // Save the delegation blob for later.
  if (!GetDataAttribute(context_handle, policy,
                        TSS_TSPATTRIB_POLICY_DELEGATION_INFO,
                        TSS_TSPATTRIB_POLDEL_OWNERBLOB, delegate_blob)) {
    LOG(ERROR) << "CreateDelegate: Failed to get delegate blob.";
    return false;
  }

  return true;
}

bool TpmInitializerImpl::GetDataAttribute(TSS_HCONTEXT context,
                                          TSS_HOBJECT object,
                                          TSS_FLAG flag,
                                          TSS_FLAG sub_flag,
                                          std::string* data) {
  UINT32 length = 0;
  trousers::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(buffer.value(), buffer.value() + length);
  return true;
}

}  // namespace tpm_manager
