// Copyright 2020 The Fuchsia 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 "src/connectivity/bluetooth/core/bt-host/sm/ecdh_key.h"

#include <zircon/assert.h>

#include <algorithm>
#include <cstddef>
#include <memory>

#include <openssl/ec_key.h>

#include "openssl/base.h"
#include "openssl/bn.h"
#include "openssl/ec.h"
#include "openssl/ecdh.h"
#include "openssl/nid.h"
#include "src/connectivity/bluetooth/core/bt-host/common/uint256.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/smp.h"

namespace bt::sm {

std::optional<EcdhKey> EcdhKey::ParseFromPublicKey(sm::PairingPublicKeyParams pub_key) {
  auto new_key = EcdhKey();
  new_key.key_ = EC_KEY_new_by_curve_name(EC_curve_nist2nid("P-256"));
  if (!new_key.key_) {
    return std::nullopt;
  }
  BIGNUM x, y;
  BN_init(&x);
  BN_init(&y);
  // Assert on le2bn output. le2bn "returns NULL on allocation failure", but allocation should
  // never fail on Fuchsia per overcommit semantics.
  ZX_ASSERT(BN_le2bn(pub_key.x, sizeof(pub_key.x), &x));
  ZX_ASSERT(BN_le2bn(pub_key.y, sizeof(pub_key.y), &y));

  // One potential cause of failure is if pub_key is not a valid ECDH key on the P-256 curve.
  int success = (EC_KEY_set_public_key_affine_coordinates(new_key.key_, &x, &y) == 1);
  BN_free(&x);
  BN_free(&y);
  if (success) {
    return new_key;
  }
  return std::nullopt;
}

EcdhKey& EcdhKey::operator=(EcdhKey&& other) noexcept {
  this->key_ = other.key_;
  other.key_ = nullptr;
  return *this;
}

EcdhKey::EcdhKey(EcdhKey&& other) noexcept : key_(other.key_) { other.key_ = nullptr; }

sm::PairingPublicKeyParams EcdhKey::GetSerializedPublicKey() const {
  sm::PairingPublicKeyParams params;
  BIGNUM x, y;
  BN_init(&x);
  BN_init(&y);
  ZX_ASSERT(EC_POINT_get_affine_coordinates_GFp(
                EC_KEY_get0_group(key_), EC_KEY_get0_public_key(key_), &x, &y, nullptr) == 1);
  ZX_ASSERT(BN_bn2le_padded(params.x, sizeof(params.x), &x) == 1);
  ZX_ASSERT(BN_bn2le_padded(params.y, sizeof(params.y), &y) == 1);
  BN_free(&x);
  BN_free(&y);
  return params;
}

UInt256 EcdhKey::GetPublicKeyX() const {
  BIGNUM x;
  BN_init(&x);
  bool success =
      EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key_), EC_KEY_get0_public_key(key_), &x,
                                          /*y=*/nullptr, /*ctx=*/nullptr) == 1;
  ZX_ASSERT(success);
  UInt256 out{};
  success = BN_bn2le_padded(out.data(), out.size(), &x) == 1;
  ZX_ASSERT(success);
  BN_free(&x);
  return out;
}

UInt256 EcdhKey::GetPublicKeyY() const {
  BIGNUM y;
  BN_init(&y);
  bool success =
      EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key_), EC_KEY_get0_public_key(key_),
                                          /*x=*/nullptr, &y, /*ctx=*/nullptr) == 1;
  ZX_ASSERT(success);
  UInt256 out{};
  success = BN_bn2le_padded(out.data(), out.size(), &y) == 1;
  ZX_ASSERT(success);
  BN_free(&y);
  return out;
}

EcdhKey::EcdhKey() : key_(nullptr) {}

EcdhKey::~EcdhKey() {
  if (key_) {
    EC_KEY_free(key_);
  }
}

LocalEcdhKey::LocalEcdhKey() : EcdhKey() {}

LocalEcdhKey::LocalEcdhKey(LocalEcdhKey&& other) noexcept : EcdhKey(std::move(other)) {}

LocalEcdhKey& LocalEcdhKey::operator=(LocalEcdhKey&& other) noexcept {
  EcdhKey::operator=(std::move(other));
  return *this;
}

std::optional<LocalEcdhKey> LocalEcdhKey::Create() {
  auto new_key = LocalEcdhKey();
  new_key.set_boringssl_key(EC_KEY_new_by_curve_name(EC_curve_nist2nid("P-256")));
  if (!new_key.boringssl_key()) {
    return std::nullopt;
  }
  if (EC_KEY_generate_key(new_key.mut_boringssl_key()) != 1) {
    return std::nullopt;
  }
  return new_key;
}

UInt256 LocalEcdhKey::CalculateDhKey(const EcdhKey& peer_public_key) const {
  UInt256 out{0};
  bool success = ECDH_compute_key(out.data(), out.size(),
                                  EC_KEY_get0_public_key(peer_public_key.boringssl_key()),
                                  boringssl_key(), /*kdf=*/nullptr) == out.size();
  ZX_ASSERT(success);
  std::reverse(out.begin(), out.end());
  return out;
}

void LocalEcdhKey::SetPrivateKeyForTesting(const UInt256& private_key) {
  BIGNUM pkey;
  BN_init(&pkey);
  BN_le2bn(private_key.data(), private_key.size(), &pkey);
  ZX_ASSERT_MSG(EC_KEY_set_private_key(mut_boringssl_key(), &pkey) == 1,
                "Could not set private key in test");
  BN_free(&pkey);
}

}  // namespace bt::sm
