[openssl] master update

Richard Levitte levitte at openssl.org
Wed Apr 3 09:43:23 UTC 2019


The branch master has been updated
       via  b6670f690c4244e63dbc02a2ba25061f9c53945f (commit)
       via  6d872a838df78518508b5661d98da62a097317b1 (commit)
       via  abbc2c408385326d9c9cd60b92a6c92b945c1d96 (commit)
       via  ac1055ef13ccb5789e2bed7b9688c8eb16dd05ce (commit)
      from  5516c19b0314ef9416c5b02ae6347c4f52209e6a (commit)


- Log -----------------------------------------------------------------
commit b6670f690c4244e63dbc02a2ba25061f9c53945f
Author: Richard Levitte <levitte at openssl.org>
Date:   Sat Mar 30 22:25:00 2019 +0100

    Replumbing: add documentation for the provider configuration module
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8549)

commit 6d872a838df78518508b5661d98da62a097317b1
Author: Richard Levitte <levitte at openssl.org>
Date:   Sat Mar 30 22:10:39 2019 +0100

    Add test for the provider configuration module
    
    We reuse test/provider_internal_test.c and test/p_test.c,
    and get it loaded one more time via the configuration file
    test/provider_internal_test.conf
    
    To support different platform standards regarding module
    extensions, we generate test/provider_internal_test.conf
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8549)

commit abbc2c408385326d9c9cd60b92a6c92b945c1d96
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Mar 20 16:53:19 2019 +0100

    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 <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8549)

commit ac1055ef13ccb5789e2bed7b9688c8eb16dd05ce
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Mar 21 08:44:06 2019 +0100

    Replumbing: add functionality to set provider parameters
    
    Provider parameters are parameters set by the core that the provider
    can retrieve.  The primary use it to support making OpenSSL
    configuration data available to the provider.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8549)

-----------------------------------------------------------------------

Summary of changes:
 .gitignore                               |   2 +
 crypto/build.info                        |   3 +-
 crypto/conf/conf_mall.c                  |   2 +
 crypto/cpt_err.c                         |  10 ++
 crypto/err/openssl.txt                   |   5 +
 crypto/provider_conf.c                   | 179 +++++++++++++++++++++++++++++++
 crypto/provider_core.c                   | 102 ++++++++++++++----
 doc/man5/config.pod                      |  61 +++++++++++
 include/internal/provider.h              |   7 +-
 include/openssl/cryptoerr.h              |   5 +
 test/build.info                          |   2 +
 test/p_test.c                            |  20 +++-
 test/provider_internal_test.c            |  43 +++++---
 test/provider_internal_test.conf.in      |  13 +++
 test/recipes/02-test_internal_provider.t |   5 +-
 15 files changed, 418 insertions(+), 41 deletions(-)
 create mode 100644 crypto/provider_conf.c
 create mode 100644 test/provider_internal_test.conf.in

diff --git a/.gitignore b/.gitignore
index 61c68f4..b32122c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -60,6 +60,8 @@ Makefile
 /test/versions
 /test/ossl_shim/ossl_shim
 /test/rsa_complex
+# Other generated files in test/
+/test/provider_internal_test.conf
 
 # Certain files that get created by tests on the fly
 /test/test-runs
diff --git a/crypto/build.info b/crypto/build.info
index 535fa35..a6f3524 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 e1d0e7a..28003a8 100644
--- a/crypto/conf/conf_mall.c
+++ b/crypto/conf/conf_mall.c
@@ -14,6 +14,7 @@
 #include <openssl/x509.h>
 #include <openssl/asn1.h>
 #include <openssl/engine.h>
+#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 3c3265d..8c38692 100644
--- a/crypto/cpt_err.c
+++ b/crypto/cpt_err.c
@@ -50,8 +50,12 @@ static const ERR_STRING_DATA CRYPTO_str_functs[] = {
      "OSSL_PROVIDER_add_builtin"},
     {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OSSL_PROVIDER_ACTIVATE, 0),
      "ossl_provider_activate"},
+    {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OSSL_PROVIDER_ADD_PARAMETER, 0),
+     "ossl_provider_add_parameter"},
     {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OSSL_PROVIDER_NEW, 0),
      "ossl_provider_new"},
+    {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OSSL_PROVIDER_SET_MODULE_PATH, 0),
+     "ossl_provider_set_module_path"},
     {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_PKEY_HMAC_INIT, 0), "pkey_hmac_init"},
     {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_PKEY_POLY1305_INIT, 0),
      "pkey_poly1305_init"},
@@ -59,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"},
@@ -75,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 8808b25..fbf35d1 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -392,11 +392,15 @@ CRYPTO_F_OPENSSL_SK_DEEP_COPY:127:OPENSSL_sk_deep_copy
 CRYPTO_F_OPENSSL_SK_DUP:128:OPENSSL_sk_dup
 CRYPTO_F_OSSL_PROVIDER_ACTIVATE:130:ossl_provider_activate
 CRYPTO_F_OSSL_PROVIDER_ADD_BUILTIN:132:OSSL_PROVIDER_add_builtin
+CRYPTO_F_OSSL_PROVIDER_ADD_PARAMETER:139:ossl_provider_add_parameter
 CRYPTO_F_OSSL_PROVIDER_NEW:131:ossl_provider_new
+CRYPTO_F_OSSL_PROVIDER_SET_MODULE_PATH:140:ossl_provider_set_module_path
 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
@@ -2160,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 0000000..9d9b7a1
--- /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 <string.h>
+#include <openssl/trace.h>
+#include <openssl/err.h>
+#include <openssl/conf.h>
+#include <openssl/safestack.h>
+#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/crypto/provider_core.c b/crypto/provider_core.c
index 7a184a7..9f4c017 100644
--- a/crypto/provider_core.c
+++ b/crypto/provider_core.c
@@ -9,6 +9,7 @@
 
 #include <openssl/core.h>
 #include <openssl/core_numbers.h>
+#include <openssl/params.h>
 #include <openssl/opensslv.h>
 #include "internal/cryptlib.h"
 #include "internal/nelem.h"
@@ -25,6 +26,12 @@ static OSSL_PROVIDER *provider_new(const char *name,
  * =========================
  */
 
+typedef struct {
+    char *name;
+    char *value;
+} INFOPAIR;
+DEFINE_STACK_OF(INFOPAIR)
+
 struct provider_store_st;        /* Forward declaration */
 
 struct ossl_provider_st {
@@ -36,8 +43,10 @@ struct ossl_provider_st {
     CRYPTO_REF_COUNT refcnt;
     CRYPTO_RWLOCK *refcnt_lock;  /* For the ref counter */
     char *name;
+    char *path;
     DSO *module;
     OSSL_provider_init_fn *init_function;
+    STACK_OF(INFOPAIR) *parameters;
     struct provider_store_st *store; /* The store this instance belongs to */
 
     /* Provider side functions */
@@ -243,6 +252,13 @@ OSSL_PROVIDER *ossl_provider_new(OPENSSL_CTX *libctx, const char *name,
     return prov;
 }
 
+static void free_infopair(INFOPAIR *pair)
+{
+    OPENSSL_free(pair->name);
+    OPENSSL_free(pair->value);
+    OPENSSL_free(pair);
+}
+
 void ossl_provider_free(OSSL_PROVIDER *prov)
 {
     if (prov != NULL) {
@@ -270,6 +286,8 @@ void ossl_provider_free(OSSL_PROVIDER *prov)
         if (ref == 0) {
             DSO_free(prov->module);
             OPENSSL_free(prov->name);
+            OPENSSL_free(prov->path);
+            sk_INFOPAIR_pop_free(prov->parameters, free_infopair);
 #ifndef HAVE_ATOMICS
             CRYPTO_THREAD_lock_free(prov->refcnt_lock);
 #endif
@@ -278,6 +296,40 @@ void ossl_provider_free(OSSL_PROVIDER *prov)
     }
 }
 
+/* Setters */
+int ossl_provider_set_module_path(OSSL_PROVIDER *prov, const char *module_path)
+{
+    OPENSSL_free(prov->path);
+    if (module_path == NULL)
+        return 1;
+    if ((prov->path = OPENSSL_strdup(module_path)) != NULL)
+        return 1;
+    CRYPTOerr(CRYPTO_F_OSSL_PROVIDER_SET_MODULE_PATH, ERR_R_MALLOC_FAILURE);
+    return 0;
+}
+
+int ossl_provider_add_parameter(OSSL_PROVIDER *prov,
+                                const char *name, const char *value)
+{
+    INFOPAIR *pair = NULL;
+
+    if ((pair = OPENSSL_zalloc(sizeof(*pair))) != NULL
+        && (prov->parameters != NULL
+            || (prov->parameters = sk_INFOPAIR_new_null()) != NULL)
+        && (pair->name = OPENSSL_strdup(name)) != NULL
+        && (pair->value = OPENSSL_strdup(value)) != NULL
+        && sk_INFOPAIR_push(prov->parameters, pair) > 0)
+        return 1;
+
+    if (pair != NULL) {
+        OPENSSL_free(pair->name);
+        OPENSSL_free(pair->value);
+        OPENSSL_free(pair);
+    }
+    CRYPTOerr(CRYPTO_F_OSSL_PROVIDER_ADD_PARAMETER, ERR_R_MALLOC_FAILURE);
+    return 0;
+}
+
 /*
  * Provider activation.
  *
@@ -310,8 +362,9 @@ static int provider_activate(OSSL_PROVIDER *prov)
      */
     if (prov->init_function == NULL) {
         if (prov->module == NULL) {
-            char *platform_module_name = NULL;
-            char *module_path = NULL;
+            char *allocated_path = NULL;
+            const char *module_path = NULL;
+            char *merged_path = NULL;
             const char *load_dir = ossl_safe_getenv("OPENSSL_MODULES");
 
             if ((prov->module = DSO_new()) == NULL) {
@@ -324,19 +377,22 @@ static int provider_activate(OSSL_PROVIDER *prov)
 
             DSO_ctrl(prov->module, DSO_CTRL_SET_FLAGS,
                      DSO_FLAG_NAME_TRANSLATION_EXT_ONLY, NULL);
-            if ((platform_module_name =
-                 DSO_convert_filename(prov->module, prov->name)) == NULL
-                || (module_path =
-                    DSO_merge(prov->module, platform_module_name,
-                              load_dir)) == NULL
-                || DSO_load(prov->module, module_path, NULL,
-                            DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == NULL) {
+
+            module_path = prov->path;
+            if (module_path == NULL)
+                module_path = allocated_path =
+                    DSO_convert_filename(prov->module, prov->name);
+            if (module_path != NULL)
+                merged_path = DSO_merge(prov->module, module_path, load_dir);
+
+            if (merged_path == NULL
+                || (DSO_load(prov->module, merged_path, NULL, 0)) == NULL) {
                 DSO_free(prov->module);
                 prov->module = NULL;
             }
 
-            OPENSSL_free(platform_module_name);
-            OPENSSL_free(module_path);
+            OPENSSL_free(merged_path);
+            OPENSSL_free(allocated_path);
         }
 
         if (prov->module != NULL)
@@ -565,17 +621,21 @@ static const OSSL_ITEM *core_get_param_types(const OSSL_PROVIDER *prov)
 static int core_get_params(const OSSL_PROVIDER *prov, const OSSL_PARAM params[])
 {
     int i;
+    const OSSL_PARAM *p;
 
-    for (i = 0; params[i].key != NULL; i++) {
-        if (strcmp(params[i].key, "openssl-version") == 0) {
-            *(void **)params[i].data = OPENSSL_VERSION_STR;
-            if (params[i].return_size)
-                *params[i].return_size = sizeof(OPENSSL_VERSION_STR);
-        } else if (strcmp(params[i].key, "provider-name") == 0) {
-            *(void **)params[i].data = prov->name;
-            if (params[i].return_size)
-                *params[i].return_size = strlen(prov->name) + 1;
-        }
+    if ((p = OSSL_PARAM_locate(params, "openssl-version")) != NULL)
+        OSSL_PARAM_set_utf8_ptr(p, OPENSSL_VERSION_STR);
+    if ((p = OSSL_PARAM_locate(params, "provider-name")) != NULL)
+        OSSL_PARAM_set_utf8_ptr(p, prov->name);
+
+    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;
diff --git a/doc/man5/config.pod b/doc/man5/config.pod
index 3d0842c..985b07f 100644
--- a/doc/man5/config.pod
+++ b/doc/man5/config.pod
@@ -106,6 +106,7 @@ section containing configuration module specific information. E.g.:
 
  oid_section = new_oids
  engines = engine_section
+ providers = provider_section
 
  [new_oids]
 
@@ -115,6 +116,10 @@ section containing configuration module specific information. E.g.:
 
  ... engine stuff here ...
 
+ [provider_section]
+
+ ... provider stuff here ...
+
 The features of each configuration module are described below.
 
 =head2 ASN1 Object Configuration Module
@@ -216,6 +221,57 @@ For example:
  # Supply all default algorithms
  default_algorithms = ALL
 
+=head2 Provider Configuration Module
+
+This provider configuration module has the name B<providers>. The
+value of this variable points to a section containing further provider
+configuration information.
+
+The section pointed to by B<providers> is a table of provider names
+(though see B<identity> below) and further sections containing
+configuration information specific to each provider module.
+
+Each provider specific section is used to load its module, perform
+activation and set parameters to pass to the provider on demand. The
+actual operation performed depends on the name of the name value pair.
+The currently supported commands are listed below.
+
+For example:
+
+ [provider_section]
+
+ # Configure provider named "foo"
+ foo = foo_section
+ # Configure provider named "bar"
+ bar = bar_section
+
+ [foo_section]
+ ... "foo" provider specific parameters ...
+
+ [bar_section]
+ ... "bar" provider specific parameters ...
+
+The command B<identity> is used to give the provider name. For example:
+
+ [provider_section]
+ # This would normally handle a provider named "foo"
+ foo = foo_section
+
+ [foo_section]
+ # Override default name and use "myfoo" instead.
+ identity = myfoo
+
+The parameter B<module> loads and adds a provider module from the
+given module path.  That path may be a simple file name, a relative
+path or an absolute path.
+
+The parameter B<activate> determines whether to activate the
+provider. The value has no importance, the presence of the parameter
+is enough for activation to take place.
+
+All parameters in the section as well as sub-sections are made
+available to the provider.
+
 =head2 EVP Configuration Module
 
 This modules has the name B<alg_section> which points to a section containing
@@ -405,6 +461,11 @@ Ignored in set-user-ID and set-group-ID programs.
 The path to the engines directory.
 Ignored in set-user-ID and set-group-ID programs.
 
+=item B<OPENSSL_MODULES>
+
+The path to the directory with OpenSSL modules, such as providers.
+Ignored in set-user-ID and set-group-ID programs.
+
 =back
 
 =head1 BUGS
diff --git a/include/internal/provider.h b/include/internal/provider.h
index 8af20a7..4966cc2 100644
--- a/include/internal/provider.h
+++ b/include/internal/provider.h
@@ -33,8 +33,10 @@ int ossl_provider_upref(OSSL_PROVIDER *prov);
 void ossl_provider_free(OSSL_PROVIDER *prov);
 
 /* Setters */
-int ossl_provider_add_module_location(OSSL_PROVIDER *prov, const char *loc);
 int ossl_provider_set_fallback(OSSL_PROVIDER *prov);
+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);
 
 /*
  * Activate the Provider
@@ -64,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 b38b272..ff5767a 100644
--- a/include/openssl/cryptoerr.h
+++ b/include/openssl/cryptoerr.h
@@ -45,11 +45,15 @@ int ERR_load_CRYPTO_strings(void);
 # define CRYPTO_F_OPENSSL_SK_DUP                          128
 # define CRYPTO_F_OSSL_PROVIDER_ADD_BUILTIN               132
 # define CRYPTO_F_OSSL_PROVIDER_ACTIVATE                  130
+# define CRYPTO_F_OSSL_PROVIDER_ADD_PARAMETER             139
 # define CRYPTO_F_OSSL_PROVIDER_NEW                       131
+# define CRYPTO_F_OSSL_PROVIDER_SET_MODULE_PATH           140
 # define CRYPTO_F_PKEY_HMAC_INIT                          123
 # 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
@@ -61,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
diff --git a/test/build.info b/test/build.info
index 973536d..25abb06 100644
--- a/test/build.info
+++ b/test/build.info
@@ -616,6 +616,8 @@ IF[{- !$disabled{tests} -}]
     DEFINE[provider_test]=OPENSSL_NO_MODULE
     DEFINE[provider_internal_test]=OPENSSL_NO_MODULE
   ENDIF
+  DEPEND[]=provider_internal_test.conf
+  GENERATE[provider_internal_test.conf]=provider_internal_test.conf.in
 
   PROGRAMS{noinst}=params_test
   SOURCE[params_test]=params_test.c
diff --git a/test/p_test.c b/test/p_test.c
index 9e1ba8e..bf13a0a 100644
--- a/test/p_test.c
+++ b/test/p_test.c
@@ -52,21 +52,33 @@ static int p_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[])
         if (strcmp(p->key, "greeting") == 0) {
             static char *opensslv = NULL;
             static char *provname = NULL;
+            static char *greeting = NULL;
             static OSSL_PARAM counter_request[] = {
+                /* Known libcrypto provided parameters */
                 { "openssl-version", OSSL_PARAM_UTF8_PTR,
                   &opensslv, sizeof(&opensslv), NULL },
                 { "provider-name", OSSL_PARAM_UTF8_PTR,
                   &provname, sizeof(&provname), NULL},
+
+                /* This might be present, if there's such a configuration */
+                { "greeting", OSSL_PARAM_UTF8_PTR,
+                  &greeting, sizeof(&greeting), NULL },
+
                 { NULL, 0, NULL, 0, NULL }
             };
             char buf[256];
             size_t buf_l;
 
             if (c_get_params(prov, counter_request)) {
-                const char *versionp = *(void **)counter_request[0].data;
-                const char *namep = *(void **)counter_request[1].data;
-                sprintf(buf, "Hello OpenSSL %.20s, greetings from %s!",
-                        versionp, namep);
+                if (greeting) {
+                    strcpy(buf, greeting);
+                } else {
+                    const char *versionp = *(void **)counter_request[0].data;
+                    const char *namep = *(void **)counter_request[1].data;
+
+                    sprintf(buf, "Hello OpenSSL %.20s, greetings from %s!",
+                            versionp, namep);
+                }
             } else {
                 sprintf(buf, "Howdy stranger...");
             }
diff --git a/test/provider_internal_test.c b/test/provider_internal_test.c
index cbb85c3..54e6714 100644
--- a/test/provider_internal_test.c
+++ b/test/provider_internal_test.c
@@ -8,6 +8,7 @@
  */
 
 #include <stddef.h>
+#include <openssl/crypto.h>
 #include "internal/provider.h"
 #include "testutil.h"
 
@@ -20,20 +21,11 @@ static OSSL_PARAM greeting_request[] = {
     { NULL, 0, NULL, 0, NULL }
 };
 
-static int test_provider(OSSL_PROVIDER *prov)
+static int test_provider(OSSL_PROVIDER *prov, const char *expected_greeting)
 {
-    const char *name = NULL;
     const char *greeting = NULL;
-    char expected_greeting[256];
     int ret = 0;
 
-    if (!TEST_ptr(name = ossl_provider_name(prov)))
-        return 0;
-
-    BIO_snprintf(expected_greeting, sizeof(expected_greeting),
-                 "Hello OpenSSL %.20s, greetings from %s!",
-                 OPENSSL_VERSION_STR, name);
-
     ret =
         TEST_true(ossl_provider_activate(prov))
         && TEST_true(ossl_provider_get_params(prov, greeting_request))
@@ -41,10 +33,22 @@ static int test_provider(OSSL_PROVIDER *prov)
         && TEST_size_t_gt(greeting_request[0].data_size, 0)
         && TEST_str_eq(greeting, expected_greeting);
 
+    TEST_info("Got this greeting: %s\n", greeting);
     ossl_provider_free(prov);
     return ret;
 }
 
+static const char *expected_greeting1(const char *name)
+{
+    static char expected_greeting[256] = "";
+
+    snprintf(expected_greeting, sizeof(expected_greeting),
+             "Hello OpenSSL %.20s, greetings from %s!",
+             OPENSSL_VERSION_STR, name);
+
+    return expected_greeting;
+}
+
 static int test_builtin_provider(void)
 {
     const char *name = "p_test_builtin";
@@ -53,7 +57,7 @@ static int test_builtin_provider(void)
     return
         TEST_ptr(prov =
                  ossl_provider_new(NULL, name, PROVIDER_INIT_FUNCTION_NAME))
-        && test_provider(prov);
+        && test_provider(prov, expected_greeting1(name));
 }
 
 #ifndef OPENSSL_NO_MODULE
@@ -64,7 +68,21 @@ static int test_loaded_provider(void)
 
     return
         TEST_ptr(prov = ossl_provider_new(NULL, name, NULL))
-        && test_provider(prov);
+        && test_provider(prov, expected_greeting1(name));
+}
+
+static int test_configured_provider(void)
+{
+    const char *name = "p_test_configured";
+    OSSL_PROVIDER *prov = NULL;
+    /* This MUST match the config file */
+    const char *expected_greeting =
+        "Hello OpenSSL, greetings from Test Provider";
+
+    return
+        OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL)
+        && TEST_ptr(prov = ossl_provider_find(NULL, name))
+        && test_provider(prov, expected_greeting);
 }
 #endif
 
@@ -73,6 +91,7 @@ int setup_tests(void)
     ADD_TEST(test_builtin_provider);
 #ifndef OPENSSL_NO_MODULE
     ADD_TEST(test_loaded_provider);
+    ADD_TEST(test_configured_provider);
 #endif
     return 1;
 }
diff --git a/test/provider_internal_test.conf.in b/test/provider_internal_test.conf.in
new file mode 100644
index 0000000..12c2924
--- /dev/null
+++ b/test/provider_internal_test.conf.in
@@ -0,0 +1,13 @@
+{- use platform -}
+openssl_conf = openssl_init
+
+[openssl_init]
+providers = providers
+
+[providers]
+p_test_configured = p_test_configured
+
+[p_test_configured]
+module = {- platform->dso('p_test') -}
+activate = 1
+greeting = Hello OpenSSL, greetings from Test Provider
diff --git a/test/recipes/02-test_internal_provider.t b/test/recipes/02-test_internal_provider.t
index 8275eb2..615d17a 100644
--- a/test/recipes/02-test_internal_provider.t
+++ b/test/recipes/02-test_internal_provider.t
@@ -7,12 +7,13 @@
 # https://www.openssl.org/source/license.html
 
 use strict;
-use OpenSSL::Test qw(:DEFAULT bldtop_dir);
+use OpenSSL::Test qw(:DEFAULT bldtop_dir bldtop_file);
 use OpenSSL::Test::Simple;
 use OpenSSL::Test::Utils;
 
 setup("test_internal_provider");
 
-$ENV{"OPENSSL_MODULES"} = bldtop_dir("test");
+$ENV{OPENSSL_MODULES} = bldtop_dir("test");
+$ENV{OPENSSL_CONF} = bldtop_file("test", "provider_internal_test.conf");
 
 simple_test("test_internal_provider", "provider_internal_test");


More information about the openssl-commits mailing list