Skip to content

Commit 9dfb2d1

Browse files
committed
crypto: warn if counter mode used in createCipher
`crypto.createCipher()` sets the fixed IV derived from password and it leads to a security risk of nonce reuse when counter mode is used. A warning is emitted when CTR, GCM or CCM is used in `crypto.createCipher()` to notify users to avoid nonce reuse. Fixes: #13801 PR-URL: #13821 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Fedor Indutny <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Tobias Nießen <[email protected]>
1 parent 70664bf commit 9dfb2d1

File tree

3 files changed

+17
-1
lines changed

3 files changed

+17
-1
lines changed

doc/api/crypto.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1198,7 +1198,11 @@ rapidly.
11981198
In line with OpenSSL's recommendation to use pbkdf2 instead of
11991199
[`EVP_BytesToKey`][] it is recommended that developers derive a key and IV on
12001200
their own using [`crypto.pbkdf2()`][] and to use [`crypto.createCipheriv()`][]
1201-
to create the `Cipher` object.
1201+
to create the `Cipher` object. Users should not use ciphers with counter mode
1202+
(e.g. CTR, GCM or CCM) in `crypto.createCipher()`. A warning is emitted when
1203+
they are used in order to avoid the risk of IV reuse that causes
1204+
vulnerabilities. For the case when IV is reused in GCM, see [Nonce-Disrespecting
1205+
Adversaries][] for details.
12021206

12031207
### crypto.createCipheriv(algorithm, key, iv)
12041208
- `algorithm` {string}
@@ -2240,6 +2244,7 @@ the `crypto`, `tls`, and `https` modules and are generally specific to OpenSSL.
22402244
[HTML5's `keygen` element]: http://www.w3.org/TR/html5/forms.html#the-keygen-element
22412245
[NIST SP 800-131A]: http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf
22422246
[NIST SP 800-132]: http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf
2247+
[Nonce-Disrespecting Adversaries]: https://github.com/nonce-disrespect/nonce-disrespect
22432248
[OpenSSL's SPKAC implementation]: https://www.openssl.org/docs/man1.0.2/apps/spkac.html
22442249
[RFC 2412]: https://www.rfc-editor.org/rfc/rfc2412.txt
22452250
[RFC 3526]: https://www.rfc-editor.org/rfc/rfc3526.txt

src/node_crypto.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3340,6 +3340,14 @@ void CipherBase::Init(const char* cipher_type,
33403340
EVP_CIPHER_CTX_init(&ctx_);
33413341
const bool encrypt = (kind_ == kCipher);
33423342
EVP_CipherInit_ex(&ctx_, cipher, nullptr, nullptr, nullptr, encrypt);
3343+
3344+
int mode = EVP_CIPHER_CTX_mode(&ctx_);
3345+
if (encrypt && (mode == EVP_CIPH_CTR_MODE || mode == EVP_CIPH_GCM_MODE ||
3346+
mode == EVP_CIPH_CCM_MODE)) {
3347+
ProcessEmitWarning(env(), "Use Cipheriv for counter mode of %s",
3348+
cipher_type);
3349+
}
3350+
33433351
if (!EVP_CIPHER_CTX_set_key_length(&ctx_, key_len)) {
33443352
EVP_CIPHER_CTX_cleanup(&ctx_);
33453353
return env()->ThrowError("Invalid key length");

test/parallel/test-crypto-cipher-decipher.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ testCipher2(Buffer.from('0123456789abcdef'));
155155
const aadbuf = Buffer.from('aadbuf');
156156
const data = Buffer.from('test-crypto-cipher-decipher');
157157

158+
common.expectWarning('Warning',
159+
'Use Cipheriv for counter mode of aes-256-gcm');
160+
158161
const cipher = crypto.createCipher('aes-256-gcm', key);
159162
cipher.setAAD(aadbuf);
160163
cipher.setAutoPadding();

0 commit comments

Comments
 (0)