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)
This commit is contained in:
Viktor Dukhovni 2025-01-16 19:44:14 +11:00
parent 42aced5c9f
commit 38a0926528
11 changed files with 168 additions and 29 deletions

View File

@ -295,6 +295,7 @@
# define OPT_PROV_ENUM \ # define OPT_PROV_ENUM \
OPT_PROV__FIRST=1600, \ OPT_PROV__FIRST=1600, \
OPT_PROV_PROVIDER, OPT_PROV_PROVIDER_PATH, OPT_PROV_PROPQUERY, \ OPT_PROV_PROVIDER, OPT_PROV_PROVIDER_PATH, OPT_PROV_PROPQUERY, \
OPT_PROV_PARAM, \
OPT_PROV__LAST OPT_PROV__LAST
# define OPT_CONFIG_OPTION \ # define OPT_CONFIG_OPTION \
@ -304,12 +305,14 @@
OPT_SECTION("Provider"), \ OPT_SECTION("Provider"), \
{ "provider-path", OPT_PROV_PROVIDER_PATH, 's', "Provider load path (must be before 'provider' argument if required)" }, \ { "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)" }, \ { "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" } { "propquery", OPT_PROV_PROPQUERY, 's', "Property query used when fetching algorithms" }
# define OPT_PROV_CASES \ # define OPT_PROV_CASES \
OPT_PROV__FIRST: case OPT_PROV__LAST: break; \ OPT_PROV__FIRST: case OPT_PROV__LAST: break; \
case OPT_PROV_PROVIDER: \ case OPT_PROV_PROVIDER: \
case OPT_PROV_PROVIDER_PATH: \ case OPT_PROV_PROVIDER_PATH: \
case OPT_PROV_PARAM: \
case OPT_PROV_PROPQUERY case OPT_PROV_PROPQUERY
/* /*

View File

@ -8,6 +8,7 @@
*/ */
#include "apps.h" #include "apps.h"
#include <ctype.h>
#include <string.h> #include <string.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/provider.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); 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) int opt_provider(int opt)
{ {
const int given = provider_option_given; const int given = provider_option_given;
@ -78,6 +151,8 @@ int opt_provider(int opt)
return app_provider_load(app_get0_libctx(), opt_arg()); return app_provider_load(app_get0_libctx(), opt_arg());
case OPT_PROV_PROVIDER_PATH: case OPT_PROV_PROVIDER_PATH:
return opt_provider_path(opt_arg()); return opt_provider_path(opt_arg());
case OPT_PROV_PARAM:
return opt_provider_param(opt_arg());
case OPT_PROV_PROPQUERY: case OPT_PROV_PROPQUERY:
return app_set_propq(opt_arg()); return app_set_propq(opt_arg());
} }

View File

@ -136,7 +136,7 @@ static int provider_conf_params_internal(OSSL_PROVIDER *prov,
} else { } else {
OSSL_TRACE2(CONF, "Provider params: %s = %s\n", name, value); OSSL_TRACE2(CONF, "Provider params: %s = %s\n", name, value);
if (prov != NULL) if (prov != NULL)
ok = ossl_provider_add_parameter(prov, name, value); ok = OSSL_PROVIDER_add_conf_parameter(prov, name, value);
else else
ok = ossl_provider_info_add_parameter(provinfo, name, value); ok = ossl_provider_info_add_parameter(provinfo, name, value);
} }

View File

@ -800,12 +800,30 @@ static int infopair_add(STACK_OF(INFOPAIR) **infopairsk, const char *name,
return 0; return 0;
} }
int ossl_provider_add_parameter(OSSL_PROVIDER *prov, int OSSL_PROVIDER_add_conf_parameter(OSSL_PROVIDER *prov,
const char *name, const char *value) const char *name, const char *value)
{ {
return infopair_add(&prov->parameters, name, 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, int ossl_provider_info_add_parameter(OSSL_PROVIDER_INFO *provinfo,
const char *name, const char *name,
const char *value) 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[]) static int core_get_params(const OSSL_CORE_HANDLE *handle, OSSL_PARAM params[])
{ {
int i;
OSSL_PARAM *p; OSSL_PARAM *p;
/* /*
* We created this object originally and we know it is actually an * 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)); OSSL_PARAM_set_utf8_ptr(p, ossl_provider_module_path(prov));
#endif #endif
if (prov->parameters == NULL) return OSSL_PROVIDER_get_conf_parameters(prov, params);
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;
} }
static OPENSSL_CORE_CTX *core_get_libctx(const OSSL_CORE_HANDLE *handle) static OPENSSL_CORE_CTX *core_get_libctx(const OSSL_CORE_HANDLE *handle)

View File

@ -3,9 +3,8 @@
=head1 NAME =head1 NAME
ossl_provider_find, ossl_provider_new, ossl_provider_up_ref, ossl_provider_find, ossl_provider_new, ossl_provider_up_ref,
ossl_provider_free, ossl_provider_free, ossl_provider_set_module_path,
ossl_provider_set_module_path, ossl_provider_set_child, ossl_provider_get_parent,
ossl_provider_add_parameter, ossl_provider_set_child, ossl_provider_get_parent,
ossl_provider_up_ref_parent, ossl_provider_free_parent, ossl_provider_up_ref_parent, ossl_provider_free_parent,
ossl_provider_default_props_update, ossl_provider_get0_dispatch, ossl_provider_default_props_update, ossl_provider_get0_dispatch,
ossl_provider_init_as_child, ossl_provider_deinit_child, ossl_provider_init_as_child, ossl_provider_deinit_child,
@ -36,8 +35,6 @@ ossl_provider_get_capabilities
/* Setters */ /* Setters */
int ossl_provider_set_module_path(OSSL_PROVIDER *prov, const char *path); 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 */ /* Child Providers */
int ossl_provider_set_child(OSSL_PROVIDER *prov, 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 ossl_provider_libctx() returns the library context the given
provider I<prov> is registered in. 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 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 parent library context. I<handle> is the B<OSSL_CORE_HANDLE> object passed to
the provider's B<OSSL_provider_init> function. the provider's B<OSSL_provider_init> function.

View File

@ -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. Specifies the search path that is to be used for looking for providers.
Equivalently, the B<OPENSSL_MODULES> environment variable may be set. 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> =item B<-propquery> I<propq>
Specifies the I<property query clause> to be used when fetching algorithms Specifies the I<property query clause> to be used when fetching algorithms

View File

@ -11,6 +11,7 @@ OSSL_PROVIDER_gettable_params, OSSL_PROVIDER_get_params,
OSSL_PROVIDER_query_operation, OSSL_PROVIDER_unquery_operation, OSSL_PROVIDER_query_operation, OSSL_PROVIDER_unquery_operation,
OSSL_PROVIDER_get0_provider_ctx, OSSL_PROVIDER_get0_dispatch, OSSL_PROVIDER_get0_provider_ctx, OSSL_PROVIDER_get0_dispatch,
OSSL_PROVIDER_add_builtin, OSSL_PROVIDER_get0_name, OSSL_PROVIDER_get_capabilities, 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 OSSL_PROVIDER_self_test
- provider routines - provider routines
@ -59,6 +60,10 @@ OSSL_PROVIDER_self_test
const char *capability, const char *capability,
OSSL_CALLBACK *cb, OSSL_CALLBACK *cb,
void *arg); 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); int OSSL_PROVIDER_self_test(const OSSL_PROVIDER *prov);
=head1 DESCRIPTION =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 function, and the variables acting as buffers for this parameter array
should be filled with data when it returns successfully. 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. 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 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 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 =head1 RETURN VALUES
OSSL_PROVIDER_set_default_search_path(), OSSL_PROVIDER_add(), 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_get_capabilities() return 1 on success, or 0 on error.
OSSL_PROVIDER_get0_default_search_path() returns a pointer to a path on success, OSSL_PROVIDER_get0_default_search_path() returns a pointer to a path on success,

View File

@ -94,12 +94,15 @@ $OpenSSL::safe::opt_r_item = ""
$OpenSSL::safe::opt_provider_synopsis = "" $OpenSSL::safe::opt_provider_synopsis = ""
. "[B<-provider> I<name>]\n" . "[B<-provider> I<name>]\n"
. "[B<-provider-path> I<path>]\n" . "[B<-provider-path> I<path>]\n"
. "[B<-provparam> I<[name:]key=value>]\n"
. "[B<-propquery> I<propq>]"; . "[B<-propquery> I<propq>]";
$OpenSSL::safe::opt_provider_item = "" $OpenSSL::safe::opt_provider_item = ""
. "=item B<-provider> I<name>\n" . "=item B<-provider> I<name>\n"
. "\n" . "\n"
. "=item B<-provider-path> I<path>\n" . "=item B<-provider-path> I<path>\n"
. "\n" . "\n"
. "=item B<-provparam> I<[name:]key=value>\n"
. "\n"
. "=item B<-propquery> I<propq>\n" . "=item B<-propquery> I<propq>\n"
. "\n" . "\n"
. "See L<openssl(1)/Provider Options>, L<provider(7)>, and L<property(7)>."; . "See L<openssl(1)/Provider Options>, L<provider(7)>, and L<property(7)>.";

View File

@ -38,8 +38,6 @@ void ossl_provider_free(OSSL_PROVIDER *prov);
/* Setters */ /* Setters */
int ossl_provider_set_module_path(OSSL_PROVIDER *prov, const char *module_path); 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_is_child(const OSSL_PROVIDER *prov);
int ossl_provider_set_child(OSSL_PROVIDER *prov, const OSSL_CORE_HANDLE *handle); int ossl_provider_set_child(OSSL_PROVIDER *prov, const OSSL_CORE_HANDLE *handle);

View File

@ -44,6 +44,25 @@ int OSSL_PROVIDER_get_capabilities(const OSSL_PROVIDER *prov,
OSSL_CALLBACK *cb, OSSL_CALLBACK *cb,
void *arg); 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, const OSSL_ALGORITHM *OSSL_PROVIDER_query_operation(const OSSL_PROVIDER *prov,
int operation_id, int operation_id,
int *no_cache); int *no_cache);

View File

@ -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_free ? 3_5_0 EXIST::FUNCTION:
OSSL_ALLOWED_ATTRIBUTES_SYNTAX_new ? 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_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: