Skip to content

Commit

Permalink
crypto: warn if counter mode used in createCipher
Browse files Browse the repository at this point in the history
`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 <info@bnoordhuis.nl>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
  • Loading branch information
shigeki authored and MylesBorins committed Sep 10, 2017
1 parent 35bd43f commit f20134b
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 1 deletion.
7 changes: 6 additions & 1 deletion doc/api/crypto.md
Original file line number Diff line number Diff line change
Expand Up @@ -1201,7 +1201,11 @@ rapidly.
In line with OpenSSL's recommendation to use pbkdf2 instead of
[`EVP_BytesToKey`][] it is recommended that developers derive a key and IV on
their own using [`crypto.pbkdf2()`][] and to use [`crypto.createCipheriv()`][]
to create the `Cipher` object.
to create the `Cipher` object. Users should not use ciphers with counter mode
(e.g. CTR, GCM or CCM) in `crypto.createCipher()`. A warning is emitted when
they are used in order to avoid the risk of IV reuse that causes
vulnerabilities. For the case when IV is reused in GCM, see [Nonce-Disrespecting
Adversaries][] for details.

### crypto.createCipheriv(algorithm, key, iv[, options])
- `algorithm` {string}
Expand Down Expand Up @@ -2271,6 +2275,7 @@ the `crypto`, `tls`, and `https` modules and are generally specific to OpenSSL.
[HTML5's `keygen` element]: http://www.w3.org/TR/html5/forms.html#the-keygen-element
[NIST SP 800-131A]: http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf
[NIST SP 800-132]: http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf
[Nonce-Disrespecting Adversaries]: https://github.com/nonce-disrespect/nonce-disrespect
[OpenSSL's SPKAC implementation]: https://www.openssl.org/docs/man1.0.2/apps/spkac.html
[RFC 2412]: https://www.rfc-editor.org/rfc/rfc2412.txt
[RFC 3526]: https://www.rfc-editor.org/rfc/rfc3526.txt
Expand Down
8 changes: 8 additions & 0 deletions src/node_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3341,6 +3341,14 @@ void CipherBase::Init(const char* cipher_type,
EVP_CIPHER_CTX_init(&ctx_);
const bool encrypt = (kind_ == kCipher);
EVP_CipherInit_ex(&ctx_, cipher, nullptr, nullptr, nullptr, encrypt);

int mode = EVP_CIPHER_CTX_mode(&ctx_);
if (encrypt && (mode == EVP_CIPH_CTR_MODE || mode == EVP_CIPH_GCM_MODE ||
mode == EVP_CIPH_CCM_MODE)) {
ProcessEmitWarning(env(), "Use Cipheriv for counter mode of %s",
cipher_type);
}

if (!EVP_CIPHER_CTX_set_key_length(&ctx_, key_len)) {
EVP_CIPHER_CTX_cleanup(&ctx_);
return env()->ThrowError("Invalid key length");
Expand Down
3 changes: 3 additions & 0 deletions test/parallel/test-crypto-cipher-decipher.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ testCipher2(Buffer.from('0123456789abcdef'));
const aadbuf = Buffer.from('aadbuf');
const data = Buffer.from('test-crypto-cipher-decipher');

common.expectWarning('Warning',
'Use Cipheriv for counter mode of aes-256-gcm');

const cipher = crypto.createCipher('aes-256-gcm', key);
cipher.setAAD(aadbuf);
cipher.setAutoPadding();
Expand Down

0 comments on commit f20134b

Please sign in to comment.