PROV_R_RESEED_ERROR:197:reseed error
PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES:222:\
search only supported for directories
+PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT:200:\
+ seed sources must not have a parent
PROV_R_SELF_TEST_KAT_FAILURE:215:self test kat failure
PROV_R_SELF_TEST_POST_FAILURE:216:self test post failure
PROV_R_TAG_NOTSET:119:tag notset
*/
CRYPTO_RWLOCK *lock;
+ EVP_RAND_CTX *seed;
+
/*
* The <primary> DRBG
*
char *rng_cipher;
char *rng_digest;
char *rng_propq;
+
+ /* Allow the randomness source to be changed */
+ char *seed_name;
+ char *seed_propq;
} RAND_GLOBAL;
/*
return;
CRYPTO_THREAD_lock_free(dgbl->lock);
- EVP_RAND_CTX_free(dgbl->primary);
CRYPTO_THREAD_cleanup_local(&dgbl->private);
CRYPTO_THREAD_cleanup_local(&dgbl->public);
+ EVP_RAND_CTX_free(dgbl->primary);
+ EVP_RAND_CTX_free(dgbl->seed);
OPENSSL_free(dgbl->rng_name);
OPENSSL_free(dgbl->rng_cipher);
OPENSSL_free(dgbl->rng_digest);
OPENSSL_free(dgbl->rng_propq);
+ OPENSSL_free(dgbl->seed_name);
+ OPENSSL_free(dgbl->seed_propq);
OPENSSL_free(dgbl);
}
EVP_RAND_CTX_free(rand);
}
+#ifndef FIPS_MODULE
+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;
+
+ name = dgbl->seed_name != NULL ? dgbl->seed_name : "SEED-SRC";
+ rand = EVP_RAND_fetch(libctx, name, dgbl->seed_propq);
+ if (rand == NULL) {
+ ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_FETCH_DRBG);
+ return NULL;
+ }
+ 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;
+ }
+ if (!EVP_RAND_instantiate(ctx, 0, 0, NULL, 0)) {
+ ERR_raise(ERR_LIB_RAND, RAND_R_ERROR_INSTANTIATING_DRBG);
+ EVP_RAND_CTX_free(ctx);
+ return NULL;
+ }
+ return ctx;
+}
+#endif
+
static EVP_RAND_CTX *rand_new_drbg(OSSL_LIB_CTX *libctx, EVP_RAND_CTX *parent,
unsigned int reseed_interval,
time_t reseed_time_interval)
if (dgbl->primary == NULL) {
if (!CRYPTO_THREAD_write_lock(dgbl->lock))
return NULL;
+#ifndef FIPS_MODULE
+ if (dgbl->seed == NULL)
+ dgbl->seed = rand_new_seed(ctx);
+#endif
if (dgbl->primary == NULL)
- dgbl->primary = rand_new_drbg(ctx, NULL, PRIMARY_RESEED_INTERVAL,
+ dgbl->primary = rand_new_drbg(ctx, dgbl->seed,
+ PRIMARY_RESEED_INTERVAL,
PRIMARY_RESEED_TIME_INTERVAL);
CRYPTO_THREAD_unlock(dgbl->lock);
}
} else if (strcasecmp(cval->name, "properties") == 0) {
if (!random_set_string(&dgbl->rng_propq, cval->value))
return 0;
+ } else if (strcasecmp(cval->name, "seed") == 0) {
+ if (!random_set_string(&dgbl->seed_name, cval->value))
+ return 0;
+ } else if (strcasecmp(cval->name, "seed_properties") == 0) {
+ if (!random_set_string(&dgbl->seed_propq, cval->value))
+ return 0;
} else {
ERR_raise_data(ERR_LIB_CRYPTO,
CRYPTO_R_UNKNOWN_NAME_IN_RANDOM_SECTION,
This sets the property query used when fetching the random bit generator and
any underlying algorithms.
+=item B<seed>
+
+This sets the randomness source that should be used. By default B<SEED-SRC>
+will be used outside of the FIPS provider. The FIPS provider uses call backs
+to access the same randomness sources from outside the validated boundary.
+
+=item B<seed_properties>
+
+This sets the property query used when fetching the randomness source.
+
=back
=head1 EXAMPLES
--- /dev/null
+=pod
+
+=head1 NAME
+
+EVP_RAND-SEED-SRC - The randomness seed source EVP_RAND implementation
+
+=head1 DESCRIPTION
+
+Support for deterministic random number generator seeding through the
+B<EVP_RAND> API.
+
+The seed sources used are specified at the time OpenSSL is configured for
+building using the B<--with-rand-seed=> option. By default, operating system
+randomness sources are used.
+
+=head2 Identity
+
+"SEED-SRC" is the name for this implementation; it can be used with the
+EVP_RAND_fetch() function.
+
+=head2 Supported parameters
+
+The supported parameters are:
+
+=over 4
+
+=item "state" (B<OSSL_RAND_PARAM_STATE>) <integer>
+
+=item "strength" (B<OSSL_RAND_PARAM_STRENGTH>) <unsigned integer>
+
+=item "max_request" (B<OSSL_RAND_PARAM_MAX_REQUEST>) <unsigned integer>
+
+These parameters work as described in L<EVP_RAND(3)/PARAMETERS>.
+
+=back
+
+=head1 NOTES
+
+A context for the seed source can be obtained by calling:
+
+ EVP_RAND *rand = EVP_RAND_fetch(NULL, "SEED-SRC", NULL);
+ EVP_RAND_CTX *rctx = EVP_RAND_CTX_new(rand);
+
+=head1 EXAMPLES
+
+ EVP_RAND *rand;
+ EVP_RAND_CTX *seed, *rctx;
+ unsigned char bytes[100];
+ OSSL_PARAM params[2], *p = params;
+ unsigned int strength = 128;
+
+ /* Create a seed source */
+ rand = EVP_RAND_fetch(NULL, "SEED-SRC", NULL);
+ seed = EVP_RAND_CTX_new(rand, NULL);
+ EVP_RAND_free(rand);
+
+ /* Feed this into a DRBG */
+ rand = EVP_RAND_fetch(NULL, "CTR-DRBG", NULL);
+ rctx = EVP_RAND_CTX_new(rand, seed);
+ EVP_RAND_free(rand);
+
+ /* Configure the DRBG */
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER,
+ SN_aes_256_ctr, 0);
+ *p = OSSL_PARAM_construct_end();
+ EVP_RAND_set_ctx_params(rctx, params);
+
+ EVP_RAND_generate(rctx, bytes, sizeof(bytes), strength, 0, NULL, 0);
+
+ EVP_RAND_CTX_free(rctx);
+ EVP_RAND_CTX_free(seed);
+
+=head1 SEE ALSO
+
+L<EVP_RAND(3)>,
+L<EVP_RAND(3)/PARAMETERS>
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
# define PROV_R_REQUIRE_CTR_MODE_CIPHER 206
# define PROV_R_RESEED_ERROR 197
# define PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES 222
+# define PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT 200
# define PROV_R_SELF_TEST_KAT_FAILURE 215
# define PROV_R_SELF_TEST_POST_FAILURE 216
# define PROV_R_TAG_NOTSET 119
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_RESEED_ERROR), "reseed error"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES),
"search only supported for directories"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT),
+ "seed sources must not have a parent"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_SELF_TEST_KAT_FAILURE),
"self test kat failure"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_SELF_TEST_POST_FAILURE),
{ "CTR-DRBG", "provider=default", ossl_drbg_ctr_functions },
{ "HASH-DRBG", "provider=default", ossl_drbg_hash_functions },
{ "HMAC-DRBG", "provider=default", ossl_drbg_ossl_hmac_functions },
+ { "SEED-SRC", "provider=default", ossl_seed_src_functions },
{ "TEST-RAND", "provider=default", ossl_test_rng_functions },
{ NULL, NULL, NULL }
};
/* RNGs */
extern const OSSL_DISPATCH ossl_test_rng_functions[];
+extern const OSSL_DISPATCH ossl_seed_src_functions[];
extern const OSSL_DISPATCH ossl_drbg_hash_functions[];
extern const OSSL_DISPATCH ossl_drbg_ossl_hmac_functions[];
extern const OSSL_DISPATCH ossl_drbg_ctr_functions[];
$COMMON=drbg.c test_rng.c drbg_ctr.c drbg_hash.c drbg_hmac.c crngt.c
SOURCE[../../libfips.a]=$COMMON
-SOURCE[../../libnonfips.a]=$COMMON
+SOURCE[../../libnonfips.a]=$COMMON seed_src.c
--- /dev/null
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/rand.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/e_os2.h>
+#include <openssl/params.h>
+#include <openssl/core_names.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/randerr.h>
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommonerr.h"
+#include "crypto/rand.h"
+#include "crypto/rand_pool.h"
+
+static OSSL_FUNC_rand_newctx_fn seed_src_new;
+static OSSL_FUNC_rand_freectx_fn seed_src_free;
+static OSSL_FUNC_rand_instantiate_fn seed_src_instantiate;
+static OSSL_FUNC_rand_uninstantiate_fn seed_src_uninstantiate;
+static OSSL_FUNC_rand_generate_fn seed_src_generate;
+static OSSL_FUNC_rand_reseed_fn seed_src_reseed;
+static OSSL_FUNC_rand_gettable_ctx_params_fn seed_src_gettable_ctx_params;
+static OSSL_FUNC_rand_get_ctx_params_fn seed_src_get_ctx_params;
+static OSSL_FUNC_rand_verify_zeroization_fn seed_src_verify_zeroization;
+static OSSL_FUNC_rand_enable_locking_fn seed_src_enable_locking;
+
+typedef struct {
+ void *provctx;
+ int state;
+} PROV_SEED_SRC;
+
+static void *seed_src_new(void *provctx, void *parent,
+ const OSSL_DISPATCH *parent_dispatch)
+{
+ PROV_SEED_SRC *s;
+
+ if (parent != NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT);
+ return NULL;
+ }
+
+ s = OPENSSL_zalloc(sizeof(*s));
+ if (s == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ s->provctx = provctx;
+ s->state = EVP_RAND_STATE_UNINITIALISED;
+ return s;
+}
+
+static void seed_src_free(void *vseed)
+{
+ OPENSSL_free(vseed);
+}
+
+static int seed_src_instantiate(void *vseed, unsigned int strength,
+ int prediction_resistance,
+ const unsigned char *pstr, size_t pstr_len)
+{
+ PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed;
+
+ s->state = EVP_RAND_STATE_READY;
+ return 1;
+}
+
+static int seed_src_uninstantiate(void *vseed)
+{
+ PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed;
+
+ s->state = EVP_RAND_STATE_UNINITIALISED;
+ return 1;
+}
+
+static int seed_src_generate(void *vseed, unsigned char *out, size_t outlen,
+ unsigned int strength,
+ ossl_unused int prediction_resistance,
+ ossl_unused const unsigned char *adin,
+ ossl_unused size_t adin_len)
+{
+ PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed;
+ size_t entropy_available;
+ RAND_POOL *pool;
+
+ if (s->state != EVP_RAND_STATE_READY) {
+ ERR_raise(ERR_LIB_PROV,
+ s->state == EVP_RAND_STATE_ERROR ? PROV_R_IN_ERROR_STATE
+ : PROV_R_NOT_INSTANTIATED);
+ return 0;
+ }
+
+ pool = rand_pool_new(strength, 1, outlen, outlen);
+ if (pool == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ /* Get entropy by polling system entropy sources. */
+ entropy_available = ossl_pool_acquire_entropy(pool);
+
+ if (entropy_available > 0)
+ memcpy(out, rand_pool_detach(pool), rand_pool_length(pool));
+
+ rand_pool_free(pool);
+ return entropy_available > 0;
+}
+
+static int seed_src_reseed(void *vseed,
+ ossl_unused int prediction_resistance,
+ ossl_unused const unsigned char *ent,
+ ossl_unused size_t ent_len,
+ ossl_unused const unsigned char *adin,
+ ossl_unused size_t adin_len)
+{
+ PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed;
+
+ if (s->state != EVP_RAND_STATE_READY) {
+ ERR_raise(ERR_LIB_PROV,
+ s->state == EVP_RAND_STATE_ERROR ? PROV_R_IN_ERROR_STATE
+ : PROV_R_NOT_INSTANTIATED);
+ return 0;
+ }
+ return 1;
+}
+
+static int seed_src_get_ctx_params(void *vseed, OSSL_PARAM params[])
+{
+ PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed;
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STATE);
+ if (p != NULL && !OSSL_PARAM_set_int(p, s->state))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STRENGTH);
+ if (p != NULL && !OSSL_PARAM_set_int(p, 1024))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, 128))
+ return 0;
+ return 1;
+}
+
+static const OSSL_PARAM *seed_src_gettable_ctx_params(ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_int(OSSL_RAND_PARAM_STATE, NULL),
+ OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL),
+ OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL),
+ OSSL_PARAM_END
+ };
+ return known_gettable_ctx_params;
+}
+
+static int seed_src_verify_zeroization(ossl_unused void *vseed)
+{
+ return 1;
+}
+
+static int seed_src_enable_locking(ossl_unused void *vseed)
+{
+ return 1;
+}
+
+const OSSL_DISPATCH ossl_seed_src_functions[] = {
+ { OSSL_FUNC_RAND_NEWCTX, (void(*)(void))seed_src_new },
+ { OSSL_FUNC_RAND_FREECTX, (void(*)(void))seed_src_free },
+ { OSSL_FUNC_RAND_INSTANTIATE,
+ (void(*)(void))seed_src_instantiate },
+ { OSSL_FUNC_RAND_UNINSTANTIATE,
+ (void(*)(void))seed_src_uninstantiate },
+ { OSSL_FUNC_RAND_GENERATE, (void(*)(void))seed_src_generate },
+ { OSSL_FUNC_RAND_RESEED, (void(*)(void))seed_src_reseed },
+ { OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))seed_src_enable_locking },
+ { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS,
+ (void(*)(void))seed_src_gettable_ctx_params },
+ { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))seed_src_get_ctx_params },
+ { OSSL_FUNC_RAND_VERIFY_ZEROIZATION,
+ (void(*)(void))seed_src_verify_zeroization },
+ { 0, NULL }
+};