]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add RAND_set1_random_provider() API
authorPauli <ppzgs1@gmail.com>
Wed, 22 May 2024 03:23:16 +0000 (13:23 +1000)
committerPauli <ppzgs1@gmail.com>
Tue, 4 Feb 2025 20:20:10 +0000 (07:20 +1100)
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/24498)

crypto/rand/rand_lib.c
include/openssl/rand.h

index a15614faa51a41b3723ddb92338e278d4dd638a3..eb983a60676af5dedbe697fbc791fb32f597f29c 100644 (file)
 #include <openssl/err.h>
 #include <openssl/opensslconf.h>
 #include <openssl/core_names.h>
+#include <openssl/provider.h>
 #include "internal/cryptlib.h"
+#include "internal/provider.h"
 #include "internal/thread_once.h"
 #include "crypto/rand.h"
 #include "crypto/cryptlib.h"
 #include "rand_local.h"
 #include "crypto/context.h"
 
+
 #ifndef OPENSSL_DEFAULT_SEED_SRC
 # define OPENSSL_DEFAULT_SEED_SRC SEED-SRC
 #endif
 
+typedef struct rand_global_st {
+    /*
+     * The three shared DRBG instances
+     *
+     * There are three shared DRBG instances: <primary>, <public>, and
+     * <private>.  The <public> and <private> DRBGs are secondary ones.
+     * These are used for non-secret (e.g. nonces) and secret
+     * (e.g. private keys) data respectively.
+     */
+    CRYPTO_RWLOCK *lock;
+
+    EVP_RAND_CTX *seed;
+
+    /*
+     * The <primary> DRBG
+     *
+     * Not used directly by the application, only for reseeding the two other
+     * DRBGs. It reseeds itself by pulling either randomness from os entropy
+     * sources or by consuming randomness which was added by RAND_add().
+     *
+     * The <primary> DRBG is a global instance which is accessed concurrently by
+     * all threads. The necessary locking is managed automatically by its child
+     * DRBG instances during reseeding.
+     */
+    EVP_RAND_CTX *primary;
+
+    /*
+     * The provider which we'll use to generate randomness.
+     */
+#ifndef FIPS_MODULE
+    OSSL_PROVIDER *random_provider;
+#endif      /* !FIPS_MODULE */
+
+    /*
+     * The <public> DRBG
+     *
+     * Used by default for generating random bytes using RAND_bytes().
+     *
+     * The <public> secondary DRBG is thread-local, i.e., there is one instance
+     * per thread.
+     */
+    CRYPTO_THREAD_LOCAL public;
+
+    /*
+     * The <private> DRBG
+     *
+     * Used by default for generating private keys using RAND_priv_bytes()
+     *
+     * The <private> secondary DRBG is thread-local, i.e., there is one
+     * instance per thread.
+     */
+    CRYPTO_THREAD_LOCAL private;
+
+    /* Which RNG is being used by default and it's configuration settings */
+    char *rng_name;
+    char *rng_cipher;
+    char *rng_digest;
+    char *rng_propq;
+
+    /* Allow the randomness source to be changed */
+    char *seed_name;
+    char *seed_propq;
+} RAND_GLOBAL;
+
+static EVP_RAND_CTX *rand_get0_public(OSSL_LIB_CTX *ctx, RAND_GLOBAL *dgbl);
+static EVP_RAND_CTX *rand_get0_private(OSSL_LIB_CTX *ctx, RAND_GLOBAL *dgbl);
+
+static RAND_GLOBAL *rand_get_global(OSSL_LIB_CTX *libctx)
+{
+    return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DRBG_INDEX);
+}
+
 #ifndef FIPS_MODULE
 # include <stdio.h>
 # include <time.h>
 /* non-NULL if default_RAND_meth is ENGINE-provided */
 static ENGINE *funct_ref;
 static CRYPTO_RWLOCK *rand_engine_lock;
-# endif
+# endif     /* !OPENSSL_NO_ENGINE */
 # ifndef OPENSSL_NO_DEPRECATED_3_0
 static CRYPTO_RWLOCK *rand_meth_lock;
 static const RAND_METHOD *default_RAND_meth;
-# endif
+# endif     /* !OPENSSL_NO_DEPRECATED_3_0 */
 static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT;
 
 static int rand_inited = 0;
@@ -55,13 +130,13 @@ DEFINE_RUN_ONCE_STATIC(do_rand_init)
     rand_engine_lock = CRYPTO_THREAD_lock_new();
     if (rand_engine_lock == NULL)
         return 0;
-# endif
+# endif     /* !OPENSSL_NO_ENGINE */
 
 # ifndef OPENSSL_NO_DEPRECATED_3_0
     rand_meth_lock = CRYPTO_THREAD_lock_new();
     if (rand_meth_lock == NULL)
         goto err;
-# endif
+# endif     /* !OPENSSL_NO_DEPRECATED_3_0 */
 
     if (!ossl_rand_pool_init())
         goto err;
@@ -73,11 +148,11 @@ DEFINE_RUN_ONCE_STATIC(do_rand_init)
 # ifndef OPENSSL_NO_DEPRECATED_3_0
     CRYPTO_THREAD_lock_free(rand_meth_lock);
     rand_meth_lock = NULL;
-# endif
+# endif     /* !OPENSSL_NO_DEPRECATED_3_0 */
 # ifndef OPENSSL_NO_ENGINE
     CRYPTO_THREAD_lock_free(rand_engine_lock);
     rand_engine_lock = NULL;
-# endif
+# endif     /* !OPENSSL_NO_ENGINE */
     return 0;
 }
 
@@ -92,16 +167,16 @@ void ossl_rand_cleanup_int(void)
     if (meth != NULL && meth->cleanup != NULL)
         meth->cleanup();
     RAND_set_rand_method(NULL);
-# endif
+# endif     /* !OPENSSL_NO_DEPRECATED_3_0 */
     ossl_rand_pool_cleanup();
 # ifndef OPENSSL_NO_ENGINE
     CRYPTO_THREAD_lock_free(rand_engine_lock);
     rand_engine_lock = NULL;
-# endif
+# endif     /* !OPENSSL_NO_ENGINE */
 # ifndef OPENSSL_NO_DEPRECATED_3_0
     CRYPTO_THREAD_lock_free(rand_meth_lock);
     rand_meth_lock = NULL;
-# endif
+# endif     /* !OPENSSL_NO_DEPRECATED_3_0 */
     ossl_release_default_drbg_ctx();
     rand_inited = 0;
 }
@@ -158,7 +233,7 @@ int RAND_poll(void)
         ossl_rand_pool_free(pool);
         return ret;
     }
-# endif
+# endif     /* !OPENSSL_NO_DEPRECATED_3_0 */
 
     RAND_seed(salt, sizeof(salt));
     return 1;
@@ -338,6 +413,7 @@ const RAND_METHOD *RAND_get_rand_method(void)
 int RAND_priv_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num,
                        unsigned int strength)
 {
+    RAND_GLOBAL *dgbl;
     EVP_RAND_CTX *rand;
 #if !defined(OPENSSL_NO_DEPRECATED_3_0) && !defined(FIPS_MODULE)
     const RAND_METHOD *meth = RAND_get_rand_method();
@@ -350,7 +426,16 @@ int RAND_priv_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num,
     }
 #endif
 
-    rand = RAND_get0_private(ctx);
+    dgbl = rand_get_global(ctx);
+    if (dgbl == NULL)
+        return 0;
+#ifndef FIPS_MODULE
+    if (dgbl->random_provider != NULL)
+        return ossl_provider_random(dgbl->random_provider,
+                                    OSSL_PROV_RANDOM_PRIVATE,
+                                    buf, num, strength);
+#endif      /* !FIPS_MODULE */
+    rand = rand_get0_private(ctx, dgbl);
     if (rand != NULL)
         return EVP_RAND_generate(rand, buf, num, strength, 0, NULL, 0);
 
@@ -367,6 +452,7 @@ int RAND_priv_bytes(unsigned char *buf, int num)
 int RAND_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num,
                   unsigned int strength)
 {
+    RAND_GLOBAL *dgbl;
     EVP_RAND_CTX *rand;
 #if !defined(OPENSSL_NO_DEPRECATED_3_0) && !defined(FIPS_MODULE)
     const RAND_METHOD *meth = RAND_get_rand_method();
@@ -379,7 +465,17 @@ int RAND_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num,
     }
 #endif
 
-    rand = RAND_get0_public(ctx);
+    dgbl = rand_get_global(ctx);
+    if (dgbl == NULL)
+        return 0;
+#ifndef FIPS_MODULE
+    if (dgbl->random_provider != NULL)
+        return ossl_provider_random(dgbl->random_provider,
+                                    OSSL_PROV_RANDOM_PRIVATE,
+                                    buf, num, strength);
+#endif      /* !FIPS_MODULE */
+
+    rand = rand_get0_public(ctx, dgbl);
     if (rand != NULL)
         return EVP_RAND_generate(rand, buf, num, strength, 0, NULL, 0);
 
@@ -393,63 +489,6 @@ int RAND_bytes(unsigned char *buf, int num)
     return RAND_bytes_ex(NULL, buf, (size_t)num, 0);
 }
 
-typedef struct rand_global_st {
-    /*
-     * The three shared DRBG instances
-     *
-     * There are three shared DRBG instances: <primary>, <public>, and
-     * <private>.  The <public> and <private> DRBGs are secondary ones.
-     * These are used for non-secret (e.g. nonces) and secret
-     * (e.g. private keys) data respectively.
-     */
-    CRYPTO_RWLOCK *lock;
-
-    EVP_RAND_CTX *seed;
-
-    /*
-     * The <primary> DRBG
-     *
-     * Not used directly by the application, only for reseeding the two other
-     * DRBGs. It reseeds itself by pulling either randomness from os entropy
-     * sources or by consuming randomness which was added by RAND_add().
-     *
-     * The <primary> DRBG is a global instance which is accessed concurrently by
-     * all threads. The necessary locking is managed automatically by its child
-     * DRBG instances during reseeding.
-     */
-    EVP_RAND_CTX *primary;
-
-    /*
-     * The <public> DRBG
-     *
-     * Used by default for generating random bytes using RAND_bytes().
-     *
-     * The <public> secondary DRBG is thread-local, i.e., there is one instance
-     * per thread.
-     */
-    CRYPTO_THREAD_LOCAL public;
-
-    /*
-     * The <private> DRBG
-     *
-     * Used by default for generating private keys using RAND_priv_bytes()
-     *
-     * The <private> secondary DRBG is thread-local, i.e., there is one
-     * instance per thread.
-     */
-    CRYPTO_THREAD_LOCAL private;
-
-    /* Which RNG is being used by default and it's configuration settings */
-    char *rng_name;
-    char *rng_cipher;
-    char *rng_digest;
-    char *rng_propq;
-
-    /* Allow the randomness source to be changed */
-    char *seed_name;
-    char *seed_propq;
-} RAND_GLOBAL;
-
 /*
  * Initialize the OSSL_LIB_CTX global DRBGs on first use.
  * Returns the allocated global data on success or NULL on failure.
@@ -501,6 +540,9 @@ void ossl_rand_ctx_free(void *vdgbl)
     CRYPTO_THREAD_cleanup_local(&dgbl->public);
     EVP_RAND_CTX_free(dgbl->primary);
     EVP_RAND_CTX_free(dgbl->seed);
+#ifndef FIPS_MODULE
+    OSSL_PROVIDER_unload(dgbl->random_provider);
+#endif      /* !FIPS_MODULE */
     OPENSSL_free(dgbl->rng_name);
     OPENSSL_free(dgbl->rng_cipher);
     OPENSSL_free(dgbl->rng_digest);
@@ -511,11 +553,6 @@ void ossl_rand_ctx_free(void *vdgbl)
     OPENSSL_free(dgbl);
 }
 
-static RAND_GLOBAL *rand_get_global(OSSL_LIB_CTX *libctx)
-{
-    return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DRBG_INDEX);
-}
-
 static void rand_delete_thread_state(void *arg)
 {
     OSSL_LIB_CTX *ctx = arg;
@@ -799,13 +836,8 @@ EVP_RAND_CTX *RAND_get0_primary(OSSL_LIB_CTX *ctx)
     return ret;
 }
 
-/*
- * Get the public random generator.
- * Returns pointer to its EVP_RAND_CTX on success, NULL on failure.
- */
-EVP_RAND_CTX *RAND_get0_public(OSSL_LIB_CTX *ctx)
+static EVP_RAND_CTX *rand_get0_public(OSSL_LIB_CTX *ctx, RAND_GLOBAL *dgbl)
 {
-    RAND_GLOBAL *dgbl = rand_get_global(ctx);
     EVP_RAND_CTX *rand, *primary;
 
     if (dgbl == NULL)
@@ -836,16 +868,19 @@ EVP_RAND_CTX *RAND_get0_public(OSSL_LIB_CTX *ctx)
 }
 
 /*
- * Get the private random generator.
+ * Get the public random generator.
  * Returns pointer to its EVP_RAND_CTX on success, NULL on failure.
  */
-EVP_RAND_CTX *RAND_get0_private(OSSL_LIB_CTX *ctx)
+EVP_RAND_CTX *RAND_get0_public(OSSL_LIB_CTX *ctx)
 {
     RAND_GLOBAL *dgbl = rand_get_global(ctx);
-    EVP_RAND_CTX *rand, *primary;
 
-    if (dgbl == NULL)
-        return NULL;
+    return dgbl == NULL ? NULL : rand_get0_public(ctx, dgbl);
+}
+
+static EVP_RAND_CTX *rand_get0_private(OSSL_LIB_CTX *ctx, RAND_GLOBAL *dgbl)
+{
+    EVP_RAND_CTX *rand, *primary;
 
     rand = CRYPTO_THREAD_get_local(&dgbl->private);
     if (rand == NULL) {
@@ -871,6 +906,17 @@ EVP_RAND_CTX *RAND_get0_private(OSSL_LIB_CTX *ctx)
     return rand;
 }
 
+/*
+ * Get the private random generator.
+ * Returns pointer to its EVP_RAND_CTX on success, NULL on failure.
+ */
+EVP_RAND_CTX *RAND_get0_private(OSSL_LIB_CTX *ctx)
+{
+    RAND_GLOBAL *dgbl = rand_get_global(ctx);
+
+    return dgbl == NULL ? NULL : rand_get0_private(ctx, dgbl);
+}
+
 #ifdef FIPS_MODULE
 EVP_RAND_CTX *ossl_rand_get0_private_noncreating(OSSL_LIB_CTX *ctx)
 {
@@ -1023,4 +1069,16 @@ int RAND_set_seed_source_type(OSSL_LIB_CTX *ctx, const char *seed,
         && random_set_string(&dgbl->seed_propq, propq);
 }
 
-#endif
+int RAND_set0_random_provider(OSSL_LIB_CTX *ctx, OSSL_PROVIDER *p)
+{
+    RAND_GLOBAL *dgbl = rand_get_global(ctx);
+    OSSL_PROVIDER *old;
+
+    if (dgbl == NULL)
+        return 0;
+    old = dgbl->random_provider;
+    dgbl->random_provider = p;
+    OSSL_PROVIDER_unload(old);
+    return 1;
+}
+#endif      /* !FIPS_MODULE */
index cb9fda49910d1acdaceeb9348b84479c839ee769..5f216c198ebd57a4c164539901595b532e0c54c0 100644 (file)
@@ -118,6 +118,9 @@ OSSL_DEPRECATEDIN_1_1_0 int RAND_event(UINT, WPARAM, LPARAM);
 #  endif
 # endif
 
+int RAND_set1_random_provider(OSSL_LIB_CTX *ctx, OSSL_PROVIDER *p);
+
+/* Which parameter to provider_random call */
 #define OSSL_PROV_RANDOM_PUBLIC     0
 #define OSSL_PROV_RANDOM_PRIVATE    1