// Copyright 2020 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/cable/v2_handshake.h"

#include "base/numerics/safe_math.h"
#include "base/strings/string_number_conversions.h"  // TODO REMOVE
#include "components/cbor/reader.h"
#include "components/cbor/writer.h"
#include "components/device_event_log/device_event_log.h"
#include "crypto/aead.h"
#include "device/fido/fido_constants.h"
#include "device/fido/fido_parsing_utils.h"
#include "third_party/boringssl/src/include/openssl/bytestring.h"
#include "third_party/boringssl/src/include/openssl/digest.h"
#include "third_party/boringssl/src/include/openssl/ec.h"
#include "third_party/boringssl/src/include/openssl/ec_key.h"
#include "third_party/boringssl/src/include/openssl/ecdh.h"
#include "third_party/boringssl/src/include/openssl/hkdf.h"
#include "third_party/boringssl/src/include/openssl/obj.h"
#include "third_party/boringssl/src/include/openssl/sha.h"

using device::fido_parsing_utils::CopyCBORBytestring;

namespace {

// Maximum value of a sequence number. Exceeding this causes all operations to
// return an error. This is assumed to be vastly larger than any caBLE exchange
// will ever reach.
constexpr uint32_t kMaxSequence = (1 << 24) - 1;

bool ConstructNonce(uint32_t counter, base::span<uint8_t, 12> out_nonce) {
  if (counter > kMaxSequence) {
    return false;
  }

  // Nonce is just a little-endian counter.
  std::array<uint8_t, sizeof(counter)> counter_bytes;
  memcpy(counter_bytes.data(), &counter, sizeof(counter));
  auto remaining =
      std::copy(counter_bytes.begin(), counter_bytes.end(), out_nonce.begin());
  std::fill(remaining, out_nonce.end(), 0);
  return true;
}

CBS CBSFromSpan(base::span<const uint8_t> in) {
  CBS cbs;
  CBS_init(&cbs, in.data(), in.size());
  return cbs;
}

bool CBS_get_span(CBS* cbs, base::span<const uint8_t>* out_span, size_t N) {
  CBS contents;
  if (!CBS_get_bytes(cbs, &contents, N)) {
    return false;
  }
  *out_span =
      base::span<const uint8_t>(CBS_data(&contents), CBS_len(&contents));
  return true;
}

constexpr uint8_t kPairedPrologue[] = "caBLE handshake";
constexpr uint8_t kQRPrologue[] = "caBLE QR code handshake";

}  // namespace

namespace device {
namespace cablev2 {

Crypter::Crypter(base::span<const uint8_t, 32> read_key,
                 base::span<const uint8_t, 32> write_key)
    : read_key_(fido_parsing_utils::Materialize(read_key)),
      write_key_(fido_parsing_utils::Materialize(write_key)) {}

Crypter::~Crypter() = default;

bool Crypter::Encrypt(std::vector<uint8_t>* message_to_encrypt) {
  // Messages will be padded in order to round their length up to a multiple
  // of kPaddingGranularity.
  constexpr size_t kPaddingGranularity = 32;
  static_assert(kPaddingGranularity > 0, "padding too small");
  static_assert(kPaddingGranularity < 256, "padding too large");
  static_assert((kPaddingGranularity & (kPaddingGranularity - 1)) == 0,
                "padding must be a power of two");

  // Padding consists of a some number of zero bytes appended to the message
  // and the final byte in the message is the number of zeros.
  base::CheckedNumeric<size_t> padded_size_checked = message_to_encrypt->size();
  padded_size_checked += 1;  // padding-length byte.
  padded_size_checked = (padded_size_checked + kPaddingGranularity - 1) &
                        ~(kPaddingGranularity - 1);
  if (!padded_size_checked.IsValid()) {
    NOTREACHED();
    return false;
  }

  const size_t padded_size = padded_size_checked.ValueOrDie();
  CHECK_GT(padded_size, message_to_encrypt->size());
  const size_t num_zeros = padded_size - message_to_encrypt->size() - 1;

  std::vector<uint8_t> padded_message(padded_size, 0);
  memcpy(padded_message.data(), message_to_encrypt->data(),
         message_to_encrypt->size());
  // The number of added zeros has to fit in a single byte so it has to be
  // less than 256.
  DCHECK_LT(num_zeros, 256u);
  padded_message[padded_message.size() - 1] = static_cast<uint8_t>(num_zeros);

  std::array<uint8_t, 12> nonce;
  if (!ConstructNonce(write_sequence_num_++, nonce)) {
    return false;
  }

  crypto::Aead aes_key(crypto::Aead::AES_256_GCM);
  aes_key.Init(write_key_);
  DCHECK_EQ(nonce.size(), aes_key.NonceLength());

  const uint8_t additional_data[2] = {
      base::strict_cast<uint8_t>(device::FidoBleDeviceCommand::kMsg),
      /*version=*/2};
  std::vector<uint8_t> ciphertext =
      aes_key.Seal(padded_message, nonce, additional_data);
  message_to_encrypt->swap(ciphertext);
  return true;
}

bool Crypter::Decrypt(FidoBleDeviceCommand command,
                      base::span<const uint8_t> ciphertext,
                      std::vector<uint8_t>* out_plaintext) {
  std::array<uint8_t, 12> nonce;
  if (!ConstructNonce(read_sequence_num_, nonce)) {
    return false;
  }

  crypto::Aead aes_key(crypto::Aead::AES_256_GCM);
  aes_key.Init(read_key_);
  DCHECK_EQ(nonce.size(), aes_key.NonceLength());

  const uint8_t additional_data[2] = {base::strict_cast<uint8_t>(command),
                                      /*version=*/2};
  base::Optional<std::vector<uint8_t>> plaintext =
      aes_key.Open(ciphertext, nonce, additional_data);

  if (!plaintext) {
    return false;
  }
  read_sequence_num_++;

  if (plaintext->empty()) {
    FIDO_LOG(ERROR) << "Invalid caBLE message.";
    return false;
  }

  const size_t padding_length = (*plaintext)[plaintext->size() - 1];
  if (padding_length + 1 > plaintext->size()) {
    FIDO_LOG(ERROR) << "Invalid caBLE message.";
    return false;
  }
  plaintext->resize(plaintext->size() - padding_length - 1);

  out_plaintext->swap(*plaintext);
  return true;
}

bool Crypter::IsCounterpartyOfForTesting(const Crypter& other) const {
  return read_key_ == other.write_key_ && write_key_ == other.read_key_;
}

HandshakeInitiator::HandshakeInitiator(
    base::span<const uint8_t, 32> psk_gen_key,
    base::span<const uint8_t, 8> nonce,
    base::span<const uint8_t, kCableEphemeralIdSize> eid,
    base::Optional<base::span<const uint8_t, kP256PointSize>> peer_identity)
    : eid_(fido_parsing_utils::Materialize(eid)) {
  HKDF(psk_.data(), psk_.size(), EVP_sha256(), psk_gen_key.data(),
       psk_gen_key.size(), /*salt=*/nonce.data(), nonce.size(),
       /*info=*/nullptr, 0);
  if (peer_identity) {
    peer_identity_ = fido_parsing_utils::Materialize(*peer_identity);
  }
}

HandshakeInitiator::~HandshakeInitiator() = default;

std::vector<uint8_t> HandshakeInitiator::BuildInitialMessage() {
  if (peer_identity_) {
    noise_.Init(Noise::HandshakeType::kNKpsk0);
    noise_.MixHash(kPairedPrologue);
  } else {
    noise_.Init(Noise::HandshakeType::kNNpsk0);
    noise_.MixHash(kQRPrologue);
  }

  noise_.MixKeyAndHash(psk_);
  ephemeral_key_.reset(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
  const EC_GROUP* group = EC_KEY_get0_group(ephemeral_key_.get());
  CHECK(EC_KEY_generate_key(ephemeral_key_.get()));
  uint8_t ephemeral_key_public_bytes[kP256PointSize];
  CHECK_EQ(sizeof(ephemeral_key_public_bytes),
           EC_POINT_point2oct(
               group, EC_KEY_get0_public_key(ephemeral_key_.get()),
               POINT_CONVERSION_UNCOMPRESSED, ephemeral_key_public_bytes,
               sizeof(ephemeral_key_public_bytes), /*ctx=*/nullptr));
  noise_.MixHash(ephemeral_key_public_bytes);
  noise_.MixKey(ephemeral_key_public_bytes);

  if (peer_identity_) {
    // If we know the identity of the peer from a previous interaction, NKpsk0
    // is performed to ensure that other browsers, which may also know the PSK,
    // cannot impersonate the authenticator.
    bssl::UniquePtr<EC_POINT> peer_identity_point(EC_POINT_new(group));
    uint8_t es_key[32];
    CHECK(EC_POINT_oct2point(group, peer_identity_point.get(),
                             peer_identity_->data(), peer_identity_->size(),
                             /*ctx=*/nullptr) &&
          ECDH_compute_key(es_key, sizeof(es_key), peer_identity_point.get(),
                           ephemeral_key_.get(), /*kdf=*/nullptr));
    noise_.MixKey(es_key);
  }

  std::vector<uint8_t> ciphertext =
      noise_.EncryptAndHash(base::span<const uint8_t>());

  std::vector<uint8_t> handshake_message;
  handshake_message.reserve(eid_.size() + sizeof(ephemeral_key_public_bytes) +
                            ciphertext.size());
  handshake_message.insert(handshake_message.end(), eid_.begin(), eid_.end());
  handshake_message.insert(
      handshake_message.end(), ephemeral_key_public_bytes,
      ephemeral_key_public_bytes + sizeof(ephemeral_key_public_bytes));
  handshake_message.insert(handshake_message.end(), ciphertext.begin(),
                           ciphertext.end());

  return handshake_message;
}

base::Optional<std::pair<std::unique_ptr<Crypter>,
                         base::Optional<std::unique_ptr<CableDiscoveryData>>>>
HandshakeInitiator::ProcessResponse(base::span<const uint8_t> response) {
  if (response.size() < kP256PointSize) {
    return base::nullopt;
  }
  auto peer_point_bytes = response.subspan(0, kP256PointSize);
  auto ciphertext = response.subspan(kP256PointSize);

  bssl::UniquePtr<EC_POINT> peer_point(
      EC_POINT_new(EC_KEY_get0_group(ephemeral_key_.get())));
  uint8_t shared_key[32];
  const EC_GROUP* group = EC_KEY_get0_group(ephemeral_key_.get());
  if (!EC_POINT_oct2point(group, peer_point.get(), peer_point_bytes.data(),
                          peer_point_bytes.size(), /*ctx=*/nullptr) ||
      !ECDH_compute_key(shared_key, sizeof(shared_key), peer_point.get(),
                        ephemeral_key_.get(), /*kdf=*/nullptr)) {
    FIDO_LOG(DEBUG) << "Peer's P-256 point not on curve.";
    return base::nullopt;
  }

  noise_.MixHash(peer_point_bytes);
  noise_.MixKey(peer_point_bytes);
  noise_.MixKey(shared_key);

  auto plaintext = noise_.DecryptAndHash(ciphertext);
  if (!plaintext || plaintext->empty() != peer_identity_.has_value()) {
    FIDO_LOG(DEBUG) << "Invalid caBLE handshake message";
    return base::nullopt;
  }

  base::Optional<std::unique_ptr<CableDiscoveryData>> discovery_data;
  if (!peer_identity_) {
    // Handshakes without a peer identity (i.e. NNpsk0 handshakes setup from a
    // QR code) send a padded message in the reply. This message can,
    // optionally, contain CBOR-encoded, long-term pairing information.
    const size_t padding_length = (*plaintext)[plaintext->size() - 1];
    if (padding_length + 1 > plaintext->size()) {
      FIDO_LOG(DEBUG) << "Invalid padding in caBLE handshake message";
      return base::nullopt;
    }
    plaintext->resize(plaintext->size() - padding_length - 1);

    if (!plaintext->empty()) {
      base::Optional<cbor::Value> pairing = cbor::Reader::Read(*plaintext);
      if (!pairing || !pairing->is_map()) {
        FIDO_LOG(DEBUG) << "CBOR parse failure in caBLE handshake message";
        return base::nullopt;
      }

      auto future_discovery = std::make_unique<CableDiscoveryData>();
      future_discovery->version = CableDiscoveryData::Version::V2;
      future_discovery->v2.emplace();
      future_discovery->v2->peer_identity.emplace();

      const cbor::Value::MapValue& pairing_map(pairing->GetMap());
      const auto name_it = pairing_map.find(cbor::Value(4));
      if (!CopyCBORBytestring(&future_discovery->v2->eid_gen_key, pairing_map,
                              1) ||
          !CopyCBORBytestring(&future_discovery->v2->psk_gen_key, pairing_map,
                              2) ||
          !CopyCBORBytestring(&future_discovery->v2->peer_identity.value(),
                              pairing_map, 3) ||
          name_it == pairing_map.end() || !name_it->second.is_string() ||
          !EC_POINT_oct2point(group, peer_point.get(),
                              future_discovery->v2->peer_identity->data(),
                              future_discovery->v2->peer_identity->size(),
                              /*ctx=*/nullptr)) {
        FIDO_LOG(DEBUG) << "CBOR structure error in caBLE handshake message";
        return base::nullopt;
      }

      future_discovery->v2->peer_name = name_it->second.GetString();
      discovery_data.emplace(std::move(future_discovery));
    }
  }

  std::array<uint8_t, 32> read_key, write_key;
  std::tie(write_key, read_key) = noise_.traffic_keys();
  return std::make_pair(std::make_unique<cablev2::Crypter>(read_key, write_key),
                        std::move(discovery_data));
}

base::Optional<std::unique_ptr<Crypter>> RespondToHandshake(
    base::span<const uint8_t, 32> psk_gen_key,
    const NonceAndEID& nonce_and_eid,
    const EC_KEY* identity,
    const CableDiscoveryData* pairing_data,
    base::span<const uint8_t> in,
    std::vector<uint8_t>* out_response) {
  DCHECK(identity == nullptr || pairing_data == nullptr);

  CBS cbs = CBSFromSpan(in);

  base::span<const uint8_t> eid;
  base::span<const uint8_t> peer_point_bytes;
  base::span<const uint8_t> ciphertext;
  if (!CBS_get_span(&cbs, &eid, device::kCableEphemeralIdSize) ||
      !CBS_get_span(&cbs, &peer_point_bytes, kP256PointSize) ||
      !CBS_get_span(&cbs, &ciphertext, 16) || CBS_len(&cbs) != 0) {
    return base::nullopt;
  }

  if (eid.size() != nonce_and_eid.second.size() ||
      memcmp(eid.data(), nonce_and_eid.second.data(), eid.size()) != 0) {
    return base::nullopt;
  }

  Noise noise;
  if (identity) {
    noise.Init(device::Noise::HandshakeType::kNKpsk0);
    noise.MixHash(kPairedPrologue);
  } else {
    noise.Init(device::Noise::HandshakeType::kNNpsk0);
    noise.MixHash(kQRPrologue);
  }

  std::array<uint8_t, 32> psk;
  HKDF(psk.data(), psk.size(), EVP_sha256(), psk_gen_key.data(),
       psk_gen_key.size(),
       /*salt=*/nonce_and_eid.first.data(), nonce_and_eid.first.size(),
       /*info=*/nullptr, 0);

  noise.MixKeyAndHash(psk);
  noise.MixHash(peer_point_bytes);
  noise.MixKey(peer_point_bytes);

  bssl::UniquePtr<EC_KEY> ephemeral_key(
      EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
  const EC_GROUP* group = EC_KEY_get0_group(ephemeral_key.get());
  CHECK(EC_KEY_generate_key(ephemeral_key.get()));
  bssl::UniquePtr<EC_POINT> peer_point(EC_POINT_new(group));
  if (!EC_POINT_oct2point(group, peer_point.get(), peer_point_bytes.data(),
                          peer_point_bytes.size(),
                          /*ctx=*/nullptr)) {
    FIDO_LOG(DEBUG) << "Peer's P-256 point not on curve.";
    return base::nullopt;
  }

  if (identity) {
    uint8_t es_key[32];
    if (!ECDH_compute_key(es_key, sizeof(es_key), peer_point.get(), identity,
                          /*kdf=*/nullptr)) {
      return base::nullopt;
    }
    noise.MixKey(es_key);
  }

  auto plaintext = noise.DecryptAndHash(ciphertext);
  if (!plaintext || !plaintext->empty()) {
    FIDO_LOG(DEBUG) << "Failed to decrypt handshake ciphertext.";
    return base::nullopt;
  }

  uint8_t ephemeral_key_public_bytes[kP256PointSize];
  CHECK_EQ(sizeof(ephemeral_key_public_bytes),
           EC_POINT_point2oct(
               group, EC_KEY_get0_public_key(ephemeral_key.get()),
               POINT_CONVERSION_UNCOMPRESSED, ephemeral_key_public_bytes,
               sizeof(ephemeral_key_public_bytes), /*ctx=*/nullptr));
  noise.MixHash(ephemeral_key_public_bytes);
  noise.MixKey(ephemeral_key_public_bytes);

  uint8_t shared_key[32];
  if (!ECDH_compute_key(shared_key, sizeof(shared_key), peer_point.get(),
                        ephemeral_key.get(), /*kdf=*/nullptr)) {
    return base::nullopt;
  }
  noise.MixKey(shared_key);

  std::vector<uint8_t> my_ciphertext;
  if (!identity) {
    uint8_t my_plaintext[256];
    memset(my_plaintext, 0, sizeof(my_plaintext));

    if (pairing_data) {
      cbor::Value::MapValue pairing;
      pairing.emplace(1, pairing_data->v2->eid_gen_key);
      pairing.emplace(2, pairing_data->v2->psk_gen_key);
      pairing.emplace(3, pairing_data->v2->peer_identity.value());
      pairing.emplace(4, pairing_data->v2->peer_name.value());
      base::Optional<std::vector<uint8_t>> cbor_bytes =
          cbor::Writer::Write(cbor::Value(std::move(pairing)));
      if (!cbor_bytes || cbor_bytes->size() > sizeof(my_plaintext) - 1) {
        FIDO_LOG(DEBUG) << "Pairing encoding failed or result too large.";
        return base::nullopt;
      }
      memcpy(my_plaintext, cbor_bytes->data(), cbor_bytes->size());
      my_plaintext[255] = sizeof(my_plaintext) - 1 - cbor_bytes->size();
    } else {
      my_plaintext[255] = 255;
    }
    my_ciphertext = noise.EncryptAndHash(my_plaintext);
  } else {
    my_ciphertext = noise.EncryptAndHash(base::span<const uint8_t>());
  }

  out_response->insert(
      out_response->end(), ephemeral_key_public_bytes,
      ephemeral_key_public_bytes + sizeof(ephemeral_key_public_bytes));
  out_response->insert(out_response->end(), my_ciphertext.begin(),
                       my_ciphertext.end());

  std::array<uint8_t, 32> read_key, write_key;
  std::tie(read_key, write_key) = noise.traffic_keys();
  return std::make_unique<Crypter>(read_key, write_key);
}

}  // namespace cablev2
}  // namespace device
