Commit 95f95b59dd for openssl.org
commit 95f95b59dded1ad376458152e4c8533018ee2f43
Author: Mounir IDRASSI <mounir.idrassi@idrix.fr>
Date: Wed Jun 3 23:44:22 2026 +0900
poly1305: reject no-key update and NULL key params
Poly1305 permits EVP_MAC_init(ctx, NULL, 0, ...) as part of staged
initialization. If no key has been installed, update still dispatched
into the uninitialized Poly1305 state, which can crash on POLY1305_ASM
builds.
Guard update with the same key_set check used by final and report no key set.
Also reject an explicit OSSL_MAC_PARAM_KEY whose data pointer is NULL before
calling Poly1305_Init(), even when the supplied size is POLY1305_KEY_SIZE.
Fixes #31332
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Daniel Kubec <kubec@openssl.foundation>
MergeDate: Mon Jul 13 15:44:48 2026
(Merged from https://github.com/openssl/openssl/pull/31382)
diff --git a/providers/implementations/macs/poly1305_prov.c b/providers/implementations/macs/poly1305_prov.c
index 8d6f9c952e..a9ca6e4f68 100644
--- a/providers/implementations/macs/poly1305_prov.c
+++ b/providers/implementations/macs/poly1305_prov.c
@@ -86,7 +86,7 @@ static size_t poly1305_size(void)
static int poly1305_setkey(struct poly1305_data_st *ctx,
const unsigned char *key, size_t keylen)
{
- if (keylen != POLY1305_KEY_SIZE) {
+ if (key == NULL || keylen != POLY1305_KEY_SIZE) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
@@ -115,6 +115,10 @@ static int poly1305_update(void *vmacctx, const unsigned char *data,
{
struct poly1305_data_st *ctx = vmacctx;
+ if (!ctx->key_set) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
+ return 0;
+ }
ctx->updated = 1;
if (datalen == 0)
return 1;
diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c
index f1de702ec7..5c37102088 100644
--- a/test/evp_extra_test.c
+++ b/test/evp_extra_test.c
@@ -2323,20 +2323,83 @@ out:
}
#ifndef OPENSSL_NO_POLY1305
-/* Test that EVP_MAC_final fails for Poly1305 when no key was set */
+/* Test Poly1305 no-key failures and staged key initialization */
static int test_evp_mac_poly1305_no_key(void)
{
int ret = 0;
EVP_MAC *mac = NULL;
EVP_MAC_CTX *ctx = NULL;
+ /* RFC 7539 Poly1305 test vector. */
+ static const unsigned char staged_data[] = "Cryptographic Forum Research Group";
+ static const unsigned char expected[16] = {
+ 0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6,
+ 0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9
+ };
+ unsigned char no_key_data[16] = { 0 };
+ unsigned char key[32] = {
+ 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33,
+ 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8,
+ 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd,
+ 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b
+ };
unsigned char out[16];
+ OSSL_PARAM key_params[2];
+ OSSL_PARAM null_key_params[2];
size_t outl = 0;
+ key_params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+ key, sizeof(key));
+ key_params[1] = OSSL_PARAM_construct_end();
+ null_key_params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+ NULL, sizeof(key));
+ null_key_params[1] = OSSL_PARAM_construct_end();
+
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))
+ || !TEST_int_eq(EVP_MAC_init(ctx, NULL, 0, NULL), 1))
+ goto err;
+
+ ERR_clear_error();
+ if (!TEST_int_eq(EVP_MAC_update(ctx, no_key_data, sizeof(no_key_data)), 0)
+ || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_NO_KEY_SET))
+ goto err;
+
+ /* The failed update must not block staged key initialization. */
+ if (!TEST_int_eq(EVP_MAC_CTX_set_params(ctx, key_params), 1)
+ || !TEST_int_eq(EVP_MAC_update(ctx, staged_data,
+ sizeof(staged_data) - 1),
+ 1)
+ || !TEST_int_eq(EVP_MAC_final(ctx, out, &outl, sizeof(out)), 1)
+ || !TEST_size_t_eq(outl, sizeof(expected))
+ || !TEST_mem_eq(out, outl, expected, sizeof(expected)))
+ goto err;
+
+ EVP_MAC_CTX_free(ctx);
+ ctx = NULL;
+
+ if (!TEST_ptr(ctx = EVP_MAC_CTX_new(mac))
+ || !TEST_int_eq(EVP_MAC_init(ctx, NULL, 0, NULL), 1))
+ goto err;
+
+ ERR_clear_error();
+ if (!TEST_int_eq(EVP_MAC_final(ctx, out, &outl, sizeof(out)), 0)
+ || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_NO_KEY_SET))
+ goto err;
+
+ ERR_clear_error();
+ if (!TEST_int_eq(EVP_MAC_init(ctx, NULL, 0, null_key_params), 0)
+ || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()),
+ PROV_R_INVALID_KEY_LENGTH))
goto err;
+
+ ERR_clear_error();
+ if (!TEST_int_eq(EVP_MAC_CTX_set_params(ctx, null_key_params), 0)
+ || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()),
+ PROV_R_INVALID_KEY_LENGTH))
+ goto err;
+
+ EVP_MAC_CTX_free(ctx);
+ ctx = NULL;
ret = 1;
err:
EVP_MAC_CTX_free(ctx);