diff options
author | slontis <shane.lontis@oracle.com> | 2024-07-31 14:56:44 +1000 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2024-08-21 15:34:40 +0200 |
commit | 390f00a1e95f241b4a104c323020c7bc90d5e829 (patch) | |
tree | c3236df10f38563b0b15df196e5c8a80a0f21013 /providers/implementations | |
parent | d2739fc350227ab17636bcb4b8209ca320b53094 (diff) |
Add HMAC FIPS keysize check.
HMAC has been changed to use a FIPS indicator for its key check.
HKDF and Single Step use a salt rather than a key when using HMAC,
so we need a mechanism to bypass this check in HMAC.
A seperate 'internal' query table has been added to the FIPS provider
for MACS. Giving HMAC a seprate dispatch table allows KDF's to ignore
the key check. If a KDF requires the key check then it must do the
check itself. The normal MAC dipatch table is used if the user fetches
HMAC directly.
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/25049)
Diffstat (limited to 'providers/implementations')
-rw-r--r-- | providers/implementations/include/prov/implementations.h | 3 | ||||
-rw-r--r-- | providers/implementations/kdfs/hkdf.c | 7 | ||||
-rw-r--r-- | providers/implementations/macs/hmac_prov.c | 84 |
3 files changed, 90 insertions, 4 deletions
diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h index a2da68ed02..6199292c53 100644 --- a/providers/implementations/include/prov/implementations.h +++ b/providers/implementations/include/prov/implementations.h @@ -258,6 +258,9 @@ extern const OSSL_DISPATCH ossl_blake2smac_functions[]; extern const OSSL_DISPATCH ossl_cmac_functions[]; extern const OSSL_DISPATCH ossl_gmac_functions[]; extern const OSSL_DISPATCH ossl_hmac_functions[]; +#ifdef FIPS_MODULE +extern const OSSL_DISPATCH ossl_hmac_internal_functions[]; +#endif extern const OSSL_DISPATCH ossl_kmac128_functions[]; extern const OSSL_DISPATCH ossl_kmac256_functions[]; extern const OSSL_DISPATCH ossl_siphash_functions[]; diff --git a/providers/implementations/kdfs/hkdf.c b/providers/implementations/kdfs/hkdf.c index 64a3e8f05e..e2bf3d5c3a 100644 --- a/providers/implementations/kdfs/hkdf.c +++ b/providers/implementations/kdfs/hkdf.c @@ -519,10 +519,9 @@ static int HKDF_Extract(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md, return 0; } /* calc: PRK = HMAC-Hash(salt, IKM) */ - return - EVP_Q_mac(libctx, "HMAC", NULL, EVP_MD_get0_name(evp_md), NULL, salt, - salt_len, ikm, ikm_len, prk, EVP_MD_get_size(evp_md), NULL) - != NULL; + return EVP_Q_mac(libctx, "HMAC", NULL, EVP_MD_get0_name(evp_md), NULL, salt, + salt_len, ikm, ikm_len, prk, EVP_MD_get_size(evp_md), NULL) + != NULL; } /* diff --git a/providers/implementations/macs/hmac_prov.c b/providers/implementations/macs/hmac_prov.c index c72c1e6c0f..d871a85033 100644 --- a/providers/implementations/macs/hmac_prov.c +++ b/providers/implementations/macs/hmac_prov.c @@ -20,6 +20,8 @@ #include <openssl/params.h> #include <openssl/evp.h> #include <openssl/hmac.h> +#include <openssl/proverr.h> +#include <openssl/err.h> #include "internal/ssl3_cbc.h" @@ -27,6 +29,9 @@ #include "prov/provider_ctx.h" #include "prov/provider_util.h" #include "prov/providercommon.h" +#include "prov/fipsindicator.h" +#include "prov/securitycheck.h" +#include "prov/fipscommon.h" /* * Forward declaration of everything implemented here. This is not strictly @@ -59,6 +64,15 @@ struct hmac_data_st { int tls_header_set; unsigned char tls_mac_out[EVP_MAX_MD_SIZE]; size_t tls_mac_out_size; +#ifdef FIPS_MODULE + /* + * 'internal' is set to 1 if HMAC is used inside another algorithm such as a + * KDF. In this case it is the parent algorithm that is responsible for + * performing any conditional FIPS indicator related checks for the HMAC. + */ + int internal; +#endif + OSSL_FIPS_IND_DECLARE }; static void *hmac_new(void *provctx) @@ -74,6 +88,7 @@ static void *hmac_new(void *provctx) return NULL; } macctx->provctx = provctx; + OSSL_FIPS_IND_INIT(macctx) return macctx; } @@ -144,12 +159,33 @@ static int hmac_setkey(struct hmac_data_st *macctx, { const EVP_MD *digest; +#ifdef FIPS_MODULE + /* + * KDF's pass a salt rather than a key, + * which is why it skips the key check unless "HMAC" is fetched directly. + */ + if (!macctx->internal) { + OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(macctx->provctx); + int approved = ossl_mac_check_key_size(keylen); + + if (!approved) { + if (!OSSL_FIPS_IND_ON_UNAPPROVED(macctx, OSSL_FIPS_IND_SETTABLE0, + libctx, "HMAC", "keysize", + FIPS_hmac_key_check)) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } + } + } +#endif + if (macctx->key != NULL) OPENSSL_secure_clear_free(macctx->key, macctx->keylen); /* Keep a copy of the key in case we need it for TLS HMAC */ macctx->key = OPENSSL_secure_malloc(keylen > 0 ? keylen : 1); if (macctx->key == NULL) return 0; + memcpy(macctx->key, key, keylen); macctx->keylen = keylen; @@ -235,6 +271,7 @@ static int hmac_final(void *vmacctx, unsigned char *out, size_t *outl, static const OSSL_PARAM known_gettable_ctx_params[] = { OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), OSSL_PARAM_size_t(OSSL_MAC_PARAM_BLOCK_SIZE, NULL), + OSSL_FIPS_IND_GETTABLE_CTX_PARAM() OSSL_PARAM_END }; static const OSSL_PARAM *hmac_gettable_ctx_params(ossl_unused void *ctx, @@ -256,6 +293,17 @@ static int hmac_get_ctx_params(void *vmacctx, OSSL_PARAM params[]) && !OSSL_PARAM_set_int(p, hmac_block_size(macctx))) return 0; +#ifdef FIPS_MODULE + p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_FIPS_APPROVED_INDICATOR); + if (p != NULL) { + int approved = 0; + + if (!macctx->internal) + approved = OSSL_FIPS_IND_GET(macctx)->approved; + if (!OSSL_PARAM_set_int(p, approved)) + return 0; + } +#endif return 1; } @@ -266,6 +314,7 @@ static const OSSL_PARAM known_settable_ctx_params[] = { OSSL_PARAM_int(OSSL_MAC_PARAM_DIGEST_NOINIT, NULL), OSSL_PARAM_int(OSSL_MAC_PARAM_DIGEST_ONESHOT, NULL), OSSL_PARAM_size_t(OSSL_MAC_PARAM_TLS_DATA_SIZE, NULL), + OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_MAC_PARAM_FIPS_KEY_CHECK) OSSL_PARAM_END }; static const OSSL_PARAM *hmac_settable_ctx_params(ossl_unused void *ctx, @@ -286,12 +335,17 @@ static int hmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[]) if (params == NULL) return 1; + if (!OSSL_FIPS_IND_SET_CTX_PARAM(macctx, OSSL_FIPS_IND_SETTABLE0, params, + OSSL_MAC_PARAM_FIPS_KEY_CHECK)) + return 0; + if (!ossl_prov_digest_load_from_params(&macctx->digest, params, ctx)) return 0; if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) { if (p->data_type != OSSL_PARAM_OCTET_STRING) return 0; + if (!hmac_setkey(macctx, p->data, p->data_size)) return 0; } @@ -319,3 +373,33 @@ const OSSL_DISPATCH ossl_hmac_functions[] = { { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))hmac_set_ctx_params }, OSSL_DISPATCH_END }; + +#ifdef FIPS_MODULE +static OSSL_FUNC_mac_newctx_fn hmac_internal_new; + +static void *hmac_internal_new(void *provctx) +{ + struct hmac_data_st *macctx = hmac_new(provctx); + + if (macctx != NULL) + macctx->internal = 1; + return macctx; +} + +const OSSL_DISPATCH ossl_hmac_internal_functions[] = { + { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))hmac_internal_new }, + { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))hmac_dup }, + { OSSL_FUNC_MAC_FREECTX, (void (*)(void))hmac_free }, + { OSSL_FUNC_MAC_INIT, (void (*)(void))hmac_init }, + { OSSL_FUNC_MAC_UPDATE, (void (*)(void))hmac_update }, + { OSSL_FUNC_MAC_FINAL, (void (*)(void))hmac_final }, + { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS, + (void (*)(void))hmac_gettable_ctx_params }, + { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))hmac_get_ctx_params }, + { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, + (void (*)(void))hmac_settable_ctx_params }, + { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))hmac_set_ctx_params }, + OSSL_DISPATCH_END +}; + +#endif /* FIPS_MODULE */ |