diff --git a/src/crypto.cpp b/src/crypto.cpp index c5e236e9d2c..f6ec0cb78c8 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -11,6 +11,7 @@ namespace crypto { using asn1_string_t = util::safe_ptr; + using x509_name_t = util::safe_ptr; cert_chain_t::cert_chain_t(): _certs {}, @@ -391,7 +392,10 @@ namespace crypto { const ASN1_BIT_STRING *asn1 = nullptr; X509_get0_signature(&asn1, nullptr, x.get()); - return {(const char *) asn1->data, (std::size_t) asn1->length}; + return { + reinterpret_cast(ASN1_STRING_get0_data(asn1)), + static_cast(ASN1_STRING_length(asn1)) + }; } std::string rand(std::size_t bytes) { @@ -461,10 +465,11 @@ namespace crypto { X509_set_pubkey(x509.get(), pkey.get()); - auto name = X509_get_subject_name(x509.get()); - X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const std::uint8_t *) cn.data(), (int) cn.size(), -1, 0); + x509_name_t name {X509_NAME_new()}; + X509_NAME_add_entry_by_txt(name.get(), "CN", MBSTRING_ASC, reinterpret_cast(cn.data()), (int) cn.size(), -1, 0); - X509_set_issuer_name(x509.get(), name); + X509_set_subject_name(x509.get(), name.get()); + X509_set_issuer_name(x509.get(), name.get()); X509_sign(x509.get(), pkey.get(), EVP_sha256()); return {pem(x509), pem(pkey)}; diff --git a/tests/unit/test_crypto.cpp b/tests/unit/test_crypto.cpp new file mode 100644 index 00000000000..e92afec3b33 --- /dev/null +++ b/tests/unit/test_crypto.cpp @@ -0,0 +1,50 @@ +/** + * @file tests/unit/test_crypto.cpp + * @brief Test src/crypto.*. + */ +// test imports +#include "../tests_common.h" + +// lib imports +#include + +// local imports +#include + +TEST(CryptoTest, GeneratedCredentialsExposeSubjectAndVerifySignatures) { + constexpr std::string_view common_name = "Sunshine Test Host"; + constexpr std::string_view payload = "payload"; + + auto creds = crypto::gen_creds(common_name, 2048); + ASSERT_FALSE(creds.x509.empty()); + ASSERT_FALSE(creds.pkey.empty()); + + auto cert = crypto::x509(creds.x509); + auto pkey = crypto::pkey(creds.pkey); + ASSERT_NE(cert.get(), nullptr); + ASSERT_NE(pkey.get(), nullptr); + + const auto subject = X509_get_subject_name(cert.get()); + ASSERT_NE(subject, nullptr); + + const auto common_name_index = X509_NAME_get_index_by_NID(subject, NID_commonName, -1); + ASSERT_GE(common_name_index, 0); + + const auto common_name_entry = X509_NAME_get_entry(subject, common_name_index); + ASSERT_NE(common_name_entry, nullptr); + + const auto common_name_data = X509_NAME_ENTRY_get_data(common_name_entry); + ASSERT_NE(common_name_data, nullptr); + + const std::string_view parsed_common_name { + reinterpret_cast(ASN1_STRING_get0_data(common_name_data)), + static_cast(ASN1_STRING_length(common_name_data)) + }; + ASSERT_EQ(parsed_common_name, common_name); + + ASSERT_FALSE(crypto::signature(cert).empty()); + + const auto signature = crypto::sign256(pkey, payload); + ASSERT_FALSE(signature.empty()); + ASSERT_TRUE(crypto::verify256(cert, payload, {reinterpret_cast(signature.data()), signature.size()})); +}