summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPauli <pauli@openssl.org>2023-09-05 04:51:05 +0200
committerMatt Caswell <matt@openssl.org>2023-09-27 18:23:04 +0200
commit4cde7585ce8eb53682256ba79e6af1949498fbfe (patch)
tree0a2d79638c8770ff7d97c4c67a19c3a897b94f82
parentrand: add extra error code (diff)
downloadopenssl-4cde7585ce8eb53682256ba79e6af1949498fbfe.tar.xz
openssl-4cde7585ce8eb53682256ba79e6af1949498fbfe.zip
fips: use seed source requested
Fixes #21909 Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/21964)
-rw-r--r--crypto/initthread.c2
-rw-r--r--crypto/provider_core.c68
-rw-r--r--crypto/rand/prov_seed.c66
-rw-r--r--crypto/rand/rand_lib.c100
-rw-r--r--doc/internal/man3/ossl_rand_get_entropy.pod45
-rw-r--r--doc/man7/EVP_RAND-TEST-RAND.pod7
-rw-r--r--doc/man7/provider-base.pod28
-rw-r--r--include/crypto/rand.h17
-rw-r--r--include/openssl/core_dispatch.h11
-rw-r--r--providers/baseprov.c8
-rw-r--r--providers/common/provider_seeding.c53
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 <openssl/core_dispatch.h>
#include <openssl/err.h>
-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<min_len> and at most I<max_len>
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<RAND_set_seed_source_type(3)>.
+
ossl_rand_cleanup_entropy() cleanses and frees any storage allocated by
-ossl_rand_get_entropy(). The seeding buffer is pointed to by I<buf> and is
-of length I<len> bytes.
+ossl_rand_get_entropy() or ossl_rand_get_user_entropy(). The entropy
+buffer is pointed to by I<buf> and is of length I<len> bytes.
ossl_rand_get_nonce() retrieves a nonce using the passed I<salt> parameter
of length I<salt_len> and operating system specific information.
@@ -41,18 +52,34 @@ The output is stored in a buffer which contains at least I<min_len> and at
most I<max_len> 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<RAND_set_seed_source_type(3)>.
+
ossl_rand_cleanup_nonce() cleanses and frees any storage allocated by
-ossl_rand_get_nonce(). The nonce buffer is pointed to by I<buf> and is
-of length I<len> bytes.
+ossl_rand_get_nonce() or ossl_rand_get_user_nonce(). The nonce buffer
+is pointed to by I<buf> and is of length I<len> 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<OSSL_RAND_PARAM_GENERATE>) <integer>
+
+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<min_len> and at most I<max_len> 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<RAND_set_seed_source_type(3)> or via L<config(5)/Random Configuration>.
+
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<buf> and its length in B<len>.
+get_entropy() or get_user_entropy(). The entropy pointer returned by
+get_entropy() or get_user_entropy() is passed in B<buf> and its length
+in B<len>.
get_nonce() retrieves a nonce using the passed I<salt> parameter
of length I<salt_len> and operating system specific information.
@@ -314,9 +327,14 @@ The output is stored in a buffer which contains at least I<min_len> and at
most I<max_len> 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<buf> and its length in B<len>.
+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<RAND_set_seed_source_type(3)> or via L<config(5)/Random Configuration>.
+
+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<buf> and its length
+in B<len>.
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 <openssl/core_dispatch.h>
#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);
}