// Copyright 2020 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/fido/authenticator_data.h"

#include <base/big_endian.h>
#include <base/strings/string_number_conversions.h>
#include <chromeos/cbor/diagnostic_writer.h>
#include <chromeos/cbor/reader.h>
#include <chromeos/cbor/writer.h>
#include <sstream>
#include <utility>

#include "cryptohome/fido/attested_credential_data.h"
#include "cryptohome/fido/fido_parsing_utils.h"
#include "cryptohome/fido/utils.h"

namespace cryptohome {
namespace fido_device {

namespace {

constexpr size_t kAttestedCredentialDataOffset =
    kRpIdHashLength + kFlagsLength + kSignCounterLength;
}  // namespace

// static
base::Optional<AuthenticatorData> AuthenticatorData::DecodeAuthenticatorData(
    base::span<const uint8_t> auth_data) {
  if (auth_data.size() < kAttestedCredentialDataOffset)
    return base::nullopt;
  auto application_parameter = auth_data.first<kRpIdHashLength>();
  uint8_t flag_byte = auth_data[kRpIdHashLength];
  auto counter =
      auth_data.subspan<kRpIdHashLength + kFlagsLength, kSignCounterLength>();

  auth_data = auth_data.subspan(kAttestedCredentialDataOffset);
  base::Optional<AttestedCredentialData> attested_credential_data;
  if (flag_byte & static_cast<uint8_t>(Flag::kAttestation)) {
    auto maybe_result =
        AttestedCredentialData::ConsumeFromCtapResponse(auth_data);
    if (!maybe_result) {
      return base::nullopt;
    }
    std::tie(attested_credential_data, auth_data) = std::move(*maybe_result);
  }

  base::Optional<cbor::Value> extensions;
  if (flag_byte & static_cast<uint8_t>(Flag::kExtensionDataIncluded)) {
    cbor::Reader::DecoderError error;
    extensions = cbor::Reader::Read(auth_data, &error);
    if (!extensions) {
      LOG(ERROR) << "CBOR decoding of authenticator data extensions failed ("
                 << cbor::Reader::ErrorCodeToString(error) << ") from "
                 << base::HexEncode(auth_data.data(), auth_data.size());
      return base::nullopt;
    }
    if (!extensions->is_map()) {
      LOG(ERROR) << "Incorrect CBOR structure of authenticator data extensions";
      return base::nullopt;
    }
  } else if (!auth_data.empty()) {
    return base::nullopt;
  }

  return AuthenticatorData(application_parameter, flag_byte, counter,
                           std::move(attested_credential_data),
                           std::move(extensions));
}

// static
base::Optional<AuthenticatorData>
AuthenticatorData::ParseMakeCredentialResponse(
    const std::vector<uint8_t>& input) {
  base::span<const uint8_t> buffer(input.data(), input.size());
  // The response is an attestation object.
  base::Optional<cbor::Value> attestation_obj = cbor::Reader::Read(buffer);
  if (!attestation_obj || !attestation_obj->is_map()) {
    LOG(ERROR) << "Attestation object is not a CBOR map.";
    return base::nullopt;
  }
  const auto& attestation_obj_map = attestation_obj->GetMap();

  // format
  auto it = attestation_obj_map.find(cbor::Value(kFormatKey));
  if (it == attestation_obj_map.end()) {
    LOG(ERROR) << "Missing format key.";
    return base::nullopt;
  }
  if (!it->second.is_string()) {
    LOG(ERROR) << "Invalid format.";
    return base::nullopt;
  }
  std::string format = it->second.GetString();

  // authenticator data
  it = attestation_obj_map.find(cbor::Value(kAuthDataKey));
  if (it == attestation_obj_map.end() || !it->second.is_bytestring()) {
    LOG(ERROR) << "Invalid AuthData value type.";
    return base::nullopt;
  }
  std::vector<uint8_t> auth_data_buffer(it->second.GetBytestring());
  base::span<const uint8_t> auth_data(auth_data_buffer.data(),
                                      auth_data_buffer.size());
  auto authenticator_data =
      AuthenticatorData::DecodeAuthenticatorData(auth_data);
  if (!authenticator_data) {
    LOG(INFO) << "Failed to parse authenticator data.";
    return base::nullopt;
  }
  return authenticator_data;
}

AuthenticatorData::AuthenticatorData(
    base::span<const uint8_t, kRpIdHashLength> application_parameter,
    uint8_t flags,
    base::span<const uint8_t, kSignCounterLength> counter,
    base::Optional<AttestedCredentialData> data,
    base::Optional<cbor::Value> extensions)
    : application_parameter_(
          fido_parsing_utils::Materialize(application_parameter)),
      flags_(flags),
      counter_(fido_parsing_utils::Materialize(counter)),
      attested_data_(std::move(data)),
      extensions_(std::move(extensions)) {
  DCHECK(!extensions_ || extensions_->is_map());
  DCHECK_EQ((flags_ & static_cast<uint8_t>(Flag::kExtensionDataIncluded)) != 0,
            !!extensions_);
  DCHECK_EQ(((flags_ & static_cast<uint8_t>(Flag::kAttestation)) != 0),
            !!attested_data_);
}

AuthenticatorData::AuthenticatorData(AuthenticatorData&& other) = default;
AuthenticatorData& AuthenticatorData::operator=(AuthenticatorData&& other) =
    default;

AuthenticatorData::~AuthenticatorData() = default;

void AuthenticatorData::DeleteDeviceAaguid() {
  if (!attested_data_)
    return;

  attested_data_->DeleteAaguid();
}

std::vector<uint8_t> AuthenticatorData::SerializeToByteArray() const {
  std::vector<uint8_t> authenticator_data;
  fido_parsing_utils::Append(&authenticator_data, application_parameter_);
  authenticator_data.insert(authenticator_data.end(), flags_);
  fido_parsing_utils::Append(&authenticator_data, counter_);

  if (attested_data_) {
    // Attestations are returned in registration responses but not in assertion
    // responses.
    fido_parsing_utils::Append(&authenticator_data,
                               attested_data_->SerializeAsBytes());
  }

  if (extensions_) {
    const auto maybe_extensions = cbor::Writer::Write(*extensions_);
    if (maybe_extensions) {
      fido_parsing_utils::Append(&authenticator_data, *maybe_extensions);
    }
  }

  return authenticator_data;
}

unsigned int AuthenticatorData::GetCounter() {
  uint32_t counter;
  fido::ReadBigEndian<uint32_t>(reinterpret_cast<const char*>(&counter_[0]),
                                &counter);
  return counter;
}

std::string AuthenticatorData::PrintFlags() {
  std::stringstream ss;
  ss << "[UP:" << obtained_user_presence() << "|"
     << "UV: " << obtained_user_verification() << "|"
     << "AT:" << attestation_credential_included() << "|"
     << "ED: " << extension_data_included() << "]";
  return ss.str();
}

std::string AuthenticatorData::ToString() {
  std::stringstream ss;
  ss << "flags: " << PrintFlags() << ", ";
  ss << "counter: " << GetCounter() << ", ";
  ss << "attested data: " << attested_data_->ToString();
  return ss.str();
}

std::vector<uint8_t> AuthenticatorData::GetCredentialId() const {
  if (!attested_data_)
    return std::vector<uint8_t>();
  return attested_data_->credential_id();
}

}  // namespace fido_device
}  // namespace cryptohome
