]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Support CLI and API setting of provider configuration parameters
authorViktor Dukhovni <openssl-users@dukhovni.org>
Thu, 16 Jan 2025 08:44:14 +0000 (19:44 +1100)
committerViktor Dukhovni <openssl-users@dukhovni.org>
Fri, 17 Jan 2025 16:46:37 +0000 (03:46 +1100)
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26427)

apps/include/opt.h
apps/lib/app_provider.c
crypto/provider_conf.c
crypto/provider_core.c
doc/internal/man3/ossl_provider_new.pod
doc/man1/openssl.pod
doc/man3/OSSL_PROVIDER.pod
doc/perlvars.pm
include/internal/provider.h
include/openssl/provider.h
util/libcrypto.num

index 2bd2fb24849266d58fe78183793f9c1363676737..637dff2fd21b8cc3d47b6a897d96f8e1c5027f2f 100644 (file)
 # 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 \
         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
 
 /*
index 63f78ae07d80b1c34df03ca560cc787c5cab6d30..85475a9be54ead850fe0c2ed6d5b880306aebbaa 100644 (file)
@@ -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());
     }
index 6a8b88e2e56da4633379f9648e11508e42fac407..930bb7a03a745ec3b6beb44872e79d6caff2601b 100644 (file)
@@ -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);
     }
index 6b2a98524d7d7b8f32238fc1e540338fd5ecf88c..787b83b71842a432025b2084aaa8c6b392aa8bac 100644 (file)
@@ -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)
index 2c406381e9d86893acf545ee1bae4a969241773e..54dd3f8a1852b30d1a55a675fc9323085e07c9cb 100644 (file)
@@ -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.
index c67f8c68e7d1093704075b0ad26fdedf3f53b3de..c8bbd9e9185a1f1be910ada1281f5d3c5df23512 100644 (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.
 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
index 2a1531e983b8559c84a4d8a36b82d12d826ae515..b3889b1ca97a25ff43ed1a6715512759229e1817 100644 (file)
@@ -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,
index 06dac990cfafdd748f48b68dce6060f445fe3738..465c79f11215dde3846f10f30451ad04e58413c4 100644 (file)
@@ -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)>.";
index ab41d643df0612f85a76f796883fb537be7eb3f2..cc1e24fa3ca89a43a1abfa72330848c7e07a0e1a 100644 (file)
@@ -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);
index 24ec0827bd6bbf65afb8f682ab9f5943ee042563..202e672d02475eb1416da51a77e6c163f3a1a1b5 100644 (file)
@@ -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);
index 9ad6d5ea7d58f4d3d8d60e8c10de769dfebaaf93..158e54022c299fa64490d48d650e496cdfcb864e 100644 (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_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: