// 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/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,
    const OwnershipTakenCallBack& ownership_taken_callback)
    : local_data_store_(local_data_store),
      tpm_status_(tpm_status),
      ownership_taken_callback_(ownership_taken_callback) {}

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

bool TpmInitializerImpl::InitializeTpm() {
  TpmStatus::TpmOwnershipStatus ownership_status;
  if (!tpm_status_->CheckAndNotifyIfTpmOwned(&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();

  if (!ownership_taken_callback_.is_null()) {
    ownership_taken_callback_.Run();
  }

  // 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_->CheckAndNotifyIfTpmOwned(&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 CheckAndNotifyIfTpmOwned().
    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;
}

void TpmInitializerImpl::PruneStoredPasswords() {
  TpmStatus::TpmOwnershipStatus ownership_status;
  if (!tpm_status_->CheckAndNotifyIfTpmOwned(&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
