From 44d2482ba62bf7fc2fd4cfc250ad09e0feaa42da Mon Sep 17 00:00:00 2001 From: Pauli Date: Mon, 21 Sep 2020 16:07:34 +1000 Subject: [PATCH] Add a "random" configuration section. This permits the default trio of DRBGs to have their type and parameters set using configuration. Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/12931) --- crypto/conf/conf_mall.c | 2 + crypto/cpt_err.c | 6 +- crypto/err/openssl.txt | 2 + crypto/rand/rand_lib.c | 108 +++++++++++++++++- .../man3/ossl_random_add_conf_module.pod | 42 +++++++ doc/man5/config.pod | 51 +++++++++ include/crypto/rand.h | 5 + include/openssl/cryptoerr.h | 2 + 8 files changed, 213 insertions(+), 5 deletions(-) create mode 100644 doc/internal/man3/ossl_random_add_conf_module.pod diff --git a/crypto/conf/conf_mall.c b/crypto/conf/conf_mall.c index 123e2abaad..5d24a36cd9 100644 --- a/crypto/conf/conf_mall.c +++ b/crypto/conf/conf_mall.c @@ -18,6 +18,7 @@ #include #include #include "internal/provider.h" +#include "crypto/rand.h" #include "conf_local.h" /* Load all OpenSSL builtin modules */ @@ -33,4 +34,5 @@ void OPENSSL_load_builtin_modules(void) EVP_add_alg_module(); conf_add_ssl_module(); ossl_provider_add_conf_module(); + ossl_random_add_conf_module(); } diff --git a/crypto/cpt_err.c b/crypto/cpt_err.c index 0201f31e61..04b6cdb27f 100644 --- a/crypto/cpt_err.c +++ b/crypto/cpt_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-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 @@ -38,6 +38,8 @@ static const ERR_STRING_DATA CRYPTO_str_reasons[] = { "provider already exists"}, {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_PROVIDER_SECTION_ERROR), "provider section error"}, + {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_RANDOM_SECTION_ERROR), + "random section error"}, {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_SECURE_MALLOC_FAILURE), "secure malloc failure"}, {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_STRING_TOO_LONG), "string too long"}, @@ -46,6 +48,8 @@ static const ERR_STRING_DATA CRYPTO_str_reasons[] = { "too many records"}, {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_TOO_SMALL_BUFFER), "too small buffer"}, + {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_UNKNOWN_NAME_IN_RANDOM_SECTION), + "unknown name in random section"}, {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_ZERO_LENGTH_NUMBER), "zero length number"}, {0, NULL} diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 775bf6f3c4..1d9dd9366f 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -2320,11 +2320,13 @@ CRYPTO_R_INVALID_OSSL_PARAM_TYPE:110:invalid ossl param type CRYPTO_R_ODD_NUMBER_OF_DIGITS:103:odd number of digits CRYPTO_R_PROVIDER_ALREADY_EXISTS:104:provider already exists CRYPTO_R_PROVIDER_SECTION_ERROR:105:provider section error +CRYPTO_R_RANDOM_SECTION_ERROR:119:random section error CRYPTO_R_SECURE_MALLOC_FAILURE:111:secure malloc failure CRYPTO_R_STRING_TOO_LONG:112:string too long CRYPTO_R_TOO_MANY_BYTES:113:too many bytes CRYPTO_R_TOO_MANY_RECORDS:114:too many records CRYPTO_R_TOO_SMALL_BUFFER:116:too small buffer +CRYPTO_R_UNKNOWN_NAME_IN_RANDOM_SECTION:120:unknown name in random section CRYPTO_R_ZERO_LENGTH_NUMBER:115:zero length number CT_R_BASE64_DECODE_ERROR:108:base64 decode error CT_R_INVALID_LOG_ID_LENGTH:100:invalid log id length diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index a37a575e5b..6b2eaab68d 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -12,6 +12,10 @@ #include #include +#include +#include +#include +#include #include "internal/cryptlib.h" #include #include "crypto/rand.h" @@ -353,6 +357,12 @@ typedef struct rand_global_st { * 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; } RAND_GLOBAL; /* @@ -405,6 +415,10 @@ static void rand_ossl_ctx_free(void *vdgbl) EVP_RAND_CTX_free(dgbl->primary); CRYPTO_THREAD_cleanup_local(&dgbl->private); CRYPTO_THREAD_cleanup_local(&dgbl->public); + OPENSSL_free(dgbl->rng_name); + OPENSSL_free(dgbl->rng_cipher); + OPENSSL_free(dgbl->rng_digest); + OPENSSL_free(dgbl->rng_propq); OPENSSL_free(dgbl); } @@ -442,10 +456,14 @@ static EVP_RAND_CTX *rand_new_drbg(OPENSSL_CTX *libctx, EVP_RAND_CTX *parent, unsigned int reseed_interval, time_t reseed_time_interval) { - EVP_RAND *rand = EVP_RAND_fetch(libctx, "CTR-DRBG", NULL); + EVP_RAND *rand; + RAND_GLOBAL *dgbl = rand_get_global(libctx); EVP_RAND_CTX *ctx; - OSSL_PARAM params[4], *p = params; - + OSSL_PARAM params[7], *p = params; + char *name, *cipher; + + name = dgbl->rng_name != NULL ? dgbl->rng_name : "CTR-DRBG"; + rand = EVP_RAND_fetch(libctx, name, dgbl->rng_propq); if (rand == NULL) { RANDerr(0, RAND_R_UNABLE_TO_FETCH_DRBG); return NULL; @@ -457,8 +475,20 @@ static EVP_RAND_CTX *rand_new_drbg(OPENSSL_CTX *libctx, EVP_RAND_CTX *parent, return NULL; } + /* + * Rather than trying to decode the DRBG settings, just pass them through + * and rely on the other end to ignore those it doesn't care about. + */ + cipher = dgbl->rng_cipher != NULL ? dgbl->rng_cipher : "AES-256-CTR"; *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER, - "AES-256-CTR", 0); + cipher, 0); + if (dgbl->rng_digest != NULL) + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_DIGEST, + dgbl->rng_digest, 0); + if (dgbl->rng_propq != NULL) + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_PROPERTIES, + dgbl->rng_propq, 0); + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_MAC, "HMAC", 0); *p++ = OSSL_PARAM_construct_uint(OSSL_DRBG_PARAM_RESEED_REQUESTS, &reseed_interval); *p++ = OSSL_PARAM_construct_time_t(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL, @@ -565,3 +595,73 @@ EVP_RAND_CTX *RAND_get0_private(OPENSSL_CTX *ctx) } return rand; } + +#ifndef FIPS_MODULE +static int random_set_string(char **p, const char *s) +{ + char *d = OPENSSL_strdup(s); + + if (d == NULL) { + CRYPTOerr(0, ERR_R_MALLOC_FAILURE); + return 0; + } + OPENSSL_free(*p); + *p = d; + return 1; +} + +/* + * Load the DRBG definitions from a configuration file. + */ +static int random_conf_init(CONF_IMODULE *md, const CONF *cnf) +{ + STACK_OF(CONF_VALUE) *elist; + CONF_VALUE *cval; + RAND_GLOBAL *dgbl = rand_get_global(cnf->libctx); + int i, r = 1; + + OSSL_TRACE1(CONF, "Loading random module: section %s\n", + CONF_imodule_get_value(md)); + + /* Value is a section containing RANDOM configuration */ + elist = NCONF_get_section(cnf, CONF_imodule_get_value(md)); + if (elist == NULL) { + CRYPTOerr(0, CRYPTO_R_RANDOM_SECTION_ERROR); + return 0; + } + + for (i = 0; i < sk_CONF_VALUE_num(elist); i++) { + cval = sk_CONF_VALUE_value(elist, i); + if (strcasecmp(cval->name, "random") == 0) { + if (!random_set_string(&dgbl->rng_name, cval->value)) + return 0; + } else if (strcasecmp(cval->name, "cipher") == 0) { + if (!random_set_string(&dgbl->rng_cipher, cval->value)) + return 0; + } else if (strcasecmp(cval->name, "digest") == 0) { + if (!random_set_string(&dgbl->rng_digest, cval->value)) + return 0; + } else if (strcasecmp(cval->name, "properties") == 0) { + if (!random_set_string(&dgbl->rng_propq, cval->value)) + return 0; + } else { + CRYPTOerr(0, CRYPTO_R_UNKNOWN_NAME_IN_RANDOM_SECTION); + ERR_add_error_data(4, "name=", cval->name, ", value=", cval->value); + r = 0; + } + } + return r; +} + + +static void random_conf_deinit(CONF_IMODULE *md) +{ + OSSL_TRACE(CONF, "Cleaned up random\n"); +} + +void ossl_random_add_conf_module(void) +{ + OSSL_TRACE(CONF, "Adding config module 'random'\n"); + CONF_module_add("random", random_conf_init, random_conf_deinit); +} +#endif diff --git a/doc/internal/man3/ossl_random_add_conf_module.pod b/doc/internal/man3/ossl_random_add_conf_module.pod new file mode 100644 index 0000000000..6d4f5810dc --- /dev/null +++ b/doc/internal/man3/ossl_random_add_conf_module.pod @@ -0,0 +1,42 @@ +=pod + +=head1 NAME + +ossl_random_add_conf_module - internal random configuration module + +=head1 SYNOPSIS + + #include "crypto/rand.h" + + /* Configuration */ + void ossl_random_add_conf_module(void); + +=head1 DESCRIPTION + +ossl_random_add_conf_module() adds the random configuration module +for providers. +This allows the type and parameters of the stardard setup of random number +generators to be configured with an OpenSSL L file. + +=head1 RETURN VALUES + +ossl_random_add_conf_module() doesn't return any value. + +=head1 SEE ALSO + +L, L, L + +=head1 HISTORY + +The functions described here were all added in OpenSSL 3.0. + +=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. + +=cut diff --git a/doc/man5/config.pod b/doc/man5/config.pod index 46d60f6ced..0a28f4ea4b 100644 --- a/doc/man5/config.pod +++ b/doc/man5/config.pod @@ -175,6 +175,7 @@ production. alg_section = evp_properties ssl_conf = ssl_configuration engines = engines + random = random [oids] ... new oids here ... @@ -191,6 +192,9 @@ production. [engines] ... engine properties here ... + [random] + ... random properties here ... + The semantics of each module are described below. The phrase "in the initialization section" refers to the section identified by the B or other name (given as B in the @@ -389,6 +393,53 @@ For example: default_algorithms = ALL other_ctrl = EMPTY +=head2 Random Configuration + +The name B in the initialization section names the section +containing the random number generater settings. + +Within the random section, the following names have meaning: + +=over 4 + +=item B + +This is used to specify the random bit generator. +For example: + + [random] + random = CTR-DRBG + +The available random bit generators are: + +=over 4 + +=item B + +=item B + +=item B + +=back + +=item B + +This specifies what cipher a B random bit generator will use. +Other random bit generators ignore this name. +The default value is B. + +=item B + +This specifies what digest the B or B random bit +generators will use. Other random bit generators ignore this name. + +=item B + +This sets the property query used when fetching the random bit generator and +any underlying algorithms. + +=back + =head1 EXAMPLES This example shows how to use quoting and escaping. diff --git a/include/crypto/rand.h b/include/crypto/rand.h index c5eef81462..a437565fe8 100644 --- a/include/crypto/rand.h +++ b/include/crypto/rand.h @@ -88,4 +88,9 @@ void rand_pool_cleanup(void); */ void rand_pool_keep_random_devices_open(int keep); +/* + * Configuration + */ +void ossl_random_add_conf_module(void); + #endif diff --git a/include/openssl/cryptoerr.h b/include/openssl/cryptoerr.h index 5ccddd0214..6add92a9ca 100644 --- a/include/openssl/cryptoerr.h +++ b/include/openssl/cryptoerr.h @@ -90,11 +90,13 @@ int ERR_load_CRYPTO_strings(void); # define CRYPTO_R_ODD_NUMBER_OF_DIGITS 103 # define CRYPTO_R_PROVIDER_ALREADY_EXISTS 104 # define CRYPTO_R_PROVIDER_SECTION_ERROR 105 +# define CRYPTO_R_RANDOM_SECTION_ERROR 119 # define CRYPTO_R_SECURE_MALLOC_FAILURE 111 # define CRYPTO_R_STRING_TOO_LONG 112 # define CRYPTO_R_TOO_MANY_BYTES 113 # define CRYPTO_R_TOO_MANY_RECORDS 114 # define CRYPTO_R_TOO_SMALL_BUFFER 116 +# define CRYPTO_R_UNKNOWN_NAME_IN_RANDOM_SECTION 120 # define CRYPTO_R_ZERO_LENGTH_NUMBER 115 #endif -- 2.39.5