]>
Commit | Line | Data |
---|---|---|
abbc2c40 RL |
1 | /* |
2 | * Copyright 2019 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 | ||
17 | /* PROVIDER config module */ | |
18 | ||
19 | DEFINE_STACK_OF(OSSL_PROVIDER) | |
20 | static STACK_OF(OSSL_PROVIDER) *activated_providers = NULL; | |
21 | ||
22 | static const char *skip_dot(const char *name) | |
23 | { | |
24 | const char *p = strchr(name, '.'); | |
25 | ||
26 | if (p != NULL) | |
27 | return p + 1; | |
28 | return name; | |
29 | } | |
30 | ||
31 | static int provider_conf_params(OSSL_PROVIDER *prov, | |
32 | const char *name, const char *value, | |
33 | const CONF *cnf) | |
34 | { | |
35 | STACK_OF(CONF_VALUE) *sect; | |
36 | int ok = 1; | |
37 | ||
abbc2c40 RL |
38 | sect = NCONF_get_section(cnf, value); |
39 | if (sect != NULL) { | |
40 | int i; | |
41 | char buffer[512]; | |
42 | size_t buffer_len = 0; | |
43 | ||
71849dff RL |
44 | OSSL_TRACE1(CONF, "Provider params: start section %s\n", value); |
45 | ||
abbc2c40 RL |
46 | if (name != NULL) { |
47 | OPENSSL_strlcpy(buffer, name, sizeof(buffer)); | |
48 | OPENSSL_strlcat(buffer, ".", sizeof(buffer)); | |
49 | buffer_len = strlen(buffer); | |
50 | } | |
51 | ||
52 | for (i = 0; i < sk_CONF_VALUE_num(sect); i++) { | |
53 | CONF_VALUE *sectconf = sk_CONF_VALUE_value(sect, i); | |
54 | ||
55 | if (buffer_len + strlen(sectconf->name) >= sizeof(buffer)) | |
56 | return 0; | |
57 | buffer[buffer_len] = '\0'; | |
58 | OPENSSL_strlcat(buffer, sectconf->name, sizeof(buffer)); | |
59 | if (!provider_conf_params(prov, buffer, sectconf->value, cnf)) | |
60 | return 0; | |
61 | } | |
71849dff RL |
62 | |
63 | OSSL_TRACE1(CONF, "Provider params: finish section %s\n", value); | |
abbc2c40 | 64 | } else { |
71849dff | 65 | OSSL_TRACE2(CONF, "Provider params: %s = %s\n", name, value); |
abbc2c40 RL |
66 | ok = ossl_provider_add_parameter(prov, name, value); |
67 | } | |
68 | ||
69 | return ok; | |
70 | } | |
71 | ||
72 | static int provider_conf_load(OPENSSL_CTX *libctx, const char *name, | |
73 | const char *value, const CONF *cnf) | |
74 | { | |
75 | int i; | |
76 | STACK_OF(CONF_VALUE) *ecmds; | |
77 | int soft = 0; | |
78 | OSSL_PROVIDER *prov = NULL; | |
79 | const char *path = NULL; | |
80 | long activate = 0; | |
81 | int ok = 0; | |
82 | ||
83 | name = skip_dot(name); | |
71849dff | 84 | OSSL_TRACE1(CONF, "Configuring provider %s\n", name); |
abbc2c40 RL |
85 | /* Value is a section containing PROVIDER commands */ |
86 | ecmds = NCONF_get_section(cnf, value); | |
87 | ||
88 | if (!ecmds) { | |
89 | CRYPTOerr(CRYPTO_F_PROVIDER_CONF_LOAD, CRYPTO_R_PROVIDER_SECTION_ERROR); | |
90 | return 0; | |
91 | } | |
92 | ||
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; | |
98 | ||
71849dff | 99 | OSSL_TRACE2(CONF, "Provider command: %s = %s\n", |
abbc2c40 RL |
100 | confname, confvalue); |
101 | ||
102 | /* First handle some special pseudo confs */ | |
103 | ||
104 | /* Override provider name to use */ | |
105 | if (strcmp(confname, "identity") == 0) | |
106 | name = confvalue; | |
107 | else if (strcmp(confname, "soft_load") == 0) | |
108 | soft = 1; | |
109 | /* Load a dynamic PROVIDER */ | |
110 | else if (strcmp(confname, "module") == 0) | |
111 | path = confvalue; | |
112 | else if (strcmp(confname, "activate") == 0) | |
113 | activate = 1; | |
114 | } | |
115 | ||
da020181 RL |
116 | prov = ossl_provider_find(libctx, name); |
117 | if (prov == NULL) | |
118 | prov = ossl_provider_new(libctx, name, NULL); | |
abbc2c40 RL |
119 | if (prov == NULL) { |
120 | if (soft) | |
121 | ERR_clear_error(); | |
122 | return 0; | |
123 | } | |
124 | ||
125 | if (path != NULL) | |
126 | ossl_provider_set_module_path(prov, path); | |
127 | ||
128 | ok = provider_conf_params(prov, NULL, value, cnf); | |
129 | ||
130 | if (ok && activate) { | |
131 | if (!ossl_provider_activate(prov)) { | |
132 | ok = 0; | |
133 | } else { | |
134 | if (activated_providers == NULL) | |
135 | activated_providers = sk_OSSL_PROVIDER_new_null(); | |
136 | sk_OSSL_PROVIDER_push(activated_providers, prov); | |
137 | ok = 1; | |
138 | } | |
139 | } | |
140 | ||
141 | if (!(activate && ok)) | |
142 | ossl_provider_free(prov); | |
143 | ||
144 | return ok; | |
145 | } | |
146 | ||
147 | static int provider_conf_init(CONF_IMODULE *md, const CONF *cnf) | |
148 | { | |
149 | STACK_OF(CONF_VALUE) *elist; | |
150 | CONF_VALUE *cval; | |
151 | int i; | |
152 | ||
71849dff RL |
153 | OSSL_TRACE1(CONF, "Loading providers module: section %s\n", |
154 | CONF_imodule_get_value(md)); | |
155 | ||
abbc2c40 RL |
156 | /* Value is a section containing PROVIDERs to configure */ |
157 | elist = NCONF_get_section(cnf, CONF_imodule_get_value(md)); | |
158 | ||
159 | if (!elist) { | |
160 | CRYPTOerr(CRYPTO_F_PROVIDER_CONF_INIT, | |
161 | CRYPTO_R_PROVIDER_SECTION_ERROR); | |
162 | return 0; | |
163 | } | |
164 | ||
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)) | |
168 | return 0; | |
169 | } | |
170 | ||
171 | return 1; | |
172 | } | |
173 | ||
174 | ||
175 | static void provider_conf_deinit(CONF_IMODULE *md) | |
176 | { | |
177 | sk_OSSL_PROVIDER_pop_free(activated_providers, ossl_provider_free); | |
178 | activated_providers = NULL; | |
71849dff | 179 | OSSL_TRACE(CONF, "Cleaned up providers\n"); |
abbc2c40 RL |
180 | } |
181 | ||
182 | void ossl_provider_add_conf_module(void) | |
183 | { | |
71849dff | 184 | OSSL_TRACE(CONF, "Adding config module 'providers'\n"); |
abbc2c40 RL |
185 | CONF_module_add("providers", provider_conf_init, provider_conf_deinit); |
186 | } |