Skip to content

Commit dc0cdaa

Browse files
bnoordhuisRafaelGSS
authored andcommitted
crypto: ensure auth tag set for chacha20-poly1305
Because OpenSSL v1.x doesn't do that by itself (OpenSSL v3.x does.) Fixes: #45874 PR-URL: #46185 Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Richard Lau <rlau@redhat.com> Reviewed-By: Filip Skokan <panva.ip@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent d3d62ed commit dc0cdaa

2 files changed

Lines changed: 39 additions & 0 deletions

File tree

‎src/crypto/crypto_cipher.cc‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,14 @@ bool CipherBase::Final(std::unique_ptr<BackingStore>* out) {
901901
if (kind_ == kDecipher && IsSupportedAuthenticatedMode(ctx_.get()))
902902
MaybePassAuthTagToOpenSSL();
903903

904+
// OpenSSL v1.x doesn't verify the presence of the auth tag so do
905+
// it ourselves, see https://github.com/nodejs/node/issues/45874.
906+
if (OPENSSL_VERSION_NUMBER < 0x30000000L && kind_ == kDecipher &&
907+
NID_chacha20_poly1305 == EVP_CIPHER_CTX_nid(ctx_.get()) &&
908+
auth_tag_state_ != kAuthTagPassedToOpenSSL) {
909+
returnfalse;
910+
}
911+
904912
// In CCM mode, final() only checks whether authentication failed in update().
905913
// EVP_CipherFinal_ex must not be called and will fail.
906914
bool ok;

‎test/parallel/test-crypto-authenticated.js‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,3 +786,34 @@ for (const test of TEST_CASES) {
786786
assert.strictEqual(plaintext.toString('hex'),testCase.plain);
787787
}
788788
}
789+
790+
// https://github.com/nodejs/node/issues/45874
791+
{
792+
constrfcTestCases=TEST_CASES.filter(({ algo, tampered })=>{
793+
returnalgo==='chacha20-poly1305'&&tampered===false;
794+
});
795+
assert.strictEqual(rfcTestCases.length,1);
796+
797+
const[testCase]=rfcTestCases;
798+
constkey=Buffer.from(testCase.key,'hex');
799+
constiv=Buffer.from(testCase.iv,'hex');
800+
constaad=Buffer.from(testCase.aad,'hex');
801+
constopt={authTagLength: 16};
802+
803+
constcipher=crypto.createCipheriv('chacha20-poly1305',key,iv,opt);
804+
constciphertext=Buffer.concat([
805+
cipher.setAAD(aad).update(testCase.plain,'hex'),
806+
cipher.final(),
807+
]);
808+
constauthTag=cipher.getAuthTag();
809+
810+
assert.strictEqual(ciphertext.toString('hex'),testCase.ct);
811+
assert.strictEqual(authTag.toString('hex'),testCase.tag);
812+
813+
constdecipher=crypto.createDecipheriv('chacha20-poly1305',key,iv,opt);
814+
decipher.setAAD(aad).update(ciphertext);
815+
816+
assert.throws(()=>{
817+
decipher.final();
818+
},/Unsupportedstateorunabletoauthenticatedata/);
819+
}

0 commit comments

Comments
 (0)