From: Simo Sorce Date: Fri, 7 Feb 2025 16:21:51 +0000 (-0500) Subject: Change also other DRBG's algorithm fetching X-Git-Tag: openssl-3.5.0-alpha1~633 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d037551ee3038c2625cbda65b5bc4ef290063a7b;p=thirdparty%2Fopenssl.git Change also other DRBG's algorithm fetching - DRBG_HASH - DRBG_HMAC Signed-off-by: Simo Sorce Reviewed-by: Tomas Mraz Reviewed-by: Tim Hudson Reviewed-by: Dmitry Belyavskiy (Merged from https://github.com/openssl/openssl/pull/26542) --- diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c index 6aa175fb3f4..4b8a9bb27da 100644 --- a/crypto/evp/digest.c +++ b/crypto/evp/digest.c @@ -1198,6 +1198,17 @@ void EVP_MD_do_all_provided(OSSL_LIB_CTX *libctx, evp_md_from_algorithm, evp_md_up_ref, evp_md_free); } +EVP_MD *evp_digest_fetch_from_prov(OSSL_PROVIDER *prov, + const char *algorithm, + const char *properties) +{ + return evp_generic_fetch_from_prov(prov, OSSL_OP_DIGEST, + algorithm, properties, + evp_md_from_algorithm, + evp_md_up_ref, + evp_md_free); +} + typedef struct { int md_nid; int hmac_nid; diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h index 278e5515520..ef1faa4516f 100644 --- a/crypto/evp/evp_local.h +++ b/crypto/evp/evp_local.h @@ -320,6 +320,12 @@ EVP_KEM *evp_kem_fetch_from_prov(OSSL_PROVIDER *prov, EVP_CIPHER *evp_cipher_fetch_from_prov(OSSL_PROVIDER *prov, const char *algorithm, const char *properties); +EVP_MD *evp_digest_fetch_from_prov(OSSL_PROVIDER *prov, + const char *algorithm, + const char *properties); +EVP_MAC *evp_mac_fetch_from_prov(OSSL_PROVIDER *prov, + const char *algorithm, + const char *properties); /* Internal structure constructors for fetched methods */ EVP_MD *evp_md_new(void); diff --git a/crypto/evp/mac_meth.c b/crypto/evp/mac_meth.c index a3e7a022085..07c159acf71 100644 --- a/crypto/evp/mac_meth.c +++ b/crypto/evp/mac_meth.c @@ -241,3 +241,14 @@ void EVP_MAC_do_all_provided(OSSL_LIB_CTX *libctx, (void (*)(void *, void *))fn, arg, evp_mac_from_algorithm, evp_mac_up_ref, evp_mac_free); } + +EVP_MAC *evp_mac_fetch_from_prov(OSSL_PROVIDER *prov, + const char *algorithm, + const char *properties) +{ + return evp_generic_fetch_from_prov(prov, OSSL_OP_MAC, + algorithm, properties, + evp_mac_from_algorithm, + evp_mac_up_ref, + evp_mac_free); +} diff --git a/providers/common/include/prov/provider_util.h b/providers/common/include/prov/provider_util.h index 5511565e79b..7b74e0fdedb 100644 --- a/providers/common/include/prov/provider_util.h +++ b/providers/common/include/prov/provider_util.h @@ -86,6 +86,8 @@ int ossl_prov_digest_copy(PROV_DIGEST *dst, const PROV_DIGEST *src); const EVP_MD *ossl_prov_digest_md(const PROV_DIGEST *pd); ENGINE *ossl_prov_digest_engine(const PROV_DIGEST *pd); +/* Set a specific md, resets current digests first */ +void ossl_prov_digest_set_md(PROV_DIGEST *pd, EVP_MD *md); /* * Set the various parameters on an EVP_MAC_CTX from the supplied arguments. diff --git a/providers/common/provider_util.c b/providers/common/provider_util.c index 5097d71e27c..1fd74cb3068 100644 --- a/providers/common/provider_util.c +++ b/providers/common/provider_util.c @@ -211,6 +211,12 @@ int ossl_prov_digest_load_from_params(PROV_DIGEST *pd, return pd->md != NULL; } +void ossl_prov_digest_set_md(PROV_DIGEST *pd, EVP_MD *md) +{ + ossl_prov_digest_reset(pd); + pd->md = pd->alloc_md = md; +} + const EVP_MD *ossl_prov_digest_md(const PROV_DIGEST *pd) { return pd->md; diff --git a/providers/implementations/rands/drbg_hash.c b/providers/implementations/rands/drbg_hash.c index 458b356b82f..7adbcd19550 100644 --- a/providers/implementations/rands/drbg_hash.c +++ b/providers/implementations/rands/drbg_hash.c @@ -22,6 +22,9 @@ #include "prov/provider_util.h" #include "prov/implementations.h" #include "drbg_local.h" +#include "crypto/evp.h" +#include "crypto/evp/evp_local.h" +#include "internal/provider.h" static OSSL_FUNC_rand_newctx_fn drbg_hash_new_wrapper; static OSSL_FUNC_rand_freectx_fn drbg_hash_free; @@ -504,11 +507,53 @@ static const OSSL_PARAM *drbg_hash_gettable_ctx_params(ossl_unused void *vctx, return known_gettable_ctx_params; } +static int drbg_fetch_digest_from_prov(const OSSL_PARAM params[], + OSSL_LIB_CTX *libctx, + EVP_MD **digest) +{ + OSSL_PROVIDER *prov = NULL; + const OSSL_PARAM *p; + EVP_MD *md = NULL; + int ret = 0; + + if (digest == NULL) + return 0; + + if ((p = OSSL_PARAM_locate_const(params, + OSSL_PROV_PARAM_CORE_PROV_NAME)) == NULL) + return 0; + if (p->data_type != OSSL_PARAM_UTF8_STRING) + return 0; + if ((prov = ossl_provider_find(libctx, (const char *)p->data, 1)) == NULL) + return 0; + + p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST); + if (p == NULL) { + ret = 1; + goto done; + } + + if (p->data_type != OSSL_PARAM_UTF8_STRING) + goto done; + + md = evp_digest_fetch_from_prov(prov, (const char *)p->data, NULL); + if (md) { + EVP_MD_free(*digest); + *digest = md; + ret = 1; + } + +done: + ossl_provider_free(prov); + return ret; +} + static int drbg_hash_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[]) { PROV_DRBG *ctx = (PROV_DRBG *)vctx; PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)ctx->data; OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx); + EVP_MD *prov_md = NULL; const EVP_MD *md; int md_size; @@ -516,8 +561,18 @@ static int drbg_hash_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[] OSSL_DRBG_PARAM_FIPS_DIGEST_CHECK)) return 0; - if (!ossl_prov_digest_load_from_params(&hash->digest, params, libctx)) - return 0; + /* try to fetch digest from provider */ + (void)ERR_set_mark(); + if (!drbg_fetch_digest_from_prov(params, libctx, &prov_md)) { + (void)ERR_pop_to_mark(); + /* fall back to full implementation search */ + if (!ossl_prov_digest_load_from_params(&hash->digest, params, libctx)) + return 0; + } else { + (void)ERR_clear_last_mark(); + if (prov_md) + ossl_prov_digest_set_md(&hash->digest, prov_md); + } md = ossl_prov_digest_md(&hash->digest); if (md != NULL) { diff --git a/providers/implementations/rands/drbg_hmac.c b/providers/implementations/rands/drbg_hmac.c index 43c75bf434d..e5766ec0490 100644 --- a/providers/implementations/rands/drbg_hmac.c +++ b/providers/implementations/rands/drbg_hmac.c @@ -19,6 +19,9 @@ #include "prov/provider_ctx.h" #include "prov/hmac_drbg.h" #include "drbg_local.h" +#include "crypto/evp.h" +#include "crypto/evp/evp_local.h" +#include "internal/provider.h" static OSSL_FUNC_rand_newctx_fn drbg_hmac_new_wrapper; static OSSL_FUNC_rand_freectx_fn drbg_hmac_free; @@ -407,11 +410,73 @@ static const OSSL_PARAM *drbg_hmac_gettable_ctx_params(ossl_unused void *vctx, return known_gettable_ctx_params; } +static int drbg_fetch_algs_from_prov(const OSSL_PARAM params[], + OSSL_LIB_CTX *libctx, + EVP_MAC_CTX **macctx, + EVP_MD **digest) +{ + OSSL_PROVIDER *prov = NULL; + const OSSL_PARAM *p; + EVP_MD *md = NULL; + EVP_MAC *mac = NULL; + int ret = 0; + + if (macctx == NULL || digest == NULL) + return 0; + + if ((p = OSSL_PARAM_locate_const(params, + OSSL_PROV_PARAM_CORE_PROV_NAME)) == NULL) + return 0; + if (p->data_type != OSSL_PARAM_UTF8_STRING) + return 0; + if ((prov = ossl_provider_find(libctx, (const char *)p->data, 1)) == NULL) + return 0; + + p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST); + if (p) { + if (p->data_type != OSSL_PARAM_UTF8_STRING) + goto done; + + md = evp_digest_fetch_from_prov(prov, (const char *)p->data, NULL); + if (md) { + EVP_MD_free(*digest); + *digest = md; + } else { + goto done; + } + } + + p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_MAC); + if (p == NULL) { + ret = 1; + goto done; + } + + if (p->data_type != OSSL_PARAM_UTF8_STRING) + goto done; + + EVP_MAC_CTX_free(*macctx); + *macctx = NULL; + + mac = evp_mac_fetch_from_prov(prov, (const char *)p->data, NULL); + if (mac) { + *macctx = EVP_MAC_CTX_new(mac); + /* The context holds on to the MAC */ + EVP_MAC_free(mac); + ret = 1; + } + +done: + ossl_provider_free(prov); + return ret; +} + static int drbg_hmac_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[]) { PROV_DRBG *ctx = (PROV_DRBG *)vctx; PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)ctx->data; OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx); + EVP_MD *prov_md = NULL; const EVP_MD *md; int md_size; @@ -419,17 +484,27 @@ static int drbg_hmac_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[] OSSL_DRBG_PARAM_FIPS_DIGEST_CHECK)) return 0; - if (!ossl_prov_digest_load_from_params(&hmac->digest, params, libctx)) - return 0; + /* try to fetch mac and digest from provider */ + (void)ERR_set_mark(); + if (!drbg_fetch_algs_from_prov(params, libctx, &hmac->ctx, &prov_md)) { + (void)ERR_pop_to_mark(); + /* fall back to full implementation search */ + if (!ossl_prov_digest_load_from_params(&hmac->digest, params, libctx)) + return 0; + + if (!ossl_prov_macctx_load_from_params(&hmac->ctx, params, + NULL, NULL, NULL, libctx)) + return 0; + } else { + (void)ERR_clear_last_mark(); + if (prov_md) + ossl_prov_digest_set_md(&hmac->digest, prov_md); + } md = ossl_prov_digest_md(&hmac->digest); if (md != NULL && !ossl_drbg_verify_digest(ctx, libctx, md)) return 0; /* Error already raised for us */ - if (!ossl_prov_macctx_load_from_params(&hmac->ctx, params, - NULL, NULL, NULL, libctx)) - return 0; - if (md != NULL && hmac->ctx != NULL) { /* These are taken from SP 800-90 10.1 Table 2 */ md_size = EVP_MD_get_size(md);