Skip to content

Commit

Permalink
rand: add a provider side seed source.
Browse files Browse the repository at this point in the history
This allows the operating system sources that OpenSSL supports to be
used directly as RNGs.  It also allows DRBG seeding to be explicitly
specified rather than being left to a fall back case.

Reviewed-by: Matt Caswell <[email protected]>
(Merged from openssl#13455)
  • Loading branch information
paulidale committed Dec 9, 2020
1 parent d8975de commit 81aef6b
Show file tree
Hide file tree
Showing 10 changed files with 348 additions and 3 deletions.
2 changes: 2 additions & 0 deletions crypto/err/openssl.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2933,6 +2933,8 @@ PROV_R_REQUIRE_CTR_MODE_CIPHER:206:require ctr mode cipher
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
Expand Down
53 changes: 51 additions & 2 deletions crypto/rand/rand_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,8 @@ typedef struct rand_global_st {
*/
CRYPTO_RWLOCK *lock;

EVP_RAND_CTX *seed;

/*
* The <primary> DRBG
*
Expand Down Expand Up @@ -363,6 +365,10 @@ typedef struct rand_global_st {
char *rng_cipher;
char *rng_digest;
char *rng_propq;

/* Allow the randomness source to be changed */
char *seed_name;
char *seed_propq;
} RAND_GLOBAL;

/*
Expand Down Expand Up @@ -412,13 +418,16 @@ static void rand_ossl_ctx_free(void *vdgbl)
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);
}
Expand Down Expand Up @@ -452,6 +461,35 @@ static void rand_delete_thread_state(void *arg)
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)
Expand Down Expand Up @@ -522,8 +560,13 @@ EVP_RAND_CTX *RAND_get0_primary(OSSL_LIB_CTX *ctx)
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);
}
Expand Down Expand Up @@ -644,6 +687,12 @@ static int random_conf_init(CONF_IMODULE *md, const CONF *cnf)
} 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,
Expand Down
10 changes: 10 additions & 0 deletions doc/man5/config.pod
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,16 @@ generators will use. Other random bit generators ignore this name.
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
Expand Down
87 changes: 87 additions & 0 deletions doc/man7/EVP_RAND-SEED-SRC.pod
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
=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
1 change: 1 addition & 0 deletions providers/common/include/prov/providercommonerr.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ int err_load_PROV_strings_int(void);
# 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
Expand Down
2 changes: 2 additions & 0 deletions providers/common/provider_err.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
{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),
Expand Down
1 change: 1 addition & 0 deletions providers/defltprov.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ static const OSSL_ALGORITHM deflt_rands[] = {
{ "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 }
};
Expand Down
1 change: 1 addition & 0 deletions providers/implementations/include/prov/implementations.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ extern const OSSL_DISPATCH ossl_kdf_krb5kdf_functions[];

/* 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[];
Expand Down
2 changes: 1 addition & 1 deletion providers/implementations/rands/build.info
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ SUBDIRS=seeding
$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
Loading

0 comments on commit 81aef6b

Please sign in to comment.