From c0c94a2dc6e1a70cf5c4b4d09ed330b00effd3e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= Date: Mon, 3 Jun 2024 13:08:47 +0000 Subject: [PATCH] crypto: fix propagation of "memory limit exceeded" When we throw ERR_CRYPTO_INVALID_SCRYPT_PARAMS after a call to EVP_PBE_scrypt, check if OpenSSL reported an error and if so, append the OpenSSL error message to the default generic error message. In particular, this catches cases when `maxmem` is not sufficient, which otherwise is difficult to identify because our documentation only provides an approximation of the required `maxmem` value. Fixes: https://github.com/nodejs/node/issues/53291 --- src/crypto/crypto_scrypt.cc | 12 +++++++++++- test/parallel/test-crypto-scrypt.js | 3 ++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/crypto/crypto_scrypt.cc b/src/crypto/crypto_scrypt.cc index 4dae07f13604d4..a262a2be96d7c3 100644 --- a/src/crypto/crypto_scrypt.cc +++ b/src/crypto/crypto_scrypt.cc @@ -104,7 +104,17 @@ Maybe ScryptTraits::AdditionalConfig( params->maxmem, nullptr, 0) != 1) { - THROW_ERR_CRYPTO_INVALID_SCRYPT_PARAMS(env); + // Do not use CryptoErrorStore or ThrowCryptoError here in order to maintain + // backward compatibility with ERR_CRYPTO_INVALID_SCRYPT_PARAMS. + uint32_t err = ERR_peek_last_error(); + if (err != 0) { + char buf[256]; + ERR_error_string_n(err, buf, sizeof(buf)); + THROW_ERR_CRYPTO_INVALID_SCRYPT_PARAMS( + env, "Invalid scrypt params: %s", buf); + } else { + THROW_ERR_CRYPTO_INVALID_SCRYPT_PARAMS(env); + } return Nothing(); } diff --git a/test/parallel/test-crypto-scrypt.js b/test/parallel/test-crypto-scrypt.js index 73bf0217b1fb67..61bd65fc92678c 100644 --- a/test/parallel/test-crypto-scrypt.js +++ b/test/parallel/test-crypto-scrypt.js @@ -178,7 +178,8 @@ for (const options of bad) { for (const options of toobig) { const expected = { - message: /Invalid scrypt param/ + message: /Invalid scrypt params:.*memory limit exceeded/, + code: 'ERR_CRYPTO_INVALID_SCRYPT_PARAMS', }; assert.throws(() => crypto.scrypt('pass', 'salt', 1, options, () => {}), expected);