Commit 07485b844a for openssl.org

commit 07485b844a0689354c2c17163604860a82d281bb
Author: 007bsd <22483432+007bsd@users.noreply.github.com>
Date:   Tue May 26 21:11:27 2026 +0300

    poly1305: prevent crash on final without a key

    EVP_MAC_init with a NULL key followed by EVP_MAC_final on a
    Poly1305 context crashed with a NULL function-pointer dispatch
    because poly1305_init accepted the no-key case as success, and
    poly1305_final had no guard before dispatching through the
    uninitialised Poly1305 state.

    Add a key_set field to struct poly1305_data_st (matching
    OCB/CCM/GCM), set it in poly1305_setkey, and refuse init and
    final if no key has been installed.

    Added a regression test asserting EVP_MAC_init with a NULL key
    returns 0.

    ##### Checklist
    - [ ] documentation is added or updated
    - [x] tests are added or updated

    CLA: trivial

    Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
    Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
    MergeDate: Mon Jun  1 07:35:02 2026
    (Merged from https://github.com/openssl/openssl/pull/31298)

diff --git a/providers/implementations/macs/poly1305_prov.c b/providers/implementations/macs/poly1305_prov.c
index cfa59b2b49..8d6f9c952e 100644
--- a/providers/implementations/macs/poly1305_prov.c
+++ b/providers/implementations/macs/poly1305_prov.c
@@ -42,6 +42,7 @@ static OSSL_FUNC_mac_final_fn poly1305_final;
 struct poly1305_data_st {
     void *provctx;
     int updated;
+    int key_set;
     POLY1305 poly1305; /* Poly1305 data */
 };

@@ -91,6 +92,7 @@ static int poly1305_setkey(struct poly1305_data_st *ctx,
     }
     Poly1305_Init(&ctx->poly1305, key);
     ctx->updated = 0;
+    ctx->key_set = 1;
     return 1;
 }

@@ -129,6 +131,10 @@ static int poly1305_final(void *vmacctx, unsigned char *out, size_t *outl,

     if (!ossl_prov_is_running())
         return 0;
+    if (!ctx->key_set) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
+        return 0;
+    }
     ctx->updated = 1;
     Poly1305_Final(&ctx->poly1305, out);
     *outl = poly1305_size();
diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c
index 7242166e76..2ca0669265 100644
--- a/test/evp_extra_test.c
+++ b/test/evp_extra_test.c
@@ -2322,6 +2322,29 @@ out:
     return ret;
 }

+#ifndef OPENSSL_NO_POLY1305
+/* Test that EVP_MAC_final fails for Poly1305 when no key was set */
+static int test_evp_mac_poly1305_no_key(void)
+{
+    int ret = 0;
+    EVP_MAC *mac = NULL;
+    EVP_MAC_CTX *ctx = NULL;
+    unsigned char out[16];
+    size_t outl = 0;
+
+    if (!TEST_ptr(mac = EVP_MAC_fetch(testctx, "Poly1305", testpropq))
+        || !TEST_ptr(ctx = EVP_MAC_CTX_new(mac))
+        || !TEST_int_eq(EVP_MAC_init(ctx, NULL, 0, NULL), 1)
+        || !TEST_int_eq(EVP_MAC_final(ctx, out, &outl, sizeof(out)), 0))
+        goto err;
+    ret = 1;
+err:
+    EVP_MAC_CTX_free(ctx);
+    EVP_MAC_free(mac);
+    return ret;
+}
+#endif
+
 static int test_d2i_AutoPrivateKey(int i)
 {
     int ret = 0;
@@ -7994,6 +8017,9 @@ int setup_tests(void)
 #endif
     ADD_TEST(test_EVP_Digest);
     ADD_TEST(test_EVP_md_null);
+#ifndef OPENSSL_NO_POLY1305
+    ADD_TEST(test_evp_mac_poly1305_no_key);
+#endif
     ADD_ALL_TESTS(test_EVP_PKEY_sign, 3);
 #ifndef OPENSSL_NO_DEPRECATED_3_0
     ADD_ALL_TESTS(test_EVP_PKEY_sign_with_app_method, 2);