// Copyright 2018 The Chromium 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 "device/fido/virtual_ctap2_device.h"

#include <array>
#include <string>
#include <utility>

#include "base/bind.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/cbor/cbor_writer.h"
#include "crypto/ec_private_key.h"
#include "device/fido/authenticator_get_assertion_response.h"
#include "device/fido/authenticator_make_credential_response.h"
#include "device/fido/ctap_get_assertion_request.h"
#include "device/fido/ctap_make_credential_request.h"
#include "device/fido/ec_public_key.h"
#include "device/fido/fido_constants.h"
#include "device/fido/fido_parsing_utils.h"
#include "device/fido/opaque_attestation_statement.h"

namespace device {

namespace {

constexpr std::array<uint8_t, kAaguidLength> kDeviceAaguid = {
    {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04,
     0x05, 0x06, 0x07, 0x08}};

std::vector<uint8_t> ConstructResponse(CtapDeviceResponseCode response_code,
                                       base::span<const uint8_t> data) {
  std::vector<uint8_t> response{base::strict_cast<uint8_t>(response_code)};
  fido_parsing_utils::Append(&response, data);
  return response;
}

void ReturnCtap2Response(
    FidoDevice::DeviceCallback cb,
    CtapDeviceResponseCode response_code,
    base::Optional<base::span<const uint8_t>> data = base::nullopt) {
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::BindOnce(std::move(cb),
                     ConstructResponse(response_code,
                                       data.value_or(std::vector<uint8_t>{}))));
}

bool AreMakeCredentialOptionsValid(const AuthenticatorSupportedOptions& options,
                                   const CtapMakeCredentialRequest& request) {
  if (request.resident_key_supported() && !options.supports_resident_key())
    return false;

  return !request.user_verification_required() ||
         options.user_verification_availability() ==
             AuthenticatorSupportedOptions::UserVerificationAvailability::
                 kSupportedAndConfigured;
}

bool AreGetAssertionOptionsValid(const AuthenticatorSupportedOptions& options,
                                 const CtapGetAssertionRequest& request) {
  if (request.user_presence_required() && !options.user_presence_required())
    return false;

  return request.user_verification() !=
             UserVerificationRequirement::kRequired ||
         options.user_verification_availability() ==
             AuthenticatorSupportedOptions::UserVerificationAvailability::
                 kSupportedAndConfigured;
}

// Checks that whether the received MakeCredential request includes EA256
// algorithm in publicKeyCredParam.
bool AreMakeCredentialParamsValid(const CtapMakeCredentialRequest& request) {
  const auto& params =
      request.public_key_credential_params().public_key_credential_params();
  return std::any_of(
      params.begin(), params.end(), [](const auto& credential_info) {
        return credential_info.algorithm ==
               base::strict_cast<int>(CoseAlgorithmIdentifier::kCoseEs256);
      });
}

std::unique_ptr<ECPublicKey> ConstructECPublicKey(
    std::string public_key_string) {
  DCHECK_EQ(64u, public_key_string.size());

  const auto public_key_x_coordinate =
      base::as_bytes(base::make_span(public_key_string)).first(32);
  const auto public_key_y_coordinate =
      base::as_bytes(base::make_span(public_key_string)).last(32);
  return std::make_unique<ECPublicKey>(
      fido_parsing_utils::kEs256,
      fido_parsing_utils::Materialize(public_key_x_coordinate),
      fido_parsing_utils::Materialize(public_key_y_coordinate));
}

std::vector<uint8_t> ConstructSignatureBuffer(
    const AuthenticatorData& authenticator_data,
    base::span<const uint8_t, kClientDataHashLength> client_data_hash) {
  std::vector<uint8_t> signature_buffer;
  fido_parsing_utils::Append(&signature_buffer,
                             authenticator_data.SerializeToByteArray());
  fido_parsing_utils::Append(&signature_buffer, client_data_hash);
  return signature_buffer;
}

std::vector<uint8_t> ConstructMakeCredentialResponse(
    base::span<const uint8_t> attestation_certificate,
    base::span<const uint8_t> signature,
    AuthenticatorData authenticator_data) {
  cbor::CBORValue::MapValue attestation_map;
  attestation_map.emplace("alg", -7);
  attestation_map.emplace("sig", fido_parsing_utils::Materialize(signature));

  cbor::CBORValue::ArrayValue certificate_chain;
  certificate_chain.emplace_back(
      fido_parsing_utils::Materialize(attestation_certificate));
  attestation_map.emplace("x5c", std::move(certificate_chain));
  AuthenticatorMakeCredentialResponse make_credential_response(
      AttestationObject(
          std::move(authenticator_data),
          std::make_unique<OpaqueAttestationStatement>(
              "packed", cbor::CBORValue(std::move(attestation_map)))));
  return GetSerializedCtapDeviceResponse(make_credential_response);
}

std::vector<uint8_t> ConstructGetAssertionResponse(
    AuthenticatorData authenticator_data,
    base::span<const uint8_t> signature,
    base::span<const uint8_t> key_handle) {
  AuthenticatorGetAssertionResponse response(
      std::move(authenticator_data),
      fido_parsing_utils::Materialize(signature));

  response.SetCredential({CredentialType::kPublicKey,
                          fido_parsing_utils::Materialize(key_handle)});
  response.SetNumCredentials(1);
  return GetSerializedCtapDeviceResponse(response);
}

}  // namespace

VirtualCtap2Device::VirtualCtap2Device()
    : VirtualFidoDevice(),
      device_info_(AuthenticatorGetInfoResponse({ProtocolVersion::kCtap},
                                                kDeviceAaguid)),
      weak_factory_(this) {}

VirtualCtap2Device::VirtualCtap2Device(scoped_refptr<State> state)
    : VirtualFidoDevice(std::move(state)),
      device_info_(AuthenticatorGetInfoResponse({ProtocolVersion::kCtap},
                                                kDeviceAaguid)),
      weak_factory_(this) {}

VirtualCtap2Device::~VirtualCtap2Device() = default;

// As all operations for VirtualCtap2Device are synchronous and we do not wait
// for user touch, Cancel command is no-op.
void VirtualCtap2Device::Cancel() {}

void VirtualCtap2Device::DeviceTransact(std::vector<uint8_t> command,
                                        DeviceCallback cb) {
  if (command.empty()) {
    ReturnCtap2Response(std::move(cb), CtapDeviceResponseCode::kCtap2ErrOther);
    return;
  }

  auto cmd_type = command[0];
  const auto request_bytes = base::make_span(command).subspan(1);
  CtapDeviceResponseCode response_code = CtapDeviceResponseCode::kCtap2ErrOther;
  std::vector<uint8_t> response_data;

  switch (static_cast<CtapRequestCommand>(cmd_type)) {
    case CtapRequestCommand::kAuthenticatorGetInfo:
      if (!request_bytes.empty()) {
        ReturnCtap2Response(std::move(cb),
                            CtapDeviceResponseCode::kCtap2ErrOther);
        return;
      }

      response_code = OnAuthenticatorGetInfo(&response_data);
      break;
    case CtapRequestCommand::kAuthenticatorMakeCredential:
      response_code = OnMakeCredential(request_bytes, &response_data);
      break;
    case CtapRequestCommand::kAuthenticatorGetAssertion:
      response_code = OnGetAssertion(request_bytes, &response_data);
      break;
    default:
      break;
  }

  // Call |callback| via the |MessageLoop| because |AuthenticatorImpl| doesn't
  // support callback hairpinning.
  ReturnCtap2Response(std::move(cb), response_code, std::move(response_data));
}

base::WeakPtr<FidoDevice> VirtualCtap2Device::GetWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

void VirtualCtap2Device::SetAuthenticatorSupportedOptions(
    AuthenticatorSupportedOptions options) {
  device_info_.SetOptions(std::move(options));
}

CtapDeviceResponseCode VirtualCtap2Device::OnMakeCredential(
    base::span<const uint8_t> request_bytes,
    std::vector<uint8_t>* response) {
  auto request = ParseCtapMakeCredentialRequest(request_bytes);
  if (!request) {
    DLOG(ERROR) << "Incorrectly formatted MakeCredential request.";
    return CtapDeviceResponseCode::kCtap2ErrOther;
  }

  if (!AreMakeCredentialOptionsValid(device_info_.options(), *request) ||
      !AreMakeCredentialParamsValid(*request)) {
    DLOG(ERROR) << "Virtual CTAP2 device does not support options required by "
                   "the request.";
    return CtapDeviceResponseCode::kCtap2ErrOther;
  }

  // Client pin is not supported.
  if (request->pin_auth()) {
    DLOG(ERROR) << "Virtual CTAP2 device does not support client pin.";
    return CtapDeviceResponseCode::kCtap2ErrPinInvalid;
  }

  // Check for already registered credentials.
  const auto rp_id_hash =
      fido_parsing_utils::CreateSHA256Hash(request->rp().rp_id());
  if (request->exclude_list()) {
    for (const auto& excluded_credential : *request->exclude_list()) {
      if (FindRegistrationData(excluded_credential.id(), rp_id_hash))
        return CtapDeviceResponseCode::kCtap2ErrCredentialExcluded;
    }
  }

  // Create key to register.
  // Note: Non-deterministic, you need to mock this out if you rely on
  // deterministic behavior.
  auto private_key = crypto::ECPrivateKey::Create();
  std::string public_key;
  bool status = private_key->ExportRawPublicKey(&public_key);
  DCHECK(status);

  // Our key handles are simple hashes of the public key.
  auto hash = fido_parsing_utils::CreateSHA256Hash(public_key);
  std::vector<uint8_t> key_handle(hash.begin(), hash.end());
  std::array<uint8_t, 2> sha256_length = {0, crypto::kSHA256Length};

  AttestedCredentialData attested_credential_data(
      kDeviceAaguid, sha256_length, key_handle,
      ConstructECPublicKey(public_key));

  auto authenticator_data = ConstructAuthenticatorData(
      rp_id_hash, 01ul, std::move(attested_credential_data));
  auto sign_buffer =
      ConstructSignatureBuffer(authenticator_data, request->client_data_hash());

  // Sign with attestation key.
  // Note: Non-deterministic, you need to mock this out if you rely on
  // deterministic behavior.
  std::vector<uint8_t> sig;
  std::unique_ptr<crypto::ECPrivateKey> attestation_private_key =
      crypto::ECPrivateKey::CreateFromPrivateKeyInfo(GetAttestationKey());
  status = Sign(attestation_private_key.get(), std::move(sign_buffer), &sig);
  DCHECK(status);

  auto attestation_cert = GenerateAttestationCertificate(
      false /* individual_attestation_requested */);
  if (!attestation_cert) {
    DLOG(ERROR) << "Failed to generate attestation certificate.";
    return CtapDeviceResponseCode::kCtap2ErrOther;
  }

  *response = ConstructMakeCredentialResponse(std::move(*attestation_cert), sig,
                                              std::move(authenticator_data));

  StoreNewKey(rp_id_hash, key_handle, std::move(private_key));
  return CtapDeviceResponseCode::kSuccess;
}

CtapDeviceResponseCode VirtualCtap2Device::OnGetAssertion(
    base::span<const uint8_t> request_bytes,
    std::vector<uint8_t>* response) {
  auto request = ParseCtapGetAssertionRequest(request_bytes);
  if (!request) {
    DLOG(ERROR) << "Incorrectly formatted GetAssertion request.";
    return CtapDeviceResponseCode::kCtap2ErrOther;
  }

  // Resident keys are not supported.
  if (!request->allow_list() || request->allow_list()->empty()) {
    DLOG(ERROR) << "Allowed credential list is empty, but Virtual CTAP2 device "
                   "does not support resident keys.";
    return CtapDeviceResponseCode::kCtap2ErrNoCredentials;
  }

  // Client pin option is not supported.
  if (request->pin_auth()) {
    DLOG(ERROR) << "Virtual CTAP2 device does not support client pin.";
    return CtapDeviceResponseCode::kCtap2ErrOther;
  }

  if (!AreGetAssertionOptionsValid(device_info_.options(), *request)) {
    DLOG(ERROR) << "Unsupported options required from the request.";
    return CtapDeviceResponseCode::kCtap2ErrOther;
  }

  const auto rp_id_hash =
      fido_parsing_utils::CreateSHA256Hash(request->rp_id());

  RegistrationData* found_data = nullptr;
  base::span<const uint8_t> credential_id;
  for (const auto& allowed_credential : *request->allow_list()) {
    if ((found_data =
             FindRegistrationData(allowed_credential.id(), rp_id_hash))) {
      credential_id = allowed_credential.id();
      break;
    }
  }

  if (!found_data)
    return CtapDeviceResponseCode::kCtap2ErrNoCredentials;

  found_data->counter++;
  auto authenticator_data =
      ConstructAuthenticatorData(rp_id_hash, found_data->counter);
  auto signature_buffer =
      ConstructSignatureBuffer(authenticator_data, request->client_data_hash());

  // Sign with the private key of the received key handle.
  std::vector<uint8_t> sig;
  auto* private_key = found_data->private_key.get();
  bool status = Sign(private_key, std::move(signature_buffer), &sig);
  DCHECK(status);

  *response = ConstructGetAssertionResponse(std::move(authenticator_data),
                                            std::move(sig), credential_id);
  return CtapDeviceResponseCode::kSuccess;
}

CtapDeviceResponseCode VirtualCtap2Device::OnAuthenticatorGetInfo(
    std::vector<uint8_t>* response) const {
  *response = EncodeToCBOR(device_info_);
  return CtapDeviceResponseCode::kSuccess;
}

AuthenticatorData VirtualCtap2Device::ConstructAuthenticatorData(
    base::span<const uint8_t, kRpIdHashLength> rp_id_hash,
    uint32_t current_signature_count,
    base::Optional<AttestedCredentialData> attested_credential_data) {
  uint8_t flag =
      base::strict_cast<uint8_t>(AuthenticatorData::Flag::kTestOfUserPresence);
  std::array<uint8_t, kSignCounterLength> signature_counter;

  // Constructing AuthenticatorData for registration operation.
  if (attested_credential_data)
    flag |= base::strict_cast<uint8_t>(AuthenticatorData::Flag::kAttestation);

  signature_counter[0] = (current_signature_count >> 24) & 0xff;
  signature_counter[1] = (current_signature_count >> 16) & 0xff;
  signature_counter[2] = (current_signature_count >> 8) & 0xff;
  signature_counter[3] = (current_signature_count)&0xff;

  return AuthenticatorData(rp_id_hash, flag, signature_counter,
                           std::move(attested_credential_data));
}

}  // namespace device
