// Copyright 2021 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#define PW_LOG_MODULE_NAME "ECDSA-BSSL"
#define PW_LOG_LEVEL PW_LOG_LEVEL_WARN

#include "openssl/bn.h"
#include "openssl/ec.h"
#include "openssl/ecdsa.h"
#include "openssl/nid.h"
#include "pw_crypto/ecdsa.h"
#include "pw_log/log.h"

namespace pw::crypto::ecdsa {

constexpr size_t kP256CurveOrderBytes = 32;

Status VerifyP256Signature(ConstByteSpan public_key,
                           ConstByteSpan digest,
                           ConstByteSpan signature) {
  const uint8_t* public_key_bytes =
      reinterpret_cast<const uint8_t*>(public_key.data());
  const uint8_t* digest_bytes = reinterpret_cast<const uint8_t*>(digest.data());
  const uint8_t* signature_bytes =
      reinterpret_cast<const uint8_t*>(signature.data());

  // Allocate objects needed for ECDSA verification. BoringSSL relies on
  // dynamic allocation.
  bssl::UniquePtr<EC_GROUP> group(
      EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
  if (!group) {
    return Status::ResourceExhausted();
  }

  bssl::UniquePtr<EC_POINT> pub_key(EC_POINT_new(group.get()));
  bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
  bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new());
  if (!(pub_key && key && sig)) {
    return Status::ResourceExhausted();
  }

  // Load the public key.
  if (!EC_POINT_oct2point(group.get(),
                          pub_key.get(),
                          public_key_bytes,
                          public_key.size(),
                          nullptr)) {
    PW_LOG_DEBUG("Bad public key format");
    return Status::InvalidArgument();
  }

  if (!EC_KEY_set_group(key.get(), group.get())) {
    return Status::InvalidArgument();
  }

  if (!EC_KEY_set_public_key(key.get(), pub_key.get())) {
    return Status::InvalidArgument();
  }

  // Load the signature.
  if (signature.size() != kP256CurveOrderBytes * 2) {
    PW_LOG_DEBUG("Bad signature format");
    return Status::InvalidArgument();
  }

  if (!(BN_bin2bn(signature_bytes, kP256CurveOrderBytes, sig->r) &&
        BN_bin2bn(signature_bytes + kP256CurveOrderBytes,
                  kP256CurveOrderBytes,
                  sig->s))) {
    return Status::Internal();
  }

  // Digest must be 32 bytes or longer (and will be truncated).
  if (digest.size() < kP256CurveOrderBytes) {
    PW_LOG_DEBUG("Digest is too short");
    return Status::InvalidArgument();
  }

  // Verify the signature.
  if (!ECDSA_do_verify(digest_bytes, digest.size(), sig.get(), key.get())) {
    PW_LOG_DEBUG("Signature verification failed");
    return Status::Unauthenticated();
  }

  return OkStatus();
}

}  // namespace pw::crypto::ecdsa
