2 * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
11 #include <openssl/trace.h>
12 #include <openssl/err.h>
13 #include <openssl/conf.h>
14 #include <openssl/safestack.h>
15 #include "internal/provider.h"
17 /* PROVIDER config module */
19 DEFINE_STACK_OF(OSSL_PROVIDER
)
20 static STACK_OF(OSSL_PROVIDER
) *activated_providers
= NULL
;
22 static const char *skip_dot(const char *name
)
24 const char *p
= strchr(name
, '.');
31 static int provider_conf_params(OSSL_PROVIDER
*prov
,
32 const char *name
, const char *value
,
35 STACK_OF(CONF_VALUE
) *sect
;
38 sect
= NCONF_get_section(cnf
, value
);
42 size_t buffer_len
= 0;
44 OSSL_TRACE1(CONF
, "Provider params: start section %s\n", value
);
47 OPENSSL_strlcpy(buffer
, name
, sizeof(buffer
));
48 OPENSSL_strlcat(buffer
, ".", sizeof(buffer
));
49 buffer_len
= strlen(buffer
);
52 for (i
= 0; i
< sk_CONF_VALUE_num(sect
); i
++) {
53 CONF_VALUE
*sectconf
= sk_CONF_VALUE_value(sect
, i
);
55 if (buffer_len
+ strlen(sectconf
->name
) >= sizeof(buffer
))
57 buffer
[buffer_len
] = '\0';
58 OPENSSL_strlcat(buffer
, sectconf
->name
, sizeof(buffer
));
59 if (!provider_conf_params(prov
, buffer
, sectconf
->value
, cnf
))
63 OSSL_TRACE1(CONF
, "Provider params: finish section %s\n", value
);
65 OSSL_TRACE2(CONF
, "Provider params: %s = %s\n", name
, value
);
66 ok
= ossl_provider_add_parameter(prov
, name
, value
);
72 static int provider_conf_load(OPENSSL_CTX
*libctx
, const char *name
,
73 const char *value
, const CONF
*cnf
)
76 STACK_OF(CONF_VALUE
) *ecmds
;
78 OSSL_PROVIDER
*prov
= NULL
;
79 const char *path
= NULL
;
83 name
= skip_dot(name
);
84 OSSL_TRACE1(CONF
, "Configuring provider %s\n", name
);
85 /* Value is a section containing PROVIDER commands */
86 ecmds
= NCONF_get_section(cnf
, value
);
89 CRYPTOerr(CRYPTO_F_PROVIDER_CONF_LOAD
, CRYPTO_R_PROVIDER_SECTION_ERROR
);
93 /* Find the needed data first */
94 for (i
= 0; i
< sk_CONF_VALUE_num(ecmds
); i
++) {
95 CONF_VALUE
*ecmd
= sk_CONF_VALUE_value(ecmds
, i
);
96 const char *confname
= skip_dot(ecmd
->name
);
97 const char *confvalue
= ecmd
->value
;
99 OSSL_TRACE2(CONF
, "Provider command: %s = %s\n",
100 confname
, confvalue
);
102 /* First handle some special pseudo confs */
104 /* Override provider name to use */
105 if (strcmp(confname
, "identity") == 0)
107 else if (strcmp(confname
, "soft_load") == 0)
109 /* Load a dynamic PROVIDER */
110 else if (strcmp(confname
, "module") == 0)
112 else if (strcmp(confname
, "activate") == 0)
116 prov
= ossl_provider_find(libctx
, name
, 1);
118 prov
= ossl_provider_new(libctx
, name
, NULL
, 1);
126 ossl_provider_set_module_path(prov
, path
);
128 ok
= provider_conf_params(prov
, NULL
, value
, cnf
);
130 if (ok
&& activate
) {
131 if (!ossl_provider_activate(prov
)) {
134 if (activated_providers
== NULL
)
135 activated_providers
= sk_OSSL_PROVIDER_new_null();
136 sk_OSSL_PROVIDER_push(activated_providers
, prov
);
141 if (!(activate
&& ok
))
142 ossl_provider_free(prov
);
147 static int provider_conf_init(CONF_IMODULE
*md
, const CONF
*cnf
)
149 STACK_OF(CONF_VALUE
) *elist
;
153 OSSL_TRACE1(CONF
, "Loading providers module: section %s\n",
154 CONF_imodule_get_value(md
));
156 /* Value is a section containing PROVIDERs to configure */
157 elist
= NCONF_get_section(cnf
, CONF_imodule_get_value(md
));
160 CRYPTOerr(CRYPTO_F_PROVIDER_CONF_INIT
,
161 CRYPTO_R_PROVIDER_SECTION_ERROR
);
165 for (i
= 0; i
< sk_CONF_VALUE_num(elist
); i
++) {
166 cval
= sk_CONF_VALUE_value(elist
, i
);
167 if (!provider_conf_load(NULL
, cval
->name
, cval
->value
, cnf
))
175 static void provider_conf_deinit(CONF_IMODULE
*md
)
177 sk_OSSL_PROVIDER_pop_free(activated_providers
, ossl_provider_free
);
178 activated_providers
= NULL
;
179 OSSL_TRACE(CONF
, "Cleaned up providers\n");
182 void ossl_provider_add_conf_module(void)
184 OSSL_TRACE(CONF
, "Adding config module 'providers'\n");
185 CONF_module_add("providers", provider_conf_init
, provider_conf_deinit
);