diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 52c7ebe71cf64a..08d14e96975812 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -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} @@ -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 diff --git a/src/node_crypto.cc b/src/node_crypto.cc index e935490971c5b2..1fa522d521acec 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -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"); diff --git a/test/parallel/test-crypto-cipher-decipher.js b/test/parallel/test-crypto-cipher-decipher.js index 0104341653f7f5..336ab3a07ba42e 100644 --- a/test/parallel/test-crypto-cipher-decipher.js +++ b/test/parallel/test-crypto-cipher-decipher.js @@ -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();