Skip to content

Commit 30c62de

Browse files
danbevdanielleadams
authored andcommitted
src,test: support dynamically linking OpenSSL 3.0
This commit enables node to dynamically link against OpenSSL 3.0. The motivation for opening this PR even though OpenSSL 3.0 has not been released yet is to allow a nightly CI job to be created. This will allow us stay on top of changes required for OpenSSL 3.0, and also to make sure that changes to node crypto do not cause issues when linking to OpenSSL 3.0. PR-URL: #37669 Refs: #29817 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Michael Dawson <midawson@redhat.com>
1 parent bd62771 commit 30c62de

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+513
-297
lines changed

node.gypi

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,11 @@
361361
],
362362
}],
363363
],
364-
}]]
364+
}, {
365+
# Set 1.0.0 as the API compability level to avoid the
366+
# deprecation warnings when using OpenSSL 3.0.
367+
'defines': ['OPENSSL_API_COMPAT=0x10000000L'],
368+
}]]
365369

366370
}, {
367371
'defines': [ 'HAVE_OPENSSL=0' ]

src/crypto/crypto_cipher.cc

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,11 @@ void CipherBase::Init(const char* cipher_type,
342342
unsigned int auth_tag_len) {
343343
HandleScope scope(env()->isolate());
344344
MarkPopErrorOnReturn mark_pop_error_on_return;
345-
345+
#if OPENSSL_VERSION_MAJOR >= 3
346+
if (EVP_default_properties_is_fips_enabled(nullptr)) {
347+
#else
346348
if (FIPS_mode()) {
349+
#endif
347350
return THROW_ERR_CRYPTO_UNSUPPORTED_OPERATION(env(),
348351
"crypto.createCipher() is not supported in FIPS mode.");
349352
}
@@ -527,7 +530,13 @@ bool CipherBase::InitAuthenticated(
527530
}
528531

529532
// TODO(tniessen) Support CCM decryption in FIPS mode
533+
534+
#if OPENSSL_VERSION_MAJOR >= 3
535+
if (mode == EVP_CIPH_CCM_MODE && kind_ == kDecipher &&
536+
EVP_default_properties_is_fips_enabled(nullptr)) {
537+
#else
530538
if (mode == EVP_CIPH_CCM_MODE && kind_ == kDecipher && FIPS_mode()) {
539+
#endif
531540
THROW_ERR_CRYPTO_UNSUPPORTED_OPERATION(env(),
532541
"CCM encryption not supported in FIPS mode");
533542
return false;

src/crypto/crypto_dsa.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ Maybe<bool> GetDsaKeyDetail(
138138
int type = EVP_PKEY_id(m_pkey.get());
139139
CHECK(type == EVP_PKEY_DSA);
140140

141-
DSA* dsa = EVP_PKEY_get0_DSA(m_pkey.get());
141+
const DSA* dsa = EVP_PKEY_get0_DSA(m_pkey.get());
142142
CHECK_NOT_NULL(dsa);
143143

144144
DSA_get0_pqg(dsa, &p, &q, nullptr);

src/crypto/crypto_ec.cc

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -463,19 +463,22 @@ bool ECDHBitsTraits::DeriveBits(
463463

464464
char* data = nullptr;
465465
size_t len = 0;
466+
ManagedEVPPKey m_privkey = params.private_->GetAsymmetricKey();
467+
ManagedEVPPKey m_pubkey = params.public_->GetAsymmetricKey();
466468

467469
switch (params.id_) {
468470
case EVP_PKEY_X25519:
469471
// Fall through
470472
case EVP_PKEY_X448: {
471-
EVPKeyCtxPointer ctx(
472-
EVP_PKEY_CTX_new(
473-
params.private_->GetAsymmetricKey().get(),
474-
nullptr));
473+
EVPKeyCtxPointer ctx = nullptr;
474+
{
475+
ctx.reset(EVP_PKEY_CTX_new(m_privkey.get(), nullptr));
476+
}
477+
Mutex::ScopedLock pub_lock(*m_pubkey.mutex());
475478
if (EVP_PKEY_derive_init(ctx.get()) <= 0 ||
476479
EVP_PKEY_derive_set_peer(
477480
ctx.get(),
478-
params.public_->GetAsymmetricKey().get()) <= 0 ||
481+
m_pubkey.get()) <= 0 ||
479482
EVP_PKEY_derive(ctx.get(), nullptr, &len) <= 0) {
480483
return false;
481484
}
@@ -492,10 +495,14 @@ bool ECDHBitsTraits::DeriveBits(
492495
break;
493496
}
494497
default: {
495-
const EC_KEY* private_key =
496-
EVP_PKEY_get0_EC_KEY(params.private_->GetAsymmetricKey().get());
497-
const EC_KEY* public_key =
498-
EVP_PKEY_get0_EC_KEY(params.public_->GetAsymmetricKey().get());
498+
const EC_KEY* private_key;
499+
{
500+
Mutex::ScopedLock priv_lock(*m_privkey.mutex());
501+
private_key = EVP_PKEY_get0_EC_KEY(m_privkey.get());
502+
}
503+
504+
Mutex::ScopedLock pub_lock(*m_pubkey.mutex());
505+
const EC_KEY* public_key = EVP_PKEY_get0_EC_KEY(m_pubkey.get());
499506

500507
const EC_GROUP* group = EC_KEY_get0_group(private_key);
501508
if (group == nullptr)
@@ -607,7 +614,7 @@ WebCryptoKeyExportStatus EC_Raw_Export(
607614
CHECK(m_pkey);
608615
Mutex::ScopedLock lock(*m_pkey.mutex());
609616

610-
EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(m_pkey.get());
617+
const EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(m_pkey.get());
611618

612619
unsigned char* data;
613620
size_t len = 0;
@@ -627,10 +634,10 @@ WebCryptoKeyExportStatus EC_Raw_Export(
627634
}
628635
CHECK_NOT_NULL(fn);
629636
// Get the size of the raw key data
630-
if (fn(key_data->GetAsymmetricKey().get(), nullptr, &len) == 0)
637+
if (fn(m_pkey.get(), nullptr, &len) == 0)
631638
return WebCryptoKeyExportStatus::INVALID_KEY_TYPE;
632639
data = MallocOpenSSL<unsigned char>(len);
633-
if (fn(key_data->GetAsymmetricKey().get(), data, &len) == 0)
640+
if (fn(m_pkey.get(), data, &len) == 0)
634641
return WebCryptoKeyExportStatus::INVALID_KEY_TYPE;
635642
} else {
636643
if (key_data->GetKeyType() != kKeyTypePublic)
@@ -696,7 +703,7 @@ Maybe<bool> ExportJWKEcKey(
696703
Mutex::ScopedLock lock(*m_pkey.mutex());
697704
CHECK_EQ(EVP_PKEY_id(m_pkey.get()), EVP_PKEY_EC);
698705

699-
EC_KEY* ec = EVP_PKEY_get0_EC_KEY(m_pkey.get());
706+
const EC_KEY* ec = EVP_PKEY_get0_EC_KEY(m_pkey.get());
700707
CHECK_NOT_NULL(ec);
701708

702709
const EC_POINT* pub = EC_KEY_get0_public_key(ec);
@@ -751,6 +758,7 @@ Maybe<bool> ExportJWKEdKey(
751758
std::shared_ptr<KeyObjectData> key,
752759
Local<Object> target) {
753760
ManagedEVPPKey pkey = key->GetAsymmetricKey();
761+
Mutex::ScopedLock lock(*pkey.mutex());
754762

755763
const char* curve = nullptr;
756764
switch (EVP_PKEY_id(pkey.get())) {
@@ -902,7 +910,7 @@ Maybe<bool> GetEcKeyDetail(
902910
Mutex::ScopedLock lock(*m_pkey.mutex());
903911
CHECK_EQ(EVP_PKEY_id(m_pkey.get()), EVP_PKEY_EC);
904912

905-
EC_KEY* ec = EVP_PKEY_get0_EC_KEY(m_pkey.get());
913+
const EC_KEY* ec = EVP_PKEY_get0_EC_KEY(m_pkey.get());
906914
CHECK_NOT_NULL(ec);
907915

908916
const EC_GROUP* group = EC_KEY_get0_group(ec);
@@ -919,8 +927,8 @@ Maybe<bool> GetEcKeyDetail(
919927
// implementation here is a adapted from Chromium's impl here:
920928
// https://github.com/chromium/chromium/blob/7af6cfd/components/webcrypto/algorithms/ecdsa.cc
921929

922-
size_t GroupOrderSize(ManagedEVPPKey key) {
923-
EC_KEY* ec = EVP_PKEY_get0_EC_KEY(key.get());
930+
size_t GroupOrderSize(const ManagedEVPPKey& key) {
931+
const EC_KEY* ec = EVP_PKEY_get0_EC_KEY(key.get());
924932
CHECK_NOT_NULL(ec);
925933
const EC_GROUP* group = EC_KEY_get0_group(ec);
926934
BignumPointer order(BN_new());

src/crypto/crypto_hkdf.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,15 +110,15 @@ bool HKDFTraits::DeriveBits(
110110
!EVP_PKEY_CTX_set_hkdf_md(ctx.get(), params.digest) ||
111111
!EVP_PKEY_CTX_set1_hkdf_salt(
112112
ctx.get(),
113-
params.salt.get(),
113+
reinterpret_cast<const unsigned char*>(params.salt.get()),
114114
params.salt.size()) ||
115115
!EVP_PKEY_CTX_set1_hkdf_key(
116116
ctx.get(),
117-
params.key->GetSymmetricKey(),
117+
reinterpret_cast<const unsigned char*>(params.key->GetSymmetricKey()),
118118
params.key->GetSymmetricKeySize()) ||
119119
!EVP_PKEY_CTX_add1_hkdf_info(
120120
ctx.get(),
121-
params.info.get(),
121+
reinterpret_cast<const unsigned char*>(params.info.get()),
122122
params.info.size())) {
123123
return false;
124124
}

src/crypto/crypto_keygen.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,9 @@ struct KeyPairGenConfig final : public MemoryRetainer {
235235
AlgorithmParams params;
236236

237237
KeyPairGenConfig() = default;
238+
~KeyPairGenConfig() {
239+
Mutex::ScopedLock priv_lock(*key.mutex());
240+
}
238241

239242
explicit KeyPairGenConfig(KeyPairGenConfig&& other) noexcept
240243
: public_key_encoding(other.public_key_encoding),

src/crypto/crypto_keys.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,8 @@ ManagedEVPPKey::ManagedEVPPKey(const ManagedEVPPKey& that) {
559559
}
560560

561561
ManagedEVPPKey& ManagedEVPPKey::operator=(const ManagedEVPPKey& that) {
562+
Mutex::ScopedLock lock(*that.mutex_);
563+
562564
pkey_.reset(that.get());
563565

564566
if (pkey_)

src/crypto/crypto_keys.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ struct PrivateKeyEncodingConfig : public AsymmetricKeyEncodingConfig {
7474
// use.
7575
class ManagedEVPPKey : public MemoryRetainer {
7676
public:
77-
ManagedEVPPKey() = default;
77+
ManagedEVPPKey() : mutex_(std::make_shared<Mutex>()) {}
7878
explicit ManagedEVPPKey(EVPKeyPointer&& pkey);
7979
ManagedEVPPKey(const ManagedEVPPKey& that);
8080
ManagedEVPPKey& operator=(const ManagedEVPPKey& that);

src/crypto/crypto_rsa.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -371,11 +371,11 @@ Maybe<bool> ExportJWKRsaKey(
371371

372372
// TODO(tniessen): Remove the "else" branch once we drop support for OpenSSL
373373
// versions older than 1.1.1e via FIPS / dynamic linking.
374-
RSA* rsa;
374+
const RSA* rsa;
375375
if (OpenSSL_version_num() >= 0x1010105fL) {
376376
rsa = EVP_PKEY_get0_RSA(m_pkey.get());
377377
} else {
378-
rsa = static_cast<RSA*>(EVP_PKEY_get0(m_pkey.get()));
378+
rsa = static_cast<const RSA*>(EVP_PKEY_get0(m_pkey.get()));
379379
}
380380
CHECK_NOT_NULL(rsa);
381381

@@ -520,11 +520,11 @@ Maybe<bool> GetRsaKeyDetail(
520520

521521
// TODO(tniessen): Remove the "else" branch once we drop support for OpenSSL
522522
// versions older than 1.1.1e via FIPS / dynamic linking.
523-
RSA* rsa;
523+
const RSA* rsa;
524524
if (OpenSSL_version_num() >= 0x1010105fL) {
525525
rsa = EVP_PKEY_get0_RSA(m_pkey.get());
526526
} else {
527-
rsa = static_cast<RSA*>(EVP_PKEY_get0(m_pkey.get()));
527+
rsa = static_cast<const RSA*>(EVP_PKEY_get0(m_pkey.get()));
528528
}
529529
CHECK_NOT_NULL(rsa);
530530

src/crypto/crypto_sig.cc

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@ namespace crypto {
2828
namespace {
2929
bool ValidateDSAParameters(EVP_PKEY* key) {
3030
/* Validate DSA2 parameters from FIPS 186-4 */
31+
#if OPENSSL_VERSION_MAJOR >= 3
32+
if (EVP_default_properties_is_fips_enabled(nullptr) &&
33+
EVP_PKEY_DSA == EVP_PKEY_base_id(key)) {
34+
#else
3135
if (FIPS_mode() && EVP_PKEY_DSA == EVP_PKEY_base_id(key)) {
32-
DSA* dsa = EVP_PKEY_get0_DSA(key);
36+
#endif
37+
const DSA* dsa = EVP_PKEY_get0_DSA(key);
3338
const BIGNUM* p;
3439
DSA_get0_pqg(dsa, &p, nullptr, nullptr);
3540
size_t L = BN_num_bits(p);
@@ -103,11 +108,11 @@ unsigned int GetBytesOfRS(const ManagedEVPPKey& pkey) {
103108
int bits, base_id = EVP_PKEY_base_id(pkey.get());
104109

105110
if (base_id == EVP_PKEY_DSA) {
106-
DSA* dsa_key = EVP_PKEY_get0_DSA(pkey.get());
111+
const DSA* dsa_key = EVP_PKEY_get0_DSA(pkey.get());
107112
// Both r and s are computed mod q, so their width is limited by that of q.
108113
bits = BN_num_bits(DSA_get0_q(dsa_key));
109114
} else if (base_id == EVP_PKEY_EC) {
110-
EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey.get());
115+
const EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey.get());
111116
const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key);
112117
bits = EC_GROUP_order_bits(ec_group);
113118
} else {
@@ -873,7 +878,7 @@ bool SignTraits::DeriveBits(
873878
case SignConfiguration::kSign: {
874879
size_t len;
875880
unsigned char* data = nullptr;
876-
if (IsOneShot(params.key->GetAsymmetricKey())) {
881+
if (IsOneShot(m_pkey)) {
877882
EVP_DigestSign(
878883
context.get(),
879884
nullptr,
@@ -905,10 +910,7 @@ bool SignTraits::DeriveBits(
905910
return false;
906911

907912
if (UseP1363Encoding(m_pkey, params.dsa_encoding)) {
908-
*out = ConvertSignatureToP1363(
909-
env,
910-
params.key->GetAsymmetricKey(),
911-
buf);
913+
*out = ConvertSignatureToP1363(env, m_pkey, buf);
912914
} else {
913915
buf.Resize(len);
914916
*out = std::move(buf);

0 commit comments

Comments
 (0)