]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
AEAD: reject late AAD in ChaCha20-Poly1305 after plaintext update
authorDaniel Kubec <kubec@openssl.foundation>
Tue, 23 Jun 2026 12:10:45 +0000 (14:10 +0200)
committerNorbert Pocs <norbertp@openssl.org>
Thu, 25 Jun 2026 07:01:39 +0000 (09:01 +0200)
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)

providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c
test/evp_extra_test.c

index 47f4c3cb68ce9fd00c1c43061625908dfcd587c9..ffd2ee744cd88b5db2ff4241e96682cf9e30abd2 100644 (file)
@@ -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;
index b0c37e476e60b8db6e9a221d34e374c6e0be9157..236991f1f57ba72edf76e4a82902b98038093809 100644 (file)
@@ -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);