From abbc2c408385326d9c9cd60b92a6c92b945c1d96 Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Wed, 20 Mar 2019 16:53:19 +0100 Subject: [PATCH] Replumbing: add a configuration module for providers This configuration module supports a configuration structure pretty much like the engine configuration module, i.e. something like this: openssl_conf = openssl_init [openssl_init] providers = provider_section [provider_section] # Configure the provider named "foo" foo = foo_section # Configure the provider named "bar" bar = bar_section [foo_section] # Override name given in the provider section identity = myfoo # The exact path of the module. This is platform specific module_path = /opt/openssl/modules/foo.so # Whether it should be automatically activated. Value is unimportant activate = whatever # Anything else goes as well, and becomes parameters that the # provider can get what = 1 # sub-sections will be followed as well ever = ever_section [ever_section] cookie = monster All the configurations in a provider section and its sub-sections become parameters for the provider to get, i.e. the "foo" provider will be able to get values for the following keys (with associated values shown): identity => myfoo module_path => /opt/openssl/modules/foo.so activate => whatever what => 1 ever.cookie => monster Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/8549) --- crypto/build.info | 3 +- crypto/conf/conf_mall.c | 2 + crypto/cpt_err.c | 6 ++ crypto/err/openssl.txt | 3 + crypto/provider_conf.c | 179 ++++++++++++++++++++++++++++++++++++ include/internal/provider.h | 3 + include/openssl/cryptoerr.h | 3 + 7 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 crypto/provider_conf.c diff --git a/crypto/build.info b/crypto/build.info index 535fa35a10..a6f3524542 100644 --- a/crypto/build.info +++ b/crypto/build.info @@ -9,7 +9,8 @@ SUBDIRS=objects buffer bio stack lhash rand evp asn1 pem x509 x509v3 conf \ LIBS=../libcrypto # The Core -SOURCE[../libcrypto]=provider_core.c provider_predefined.c core_fetch.c +SOURCE[../libcrypto]=provider_core.c provider_predefined.c provider_conf.c \ + core_fetch.c # Central utilities SOURCE[../libcrypto]=\ diff --git a/crypto/conf/conf_mall.c b/crypto/conf/conf_mall.c index e1d0e7aef3..28003a8fae 100644 --- a/crypto/conf/conf_mall.c +++ b/crypto/conf/conf_mall.c @@ -14,6 +14,7 @@ #include #include #include +#include "internal/provider.h" #include "conf_lcl.h" /* Load all OpenSSL builtin modules */ @@ -28,4 +29,5 @@ void OPENSSL_load_builtin_modules(void) #endif EVP_add_alg_module(); conf_add_ssl_module(); + ossl_provider_add_conf_module(); } diff --git a/crypto/cpt_err.c b/crypto/cpt_err.c index cca8037855..8c386925f8 100644 --- a/crypto/cpt_err.c +++ b/crypto/cpt_err.c @@ -63,6 +63,10 @@ static const ERR_STRING_DATA CRYPTO_str_functs[] = { "pkey_siphash_init"}, {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_PROVIDER_ACTIVATE, 0), "provider_activate"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_PROVIDER_CONF_INIT, 0), + "provider_conf_init"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_PROVIDER_CONF_LOAD, 0), + "provider_conf_load"}, {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_PROVIDER_NEW, 0), "provider_new"}, {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_PROVIDER_STORE_NEW, 0), "provider_store_new"}, @@ -79,6 +83,8 @@ static const ERR_STRING_DATA CRYPTO_str_reasons[] = { "odd number of digits"}, {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_PROVIDER_ALREADY_EXISTS), "provider already exists"}, + {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_PROVIDER_SECTION_ERROR), + "provider section error"}, {0, NULL} }; diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index a3f3d48ce8..fbf35d14bf 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -399,6 +399,8 @@ CRYPTO_F_PKEY_HMAC_INIT:123:pkey_hmac_init CRYPTO_F_PKEY_POLY1305_INIT:124:pkey_poly1305_init CRYPTO_F_PKEY_SIPHASH_INIT:125:pkey_siphash_init CRYPTO_F_PROVIDER_ACTIVATE:134:provider_activate +CRYPTO_F_PROVIDER_CONF_INIT:137:provider_conf_init +CRYPTO_F_PROVIDER_CONF_LOAD:138:provider_conf_load CRYPTO_F_PROVIDER_NEW:135:provider_new CRYPTO_F_PROVIDER_STORE_NEW:136:provider_store_new CRYPTO_F_SK_RESERVE:129:sk_reserve @@ -2162,6 +2164,7 @@ CRYPTO_R_FIPS_MODE_NOT_SUPPORTED:101:fips mode not supported CRYPTO_R_ILLEGAL_HEX_DIGIT:102:illegal hex digit 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 CT_R_BASE64_DECODE_ERROR:108:base64 decode error CT_R_INVALID_LOG_ID_LENGTH:100:invalid log id length CT_R_LOG_CONF_INVALID:109:log conf invalid diff --git a/crypto/provider_conf.c b/crypto/provider_conf.c new file mode 100644 index 0000000000..9d9b7a1348 --- /dev/null +++ b/crypto/provider_conf.c @@ -0,0 +1,179 @@ +/* + * Copyright 2019 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 +#include +#include +#include +#include +#include "internal/provider.h" + +/* PROVIDER config module */ + +DEFINE_STACK_OF(OSSL_PROVIDER) +static STACK_OF(OSSL_PROVIDER) *activated_providers = NULL; + +static const char *skip_dot(const char *name) +{ + const char *p = strchr(name, '.'); + + if (p != NULL) + return p + 1; + return name; +} + +static int provider_conf_params(OSSL_PROVIDER *prov, + const char *name, const char *value, + const CONF *cnf) +{ + STACK_OF(CONF_VALUE) *sect; + int ok = 1; + + OSSL_TRACE2(PROVIDER_CONF, "PROVIDER conf: %s = %s\n", name, value); + + sect = NCONF_get_section(cnf, value); + if (sect != NULL) { + int i; + char buffer[512]; + size_t buffer_len = 0; + + if (name != NULL) { + OPENSSL_strlcpy(buffer, name, sizeof(buffer)); + OPENSSL_strlcat(buffer, ".", sizeof(buffer)); + buffer_len = strlen(buffer); + } + + for (i = 0; i < sk_CONF_VALUE_num(sect); i++) { + CONF_VALUE *sectconf = sk_CONF_VALUE_value(sect, i); + + if (buffer_len + strlen(sectconf->name) >= sizeof(buffer)) + return 0; + buffer[buffer_len] = '\0'; + OPENSSL_strlcat(buffer, sectconf->name, sizeof(buffer)); + if (!provider_conf_params(prov, buffer, sectconf->value, cnf)) + return 0; + } + } else { + ok = ossl_provider_add_parameter(prov, name, value); + } + + return ok; +} + +static int provider_conf_load(OPENSSL_CTX *libctx, const char *name, + const char *value, const CONF *cnf) +{ + int i; + STACK_OF(CONF_VALUE) *ecmds; + int soft = 0; + OSSL_PROVIDER *prov = NULL; + const char *path = NULL; + long activate = 0; + int ok = 0; + + name = skip_dot(name); + OSSL_TRACE1(PROVIDER_CONF, "Configuring provider %s\n", name); + /* Value is a section containing PROVIDER commands */ + ecmds = NCONF_get_section(cnf, value); + + if (!ecmds) { + CRYPTOerr(CRYPTO_F_PROVIDER_CONF_LOAD, CRYPTO_R_PROVIDER_SECTION_ERROR); + return 0; + } + + /* Find the needed data first */ + for (i = 0; i < sk_CONF_VALUE_num(ecmds); i++) { + CONF_VALUE *ecmd = sk_CONF_VALUE_value(ecmds, i); + const char *confname = skip_dot(ecmd->name); + const char *confvalue = ecmd->value; + + OSSL_TRACE2(PROVIDER_CONF, "PROVIDER conf: %s = %s\n", + confname, confvalue); + + /* First handle some special pseudo confs */ + + /* Override provider name to use */ + if (strcmp(confname, "identity") == 0) + name = confvalue; + else if (strcmp(confname, "soft_load") == 0) + soft = 1; + /* Load a dynamic PROVIDER */ + else if (strcmp(confname, "module") == 0) + path = confvalue; + else if (strcmp(confname, "activate") == 0) + activate = 1; + } + + prov = ossl_provider_new(libctx, name, NULL); + if (prov == NULL) { + if (soft) + ERR_clear_error(); + return 0; + } + + if (path != NULL) + ossl_provider_set_module_path(prov, path); + + ok = provider_conf_params(prov, NULL, value, cnf); + + if (ok && activate) { + if (!ossl_provider_activate(prov)) { + ok = 0; + } else { + if (activated_providers == NULL) + activated_providers = sk_OSSL_PROVIDER_new_null(); + sk_OSSL_PROVIDER_push(activated_providers, prov); + ok = 1; + } + } + + if (!(activate && ok)) + ossl_provider_free(prov); + + return ok; +} + +static int provider_conf_init(CONF_IMODULE *md, const CONF *cnf) +{ + STACK_OF(CONF_VALUE) *elist; + CONF_VALUE *cval; + int i; + + OSSL_TRACE2(PROVIDER_CONF, "Loading provider module: name %s, value %s\n", + CONF_imodule_get_name(md), CONF_imodule_get_value(md)); + /* Value is a section containing PROVIDERs to configure */ + elist = NCONF_get_section(cnf, CONF_imodule_get_value(md)); + + if (!elist) { + CRYPTOerr(CRYPTO_F_PROVIDER_CONF_INIT, + CRYPTO_R_PROVIDER_SECTION_ERROR); + return 0; + } + + for (i = 0; i < sk_CONF_VALUE_num(elist); i++) { + cval = sk_CONF_VALUE_value(elist, i); + if (!provider_conf_load(NULL, cval->name, cval->value, cnf)) + return 0; + } + + return 1; +} + + +static void provider_conf_deinit(CONF_IMODULE *md) +{ + sk_OSSL_PROVIDER_pop_free(activated_providers, ossl_provider_free); + activated_providers = NULL; + OSSL_TRACE(PROVIDER_CONF, "Cleaned up providers\n"); +} + +void ossl_provider_add_conf_module(void) +{ + CONF_module_add("providers", provider_conf_init, provider_conf_deinit); +} diff --git a/include/internal/provider.h b/include/internal/provider.h index abd5ec4392..4966cc2595 100644 --- a/include/internal/provider.h +++ b/include/internal/provider.h @@ -66,6 +66,9 @@ const OSSL_ALGORITHM *ossl_provider_query_operation(const OSSL_PROVIDER *prov, int operation_id, int *no_cache); +/* Configuration */ +void ossl_provider_add_conf_module(void); + # ifdef __cplusplus } # endif diff --git a/include/openssl/cryptoerr.h b/include/openssl/cryptoerr.h index 4d44a1ce09..ff5767a1d3 100644 --- a/include/openssl/cryptoerr.h +++ b/include/openssl/cryptoerr.h @@ -52,6 +52,8 @@ int ERR_load_CRYPTO_strings(void); # define CRYPTO_F_PKEY_POLY1305_INIT 124 # define CRYPTO_F_PKEY_SIPHASH_INIT 125 # define CRYPTO_F_PROVIDER_ACTIVATE 134 +# define CRYPTO_F_PROVIDER_CONF_INIT 137 +# define CRYPTO_F_PROVIDER_CONF_LOAD 138 # define CRYPTO_F_PROVIDER_NEW 135 # define CRYPTO_F_PROVIDER_STORE_NEW 136 # define CRYPTO_F_SK_RESERVE 129 @@ -63,5 +65,6 @@ int ERR_load_CRYPTO_strings(void); # define CRYPTO_R_ILLEGAL_HEX_DIGIT 102 # define CRYPTO_R_ODD_NUMBER_OF_DIGITS 103 # define CRYPTO_R_PROVIDER_ALREADY_EXISTS 104 +# define CRYPTO_R_PROVIDER_SECTION_ERROR 105 #endif -- 2.34.1