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