]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/provider_conf.c
a04a7aa5535e86c9b724bd82800b875ea8871730
[thirdparty/openssl.git] / crypto / provider_conf.c
1 /*
2 * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
3 *
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
8 */
9
10 #include <string.h>
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"
16 #include "internal/cryptlib.h"
17
18 DEFINE_STACK_OF(OSSL_PROVIDER)
19
20 /* PROVIDER config module */
21
22 typedef struct {
23 STACK_OF(OSSL_PROVIDER) *activated_providers;
24 } PROVIDER_CONF_GLOBAL;
25
26 static void *prov_conf_ossl_ctx_new(OSSL_LIB_CTX *libctx)
27 {
28 PROVIDER_CONF_GLOBAL *pcgbl = OPENSSL_zalloc(sizeof(*pcgbl));
29
30 if (pcgbl == NULL)
31 return NULL;
32
33 return pcgbl;
34 }
35
36 static void prov_conf_ossl_ctx_free(void *vpcgbl)
37 {
38 PROVIDER_CONF_GLOBAL *pcgbl = vpcgbl;
39
40 sk_OSSL_PROVIDER_pop_free(pcgbl->activated_providers,
41 ossl_provider_free);
42
43 OSSL_TRACE(CONF, "Cleaned up providers\n");
44 OPENSSL_free(pcgbl);
45 }
46
47 static const OSSL_LIB_CTX_METHOD provider_conf_ossl_ctx_method = {
48 prov_conf_ossl_ctx_new,
49 prov_conf_ossl_ctx_free,
50 };
51
52 static const char *skip_dot(const char *name)
53 {
54 const char *p = strchr(name, '.');
55
56 if (p != NULL)
57 return p + 1;
58 return name;
59 }
60
61 static int provider_conf_params(OSSL_PROVIDER *prov,
62 const char *name, const char *value,
63 const CONF *cnf)
64 {
65 STACK_OF(CONF_VALUE) *sect;
66 int ok = 1;
67
68 sect = NCONF_get_section(cnf, value);
69 if (sect != NULL) {
70 int i;
71 char buffer[512];
72 size_t buffer_len = 0;
73
74 OSSL_TRACE1(CONF, "Provider params: start section %s\n", value);
75
76 if (name != NULL) {
77 OPENSSL_strlcpy(buffer, name, sizeof(buffer));
78 OPENSSL_strlcat(buffer, ".", sizeof(buffer));
79 buffer_len = strlen(buffer);
80 }
81
82 for (i = 0; i < sk_CONF_VALUE_num(sect); i++) {
83 CONF_VALUE *sectconf = sk_CONF_VALUE_value(sect, i);
84
85 if (buffer_len + strlen(sectconf->name) >= sizeof(buffer))
86 return 0;
87 buffer[buffer_len] = '\0';
88 OPENSSL_strlcat(buffer, sectconf->name, sizeof(buffer));
89 if (!provider_conf_params(prov, buffer, sectconf->value, cnf))
90 return 0;
91 }
92
93 OSSL_TRACE1(CONF, "Provider params: finish section %s\n", value);
94 } else {
95 OSSL_TRACE2(CONF, "Provider params: %s = %s\n", name, value);
96 ok = ossl_provider_add_parameter(prov, name, value);
97 }
98
99 return ok;
100 }
101
102 static int provider_conf_load(OSSL_LIB_CTX *libctx, const char *name,
103 const char *value, const CONF *cnf)
104 {
105 int i;
106 STACK_OF(CONF_VALUE) *ecmds;
107 int soft = 0;
108 OSSL_PROVIDER *prov = NULL;
109 const char *path = NULL;
110 long activate = 0;
111 int ok = 0;
112 PROVIDER_CONF_GLOBAL *pcgbl
113 = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_PROVIDER_CONF_INDEX,
114 &provider_conf_ossl_ctx_method);
115
116 name = skip_dot(name);
117 OSSL_TRACE1(CONF, "Configuring provider %s\n", name);
118 /* Value is a section containing PROVIDER commands */
119 ecmds = NCONF_get_section(cnf, value);
120
121 if (!ecmds) {
122 ERR_raise_data(ERR_LIB_CRYPTO, CRYPTO_R_PROVIDER_SECTION_ERROR,
123 "section=%s not found", value);
124 return 0;
125 }
126
127 /* Find the needed data first */
128 for (i = 0; i < sk_CONF_VALUE_num(ecmds); i++) {
129 CONF_VALUE *ecmd = sk_CONF_VALUE_value(ecmds, i);
130 const char *confname = skip_dot(ecmd->name);
131 const char *confvalue = ecmd->value;
132
133 OSSL_TRACE2(CONF, "Provider command: %s = %s\n",
134 confname, confvalue);
135
136 /* First handle some special pseudo confs */
137
138 /* Override provider name to use */
139 if (strcmp(confname, "identity") == 0)
140 name = confvalue;
141 else if (strcmp(confname, "soft_load") == 0)
142 soft = 1;
143 /* Load a dynamic PROVIDER */
144 else if (strcmp(confname, "module") == 0)
145 path = confvalue;
146 else if (strcmp(confname, "activate") == 0)
147 activate = 1;
148 }
149
150 prov = ossl_provider_find(libctx, name, 1);
151 if (prov == NULL)
152 prov = ossl_provider_new(libctx, name, NULL, 1);
153 if (prov == NULL) {
154 if (soft)
155 ERR_clear_error();
156 return 0;
157 }
158
159 if (path != NULL)
160 ossl_provider_set_module_path(prov, path);
161
162 ok = provider_conf_params(prov, NULL, value, cnf);
163
164 if (ok && activate) {
165 if (!ossl_provider_activate(prov, 0)) {
166 ok = 0;
167 } else {
168 if (pcgbl->activated_providers == NULL)
169 pcgbl->activated_providers = sk_OSSL_PROVIDER_new_null();
170 sk_OSSL_PROVIDER_push(pcgbl->activated_providers, prov);
171 ok = 1;
172 }
173 }
174
175 if (!(activate && ok))
176 ossl_provider_free(prov);
177
178 return ok;
179 }
180
181 static int provider_conf_init(CONF_IMODULE *md, const CONF *cnf)
182 {
183 STACK_OF(CONF_VALUE) *elist;
184 CONF_VALUE *cval;
185 int i;
186
187 OSSL_TRACE1(CONF, "Loading providers module: section %s\n",
188 CONF_imodule_get_value(md));
189
190 /* Value is a section containing PROVIDERs to configure */
191 elist = NCONF_get_section(cnf, CONF_imodule_get_value(md));
192
193 if (!elist) {
194 ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_PROVIDER_SECTION_ERROR);
195 return 0;
196 }
197
198 for (i = 0; i < sk_CONF_VALUE_num(elist); i++) {
199 cval = sk_CONF_VALUE_value(elist, i);
200 if (!provider_conf_load(cnf->libctx, cval->name, cval->value, cnf))
201 return 0;
202 }
203
204 return 1;
205 }
206
207 void ossl_provider_add_conf_module(void)
208 {
209 OSSL_TRACE(CONF, "Adding config module 'providers'\n");
210 CONF_module_add("providers", provider_conf_init, NULL);
211 }