Skip to content

Commit 4b4b71b

Browse files
committed
crypto: reduce memory usage of SignFinal
The fixed-size buffer on the stack is unnecessary and way too large for most applications. This change removes it and allocates the required memory directly instead of copying into heap later.
1 parent bcbb937 commit 4b4b71b

File tree

2 files changed

+21
-24
lines changed

2 files changed

+21
-24
lines changed

src/node_crypto.cc

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3517,36 +3517,38 @@ void Sign::SignUpdate(const FunctionCallbackInfo<Value>& args) {
35173517
sign->CheckThrow(err);
35183518
}
35193519

3520-
static int Node_SignFinal(EVPMDPointer&& mdctx, unsigned char* md,
3521-
unsigned int* sig_len,
3522-
const EVPKeyPointer& pkey, int padding,
3523-
int pss_salt_len) {
3520+
static MallocedBuffer<unsigned char> Node_SignFinal(EVPMDPointer&& mdctx,
3521+
const EVPKeyPointer& pkey,
3522+
int padding,
3523+
int pss_salt_len) {
35243524
unsigned char m[EVP_MAX_MD_SIZE];
35253525
unsigned int m_len;
35263526

3527-
*sig_len = 0;
35283527
if (!EVP_DigestFinal_ex(mdctx.get(), m, &m_len))
3529-
return 0;
3528+
return MallocedBuffer<unsigned char>();
3529+
3530+
int signed_sig_len = EVP_PKEY_size(pkey.get());
3531+
CHECK_GE(signed_sig_len, 0);
3532+
size_t sig_len = static_cast<size_t>(signed_sig_len);
3533+
MallocedBuffer<unsigned char> sig(sig_len);
35303534

3531-
size_t sltmp = static_cast<size_t>(EVP_PKEY_size(pkey.get()));
35323535
EVPKeyCtxPointer pkctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
35333536
if (pkctx &&
35343537
EVP_PKEY_sign_init(pkctx.get()) > 0 &&
35353538
ApplyRSAOptions(pkey, pkctx.get(), padding, pss_salt_len) &&
35363539
EVP_PKEY_CTX_set_signature_md(pkctx.get(),
35373540
EVP_MD_CTX_md(mdctx.get())) > 0 &&
3538-
EVP_PKEY_sign(pkctx.get(), md, &sltmp, m, m_len) > 0) {
3539-
*sig_len = sltmp;
3540-
return 1;
3541+
EVP_PKEY_sign(pkctx.get(), sig.data, &sig_len, m, m_len) > 0) {
3542+
return MallocedBuffer<unsigned char>(sig.release(), sig_len);
35413543
}
3542-
return 0;
3544+
3545+
return MallocedBuffer<unsigned char>();
35433546
}
35443547

35453548
SignBase::Error Sign::SignFinal(const char* key_pem,
35463549
int key_pem_len,
35473550
const char* passphrase,
3548-
unsigned char* sig,
3549-
unsigned int* sig_len,
3551+
MallocedBuffer<unsigned char>* buffer,
35503552
int padding,
35513553
int salt_len) {
35523554
if (!mdctx_)
@@ -3591,10 +3593,8 @@ SignBase::Error Sign::SignFinal(const char* key_pem,
35913593
}
35923594
#endif // NODE_FIPS_MODE
35933595

3594-
if (Node_SignFinal(std::move(mdctx), sig, sig_len, pkey, padding, salt_len))
3595-
return kSignOk;
3596-
else
3597-
return kSignPrivateKey;
3596+
*buffer = Node_SignFinal(std::move(mdctx), pkey, padding, salt_len);
3597+
return buffer->is_empty() ? kSignPrivateKey : kSignOk;
35983598
}
35993599

36003600

@@ -3618,22 +3618,20 @@ void Sign::SignFinal(const FunctionCallbackInfo<Value>& args) {
36183618
int salt_len = args[3].As<Int32>()->Value();
36193619

36203620
ClearErrorOnReturn clear_error_on_return;
3621-
unsigned char md_value[8192];
3622-
unsigned int md_len = sizeof(md_value);
3621+
MallocedBuffer<unsigned char> sig;
36233622

36243623
Error err = sign->SignFinal(
36253624
buf,
36263625
buf_len,
36273626
len >= 2 && !args[1]->IsNull() ? *passphrase : nullptr,
3628-
md_value,
3629-
&md_len,
3627+
&sig,
36303628
padding,
36313629
salt_len);
36323630
if (err != kSignOk)
36333631
return sign->CheckThrow(err);
36343632

36353633
Local<Object> rc =
3636-
Buffer::Copy(env, reinterpret_cast<char*>(md_value), md_len)
3634+
Buffer::New(env, reinterpret_cast<char*>(sig.data), sig.size)
36373635
.ToLocalChecked();
36383636
args.GetReturnValue().Set(rc);
36393637
}

src/node_crypto.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -521,8 +521,7 @@ class Sign : public SignBase {
521521
Error SignFinal(const char* key_pem,
522522
int key_pem_len,
523523
const char* passphrase,
524-
unsigned char* sig,
525-
unsigned int* sig_len,
524+
MallocedBuffer<unsigned char>* sig,
526525
int padding,
527526
int saltlen);
528527

0 commit comments

Comments
 (0)