From: Mounir IDRASSI Date: Wed, 3 Jun 2026 14:44:22 +0000 (+0900) Subject: poly1305: reject no-key update and NULL key params X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=95f95b59dded1ad376458152e4c8533018ee2f43;p=thirdparty%2Fopenssl.git 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 Reviewed-by: Daniel Kubec 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 8d6f9c952e9..a9ca6e4f688 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 f1de702ec7a..5c371020889 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);