Skip to content

Commit 2c59b2e

Browse files
fix(crypto): OpenSSL 4.x compatibility (#5330)
1 parent 5dcf3f0 commit 2c59b2e

2 files changed

Lines changed: 59 additions & 4 deletions

File tree

src/crypto.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace crypto {
1313
using asn1_string_t = util::safe_ptr<ASN1_STRING, ASN1_STRING_free>;
14+
using x509_name_t = util::safe_ptr<X509_NAME, &X509_NAME_free>;
1415

1516
cert_chain_t::cert_chain_t():
1617
_certs {},
@@ -391,7 +392,10 @@ namespace crypto {
391392
const ASN1_BIT_STRING *asn1 = nullptr;
392393
X509_get0_signature(&asn1, nullptr, x.get());
393394

394-
return {(const char *) asn1->data, (std::size_t) asn1->length};
395+
return {
396+
reinterpret_cast<const char *>(ASN1_STRING_get0_data(asn1)),
397+
static_cast<std::size_t>(ASN1_STRING_length(asn1))
398+
};
395399
}
396400

397401
std::string rand(std::size_t bytes) {
@@ -461,10 +465,11 @@ namespace crypto {
461465

462466
X509_set_pubkey(x509.get(), pkey.get());
463467

464-
auto name = X509_get_subject_name(x509.get());
465-
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const std::uint8_t *) cn.data(), (int) cn.size(), -1, 0);
468+
x509_name_t name {X509_NAME_new()};
469+
X509_NAME_add_entry_by_txt(name.get(), "CN", MBSTRING_ASC, reinterpret_cast<const std::uint8_t *>(cn.data()), (int) cn.size(), -1, 0);
466470

467-
X509_set_issuer_name(x509.get(), name);
471+
X509_set_subject_name(x509.get(), name.get());
472+
X509_set_issuer_name(x509.get(), name.get());
468473
X509_sign(x509.get(), pkey.get(), EVP_sha256());
469474

470475
return {pem(x509), pem(pkey)};

tests/unit/test_crypto.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* @file tests/unit/test_crypto.cpp
3+
* @brief Test src/crypto.*.
4+
*/
5+
// test imports
6+
#include "../tests_common.h"
7+
8+
// lib imports
9+
#include <openssl/x509.h>
10+
11+
// local imports
12+
#include <src/crypto.h>
13+
14+
TEST(CryptoTest, GeneratedCredentialsExposeSubjectAndVerifySignatures) {
15+
constexpr std::string_view common_name = "Sunshine Test Host";
16+
constexpr std::string_view payload = "payload";
17+
18+
auto creds = crypto::gen_creds(common_name, 2048);
19+
ASSERT_FALSE(creds.x509.empty());
20+
ASSERT_FALSE(creds.pkey.empty());
21+
22+
auto cert = crypto::x509(creds.x509);
23+
auto pkey = crypto::pkey(creds.pkey);
24+
ASSERT_NE(cert.get(), nullptr);
25+
ASSERT_NE(pkey.get(), nullptr);
26+
27+
const auto subject = X509_get_subject_name(cert.get());
28+
ASSERT_NE(subject, nullptr);
29+
30+
const auto common_name_index = X509_NAME_get_index_by_NID(subject, NID_commonName, -1);
31+
ASSERT_GE(common_name_index, 0);
32+
33+
const auto common_name_entry = X509_NAME_get_entry(subject, common_name_index);
34+
ASSERT_NE(common_name_entry, nullptr);
35+
36+
const auto common_name_data = X509_NAME_ENTRY_get_data(common_name_entry);
37+
ASSERT_NE(common_name_data, nullptr);
38+
39+
const std::string_view parsed_common_name {
40+
reinterpret_cast<const char *>(ASN1_STRING_get0_data(common_name_data)),
41+
static_cast<std::size_t>(ASN1_STRING_length(common_name_data))
42+
};
43+
ASSERT_EQ(parsed_common_name, common_name);
44+
45+
ASSERT_FALSE(crypto::signature(cert).empty());
46+
47+
const auto signature = crypto::sign256(pkey, payload);
48+
ASSERT_FALSE(signature.empty());
49+
ASSERT_TRUE(crypto::verify256(cert, payload, {reinterpret_cast<const char *>(signature.data()), signature.size()}));
50+
}

0 commit comments

Comments
 (0)