1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci#include <string.h>
11e1051a39Sopenharmony_ci#include <openssl/trace.h>
12e1051a39Sopenharmony_ci#include <openssl/err.h>
13e1051a39Sopenharmony_ci#include <openssl/conf.h>
14e1051a39Sopenharmony_ci#include <openssl/safestack.h>
15e1051a39Sopenharmony_ci#include <openssl/provider.h>
16e1051a39Sopenharmony_ci#include "internal/provider.h"
17e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
18e1051a39Sopenharmony_ci#include "provider_local.h"
19e1051a39Sopenharmony_ci
20e1051a39Sopenharmony_ciDEFINE_STACK_OF(OSSL_PROVIDER)
21e1051a39Sopenharmony_ci
22e1051a39Sopenharmony_ci/* PROVIDER config module */
23e1051a39Sopenharmony_ci
24e1051a39Sopenharmony_citypedef struct {
25e1051a39Sopenharmony_ci    CRYPTO_RWLOCK *lock;
26e1051a39Sopenharmony_ci    STACK_OF(OSSL_PROVIDER) *activated_providers;
27e1051a39Sopenharmony_ci} PROVIDER_CONF_GLOBAL;
28e1051a39Sopenharmony_ci
29e1051a39Sopenharmony_cistatic void *prov_conf_ossl_ctx_new(OSSL_LIB_CTX *libctx)
30e1051a39Sopenharmony_ci{
31e1051a39Sopenharmony_ci    PROVIDER_CONF_GLOBAL *pcgbl = OPENSSL_zalloc(sizeof(*pcgbl));
32e1051a39Sopenharmony_ci
33e1051a39Sopenharmony_ci    if (pcgbl == NULL)
34e1051a39Sopenharmony_ci        return NULL;
35e1051a39Sopenharmony_ci
36e1051a39Sopenharmony_ci    pcgbl->lock = CRYPTO_THREAD_lock_new();
37e1051a39Sopenharmony_ci    if (pcgbl->lock == NULL) {
38e1051a39Sopenharmony_ci        OPENSSL_free(pcgbl);
39e1051a39Sopenharmony_ci        return NULL;
40e1051a39Sopenharmony_ci    }
41e1051a39Sopenharmony_ci
42e1051a39Sopenharmony_ci    return pcgbl;
43e1051a39Sopenharmony_ci}
44e1051a39Sopenharmony_ci
45e1051a39Sopenharmony_cistatic void prov_conf_ossl_ctx_free(void *vpcgbl)
46e1051a39Sopenharmony_ci{
47e1051a39Sopenharmony_ci    PROVIDER_CONF_GLOBAL *pcgbl = vpcgbl;
48e1051a39Sopenharmony_ci
49e1051a39Sopenharmony_ci    sk_OSSL_PROVIDER_pop_free(pcgbl->activated_providers,
50e1051a39Sopenharmony_ci                              ossl_provider_free);
51e1051a39Sopenharmony_ci
52e1051a39Sopenharmony_ci    OSSL_TRACE(CONF, "Cleaned up providers\n");
53e1051a39Sopenharmony_ci    CRYPTO_THREAD_lock_free(pcgbl->lock);
54e1051a39Sopenharmony_ci    OPENSSL_free(pcgbl);
55e1051a39Sopenharmony_ci}
56e1051a39Sopenharmony_ci
57e1051a39Sopenharmony_cistatic const OSSL_LIB_CTX_METHOD provider_conf_ossl_ctx_method = {
58e1051a39Sopenharmony_ci    /* Must be freed before the provider store is freed */
59e1051a39Sopenharmony_ci    OSSL_LIB_CTX_METHOD_PRIORITY_2,
60e1051a39Sopenharmony_ci    prov_conf_ossl_ctx_new,
61e1051a39Sopenharmony_ci    prov_conf_ossl_ctx_free,
62e1051a39Sopenharmony_ci};
63e1051a39Sopenharmony_ci
64e1051a39Sopenharmony_cistatic const char *skip_dot(const char *name)
65e1051a39Sopenharmony_ci{
66e1051a39Sopenharmony_ci    const char *p = strchr(name, '.');
67e1051a39Sopenharmony_ci
68e1051a39Sopenharmony_ci    if (p != NULL)
69e1051a39Sopenharmony_ci        return p + 1;
70e1051a39Sopenharmony_ci    return name;
71e1051a39Sopenharmony_ci}
72e1051a39Sopenharmony_ci
73e1051a39Sopenharmony_ci/*
74e1051a39Sopenharmony_ci * Parse the provider params section
75e1051a39Sopenharmony_ci * Returns:
76e1051a39Sopenharmony_ci * 1 for success
77e1051a39Sopenharmony_ci * 0 for non-fatal errors
78e1051a39Sopenharmony_ci * < 0 for fatal errors
79e1051a39Sopenharmony_ci */
80e1051a39Sopenharmony_cistatic int provider_conf_params_internal(OSSL_PROVIDER *prov,
81e1051a39Sopenharmony_ci                                         OSSL_PROVIDER_INFO *provinfo,
82e1051a39Sopenharmony_ci                                         const char *name, const char *value,
83e1051a39Sopenharmony_ci                                         const CONF *cnf,
84e1051a39Sopenharmony_ci                                         STACK_OF(OPENSSL_CSTRING) *visited)
85e1051a39Sopenharmony_ci{
86e1051a39Sopenharmony_ci    STACK_OF(CONF_VALUE) *sect;
87e1051a39Sopenharmony_ci    int ok = 1;
88e1051a39Sopenharmony_ci    int rc = 0;
89e1051a39Sopenharmony_ci
90e1051a39Sopenharmony_ci    sect = NCONF_get_section(cnf, value);
91e1051a39Sopenharmony_ci    if (sect != NULL) {
92e1051a39Sopenharmony_ci        int i;
93e1051a39Sopenharmony_ci        char buffer[512];
94e1051a39Sopenharmony_ci        size_t buffer_len = 0;
95e1051a39Sopenharmony_ci
96e1051a39Sopenharmony_ci        OSSL_TRACE1(CONF, "Provider params: start section %s\n", value);
97e1051a39Sopenharmony_ci
98e1051a39Sopenharmony_ci        /*
99e1051a39Sopenharmony_ci         * Check to see if the provided section value has already
100e1051a39Sopenharmony_ci         * been visited.  If it has, then we have a recursive lookup
101e1051a39Sopenharmony_ci         * in the configuration which isn't valid.  As such we should error
102e1051a39Sopenharmony_ci         * out
103e1051a39Sopenharmony_ci         */
104e1051a39Sopenharmony_ci        for (i = 0; i < sk_OPENSSL_CSTRING_num(visited); i++) {
105e1051a39Sopenharmony_ci            if (sk_OPENSSL_CSTRING_value(visited, i) == value) {
106e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_CONF, CONF_R_RECURSIVE_SECTION_REFERENCE);
107e1051a39Sopenharmony_ci                return -1;
108e1051a39Sopenharmony_ci            }
109e1051a39Sopenharmony_ci        }
110e1051a39Sopenharmony_ci
111e1051a39Sopenharmony_ci        /*
112e1051a39Sopenharmony_ci         * We've not visited this node yet, so record it on the stack
113e1051a39Sopenharmony_ci         */
114e1051a39Sopenharmony_ci        if (!sk_OPENSSL_CSTRING_push(visited, value))
115e1051a39Sopenharmony_ci            return -1;
116e1051a39Sopenharmony_ci
117e1051a39Sopenharmony_ci        if (name != NULL) {
118e1051a39Sopenharmony_ci            OPENSSL_strlcpy(buffer, name, sizeof(buffer));
119e1051a39Sopenharmony_ci            OPENSSL_strlcat(buffer, ".", sizeof(buffer));
120e1051a39Sopenharmony_ci            buffer_len = strlen(buffer);
121e1051a39Sopenharmony_ci        }
122e1051a39Sopenharmony_ci
123e1051a39Sopenharmony_ci        for (i = 0; i < sk_CONF_VALUE_num(sect); i++) {
124e1051a39Sopenharmony_ci            CONF_VALUE *sectconf = sk_CONF_VALUE_value(sect, i);
125e1051a39Sopenharmony_ci
126e1051a39Sopenharmony_ci            if (buffer_len + strlen(sectconf->name) >= sizeof(buffer)) {
127e1051a39Sopenharmony_ci                sk_OPENSSL_CSTRING_pop(visited);
128e1051a39Sopenharmony_ci                return -1;
129e1051a39Sopenharmony_ci            }
130e1051a39Sopenharmony_ci            buffer[buffer_len] = '\0';
131e1051a39Sopenharmony_ci            OPENSSL_strlcat(buffer, sectconf->name, sizeof(buffer));
132e1051a39Sopenharmony_ci            rc = provider_conf_params_internal(prov, provinfo, buffer,
133e1051a39Sopenharmony_ci                                               sectconf->value, cnf, visited);
134e1051a39Sopenharmony_ci            if (rc < 0) {
135e1051a39Sopenharmony_ci                sk_OPENSSL_CSTRING_pop(visited);
136e1051a39Sopenharmony_ci                return rc;
137e1051a39Sopenharmony_ci            }
138e1051a39Sopenharmony_ci        }
139e1051a39Sopenharmony_ci        sk_OPENSSL_CSTRING_pop(visited);
140e1051a39Sopenharmony_ci
141e1051a39Sopenharmony_ci        OSSL_TRACE1(CONF, "Provider params: finish section %s\n", value);
142e1051a39Sopenharmony_ci    } else {
143e1051a39Sopenharmony_ci        OSSL_TRACE2(CONF, "Provider params: %s = %s\n", name, value);
144e1051a39Sopenharmony_ci        if (prov != NULL)
145e1051a39Sopenharmony_ci            ok = ossl_provider_add_parameter(prov, name, value);
146e1051a39Sopenharmony_ci        else
147e1051a39Sopenharmony_ci            ok = ossl_provider_info_add_parameter(provinfo, name, value);
148e1051a39Sopenharmony_ci    }
149e1051a39Sopenharmony_ci
150e1051a39Sopenharmony_ci    return ok;
151e1051a39Sopenharmony_ci}
152e1051a39Sopenharmony_ci
153e1051a39Sopenharmony_ci/*
154e1051a39Sopenharmony_ci * recursively parse the provider configuration section
155e1051a39Sopenharmony_ci * of the config file.
156e1051a39Sopenharmony_ci * Returns
157e1051a39Sopenharmony_ci * 1 on success
158e1051a39Sopenharmony_ci * 0 on non-fatal error
159e1051a39Sopenharmony_ci * < 0 on fatal errors
160e1051a39Sopenharmony_ci */
161e1051a39Sopenharmony_cistatic int provider_conf_params(OSSL_PROVIDER *prov,
162e1051a39Sopenharmony_ci                                OSSL_PROVIDER_INFO *provinfo,
163e1051a39Sopenharmony_ci                                const char *name, const char *value,
164e1051a39Sopenharmony_ci                                const CONF *cnf)
165e1051a39Sopenharmony_ci{
166e1051a39Sopenharmony_ci    int rc;
167e1051a39Sopenharmony_ci    STACK_OF(OPENSSL_CSTRING) *visited = sk_OPENSSL_CSTRING_new_null();
168e1051a39Sopenharmony_ci
169e1051a39Sopenharmony_ci    if (visited == NULL)
170e1051a39Sopenharmony_ci        return -1;
171e1051a39Sopenharmony_ci
172e1051a39Sopenharmony_ci    rc = provider_conf_params_internal(prov, provinfo, name,
173e1051a39Sopenharmony_ci                                       value, cnf, visited);
174e1051a39Sopenharmony_ci
175e1051a39Sopenharmony_ci    sk_OPENSSL_CSTRING_free(visited);
176e1051a39Sopenharmony_ci
177e1051a39Sopenharmony_ci    return rc;
178e1051a39Sopenharmony_ci}
179e1051a39Sopenharmony_ci
180e1051a39Sopenharmony_cistatic int prov_already_activated(const char *name,
181e1051a39Sopenharmony_ci                                  STACK_OF(OSSL_PROVIDER) *activated)
182e1051a39Sopenharmony_ci{
183e1051a39Sopenharmony_ci    int i, max;
184e1051a39Sopenharmony_ci
185e1051a39Sopenharmony_ci    if (activated == NULL)
186e1051a39Sopenharmony_ci        return 0;
187e1051a39Sopenharmony_ci
188e1051a39Sopenharmony_ci    max = sk_OSSL_PROVIDER_num(activated);
189e1051a39Sopenharmony_ci    for (i = 0; i < max; i++) {
190e1051a39Sopenharmony_ci        OSSL_PROVIDER *tstprov = sk_OSSL_PROVIDER_value(activated, i);
191e1051a39Sopenharmony_ci
192e1051a39Sopenharmony_ci        if (strcmp(OSSL_PROVIDER_get0_name(tstprov), name) == 0) {
193e1051a39Sopenharmony_ci            return 1;
194e1051a39Sopenharmony_ci        }
195e1051a39Sopenharmony_ci    }
196e1051a39Sopenharmony_ci
197e1051a39Sopenharmony_ci    return 0;
198e1051a39Sopenharmony_ci}
199e1051a39Sopenharmony_ci
200e1051a39Sopenharmony_cistatic int provider_conf_load(OSSL_LIB_CTX *libctx, const char *name,
201e1051a39Sopenharmony_ci                              const char *value, const CONF *cnf)
202e1051a39Sopenharmony_ci{
203e1051a39Sopenharmony_ci    int i;
204e1051a39Sopenharmony_ci    STACK_OF(CONF_VALUE) *ecmds;
205e1051a39Sopenharmony_ci    int soft = 0;
206e1051a39Sopenharmony_ci    OSSL_PROVIDER *prov = NULL, *actual = NULL;
207e1051a39Sopenharmony_ci    const char *path = NULL;
208e1051a39Sopenharmony_ci    long activate = 0;
209e1051a39Sopenharmony_ci    int ok = 0;
210e1051a39Sopenharmony_ci    int added = 0;
211e1051a39Sopenharmony_ci
212e1051a39Sopenharmony_ci    name = skip_dot(name);
213e1051a39Sopenharmony_ci    OSSL_TRACE1(CONF, "Configuring provider %s\n", name);
214e1051a39Sopenharmony_ci    /* Value is a section containing PROVIDER commands */
215e1051a39Sopenharmony_ci    ecmds = NCONF_get_section(cnf, value);
216e1051a39Sopenharmony_ci
217e1051a39Sopenharmony_ci    if (!ecmds) {
218e1051a39Sopenharmony_ci        ERR_raise_data(ERR_LIB_CRYPTO, CRYPTO_R_PROVIDER_SECTION_ERROR,
219e1051a39Sopenharmony_ci                       "section=%s not found", value);
220e1051a39Sopenharmony_ci        return 0;
221e1051a39Sopenharmony_ci    }
222e1051a39Sopenharmony_ci
223e1051a39Sopenharmony_ci    /* Find the needed data first */
224e1051a39Sopenharmony_ci    for (i = 0; i < sk_CONF_VALUE_num(ecmds); i++) {
225e1051a39Sopenharmony_ci        CONF_VALUE *ecmd = sk_CONF_VALUE_value(ecmds, i);
226e1051a39Sopenharmony_ci        const char *confname = skip_dot(ecmd->name);
227e1051a39Sopenharmony_ci        const char *confvalue = ecmd->value;
228e1051a39Sopenharmony_ci
229e1051a39Sopenharmony_ci        OSSL_TRACE2(CONF, "Provider command: %s = %s\n",
230e1051a39Sopenharmony_ci                    confname, confvalue);
231e1051a39Sopenharmony_ci
232e1051a39Sopenharmony_ci        /* First handle some special pseudo confs */
233e1051a39Sopenharmony_ci
234e1051a39Sopenharmony_ci        /* Override provider name to use */
235e1051a39Sopenharmony_ci        if (strcmp(confname, "identity") == 0)
236e1051a39Sopenharmony_ci            name = confvalue;
237e1051a39Sopenharmony_ci        else if (strcmp(confname, "soft_load") == 0)
238e1051a39Sopenharmony_ci            soft = 1;
239e1051a39Sopenharmony_ci        /* Load a dynamic PROVIDER */
240e1051a39Sopenharmony_ci        else if (strcmp(confname, "module") == 0)
241e1051a39Sopenharmony_ci            path = confvalue;
242e1051a39Sopenharmony_ci        else if (strcmp(confname, "activate") == 0)
243e1051a39Sopenharmony_ci            activate = 1;
244e1051a39Sopenharmony_ci    }
245e1051a39Sopenharmony_ci
246e1051a39Sopenharmony_ci    if (activate) {
247e1051a39Sopenharmony_ci        PROVIDER_CONF_GLOBAL *pcgbl
248e1051a39Sopenharmony_ci            = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_PROVIDER_CONF_INDEX,
249e1051a39Sopenharmony_ci                                    &provider_conf_ossl_ctx_method);
250e1051a39Sopenharmony_ci
251e1051a39Sopenharmony_ci        if (pcgbl == NULL || !CRYPTO_THREAD_write_lock(pcgbl->lock)) {
252e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
253e1051a39Sopenharmony_ci            return 0;
254e1051a39Sopenharmony_ci        }
255e1051a39Sopenharmony_ci        if (!prov_already_activated(name, pcgbl->activated_providers)) {
256e1051a39Sopenharmony_ci            /*
257e1051a39Sopenharmony_ci            * There is an attempt to activate a provider, so we should disable
258e1051a39Sopenharmony_ci            * loading of fallbacks. Otherwise a misconfiguration could mean the
259e1051a39Sopenharmony_ci            * intended provider does not get loaded. Subsequent fetches could
260e1051a39Sopenharmony_ci            * then fallback to the default provider - which may be the wrong
261e1051a39Sopenharmony_ci            * thing.
262e1051a39Sopenharmony_ci            */
263e1051a39Sopenharmony_ci            if (!ossl_provider_disable_fallback_loading(libctx)) {
264e1051a39Sopenharmony_ci                CRYPTO_THREAD_unlock(pcgbl->lock);
265e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
266e1051a39Sopenharmony_ci                return 0;
267e1051a39Sopenharmony_ci            }
268e1051a39Sopenharmony_ci            prov = ossl_provider_find(libctx, name, 1);
269e1051a39Sopenharmony_ci            if (prov == NULL)
270e1051a39Sopenharmony_ci                prov = ossl_provider_new(libctx, name, NULL, 1);
271e1051a39Sopenharmony_ci            if (prov == NULL) {
272e1051a39Sopenharmony_ci                CRYPTO_THREAD_unlock(pcgbl->lock);
273e1051a39Sopenharmony_ci                if (soft)
274e1051a39Sopenharmony_ci                    ERR_clear_error();
275e1051a39Sopenharmony_ci                return 0;
276e1051a39Sopenharmony_ci            }
277e1051a39Sopenharmony_ci
278e1051a39Sopenharmony_ci            if (path != NULL)
279e1051a39Sopenharmony_ci                ossl_provider_set_module_path(prov, path);
280e1051a39Sopenharmony_ci
281e1051a39Sopenharmony_ci            ok = provider_conf_params(prov, NULL, NULL, value, cnf);
282e1051a39Sopenharmony_ci
283e1051a39Sopenharmony_ci            if (ok > 0) {
284e1051a39Sopenharmony_ci                if (!ossl_provider_activate(prov, 1, 0)) {
285e1051a39Sopenharmony_ci                    ok = 0;
286e1051a39Sopenharmony_ci                } else if (!ossl_provider_add_to_store(prov, &actual, 0)) {
287e1051a39Sopenharmony_ci                    ossl_provider_deactivate(prov, 1);
288e1051a39Sopenharmony_ci                    ok = 0;
289e1051a39Sopenharmony_ci                } else if (actual != prov
290e1051a39Sopenharmony_ci                           && !ossl_provider_activate(actual, 1, 0)) {
291e1051a39Sopenharmony_ci                    ossl_provider_free(actual);
292e1051a39Sopenharmony_ci                    ok = 0;
293e1051a39Sopenharmony_ci                } else {
294e1051a39Sopenharmony_ci                    if (pcgbl->activated_providers == NULL)
295e1051a39Sopenharmony_ci                        pcgbl->activated_providers = sk_OSSL_PROVIDER_new_null();
296e1051a39Sopenharmony_ci                    if (pcgbl->activated_providers == NULL
297e1051a39Sopenharmony_ci                        || !sk_OSSL_PROVIDER_push(pcgbl->activated_providers,
298e1051a39Sopenharmony_ci                                                  actual)) {
299e1051a39Sopenharmony_ci                        ossl_provider_deactivate(actual, 1);
300e1051a39Sopenharmony_ci                        ossl_provider_free(actual);
301e1051a39Sopenharmony_ci                        ok = 0;
302e1051a39Sopenharmony_ci                    } else {
303e1051a39Sopenharmony_ci                        ok = 1;
304e1051a39Sopenharmony_ci                    }
305e1051a39Sopenharmony_ci                }
306e1051a39Sopenharmony_ci            }
307e1051a39Sopenharmony_ci            if (ok <= 0)
308e1051a39Sopenharmony_ci                ossl_provider_free(prov);
309e1051a39Sopenharmony_ci        }
310e1051a39Sopenharmony_ci        CRYPTO_THREAD_unlock(pcgbl->lock);
311e1051a39Sopenharmony_ci    } else {
312e1051a39Sopenharmony_ci        OSSL_PROVIDER_INFO entry;
313e1051a39Sopenharmony_ci
314e1051a39Sopenharmony_ci        memset(&entry, 0, sizeof(entry));
315e1051a39Sopenharmony_ci        ok = 1;
316e1051a39Sopenharmony_ci        if (name != NULL) {
317e1051a39Sopenharmony_ci            entry.name = OPENSSL_strdup(name);
318e1051a39Sopenharmony_ci            if (entry.name == NULL) {
319e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
320e1051a39Sopenharmony_ci                ok = 0;
321e1051a39Sopenharmony_ci            }
322e1051a39Sopenharmony_ci        }
323e1051a39Sopenharmony_ci        if (ok && path != NULL) {
324e1051a39Sopenharmony_ci            entry.path = OPENSSL_strdup(path);
325e1051a39Sopenharmony_ci            if (entry.path == NULL) {
326e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
327e1051a39Sopenharmony_ci                ok = 0;
328e1051a39Sopenharmony_ci            }
329e1051a39Sopenharmony_ci        }
330e1051a39Sopenharmony_ci        if (ok)
331e1051a39Sopenharmony_ci            ok = provider_conf_params(NULL, &entry, NULL, value, cnf);
332e1051a39Sopenharmony_ci        if (ok >= 1 && (entry.path != NULL || entry.parameters != NULL)) {
333e1051a39Sopenharmony_ci            ok = ossl_provider_info_add_to_store(libctx, &entry);
334e1051a39Sopenharmony_ci            added = 1;
335e1051a39Sopenharmony_ci        }
336e1051a39Sopenharmony_ci        if (added == 0)
337e1051a39Sopenharmony_ci            ossl_provider_info_clear(&entry);
338e1051a39Sopenharmony_ci    }
339e1051a39Sopenharmony_ci
340e1051a39Sopenharmony_ci    /*
341e1051a39Sopenharmony_ci     * Provider activation returns a tristate:
342e1051a39Sopenharmony_ci     * 1 for successful activation
343e1051a39Sopenharmony_ci     * 0 for non-fatal activation failure
344e1051a39Sopenharmony_ci     * < 0 for fatal activation failure
345e1051a39Sopenharmony_ci     * We return success (1) for activation, (1) for non-fatal activation
346e1051a39Sopenharmony_ci     * failure, and (0) for fatal activation failure
347e1051a39Sopenharmony_ci     */
348e1051a39Sopenharmony_ci    return ok >= 0;
349e1051a39Sopenharmony_ci}
350e1051a39Sopenharmony_ci
351e1051a39Sopenharmony_cistatic int provider_conf_init(CONF_IMODULE *md, const CONF *cnf)
352e1051a39Sopenharmony_ci{
353e1051a39Sopenharmony_ci    STACK_OF(CONF_VALUE) *elist;
354e1051a39Sopenharmony_ci    CONF_VALUE *cval;
355e1051a39Sopenharmony_ci    int i;
356e1051a39Sopenharmony_ci
357e1051a39Sopenharmony_ci    OSSL_TRACE1(CONF, "Loading providers module: section %s\n",
358e1051a39Sopenharmony_ci                CONF_imodule_get_value(md));
359e1051a39Sopenharmony_ci
360e1051a39Sopenharmony_ci    /* Value is a section containing PROVIDERs to configure */
361e1051a39Sopenharmony_ci    elist = NCONF_get_section(cnf, CONF_imodule_get_value(md));
362e1051a39Sopenharmony_ci
363e1051a39Sopenharmony_ci    if (!elist) {
364e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_PROVIDER_SECTION_ERROR);
365e1051a39Sopenharmony_ci        return 0;
366e1051a39Sopenharmony_ci    }
367e1051a39Sopenharmony_ci
368e1051a39Sopenharmony_ci    for (i = 0; i < sk_CONF_VALUE_num(elist); i++) {
369e1051a39Sopenharmony_ci        cval = sk_CONF_VALUE_value(elist, i);
370e1051a39Sopenharmony_ci        if (!provider_conf_load(NCONF_get0_libctx((CONF *)cnf),
371e1051a39Sopenharmony_ci                                cval->name, cval->value, cnf))
372e1051a39Sopenharmony_ci            return 0;
373e1051a39Sopenharmony_ci    }
374e1051a39Sopenharmony_ci
375e1051a39Sopenharmony_ci    return 1;
376e1051a39Sopenharmony_ci}
377e1051a39Sopenharmony_ci
378e1051a39Sopenharmony_civoid ossl_provider_add_conf_module(void)
379e1051a39Sopenharmony_ci{
380e1051a39Sopenharmony_ci    OSSL_TRACE(CONF, "Adding config module 'providers'\n");
381e1051a39Sopenharmony_ci    CONF_module_add("providers", provider_conf_init, NULL);
382e1051a39Sopenharmony_ci}
383