Skip to content

Commit b9787fd

Browse files
sam-githubBridgeAR
authored andcommitted
crypto: check for invalid chacha20-poly1305 IVs
IV lengths of 13, 14, 15, and 16 are invalid, but are not checked by OpenSSL. IV lengths of 17 or greater are also invalid, but they were already checked by OpenSSL. See: - openssl/openssl@f426625b6a - https://www.openssl.org/news/secadv/20190306.txt PR-URL: #26537 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
1 parent 667a402 commit b9787fd

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

Diff for: src/node_crypto.cc

+10
Original file line numberDiff line numberDiff line change
@@ -3660,6 +3660,16 @@ void CipherBase::InitIv(const char* cipher_type,
36603660
return env()->ThrowError("Invalid IV length");
36613661
}
36623662

3663+
if (EVP_CIPHER_nid(cipher) == NID_chacha20_poly1305) {
3664+
CHECK(has_iv);
3665+
// Check for invalid IV lengths, since OpenSSL does not under some
3666+
// conditions:
3667+
// https://www.openssl.org/news/secadv/20190306.txt.
3668+
if (iv_len > 12) {
3669+
return env()->ThrowError("Invalid IV length");
3670+
}
3671+
}
3672+
36633673
CommonInit(cipher_type, cipher, key, key_len, iv, iv_len, auth_tag_len);
36643674
}
36653675

Diff for: test/parallel/test-crypto-authenticated.js

+48
Original file line numberDiff line numberDiff line change
@@ -616,3 +616,51 @@ for (const test of TEST_CASES) {
616616
assert(plain.equals(plaintext));
617617
}
618618
}
619+
620+
621+
// Test chacha20-poly1305 rejects invalid IV lengths of 13, 14, 15, and 16 (a
622+
// length of 17 or greater was already rejected).
623+
// - https://www.openssl.org/news/secadv/20190306.txt
624+
{
625+
// Valid extracted from TEST_CASES, check that it detects IV tampering.
626+
const valid = {
627+
algo: 'chacha20-poly1305',
628+
key: '808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f',
629+
iv: '070000004041424344454647',
630+
plain: '4c616469657320616e642047656e746c656d656e206f662074686520636c6173' +
631+
'73206f66202739393a204966204920636f756c64206f6666657220796f75206f' +
632+
'6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73' +
633+
'637265656e20776f756c642062652069742e',
634+
plainIsHex: true,
635+
aad: '50515253c0c1c2c3c4c5c6c7',
636+
ct: 'd31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5' +
637+
'a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e06' +
638+
'0b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fa' +
639+
'b324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d265' +
640+
'86cec64b6116',
641+
tag: '1ae10b594f09e26a7e902ecbd0600691',
642+
tampered: false,
643+
};
644+
645+
// Invalid IV lengths should be detected:
646+
// - 12 and below are valid.
647+
// - 13-16 are not detected as invalid by some OpenSSL versions.
648+
check(13);
649+
check(14);
650+
check(15);
651+
check(16);
652+
// - 17 and above were always detected as invalid by OpenSSL.
653+
check(17);
654+
655+
function check(ivLength) {
656+
const prefix = ivLength - valid.iv.length / 2;
657+
assert.throws(() => crypto.createCipheriv(
658+
valid.algo,
659+
Buffer.from(valid.key, 'hex'),
660+
Buffer.from(H(prefix) + valid.iv, 'hex'),
661+
{ authTagLength: valid.tag.length / 2 }
662+
), errMessages.length, `iv length ${ivLength} was not rejected`);
663+
664+
function H(length) { return '00'.repeat(length); }
665+
}
666+
}

0 commit comments

Comments
 (0)