Path: blob/main/crypto/openssl/providers/implementations/macs/hmac_prov.c
48383 views
/*1* Copyright 2018-2025 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89/*10* HMAC low level APIs are deprecated for public use, but still ok for internal11* use.12*/13#include "internal/deprecated.h"1415#include <string.h>1617#include <openssl/core_dispatch.h>18#include <openssl/core_names.h>19#include <openssl/params.h>20#include <openssl/evp.h>21#include <openssl/hmac.h>22#include <openssl/proverr.h>23#include <openssl/err.h>2425#include "internal/ssl3_cbc.h"2627#include "prov/implementations.h"28#include "prov/provider_ctx.h"29#include "prov/provider_util.h"30#include "prov/providercommon.h"31#include "prov/securitycheck.h"3233/*34* Forward declaration of everything implemented here. This is not strictly35* necessary for the compiler, but provides an assurance that the signatures36* of the functions in the dispatch table are correct.37*/38static OSSL_FUNC_mac_newctx_fn hmac_new;39static OSSL_FUNC_mac_dupctx_fn hmac_dup;40static OSSL_FUNC_mac_freectx_fn hmac_free;41static OSSL_FUNC_mac_gettable_ctx_params_fn hmac_gettable_ctx_params;42static OSSL_FUNC_mac_get_ctx_params_fn hmac_get_ctx_params;43static OSSL_FUNC_mac_settable_ctx_params_fn hmac_settable_ctx_params;44static OSSL_FUNC_mac_set_ctx_params_fn hmac_set_ctx_params;45static OSSL_FUNC_mac_init_fn hmac_init;46static OSSL_FUNC_mac_update_fn hmac_update;47static OSSL_FUNC_mac_final_fn hmac_final;4849/* local HMAC context structure */5051/* typedef EVP_MAC_IMPL */52struct hmac_data_st {53void *provctx;54HMAC_CTX *ctx; /* HMAC context */55PROV_DIGEST digest;56unsigned char *key;57size_t keylen;58/* Length of full TLS record including the MAC and any padding */59size_t tls_data_size;60unsigned char tls_header[13];61int tls_header_set;62unsigned char tls_mac_out[EVP_MAX_MD_SIZE];63size_t tls_mac_out_size;64#ifdef FIPS_MODULE65/*66* 'internal' is set to 1 if HMAC is used inside another algorithm such as a67* KDF. In this case it is the parent algorithm that is responsible for68* performing any conditional FIPS indicator related checks for the HMAC.69*/70int internal;71#endif72OSSL_FIPS_IND_DECLARE73};7475static void *hmac_new(void *provctx)76{77struct hmac_data_st *macctx;7879if (!ossl_prov_is_running())80return NULL;8182if ((macctx = OPENSSL_zalloc(sizeof(*macctx))) == NULL83|| (macctx->ctx = HMAC_CTX_new()) == NULL) {84OPENSSL_free(macctx);85return NULL;86}87macctx->provctx = provctx;88OSSL_FIPS_IND_INIT(macctx)8990return macctx;91}9293static void hmac_free(void *vmacctx)94{95struct hmac_data_st *macctx = vmacctx;9697if (macctx != NULL) {98HMAC_CTX_free(macctx->ctx);99ossl_prov_digest_reset(&macctx->digest);100OPENSSL_clear_free(macctx->key, macctx->keylen);101OPENSSL_free(macctx);102}103}104105static void *hmac_dup(void *vsrc)106{107struct hmac_data_st *src = vsrc;108struct hmac_data_st *dst;109HMAC_CTX *ctx;110111if (!ossl_prov_is_running())112return NULL;113dst = hmac_new(src->provctx);114if (dst == NULL)115return NULL;116117ctx = dst->ctx;118*dst = *src;119dst->ctx = ctx;120dst->key = NULL;121memset(&dst->digest, 0, sizeof(dst->digest));122123if (!HMAC_CTX_copy(dst->ctx, src->ctx)124|| !ossl_prov_digest_copy(&dst->digest, &src->digest)) {125hmac_free(dst);126return NULL;127}128if (src->key != NULL) {129dst->key = OPENSSL_malloc(src->keylen > 0 ? src->keylen : 1);130if (dst->key == NULL) {131hmac_free(dst);132return 0;133}134if (src->keylen > 0)135memcpy(dst->key, src->key, src->keylen);136}137return dst;138}139140static size_t hmac_size(struct hmac_data_st *macctx)141{142return HMAC_size(macctx->ctx);143}144145static int hmac_block_size(struct hmac_data_st *macctx)146{147const EVP_MD *md = ossl_prov_digest_md(&macctx->digest);148149if (md == NULL)150return 0;151return EVP_MD_block_size(md);152}153154static int hmac_setkey(struct hmac_data_st *macctx,155const unsigned char *key, size_t keylen)156{157const EVP_MD *digest;158159#ifdef FIPS_MODULE160/*161* KDF's pass a salt rather than a key,162* which is why it skips the key check unless "HMAC" is fetched directly.163*/164if (!macctx->internal) {165OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(macctx->provctx);166int approved = ossl_mac_check_key_size(keylen);167168if (!approved) {169if (!OSSL_FIPS_IND_ON_UNAPPROVED(macctx, OSSL_FIPS_IND_SETTABLE0,170libctx, "HMAC", "keysize",171ossl_fips_config_hmac_key_check)) {172ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);173return 0;174}175}176}177#endif178179if (macctx->key != NULL)180OPENSSL_clear_free(macctx->key, macctx->keylen);181/* Keep a copy of the key in case we need it for TLS HMAC */182macctx->key = OPENSSL_malloc(keylen > 0 ? keylen : 1);183if (macctx->key == NULL)184return 0;185186if (keylen > 0)187memcpy(macctx->key, key, keylen);188macctx->keylen = keylen;189190digest = ossl_prov_digest_md(&macctx->digest);191/* HMAC_Init_ex doesn't tolerate all zero params, so we must be careful */192if (key != NULL || (macctx->tls_data_size == 0 && digest != NULL))193return HMAC_Init_ex(macctx->ctx, key, keylen, digest,194ossl_prov_digest_engine(&macctx->digest));195return 1;196}197198static int hmac_init(void *vmacctx, const unsigned char *key,199size_t keylen, const OSSL_PARAM params[])200{201struct hmac_data_st *macctx = vmacctx;202203if (!ossl_prov_is_running() || !hmac_set_ctx_params(macctx, params))204return 0;205206if (key != NULL)207return hmac_setkey(macctx, key, keylen);208209/* Just reinit the HMAC context */210return HMAC_Init_ex(macctx->ctx, NULL, 0, NULL, NULL);211}212213static int hmac_update(void *vmacctx, const unsigned char *data,214size_t datalen)215{216struct hmac_data_st *macctx = vmacctx;217218if (macctx->tls_data_size > 0) {219/* We're doing a TLS HMAC */220if (!macctx->tls_header_set) {221/* We expect the first update call to contain the TLS header */222if (datalen != sizeof(macctx->tls_header))223return 0;224memcpy(macctx->tls_header, data, datalen);225macctx->tls_header_set = 1;226return 1;227}228/* macctx->tls_data_size is datalen plus the padding length */229if (macctx->tls_data_size < datalen)230return 0;231232return ssl3_cbc_digest_record(ossl_prov_digest_md(&macctx->digest),233macctx->tls_mac_out,234&macctx->tls_mac_out_size,235macctx->tls_header,236data,237datalen,238macctx->tls_data_size,239macctx->key,240macctx->keylen,2410);242}243244return HMAC_Update(macctx->ctx, data, datalen);245}246247static int hmac_final(void *vmacctx, unsigned char *out, size_t *outl,248size_t outsize)249{250unsigned int hlen;251struct hmac_data_st *macctx = vmacctx;252253if (!ossl_prov_is_running())254return 0;255if (macctx->tls_data_size > 0) {256if (macctx->tls_mac_out_size == 0)257return 0;258if (outl != NULL)259*outl = macctx->tls_mac_out_size;260memcpy(out, macctx->tls_mac_out, macctx->tls_mac_out_size);261return 1;262}263if (!HMAC_Final(macctx->ctx, out, &hlen))264return 0;265*outl = hlen;266return 1;267}268269static const OSSL_PARAM known_gettable_ctx_params[] = {270OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),271OSSL_PARAM_size_t(OSSL_MAC_PARAM_BLOCK_SIZE, NULL),272OSSL_FIPS_IND_GETTABLE_CTX_PARAM()273OSSL_PARAM_END274};275static const OSSL_PARAM *hmac_gettable_ctx_params(ossl_unused void *ctx,276ossl_unused void *provctx)277{278return known_gettable_ctx_params;279}280281static int hmac_get_ctx_params(void *vmacctx, OSSL_PARAM params[])282{283struct hmac_data_st *macctx = vmacctx;284OSSL_PARAM *p;285286if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL287&& !OSSL_PARAM_set_size_t(p, hmac_size(macctx)))288return 0;289290if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_BLOCK_SIZE)) != NULL291&& !OSSL_PARAM_set_int(p, hmac_block_size(macctx)))292return 0;293294#ifdef FIPS_MODULE295p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_FIPS_APPROVED_INDICATOR);296if (p != NULL) {297int approved = 0;298299if (!macctx->internal)300approved = OSSL_FIPS_IND_GET(macctx)->approved;301if (!OSSL_PARAM_set_int(p, approved))302return 0;303}304#endif305return 1;306}307308static const OSSL_PARAM known_settable_ctx_params[] = {309OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_DIGEST, NULL, 0),310OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_PROPERTIES, NULL, 0),311OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0),312OSSL_PARAM_int(OSSL_MAC_PARAM_DIGEST_NOINIT, NULL),313OSSL_PARAM_int(OSSL_MAC_PARAM_DIGEST_ONESHOT, NULL),314OSSL_PARAM_size_t(OSSL_MAC_PARAM_TLS_DATA_SIZE, NULL),315OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_MAC_PARAM_FIPS_KEY_CHECK)316OSSL_PARAM_END317};318static const OSSL_PARAM *hmac_settable_ctx_params(ossl_unused void *ctx,319ossl_unused void *provctx)320{321return known_settable_ctx_params;322}323324/*325* ALL parameters should be set before init().326*/327static int hmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[])328{329struct hmac_data_st *macctx = vmacctx;330OSSL_LIB_CTX *ctx = PROV_LIBCTX_OF(macctx->provctx);331const OSSL_PARAM *p;332333if (ossl_param_is_empty(params))334return 1;335336if (!OSSL_FIPS_IND_SET_CTX_PARAM(macctx, OSSL_FIPS_IND_SETTABLE0, params,337OSSL_MAC_PARAM_FIPS_KEY_CHECK))338return 0;339340if (!ossl_prov_digest_load_from_params(&macctx->digest, params, ctx))341return 0;342343if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) {344if (p->data_type != OSSL_PARAM_OCTET_STRING)345return 0;346347if (!hmac_setkey(macctx, p->data, p->data_size))348return 0;349}350351if ((p = OSSL_PARAM_locate_const(params,352OSSL_MAC_PARAM_TLS_DATA_SIZE)) != NULL) {353if (!OSSL_PARAM_get_size_t(p, &macctx->tls_data_size))354return 0;355}356return 1;357}358359const OSSL_DISPATCH ossl_hmac_functions[] = {360{ OSSL_FUNC_MAC_NEWCTX, (void (*)(void))hmac_new },361{ OSSL_FUNC_MAC_DUPCTX, (void (*)(void))hmac_dup },362{ OSSL_FUNC_MAC_FREECTX, (void (*)(void))hmac_free },363{ OSSL_FUNC_MAC_INIT, (void (*)(void))hmac_init },364{ OSSL_FUNC_MAC_UPDATE, (void (*)(void))hmac_update },365{ OSSL_FUNC_MAC_FINAL, (void (*)(void))hmac_final },366{ OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS,367(void (*)(void))hmac_gettable_ctx_params },368{ OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))hmac_get_ctx_params },369{ OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,370(void (*)(void))hmac_settable_ctx_params },371{ OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))hmac_set_ctx_params },372OSSL_DISPATCH_END373};374375#ifdef FIPS_MODULE376static OSSL_FUNC_mac_newctx_fn hmac_internal_new;377378static void *hmac_internal_new(void *provctx)379{380struct hmac_data_st *macctx = hmac_new(provctx);381382if (macctx != NULL)383macctx->internal = 1;384return macctx;385}386387const OSSL_DISPATCH ossl_hmac_internal_functions[] = {388{ OSSL_FUNC_MAC_NEWCTX, (void (*)(void))hmac_internal_new },389{ OSSL_FUNC_MAC_DUPCTX, (void (*)(void))hmac_dup },390{ OSSL_FUNC_MAC_FREECTX, (void (*)(void))hmac_free },391{ OSSL_FUNC_MAC_INIT, (void (*)(void))hmac_init },392{ OSSL_FUNC_MAC_UPDATE, (void (*)(void))hmac_update },393{ OSSL_FUNC_MAC_FINAL, (void (*)(void))hmac_final },394{ OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS,395(void (*)(void))hmac_gettable_ctx_params },396{ OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))hmac_get_ctx_params },397{ OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,398(void (*)(void))hmac_settable_ctx_params },399{ OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))hmac_set_ctx_params },400OSSL_DISPATCH_END401};402403#endif /* FIPS_MODULE */404405406