From 4b4b71b7d4df268b3e74c3f434682399bc50ce69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= Date: Thu, 11 Oct 2018 19:56:49 +0200 Subject: [PATCH] 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. --- src/node_crypto.cc | 42 ++++++++++++++++++++---------------------- src/node_crypto.h | 3 +-- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 96f4cf2ba7076d..7b108fde29eccf 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -3517,36 +3517,38 @@ void Sign::SignUpdate(const FunctionCallbackInfo& args) { sign->CheckThrow(err); } -static int Node_SignFinal(EVPMDPointer&& mdctx, unsigned char* md, - unsigned int* sig_len, - const EVPKeyPointer& pkey, int padding, - int pss_salt_len) { +static MallocedBuffer Node_SignFinal(EVPMDPointer&& mdctx, + const EVPKeyPointer& pkey, + int padding, + int pss_salt_len) { unsigned char m[EVP_MAX_MD_SIZE]; unsigned int m_len; - *sig_len = 0; if (!EVP_DigestFinal_ex(mdctx.get(), m, &m_len)) - return 0; + return MallocedBuffer(); + + int signed_sig_len = EVP_PKEY_size(pkey.get()); + CHECK_GE(signed_sig_len, 0); + size_t sig_len = static_cast(signed_sig_len); + MallocedBuffer sig(sig_len); - size_t sltmp = static_cast(EVP_PKEY_size(pkey.get())); EVPKeyCtxPointer pkctx(EVP_PKEY_CTX_new(pkey.get(), nullptr)); if (pkctx && EVP_PKEY_sign_init(pkctx.get()) > 0 && ApplyRSAOptions(pkey, pkctx.get(), padding, pss_salt_len) && EVP_PKEY_CTX_set_signature_md(pkctx.get(), EVP_MD_CTX_md(mdctx.get())) > 0 && - EVP_PKEY_sign(pkctx.get(), md, &sltmp, m, m_len) > 0) { - *sig_len = sltmp; - return 1; + EVP_PKEY_sign(pkctx.get(), sig.data, &sig_len, m, m_len) > 0) { + return MallocedBuffer(sig.release(), sig_len); } - return 0; + + return MallocedBuffer(); } SignBase::Error Sign::SignFinal(const char* key_pem, int key_pem_len, const char* passphrase, - unsigned char* sig, - unsigned int* sig_len, + MallocedBuffer* buffer, int padding, int salt_len) { if (!mdctx_) @@ -3591,10 +3593,8 @@ SignBase::Error Sign::SignFinal(const char* key_pem, } #endif // NODE_FIPS_MODE - if (Node_SignFinal(std::move(mdctx), sig, sig_len, pkey, padding, salt_len)) - return kSignOk; - else - return kSignPrivateKey; + *buffer = Node_SignFinal(std::move(mdctx), pkey, padding, salt_len); + return buffer->is_empty() ? kSignPrivateKey : kSignOk; } @@ -3618,22 +3618,20 @@ void Sign::SignFinal(const FunctionCallbackInfo& args) { int salt_len = args[3].As()->Value(); ClearErrorOnReturn clear_error_on_return; - unsigned char md_value[8192]; - unsigned int md_len = sizeof(md_value); + MallocedBuffer sig; Error err = sign->SignFinal( buf, buf_len, len >= 2 && !args[1]->IsNull() ? *passphrase : nullptr, - md_value, - &md_len, + &sig, padding, salt_len); if (err != kSignOk) return sign->CheckThrow(err); Local rc = - Buffer::Copy(env, reinterpret_cast(md_value), md_len) + Buffer::New(env, reinterpret_cast(sig.data), sig.size) .ToLocalChecked(); args.GetReturnValue().Set(rc); } diff --git a/src/node_crypto.h b/src/node_crypto.h index f4afd2fdaf5758..eac9049228b213 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -521,8 +521,7 @@ class Sign : public SignBase { Error SignFinal(const char* key_pem, int key_pem_len, const char* passphrase, - unsigned char* sig, - unsigned int* sig_len, + MallocedBuffer* sig, int padding, int saltlen);