// Copyright 2026 Google LLC
//
// 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.
//

#include "testing/crypto_testing.h"

#include <cstddef>
#include <string>

#include "absl/log/check.h"
#include "absl/time/time.h"
#include "openssl/asn1.h"
#include "openssl/base.h"
#include "openssl/bn.h"
#include "openssl/digest.h"
#include "openssl/ec_key.h"
#include "openssl/evp.h"
#include "openssl/rsa.h"
#include "openssl/x509.h"

namespace credentio {

bssl::UniquePtr<EVP_PKEY> CreateTestEcKey(int nid) {
  bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(nid));
  CHECK_NE(key, nullptr);

  CHECK(EC_KEY_generate_key(key.get()));

  bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
  CHECK_NE(pkey, nullptr);
  CHECK(EVP_PKEY_set1_EC_KEY(pkey.get(), key.get()));
  return pkey;
}

bssl::UniquePtr<EVP_PKEY> CreateTestRsaKey(size_t num_bits) {
  bssl::UniquePtr<BIGNUM> rsa_f4(BN_new());
  CHECK_NE(rsa_f4, nullptr);
  CHECK(BN_set_word(rsa_f4.get(), RSA_F4));

  bssl::UniquePtr<RSA> rsa(RSA_new());
  CHECK_NE(rsa, nullptr);

  CHECK(RSA_generate_key_ex(rsa.get(), num_bits, rsa_f4.get(), nullptr));

  bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
  CHECK_NE(pkey, nullptr);
  CHECK(EVP_PKEY_set1_RSA(pkey.get(), rsa.get()));
  return pkey;
}

bssl::UniquePtr<EVP_PKEY> CreateTestEdKey() {
  bssl::UniquePtr<EVP_PKEY_CTX> ctx(
      EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, nullptr));
  CHECK_NE(ctx, nullptr);
  CHECK(EVP_PKEY_keygen_init(ctx.get()));
  EVP_PKEY* pkey = nullptr;
  CHECK(EVP_PKEY_keygen(ctx.get(), &pkey));
  return bssl::UniquePtr<EVP_PKEY>(pkey);
}

bssl::UniquePtr<X509> CreateTestCertificate(
    const TestCertificateOptions& options) {
  // Options validation.
  CHECK(!options.subject_common_name.empty());
  CHECK(!options.issuer_common_name.empty());
  CHECK(options.signing_key != nullptr);
  CHECK(options.private_key != nullptr);

  // Create the X509 object.
  bssl::UniquePtr<X509> x509(X509_new());
  CHECK(X509_set_version(x509.get(), 2));

  // Set the not_before/not_after fields.
  bssl::UniquePtr<ASN1_TIME> not_before(ASN1_TIME_new());
  CHECK(ASN1_TIME_set(not_before.get(), absl::ToTimeT(options.not_before)));
  CHECK(X509_set1_notBefore(x509.get(), not_before.get()));

  bssl::UniquePtr<ASN1_TIME> not_after(ASN1_TIME_new());
  CHECK(ASN1_TIME_set(not_after.get(), absl::ToTimeT(options.not_after)));
  CHECK(X509_set1_notAfter(x509.get(), not_after.get()));

  // Set the subject DN.
  bssl::UniquePtr<X509_NAME> subject_name(X509_NAME_new());
  CHECK(X509_NAME_add_entry_by_txt(subject_name.get(), /*field=*/"CN",
                                   MBSTRING_ASC,
                                   reinterpret_cast<const unsigned char*>(
                                       options.subject_common_name.c_str()),
                                   /*len=*/-1, /*loc=*/-1,
                                   /*set=*/0));
  CHECK(X509_NAME_add_entry_by_txt(
      subject_name.get(), /*field=*/"O", MBSTRING_ASC,
      reinterpret_cast<const unsigned char*>("Google"),
      /*len=*/-1, /*loc=*/-1,
      /*set=*/0));
  CHECK(X509_NAME_add_entry_by_txt(
      subject_name.get(), /*field=*/"OU", MBSTRING_ASC,
      reinterpret_cast<const unsigned char*>("Google OU"),
      /*len=*/-1, /*loc=*/-1,
      /*set=*/0));
  CHECK(X509_set_subject_name(x509.get(), subject_name.get()));

  // Set the issuer DN.
  bssl::UniquePtr<X509_NAME> issuer_name(X509_NAME_new());
  CHECK(X509_NAME_add_entry_by_txt(issuer_name.get(), /*field=*/"CN",
                                   MBSTRING_ASC,
                                   reinterpret_cast<const unsigned char*>(
                                       options.issuer_common_name.c_str()),
                                   /*len=*/-1, /*loc=*/-1,
                                   /*set=*/0));
  CHECK(X509_NAME_add_entry_by_txt(
      issuer_name.get(), /*field=*/"O", MBSTRING_ASC,
      reinterpret_cast<const unsigned char*>("Google"),
      /*len=*/-1, /*loc=*/-1,
      /*set=*/0));
  CHECK(X509_NAME_add_entry_by_txt(
      issuer_name.get(), /*field=*/"OU", MBSTRING_ASC,
      reinterpret_cast<const unsigned char*>("Google OU"),
      /*len=*/-1, /*loc=*/-1,
      /*set=*/0));
  CHECK(X509_set_issuer_name(x509.get(), issuer_name.get()));

  // Set the public key and sign the certificate.
  CHECK(X509_set_pubkey(x509.get(), options.private_key));
  CHECK(X509_sign(x509.get(), options.signing_key, EVP_sha256()));

  return x509;
}

}  // namespace credentio
