// Copyright 2022 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 "cryptohome/error/cryptohome_tpm_error.h"

#include <memory>
#include <optional>
#include <set>
#include <string>
#include <utility>

#include <cryptohome/proto_bindings/UserDataAuth.pb.h>
#include <libhwsec/error/tpm_retry_action.h>

#include "cryptohome/auth_blocks/tpm_auth_block_utils.h"

namespace cryptohome {

namespace error {

namespace {

using hwsec_foundation::status::NewStatus;
using hwsec_foundation::status::OkStatus;
using hwsec_foundation::status::StatusChain;

// PopulateActionFromRetry is a helper function that converts the libhwsec
// TPMRetryAction into CryptohomeError's Action.
void PopulateActionFromRetry(const hwsec::TPMRetryAction retry,
                             std::set<CryptohomeError::Action>* actions) {
  switch (retry) {
    case hwsec::TPMRetryAction::kCommunication:
    case hwsec::TPMRetryAction::kSession:
    case hwsec::TPMRetryAction::kReboot:
      actions->insert(ErrorAction::kReboot);
      break;
    case hwsec::TPMRetryAction::kLater:
      actions->insert(ErrorAction::kRetry);
      break;
    case hwsec::TPMRetryAction::kDefend:
      actions->insert(ErrorAction::kTpmLockout);
      break;
    case hwsec::TPMRetryAction::kUserAuth:
      actions->insert(ErrorAction::kAuth);
      break;
    case hwsec::TPMRetryAction::kNoRetry:
      actions->insert(ErrorAction::kDevCheckUnexpectedState);
      break;
    case hwsec::TPMRetryAction::kNone:
      // No action.
      break;
  }
}

// Converts a normal ErrorLocation into a Unified Error Code that this class'
// |loc_| expects.
CryptohomeError::ErrorLocationPair ErrorLocationToUnified(
    const CryptohomeError::ErrorLocationPair& loc) {
  DCHECK_EQ(loc.location() & (~hwsec::unified_tpm_error::kUnifiedErrorMask), 0);
  return CryptohomeError::ErrorLocationPair(
      loc.location() & hwsec::unified_tpm_error::kUnifiedErrorMask, loc.name());
}

StatusChain<CryptohomeTPMError> FromTPMErrorBase(
    StatusChain<hwsec::TPMErrorBase> status) {
  if (status.ok()) {
    return OkStatus<CryptohomeTPMError>();
  }

  // Status chain currently doesn't offer a way to get the last element of the
  // stack, so we'll need to iterate through it.
  hwsec::TPMErrorBase const* last;
  for (const auto& err : status.const_range()) {
    last = err;
  }

  // Populate the retry actions.
  std::set<CryptohomeError::Action> actual_actions;
  auto retry = last->ToTPMRetryAction();
  PopulateActionFromRetry(retry, &actual_actions);

  // Get the unified error code from the last node.
  CryptohomeError::ErrorLocation loc = last->UnifiedErrorCode();
  std::string loc_str = last->ToString();
  return NewStatus<CryptohomeTPMError>(
      CryptohomeError::ErrorLocationPair(loc, std::move(loc_str)),
      std::move(actual_actions), retry, std::move(status), std::nullopt);
}

}  // namespace

CryptohomeTPMError::CryptohomeTPMError(
    const ErrorLocationPair& loc,
    const std::set<CryptohomeError::Action>& actions,
    const hwsec::TPMRetryAction retry,
    std::optional<hwsec_foundation::status::StatusChain<hwsec::TPMErrorBase>>
        tpm_error,
    const std::optional<user_data_auth::CryptohomeErrorCode> ec)
    : CryptohomeCryptoError(
          loc, actions, TpmAuthBlockUtils::TPMRetryActionToCrypto(retry), ec),
      retry_(retry),
      tpm_error_(std::move(tpm_error)) {}

StatusChain<CryptohomeTPMError> CryptohomeTPMError::MakeStatusTrait::operator()(
    const ErrorLocationPair& loc,
    std::set<CryptohomeError::Action> actions,
    const hwsec::TPMRetryAction retry) {
  PopulateActionFromRetry(retry, &actions);
  auto unified = ErrorLocationToUnified(loc);
  return NewStatus<CryptohomeTPMError>(unified, std::move(actions), retry,
                                       std::nullopt, std::nullopt);
}

StatusChain<CryptohomeTPMError> CryptohomeTPMError::MakeStatusTrait::operator()(
    StatusChain<hwsec::TPMErrorBase> status) {
  return FromTPMErrorBase(std::move(status));
}

CryptohomeTPMError::MakeStatusTrait::Unactioned
CryptohomeTPMError::MakeStatusTrait::operator()(
    const ErrorLocationPair& loc,
    const std::set<CryptohomeError::Action>& actions) {
  return CryptohomeTPMError::MakeStatusTrait::Unactioned(loc,
                                                         std::move(actions));
}

CryptohomeTPMError::MakeStatusTrait::Unactioned
CryptohomeTPMError::MakeStatusTrait::operator()(const ErrorLocationPair& loc) {
  return CryptohomeTPMError::MakeStatusTrait::Unactioned(loc, NoErrorAction());
}

CryptohomeTPMError::MakeStatusTrait::Unactioned::Unactioned(
    const ErrorLocationPair& loc,
    const std::set<CryptohomeError::Action>& actions)
    : unified_loc_(ErrorLocationToUnified(loc)), actions_(std::move(actions)) {}

StatusChain<CryptohomeTPMError>
CryptohomeTPMError::MakeStatusTrait::Unactioned::Wrap(
    StatusChain<CryptohomeTPMError> status) && {
  DCHECK(!status.ok());
  return NewStatus<CryptohomeTPMError>(unified_loc_, std::move(actions_),
                                       status->ToTPMRetryAction(), std::nullopt,
                                       std::nullopt)
      .Wrap(std::move(status));
}

}  // namespace error

}  // namespace cryptohome
