diff options
author | Viktor Dukhovni <openssl-users@dukhovni.org> | 2025-01-16 09:44:14 +0100 |
---|---|---|
committer | Viktor Dukhovni <openssl-users@dukhovni.org> | 2025-01-17 17:46:37 +0100 |
commit | 38a0926528791762cf8f0f4e3ed0e2f590b894b9 (patch) | |
tree | c1b6120d859a098d508b1edff9d3dd6d03150964 | |
parent | Work around to get llvm-mingw working on aarch64 (diff) | |
download | openssl-38a0926528791762cf8f0f4e3ed0e2f590b894b9.tar.xz openssl-38a0926528791762cf8f0f4e3ed0e2f590b894b9.zip |
Support CLI and API setting of provider configuration parameters
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26427)
-rw-r--r-- | apps/include/opt.h | 3 | ||||
-rw-r--r-- | apps/lib/app_provider.c | 75 | ||||
-rw-r--r-- | crypto/provider_conf.c | 2 | ||||
-rw-r--r-- | crypto/provider_core.c | 34 | ||||
-rw-r--r-- | doc/internal/man3/ossl_provider_new.pod | 14 | ||||
-rw-r--r-- | doc/man1/openssl.pod | 15 | ||||
-rw-r--r-- | doc/man3/OSSL_PROVIDER.pod | 28 | ||||
-rw-r--r-- | doc/perlvars.pm | 3 | ||||
-rw-r--r-- | include/internal/provider.h | 2 | ||||
-rw-r--r-- | include/openssl/provider.h | 19 | ||||
-rw-r--r-- | util/libcrypto.num | 2 |
11 files changed, 168 insertions, 29 deletions
diff --git a/apps/include/opt.h b/apps/include/opt.h index 2bd2fb2484..637dff2fd2 100644 --- a/apps/include/opt.h +++ b/apps/include/opt.h @@ -295,6 +295,7 @@ # define OPT_PROV_ENUM \ OPT_PROV__FIRST=1600, \ OPT_PROV_PROVIDER, OPT_PROV_PROVIDER_PATH, OPT_PROV_PROPQUERY, \ + OPT_PROV_PARAM, \ OPT_PROV__LAST # define OPT_CONFIG_OPTION \ @@ -304,12 +305,14 @@ OPT_SECTION("Provider"), \ { "provider-path", OPT_PROV_PROVIDER_PATH, 's', "Provider load path (must be before 'provider' argument if required)" }, \ { "provider", OPT_PROV_PROVIDER, 's', "Provider to load (can be specified multiple times)" }, \ + { "provparam", OPT_PROV_PARAM, 's', "Set a provider key-value parameter" }, \ { "propquery", OPT_PROV_PROPQUERY, 's', "Property query used when fetching algorithms" } # define OPT_PROV_CASES \ OPT_PROV__FIRST: case OPT_PROV__LAST: break; \ case OPT_PROV_PROVIDER: \ case OPT_PROV_PROVIDER_PATH: \ + case OPT_PROV_PARAM: \ case OPT_PROV_PROPQUERY /* diff --git a/apps/lib/app_provider.c b/apps/lib/app_provider.c index 63f78ae07d..85475a9be5 100644 --- a/apps/lib/app_provider.c +++ b/apps/lib/app_provider.c @@ -8,6 +8,7 @@ */ #include "apps.h" +#include <ctype.h> #include <string.h> #include <openssl/err.h> #include <openssl/provider.h> @@ -65,6 +66,78 @@ static int opt_provider_path(const char *path) return OSSL_PROVIDER_set_default_search_path(app_get0_libctx(), path); } +struct prov_param_st { + char *name; + char *key; + char *val; + int found; +}; + +static int set_prov_param(OSSL_PROVIDER *prov, void *vp) +{ + struct prov_param_st *p = (struct prov_param_st *)vp; + + if (p->name != NULL && strcmp(OSSL_PROVIDER_get0_name(prov), p->name) != 0) + return 1; + p->found = 1; + return OSSL_PROVIDER_add_conf_parameter(prov, p->key, p->val); +} + +static int opt_provider_param(const char *arg) +{ + struct prov_param_st p; + char *copy, *tmp; + int ret = 0; + + if ((copy = OPENSSL_strdup(arg)) == NULL + || (p.val = strchr(copy, '=')) == NULL) { + opt_printf_stderr("%s: malformed '-provparam' option value: '%s'\n", + opt_getprog(), arg); + goto end; + } + + /* Drop whitespace on both sides of the '=' sign */ + *(tmp = p.val++) = '\0'; + while (tmp > copy && isspace(_UC(*--tmp))) + *tmp = '\0'; + while (isspace(_UC(*p.val))) + ++p.val; + + /* + * Split the key on ':', to get the optional provider, empty or missing + * means all. + */ + if ((p.key = strchr(copy, ':')) != NULL) { + *p.key++ = '\0'; + p.name = *copy != '\0' ? copy : NULL; + } else { + p.name = NULL; + p.key = copy; + } + + /* The key must not be empty */ + if (*p.key == '\0') { + opt_printf_stderr("%s: malformed '-provparam' option value: '%s'\n", + opt_getprog(), arg); + goto end; + } + + p.found = 0; + ret = OSSL_PROVIDER_do_all(app_get0_libctx(), set_prov_param, (void *)&p); + if (ret == 0) { + opt_printf_stderr("%s: Error setting provider '%s' parameter '%s'\n", + opt_getprog(), p.name, p.key); + } else if (p.found == 0) { + opt_printf_stderr("%s: No provider named '%s' is loaded\n", + opt_getprog(), p.name); + ret = 0; + } + + end: + OPENSSL_free(copy); + return ret; +} + int opt_provider(int opt) { const int given = provider_option_given; @@ -78,6 +151,8 @@ int opt_provider(int opt) return app_provider_load(app_get0_libctx(), opt_arg()); case OPT_PROV_PROVIDER_PATH: return opt_provider_path(opt_arg()); + case OPT_PROV_PARAM: + return opt_provider_param(opt_arg()); case OPT_PROV_PROPQUERY: return app_set_propq(opt_arg()); } diff --git a/crypto/provider_conf.c b/crypto/provider_conf.c index 6a8b88e2e5..930bb7a03a 100644 --- a/crypto/provider_conf.c +++ b/crypto/provider_conf.c @@ -136,7 +136,7 @@ static int provider_conf_params_internal(OSSL_PROVIDER *prov, } else { OSSL_TRACE2(CONF, "Provider params: %s = %s\n", name, value); if (prov != NULL) - ok = ossl_provider_add_parameter(prov, name, value); + ok = OSSL_PROVIDER_add_conf_parameter(prov, name, value); else ok = ossl_provider_info_add_parameter(provinfo, name, value); } diff --git a/crypto/provider_core.c b/crypto/provider_core.c index 6b2a98524d..787b83b718 100644 --- a/crypto/provider_core.c +++ b/crypto/provider_core.c @@ -800,12 +800,30 @@ static int infopair_add(STACK_OF(INFOPAIR) **infopairsk, const char *name, return 0; } -int ossl_provider_add_parameter(OSSL_PROVIDER *prov, - const char *name, const char *value) +int OSSL_PROVIDER_add_conf_parameter(OSSL_PROVIDER *prov, + const char *name, const char *value) { return infopair_add(&prov->parameters, name, value); } +int OSSL_PROVIDER_get_conf_parameters(OSSL_PROVIDER *prov, OSSL_PARAM params[]) +{ + int i; + + if (prov->parameters == NULL) + return 1; + + for (i = 0; i < sk_INFOPAIR_num(prov->parameters); i++) { + INFOPAIR *pair = sk_INFOPAIR_value(prov->parameters, i); + OSSL_PARAM *p = OSSL_PARAM_locate(params, pair->name); + + if (p != NULL + && !OSSL_PARAM_set_utf8_ptr(p, pair->value)) + return 0; + } + return 1; +} + int ossl_provider_info_add_parameter(OSSL_PROVIDER_INFO *provinfo, const char *name, const char *value) @@ -2203,7 +2221,6 @@ static const OSSL_PARAM *core_gettable_params(const OSSL_CORE_HANDLE *handle) static int core_get_params(const OSSL_CORE_HANDLE *handle, OSSL_PARAM params[]) { - int i; OSSL_PARAM *p; /* * We created this object originally and we know it is actually an @@ -2222,16 +2239,7 @@ static int core_get_params(const OSSL_CORE_HANDLE *handle, OSSL_PARAM params[]) OSSL_PARAM_set_utf8_ptr(p, ossl_provider_module_path(prov)); #endif - if (prov->parameters == NULL) - return 1; - - for (i = 0; i < sk_INFOPAIR_num(prov->parameters); i++) { - INFOPAIR *pair = sk_INFOPAIR_value(prov->parameters, i); - - if ((p = OSSL_PARAM_locate(params, pair->name)) != NULL) - OSSL_PARAM_set_utf8_ptr(p, pair->value); - } - return 1; + return OSSL_PROVIDER_get_conf_parameters(prov, params); } static OPENSSL_CORE_CTX *core_get_libctx(const OSSL_CORE_HANDLE *handle) diff --git a/doc/internal/man3/ossl_provider_new.pod b/doc/internal/man3/ossl_provider_new.pod index 2c406381e9..54dd3f8a18 100644 --- a/doc/internal/man3/ossl_provider_new.pod +++ b/doc/internal/man3/ossl_provider_new.pod @@ -3,9 +3,8 @@ =head1 NAME ossl_provider_find, ossl_provider_new, ossl_provider_up_ref, -ossl_provider_free, -ossl_provider_set_module_path, -ossl_provider_add_parameter, ossl_provider_set_child, ossl_provider_get_parent, +ossl_provider_free, ossl_provider_set_module_path, +ossl_provider_set_child, ossl_provider_get_parent, ossl_provider_up_ref_parent, ossl_provider_free_parent, ossl_provider_default_props_update, ossl_provider_get0_dispatch, ossl_provider_init_as_child, ossl_provider_deinit_child, @@ -36,8 +35,6 @@ ossl_provider_get_capabilities /* Setters */ int ossl_provider_set_module_path(OSSL_PROVIDER *prov, const char *path); - int ossl_provider_add_parameter(OSSL_PROVIDER *prov, const char *name, - const char *value); /* Child Providers */ int ossl_provider_set_child(OSSL_PROVIDER *prov, @@ -167,13 +164,6 @@ on this in L</NOTES>). ossl_provider_libctx() returns the library context the given provider I<prov> is registered in. -ossl_provider_add_parameter() adds a global parameter for the provider -to retrieve as it sees fit. -The parameters are a combination of I<name> and I<value>, and the -provider will use the name to find the value it wants. -Only text parameters can be given, and it's up to the provider to -interpret them. - ossl_provider_set_child() marks this provider as a child of a provider in the parent library context. I<handle> is the B<OSSL_CORE_HANDLE> object passed to the provider's B<OSSL_provider_init> function. diff --git a/doc/man1/openssl.pod b/doc/man1/openssl.pod index c67f8c68e7..c8bbd9e918 100644 --- a/doc/man1/openssl.pod +++ b/doc/man1/openssl.pod @@ -681,6 +681,21 @@ See L<provider(7)> for a more detailed description. Specifies the search path that is to be used for looking for providers. Equivalently, the B<OPENSSL_MODULES> environment variable may be set. +=item B<-provparam> I<[name:]key=value> + +Set configuration parameter I<key> to value I<val> in provider I<name> +(optional), if I<name> is not specified, the setting will be applied to all +loaded providers. +This option can be specified multiple times, to set multiple parameters. +Options that specify nondefault providers to load should precede this option +if the setting is intended to apply to the to be loaded providers. +Parameters that only affect provider initialisation must, for now, be set in +the configuration file, only parameters that are also queried as needed later +have any affect when set via this interface. +Only UTF8-string-valued parameters are supported. +See the documentation of the specific provider and associated algorithms for +any supported parameters. + =item B<-propquery> I<propq> Specifies the I<property query clause> to be used when fetching algorithms diff --git a/doc/man3/OSSL_PROVIDER.pod b/doc/man3/OSSL_PROVIDER.pod index 2a1531e983..b3889b1ca9 100644 --- a/doc/man3/OSSL_PROVIDER.pod +++ b/doc/man3/OSSL_PROVIDER.pod @@ -11,6 +11,7 @@ OSSL_PROVIDER_gettable_params, OSSL_PROVIDER_get_params, OSSL_PROVIDER_query_operation, OSSL_PROVIDER_unquery_operation, OSSL_PROVIDER_get0_provider_ctx, OSSL_PROVIDER_get0_dispatch, OSSL_PROVIDER_add_builtin, OSSL_PROVIDER_get0_name, OSSL_PROVIDER_get_capabilities, +OSSL_PROVIDER_add_conf_parameter, OSSL_PROVIDER_get_conf_parameters, OSSL_PROVIDER_self_test - provider routines @@ -59,6 +60,10 @@ OSSL_PROVIDER_self_test const char *capability, OSSL_CALLBACK *cb, void *arg); + int OSSL_PROVIDER_add_conf_parameter(OSSL_PROVIDER *prov, const char *name, + const char *value); + int OSSL_PROVIDER_get_conf_parameters(OSSL_PROVIDER *prov, + OSSL_PARAM params[]); int OSSL_PROVIDER_self_test(const OSSL_PROVIDER *prov); =head1 DESCRIPTION @@ -137,6 +142,25 @@ The caller must prepare the L<OSSL_PARAM(3)> array before calling this function, and the variables acting as buffers for this parameter array should be filled with data when it returns successfully. +OSSL_PROVIDER_add_conf_parameter() sets the provider configuration parameter +I<name> to B<value>. +Provider configuration parameters are managed by the OpenSSL core and normally +set in the configuration file, but can also be set early in the main program +before a provider is in use by multiple threads. +Parameters that only affect provider initialisation must, for now, be set in +the configuration file, only parameters that are also queried later have any +affect when set via this interface. +Only text parameters can be given, and it's up to the provider to +interpret them. + +OSSL_PROVIDER_get_conf_parameters() retrieves global configuration parameters +associated with B<prov>. +These configuration parameters are stored for each provider by the OpenSSL core, +not the provider itself, parameters managed by the provider are queried via +B<OSSL_PROVIDER_get_params()> described above. +The parameters are returned by reference, not as copies, and so the elements of +the I<param> array must have B<OSSL_PARAM_UTF8_PTR> as their B<data_type>. + OSSL_PROVIDER_self_test() is used to run a provider's self tests on demand. If the self tests fail then the provider will fail to provide any further services and algorithms. L<OSSL_SELF_TEST_set_callback(3)> may be called @@ -177,7 +201,9 @@ L<provider-base(7)/CAPABILTIIES>. =head1 RETURN VALUES OSSL_PROVIDER_set_default_search_path(), OSSL_PROVIDER_add(), -OSSL_PROVIDER_unload(), OSSL_PROVIDER_get_params() and +OSSL_PROVIDER_unload(), OSSL_PROVIDER_get_params(), +OSSL_PROVIDER_add_conf_parameter(), OSSL_PROVIDER_get_conf_parameters() +and OSSL_PROVIDER_get_capabilities() return 1 on success, or 0 on error. OSSL_PROVIDER_get0_default_search_path() returns a pointer to a path on success, diff --git a/doc/perlvars.pm b/doc/perlvars.pm index 06dac990cf..465c79f112 100644 --- a/doc/perlvars.pm +++ b/doc/perlvars.pm @@ -94,12 +94,15 @@ $OpenSSL::safe::opt_r_item = "" $OpenSSL::safe::opt_provider_synopsis = "" . "[B<-provider> I<name>]\n" . "[B<-provider-path> I<path>]\n" +. "[B<-provparam> I<[name:]key=value>]\n" . "[B<-propquery> I<propq>]"; $OpenSSL::safe::opt_provider_item = "" . "=item B<-provider> I<name>\n" . "\n" . "=item B<-provider-path> I<path>\n" . "\n" +. "=item B<-provparam> I<[name:]key=value>\n" +. "\n" . "=item B<-propquery> I<propq>\n" . "\n" . "See L<openssl(1)/Provider Options>, L<provider(7)>, and L<property(7)>."; diff --git a/include/internal/provider.h b/include/internal/provider.h index ab41d643df..cc1e24fa3c 100644 --- a/include/internal/provider.h +++ b/include/internal/provider.h @@ -38,8 +38,6 @@ void ossl_provider_free(OSSL_PROVIDER *prov); /* Setters */ int ossl_provider_set_module_path(OSSL_PROVIDER *prov, const char *module_path); -int ossl_provider_add_parameter(OSSL_PROVIDER *prov, const char *name, - const char *value); int ossl_provider_is_child(const OSSL_PROVIDER *prov); int ossl_provider_set_child(OSSL_PROVIDER *prov, const OSSL_CORE_HANDLE *handle); diff --git a/include/openssl/provider.h b/include/openssl/provider.h index 24ec0827bd..202e672d02 100644 --- a/include/openssl/provider.h +++ b/include/openssl/provider.h @@ -44,6 +44,25 @@ int OSSL_PROVIDER_get_capabilities(const OSSL_PROVIDER *prov, OSSL_CALLBACK *cb, void *arg); +/*- + * Provider configuration parameters are normally set in the configuration file, + * but can also be set early in the main program before a provider is in use by + * multiple threads. + * + * Only UTF8-string values are supported. + */ +int OSSL_PROVIDER_add_conf_parameter(OSSL_PROVIDER *prov, const char *name, + const char *value); +/* + * Retrieves any of the requested configuration parameters for the given + * provider that were set in the configuration file or via the above + * OSSL_PROVIDER_add_parameter() function. + * + * The |params| array elements MUST have type OSSL_PARAM_UTF8_PTR, values are + * returned by reference, not as copies. + */ +int OSSL_PROVIDER_get_conf_parameters(OSSL_PROVIDER *prov, OSSL_PARAM params[]); + const OSSL_ALGORITHM *OSSL_PROVIDER_query_operation(const OSSL_PROVIDER *prov, int operation_id, int *no_cache); diff --git a/util/libcrypto.num b/util/libcrypto.num index 9ad6d5ea7d..158e54022c 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5876,3 +5876,5 @@ i2d_OSSL_ALLOWED_ATTRIBUTES_SYNTAX ? 3_5_0 EXIST::FUNCTION: OSSL_ALLOWED_ATTRIBUTES_SYNTAX_free ? 3_5_0 EXIST::FUNCTION: OSSL_ALLOWED_ATTRIBUTES_SYNTAX_new ? 3_5_0 EXIST::FUNCTION: OSSL_ALLOWED_ATTRIBUTES_SYNTAX_it ? 3_5_0 EXIST::FUNCTION: +OSSL_PROVIDER_add_conf_parameter ? 3_5_0 EXIST::FUNCTION: +OSSL_PROVIDER_get_conf_parameters ? 3_5_0 EXIST::FUNCTION: |