]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Change also other DRBG's algorithm fetching
authorSimo Sorce <simo@redhat.com>
Fri, 7 Feb 2025 16:21:51 +0000 (11:21 -0500)
committerDmitry Belyavskiy <beldmit@gmail.com>
Tue, 11 Feb 2025 20:48:15 +0000 (21:48 +0100)
- DRBG_HASH
- DRBG_HMAC

Signed-off-by: Simo Sorce <simo@redhat.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/26542)

crypto/evp/digest.c
crypto/evp/evp_local.h
crypto/evp/mac_meth.c
providers/common/include/prov/provider_util.h
providers/common/provider_util.c
providers/implementations/rands/drbg_hash.c
providers/implementations/rands/drbg_hmac.c

index 6aa175fb3f4beb7f63afaa1fbcae3bcd1d45f248..4b8a9bb27daab990aee14a0aba87854d4fe688b3 100644 (file)
@@ -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;
index 278e551552030e2e03a536237dad904fc4673727..ef1faa4516f3a4a933c30147f79ba085698c5395 100644 (file)
@@ -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);
index a3e7a0220850db2f517ef129a4db64cfa1d2d291..07c159acf713bb7fb6916b2030fe633fdf9780b2 100644 (file)
@@ -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);
+}
index 5511565e79b3a2b6e5836eebb1355f341fba95ca..7b74e0fdedba194adc23bb4e4506e0b3355e2f9e 100644 (file)
@@ -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.
index 5097d71e27ccecf25b3d12c6791f74cbff341229..1fd74cb30685338606b888a7327202c96662773c 100644 (file)
@@ -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;
index 458b356b82f8f69cd5ebfd637cd1827631bee71d..7adbcd19550650a5a4dd32551d7d56d21add1967 100644 (file)
@@ -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) {
index 43c75bf434dc958297fd549ea50ff1b6cd6cfd62..e5766ec049060c3a4cf033ca47ab68d01587ac76 100644 (file)
@@ -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);