2
0
mirror of https://github.com/openssl/openssl.git synced 2025-04-24 20:51:14 +08:00

Add RAND_set1_random_provider() API

Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/24498)
This commit is contained in:
Pauli 2024-05-22 13:23:16 +10:00
parent 37172e2ab8
commit 4636a39503
2 changed files with 147 additions and 86 deletions
crypto/rand
include/openssl

@ -13,17 +13,92 @@
#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>
@ -40,11 +115,11 @@
/* 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 */

@ -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