Commit fc972e592e for openssl.org
commit fc972e592ede98d7a51e1a25e4509bb9086f1f4e
Author: Daniel Kubec <kubec@openssl.foundation>
Date: Tue Jun 23 14:10:45 2026 +0200
AEAD: reject late AAD in ChaCha20-Poly1305 after plaintext update
Align behavior with AES GCM, which already rejects this misuse with a hard
error, by tracking whether plaintext processing has started and returning an
error if AAD is supplied afterwards.
Fixes #31188
Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
Reviewed-by: Bob Beck <beck@openssl.org>
MergeDate: Thu Jun 25 07:01:44 2026
(Merged from https://github.com/openssl/openssl/pull/31673)
diff --git a/providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c b/providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c
index 47f4c3cb68..ffd2ee744c 100644
--- a/providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c
+++ b/providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c
@@ -301,6 +301,8 @@ static int chacha20_poly1305_aead_cipher(PROV_CIPHER_CTX *bctx,
if (in != NULL) { /* aad or text */
if (out == NULL) { /* aad */
+ if (ctx->len.text != 0)
+ goto err;
Poly1305_Update(poly, in, inl);
ctx->len.aad += inl;
ctx->aad = 1;
diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c
index b0c37e476e..236991f1f5 100644
--- a/test/evp_extra_test.c
+++ b/test/evp_extra_test.c
@@ -7636,6 +7636,30 @@ err:
return ret;
}
+#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
+static int test_chacha20_poly1305_late_aad(void)
+{
+ EVP_CIPHER_CTX *ctx = NULL;
+ EVP_CIPHER *c = NULL;
+ unsigned char key[32] = { 0 };
+ unsigned char iv[12] = { 0 };
+ unsigned char aad[4] = "aad";
+ unsigned char msg[8] = "message";
+ unsigned char out[32];
+ int len, test;
+
+ test = TEST_ptr(ctx = EVP_CIPHER_CTX_new())
+ && TEST_ptr(c = EVP_CIPHER_fetch(testctx, "ChaCha20-Poly1305", testpropq))
+ && TEST_true(EVP_EncryptInit_ex2(ctx, c, key, iv, NULL))
+ && TEST_true(EVP_EncryptUpdate(ctx, NULL, &len, aad, sizeof(aad)))
+ && TEST_true(EVP_EncryptUpdate(ctx, out, &len, msg, sizeof(msg)))
+ && TEST_false(EVP_EncryptUpdate(ctx, NULL, &len, aad, sizeof(aad)));
+
+ EVP_CIPHER_free(c);
+ EVP_CIPHER_CTX_free(ctx);
+ return test;
+}
+#endif
/*
* AES-SIV reuse-without-rekey:
* msg1: legit non-empty CT, tag verifies, final_ret=0
@@ -8870,6 +8894,7 @@ int setup_tests(void)
#endif
#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
ADD_TEST(test_decrypt_null_chunks);
+ ADD_TEST(test_chacha20_poly1305_late_aad);
#endif
#ifndef OPENSSL_NO_DH
ADD_TEST(test_DH_priv_pub);