Skip to content

Commit 2c32e59

Browse files
bnoordhuisaddaleax
authored andcommitted
crypto: clear openssl error stack after en/decrypt
The publicEncrypt/privateDecrypt/etc. family of functions didn't clear OpenSSL's error stack on early return. Notably, trying to use an encrypted key with the wrong passphrase left an error on the stack that made subsequent encrypt or decrypt operations fail, even with an unencrypted key. Fixes: #32240 PR-URL: #32248 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Richard Lau <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Tobias Nießen <[email protected]>
1 parent e2b08f0 commit 2c32e59

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

src/node_crypto.cc

+1-2
Original file line numberDiff line numberDiff line change
@@ -5026,6 +5026,7 @@ template <PublicKeyCipher::Operation operation,
50265026
PublicKeyCipher::EVP_PKEY_cipher_init_t EVP_PKEY_cipher_init,
50275027
PublicKeyCipher::EVP_PKEY_cipher_t EVP_PKEY_cipher>
50285028
void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
5029+
MarkPopErrorOnReturn mark_pop_error_on_return;
50295030
Environment* env = Environment::GetCurrent(args);
50305031

50315032
unsigned int offset = 0;
@@ -5056,8 +5057,6 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
50565057

50575058
AllocatedBuffer out;
50585059

5059-
ClearErrorOnReturn clear_error_on_return;
5060-
50615060
bool r = Cipher<operation, EVP_PKEY_cipher_init, EVP_PKEY_cipher>(
50625061
env,
50635062
pkey,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
'use strict';
2+
3+
// Verify that privateDecrypt() does not leave an error on the
4+
// openssl error stack that is visible to subsequent operations.
5+
6+
const common = require('../common');
7+
if (!common.hasCrypto)
8+
common.skip('missing crypto');
9+
10+
const assert = require('assert');
11+
const {
12+
generateKeyPairSync,
13+
publicEncrypt,
14+
privateDecrypt,
15+
} = require('crypto');
16+
17+
const pair = generateKeyPairSync('rsa', { modulusLength: 512 });
18+
19+
const expected = Buffer.from('shibboleth');
20+
const encrypted = publicEncrypt(pair.publicKey, expected);
21+
22+
const pkey = pair.privateKey.export({ type: 'pkcs1', format: 'pem' });
23+
const pkeyEncrypted =
24+
pair.privateKey.export({
25+
type: 'pkcs1',
26+
format: 'pem',
27+
cipher: 'aes128',
28+
passphrase: 'secret',
29+
});
30+
31+
function decrypt(key) {
32+
const decrypted = privateDecrypt(key, encrypted);
33+
assert.deepStrictEqual(decrypted, expected);
34+
}
35+
36+
decrypt(pkey);
37+
assert.throws(() => decrypt(pkeyEncrypted), { code: 'ERR_MISSING_PASSPHRASE' });
38+
decrypt(pkey); // Should not throw.

0 commit comments

Comments
 (0)