Skip to content

Commit d192516

Browse files
bnoordhuistargos
authored andcommittedApr 22, 2020
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 <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de>
1 parent 191cde0 commit d192516

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
@@ -5011,6 +5011,7 @@ template <PublicKeyCipher::Operation operation,
50115011
PublicKeyCipher::EVP_PKEY_cipher_init_t EVP_PKEY_cipher_init,
50125012
PublicKeyCipher::EVP_PKEY_cipher_t EVP_PKEY_cipher>
50135013
void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
5014+
MarkPopErrorOnReturn mark_pop_error_on_return;
50145015
Environment* env = Environment::GetCurrent(args);
50155016

50165017
unsigned int offset = 0;
@@ -5041,8 +5042,6 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
50415042

50425043
AllocatedBuffer out;
50435044

5044-
ClearErrorOnReturn clear_error_on_return;
5045-
50465045
bool r = Cipher<operation, EVP_PKEY_cipher_init, EVP_PKEY_cipher>(
50475046
env,
50485047
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)
Please sign in to comment.