From: Daniel Kubec Date: Tue, 23 Jun 2026 12:10:45 +0000 (+0200) Subject: AEAD: reject late AAD in ChaCha20-Poly1305 after plaintext update X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fc972e592ede98d7a51e1a25e4509bb9086f1f4e;p=thirdparty%2Fopenssl.git 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 Reviewed-by: Bob Beck 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 47f4c3cb68c..ffd2ee744cd 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 b0c37e476e6..236991f1f57 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);