Skip to content

Commit 00bffa6

Browse files
pmq20indutny
authored andcommitted
crypto: check for OpenSSL errors when signing
Errors might be injected into OpenSSL's error stack without the return value of `PEM_read_bio_PrivateKey` being set to `nullptr`. See the test of `test_bad_rsa_privkey.pem` for an example. PR-URL: #2342 Reviewed-By: Fedor Indutny <[email protected]>
1 parent 102939a commit 00bffa6

File tree

3 files changed

+37
-1
lines changed

3 files changed

+37
-1
lines changed

src/node_crypto.cc

+11-1
Original file line numberDiff line numberDiff line change
@@ -3585,7 +3585,11 @@ SignBase::Error Sign::SignFinal(const char* key_pem,
35853585
nullptr,
35863586
CryptoPemCallback,
35873587
const_cast<char*>(passphrase));
3588-
if (pkey == nullptr)
3588+
3589+
// Errors might be injected into OpenSSL's error stack
3590+
// without `pkey` being set to nullptr;
3591+
// cf. the test of `test_bad_rsa_privkey.pem` for an example.
3592+
if (pkey == nullptr || 0 != ERR_peek_error())
35893593
goto exit;
35903594

35913595
if (EVP_SignFinal(&mdctx_, *sig, sig_len, pkey))
@@ -3633,6 +3637,9 @@ void Sign::SignFinal(const FunctionCallbackInfo<Value>& args) {
36333637
md_len = 8192; // Maximum key size is 8192 bits
36343638
md_value = new unsigned char[md_len];
36353639

3640+
ClearErrorOnReturn clear_error_on_return;
3641+
(void) &clear_error_on_return; // Silence compiler warning.
3642+
36363643
Error err = sign->SignFinal(
36373644
buf,
36383645
buf_len,
@@ -3967,6 +3974,9 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
39673974
unsigned char* out_value = nullptr;
39683975
size_t out_len = 0;
39693976

3977+
ClearErrorOnReturn clear_error_on_return;
3978+
(void) &clear_error_on_return; // Silence compiler warning.
3979+
39703980
bool r = Cipher<operation, EVP_PKEY_cipher_init, EVP_PKEY_cipher>(
39713981
kbuf,
39723982
klen,
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEAz0ZHmXyxQSdWk6NF
3+
GRotTax0O94iHv843su0mOynV9QLvlAwMrUk9k4+/SwyLu0eE3iYsYgXstXi3t2u
4+
rDSIMwIDAQABAkAH4ag/Udp7m79TBdZOygwG9BPHYv7xJstGzYAkgHssf7Yd5ZuC
5+
hpKtBvWdPXZaAFbwF8NSisMl98Q/9zgB/q5BAiEA5zXuwMnwt4hE2YqzBDRFB4g9
6+
I+v+l1soy6x7Wdqo9esCIQDlf15qDb26uRDurBioE3IpZstWIIvLDdKqviZXKMs8
7+
2QIgWeC5QvA9RtsOCJLGLCg1fUwUmFYwzZ1+Kk6OVMuPSqkCIDIWFSXyL8kzoKVm
8+
O89axxyQCaqXWcsMDkEjVLzK82gpAiB7lzdDHr7MoMWwV2wC/heEFC2p0Rw4wg9j
9+
1V8QbL0Q0A==
10+
-----END RSA PRIVATE KEY-----

test/parallel/test-crypto.js

+16
Original file line numberDiff line numberDiff line change
@@ -124,5 +124,21 @@ assert.throws(function() {
124124
crypto.createSign('RSA-SHA256').update('test').sign(priv);
125125
}, /RSA_sign:digest too big for rsa key/);
126126

127+
assert.throws(function() {
128+
// The correct header inside `test_bad_rsa_privkey.pem` should have been
129+
// -----BEGIN PRIVATE KEY----- and -----END PRIVATE KEY-----
130+
// instead of
131+
// -----BEGIN RSA PRIVATE KEY----- and -----END RSA PRIVATE KEY-----
132+
// It is generated in this way:
133+
// $ openssl genrsa -out mykey.pem 512;
134+
// $ openssl pkcs8 -topk8 -inform PEM -outform PEM -in mykey.pem \
135+
// -out private_key.pem -nocrypt;
136+
// Then open private_key.pem and change its header and footer.
137+
var sha1_privateKey = fs.readFileSync(common.fixturesDir +
138+
'/test_bad_rsa_privkey.pem', 'ascii');
139+
// this would inject errors onto OpenSSL's error stack
140+
crypto.createSign('sha1').sign(sha1_privateKey);
141+
}, /asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag/);
142+
127143
// Make sure memory isn't released before being returned
128144
console.log(crypto.randomBytes(16));

0 commit comments

Comments
 (0)