Skip to content

Commit

Permalink
crypto: avoid taking ownership of OpenSSL objects
Browse files Browse the repository at this point in the history
It is often unnecessary to obtain (shared) ownership of OpenSSL objects
in this code, and it generally is more costly to do so as opposed to
just obtaining a pointer to the respective OpenSSL object. Therefore,
this patch replaces various OpenSSL function calls that take ownership
with ones that do not.

Refs: #53436
PR-URL: #53460
Reviewed-By: Daniel Lemire <[email protected]>
Reviewed-By: Rafael Gonzaga <[email protected]>
  • Loading branch information
tniessen authored and marco-ippolito committed Aug 19, 2024
1 parent 57b8b8e commit ceb1d5e
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 34 deletions.
8 changes: 0 additions & 8 deletions src/crypto/crypto_common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,6 @@
#include <string>
#include <unordered_map>

// Some OpenSSL 1.1.1 functions unnecessarily operate on and return non-const
// pointers, whereas the same functions in OpenSSL 3 use const pointers.
#if OPENSSL_VERSION_MAJOR >= 3
#define OSSL3_CONST const
#else
#define OSSL3_CONST
#endif

namespace node {

using v8::Array;
Expand Down
8 changes: 8 additions & 0 deletions src/crypto/crypto_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@

#include <string>

// Some OpenSSL 1.1.1 functions unnecessarily operate on and return non-const
// pointers, whereas the same functions in OpenSSL 3 use const pointers.
#if OPENSSL_VERSION_MAJOR >= 3
#define OSSL3_CONST const
#else
#define OSSL3_CONST
#endif

namespace node {
namespace crypto {

Expand Down
52 changes: 26 additions & 26 deletions src/crypto/crypto_keys.cc
Original file line number Diff line number Diff line change
Expand Up @@ -289,11 +289,9 @@ MaybeLocal<Value> BIOToStringOrBuffer(
}
}


MaybeLocal<Value> WritePrivateKey(
Environment* env,
EVP_PKEY* pkey,
const PrivateKeyEncodingConfig& config) {
MaybeLocal<Value> WritePrivateKey(Environment* env,
OSSL3_CONST EVP_PKEY* pkey,
const PrivateKeyEncodingConfig& config) {
BIOPointer bio(BIO_new(BIO_s_mem()));
CHECK(bio);

Expand Down Expand Up @@ -327,20 +325,21 @@ MaybeLocal<Value> WritePrivateKey(
// PKCS#1 is only permitted for RSA keys.
CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_RSA);

RSAPointer rsa(EVP_PKEY_get1_RSA(pkey));
OSSL3_CONST RSA* rsa = EVP_PKEY_get0_RSA(pkey);
if (config.format_ == kKeyFormatPEM) {
// Encode PKCS#1 as PEM.
err = PEM_write_bio_RSAPrivateKey(
bio.get(), rsa.get(),
config.cipher_,
reinterpret_cast<unsigned char*>(pass),
pass_len,
nullptr, nullptr) != 1;
err = PEM_write_bio_RSAPrivateKey(bio.get(),
rsa,
config.cipher_,
reinterpret_cast<unsigned char*>(pass),
pass_len,
nullptr,
nullptr) != 1;
} else {
// Encode PKCS#1 as DER. This does not permit encryption.
CHECK_EQ(config.format_, kKeyFormatDER);
CHECK_NULL(config.cipher_);
err = i2d_RSAPrivateKey_bio(bio.get(), rsa.get()) != 1;
err = i2d_RSAPrivateKey_bio(bio.get(), rsa) != 1;
}
} else if (encoding_type == kKeyEncodingPKCS8) {
if (config.format_ == kKeyFormatPEM) {
Expand All @@ -367,20 +366,21 @@ MaybeLocal<Value> WritePrivateKey(
// SEC1 is only permitted for EC keys.
CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_EC);

ECKeyPointer ec_key(EVP_PKEY_get1_EC_KEY(pkey));
OSSL3_CONST EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey);
if (config.format_ == kKeyFormatPEM) {
// Encode SEC1 as PEM.
err = PEM_write_bio_ECPrivateKey(
bio.get(), ec_key.get(),
config.cipher_,
reinterpret_cast<unsigned char*>(pass),
pass_len,
nullptr, nullptr) != 1;
err = PEM_write_bio_ECPrivateKey(bio.get(),
ec_key,
config.cipher_,
reinterpret_cast<unsigned char*>(pass),
pass_len,
nullptr,
nullptr) != 1;
} else {
// Encode SEC1 as DER. This does not permit encryption.
CHECK_EQ(config.format_, kKeyFormatDER);
CHECK_NULL(config.cipher_);
err = i2d_ECPrivateKey_bio(bio.get(), ec_key.get()) != 1;
err = i2d_ECPrivateKey_bio(bio.get(), ec_key) != 1;
}
}

Expand All @@ -391,20 +391,20 @@ MaybeLocal<Value> WritePrivateKey(
return BIOToStringOrBuffer(env, bio.get(), config.format_);
}

bool WritePublicKeyInner(EVP_PKEY* pkey,
bool WritePublicKeyInner(OSSL3_CONST EVP_PKEY* pkey,
const BIOPointer& bio,
const PublicKeyEncodingConfig& config) {
if (config.type_.ToChecked() == kKeyEncodingPKCS1) {
// PKCS#1 is only valid for RSA keys.
CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_RSA);
RSAPointer rsa(EVP_PKEY_get1_RSA(pkey));
OSSL3_CONST RSA* rsa = EVP_PKEY_get0_RSA(pkey);
if (config.format_ == kKeyFormatPEM) {
// Encode PKCS#1 as PEM.
return PEM_write_bio_RSAPublicKey(bio.get(), rsa.get()) == 1;
return PEM_write_bio_RSAPublicKey(bio.get(), rsa) == 1;
} else {
// Encode PKCS#1 as DER.
CHECK_EQ(config.format_, kKeyFormatDER);
return i2d_RSAPublicKey_bio(bio.get(), rsa.get()) == 1;
return i2d_RSAPublicKey_bio(bio.get(), rsa) == 1;
}
} else {
CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSPKI);
Expand All @@ -420,7 +420,7 @@ bool WritePublicKeyInner(EVP_PKEY* pkey,
}

MaybeLocal<Value> WritePublicKey(Environment* env,
EVP_PKEY* pkey,
OSSL3_CONST EVP_PKEY* pkey,
const PublicKeyEncodingConfig& config) {
BIOPointer bio(BIO_new(BIO_s_mem()));
CHECK(bio);
Expand Down

0 comments on commit ceb1d5e

Please sign in to comment.