Commit 2248a56029 for openssl.org

commit 2248a5602982239b5b4bf17ddf5f1d3682c2db21
Author: Danny Nichols <dtn7890@rit.edu>
Date:   Tue Nov 10 16:56:12 2026 -0500

    test: migrate test_evp_aead_tag_reject from evp_extra_test.c to evp_aead_test.c

    Reviewed-by: Neil Horman <nhorman@openssl.org>
    Reviewed-by: Andrew Dinh <andrewd@openssl.org>
    Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
    Merge-date: Thu Nov 12 11:26:06 2026
    Merged-from: https://github.com/openssl/openssl/pull/32952

diff --git a/test/evp_aead_test.c b/test/evp_aead_test.c
index 54b870c426..b024f76875 100644
--- a/test/evp_aead_test.c
+++ b/test/evp_aead_test.c
@@ -1579,6 +1579,91 @@ static int test_aes_gcm_ivlen_change_cve_2023_5363(void)
             gcm_ct, sizeof(gcm_ct), gcm_tag, sizeof(gcm_tag));
 }

+static int test_evp_aead_tag_reject(int idx)
+{
+    const AEAD_DATA *info = &aead_list[idx];
+    EVP_CIPHER_CTX *ctx_ct = NULL;
+    EVP_CIPHER_CTX *ctx_aad = NULL;
+    EVP_CIPHER_CTX *ctx_ct_aad = NULL;
+    EVP_CIPHER_CTX *ctx_c_ct = NULL;
+    unsigned char key[EVP_MAX_KEY_LENGTH];
+    unsigned char iv[EVP_MAX_IV_LENGTH];
+    unsigned char aad[] = "aad";
+    unsigned char ct[] = "ciphertext";
+    unsigned char out[sizeof(ct) + EVP_MAX_BLOCK_LENGTH];
+    unsigned char tag[EVPTEST_TAG_LEN_MAX] = { 0xd0 };
+    OSSL_PARAM params[2];
+    int i, len = 0, testresult = 0;
+
+    /* CCM and SIV verify the tag at Update, not at Final */
+    if (info->mode == EVP_CIPH_CCM_MODE
+        || info->mode == EVP_CIPH_SIV_MODE)
+        return TEST_skip("Cipher %s skipped, Cipher is CCM or SIV mode",
+            info->name);
+
+    for (i = 0; i < info->keylen && i < (int)sizeof(key); i++)
+        key[i] = (unsigned char)(0x11 + i);
+    for (i = 0; i < info->ivlen && i < (int)sizeof(iv); i++)
+        iv[i] = (unsigned char)(0x22 + i);
+    params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,
+        tag, info->taglen);
+    params[1] = OSSL_PARAM_construct_end();
+
+    /* ciphertext only */
+    ERR_clear_error();
+    if (!TEST_ptr(ctx_ct = EVP_CIPHER_CTX_new())
+        || !TEST_true(EVP_DecryptInit_ex2(ctx_ct, info->ciph, key, iv, params))
+        || !TEST_true(EVP_DecryptUpdate(ctx_ct, out, &len, ct, sizeof(ct)))
+        || !TEST_int_le(EVP_DecryptFinal_ex(ctx_ct, out + len, &len), 0)
+        || !TEST_err_r(ERR_LIB_PROV, PROV_R_BAD_DECRYPT)) {
+        TEST_info("test_evp_aead_tag_reject %s: ciphertext variant", info->name);
+        goto err;
+    }
+
+    /* AAD only */
+    ERR_clear_error();
+    if (!TEST_ptr(ctx_aad = EVP_CIPHER_CTX_new())
+        || !TEST_true(EVP_DecryptInit_ex2(ctx_aad, info->ciph, key, iv, params))
+        || !TEST_true(EVP_DecryptUpdate(ctx_aad, NULL, &len, aad, sizeof(aad)))
+        || !TEST_int_le(EVP_DecryptFinal_ex(ctx_aad, out, &len), 0)
+        || !TEST_err_r(ERR_LIB_PROV, PROV_R_BAD_DECRYPT)) {
+        TEST_info("test_evp_aead_tag_reject %s: AAD variant", info->name);
+        goto err;
+    }
+
+    /* ciphertext + AAD */
+    ERR_clear_error();
+    if (!TEST_ptr(ctx_ct_aad = EVP_CIPHER_CTX_new())
+        || !TEST_true(EVP_DecryptInit_ex2(ctx_ct_aad, info->ciph, key, iv, params))
+        || !TEST_true(EVP_DecryptUpdate(ctx_ct_aad, NULL, &len, aad, sizeof(aad)))
+        || !TEST_true(EVP_DecryptUpdate(ctx_ct_aad, out, &len, ct, sizeof(ct)))
+        || !TEST_int_le(EVP_DecryptFinal_ex(ctx_ct_aad, out + len, &len), 0)
+        || !TEST_err_r(ERR_LIB_PROV, PROV_R_BAD_DECRYPT)) {
+        TEST_info("test_evp_aead_tag_reject %s: ciphertext + AAD variant", info->name);
+        goto err;
+    }
+
+    /* ciphertext only, EVP_Cipher() interface */
+    ERR_clear_error();
+    if (!TEST_ptr(ctx_c_ct = EVP_CIPHER_CTX_new())
+        || !TEST_true(EVP_DecryptInit_ex2(ctx_c_ct, info->ciph, key, iv, params))
+        || !TEST_int_ge(EVP_Cipher(ctx_c_ct, out, ct, sizeof(ct)), 0)
+        || !TEST_int_lt(EVP_Cipher(ctx_c_ct, out, NULL, 0), 0)
+        || !TEST_err_r(ERR_LIB_PROV, PROV_R_BAD_DECRYPT)) {
+        TEST_info("test_evp_aead_tag_reject %s: ciphertext variant (EVP_Cipher)",
+            info->name);
+        goto err;
+    }
+
+    testresult = 1;
+err:
+    EVP_CIPHER_CTX_free(ctx_ct);
+    EVP_CIPHER_CTX_free(ctx_aad);
+    EVP_CIPHER_CTX_free(ctx_ct_aad);
+    EVP_CIPHER_CTX_free(ctx_c_ct);
+    return testresult;
+}
+
 int setup_tests(void)
 {
     size_t i = 0;
@@ -1605,6 +1690,7 @@ int setup_tests(void)
     ADD_ALL_TESTS(test_gcm_reinit, OSSL_NELEM(gcm_reinit_tests));
     ADD_ALL_TESTS(test_evp_stale_key_reinit, OSSL_NELEM(aead_list));
     ADD_TEST(test_aes_gcm_ivlen_change_cve_2023_5363);
+    ADD_ALL_TESTS(test_evp_aead_tag_reject, OSSL_NELEM(aead_list));
     return 1;
 }

diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c
index 9c1ea56fc5..bfe0264f72 100644
--- a/test/evp_extra_test.c
+++ b/test/evp_extra_test.c
@@ -6467,99 +6467,6 @@ err:
     return testresult;
 }

-/*
- * A decrypt with a wrong tag must be rejected by EVP_DecryptFinal_ex().
- * Negative test for the rejection, as well as the expected error reason.
- * Does ct / aad / ct + aad variants.
- */
-static int test_evp_aead_tag_reject(int idx)
-{
-    const EVP_CIPHER_TEST_INFO *info = &cipher_list[idx];
-    EVP_CIPHER_CTX *ctx_ct = NULL;
-    EVP_CIPHER_CTX *ctx_aad = NULL;
-    EVP_CIPHER_CTX *ctx_ct_aad = NULL;
-    EVP_CIPHER_CTX *ctx_c_ct = NULL;
-    unsigned char key[EVP_MAX_KEY_LENGTH];
-    unsigned char iv[EVP_MAX_IV_LENGTH];
-    unsigned char aad[] = "aad";
-    unsigned char ct[] = "ciphertext";
-    unsigned char out[sizeof(ct) + EVP_MAX_BLOCK_LENGTH];
-    unsigned char tag[EVPTEST_TAG_LEN_MAX] = { 0xd0 };
-    OSSL_PARAM params[2];
-    int i, len = 0, testresult = 0;
-
-    if (info->taglen == 0 /* skip non-AEAD */
-        || info->mode == EVP_CIPH_CCM_MODE /* verifies at update, not final */
-        /* skip TLS stitched MTE ciphers */
-        || EVP_CIPHER_is_a(info->ciph, "AES-128-CBC-HMAC-SHA1")
-        || EVP_CIPHER_is_a(info->ciph, "AES-256-CBC-HMAC-SHA1")
-        || EVP_CIPHER_is_a(info->ciph, "AES-128-CBC-HMAC-SHA256")
-        || EVP_CIPHER_is_a(info->ciph, "AES-256-CBC-HMAC-SHA256"))
-        return 1;
-
-    for (i = 0; i < info->keylen && i < (int)sizeof(key); i++)
-        key[i] = (unsigned char)(0x11 + i);
-    for (i = 0; i < info->ivlen && i < (int)sizeof(iv); i++)
-        iv[i] = (unsigned char)(0x22 + i);
-    params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,
-        tag, info->taglen);
-    params[1] = OSSL_PARAM_construct_end();
-
-    /* ciphertext only */
-    ERR_clear_error();
-    if (!TEST_ptr(ctx_ct = EVP_CIPHER_CTX_new())
-        || !TEST_true(EVP_DecryptInit_ex2(ctx_ct, info->ciph, key, iv, params))
-        || !TEST_true(EVP_DecryptUpdate(ctx_ct, out, &len, ct, sizeof(ct)))
-        || !TEST_int_le(EVP_DecryptFinal_ex(ctx_ct, out + len, &len), 0)
-        || !TEST_err_r(ERR_LIB_PROV, PROV_R_BAD_DECRYPT)) {
-        TEST_info("test_evp_aead_tag_reject %s: ciphertext variant", info->name);
-        goto err;
-    }
-
-    /* AAD only */
-    ERR_clear_error();
-    if (!TEST_ptr(ctx_aad = EVP_CIPHER_CTX_new())
-        || !TEST_true(EVP_DecryptInit_ex2(ctx_aad, info->ciph, key, iv, params))
-        || !TEST_true(EVP_DecryptUpdate(ctx_aad, NULL, &len, aad, sizeof(aad)))
-        || !TEST_int_le(EVP_DecryptFinal_ex(ctx_aad, out, &len), 0)
-        || !TEST_err_r(ERR_LIB_PROV, PROV_R_BAD_DECRYPT)) {
-        TEST_info("test_evp_aead_tag_reject %s: AAD variant", info->name);
-        goto err;
-    }
-
-    /* ciphertext + AAD */
-    ERR_clear_error();
-    if (!TEST_ptr(ctx_ct_aad = EVP_CIPHER_CTX_new())
-        || !TEST_true(EVP_DecryptInit_ex2(ctx_ct_aad, info->ciph, key, iv, params))
-        || !TEST_true(EVP_DecryptUpdate(ctx_ct_aad, NULL, &len, aad, sizeof(aad)))
-        || !TEST_true(EVP_DecryptUpdate(ctx_ct_aad, out, &len, ct, sizeof(ct)))
-        || !TEST_int_le(EVP_DecryptFinal_ex(ctx_ct_aad, out + len, &len), 0)
-        || !TEST_err_r(ERR_LIB_PROV, PROV_R_BAD_DECRYPT)) {
-        TEST_info("test_evp_aead_tag_reject %s: ciphertext + AAD variant", info->name);
-        goto err;
-    }
-
-    /* ciphertext only, EVP_Cipher() interface */
-    ERR_clear_error();
-    if (!TEST_ptr(ctx_c_ct = EVP_CIPHER_CTX_new())
-        || !TEST_true(EVP_DecryptInit_ex2(ctx_c_ct, info->ciph, key, iv, params))
-        || !TEST_int_ge(EVP_Cipher(ctx_c_ct, out, ct, sizeof(ct)), 0)
-        || !TEST_int_lt(EVP_Cipher(ctx_c_ct, out, NULL, 0), 0)
-        || !TEST_err_r(ERR_LIB_PROV, PROV_R_BAD_DECRYPT)) {
-        TEST_info("test_evp_aead_tag_reject %s: ciphertext variant (EVP_Cipher)",
-            info->name);
-        goto err;
-    }
-
-    testresult = 1;
-err:
-    EVP_CIPHER_CTX_free(ctx_ct);
-    EVP_CIPHER_CTX_free(ctx_aad);
-    EVP_CIPHER_CTX_free(ctx_ct_aad);
-    EVP_CIPHER_CTX_free(ctx_c_ct);
-    return testresult;
-}
-
 /*
  * Decrypt roundtrip:
  * Encrypt single-call, decrypt via multi-step init, verify plaintext recovery.
@@ -10031,7 +9938,6 @@ int setup_tests(void)
     ADD_ALL_TESTS(test_evp_diff_order_init, cipher_list_n);
     ADD_ALL_TESTS(test_evp_decrypt_roundtrip_multistep, cipher_list_n);
     ADD_ALL_TESTS(test_evp_aead_tag_direction, cipher_list_n);
-    ADD_ALL_TESTS(test_evp_aead_tag_reject, cipher_list_n);

     ADD_ALL_TESTS(test_evp_init_seq, OSSL_NELEM(evp_init_tests));
     ADD_ALL_TESTS(test_evp_reset, OSSL_NELEM(evp_reset_tests));