]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Prefer DRBG ciphers from the same provider
authorSimo Sorce <simo@redhat.com>
Thu, 23 Jan 2025 16:01:39 +0000 (11:01 -0500)
committerDmitry Belyavskiy <beldmit@gmail.com>
Tue, 11 Feb 2025 20:48:15 +0000 (21:48 +0100)
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/evp_enc.c
crypto/evp/evp_local.h
crypto/rand/rand_lib.c
providers/implementations/rands/drbg_ctr.c

index 17320191340c2bf413322710758e25bf3a1fb616..833ebdee28701790843c103d7ba5eefa407a4a64 100644 (file)
@@ -1886,6 +1886,17 @@ EVP_CIPHER *EVP_CIPHER_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
     return cipher;
 }
 
+EVP_CIPHER *evp_cipher_fetch_from_prov(OSSL_PROVIDER *prov,
+                                       const char *algorithm,
+                                       const char *properties)
+{
+    return evp_generic_fetch_from_prov(prov, OSSL_OP_CIPHER,
+                                       algorithm, properties,
+                                       evp_cipher_from_algorithm,
+                                       evp_cipher_up_ref,
+                                       evp_cipher_free);
+}
+
 int EVP_CIPHER_can_pipeline(const EVP_CIPHER *cipher, int enc)
 {
     if (((enc && cipher->p_einit != NULL) || (!enc && cipher->p_dinit != NULL))
index 352f4ff2e527dacd3bfe44d2385859d9fc2009fd..278e551552030e2e03a536237dad904fc4673727 100644 (file)
@@ -317,6 +317,9 @@ EVP_KEYEXCH *evp_keyexch_fetch_from_prov(OSSL_PROVIDER *prov,
 EVP_KEM *evp_kem_fetch_from_prov(OSSL_PROVIDER *prov,
                                  const char *name,
                                  const char *properties);
+EVP_CIPHER *evp_cipher_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 ce7dfb12c806c3240d725733fd94ce0b6a198c9f..566504f3ff1ddd5cb1db04df24b247e620f9fba2 100644 (file)
@@ -21,6 +21,7 @@
 #include "crypto/cryptlib.h"
 #include "rand_local.h"
 #include "crypto/context.h"
+#include "internal/provider.h"
 
 #ifndef OPENSSL_DEFAULT_SEED_SRC
 # define OPENSSL_DEFAULT_SEED_SRC SEED-SRC
@@ -724,8 +725,9 @@ static EVP_RAND_CTX *rand_new_drbg(OSSL_LIB_CTX *libctx, EVP_RAND_CTX *parent,
     EVP_RAND *rand;
     RAND_GLOBAL *dgbl = rand_get_global(libctx);
     EVP_RAND_CTX *ctx;
-    OSSL_PARAM params[8], *p = params;
+    OSSL_PARAM params[9], *p = params;
     const OSSL_PARAM *settables;
+    const char *prov_name;
     char *name, *cipher;
     int use_df = 1;
 
@@ -737,6 +739,7 @@ static EVP_RAND_CTX *rand_new_drbg(OSSL_LIB_CTX *libctx, EVP_RAND_CTX *parent,
         ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_FETCH_DRBG);
         return NULL;
     }
+    prov_name = ossl_provider_name(EVP_RAND_get0_provider(rand));
     ctx = EVP_RAND_CTX_new(rand, parent);
     EVP_RAND_free(rand);
     if (ctx == NULL) {
@@ -754,6 +757,9 @@ static EVP_RAND_CTX *rand_new_drbg(OSSL_LIB_CTX *libctx, EVP_RAND_CTX *parent,
             && OSSL_PARAM_locate_const(settables, OSSL_DRBG_PARAM_DIGEST))
         *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_DIGEST,
                                                 dgbl->rng_digest, 0);
+    if (prov_name != NULL)
+        *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_CORE_PROV_NAME,
+                                                (char *)prov_name, 0);
     if (dgbl->rng_propq != NULL)
         *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_PROPERTIES,
                                                 dgbl->rng_propq, 0);
index abd0b1a1c89326069253f06c2ec374455267be01..4aa1aa907e45822ef24fb941251ecb8746a947f4 100644 (file)
@@ -20,6 +20,9 @@
 #include "prov/providercommon.h"
 #include "prov/provider_ctx.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_ctr_new_wrapper;
 static OSSL_FUNC_rand_freectx_fn drbg_ctr_free;
@@ -709,6 +712,7 @@ static int drbg_ctr_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[])
     PROV_DRBG *ctx = (PROV_DRBG *)vctx;
     PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)ctx->data;
     OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
+    OSSL_PROVIDER *prov = NULL;
     const OSSL_PARAM *p;
     char *ecb;
     const char *propquery = NULL;
@@ -728,32 +732,66 @@ static int drbg_ctr_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[])
         propquery = (const char *)p->data;
     }
 
+    if ((p = OSSL_PARAM_locate_const(params,
+                                     OSSL_PROV_PARAM_CORE_PROV_NAME)) != NULL) {
+        if (p->data_type != OSSL_PARAM_UTF8_STRING)
+            return 0;
+        if ((prov = ossl_provider_find(libctx,
+                                       (const char *)p->data, 1)) == NULL)
+            return 0;
+    }
+
     if ((p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_CIPHER)) != NULL) {
         const char *base = (const char *)p->data;
         size_t ctr_str_len = sizeof("CTR") - 1;
         size_t ecb_str_len = sizeof("ECB") - 1;
 
         if (p->data_type != OSSL_PARAM_UTF8_STRING
-                || p->data_size < ctr_str_len)
+                || p->data_size < ctr_str_len) {
+            ossl_provider_free(prov);
             return 0;
+        }
         if (OPENSSL_strcasecmp("CTR", base + p->data_size - ctr_str_len) != 0) {
             ERR_raise(ERR_LIB_PROV, PROV_R_REQUIRE_CTR_MODE_CIPHER);
+            ossl_provider_free(prov);
             return 0;
         }
-        if ((ecb = OPENSSL_strndup(base, p->data_size)) == NULL)
+        if ((ecb = OPENSSL_strndup(base, p->data_size)) == NULL) {
+            ossl_provider_free(prov);
             return 0;
+        }
         strcpy(ecb + p->data_size - ecb_str_len, "ECB");
         EVP_CIPHER_free(ctr->cipher_ecb);
         EVP_CIPHER_free(ctr->cipher_ctr);
-        ctr->cipher_ctr = EVP_CIPHER_fetch(libctx, base, propquery);
-        ctr->cipher_ecb = EVP_CIPHER_fetch(libctx, ecb, propquery);
+        /*
+         * Try to fetch algorithms from our own provider code, fallback
+         * to generic fetch only if that fails
+         */
+        (void)ERR_set_mark();
+        ctr->cipher_ctr = evp_cipher_fetch_from_prov(prov, base, NULL);
+        if (ctr->cipher_ctr == NULL) {
+            (void)ERR_pop_to_mark();
+            ctr->cipher_ctr = EVP_CIPHER_fetch(libctx, base, propquery);
+        } else {
+            (void)ERR_clear_last_mark();
+        }
+        (void)ERR_set_mark();
+        ctr->cipher_ecb = evp_cipher_fetch_from_prov(prov, ecb, NULL);
+        if (ctr->cipher_ecb == NULL) {
+            (void)ERR_pop_to_mark();
+            ctr->cipher_ecb = EVP_CIPHER_fetch(libctx, ecb, propquery);
+        } else {
+            (void)ERR_clear_last_mark();
+        }
         OPENSSL_free(ecb);
         if (ctr->cipher_ctr == NULL || ctr->cipher_ecb == NULL) {
             ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_FIND_CIPHERS);
+            ossl_provider_free(prov);
             return 0;
         }
         cipher_init = 1;
     }
+    ossl_provider_free(prov);
 
     if (cipher_init && !drbg_ctr_init(ctx))
         return 0;