From 4cde7585ce8eb53682256ba79e6af1949498fbfe Mon Sep 17 00:00:00 2001 From: Pauli Date: Tue, 5 Sep 2023 12:51:05 +1000 Subject: [PATCH] fips: use seed source requested Fixes #21909 Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/21964) --- crypto/initthread.c | 2 +- crypto/provider_core.c | 68 +++++++++++-- crypto/rand/prov_seed.c | 66 ++++++++++++- crypto/rand/rand_lib.c | 100 +++++++++++++++++--- doc/internal/man3/ossl_rand_get_entropy.pod | 45 +++++++-- doc/man7/EVP_RAND-TEST-RAND.pod | 7 ++ doc/man7/provider-base.pod | 28 +++++- include/crypto/rand.h | 17 +++- include/openssl/core_dispatch.h | 11 +++ providers/baseprov.c | 8 ++ providers/common/provider_seeding.c | 53 +++++++++-- 11 files changed, 350 insertions(+), 55 deletions(-) diff --git a/crypto/initthread.c b/crypto/initthread.c index 03586bcbca..54a33c3286 100644 --- a/crypto/initthread.c +++ b/crypto/initthread.c @@ -257,7 +257,7 @@ void *ossl_thread_event_ctx_new(OSSL_LIB_CTX *libctx) if (tlocal == NULL) return NULL; - if (!CRYPTO_THREAD_init_local(tlocal, NULL)) { + if (!CRYPTO_THREAD_init_local(tlocal, NULL)) { goto err; } diff --git a/crypto/provider_core.c b/crypto/provider_core.c index 7f5e48f26c..266934937c 100644 --- a/crypto/provider_core.c +++ b/crypto/provider_core.c @@ -1930,10 +1930,12 @@ OSSL_FUNC_BIO_free_fn ossl_core_bio_free; OSSL_FUNC_BIO_vprintf_fn ossl_core_bio_vprintf; OSSL_FUNC_BIO_vsnprintf_fn BIO_vsnprintf; static OSSL_FUNC_self_test_cb_fn core_self_test_get_callback; -OSSL_FUNC_get_entropy_fn ossl_rand_get_entropy; -OSSL_FUNC_cleanup_entropy_fn ossl_rand_cleanup_entropy; -OSSL_FUNC_get_nonce_fn ossl_rand_get_nonce; -OSSL_FUNC_cleanup_nonce_fn ossl_rand_cleanup_nonce; +static OSSL_FUNC_get_user_entropy_fn rand_get_user_entropy; +static OSSL_FUNC_get_entropy_fn rand_get_entropy; +static OSSL_FUNC_cleanup_entropy_fn rand_cleanup_entropy; +static OSSL_FUNC_get_user_nonce_fn rand_get_user_nonce; +static OSSL_FUNC_get_nonce_fn rand_get_nonce; +static OSSL_FUNC_cleanup_nonce_fn rand_cleanup_nonce; #endif OSSL_FUNC_CRYPTO_malloc_fn CRYPTO_malloc; OSSL_FUNC_CRYPTO_zalloc_fn CRYPTO_zalloc; @@ -2094,6 +2096,54 @@ static void core_self_test_get_callback(OPENSSL_CORE_CTX *libctx, OSSL_SELF_TEST_get_callback((OSSL_LIB_CTX *)libctx, cb, cbarg); } +static size_t rand_get_entropy(const OSSL_CORE_HANDLE *handle, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len) +{ + return ossl_rand_get_entropy((OSSL_LIB_CTX *)core_get_libctx(handle), + pout, entropy, min_len, max_len); +} + +static size_t rand_get_user_entropy(const OSSL_CORE_HANDLE *handle, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len) +{ + return ossl_rand_get_user_entropy((OSSL_LIB_CTX *)core_get_libctx(handle), + pout, entropy, min_len, max_len); +} + +static void rand_cleanup_entropy(const OSSL_CORE_HANDLE *handle, + unsigned char *buf, size_t len) +{ + ossl_rand_cleanup_entropy((OSSL_LIB_CTX *)core_get_libctx(handle), + buf, len); +} + +static size_t rand_get_nonce(const OSSL_CORE_HANDLE *handle, + unsigned char **pout, + size_t min_len, size_t max_len, + const void *salt, size_t salt_len) +{ + return ossl_rand_get_nonce((OSSL_LIB_CTX *)core_get_libctx(handle), + pout, min_len, max_len, salt, salt_len); +} + +static size_t rand_get_user_nonce(const OSSL_CORE_HANDLE *handle, + unsigned char **pout, + size_t min_len, size_t max_len, + const void *salt, size_t salt_len) +{ + return ossl_rand_get_user_nonce((OSSL_LIB_CTX *)core_get_libctx(handle), + pout, min_len, max_len, salt, salt_len); +} + +static void rand_cleanup_nonce(const OSSL_CORE_HANDLE *handle, + unsigned char *buf, size_t len) +{ + ossl_rand_cleanup_nonce((OSSL_LIB_CTX *)core_get_libctx(handle), + buf, len); +} + static const char *core_provider_get0_name(const OSSL_CORE_HANDLE *prov) { return OSSL_PROVIDER_get0_name((const OSSL_PROVIDER *)prov); @@ -2187,10 +2237,12 @@ static const OSSL_DISPATCH core_dispatch_[] = { { OSSL_FUNC_BIO_VPRINTF, (void (*)(void))ossl_core_bio_vprintf }, { OSSL_FUNC_BIO_VSNPRINTF, (void (*)(void))BIO_vsnprintf }, { OSSL_FUNC_SELF_TEST_CB, (void (*)(void))core_self_test_get_callback }, - { OSSL_FUNC_GET_ENTROPY, (void (*)(void))ossl_rand_get_entropy }, - { OSSL_FUNC_CLEANUP_ENTROPY, (void (*)(void))ossl_rand_cleanup_entropy }, - { OSSL_FUNC_GET_NONCE, (void (*)(void))ossl_rand_get_nonce }, - { OSSL_FUNC_CLEANUP_NONCE, (void (*)(void))ossl_rand_cleanup_nonce }, + { OSSL_FUNC_GET_ENTROPY, (void (*)(void))rand_get_entropy }, + { OSSL_FUNC_CLEANUP_ENTROPY, (void (*)(void))rand_cleanup_entropy }, + { OSSL_FUNC_GET_NONCE, (void (*)(void))rand_get_nonce }, + { OSSL_FUNC_CLEANUP_NONCE, (void (*)(void))rand_cleanup_nonce }, + { OSSL_FUNC_GET_USER_ENTROPY, (void (*)(void))rand_get_user_entropy }, + { OSSL_FUNC_GET_USER_NONCE, (void (*)(void))rand_get_user_nonce }, #endif { OSSL_FUNC_CRYPTO_MALLOC, (void (*)(void))CRYPTO_malloc }, { OSSL_FUNC_CRYPTO_ZALLOC, (void (*)(void))CRYPTO_zalloc }, diff --git a/crypto/rand/prov_seed.c b/crypto/rand/prov_seed.c index 546c204094..96c73f7e66 100644 --- a/crypto/rand/prov_seed.c +++ b/crypto/rand/prov_seed.c @@ -7,12 +7,14 @@ * https://www.openssl.org/source/license.html */ +#include "rand_local.h" #include "crypto/rand.h" #include "crypto/rand_pool.h" +#include "internal/core.h" #include #include -size_t ossl_rand_get_entropy(ossl_unused const OSSL_CORE_HANDLE *handle, +size_t ossl_rand_get_entropy(ossl_unused OSSL_LIB_CTX *ctx, unsigned char **pout, int entropy, size_t min_len, size_t max_len) { @@ -38,14 +40,46 @@ size_t ossl_rand_get_entropy(ossl_unused const OSSL_CORE_HANDLE *handle, return ret; } -void ossl_rand_cleanup_entropy(ossl_unused const OSSL_CORE_HANDLE *handle, +size_t ossl_rand_get_user_entropy(OSSL_LIB_CTX *ctx, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len) +{ + unsigned char *buf; + EVP_RAND_CTX *rng = ossl_rand_get0_seed_noncreating(ctx); + size_t ret; + + if (rng == NULL) + return ossl_rand_get_entropy(ctx, pout, entropy, min_len, max_len); + + /* Determine how many bytes to generate */ + ret = entropy > 0 ? (size_t)(7 + entropy) / 8 : min_len; + if (ret < min_len) + ret = min_len; + else if (ret > max_len) + ret = max_len; + + /* Allocate the return buffer */ + if ((buf = OPENSSL_secure_malloc(ret)) == NULL) + return 0; + + /* Fill the buffer */ + if (!EVP_RAND_generate(rng, buf, ret, entropy, 0, NULL, 0)) { + OPENSSL_free(buf); + return 0; + } + *pout = buf; + return ret; +} + +void ossl_rand_cleanup_entropy(ossl_unused OSSL_LIB_CTX *ctx, unsigned char *buf, size_t len) { OPENSSL_secure_clear_free(buf, len); } -size_t ossl_rand_get_nonce(ossl_unused const OSSL_CORE_HANDLE *handle, - unsigned char **pout, size_t min_len, size_t max_len, +size_t ossl_rand_get_nonce(ossl_unused OSSL_LIB_CTX *ctx, + unsigned char **pout, + size_t min_len, ossl_unused size_t max_len, const void *salt, size_t salt_len) { size_t ret = 0; @@ -69,7 +103,29 @@ size_t ossl_rand_get_nonce(ossl_unused const OSSL_CORE_HANDLE *handle, return ret; } -void ossl_rand_cleanup_nonce(ossl_unused const OSSL_CORE_HANDLE *handle, +size_t ossl_rand_get_user_nonce(OSSL_LIB_CTX *ctx, + unsigned char **pout, + size_t min_len, size_t max_len, + const void *salt, size_t salt_len) +{ + unsigned char *buf; + EVP_RAND_CTX *rng = ossl_rand_get0_seed_noncreating(ctx); + + if (rng == NULL) + return ossl_rand_get_nonce(ctx, pout, min_len, max_len, salt, salt_len); + + if ((buf = OPENSSL_malloc(min_len)) == NULL) + return 0; + + if (!EVP_RAND_generate(rng, buf, min_len, 0, 0, salt, salt_len)) { + OPENSSL_free(buf); + return 0; + } + *pout = buf; + return min_len; +} + +void ossl_rand_cleanup_nonce(ossl_unused OSSL_LIB_CTX *ctx, unsigned char *buf, size_t len) { OPENSSL_clear_free(buf, len); diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index 4630f19da0..46e294a378 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -30,6 +30,7 @@ # include "crypto/rand_pool.h" # include "prov/seeding.h" # include "internal/e_os.h" +# include "internal/property.h" # ifndef OPENSSL_NO_ENGINE /* non-NULL if default_RAND_meth is ENGINE-provided */ @@ -345,8 +346,6 @@ int RAND_priv_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num, } #endif - if (num < 0) - return 0; rand = RAND_get0_private(ctx); if (rand != NULL) return EVP_RAND_generate(rand, buf, num, strength, 0, NULL, 0); @@ -356,6 +355,8 @@ int RAND_priv_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num, int RAND_priv_bytes(unsigned char *buf, int num) { + if (num < 0) + return 0; return RAND_priv_bytes_ex(NULL, buf, (size_t)num, 0); } @@ -374,8 +375,6 @@ int RAND_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num, } #endif - if (num < 0) - return 0; rand = RAND_get0_public(ctx); if (rand != NULL) return EVP_RAND_generate(rand, buf, num, strength, 0, NULL, 0); @@ -385,6 +384,8 @@ int RAND_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num, int RAND_bytes(unsigned char *buf, int num) { + if (num < 0) + return 0; return RAND_bytes_ex(NULL, buf, (size_t)num, 0); } @@ -534,29 +535,104 @@ static EVP_RAND_CTX *rand_new_seed(OSSL_LIB_CTX *libctx) { EVP_RAND *rand; RAND_GLOBAL *dgbl = rand_get_global(libctx); - EVP_RAND_CTX *ctx; - char *name; + EVP_RAND_CTX *ctx = NULL; + const char *propq = dgbl->seed_propq; + char *name, *props = NULL; + size_t props_len; + OSSL_PROPERTY_LIST *pl1, *pl2, *pl3 = NULL; if (dgbl == NULL) return NULL; - name = dgbl->seed_name != NULL ? dgbl->seed_name : "SEED-SRC"; - rand = EVP_RAND_fetch(libctx, name, dgbl->seed_propq); + if (dgbl->seed_name != NULL) { + name = dgbl->seed_name; + } else { + /* + * Default to our internal seed source. This isn't part of the FIPS + * provider so we need to override any FIPS properties. + */ + if (propq == NULL || *propq == '\0') { + propq = "-fips"; + } else { + pl1 = ossl_parse_query(libctx, propq, 1); + if (pl1 == NULL) { + ERR_raise(ERR_LIB_RAND, RAND_R_INVALID_PROPERTY_QUERY); + return NULL; + } + pl2 = ossl_parse_query(libctx, "-fips", 1); + if (pl2 == NULL) { + ossl_property_free(pl1); + ERR_raise(ERR_LIB_RAND, ERR_R_INTERNAL_ERROR); + return NULL; + } + pl3 = ossl_property_merge(pl2, pl1); + ossl_property_free(pl1); + ossl_property_free(pl2); + if (pl3 == NULL) { + ERR_raise(ERR_LIB_RAND, ERR_R_INTERNAL_ERROR); + return NULL; + } + props_len = ossl_property_list_to_string(libctx, pl3, NULL, 0); + if (props_len == 0) { + /* Shouldn't happen since we added a query element */ + ERR_raise(ERR_LIB_RAND, ERR_R_INTERNAL_ERROR); + goto err; + } else { + props = OPENSSL_malloc(props_len); + if (props == NULL) { + ERR_raise(ERR_LIB_RAND, ERR_R_MALLOC_FAILURE); + goto err; + } + if (ossl_property_list_to_string(libctx, pl3, + props, props_len) == 0) { + ERR_raise(ERR_LIB_RAND, ERR_R_INTERNAL_ERROR); + goto err; + } + ossl_property_free(pl3); + pl3 = NULL; + propq = props; + } + } + name = "SEED-SRC"; + } + + rand = EVP_RAND_fetch(libctx, name, propq); if (rand == NULL) { ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_FETCH_DRBG); - return NULL; + goto err; } ctx = EVP_RAND_CTX_new(rand, NULL); EVP_RAND_free(rand); if (ctx == NULL) { ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_CREATE_DRBG); - return NULL; + goto err; } if (!EVP_RAND_instantiate(ctx, 0, 0, NULL, 0, NULL)) { ERR_raise(ERR_LIB_RAND, RAND_R_ERROR_INSTANTIATING_DRBG); EVP_RAND_CTX_free(ctx); - return NULL; + goto err; } + OPENSSL_free(props); return ctx; + err: + EVP_RAND_CTX_free(ctx); + ossl_property_free(pl3); + OPENSSL_free(props); + return NULL; +} + +EVP_RAND_CTX *ossl_rand_get0_seed_noncreating(OSSL_LIB_CTX *ctx) +{ + RAND_GLOBAL *dgbl = rand_get_global(ctx); + EVP_RAND_CTX *ret; + + if (dgbl == NULL) + return NULL; + + if (!CRYPTO_THREAD_read_lock(dgbl->lock)) + return NULL; + ret = dgbl->seed; + CRYPTO_THREAD_unlock(dgbl->lock); + return ret; } #endif @@ -882,7 +958,7 @@ int RAND_set_seed_source_type(OSSL_LIB_CTX *ctx, const char *seed, if (dgbl == NULL) return 0; - if (dgbl->primary != NULL) { + if (dgbl->seed != NULL) { ERR_raise(ERR_LIB_CRYPTO, RAND_R_ALREADY_INSTANTIATED); return 0; } diff --git a/doc/internal/man3/ossl_rand_get_entropy.pod b/doc/internal/man3/ossl_rand_get_entropy.pod index 4da3f1f4d9..48343b6fe0 100644 --- a/doc/internal/man3/ossl_rand_get_entropy.pod +++ b/doc/internal/man3/ossl_rand_get_entropy.pod @@ -2,8 +2,8 @@ =head1 NAME -ossl_rand_get_entropy, ossl_rand_cleanup_entropy, -ossl_rand_get_nonce, ossl_rand_cleanup_nonce +ossl_rand_get_entropy, ossl_rand_get_user_entropy, ossl_rand_cleanup_entropy, +ossl_rand_get_nonce, ossl_rand_get_user_nonce, ossl_rand_cleanup_nonce - get seed material from the operating system =head1 SYNOPSIS @@ -13,11 +13,17 @@ ossl_rand_get_nonce, ossl_rand_cleanup_nonce size_t ossl_rand_get_entropy(OSSL_CORE_HANDLE *handle, unsigned char **pout, int entropy, size_t min_len, size_t max_len); + size_t ossl_rand_get_user_entropy(OSSL_CORE_HANDLE *handle, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len); void ossl_rand_cleanup_entropy(OSSL_CORE_HANDLE *handle, unsigned char *buf, size_t len); size_t ossl_rand_get_nonce(OSSL_CORE_HANDLE *handle, unsigned char **pout, size_t min_len, size_t max_len, const void *salt, size_t salt_len); + size_t ossl_rand_get_user_nonce(OSSL_CORE_HANDLE *handle, unsigned char **pout, + size_t min_len, size_t max_len, + const void *salt, size_t salt_len); void ossl_rand_cleanup_nonce(OSSL_CORE_HANDLE *handle, unsigned char *buf, size_t len); @@ -29,9 +35,14 @@ stored in a buffer which contains at least I and at most I bytes. The buffer address is stored in I<*pout> and the buffer length is returned to the caller. +ossl_rand_get_user_entropy() is the same as ossl_rand_get_entropy() +except that it retrieves the seeding material from the library context's +DRBG seed source. By default this is the operating system but it can +be changed by calling L. + ossl_rand_cleanup_entropy() cleanses and frees any storage allocated by -ossl_rand_get_entropy(). The seeding buffer is pointed to by I and is -of length I bytes. +ossl_rand_get_entropy() or ossl_rand_get_user_entropy(). The entropy +buffer is pointed to by I and is of length I bytes. ossl_rand_get_nonce() retrieves a nonce using the passed I parameter of length I and operating system specific information. @@ -41,18 +52,34 @@ The output is stored in a buffer which contains at least I and at most I bytes. The buffer address is stored in I<*pout> and the buffer length returned to the caller. +ossl_rand_get_user_nonce() is the same as ossl_rand_get_nonce() except +that it retrieves the seeding material from the library context's DRBG +seed source. By default this is the operating system but it can be +changed by calling L. + ossl_rand_cleanup_nonce() cleanses and frees any storage allocated by -ossl_rand_get_nonce(). The nonce buffer is pointed to by I and is -of length I bytes. +ossl_rand_get_nonce() or ossl_rand_get_user_nonce(). The nonce buffer +is pointed to by I and is of length I bytes. + +=head1 NOTES + +FIPS providers 3.0.0, 3.0.8 and 3.0.9 incorrectly pass a provider +internal pointer to ossl_rand_get_entropy(), ossl_rand_cleanup_entropy(), +ossl_rand_get_nonce() and ossl_rand_cleanup_nonce(). This pointer cannot +be safely dereferenced. =head1 RETURN VALUES -ossl_rand_get_entropy() and ossl_rand_get_nonce() return the number of bytes -in I<*pout> or 0 on error. +ossl_rand_get_entropy(), ossl_rand_get_user_entropy(), +ossl_rand_get_nonce() and ossl_rand_get_user_nonce() return the number +of bytes in I<*pout> or 0 on error. =head1 HISTORY -The functions described here were all added in OpenSSL 3.0. +The functions ossl_rand_get_user_entropy() and ossl_rand_get_user_nonce() +were added in OpenSSL 3.0.12, 3.1.4 and 3.2.0. + +The remaining functions described here were all added in OpenSSL 3.0. =head1 COPYRIGHT diff --git a/doc/man7/EVP_RAND-TEST-RAND.pod b/doc/man7/EVP_RAND-TEST-RAND.pod index ff5207565c..feab01431d 100644 --- a/doc/man7/EVP_RAND-TEST-RAND.pod +++ b/doc/man7/EVP_RAND-TEST-RAND.pod @@ -60,6 +60,13 @@ If there are insufficient data present to satisfy a call, an error is returned. Sets the bytes returned when the test generator is sent a nonce request. Each nonce request will return all of the bytes. +=item "generate" (B) + +If this parameter is zero, it will only emit the nonce and entropy data +supplied via the aforementioned parameters. Otherwise, low quality +non-cryptographic pseudorandom output is produced. This parameter defaults +to zero. + =back =head1 NOTES diff --git a/doc/man7/provider-base.pod b/doc/man7/provider-base.pod index 33d7fe7f55..eb9e8d3575 100644 --- a/doc/man7/provider-base.pod +++ b/doc/man7/provider-base.pod @@ -76,11 +76,17 @@ provider-base size_t get_entropy(const OSSL_CORE_HANDLE *handle, unsigned char **pout, int entropy, size_t min_len, size_t max_len); + size_t get_user_entropy(const OSSL_CORE_HANDLE *handle, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len); void cleanup_entropy(const OSSL_CORE_HANDLE *handle, unsigned char *buf, size_t len); size_t get_nonce(const OSSL_CORE_HANDLE *handle, unsigned char **pout, size_t min_len, size_t max_len, const void *salt, size_t salt_len); + size_t get_user_nonce(const OSSL_CORE_HANDLE *handle, + unsigned char **pout, size_t min_len, size_t max_len, + const void *salt, size_t salt_len); void cleanup_nonce(const OSSL_CORE_HANDLE *handle, unsigned char *buf, size_t len); @@ -171,8 +177,10 @@ provider): OPENSSL_cleanse OSSL_FUNC_OPENSSL_CLEANSE OSSL_SELF_TEST_set_callback OSSL_FUNC_SELF_TEST_CB ossl_rand_get_entropy OSSL_FUNC_GET_ENTROPY + ossl_rand_get_user_entropy OSSL_FUNC_GET_USER_ENTROPY ossl_rand_cleanup_entropy OSSL_FUNC_CLEANUP_ENTROPY ossl_rand_get_nonce OSSL_FUNC_GET_NONCE + ossl_rand_get_user_nonce OSSL_FUNC_GET_USER_NONCE ossl_rand_cleanup_nonce OSSL_FUNC_CLEANUP_NONCE provider_register_child_cb OSSL_FUNC_PROVIDER_REGISTER_CHILD_CB provider_deregister_child_cb OSSL_FUNC_PROVIDER_DEREGISTER_CHILD_CB @@ -302,9 +310,14 @@ output will have at least I and at most I bytes. The buffer address is stored in I<*pout> and the buffer length is returned to the caller. On error, zero is returned. +get_user_entropy() is the same as get_entropy() except that it will +attempt to gather seed material via the seed source specified by a call to +L or via L. + cleanup_entropy() is used to clean up and free the buffer returned by -get_entropy(). The entropy pointer returned by get_entropy() is passed in -B and its length in B. +get_entropy() or get_user_entropy(). The entropy pointer returned by +get_entropy() or get_user_entropy() is passed in B and its length +in B. get_nonce() retrieves a nonce using the passed I parameter of length I and operating system specific information. @@ -314,9 +327,14 @@ The output is stored in a buffer which contains at least I and at most I bytes. The buffer address is stored in I<*pout> and the buffer length returned to the caller. On error, zero is returned. -cleanup_nonce() is used to clean up and free the buffer returned by -get_nonce(). The nonce pointer returned by get_nonce() is passed in -B and its length in B. +get_user_nonce() is the same as get_nonce() except that it will attempt +to gather seed material via the seed source specified by a call to +L or via L. + +cleanup_nonce() is used to clean up and free the buffer returned +by get_nonce() or get_user_nonce(). The nonce pointer returned by +get_nonce() or get_user_nonce() is passed in B and its length +in B. provider_register_child_cb() registers callbacks for being informed about the loading and unloading of providers in the application's library context. diff --git a/include/crypto/rand.h b/include/crypto/rand.h index 7345bf625f..730be8b5d0 100644 --- a/include/crypto/rand.h +++ b/include/crypto/rand.h @@ -108,15 +108,21 @@ void ossl_random_add_conf_module(void); /* * Get and cleanup random seed material. */ -size_t ossl_rand_get_entropy(ossl_unused const OSSL_CORE_HANDLE *handle, +size_t ossl_rand_get_entropy(OSSL_LIB_CTX *ctx, unsigned char **pout, int entropy, size_t min_len, size_t max_len); -void ossl_rand_cleanup_entropy(ossl_unused const OSSL_CORE_HANDLE *handle, +size_t ossl_rand_get_user_entropy(OSSL_LIB_CTX *ctx, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len); +void ossl_rand_cleanup_entropy(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t len); -size_t ossl_rand_get_nonce(ossl_unused const OSSL_CORE_HANDLE *handle, +size_t ossl_rand_get_nonce(OSSL_LIB_CTX *ctx, unsigned char **pout, size_t min_len, size_t max_len, const void *salt, size_t salt_len); -void ossl_rand_cleanup_nonce(ossl_unused const OSSL_CORE_HANDLE *handle, +size_t ossl_rand_get_user_nonce(OSSL_LIB_CTX *ctx, unsigned char **pout, + size_t min_len, size_t max_len, + const void *salt, size_t salt_len); +void ossl_rand_cleanup_nonce(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t len); /* @@ -127,6 +133,7 @@ int ossl_pool_add_nonce_data(RAND_POOL *pool); # ifdef FIPS_MODULE EVP_RAND_CTX *ossl_rand_get0_private_noncreating(OSSL_LIB_CTX *ctx); +# else +EVP_RAND_CTX *ossl_rand_get0_seed_noncreating(OSSL_LIB_CTX *ctx); # endif - #endif diff --git a/include/openssl/core_dispatch.h b/include/openssl/core_dispatch.h index 73f040285c..6c952f18aa 100644 --- a/include/openssl/core_dispatch.h +++ b/include/openssl/core_dispatch.h @@ -176,6 +176,10 @@ OSSL_CORE_MAKE_FUNC(int, BIO_vsnprintf, OSSL_CORE_MAKE_FUNC(int, BIO_ctrl, (OSSL_CORE_BIO *bio, int cmd, long num, void *ptr)) +/* New seeding functions prototypes with the 101-104 series */ +#define OSSL_FUNC_GET_USER_ENTROPY 98 +#define OSSL_FUNC_GET_USER_NONCE 99 + #define OSSL_FUNC_SELF_TEST_CB 100 OSSL_CORE_MAKE_FUNC(void, self_test_cb, (OPENSSL_CORE_CTX *ctx, OSSL_CALLBACK **cb, void **cbarg)) @@ -188,12 +192,19 @@ OSSL_CORE_MAKE_FUNC(void, self_test_cb, (OPENSSL_CORE_CTX *ctx, OSSL_CALLBACK ** OSSL_CORE_MAKE_FUNC(size_t, get_entropy, (const OSSL_CORE_HANDLE *handle, unsigned char **pout, int entropy, size_t min_len, size_t max_len)) +OSSL_CORE_MAKE_FUNC(size_t, get_user_entropy, (const OSSL_CORE_HANDLE *handle, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len)) OSSL_CORE_MAKE_FUNC(void, cleanup_entropy, (const OSSL_CORE_HANDLE *handle, unsigned char *buf, size_t len)) OSSL_CORE_MAKE_FUNC(size_t, get_nonce, (const OSSL_CORE_HANDLE *handle, unsigned char **pout, size_t min_len, size_t max_len, const void *salt, size_t salt_len)) +OSSL_CORE_MAKE_FUNC(size_t, get_user_nonce, (const OSSL_CORE_HANDLE *handle, + unsigned char **pout, size_t min_len, + size_t max_len, const void *salt, + size_t salt_len)) OSSL_CORE_MAKE_FUNC(void, cleanup_nonce, (const OSSL_CORE_HANDLE *handle, unsigned char *buf, size_t len)) diff --git a/providers/baseprov.c b/providers/baseprov.c index 2e5dbe410f..6b8de7cb36 100644 --- a/providers/baseprov.c +++ b/providers/baseprov.c @@ -19,6 +19,7 @@ #include "prov/providercommon.h" #include "prov/implementations.h" #include "prov/provider_util.h" +#include "prov/names.h" /* * Forward declarations to ensure that interface functions are correctly @@ -90,6 +91,11 @@ static const OSSL_ALGORITHM base_store[] = { #undef STORE }; +static const OSSL_ALGORITHM base_rands[] = { + { PROV_NAMES_SEED_SRC, "provider=base", ossl_seed_src_functions }, + { NULL, NULL, NULL } +}; + static const OSSL_ALGORITHM *base_query(void *provctx, int operation_id, int *no_cache) { @@ -101,6 +107,8 @@ static const OSSL_ALGORITHM *base_query(void *provctx, int operation_id, return base_decoder; case OSSL_OP_STORE: return base_store; + case OSSL_OP_RAND: + return base_rands; } return NULL; } diff --git a/providers/common/provider_seeding.c b/providers/common/provider_seeding.c index d67ddf7b13..f6463f8ada 100644 --- a/providers/common/provider_seeding.c +++ b/providers/common/provider_seeding.c @@ -9,12 +9,33 @@ #include #include "prov/seeding.h" +#include "prov/providercommon.h" static OSSL_FUNC_get_entropy_fn *c_get_entropy = NULL; +static OSSL_FUNC_get_user_entropy_fn *c_get_user_entropy = NULL; static OSSL_FUNC_cleanup_entropy_fn *c_cleanup_entropy = NULL; static OSSL_FUNC_get_nonce_fn *c_get_nonce = NULL; +static OSSL_FUNC_get_user_nonce_fn *c_get_user_nonce = NULL; static OSSL_FUNC_cleanup_nonce_fn *c_cleanup_nonce = NULL; +#ifdef FIPS_MODULE +/* + * The FIPS provider uses an internal library context which is what the + * passed provider context references. Since the seed source is external + * to the FIPS provider, this is the wrong one. We need to convert this + * to the correct core handle before up-calling libcrypto. + */ +# define CORE_HANDLE(provctx) \ + FIPS_get_core_handle(ossl_prov_ctx_get0_libctx(provctx)) +#else +/* + * The non-FIPS path *should* be unused because the full DRBG chain including + * seed source is instantiated. However, that might not apply for third + * party providers, so this is retained for compatibility. + */ +# define CORE_HANDLE(provctx) ossl_prov_ctx_get0_handle(provctx) +#endif + int ossl_prov_seeding_from_dispatch(const OSSL_DISPATCH *fns) { for (; fns->function_id != 0; fns++) { @@ -29,12 +50,18 @@ int ossl_prov_seeding_from_dispatch(const OSSL_DISPATCH *fns) case OSSL_FUNC_GET_ENTROPY: set_func(c_get_entropy, OSSL_FUNC_get_entropy(fns)); break; + case OSSL_FUNC_GET_USER_ENTROPY: + set_func(c_get_user_entropy, OSSL_FUNC_get_user_entropy(fns)); + break; case OSSL_FUNC_CLEANUP_ENTROPY: set_func(c_cleanup_entropy, OSSL_FUNC_cleanup_entropy(fns)); break; case OSSL_FUNC_GET_NONCE: set_func(c_get_nonce, OSSL_FUNC_get_nonce(fns)); break; + case OSSL_FUNC_GET_USER_NONCE: + set_func(c_get_user_nonce, OSSL_FUNC_get_user_nonce(fns)); + break; case OSSL_FUNC_CLEANUP_NONCE: set_func(c_cleanup_nonce, OSSL_FUNC_cleanup_nonce(fns)); break; @@ -47,31 +74,37 @@ int ossl_prov_seeding_from_dispatch(const OSSL_DISPATCH *fns) size_t ossl_prov_get_entropy(PROV_CTX *prov_ctx, unsigned char **pout, int entropy, size_t min_len, size_t max_len) { - if (c_get_entropy == NULL) - return 0; - return c_get_entropy(ossl_prov_ctx_get0_handle(prov_ctx), - pout, entropy, min_len, max_len); + const OSSL_CORE_HANDLE *handle = CORE_HANDLE(prov_ctx); + + if (c_get_user_entropy != NULL) + return c_get_user_entropy(handle, pout, entropy, min_len, max_len); + if (c_get_entropy != NULL) + return c_get_entropy(handle, pout, entropy, min_len, max_len); + return 0; } void ossl_prov_cleanup_entropy(PROV_CTX *prov_ctx, unsigned char *buf, size_t len) { if (c_cleanup_entropy != NULL) - c_cleanup_entropy(ossl_prov_ctx_get0_handle(prov_ctx), buf, len); + c_cleanup_entropy(CORE_HANDLE(prov_ctx), buf, len); } size_t ossl_prov_get_nonce(PROV_CTX *prov_ctx, unsigned char **pout, size_t min_len, size_t max_len, const void *salt, size_t salt_len) { - if (c_get_nonce == NULL) - return 0; - return c_get_nonce(ossl_prov_ctx_get0_handle(prov_ctx), pout, - min_len, max_len, salt, salt_len); + const OSSL_CORE_HANDLE *handle = CORE_HANDLE(prov_ctx); + + if (c_get_user_nonce != NULL) + return c_get_user_nonce(handle, pout, min_len, max_len, salt, salt_len); + if (c_get_nonce != NULL) + return c_get_nonce(handle, pout, min_len, max_len, salt, salt_len); + return 0; } void ossl_prov_cleanup_nonce(PROV_CTX *prov_ctx, unsigned char *buf, size_t len) { if (c_cleanup_nonce != NULL) - c_cleanup_nonce(ossl_prov_ctx_get0_handle(prov_ctx), buf, len); + c_cleanup_nonce(CORE_HANDLE(prov_ctx), buf, len); }