// Copyright 2019 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 <memory>
#include <string>
#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/check.h>
#include <base/files/file_util.h>
#include <base/strings/string_number_conversions.h>
#include <chromeos/constants/cryptohome.h>

#include "cryptohome/dircrypto_data_migrator/migration_helper.h"
#include "cryptohome/proxy/legacy_cryptohome_interface_adaptor.h"

namespace {
constexpr base::TimeDelta kDefaultTimeout = base::TimeDelta::FromMinutes(5);
constexpr base::TimeDelta kAttestationProxyTimeout =
    base::TimeDelta::FromMinutes(5);
constexpr base::TimeDelta kMountTimeout = base::TimeDelta::FromMinutes(5);
}

namespace cryptohome {

void LegacyCryptohomeInterfaceAdaptor::RegisterAsync() {
  RegisterWithDBusObject(dbus_object_);

  // Register the dbus signal handlers
  userdataauth_proxy_->RegisterDircryptoMigrationProgressSignalHandler(
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::OnDircryptoMigrationProgressSignal,
          base::Unretained(this)),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::OnSignalConnectedHandler,
                 base::Unretained(this)));
  userdataauth_proxy_->RegisterLowDiskSpaceSignalHandler(
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::OnLowDiskSpaceSignal,
                 base::Unretained(this)),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::OnSignalConnectedHandler,
                 base::Unretained(this)));
  tpm_ownership_proxy_->RegisterSignalOwnershipTakenSignalHandler(
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::OnOwnershipTakenSignal,
                 base::Unretained(this)),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::OnSignalConnectedHandler,
                 base::Unretained(this)));
}

void LegacyCryptohomeInterfaceAdaptor::IsMounted(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<bool>>(std::move(response));

  user_data_auth::IsMountedRequest request;
  userdataauth_proxy_->IsMountedAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::IsMountedOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::IsMountedOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const user_data_auth::IsMountedReply& reply) {
  response->Return(reply.is_mounted());
}

void LegacyCryptohomeInterfaceAdaptor::IsMountedForUser(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool, bool>>
        response,
    const std::string& in_username) {
  auto response_shared = std::make_shared<SharedDBusMethodResponse<bool, bool>>(
      std::move(response));

  user_data_auth::IsMountedRequest request;
  request.set_username(in_username);
  userdataauth_proxy_->IsMountedAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::IsMountedForUserOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool, bool>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::IsMountedForUserOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool, bool>> response,
    const user_data_auth::IsMountedReply& reply) {
  response->Return(reply.is_mounted(), reply.is_ephemeral_mount());
}

void LegacyCryptohomeInterfaceAdaptor::ListKeysEx(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::AccountIdentifier& in_account_id,
    const cryptohome::AuthorizationRequest& in_authorization_request,
    const cryptohome::ListKeysRequest& /*in_list_keys_request*/) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::ListKeysRequest request;
  request.mutable_account_id()->CopyFrom(in_account_id);
  request.mutable_authorization_request()->CopyFrom(in_authorization_request);
  // Note that in_list_keys_request is empty
  userdataauth_proxy_->ListKeysAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ListKeysExOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::ListKeysExOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>> response,
    const user_data_auth::ListKeysReply& reply) {
  cryptohome::BaseReply result;
  result.set_error(static_cast<cryptohome::CryptohomeErrorCode>(reply.error()));
  cryptohome::ListKeysReply* result_extension =
      result.MutableExtension(cryptohome::ListKeysReply::reply);
  result_extension->mutable_labels()->CopyFrom(reply.labels());
  ClearErrorIfNotSet(&result);
  response->Return(result);
}

void LegacyCryptohomeInterfaceAdaptor::CheckKeyEx(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::AccountIdentifier& in_account_id,
    const cryptohome::AuthorizationRequest& in_authorization_request,
    const cryptohome::CheckKeyRequest& in_check_key_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::CheckKeyRequest request;
  request.mutable_account_id()->CopyFrom(in_account_id);
  request.mutable_authorization_request()->CopyFrom(in_authorization_request);
  userdataauth_proxy_->CheckKeyAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardBaseReplyErrorCode<
                     user_data_auth::CheckKeyReply>,
                 response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::RemoveKeyEx(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::AccountIdentifier& in_account_id,
    const cryptohome::AuthorizationRequest& in_authorization_request,
    const cryptohome::RemoveKeyRequest& in_remove_key_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::RemoveKeyRequest request;
  request.mutable_account_id()->CopyFrom(in_account_id);
  request.mutable_authorization_request()->CopyFrom(in_authorization_request);
  request.mutable_key()->CopyFrom(in_remove_key_request.key());
  userdataauth_proxy_->RemoveKeyAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardBaseReplyErrorCode<
                     user_data_auth::RemoveKeyReply>,
                 response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::MassRemoveKeys(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::AccountIdentifier& in_account_id,
    const cryptohome::AuthorizationRequest& in_authorization_request,
    const cryptohome::MassRemoveKeysRequest& in_mass_remove_keys_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::MassRemoveKeysRequest request;
  request.mutable_account_id()->CopyFrom(in_account_id);
  request.mutable_authorization_request()->CopyFrom(in_authorization_request);
  request.mutable_exempt_key_data()->CopyFrom(
      in_mass_remove_keys_request.exempt_key_data());
  userdataauth_proxy_->MassRemoveKeysAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardBaseReplyErrorCode<
                     user_data_auth::MassRemoveKeysReply>,
                 response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::GetKeyDataEx(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::AccountIdentifier& in_account_id,
    const cryptohome::AuthorizationRequest& in_authorization_request,
    const cryptohome::GetKeyDataRequest& in_get_key_data_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::GetKeyDataRequest request;
  request.mutable_account_id()->CopyFrom(in_account_id);
  request.mutable_authorization_request()->CopyFrom(in_authorization_request);
  request.mutable_key()->CopyFrom(in_get_key_data_request.key());
  userdataauth_proxy_->GetKeyDataAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::GetKeyDataOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::GetKeyDataOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>> response,
    const user_data_auth::GetKeyDataReply& reply) {
  cryptohome::BaseReply result;
  result.set_error(static_cast<cryptohome::CryptohomeErrorCode>(reply.error()));
  cryptohome::GetKeyDataReply* result_extension =
      result.MutableExtension(cryptohome::GetKeyDataReply::reply);
  result_extension->mutable_key_data()->CopyFrom(reply.key_data());
  ClearErrorIfNotSet(&result);
  response->Return(result);
}

void LegacyCryptohomeInterfaceAdaptor::MigrateKeyEx(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::AccountIdentifier& in_account,
    const cryptohome::AuthorizationRequest& in_authorization_request,
    const cryptohome::MigrateKeyRequest& in_migrate_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::MigrateKeyRequest request;
  request.mutable_account_id()->CopyFrom(in_account);
  request.mutable_authorization_request()->CopyFrom(in_authorization_request);
  request.set_secret(in_migrate_request.secret());
  userdataauth_proxy_->MigrateKeyAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardBaseReplyErrorCode<
                     user_data_auth::MigrateKeyReply>,
                 response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::AddKeyEx(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::AccountIdentifier& in_account_id,
    const cryptohome::AuthorizationRequest& in_authorization_request,
    const cryptohome::AddKeyRequest& in_add_key_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::AddKeyRequest request;
  request.mutable_account_id()->CopyFrom(in_account_id);
  request.mutable_authorization_request()->CopyFrom(in_authorization_request);
  request.mutable_key()->CopyFrom(in_add_key_request.key());
  request.set_clobber_if_exists(in_add_key_request.clobber_if_exists());
  userdataauth_proxy_->AddKeyAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardBaseReplyErrorCode<
                     user_data_auth::AddKeyReply>,
                 response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::AddDataRestoreKey(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::AccountIdentifier& in_account_id,
    const cryptohome::AuthorizationRequest& in_authorization_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::AddDataRestoreKeyRequest request;
  request.mutable_account_id()->CopyFrom(in_account_id);
  request.mutable_authorization_request()->CopyFrom(in_authorization_request);
  userdataauth_proxy_->AddDataRestoreKeyAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::AddDataRestoreKeyOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::AddDataRestoreKeyOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>> response,
    const user_data_auth::AddDataRestoreKeyReply& reply) {
  cryptohome::BaseReply result;
  result.set_error(static_cast<cryptohome::CryptohomeErrorCode>(reply.error()));
  cryptohome::AddDataRestoreKeyReply* result_extension =
      result.MutableExtension(cryptohome::AddDataRestoreKeyReply::reply);
  if (result.error() == CRYPTOHOME_ERROR_NOT_SET) {
    result_extension->set_data_restore_key(reply.data_restore_key());
  }
  ClearErrorIfNotSet(&result);
  response->Return(result);
}

void LegacyCryptohomeInterfaceAdaptor::RemoveEx(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::AccountIdentifier& in_account) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::RemoveRequest request;
  request.mutable_identifier()->CopyFrom(in_account);
  userdataauth_proxy_->RemoveAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardBaseReplyErrorCode<
                     user_data_auth::RemoveReply>,
                 response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::GetSystemSalt(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<std::vector<uint8_t>>>
        response) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<std::vector<uint8_t>>>(
          std::move(response));

  user_data_auth::GetSystemSaltRequest request;
  misc_proxy_->GetSystemSaltAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::GetSystemSaltOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::ForwardError<std::vector<uint8_t>>,
          base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::GetSystemSaltOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<std::vector<uint8_t>>> response,
    const user_data_auth::GetSystemSaltReply& reply) {
  std::vector<uint8_t> salt(reply.salt().begin(), reply.salt().end());
  response->Return(salt);
}

void LegacyCryptohomeInterfaceAdaptor::GetSanitizedUsername(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<std::string>>
        response,
    const std::string& in_username) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<std::string>>(
          std::move(response));

  user_data_auth::GetSanitizedUsernameRequest request;
  request.set_username(in_username);
  misc_proxy_->GetSanitizedUsernameAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::GetSanitizedUsernameOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<std::string>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::GetSanitizedUsernameOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<std::string>> response,
    const user_data_auth::GetSanitizedUsernameReply& reply) {
  response->Return(reply.sanitized_username());
}

void LegacyCryptohomeInterfaceAdaptor::MountEx(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::AccountIdentifier& in_account_id,
    const cryptohome::AuthorizationRequest& in_authorization_request,
    const cryptohome::MountRequest& in_mount_request) {
  std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>>
      response_shared =
          std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
              std::move(response));

  user_data_auth::MountRequest request;
  *request.mutable_account() = in_account_id;
  request.mutable_authorization()->CopyFrom(in_authorization_request);
  request.set_require_ephemeral(in_mount_request.require_ephemeral());
  if (in_mount_request.has_create()) {
    request.mutable_create()->mutable_keys()->CopyFrom(
        in_mount_request.create().keys());
    request.mutable_create()->set_copy_authorization_key(
        in_mount_request.create().copy_authorization_key());
    request.mutable_create()->set_force_ecryptfs(
        in_mount_request.create().force_ecryptfs());
  }
  request.set_force_dircrypto_if_available(
      in_mount_request.force_dircrypto_if_available());
  request.set_to_migrate_from_ecryptfs(
      in_mount_request.to_migrate_from_ecryptfs());
  request.set_public_mount(in_mount_request.public_mount());
  request.set_guest_mount(false);
  request.set_auth_session_id(in_mount_request.auth_session_id());
  // There's another MountGuestEx to handle guest mount. This method only
  // deal with non-guest mount so guest_mount is false here.

  userdataauth_proxy_->MountAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::MountExOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kMountTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::MountExOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>> response,
    const user_data_auth::MountReply& reply) {
  if (reply.error() ==
      user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_INVALID_ARGUMENT) {
    constexpr char error_msg[] =
        "Invalid argument on MountEx(), see logs for more details.";
    LOG(WARNING) << error_msg;
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             DBUS_ERROR_INVALID_ARGS, error_msg);
    return;
  }
  cryptohome::BaseReply result;
  result.set_error(static_cast<cryptohome::CryptohomeErrorCode>(reply.error()));
  MountReply* result_extension =
      result.MutableExtension(cryptohome::MountReply::reply);
  result_extension->set_recreated(reply.recreated());
  result_extension->set_sanitized_username(reply.sanitized_username());
  ClearErrorIfNotSet(&result);
  response->Return(result);
}

void LegacyCryptohomeInterfaceAdaptor::MountGuestEx(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::MountGuestRequest& in_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::MountRequest request;
  request.set_guest_mount(true);

  userdataauth_proxy_->MountAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardBaseReplyErrorCode<
                     user_data_auth::MountReply>,
                 response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kMountTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::RenameCryptohome(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::AccountIdentifier& in_cryptohome_id_from,
    const cryptohome::AccountIdentifier& in_cryptohome_id_to) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::RenameRequest request;
  *request.mutable_id_from() = in_cryptohome_id_from;
  *request.mutable_id_to() = in_cryptohome_id_to;
  userdataauth_proxy_->RenameAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardBaseReplyErrorCode<
                     user_data_auth::RenameReply>,
                 response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::GetAccountDiskUsage(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::AccountIdentifier& in_account_id) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::GetAccountDiskUsageRequest request;
  *request.mutable_identifier() = in_account_id;
  userdataauth_proxy_->GetAccountDiskUsageAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::GetAccountDiskUsageOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::GetAccountDiskUsageOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>> response,
    const user_data_auth::GetAccountDiskUsageReply& reply) {
  cryptohome::BaseReply result;
  result.set_error(static_cast<cryptohome::CryptohomeErrorCode>(reply.error()));
  cryptohome::GetAccountDiskUsageReply* result_extension =
      result.MutableExtension(cryptohome::GetAccountDiskUsageReply::reply);
  result_extension->set_size(reply.size());
  ClearErrorIfNotSet(&result);
  response->Return(result);
}

void LegacyCryptohomeInterfaceAdaptor::UnmountEx(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::UnmountRequest& in_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::UnmountRequest request;
  userdataauth_proxy_->UnmountAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardBaseReplyErrorCode<
                     user_data_auth::UnmountReply>,
                 response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::UpdateCurrentUserActivityTimestamp(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>> response,
    int32_t in_time_shift_sec) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<>>(std::move(response));

  user_data_auth::UpdateCurrentUserActivityTimestampRequest request;
  request.set_time_shift_sec(in_time_shift_sec);
  misc_proxy_->UpdateCurrentUserActivityTimestampAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::
                     UpdateCurrentUserActivityTimestampOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::
    UpdateCurrentUserActivityTimestampOnSuccess(
        std::shared_ptr<SharedDBusMethodResponse<>> response,
        const user_data_auth::UpdateCurrentUserActivityTimestampReply& reply) {
  if (reply.error() != user_data_auth::CRYPTOHOME_ERROR_NOT_SET) {
    LOG(WARNING) << "UpdateCurrentUserActivityTimestamp() failure received by "
                    "cryptohome-proxy, error "
                 << static_cast<int>(reply.error());
  }
  response->Return();
}

void LegacyCryptohomeInterfaceAdaptor::TpmIsReady(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<bool>>(std::move(response));

  tpm_manager::GetTpmStatusRequest request;
  tpm_ownership_proxy_->GetTpmStatusAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::TpmIsReadyOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmIsReadyOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const tpm_manager::GetTpmStatusReply& reply) {
  response->Return(reply.enabled() && reply.owned());
}

void LegacyCryptohomeInterfaceAdaptor::TpmIsEnabled(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<bool>>(std::move(response));

  tpm_manager::GetTpmStatusRequest request;
  tpm_ownership_proxy_->GetTpmStatusAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::TpmIsEnabledOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmIsEnabledOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const tpm_manager::GetTpmStatusReply& reply) {
  response->Return(reply.enabled());
}

void LegacyCryptohomeInterfaceAdaptor::TpmGetPassword(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<std::string>>
        response) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<std::string>>(
          std::move(response));

  tpm_manager::GetTpmStatusRequest request;
  tpm_ownership_proxy_->GetTpmStatusAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::TpmGetPasswordOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<std::string>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmGetPasswordOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<std::string>> response,
    const tpm_manager::GetTpmStatusReply& reply) {
  response->Return(reply.local_data().owner_password());
}

void LegacyCryptohomeInterfaceAdaptor::TpmIsOwned(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<bool>>(std::move(response));

  tpm_manager::GetTpmStatusRequest request;
  tpm_ownership_proxy_->GetTpmStatusAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::TpmIsOwnedOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmIsOwnedOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const tpm_manager::GetTpmStatusReply& reply) {
  response->Return(reply.owned());
}

void LegacyCryptohomeInterfaceAdaptor::TpmCanAttemptOwnership(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>> response) {
  tpm_manager::TakeOwnershipRequest request;
  tpm_ownership_proxy_->TakeOwnershipAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::TpmCanAttemptOwnershipOnSuccess,
          base::Unretained(this)),
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::TpmCanAttemptOwnershipOnFailure,
          base::Unretained(this)),
      kDefaultTimeout.InMilliseconds());

  // Note that this method is special in the sense that this call will return
  // immediately as soon as the target method is called on the UserDataAuth
  // side. The result from the target method on UserDataAuth side is not passed
  // back to the caller of this method, but instead is logged if there's any
  // failure.
  response->Return();
}

void LegacyCryptohomeInterfaceAdaptor::TpmCanAttemptOwnershipOnSuccess(
    const tpm_manager::TakeOwnershipReply& reply) {
  if (reply.status() != tpm_manager::STATUS_SUCCESS) {
    LOG(WARNING) << "TakeOwnership failure observed in "
                    "TpmCanAttemptOwnership() of cryptohome-proxy. Status: "
                 << static_cast<int>(reply.status());
  }
}

void LegacyCryptohomeInterfaceAdaptor::TpmCanAttemptOwnershipOnFailure(
    brillo::Error* err) {
  // Note that creation of Error object already logs the error.
  LOG(WARNING) << "TakeOwnership encountered an error, observed in "
                  "TpmCanAttemptOwnership() of cryptohome-proxy.";
}

void LegacyCryptohomeInterfaceAdaptor::TpmClearStoredPassword(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>> response) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<>>(std::move(response));

  tpm_manager::ClearStoredOwnerPasswordRequest request;
  tpm_ownership_proxy_->ClearStoredOwnerPasswordAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::TpmClearStoredPasswordOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmClearStoredPasswordOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<>> response,
    const tpm_manager::ClearStoredOwnerPasswordReply& reply) {
  response->Return();
}

void LegacyCryptohomeInterfaceAdaptor::TpmIsAttestationPrepared(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response) {
  attestation::GetEnrollmentPreparationsRequest request;

  std::shared_ptr<SharedDBusMethodResponse<bool>> response_shared(
      new SharedDBusMethodResponse<bool>(std::move(response)));

  attestation_proxy_->GetEnrollmentPreparationsAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::TpmIsAttestationPreparedOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmIsAttestationPreparedOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const attestation::GetEnrollmentPreparationsReply& reply) {
  bool prepared = false;
  for (const auto& preparation : reply.enrollment_preparations()) {
    if (preparation.second) {
      prepared = true;
      break;
    }
  }

  response->Return(prepared);
}

void LegacyCryptohomeInterfaceAdaptor::
    TpmAttestationGetEnrollmentPreparationsEx(
        std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
            cryptohome::BaseReply>> response,
        const cryptohome::AttestationGetEnrollmentPreparationsRequest&
            in_request) {
  base::Optional<attestation::ACAType> aca_type;
  const int in_pca_type = in_request.pca_type();
  aca_type = IntegerToACAType(in_pca_type);
  if (!aca_type.has_value()) {
    std::string error_msg =
        "Requested ACA type " + std::to_string(in_pca_type) +
        " is not supported in TpmAttestationGetEnrollmentPreparationsEx()";
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             DBUS_ERROR_NOT_SUPPORTED, error_msg);
    return;
  }

  std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>>
      response_shared(new SharedDBusMethodResponse<cryptohome::BaseReply>(
          std::move(response)));

  attestation::GetEnrollmentPreparationsRequest request;
  request.set_aca_type(aca_type.value());

  attestation_proxy_->GetEnrollmentPreparationsAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::
                     TpmAttestationGetEnrollmentPreparationsExOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::
    TpmAttestationGetEnrollmentPreparationsExOnSuccess(
        std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>>
            response,
        const attestation::GetEnrollmentPreparationsReply& reply) {
  cryptohome::BaseReply result;
  AttestationGetEnrollmentPreparationsReply* extension =
      result.MutableExtension(AttestationGetEnrollmentPreparationsReply::reply);

  if (reply.status() != attestation::STATUS_SUCCESS) {
    // Failure.
    result.set_error(CRYPTOHOME_ERROR_INTERNAL_ATTESTATION_ERROR);
  } else {
    auto map = reply.enrollment_preparations();
    for (auto it = map.cbegin(), end = map.cend(); it != end; ++it) {
      (*extension->mutable_enrollment_preparations())[it->first] = it->second;
    }
  }

  ClearErrorIfNotSet(&result);
  response->Return(result);
}

void LegacyCryptohomeInterfaceAdaptor::TpmVerifyAttestationData(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response,
    bool in_is_cros_core) {
  std::shared_ptr<SharedDBusMethodResponse<bool>> response_shared(
      new SharedDBusMethodResponse<bool>(std::move(response)));

  attestation::VerifyRequest request;
  request.set_cros_core(in_is_cros_core);
  request.set_ek_only(false);

  attestation_proxy_->VerifyAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::TpmVerifyAttestationDataOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmVerifyAttestationDataOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const attestation::VerifyReply& reply) {
  if (reply.status() != attestation::STATUS_SUCCESS) {
    std::string error_msg =
        "TpmVerifyAttestationData(): Attestation daemon returned status " +
        std::to_string(static_cast<int>(reply.status()));
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             DBUS_ERROR_FAILED, error_msg);
    return;
  }
  response->Return(reply.verified());
}

void LegacyCryptohomeInterfaceAdaptor::TpmVerifyEK(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response,
    bool in_is_cros_core) {
  std::shared_ptr<SharedDBusMethodResponse<bool>> response_shared(
      new SharedDBusMethodResponse<bool>(std::move(response)));

  attestation::VerifyRequest request;
  request.set_cros_core(in_is_cros_core);
  request.set_ek_only(true);

  attestation_proxy_->VerifyAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::TpmVerifyEKOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmVerifyEKOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const attestation::VerifyReply& reply) {
  if (reply.status() != attestation::STATUS_SUCCESS) {
    std::string error_msg =
        "TpmVerifyEK(): Attestation daemon returned status " +
        std::to_string(static_cast<int>(reply.status()));
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             DBUS_ERROR_FAILED, error_msg);
    return;
  }
  response->Return(reply.verified());
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationCreateEnrollRequest(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<std::vector<uint8_t>>> response,
    int32_t in_pca_type) {
  attestation::CreateEnrollRequestRequest request;
  base::Optional<attestation::ACAType> aca_type;
  aca_type = IntegerToACAType(in_pca_type);
  if (!aca_type.has_value()) {
    std::string error_msg = "Requested ACA type " +
                            std::to_string(in_pca_type) + " is not supported";
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             DBUS_ERROR_NOT_SUPPORTED, error_msg);
    return;
  }
  request.set_aca_type(aca_type.value());

  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<std::vector<uint8_t>>>(
          std::move(response));

  attestation_proxy_->CreateEnrollRequestAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::
                     TpmAttestationCreateEnrollRequestOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::ForwardError<std::vector<uint8_t>>,
          base::Unretained(this), response_shared),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::
    TpmAttestationCreateEnrollRequestOnSuccess(
        std::shared_ptr<SharedDBusMethodResponse<std::vector<uint8_t>>>
            response,
        const attestation::CreateEnrollRequestReply& reply) {
  if (reply.status() != attestation::STATUS_SUCCESS) {
    std::string error_msg = "Attestation daemon returned status " +
                            std::to_string(static_cast<int>(reply.status()));
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             DBUS_ERROR_FAILED, error_msg);
    return;
  }
  std::vector<uint8_t> result(reply.pca_request().begin(),
                              reply.pca_request().end());
  response->Return(result);
}

void LegacyCryptohomeInterfaceAdaptor::AsyncTpmAttestationCreateEnrollRequest(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<int32_t>> response,
    int32_t in_pca_type) {
  attestation::CreateEnrollRequestRequest request;

  base::Optional<attestation::ACAType> aca_type;
  aca_type = IntegerToACAType(in_pca_type);
  if (!aca_type.has_value()) {
    std::string error_msg =
        "AsyncTpmAttestationCreateEnrollRequest(): Requested ACA type " +
        std::to_string(in_pca_type) + " is not supported";
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             DBUS_ERROR_NOT_SUPPORTED, error_msg);
    return;
  }
  request.set_aca_type(aca_type.value());

  int async_id = HandleAsyncData<attestation::CreateEnrollRequestRequest,
                                 attestation::CreateEnrollRequestReply>(
      &attestation::CreateEnrollRequestReply::pca_request, request,
      base::BindOnce(
          &org::chromium::AttestationProxyInterface::CreateEnrollRequestAsync,
          base::Unretained(attestation_proxy_)),
      kAttestationProxyTimeout.InMilliseconds());
  response->Return(async_id);
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationEnroll(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response,
    int32_t in_pca_type,
    const std::vector<uint8_t>& in_pca_response) {
  attestation::FinishEnrollRequest request;
  request.set_pca_response(in_pca_response.data(), in_pca_response.size());
  base::Optional<attestation::ACAType> aca_type;
  aca_type = IntegerToACAType(in_pca_type);
  if (!aca_type.has_value()) {
    std::string error_msg = "Requested ACA type " +
                            std::to_string(in_pca_type) + " is not supported";
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             DBUS_ERROR_NOT_SUPPORTED, error_msg);
    return;
  }
  request.set_aca_type(aca_type.value());

  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<bool>>(std::move(response));
  attestation_proxy_->FinishEnrollAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::TpmAttestationEnrollSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationEnrollSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const attestation::FinishEnrollReply& reply) {
  response->Return(reply.status() ==
                   attestation::AttestationStatus::STATUS_SUCCESS);
}

void LegacyCryptohomeInterfaceAdaptor::AsyncTpmAttestationEnroll(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<int32_t>> response,
    int32_t in_pca_type,
    const std::vector<uint8_t>& in_pca_response) {
  attestation::FinishEnrollRequest request;
  request.set_pca_response(in_pca_response.data(), in_pca_response.size());
  base::Optional<attestation::ACAType> aca_type;
  aca_type = IntegerToACAType(in_pca_type);
  if (!aca_type.has_value()) {
    std::string error_msg = "Requested ACA type " +
                            std::to_string(in_pca_type) + " is not supported";
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             DBUS_ERROR_NOT_SUPPORTED, error_msg);
    return;
  }
  request.set_aca_type(aca_type.value());

  int async_id = HandleAsyncStatus<attestation::FinishEnrollRequest,
                                   attestation::FinishEnrollReply>(
      request,
      base::BindOnce(
          &org::chromium::AttestationProxyInterface::FinishEnrollAsync,
          base::Unretained(attestation_proxy_)),
      kAttestationProxyTimeout.InMilliseconds());

  response->Return(async_id);
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationCreateCertRequest(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<std::vector<uint8_t>>> response,
    int32_t in_pca_type,
    int32_t in_certificate_profile,
    const std::string& in_username,
    const std::string& in_request_origin) {
  attestation::CreateCertificateRequestRequest request;
  request.set_certificate_profile(
      IntegerToCertificateProfile(in_certificate_profile));
  request.set_username(in_username);
  request.set_request_origin(in_request_origin);
  base::Optional<attestation::ACAType> aca_type;
  aca_type = IntegerToACAType(in_pca_type);
  if (!aca_type.has_value()) {
    std::string error_msg = "Requested ACA type " +
                            std::to_string(in_pca_type) + " is not supported";
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             DBUS_ERROR_NOT_SUPPORTED, error_msg);
    return;
  }
  request.set_aca_type(aca_type.value());

  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<std::vector<uint8_t>>>(
          std::move(response));
  attestation_proxy_->CreateCertificateRequestAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::
                     TpmAttestationCreateCertRequestOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::ForwardError<std::vector<uint8_t>>,
          base::Unretained(this), response_shared),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationCreateCertRequestOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<std::vector<uint8_t>>> response,
    const attestation::CreateCertificateRequestReply& reply) {
  if (reply.status() != attestation::STATUS_SUCCESS) {
    std::string error_msg = "Attestation daemon returned status " +
                            std::to_string(static_cast<int>(reply.status()));
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             DBUS_ERROR_FAILED, error_msg);
    return;
  }
  std::vector<uint8_t> result(reply.pca_request().begin(),
                              reply.pca_request().end());
  response->Return(result);
}

void LegacyCryptohomeInterfaceAdaptor::AsyncTpmAttestationCreateCertRequest(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<int32_t>> response,
    int32_t in_pca_type,
    int32_t in_certificate_profile,
    const std::string& in_username,
    const std::string& in_request_origin) {
  attestation::CreateCertificateRequestRequest request;

  base::Optional<attestation::ACAType> aca_type;
  aca_type = IntegerToACAType(in_pca_type);
  if (!aca_type.has_value()) {
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             DBUS_ERROR_NOT_SUPPORTED,
                             "Requested ACA type is not supported");
    return;
  }

  request.set_aca_type(aca_type.value());
  request.set_certificate_profile(
      IntegerToCertificateProfile(in_certificate_profile));
  request.set_username(in_username);
  request.set_request_origin(in_request_origin);
  int async_id = HandleAsyncData<attestation::CreateCertificateRequestRequest,
                                 attestation::CreateCertificateRequestReply>(
      &attestation::CreateCertificateRequestReply::pca_request, request,
      base::BindOnce(&org::chromium::AttestationProxyInterface::
                         CreateCertificateRequestAsync,
                     base::Unretained(attestation_proxy_)),
      kAttestationProxyTimeout.InMilliseconds());
  response->Return(async_id);
  return;
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationFinishCertRequest(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<std::vector<uint8_t>,
                                                           bool>> response,
    const std::vector<uint8_t>& in_pca_response,
    bool in_is_user_specific,
    const std::string& in_username,
    const std::string& in_key_name) {
  attestation::FinishCertificateRequestRequest request;
  request.set_pca_response(in_pca_response.data(), in_pca_response.size());
  request.set_key_label(in_key_name);
  if (in_is_user_specific) {
    request.set_username(in_username);
  }

  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<std::vector<uint8_t>, bool>>(
          std::move(response));
  attestation_proxy_->FinishCertificateRequestAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::
                     TpmAttestationFinishCertRequestOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::ForwardError<std::vector<uint8_t>,
                                                          bool>,
          base::Unretained(this), response_shared),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationFinishCertRequestOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<std::vector<uint8_t>, bool>>
        response,
    const attestation::FinishCertificateRequestReply& reply) {
  std::vector<uint8_t> cert;
  if (reply.status() == attestation::AttestationStatus::STATUS_SUCCESS) {
    cert.assign(reply.certificate().begin(), reply.certificate().end());
  } else {
    LOG(WARNING) << "TpmAttestationFinishCertRequest(): Attestation daemon "
                    "returned status "
                 << static_cast<int>(reply.status());
  }
  response->Return(
      cert, reply.status() == attestation::AttestationStatus::STATUS_SUCCESS);
}

void LegacyCryptohomeInterfaceAdaptor::AsyncTpmAttestationFinishCertRequest(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<int32_t>> response,
    const std::vector<uint8_t>& in_pca_response,
    bool in_is_user_specific,
    const std::string& in_username,
    const std::string& in_key_name) {
  attestation::FinishCertificateRequestRequest request;
  request.set_pca_response(in_pca_response.data(), in_pca_response.size());
  request.set_key_label(in_key_name);
  if (in_is_user_specific) {
    request.set_username(in_username);
  }

  int async_id = HandleAsyncData<attestation::FinishCertificateRequestRequest,
                                 attestation::FinishCertificateRequestReply>(
      &attestation::FinishCertificateRequestReply::certificate, request,
      base::BindOnce(&org::chromium::AttestationProxyInterface::
                         FinishCertificateRequestAsync,
                     base::Unretained(attestation_proxy_)),
      kAttestationProxyTimeout.InMilliseconds());
  response->Return(async_id);
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationEnrollEx(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response,
    int32_t in_pca_type,
    bool in_forced) {
  DCHECK(false) << "Not implemented.";
}

void LegacyCryptohomeInterfaceAdaptor::AsyncTpmAttestationEnrollEx(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<int32_t>> response,
    int32_t in_pca_type,
    bool in_forced) {
  DCHECK(false) << "Not implemented.";
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationGetCertificateEx(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<std::vector<uint8_t>,
                                                           bool>> response,
    int32_t in_certificate_profile,
    const std::string& in_username,
    const std::string& in_request_origin,
    int32_t in_pca_type,
    int32_t in_key_type,
    const std::string& in_key_name,
    bool in_forced,
    bool in_shall_trigger_enrollment) {
  DCHECK(false) << "Not implemented.";
}

void LegacyCryptohomeInterfaceAdaptor::AsyncTpmAttestationGetCertificateEx(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<int32_t>> response,
    int32_t in_certificate_profile,
    const std::string& in_username,
    const std::string& in_request_origin,
    int32_t in_pca_type,
    int32_t in_key_type,
    const std::string& in_key_name,
    bool in_forced,
    bool in_shall_trigger_enrollment) {
  DCHECK(false) << "Not implemented.";
}

void LegacyCryptohomeInterfaceAdaptor::TpmIsAttestationEnrolled(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response) {
  std::shared_ptr<SharedDBusMethodResponse<bool>> response_shared(
      new SharedDBusMethodResponse<bool>(std::move(response)));

  attestation::GetStatusRequest request;
  request.set_extended_status(false);

  attestation_proxy_->GetStatusAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::TpmIsAttestationEnrolledOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmIsAttestationEnrolledOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const attestation::GetStatusReply& reply) {
  if (reply.status() != attestation::AttestationStatus::STATUS_SUCCESS) {
    std::string error_msg =
        "TpmIsAttestationEnrolled(): Attestation daemon returned status " +
        std::to_string(static_cast<int>(reply.status()));
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             DBUS_ERROR_FAILED, error_msg);
    return;
  }
  response->Return(reply.enrolled());
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationDoesKeyExist(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response,
    bool in_is_user_specific,
    const std::string& in_username,
    const std::string& in_key_name) {
  std::shared_ptr<SharedDBusMethodResponse<bool>> response_shared(
      new SharedDBusMethodResponse<bool>(std::move(response)));

  attestation::GetKeyInfoRequest request;
  request.set_key_label(in_key_name);
  if (in_is_user_specific) {
    request.set_username(in_username);
  }

  attestation_proxy_->GetKeyInfoAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::
                     TpmAttestationDoesKeyExistOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationDoesKeyExistOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const attestation::GetKeyInfoReply& reply) {
  response->Return(reply.status() ==
                   attestation::AttestationStatus::STATUS_SUCCESS);
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationGetCertificate(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<std::vector<uint8_t>,
                                                           bool>> response,
    bool in_is_user_specific,
    const std::string& in_username,
    const std::string& in_key_name) {
  std::shared_ptr<SharedDBusMethodResponse<std::vector<uint8_t>, bool>>
      response_shared(new SharedDBusMethodResponse<std::vector<uint8_t>, bool>(
          std::move(response)));

  attestation::GetKeyInfoRequest request;
  request.set_key_label(in_key_name);
  if (in_is_user_specific) {
    request.set_username(in_username);
  }

  attestation_proxy_->GetKeyInfoAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::
                     TpmAttestationGetCertificateOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::ForwardError<std::vector<uint8_t>,
                                                          bool>,
          base::Unretained(this), response_shared),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationGetCertificateOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<std::vector<uint8_t>, bool>>
        response,
    const attestation::GetKeyInfoReply& reply) {
  if (reply.status() != attestation::AttestationStatus::STATUS_SUCCESS) {
    std::string error_msg =
        "TpmAttestationGetCertificate(): Attestation daemon returned status " +
        std::to_string(static_cast<int>(reply.status()));
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             DBUS_ERROR_FAILED, error_msg);
    return;
  }
  std::vector<uint8_t> cert(reply.certificate().begin(),
                            reply.certificate().end());
  response->Return(
      cert, reply.status() == attestation::AttestationStatus::STATUS_SUCCESS);
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationGetPublicKey(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<std::vector<uint8_t>,
                                                           bool>> response,
    bool in_is_user_specific,
    const std::string& in_username,
    const std::string& in_key_name) {
  std::shared_ptr<SharedDBusMethodResponse<std::vector<uint8_t>, bool>>
      response_shared(new SharedDBusMethodResponse<std::vector<uint8_t>, bool>(
          std::move(response)));

  attestation::GetKeyInfoRequest request;
  request.set_key_label(in_key_name);
  if (in_is_user_specific) {
    request.set_username(in_username);
  }

  attestation_proxy_->GetKeyInfoAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::
                     TpmAttestationGetPublicKeyOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::ForwardError<std::vector<uint8_t>,
                                                          bool>,
          base::Unretained(this), response_shared),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationGetPublicKeyOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<std::vector<uint8_t>, bool>>
        response,
    const attestation::GetKeyInfoReply& reply) {
  if (reply.status() != attestation::AttestationStatus::STATUS_SUCCESS) {
    std::string error_msg =
        "TpmAttestationGetPublicKey(): Attestation daemon returned status " +
        std::to_string(static_cast<int>(reply.status()));
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             DBUS_ERROR_FAILED, error_msg);
    return;
  }
  std::vector<uint8_t> public_key(reply.public_key().begin(),
                                  reply.public_key().end());
  response->Return(
      public_key,
      reply.status() == attestation::AttestationStatus::STATUS_SUCCESS);
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationGetEnrollmentId(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<std::vector<uint8_t>,
                                                           bool>> response,
    bool in_ignore_cache) {
  attestation::GetEnrollmentIdRequest request;
  request.set_ignore_cache(in_ignore_cache);

  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<std::vector<uint8_t>, bool>>(
          std::move(response));
  attestation_proxy_->GetEnrollmentIdAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::
                     TpmAttestationGetEnrollmentIdOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::ForwardError<std::vector<uint8_t>,
                                                          bool>,
          base::Unretained(this), response_shared),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationGetEnrollmentIdOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<std::vector<uint8_t>, bool>>
        response,
    const attestation::GetEnrollmentIdReply& reply) {
  std::vector<uint8_t> enrollment_id;
  if (reply.status() == attestation::AttestationStatus::STATUS_SUCCESS) {
    enrollment_id.assign(reply.enrollment_id().begin(),
                         reply.enrollment_id().end());
  } else {
    LOG(WARNING) << "TpmAttestationGetEnrollmentId(): Attestation daemon "
                    "returned status "
                 << static_cast<int>(reply.status());
  }
  response->Return(
      enrollment_id,
      reply.status() == attestation::AttestationStatus::STATUS_SUCCESS);
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationRegisterKey(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<int32_t>> response,
    bool in_is_user_specific,
    const std::string& in_username,
    const std::string& in_key_name) {
  attestation::RegisterKeyWithChapsTokenRequest request;
  request.set_key_label(in_key_name);
  if (in_is_user_specific) {
    request.set_username(in_username);
  }

  int async_id =
      HandleAsyncStatus<attestation::RegisterKeyWithChapsTokenRequest,
                        attestation::RegisterKeyWithChapsTokenReply>(
          request,
          base::BindOnce(&org::chromium::AttestationProxyInterface::
                             RegisterKeyWithChapsTokenAsync,
                         base::Unretained(attestation_proxy_)),
          kAttestationProxyTimeout.InMilliseconds());

  response->Return(async_id);
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationSignEnterpriseChallenge(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<int32_t>> response,
    bool in_is_user_specific,
    const std::string& in_username,
    const std::string& in_key_name,
    const std::string& in_domain,
    const std::vector<uint8_t>& in_device_id,
    bool in_include_signed_public_key,
    const std::vector<uint8_t>& in_challenge) {
  TpmAttestationSignEnterpriseVaChallenge(
      std::move(response), static_cast<int32_t>(attestation::DEFAULT_VA),
      in_is_user_specific, in_username, in_key_name, in_domain, in_device_id,
      in_include_signed_public_key, in_challenge);
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationSignEnterpriseVaChallenge(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<int32_t>> response,
    int32_t in_va_type,
    bool in_is_user_specific,
    const std::string& in_username,
    const std::string& in_key_name,
    const std::string& in_domain,
    const std::vector<uint8_t>& in_device_id,
    bool in_include_signed_public_key,
    const std::vector<uint8_t>& in_challenge) {
  TpmAttestationSignEnterpriseVaChallengeV2Actual(
      std::move(response), in_va_type, in_is_user_specific, in_username,
      in_key_name, in_domain, in_device_id, in_include_signed_public_key,
      in_challenge, base::nullopt);
}

void LegacyCryptohomeInterfaceAdaptor::
    TpmAttestationSignEnterpriseVaChallengeV2(
        std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<int32_t>>
            response,
        int32_t in_va_type,
        bool in_is_user_specific,
        const std::string& in_username,
        const std::string& in_key_name,
        const std::string& in_domain,
        const std::vector<uint8_t>& in_device_id,
        bool in_include_signed_public_key,
        const std::vector<uint8_t>& in_challenge,
        const std::string& in_key_name_for_spkac) {
  TpmAttestationSignEnterpriseVaChallengeV2Actual(
      std::move(response), in_va_type, in_is_user_specific, in_username,
      in_key_name, in_domain, in_device_id, in_include_signed_public_key,
      in_challenge, in_key_name_for_spkac);
}

void LegacyCryptohomeInterfaceAdaptor::
    TpmAttestationSignEnterpriseVaChallengeV2Actual(
        std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<int32_t>>
            response,
        int32_t in_va_type,
        bool in_is_user_specific,
        const std::string& in_username,
        const std::string& in_key_name,
        const std::string& in_domain,
        const std::vector<uint8_t>& in_device_id,
        bool in_include_signed_public_key,
        const std::vector<uint8_t>& in_challenge,
        const base::Optional<std::string> in_key_name_for_spkac) {
  base::Optional<attestation::VAType> va_type;
  va_type = IntegerToVAType(in_va_type);
  if (!va_type.has_value()) {
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             DBUS_ERROR_NOT_SUPPORTED,
                             "Requested VA type is not supported");
    return;
  }

  attestation::SignEnterpriseChallengeRequest request;
  request.set_va_type(va_type.value());
  request.set_key_label(in_key_name);
  if (in_is_user_specific) {
    request.set_username(in_username);
  }
  request.set_domain(in_domain);
  *request.mutable_device_id() = {in_device_id.begin(), in_device_id.end()};
  request.set_include_signed_public_key(in_include_signed_public_key);
  *request.mutable_challenge() = {in_challenge.begin(), in_challenge.end()};
  if (in_key_name_for_spkac) {
    request.set_key_name_for_spkac(in_key_name_for_spkac.value());
  }

  int async_id = HandleAsyncData<attestation::SignEnterpriseChallengeRequest,
                                 attestation::SignEnterpriseChallengeReply>(
      &attestation::SignEnterpriseChallengeReply::challenge_response, request,
      base::BindOnce(&org::chromium::AttestationProxyInterface::
                         SignEnterpriseChallengeAsync,
                     base::Unretained(attestation_proxy_)),
      kAttestationProxyTimeout.InMilliseconds());

  response->Return(async_id);
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationSignSimpleChallenge(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<int32_t>> response,
    bool in_is_user_specific,
    const std::string& in_username,
    const std::string& in_key_name,
    const std::vector<uint8_t>& in_challenge) {
  attestation::SignSimpleChallengeRequest request;
  request.set_key_label(in_key_name);
  if (in_is_user_specific) {
    request.set_username(in_username);
  }
  *request.mutable_challenge() = {in_challenge.begin(), in_challenge.end()};

  int async_id = HandleAsyncData<attestation::SignSimpleChallengeRequest,
                                 attestation::SignSimpleChallengeReply>(
      &attestation::SignSimpleChallengeReply::challenge_response, request,
      base::BindOnce(
          &org::chromium::AttestationProxyInterface::SignSimpleChallengeAsync,
          base::Unretained(attestation_proxy_)),
      kAttestationProxyTimeout.InMilliseconds());

  response->Return(async_id);
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationGetKeyPayload(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<std::vector<uint8_t>,
                                                           bool>> response,
    bool in_is_user_specific,
    const std::string& in_username,
    const std::string& in_key_name) {
  std::shared_ptr<SharedDBusMethodResponse<std::vector<uint8_t>, bool>>
      response_shared(new SharedDBusMethodResponse<std::vector<uint8_t>, bool>(
          std::move(response)));

  attestation::GetKeyInfoRequest request;
  request.set_key_label(in_key_name);
  if (in_is_user_specific) {
    request.set_username(in_username);
  }

  attestation_proxy_->GetKeyInfoAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::
                     TpmAttestationGetKeyPayloadOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::ForwardError<std::vector<uint8_t>,
                                                          bool>,
          base::Unretained(this), response_shared),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationGetKeyPayloadOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<std::vector<uint8_t>, bool>>
        response,
    const attestation::GetKeyInfoReply& reply) {
  if (reply.status() != attestation::AttestationStatus::STATUS_SUCCESS) {
    std::string error_msg =
        "TpmAttestationGetKeyPayload(): Attestation daemon returned status " +
        std::to_string(static_cast<int>(reply.status()));
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             DBUS_ERROR_FAILED, error_msg);
    return;
  }
  std::vector<uint8_t> public_key(reply.payload().begin(),
                                  reply.payload().end());
  response->Return(
      public_key,
      reply.status() == attestation::AttestationStatus::STATUS_SUCCESS);
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationSetKeyPayload(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response,
    bool in_is_user_specific,
    const std::string& in_username,
    const std::string& in_key_name,
    const std::vector<uint8_t>& in_payload) {
  std::shared_ptr<SharedDBusMethodResponse<bool>> response_shared(
      new SharedDBusMethodResponse<bool>(std::move(response)));

  attestation::SetKeyPayloadRequest request;
  request.set_key_label(in_key_name);
  if (in_is_user_specific) {
    request.set_username(in_username);
  }
  *request.mutable_payload() = {in_payload.begin(), in_payload.end()};

  attestation_proxy_->SetKeyPayloadAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::
                     TpmAttestationSetKeyPayloadOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationSetKeyPayloadOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const attestation::SetKeyPayloadReply& reply) {
  if (reply.status() != attestation::AttestationStatus::STATUS_SUCCESS) {
    LOG(WARNING)
        << "TpmAttestationSetKeyPayload(): Attestation daemon returned status "
        << static_cast<int>(reply.status());
  }
  response->Return(reply.status() ==
                   attestation::AttestationStatus::STATUS_SUCCESS);
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationDeleteKeys(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response,
    bool in_is_user_specific,
    const std::string& in_username,
    const std::string& in_key_prefix) {
  std::shared_ptr<SharedDBusMethodResponse<bool>> response_shared(
      new SharedDBusMethodResponse<bool>(std::move(response)));

  attestation::DeleteKeysRequest request;
  request.set_key_label_match(in_key_prefix);
  request.set_match_behavior(
      attestation::DeleteKeysRequest::MATCH_BEHAVIOR_PREFIX);
  if (in_is_user_specific) {
    request.set_username(in_username);
  }

  attestation_proxy_->DeleteKeysAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::TpmAttestationDeleteKeysOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationDeleteKeysOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const attestation::DeleteKeysReply& reply) {
  if (reply.status() != attestation::AttestationStatus::STATUS_SUCCESS) {
    LOG(WARNING)
        << "TpmAttestationDeleteKeys(): Attestation daemon returned status "
        << static_cast<int>(reply.status());
  }
  response->Return(reply.status() ==
                   attestation::AttestationStatus::STATUS_SUCCESS);
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationDeleteKey(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response,
    bool in_is_user_specific,
    const std::string& in_username,
    const std::string& in_key_name) {
  std::shared_ptr<SharedDBusMethodResponse<bool>> response_shared(
      new SharedDBusMethodResponse<bool>(std::move(response)));

  attestation::DeleteKeysRequest request;
  request.set_key_label_match(in_key_name);
  request.set_match_behavior(
      attestation::DeleteKeysRequest::MATCH_BEHAVIOR_EXACT);
  if (in_is_user_specific) {
    request.set_username(in_username);
  }

  attestation_proxy_->DeleteKeysAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::TpmAttestationDeleteKeysOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationDeleteKeyOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const attestation::DeleteKeysReply& reply) {
  if (reply.status() != attestation::AttestationStatus::STATUS_SUCCESS) {
    LOG(WARNING)
        << "TpmAttestationDeleteKey(): Attestation daemon returned status "
        << static_cast<int>(reply.status());
  }
  response->Return(reply.status() ==
                   attestation::AttestationStatus::STATUS_SUCCESS);
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationGetEK(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<std::string, bool>>
        response) {
  std::shared_ptr<SharedDBusMethodResponse<std::string, bool>> response_shared(
      new SharedDBusMethodResponse<std::string, bool>(std::move(response)));

  attestation::GetEndorsementInfoRequest request;

  attestation_proxy_->GetEndorsementInfoAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::TpmAttestationGetEKOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::ForwardError<std::string, bool>,
          base::Unretained(this), response_shared),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationGetEKOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<std::string, bool>> response,
    const attestation::GetEndorsementInfoReply& reply) {
  if (reply.status() != attestation::AttestationStatus::STATUS_SUCCESS) {
    LOG(WARNING) << "TpmAttestationGetEK(): Attestation daemon returned status "
                 << static_cast<int>(reply.status());
  }
  response->Return(
      reply.ek_info(),
      reply.status() == attestation::AttestationStatus::STATUS_SUCCESS);
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationResetIdentity(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<std::vector<uint8_t>,
                                                           bool>> response,
    const std::string& in_reset_token) {
  attestation::ResetIdentityRequest request;
  request.set_reset_token(in_reset_token);

  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<std::vector<uint8_t>, bool>>(
          std::move(response));
  attestation_proxy_->ResetIdentityAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::
                     TpmAttestationResetIdentityOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::ForwardError<std::vector<uint8_t>,
                                                          bool>,
          base::Unretained(this), response_shared),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmAttestationResetIdentityOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<std::vector<uint8_t>, bool>>
        response,
    const attestation::ResetIdentityReply& reply) {
  std::vector<uint8_t> reset_request;
  if (reply.status() == attestation::AttestationStatus::STATUS_SUCCESS) {
    reset_request.assign(reply.reset_request().begin(),
                         reply.reset_request().end());
  } else {
    LOG(WARNING)
        << "TpmAttestationResetIdentity(): Attestation daemon returned status "
        << static_cast<int>(reply.status());
  }
  response->Return(
      reset_request,
      reply.status() == attestation::AttestationStatus::STATUS_SUCCESS);
}

void LegacyCryptohomeInterfaceAdaptor::TpmGetVersionStructured(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<uint32_t,
                                                           uint64_t,
                                                           uint32_t,
                                                           uint32_t,
                                                           uint64_t,
                                                           std::string>>
        response) {
  auto response_shared = std::make_shared<SharedDBusMethodResponse<
      uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, std::string>>(
      std::move(response));

  tpm_manager::GetVersionInfoRequest request;
  tpm_ownership_proxy_->GetVersionInfoAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::TpmGetVersionStructuredOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::ForwardError<
              uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, std::string>,
          base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::TpmGetVersionStructuredOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<uint32_t,
                                             uint64_t,
                                             uint32_t,
                                             uint32_t,
                                             uint64_t,
                                             std::string>> response,
    const tpm_manager::GetVersionInfoReply& reply) {
  // Note that the TpmGetVersionSuccessStructured method in CryptohomeInterface
  // doesn't return any error, so we don't check reply.status() here.
  response->Return(reply.family(), reply.spec_level(), reply.manufacturer(),
                   reply.tpm_model(), reply.firmware_version(),
                   base::HexEncode(reply.vendor_specific().data(),
                                   reply.vendor_specific().size()));
}

void LegacyCryptohomeInterfaceAdaptor::Pkcs11IsTpmTokenReady(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<bool>>(std::move(response));

  user_data_auth::Pkcs11IsTpmTokenReadyRequest request;
  pkcs11_proxy_->Pkcs11IsTpmTokenReadyAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::Pkcs11IsTpmTokenReadyOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::Pkcs11IsTpmTokenReadyOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const user_data_auth::Pkcs11IsTpmTokenReadyReply& reply) {
  response->Return(reply.ready());
}

void LegacyCryptohomeInterfaceAdaptor::Pkcs11GetTpmTokenInfo(
    std::unique_ptr<brillo::dbus_utils::
                        DBusMethodResponse<std::string, std::string, int32_t>>
        response) {
  auto response_shared = std::make_shared<
      SharedDBusMethodResponse<std::string, std::string, int32_t>>(
      std::move(response));

  user_data_auth::Pkcs11GetTpmTokenInfoRequest request;
  pkcs11_proxy_->Pkcs11GetTpmTokenInfoAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::Pkcs11GetTpmTokenInfoOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::ForwardError<std::string,
                                                          std::string, int32_t>,
          base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::Pkcs11GetTpmTokenInfoForUser(
    std::unique_ptr<brillo::dbus_utils::
                        DBusMethodResponse<std::string, std::string, int32_t>>
        response,
    const std::string& in_username) {
  auto response_shared = std::make_shared<
      SharedDBusMethodResponse<std::string, std::string, int32_t>>(
      std::move(response));

  user_data_auth::Pkcs11GetTpmTokenInfoRequest request;
  request.set_username(in_username);
  // Note that the response needed for Pkcs11GetTpmTokenInfo and
  // Pkcs11GetTpmTokenInfoForUser are the same, so we'll use the
  // Pkcs11GetTpmTokenInfo version here.
  pkcs11_proxy_->Pkcs11GetTpmTokenInfoAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::Pkcs11GetTpmTokenInfoOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::ForwardError<std::string,
                                                          std::string, int32_t>,
          base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::Pkcs11GetTpmTokenInfoOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<std::string, std::string, int32_t>>
        response,
    const user_data_auth::Pkcs11GetTpmTokenInfoReply& reply) {
  response->Return(reply.token_info().label(), reply.token_info().user_pin(),
                   reply.token_info().slot());
}

void LegacyCryptohomeInterfaceAdaptor::Pkcs11Terminate(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>> response,
    const std::string& in_username) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<>>(std::move(response));

  user_data_auth::Pkcs11TerminateRequest request;
  request.set_username(in_username);
  pkcs11_proxy_->Pkcs11TerminateAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::Pkcs11TerminateOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::Pkcs11TerminateOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<>> response,
    const user_data_auth::Pkcs11TerminateReply& reply) {
  response->Return();
}

void LegacyCryptohomeInterfaceAdaptor::GetStatusString(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<std::string>>
        response) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<std::string>>(
          std::move(response));

  user_data_auth::GetStatusStringRequest request;
  misc_proxy_->GetStatusStringAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::GetStatusStringOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<std::string>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::GetStatusStringOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<std::string>> response,
    const user_data_auth::GetStatusStringReply& reply) {
  response->Return(reply.status());
}

void LegacyCryptohomeInterfaceAdaptor::InstallAttributesGet(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<std::vector<uint8_t>,
                                                           bool>> response,
    const std::string& in_name) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<std::vector<uint8_t>, bool>>(
          std::move(response));

  user_data_auth::InstallAttributesGetRequest request;
  request.set_name(in_name);
  install_attributes_proxy_->InstallAttributesGetAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::InstallAttributesGetOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::ForwardError<std::vector<uint8_t>,
                                                          bool>,
          base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::InstallAttributesGetOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<std::vector<uint8_t>, bool>>
        response,
    const user_data_auth::InstallAttributesGetReply& reply) {
  std::vector<uint8_t> result(reply.value().begin(), reply.value().end());
  bool success = (reply.error() == user_data_auth::CRYPTOHOME_ERROR_NOT_SET);
  response->Return(result, success);
}

void LegacyCryptohomeInterfaceAdaptor::InstallAttributesSet(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response,
    const std::string& in_name,
    const std::vector<uint8_t>& in_value) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<bool>>(std::move(response));

  user_data_auth::InstallAttributesSetRequest request;
  request.set_name(in_name);
  *request.mutable_value() = {in_value.begin(), in_value.end()};
  install_attributes_proxy_->InstallAttributesSetAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::InstallAttributesSetOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::InstallAttributesSetOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const user_data_auth::InstallAttributesSetReply& reply) {
  bool success = (reply.error() == user_data_auth::CRYPTOHOME_ERROR_NOT_SET);
  response->Return(success);
}

void LegacyCryptohomeInterfaceAdaptor::InstallAttributesCount(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<int32_t>> response) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<int32_t>>(std::move(response));

  user_data_auth::InstallAttributesGetStatusRequest request;
  install_attributes_proxy_->InstallAttributesGetStatusAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::InstallAttributesCountOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<int32_t>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::InstallAttributesCountOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<int32_t>> response,
    const user_data_auth::InstallAttributesGetStatusReply& reply) {
  response->Return(reply.count());
}

void LegacyCryptohomeInterfaceAdaptor::InstallAttributesFinalize(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<bool>>(std::move(response));

  user_data_auth::InstallAttributesFinalizeRequest request;
  install_attributes_proxy_->InstallAttributesFinalizeAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::InstallAttributesFinalizeOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::InstallAttributesFinalizeOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const user_data_auth::InstallAttributesFinalizeReply& reply) {
  bool success = (reply.error() == user_data_auth::CRYPTOHOME_ERROR_NOT_SET);
  response->Return(success);
}

void LegacyCryptohomeInterfaceAdaptor::InstallAttributesIsReady(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<bool>>(std::move(response));

  user_data_auth::InstallAttributesGetStatusRequest request;
  install_attributes_proxy_->InstallAttributesGetStatusAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::InstallAttributesIsReadyOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::InstallAttributesIsReadyOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const user_data_auth::InstallAttributesGetStatusReply& reply) {
  bool ready =
      (reply.state() != user_data_auth::InstallAttributesState::UNKNOWN &&
       reply.state() != user_data_auth::InstallAttributesState::TPM_NOT_OWNED);
  response->Return(ready);
}

void LegacyCryptohomeInterfaceAdaptor::InstallAttributesIsSecure(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<bool>>(std::move(response));

  user_data_auth::InstallAttributesGetStatusRequest request;
  install_attributes_proxy_->InstallAttributesGetStatusAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::InstallAttributesIsSecureOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::InstallAttributesIsSecureOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const user_data_auth::InstallAttributesGetStatusReply& reply) {
  response->Return(reply.is_secure());
}

void LegacyCryptohomeInterfaceAdaptor::InstallAttributesIsInvalid(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<bool>>(std::move(response));

  user_data_auth::InstallAttributesGetStatusRequest request;
  install_attributes_proxy_->InstallAttributesGetStatusAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::
                     InstallAttributesIsInvalidOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::InstallAttributesIsInvalidOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const user_data_auth::InstallAttributesGetStatusReply& reply) {
  bool is_invalid =
      (reply.state() == user_data_auth::InstallAttributesState::INVALID);
  response->Return(is_invalid);
}

void LegacyCryptohomeInterfaceAdaptor::InstallAttributesIsFirstInstall(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<bool>>(std::move(response));

  user_data_auth::InstallAttributesGetStatusRequest request;
  install_attributes_proxy_->InstallAttributesGetStatusAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::
                     InstallAttributesIsFirstInstallOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::InstallAttributesIsFirstInstallOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const user_data_auth::InstallAttributesGetStatusReply& reply) {
  bool is_first_install =
      (reply.state() == user_data_auth::InstallAttributesState::FIRST_INSTALL);
  response->Return(is_first_install);
}

void LegacyCryptohomeInterfaceAdaptor::SignBootLockbox(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::SignBootLockboxRequest& in_request) {
  // Note that this version of Boot Lockbox is deprecated for security and
  // performance issue. Please use the version in bootlockboxd instead.
  response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                           DBUS_ERROR_NOT_SUPPORTED,
                           "Deprecated method SignBootLockbox() called");
}

void LegacyCryptohomeInterfaceAdaptor::VerifyBootLockbox(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::VerifyBootLockboxRequest& in_request) {
  // Note that this version of Boot Lockbox is deprecated for security and
  // performance issue. Please use the version in bootlockboxd instead.
  response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                           DBUS_ERROR_NOT_SUPPORTED,
                           "Deprecated method VerifyBootLockbox() called");
}

void LegacyCryptohomeInterfaceAdaptor::FinalizeBootLockbox(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::FinalizeBootLockboxRequest& in_request) {
  // Note that this version of Boot Lockbox is deprecated for security and
  // performance issue. Please use the version in bootlockboxd instead.
  response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                           DBUS_ERROR_NOT_SUPPORTED,
                           "Deprecated method FinalizeBootLockbox() called");
}

void LegacyCryptohomeInterfaceAdaptor::GetBootAttribute(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::GetBootAttributeRequest& in_request) {
  // BootAttribute series methods are no longer available.
  response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                           DBUS_ERROR_NOT_SUPPORTED,
                           "Obsolete method GetBootAttribute() called");
}

void LegacyCryptohomeInterfaceAdaptor::SetBootAttribute(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::SetBootAttributeRequest& in_request) {
  // BootAttribute series methods are no longer available.
  response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                           DBUS_ERROR_NOT_SUPPORTED,
                           "Obsolete method SetBootAttribute() called");
}

void LegacyCryptohomeInterfaceAdaptor::FlushAndSignBootAttributes(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::FlushAndSignBootAttributesRequest& in_request) {
  // BootAttribute series methods are no longer available.
  response->ReplyWithError(
      FROM_HERE, brillo::errors::dbus::kDomain, DBUS_ERROR_NOT_SUPPORTED,
      "Obsolete method FlushAndSignBootAttributes() called");
}

void LegacyCryptohomeInterfaceAdaptor::GetLoginStatus(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::GetLoginStatusRequest& in_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::GetLoginStatusRequest request;
  misc_proxy_->GetLoginStatusAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::GetLoginStatusOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::GetLoginStatusOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>> response,
    const user_data_auth::GetLoginStatusReply& reply) {
  cryptohome::BaseReply result;
  result.set_error(static_cast<cryptohome::CryptohomeErrorCode>(reply.error()));
  auto* extension =
      result.MutableExtension(cryptohome::GetLoginStatusReply::reply);
  extension->set_owner_user_exists(reply.owner_user_exists());
  extension->set_is_locked_to_single_user(reply.is_locked_to_single_user());

  // See definition of user_data_auth::GetLoginStatusReply for more information
  // on why |boot_lockbox_finalized| is deprecated.
  // Note that it's set to a false value here to ensure clients that expect this
  // field continues to work.
  extension->set_boot_lockbox_finalized(false);

  ClearErrorIfNotSet(&result);
  response->Return(result);
}

void LegacyCryptohomeInterfaceAdaptor::GetTpmStatus(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::GetTpmStatusRequest& in_request) {
  // This method requires the output of more than 1 method and thus is divided
  // into various parts:
  // - TpmManager stage: Calls GetTpmStatus() in tpm_manager
  // - DictionaryAttack stage: Calls GetDictionaryAttackInfo() in tpm_manager
  // - InstallAttributes stage: Calls InstallAttributesGetStatus() in
  // UserDataAuth
  // - Attestation stage: Calls GetStatus() in attestation
  // The 4 stages is executed back to back according to the sequence listed
  // above. After all of them are done, we'll take their results and form the
  // response for this method call.
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  tpm_manager::GetTpmStatusRequest request;
  tpm_ownership_proxy_->GetTpmStatusAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::
                     GetTpmStatusOnStageOwnershipStatusDone,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::GetTpmStatusOnStageOwnershipStatusDone(
    std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>> response,
    const tpm_manager::GetTpmStatusReply& status_reply) {
  if (status_reply.status() != tpm_manager::STATUS_SUCCESS) {
    LOG(ERROR) << "GetTpmStatus() failed to call GetTpmStatus in tpm_manager, "
                  "error status "
               << static_cast<int>(status_reply.status());
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             DBUS_ERROR_FAILED, "GetTpmStatus() failed");
    return;
  }

  BaseReply reply;
  GetTpmStatusReply* extension =
      reply.MutableExtension(cryptohome::GetTpmStatusReply::reply);
  extension->set_enabled(status_reply.enabled());
  extension->set_owned(status_reply.owned());
  if (!status_reply.local_data().owner_password().empty()) {
    extension->set_initialized(false);
    extension->set_owner_password(status_reply.local_data().owner_password());
  } else {
    // Initialized is true only when the TPM is owned and the owner password has
    // already been destroyed.
    extension->set_initialized(extension->owned());
  }

  bool has_reset_lock_permissions = true;
  if (status_reply.local_data().owner_password().empty()) {
    if (status_reply.local_data().lockout_password().empty() &&
        !status_reply.local_data().has_owner_delegate()) {
      has_reset_lock_permissions = false;
    } else if (status_reply.local_data().has_owner_delegate() &&
               !status_reply.local_data()
                    .owner_delegate()
                    .has_reset_lock_permissions()) {
      has_reset_lock_permissions = false;
    }
  }
  extension->set_has_reset_lock_permissions(has_reset_lock_permissions);

  tpm_manager::GetDictionaryAttackInfoRequest request;
  tpm_ownership_proxy_->GetDictionaryAttackInfoAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::
                     GetTpmStatusOnStageDictionaryAttackDone,
                 base::Unretained(this), response, reply),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::GetTpmStatusOnStageDictionaryAttackDone(
    std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>> response,
    BaseReply reply,
    const tpm_manager::GetDictionaryAttackInfoReply& da_reply) {
  // Note that it is intentional that we do not fail even if
  // GetDictionaryAttackInfo() fails. This failure is logged as an error, but
  // not acted upon.

  GetTpmStatusReply* extension =
      reply.MutableExtension(cryptohome::GetTpmStatusReply::reply);
  if (da_reply.status() == tpm_manager::STATUS_SUCCESS) {
    extension->set_dictionary_attack_counter(
        da_reply.dictionary_attack_counter());
    extension->set_dictionary_attack_threshold(
        da_reply.dictionary_attack_threshold());
    extension->set_dictionary_attack_lockout_in_effect(
        da_reply.dictionary_attack_lockout_in_effect());
    extension->set_dictionary_attack_lockout_seconds_remaining(
        da_reply.dictionary_attack_lockout_seconds_remaining());
  } else {
    LOG(ERROR) << "Failed to call GetDictionaryAttackInfo() in GetTpmStatus(), "
                  "error status "
               << static_cast<int>(da_reply.status());
  }

  user_data_auth::InstallAttributesGetStatusRequest request;
  install_attributes_proxy_->InstallAttributesGetStatusAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::
                     GetTpmStatusOnStageInstallAttributesDone,
                 base::Unretained(this), response, reply),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::GetTpmStatusOnStageInstallAttributesDone(
    std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>> response,
    BaseReply reply,
    const user_data_auth::InstallAttributesGetStatusReply& install_attr_reply) {
  if (install_attr_reply.error() != user_data_auth::CRYPTOHOME_ERROR_NOT_SET) {
    LOG(ERROR) << "GetTpmStatus() failed to call InstallAttributesGetStatus in "
                  "UserDataAuth, error status "
               << static_cast<int>(install_attr_reply.error());
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             DBUS_ERROR_FAILED,
                             "InstallAttributesGetStatus() failed");
    return;
  }

  GetTpmStatusReply* extension =
      reply.MutableExtension(cryptohome::GetTpmStatusReply::reply);

  extension->set_install_lockbox_finalized(
      extension->owned() && install_attr_reply.state() ==
                                user_data_auth::InstallAttributesState::VALID);

  // Set up the parameters for GetStatus() in attestationd.
  attestation::GetStatusRequest request;
  request.set_extended_status(true);

  attestation_proxy_->GetStatusAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::GetTpmStatusOnStageAttestationDone,
          base::Unretained(this), response, reply),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::GetTpmStatusOnStageAttestationDone(
    std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>> response,
    BaseReply reply,
    const attestation::GetStatusReply& attestation_reply) {
  GetTpmStatusReply* extension =
      reply.MutableExtension(cryptohome::GetTpmStatusReply::reply);

  extension->set_boot_lockbox_finalized(false);
  extension->set_is_locked_to_single_user(platform_->FileExists(
      base::FilePath(cryptohome::kLockedToSingleUserFile)));

  if (attestation_reply.status() ==
      attestation::AttestationStatus::STATUS_SUCCESS) {
    extension->set_attestation_prepared(
        attestation_reply.prepared_for_enrollment());
    extension->set_attestation_enrolled(attestation_reply.enrolled());
    extension->set_verified_boot_measured(attestation_reply.verified_boot());
    for (auto it = attestation_reply.identities().cbegin(),
              end = attestation_reply.identities().cend();
         it != end; ++it) {
      auto* identity = extension->mutable_identities()->Add();
      identity->set_features(it->features());
    }
    for (auto it = attestation_reply.identity_certificates().cbegin(),
              end = attestation_reply.identity_certificates().cend();
         it != end; ++it) {
      GetTpmStatusReply::IdentityCertificate identity_certificate;
      identity_certificate.set_identity(it->second.identity());
      identity_certificate.set_aca(it->second.aca());
      extension->mutable_identity_certificates()->insert(
          google::protobuf::Map<int, GetTpmStatusReply::IdentityCertificate>::
              value_type(it->first, identity_certificate));
    }
  } else {
    LOG(ERROR) << "Failed to call GetStatus() in attestation during "
                  "GetTpmStatus(), error status "
               << static_cast<int>(attestation_reply.status());

    extension->set_attestation_prepared(false);
    extension->set_attestation_enrolled(false);
    extension->set_verified_boot_measured(false);
  }

  ClearErrorIfNotSet(&reply);
  response->Return(reply);
}

void LegacyCryptohomeInterfaceAdaptor::GetEndorsementInfo(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::GetEndorsementInfoRequest& in_request) {
  std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>>
      response_shared(new SharedDBusMethodResponse<cryptohome::BaseReply>(
          std::move(response)));

  attestation::GetEndorsementInfoRequest request;

  attestation_proxy_->GetEndorsementInfoAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::GetEndorsementInfoOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kAttestationProxyTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::GetEndorsementInfoOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>> response,
    const attestation::GetEndorsementInfoReply& reply) {
  cryptohome::BaseReply result;
  if (reply.status() != attestation::AttestationStatus::STATUS_SUCCESS) {
    LOG(WARNING) << "GetEndorsementInfo(): Attestation daemon returned status "
                 << static_cast<int>(reply.status());
    result.set_error(cryptohome::CRYPTOHOME_ERROR_TPM_EK_NOT_AVAILABLE);
  } else {
    GetEndorsementInfoReply* extension =
        result.MutableExtension(cryptohome::GetEndorsementInfoReply::reply);
    extension->set_ek_public_key(reply.ek_public_key());
    if (!reply.ek_certificate().empty()) {
      extension->set_ek_certificate(reply.ek_certificate());
    }
  }
  ClearErrorIfNotSet(&result);
  response->Return(result);
}

void LegacyCryptohomeInterfaceAdaptor::InitializeCastKey(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::InitializeCastKeyRequest& in_request) {
  // InitializeCastKey() is no longer available.
  response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                           DBUS_ERROR_NOT_SUPPORTED,
                           "Obsolete method InitializeCastKey() called");
}

void LegacyCryptohomeInterfaceAdaptor::StartFingerprintAuthSession(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::AccountIdentifier& in_account_id,
    const cryptohome::StartFingerprintAuthSessionRequest& in_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::StartFingerprintAuthSessionRequest request;
  request.mutable_account_id()->CopyFrom(in_account_id);
  userdataauth_proxy_->StartFingerprintAuthSessionAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardBaseReplyErrorCode<
                     user_data_auth::StartFingerprintAuthSessionReply>,
                 response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::EndFingerprintAuthSession(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::EndFingerprintAuthSessionRequest& in_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::EndFingerprintAuthSessionRequest request;
  userdataauth_proxy_->EndFingerprintAuthSessionAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardBaseReplyErrorCode<
                     user_data_auth::EndFingerprintAuthSessionReply>,
                 response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::GetWebAuthnSecret(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::AccountIdentifier& in_account_id,
    const cryptohome::GetWebAuthnSecretRequest& in_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::GetWebAuthnSecretRequest request;
  request.mutable_account_id()->CopyFrom(in_account_id);
  userdataauth_proxy_->GetWebAuthnSecretAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::GetWebAuthnSecretOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared));
}

void LegacyCryptohomeInterfaceAdaptor::GetWebAuthnSecretOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>> response,
    const user_data_auth::GetWebAuthnSecretReply& reply) {
  cryptohome::BaseReply result;
  result.set_error(static_cast<cryptohome::CryptohomeErrorCode>(reply.error()));
  cryptohome::GetWebAuthnSecretReply* result_extension =
      result.MutableExtension(cryptohome::GetWebAuthnSecretReply::reply);
  if (result.error() == CRYPTOHOME_ERROR_NOT_SET) {
    result_extension->set_webauthn_secret(reply.webauthn_secret());
  }
  ClearErrorIfNotSet(&result);
  response->Return(result);
}

void LegacyCryptohomeInterfaceAdaptor::GetFirmwareManagementParameters(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::GetFirmwareManagementParametersRequest& in_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::GetFirmwareManagementParametersRequest request;
  install_attributes_proxy_->GetFirmwareManagementParametersAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::
                     GetFirmwareManagementParametersOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::GetFirmwareManagementParametersOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>> response,
    const user_data_auth::GetFirmwareManagementParametersReply& reply) {
  cryptohome::BaseReply result;
  result.set_error(static_cast<cryptohome::CryptohomeErrorCode>(reply.error()));
  cryptohome::GetFirmwareManagementParametersReply* result_extension =
      result.MutableExtension(
          cryptohome::GetFirmwareManagementParametersReply::reply);
  result_extension->set_flags(reply.fwmp().flags());
  *result_extension->mutable_developer_key_hash() =
      reply.fwmp().developer_key_hash();
  ClearErrorIfNotSet(&result);
  response->Return(result);
}

void LegacyCryptohomeInterfaceAdaptor::SetFirmwareManagementParameters(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::SetFirmwareManagementParametersRequest& in_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::SetFirmwareManagementParametersRequest request;
  request.mutable_fwmp()->set_flags(in_request.flags());
  *request.mutable_fwmp()->mutable_developer_key_hash() =
      in_request.developer_key_hash();
  install_attributes_proxy_->SetFirmwareManagementParametersAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardBaseReplyErrorCode<
                     user_data_auth::SetFirmwareManagementParametersReply>,
                 response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::RemoveFirmwareManagementParameters(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::RemoveFirmwareManagementParametersRequest& in_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::RemoveFirmwareManagementParametersRequest request;
  install_attributes_proxy_->RemoveFirmwareManagementParametersAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardBaseReplyErrorCode<
                     user_data_auth::RemoveFirmwareManagementParametersReply>,
                 response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::MigrateToDircrypto(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>> response,
    const cryptohome::AccountIdentifier& in_account_id,
    const cryptohome::MigrateToDircryptoRequest& in_migrate_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<>>(std::move(response));

  user_data_auth::StartMigrateToDircryptoRequest request;
  *request.mutable_account_id() = in_account_id;
  request.set_minimal_migration(in_migrate_request.minimal_migration());
  userdataauth_proxy_->StartMigrateToDircryptoAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::MigrateToDircryptoOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::MigrateToDircryptoOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<>> response,
    const user_data_auth::StartMigrateToDircryptoReply& reply) {
  if (reply.error() != user_data_auth::CRYPTOHOME_ERROR_NOT_SET) {
    LOG(WARNING) << "StartMigrateToDircryptoAsync() failed with error code "
                 << static_cast<int>(reply.error());
  }
  response->Return();
}

void LegacyCryptohomeInterfaceAdaptor::NeedsDircryptoMigration(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response,
    const cryptohome::AccountIdentifier& in_account_id) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<bool>>(std::move(response));

  user_data_auth::NeedsDircryptoMigrationRequest request;
  *request.mutable_account_id() = in_account_id;
  userdataauth_proxy_->NeedsDircryptoMigrationAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::NeedsDircryptoMigrationOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::NeedsDircryptoMigrationOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const user_data_auth::NeedsDircryptoMigrationReply& reply) {
  if (reply.error() != user_data_auth::CRYPTOHOME_ERROR_NOT_SET) {
    // There's an error, we should return an error.
    LOG(ERROR) << "NeedsDircryptoMigration returned "
               << static_cast<int>(reply.error());
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             DBUS_ERROR_FAILED,
                             "An error occurred on the UserDataAuth side when "
                             "proxying NeedsDircryptoMigration.");
    return;
  }
  response->Return(reply.needs_dircrypto_migration());
}

void LegacyCryptohomeInterfaceAdaptor::GetSupportedKeyPolicies(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::GetSupportedKeyPoliciesRequest& in_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::GetSupportedKeyPoliciesRequest request;
  userdataauth_proxy_->GetSupportedKeyPoliciesAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::GetSupportedKeyPoliciesOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::GetSupportedKeyPoliciesOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>> response,
    const user_data_auth::GetSupportedKeyPoliciesReply& reply) {
  cryptohome::BaseReply base_reply;
  cryptohome::GetSupportedKeyPoliciesReply* extension =
      base_reply.MutableExtension(
          cryptohome::GetSupportedKeyPoliciesReply::reply);

  extension->set_low_entropy_credentials(
      reply.low_entropy_credentials_supported());
  ClearErrorIfNotSet(&base_reply);
  response->Return(base_reply);
}

void LegacyCryptohomeInterfaceAdaptor::IsQuotaSupported(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<bool>>(std::move(response));

  user_data_auth::GetArcDiskFeaturesRequest request;
  arc_quota_proxy_->GetArcDiskFeaturesAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::IsQuotaSupportedOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::IsQuotaSupportedOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const user_data_auth::GetArcDiskFeaturesReply& reply) {
  response->Return(reply.quota_supported());
}

void LegacyCryptohomeInterfaceAdaptor::GetCurrentSpaceForUid(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<int64_t>> response,
    uint32_t in_uid) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<int64_t>>(std::move(response));

  user_data_auth::GetCurrentSpaceForArcUidRequest request;
  request.set_uid(in_uid);
  arc_quota_proxy_->GetCurrentSpaceForArcUidAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::GetCurrentSpaceForUidOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<int64_t>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::GetCurrentSpaceForUidOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<int64_t>> response,
    const user_data_auth::GetCurrentSpaceForArcUidReply& reply) {
  response->Return(reply.cur_space());
}

void LegacyCryptohomeInterfaceAdaptor::GetCurrentSpaceForGid(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<int64_t>> response,
    uint32_t in_gid) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<int64_t>>(std::move(response));

  user_data_auth::GetCurrentSpaceForArcGidRequest request;
  request.set_gid(in_gid);
  arc_quota_proxy_->GetCurrentSpaceForArcGidAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::GetCurrentSpaceForGidOnSuccess,
          base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<int64_t>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::GetCurrentSpaceForGidOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<int64_t>> response,
    const user_data_auth::GetCurrentSpaceForArcGidReply& reply) {
  response->Return(reply.cur_space());
}

void LegacyCryptohomeInterfaceAdaptor::GetCurrentSpaceForProjectId(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<int64_t>> response,
    uint32_t in_project_id) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<int64_t>>(std::move(response));

  user_data_auth::GetCurrentSpaceForArcProjectIdRequest request;
  request.set_project_id(in_project_id);
  arc_quota_proxy_->GetCurrentSpaceForArcProjectIdAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::
                     GetCurrentSpaceForProjectIdOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<int64_t>,
                 base::Unretained(this), response_shared));
}

void LegacyCryptohomeInterfaceAdaptor::GetCurrentSpaceForProjectIdOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<int64_t>> response,
    const user_data_auth::GetCurrentSpaceForArcProjectIdReply& reply) {
  response->Return(reply.cur_space());
}

void LegacyCryptohomeInterfaceAdaptor::SetProjectId(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response,
    uint32_t in_project_id,
    int32_t in_parent_path,
    const std::string& in_child_path,
    const cryptohome::AccountIdentifier& in_account_id) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<bool>>(std::move(response));

  user_data_auth::SetProjectIdRequest request;
  request.set_project_id(in_project_id);
  request.set_parent_path(
      static_cast<user_data_auth::SetProjectIdAllowedPathType>(in_parent_path));
  request.set_child_path(in_child_path);
  request.mutable_account_id()->CopyFrom(in_account_id);
  arc_quota_proxy_->SetProjectIdAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::SetProjectIdOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<bool>,
                 base::Unretained(this), response_shared));
}

void LegacyCryptohomeInterfaceAdaptor::SetProjectIdOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<bool>> response,
    const user_data_auth::SetProjectIdReply& reply) {
  response->Return(reply.success());
}

void LegacyCryptohomeInterfaceAdaptor::LockToSingleUserMountUntilReboot(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::LockToSingleUserMountUntilRebootRequest& in_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::LockToSingleUserMountUntilRebootRequest request;
  if (in_request.has_account_id()) {
    *request.mutable_account_id() = in_request.account_id();
  }
  misc_proxy_->LockToSingleUserMountUntilRebootAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::
                     LockToSingleUserMountUntilRebootOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::
    LockToSingleUserMountUntilRebootOnSuccess(
        std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>>
            response,
        const user_data_auth::LockToSingleUserMountUntilRebootReply& reply) {
  cryptohome::BaseReply result;
  cryptohome::LockToSingleUserMountUntilRebootReply* result_extension =
      result.MutableExtension(
          cryptohome::LockToSingleUserMountUntilRebootReply::reply);
  if (reply.error() == user_data_auth::CRYPTOHOME_ERROR_FAILED_TO_READ_PCR) {
    result_extension->set_result(cryptohome::FAILED_TO_READ_PCR);
    result.set_error(cryptohome::CRYPTOHOME_ERROR_TPM_COMM_ERROR);
  } else if (reply.error() ==
             user_data_auth::CRYPTOHOME_ERROR_PCR_ALREADY_EXTENDED) {
    result_extension->set_result(cryptohome::PCR_ALREADY_EXTENDED);
  } else if (reply.error() ==
             user_data_auth::CRYPTOHOME_ERROR_FAILED_TO_EXTEND_PCR) {
    result_extension->set_result(cryptohome::FAILED_TO_EXTEND_PCR);
    result.set_error(cryptohome::CRYPTOHOME_ERROR_TPM_COMM_ERROR);
  } else if (reply.error() == user_data_auth::CRYPTOHOME_ERROR_NOT_SET) {
    result_extension->set_result(cryptohome::SUCCESS);
  } else {
    LOG(DFATAL) << "Invalid error code returned by "
                   "LockToSingleUserMountUntilReboot() in UserDataAuth";
    result.ClearExtension(
        cryptohome::LockToSingleUserMountUntilRebootReply::reply);
  }
  ClearErrorIfNotSet(&result);
  response->Return(result);
}

void LegacyCryptohomeInterfaceAdaptor::GetRsuDeviceId(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::GetRsuDeviceIdRequest& in_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::GetRsuDeviceIdRequest request;
  misc_proxy_->GetRsuDeviceIdAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::GetRsuDeviceIdOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::GetRsuDeviceIdOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>> response,
    const user_data_auth::GetRsuDeviceIdReply& reply) {
  cryptohome::BaseReply result;
  result.set_error(static_cast<cryptohome::CryptohomeErrorCode>(reply.error()));
  if (reply.error() == user_data_auth::CRYPTOHOME_ERROR_NOT_SET) {
    cryptohome::GetRsuDeviceIdReply* result_extension =
        result.MutableExtension(cryptohome::GetRsuDeviceIdReply::reply);
    *result_extension->mutable_rsu_device_id() = reply.rsu_device_id();
  }
  ClearErrorIfNotSet(&result);
  response->Return(result);
}

void LegacyCryptohomeInterfaceAdaptor::CheckHealth(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::CheckHealthRequest& in_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::CheckHealthRequest request;
  misc_proxy_->CheckHealthAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::CheckHealthOnSuccess,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::CheckHealthOnSuccess(
    std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>> response,
    const user_data_auth::CheckHealthReply& reply) {
  cryptohome::BaseReply result;
  CheckHealthReply* reply_extension =
      result.MutableExtension(CheckHealthReply::reply);
  reply_extension->set_requires_powerwash(reply.requires_powerwash());
  response->Return(result);
}

void LegacyCryptohomeInterfaceAdaptor::OnDircryptoMigrationProgressSignal(
    const user_data_auth::DircryptoMigrationProgress& progress) {
  VirtualSendDircryptoMigrationProgressSignal(
      dircrypto_data_migrator::MigrationHelper::ConvertDircryptoMigrationStatus(
          progress.status()),
      progress.current_bytes(), progress.total_bytes());
}

void LegacyCryptohomeInterfaceAdaptor::OnLowDiskSpaceSignal(
    const user_data_auth::LowDiskSpace& payload) {
  VirtualSendLowDiskSpaceSignal(payload.disk_free_bytes());
}

void LegacyCryptohomeInterfaceAdaptor::OnOwnershipTakenSignal(
    const tpm_manager::OwnershipTakenSignal& /*payload*/) {
  // Since the ownership taken signal is only sent when the ownership is taken,
  // it implies `is_ready` and `is_owned`. We also hardcode
  // `was_owned_this_boot` to be `false`; it's not used anymore so we don't
  // bother maintaining it in tpm manager.
  SendTpmInitStatusSignal(/*is_ready=*/true, /*is_owned=*/true,
                          /*was_owned_this_boot=*/false);
}

void LegacyCryptohomeInterfaceAdaptor::OnSignalConnectedHandler(
    const std::string& interface, const std::string& signal, bool success) {
  if (!success) {
    LOG(ERROR)
        << "Failure to connect DBus signal in cryptohome-proxy, interface="
        << interface << ", signal=" << signal;
  }
}

// A helper function which maps an integer to a valid CertificateProfile.
attestation::CertificateProfile
LegacyCryptohomeInterfaceAdaptor::IntegerToCertificateProfile(
    int profile_value) {
  // The protobuf compiler generates the _IsValid function.
  if (!attestation::CertificateProfile_IsValid(profile_value)) {
    return attestation::CertificateProfile::ENTERPRISE_USER_CERTIFICATE;
  }
  return static_cast<attestation::CertificateProfile>(profile_value);
}

// A helper function which maps an integer to a valid ACAType.
base::Optional<attestation::ACAType>
LegacyCryptohomeInterfaceAdaptor::IntegerToACAType(int type) {
  if (!attestation::ACAType_IsValid(type)) {
    return base::nullopt;
  }
  return static_cast<attestation::ACAType>(type);
}

// A helper function which maps an integer to a valid VAType.
base::Optional<attestation::VAType>
LegacyCryptohomeInterfaceAdaptor::IntegerToVAType(int type) {
  if (!attestation::VAType_IsValid(type)) {
    return base::nullopt;
  }
  return static_cast<attestation::VAType>(type);
}

void LegacyCryptohomeInterfaceAdaptor::ClearErrorIfNotSet(
    cryptohome::BaseReply* reply) {
  if (reply->has_error() &&
      reply->error() == cryptohome::CRYPTOHOME_ERROR_NOT_SET) {
    reply->clear_error();
  }
}

void LegacyCryptohomeInterfaceAdaptor::StartAuthSession(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::AccountIdentifier& in_account_id,
    const cryptohome::StartAuthSessionRequest& in_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::StartAuthSessionRequest request;
  request.mutable_account_id()->CopyFrom(in_account_id);
  request.set_flags(in_request.flags());
  userdataauth_proxy_->StartAuthSessionAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::StartAuthSessionOnStarted,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::StartAuthSessionOnStarted(
    std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>> response,
    const user_data_auth::StartAuthSessionReply& reply) {
  cryptohome::BaseReply result;
  result.set_error(static_cast<cryptohome::CryptohomeErrorCode>(reply.error()));
  cryptohome::StartAuthSessionReply* result_extension =
      result.MutableExtension(cryptohome::StartAuthSessionReply::reply);
  result_extension->set_auth_session_id(reply.auth_session_id());
  ClearErrorIfNotSet(&result);
  response->Return(result);
}

void LegacyCryptohomeInterfaceAdaptor::AddCredentials(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::AddCredentialsRequest& in_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::AddCredentialsRequest request;
  request.set_auth_session_id(in_request.auth_session_id());
  request.mutable_authorization()->CopyFrom(in_request.authorization());
  userdataauth_proxy_->AddCredentialsAsync(
      request,
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::AddCredentialsOnDone,
                 base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::AddCredentialsOnDone(
    std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>> response,
    const user_data_auth::AddCredentialsReply& reply) {
  cryptohome::BaseReply result;
  result.set_error(static_cast<cryptohome::CryptohomeErrorCode>(reply.error()));
  ClearErrorIfNotSet(&result);
  response->Return(result);
}

void LegacyCryptohomeInterfaceAdaptor::AuthenticateAuthSession(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<cryptohome::BaseReply>> response,
    const cryptohome::AuthenticateAuthSessionRequest& in_request) {
  auto response_shared =
      std::make_shared<SharedDBusMethodResponse<cryptohome::BaseReply>>(
          std::move(response));

  user_data_auth::AuthenticateAuthSessionRequest request;
  request.set_auth_session_id(in_request.auth_session_id());
  request.mutable_authorization()->CopyFrom(in_request.authorization());
  userdataauth_proxy_->AuthenticateAuthSessionAsync(
      request,
      base::Bind(
          &LegacyCryptohomeInterfaceAdaptor::AuthenticateAuthSessionOnDone,
          base::Unretained(this), response_shared),
      base::Bind(&LegacyCryptohomeInterfaceAdaptor::ForwardError<
                     cryptohome::BaseReply>,
                 base::Unretained(this), response_shared),
      kDefaultTimeout.InMilliseconds());
}

void LegacyCryptohomeInterfaceAdaptor::AuthenticateAuthSessionOnDone(
    std::shared_ptr<SharedDBusMethodResponse<cryptohome::BaseReply>> response,
    const user_data_auth::AuthenticateAuthSessionReply& reply) {
  cryptohome::BaseReply result;
  result.set_error(static_cast<cryptohome::CryptohomeErrorCode>(reply.error()));
  cryptohome::AuthenticateAuthSessionReply* result_extension =
      result.MutableExtension(cryptohome::AuthenticateAuthSessionReply::reply);
  result_extension->set_authenticated(reply.authenticated());
  ClearErrorIfNotSet(&result);
  response->Return(result);
}

}  // namespace cryptohome
