// 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"
#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
