// Copyright 2021 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/auth_blocks/async_challenge_credential_auth_block.h"

#include <memory>
#include <utility>
#include <variant>

#include <base/check.h>
#include <base/logging.h>
#include <base/notreached.h>

#include "cryptohome/auth_blocks/auth_block_state.h"
#include "cryptohome/auth_blocks/libscrypt_compat_auth_block.h"
#include "cryptohome/challenge_credentials/challenge_credentials_helper_impl.h"
#include "cryptohome/cryptohome_metrics.h"
#include "cryptohome/error/location_utils.h"
#include "cryptohome/key_objects.h"

using cryptohome::error::CryptohomeCryptoError;
using cryptohome::error::ErrorAction;
using cryptohome::error::ErrorActionSet;
using hwsec_foundation::status::MakeStatus;
using hwsec_foundation::status::OkStatus;
using hwsec_foundation::status::StatusChain;

namespace cryptohome {

AsyncChallengeCredentialAuthBlock::AsyncChallengeCredentialAuthBlock(
    Tpm* tpm,
    ChallengeCredentialsHelper* challenge_credentials_helper,
    std::unique_ptr<KeyChallengeService> key_challenge_service,
    const std::string& account_id)
    : AuthBlock(kSignatureChallengeProtected),
      tpm_(tpm),
      challenge_credentials_helper_(challenge_credentials_helper),
      key_challenge_service_(std::move(key_challenge_service)),
      account_id_(account_id) {
  CHECK(tpm_);
  CHECK(challenge_credentials_helper_);
  CHECK(key_challenge_service_);
}

void AsyncChallengeCredentialAuthBlock::Create(const AuthInput& auth_input,
                                               CreateCallback callback) {
  if (!key_challenge_service_) {
    LOG(ERROR) << __func__ << ": No valid key challenge service.";
    std::move(callback).Run(
        MakeStatus<CryptohomeCryptoError>(
            CRYPTOHOME_ERR_LOC(kLocAsyncChalCredAuthBlockNoKeyServiceInCreate),
            ErrorActionSet({ErrorAction::kDevCheckUnexpectedState}),
            CryptoError::CE_OTHER_CRYPTO),
        nullptr, nullptr);
    return;
  }

  if (!auth_input.obfuscated_username.has_value()) {
    LOG(ERROR) << __func__ << ": No valid obfuscated username.";
    std::move(callback).Run(
        MakeStatus<CryptohomeCryptoError>(
            CRYPTOHOME_ERR_LOC(kLocAsyncChalCredAuthBlockNoInputUserInCreate),
            ErrorActionSet({ErrorAction::kDevCheckUnexpectedState}),
            CryptoError::CE_OTHER_CRYPTO),
        nullptr, nullptr);
    return;
  }

  if (!auth_input.challenge_credential_auth_input.has_value()) {
    LOG(ERROR) << __func__ << ": No valid challenge credential auth input.";
    std::move(callback).Run(
        MakeStatus<CryptohomeCryptoError>(
            CRYPTOHOME_ERR_LOC(kLocAsyncChalCredAuthBlockNoInputAuthInCreate),
            ErrorActionSet(
                {ErrorAction::kDevCheckUnexpectedState, ErrorAction::kAuth}),
            CryptoError::CE_OTHER_CRYPTO),
        nullptr, nullptr);
    return;
  }

  if (auth_input.challenge_credential_auth_input.value()
          .challenge_signature_algorithms.empty()) {
    LOG(ERROR) << __func__ << ": No valid challenge signature algorithms.";
    std::move(callback).Run(
        MakeStatus<CryptohomeCryptoError>(
            CRYPTOHOME_ERR_LOC(kLocAsyncChalCredAuthBlockNoInputAlgInCreate),
            ErrorActionSet(
                {ErrorAction::kDevCheckUnexpectedState, ErrorAction::kAuth}),
            CryptoError::CE_OTHER_CRYPTO),
        nullptr, nullptr);
    return;
  }

  structure::ChallengePublicKeyInfo public_key_info{
      .public_key_spki_der = auth_input.challenge_credential_auth_input.value()
                                 .public_key_spki_der,
      .signature_algorithm = auth_input.challenge_credential_auth_input.value()
                                 .challenge_signature_algorithms,
  };

  const std::string& obfuscated_username =
      auth_input.obfuscated_username.value();

  challenge_credentials_helper_->GenerateNew(
      std::move(account_id_), std::move(public_key_info), obfuscated_username,
      std::move(key_challenge_service_),
      base::BindOnce(&AsyncChallengeCredentialAuthBlock::CreateContinue,
                     weak_factory_.GetWeakPtr(), std::move(callback)));
}

void AsyncChallengeCredentialAuthBlock::CreateContinue(
    CreateCallback callback,
    std::unique_ptr<structure::SignatureChallengeInfo> signature_challenge_info,
    std::unique_ptr<brillo::SecureBlob> passkey) {
  if (!passkey) {
    // TODO(b/229569484): Make ChallengeCredentialHelper pass the error in.
    LOG(ERROR) << __func__ << ": Failed to obtain challenge-response passkey.";
    std::move(callback).Run(
        MakeStatus<CryptohomeCryptoError>(
            CRYPTOHOME_ERR_LOC(
                kLocAsyncChalCredAuthBlockServiceGenerateFailedInCreate),
            ErrorActionSet({ErrorAction::kRetry, ErrorAction::kAuth,
                            ErrorAction::kReboot}),
            CryptoError::CE_OTHER_CRYPTO),
        nullptr, nullptr);
    return;
  }

  // We only need passkey for the AuthInput.
  AuthInput auth_input = {.user_input = std::move(*passkey)};

  auto key_blobs = std::make_unique<KeyBlobs>();
  auto scrypt_auth_state = std::make_unique<AuthBlockState>();

  LibScryptCompatAuthBlock scrypt_auth_block;
  CryptoStatus error = scrypt_auth_block.Create(
      auth_input, scrypt_auth_state.get(), key_blobs.get());

  if (!error.ok()) {
    LOG(ERROR) << __func__
               << "scrypt creation failed for challenge credential.";
    std::move(callback).Run(
        MakeStatus<CryptohomeCryptoError>(
            CRYPTOHOME_ERR_LOC(
                kLocAsyncChalCredAuthBlockCannotCreateScryptInCreate))
            .Wrap(std::move(error)),
        nullptr, nullptr);
    return;
  }

  if (auto* scrypt_state = std::get_if<LibScryptCompatAuthBlockState>(
          &scrypt_auth_state->state)) {
    ChallengeCredentialAuthBlockState cc_state = {
        .scrypt_state = std::move(*scrypt_state),
        .keyset_challenge_info = std::move(*signature_challenge_info),
    };

    auto auth_block_state = std::make_unique<AuthBlockState>(
        AuthBlockState{.state = std::move(cc_state)});

    std::move(callback).Run(OkStatus<CryptohomeCryptoError>(),
                            std::move(key_blobs), std::move(auth_block_state));
  } else {
    // This should never happen, but handling it anyway on the safe side.
    NOTREACHED() << "scrypt derivation failed for challenge credential.";
    std::move(callback).Run(
        MakeStatus<CryptohomeCryptoError>(
            CRYPTOHOME_ERR_LOC(
                kLocAsyncChalCredAuthBlockScryptDerivationFailedInCreate),
            ErrorActionSet({ErrorAction::kDevCheckUnexpectedState}),
            CryptoError::CE_OTHER_CRYPTO),
        nullptr, nullptr);
  }
}

void AsyncChallengeCredentialAuthBlock::Derive(const AuthInput& auth_input,
                                               const AuthBlockState& state,
                                               DeriveCallback callback) {
  if (!key_challenge_service_) {
    LOG(ERROR) << __func__ << ": No valid key challenge service.";
    std::move(callback).Run(
        MakeStatus<CryptohomeCryptoError>(
            CRYPTOHOME_ERR_LOC(kLocAsyncChalCredAuthBlockNoKeyServiceInDerive),
            ErrorActionSet({ErrorAction::kDevCheckUnexpectedState}),
            CryptoError::CE_OTHER_CRYPTO),
        nullptr);
    return;
  }

  const ChallengeCredentialAuthBlockState* cc_state =
      std::get_if<ChallengeCredentialAuthBlockState>(&state.state);
  if (cc_state == nullptr) {
    LOG(ERROR) << __func__
               << "Invalid state for challenge credential AuthBlock.";
    std::move(callback).Run(
        MakeStatus<CryptohomeCryptoError>(
            CRYPTOHOME_ERR_LOC(
                kLocAsyncChalCredAuthBlockInvalidBlockStateInDerive),
            ErrorActionSet({ErrorAction::kDevCheckUnexpectedState}),
            CryptoError::CE_OTHER_FATAL),
        nullptr);
    return;
  }

  if (!cc_state->keyset_challenge_info.has_value()) {
    LOG(ERROR)
        << __func__
        << "No signature challenge info in challenge credential AuthBlock.";
    std::move(callback).Run(
        MakeStatus<CryptohomeCryptoError>(
            CRYPTOHOME_ERR_LOC(
                kLocAsyncChalCredAuthBlockNoChallengeInfoInDerive),
            ErrorActionSet({ErrorAction::kDevCheckUnexpectedState}),
            CryptoError::CE_OTHER_CRYPTO),
        nullptr);
    return;
  }

  const structure::SignatureChallengeInfo& keyset_challenge_info =
      cc_state->keyset_challenge_info.value();
  if (!keyset_challenge_info.salt_signature_algorithm.has_value()) {
    LOG(ERROR)
        << __func__
        << "No signature algorithm info in challenge credential AuthBlock.";
    std::move(callback).Run(
        MakeStatus<CryptohomeCryptoError>(
            CRYPTOHOME_ERR_LOC(
                kLocAsyncChalCredAuthBlockNoAlgorithmInfoInDerive),
            ErrorActionSet({ErrorAction::kDevCheckUnexpectedState}),
            CryptoError::CE_OTHER_CRYPTO),
        nullptr);
    return;
  }

  structure::ChallengePublicKeyInfo public_key_info{
      .public_key_spki_der = keyset_challenge_info.public_key_spki_der,
      .signature_algorithm =
          {keyset_challenge_info.salt_signature_algorithm.value()},
  };

  AuthBlockState scrypt_state = {.state = cc_state->scrypt_state};

  challenge_credentials_helper_->Decrypt(
      std::move(account_id_), std::move(public_key_info),
      cc_state->keyset_challenge_info.value(),
      auth_input.locked_to_single_user.value_or(false),
      std::move(key_challenge_service_),
      base::BindOnce(&AsyncChallengeCredentialAuthBlock::DeriveContinue,
                     weak_factory_.GetWeakPtr(), std::move(callback),
                     std::move(scrypt_state)));
  return;
}

void AsyncChallengeCredentialAuthBlock::DeriveContinue(
    DeriveCallback callback,
    const AuthBlockState& scrypt_state,
    std::unique_ptr<brillo::SecureBlob> passkey) {
  if (!passkey) {
    LOG(ERROR) << __func__ << ": Failed to obtain challenge-response passkey.";
    std::move(callback).Run(
        MakeStatus<CryptohomeCryptoError>(
            CRYPTOHOME_ERR_LOC(
                kLocAsyncChalCredAuthBlockServiceDeriveFailedInDerive),
            ErrorActionSet({ErrorAction::kRetry, ErrorAction::kAuth,
                            ErrorAction::kReboot, ErrorAction::kIncorrectAuth}),
            CryptoError::CE_OTHER_CRYPTO),
        nullptr);
    return;
  }

  // We only need passkey for the LibScryptCompatAuthBlock AuthInput.
  AuthInput auth_input = {.user_input = std::move(*passkey)};

  LibScryptCompatAuthBlock scrypt_auth_block;
  auto key_blobs = std::make_unique<KeyBlobs>();
  CryptoStatus error =
      scrypt_auth_block.Derive(auth_input, scrypt_state, key_blobs.get());

  if (!error.ok()) {
    LOG(ERROR) << __func__
               << "scrypt derivation failed for challenge credential.";
    std::move(callback).Run(
        MakeStatus<CryptohomeCryptoError>(
            CRYPTOHOME_ERR_LOC(
                kLocAsyncChalCredAuthBlockScryptDeriveFailedInDerive))
            .Wrap(std::move(error)),
        nullptr);
    return;
  }

  std::move(callback).Run(OkStatus<CryptohomeCryptoError>(),
                          std::move(key_blobs));
  return;
}

}  // namespace cryptohome
