summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorViktor Dukhovni <openssl-users@dukhovni.org>2025-01-16 09:44:14 +0100
committerViktor Dukhovni <openssl-users@dukhovni.org>2025-01-17 17:46:37 +0100
commit38a0926528791762cf8f0f4e3ed0e2f590b894b9 (patch)
treec1b6120d859a098d508b1edff9d3dd6d03150964
parentWork around to get llvm-mingw working on aarch64 (diff)
downloadopenssl-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.h3
-rw-r--r--apps/lib/app_provider.c75
-rw-r--r--crypto/provider_conf.c2
-rw-r--r--crypto/provider_core.c34
-rw-r--r--doc/internal/man3/ossl_provider_new.pod14
-rw-r--r--doc/man1/openssl.pod15
-rw-r--r--doc/man3/OSSL_PROVIDER.pod28
-rw-r--r--doc/perlvars.pm3
-rw-r--r--include/internal/provider.h2
-rw-r--r--include/openssl/provider.h19
-rw-r--r--util/libcrypto.num2
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: