]>
Commit | Line | Data |
---|---|---|
a94a3e0d 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 <openssl/crypto.h> | |
11 | #include <openssl/core_numbers.h> | |
12 | #include <openssl/evp.h> | |
13 | #include <openssl/err.h> | |
14 | #include "internal/provider.h" | |
15 | #include "internal/refcount.h" | |
25f2138b | 16 | #include "crypto/evp.h" |
706457b7 | 17 | #include "evp_local.h" |
a94a3e0d RL |
18 | |
19 | ||
20 | static void *keymgmt_new(void) | |
21 | { | |
22 | EVP_KEYMGMT *keymgmt = NULL; | |
23 | ||
24 | if ((keymgmt = OPENSSL_zalloc(sizeof(*keymgmt))) == NULL | |
25 | || (keymgmt->lock = CRYPTO_THREAD_lock_new()) == NULL) { | |
26 | EVP_KEYMGMT_free(keymgmt); | |
6b9e3724 | 27 | EVPerr(0, ERR_R_MALLOC_FAILURE); |
a94a3e0d RL |
28 | return NULL; |
29 | } | |
30 | ||
31 | keymgmt->refcnt = 1; | |
32 | ||
33 | return keymgmt; | |
34 | } | |
35 | ||
f7c16d48 RL |
36 | static void *keymgmt_from_dispatch(int name_id, |
37 | const OSSL_DISPATCH *fns, | |
0ddf74bf | 38 | OSSL_PROVIDER *prov) |
a94a3e0d RL |
39 | { |
40 | EVP_KEYMGMT *keymgmt = NULL; | |
4fe54d67 | 41 | int setparamfncnt = 0, getparamfncnt = 0, importfncnt = 0, exportfncnt = 0; |
a94a3e0d | 42 | |
f7c16d48 | 43 | if ((keymgmt = keymgmt_new()) == NULL) { |
6b9e3724 | 44 | EVP_KEYMGMT_free(keymgmt); |
a94a3e0d | 45 | return NULL; |
6b9e3724 | 46 | } |
f7c16d48 | 47 | keymgmt->name_id = name_id; |
a94a3e0d RL |
48 | |
49 | for (; fns->function_id != 0; fns++) { | |
50 | switch (fns->function_id) { | |
b305452f RL |
51 | case OSSL_FUNC_KEYMGMT_NEW: |
52 | if (keymgmt->new == NULL) | |
53 | keymgmt->new = OSSL_get_OP_keymgmt_new(fns); | |
a94a3e0d | 54 | break; |
b305452f RL |
55 | case OSSL_FUNC_KEYMGMT_FREE: |
56 | if (keymgmt->free == NULL) | |
57 | keymgmt->free = OSSL_get_OP_keymgmt_free(fns); | |
a94a3e0d | 58 | break; |
b305452f | 59 | case OSSL_FUNC_KEYMGMT_GET_PARAMS: |
273a67e3 | 60 | if (keymgmt->get_params == NULL) { |
4fe54d67 | 61 | getparamfncnt++; |
b305452f | 62 | keymgmt->get_params = OSSL_get_OP_keymgmt_get_params(fns); |
273a67e3 | 63 | } |
a94a3e0d | 64 | break; |
b305452f | 65 | case OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS: |
273a67e3 | 66 | if (keymgmt->gettable_params == NULL) { |
4fe54d67 | 67 | getparamfncnt++; |
b305452f RL |
68 | keymgmt->gettable_params = |
69 | OSSL_get_OP_keymgmt_gettable_params(fns); | |
273a67e3 | 70 | } |
a94a3e0d | 71 | break; |
4fe54d67 NT |
72 | case OSSL_FUNC_KEYMGMT_SET_PARAMS: |
73 | if (keymgmt->set_params == NULL) { | |
74 | setparamfncnt++; | |
75 | keymgmt->set_params = OSSL_get_OP_keymgmt_set_params(fns); | |
76 | } | |
77 | break; | |
78 | case OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS: | |
79 | if (keymgmt->settable_params == NULL) { | |
80 | setparamfncnt++; | |
81 | keymgmt->settable_params = | |
82 | OSSL_get_OP_keymgmt_settable_params(fns); | |
83 | } | |
84 | break; | |
b305452f RL |
85 | case OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME: |
86 | if (keymgmt->query_operation_name == NULL) | |
87 | keymgmt->query_operation_name = | |
88 | OSSL_get_OP_keymgmt_query_operation_name(fns); | |
6508e858 | 89 | break; |
b305452f RL |
90 | case OSSL_FUNC_KEYMGMT_HAS: |
91 | if (keymgmt->has == NULL) | |
92 | keymgmt->has = OSSL_get_OP_keymgmt_has(fns); | |
6508e858 | 93 | break; |
b305452f RL |
94 | case OSSL_FUNC_KEYMGMT_VALIDATE: |
95 | if (keymgmt->validate == NULL) | |
96 | keymgmt->validate = OSSL_get_OP_keymgmt_validate(fns); | |
e62a45b6 | 97 | break; |
bee5d6cd RL |
98 | case OSSL_FUNC_KEYMGMT_MATCH: |
99 | if (keymgmt->match == NULL) | |
100 | keymgmt->match = OSSL_get_OP_keymgmt_match(fns); | |
101 | break; | |
b305452f | 102 | case OSSL_FUNC_KEYMGMT_IMPORT: |
273a67e3 RL |
103 | if (keymgmt->import == NULL) { |
104 | importfncnt++; | |
b305452f | 105 | keymgmt->import = OSSL_get_OP_keymgmt_import(fns); |
273a67e3 | 106 | } |
12603de6 | 107 | break; |
b305452f | 108 | case OSSL_FUNC_KEYMGMT_IMPORT_TYPES: |
273a67e3 RL |
109 | if (keymgmt->import_types == NULL) { |
110 | importfncnt++; | |
b305452f | 111 | keymgmt->import_types = OSSL_get_OP_keymgmt_import_types(fns); |
273a67e3 | 112 | } |
12603de6 | 113 | break; |
b305452f | 114 | case OSSL_FUNC_KEYMGMT_EXPORT: |
273a67e3 RL |
115 | if (keymgmt->export == NULL) { |
116 | exportfncnt++; | |
b305452f | 117 | keymgmt->export = OSSL_get_OP_keymgmt_export(fns); |
273a67e3 | 118 | } |
12603de6 | 119 | break; |
b305452f | 120 | case OSSL_FUNC_KEYMGMT_EXPORT_TYPES: |
273a67e3 RL |
121 | if (keymgmt->export_types == NULL) { |
122 | exportfncnt++; | |
b305452f | 123 | keymgmt->export_types = OSSL_get_OP_keymgmt_export_types(fns); |
273a67e3 | 124 | } |
12603de6 | 125 | break; |
a94a3e0d RL |
126 | } |
127 | } | |
128 | /* | |
129 | * Try to check that the method is sensible. | |
b305452f RL |
130 | * At least one constructor and the destructor are MANDATORY |
131 | * The functions 'has' is MANDATORY | |
a94a3e0d RL |
132 | * It makes no sense being able to free stuff if you can't create it. |
133 | * It makes no sense providing OSSL_PARAM descriptors for import and | |
134 | * export if you can't import or export. | |
135 | */ | |
b305452f RL |
136 | if (keymgmt->free == NULL |
137 | || keymgmt->new == NULL | |
138 | || keymgmt->has == NULL | |
4fe54d67 NT |
139 | || (getparamfncnt != 0 && getparamfncnt != 2) |
140 | || (setparamfncnt != 0 && setparamfncnt != 2) | |
273a67e3 RL |
141 | || (importfncnt != 0 && importfncnt != 2) |
142 | || (exportfncnt != 0 && exportfncnt != 2)) { | |
a94a3e0d RL |
143 | EVP_KEYMGMT_free(keymgmt); |
144 | EVPerr(0, EVP_R_INVALID_PROVIDER_FUNCTIONS); | |
145 | return NULL; | |
146 | } | |
147 | keymgmt->prov = prov; | |
148 | if (prov != NULL) | |
149 | ossl_provider_up_ref(prov); | |
150 | ||
151 | return keymgmt; | |
152 | } | |
153 | ||
f7c16d48 RL |
154 | EVP_KEYMGMT *evp_keymgmt_fetch_by_number(OPENSSL_CTX *ctx, int name_id, |
155 | const char *properties) | |
156 | { | |
157 | return evp_generic_fetch_by_number(ctx, | |
158 | OSSL_OP_KEYMGMT, name_id, properties, | |
0ddf74bf | 159 | keymgmt_from_dispatch, |
f7c16d48 RL |
160 | (int (*)(void *))EVP_KEYMGMT_up_ref, |
161 | (void (*)(void *))EVP_KEYMGMT_free); | |
162 | } | |
163 | ||
a94a3e0d RL |
164 | EVP_KEYMGMT *EVP_KEYMGMT_fetch(OPENSSL_CTX *ctx, const char *algorithm, |
165 | const char *properties) | |
166 | { | |
f7c16d48 | 167 | return evp_generic_fetch(ctx, OSSL_OP_KEYMGMT, algorithm, properties, |
0ddf74bf | 168 | keymgmt_from_dispatch, |
f7c16d48 RL |
169 | (int (*)(void *))EVP_KEYMGMT_up_ref, |
170 | (void (*)(void *))EVP_KEYMGMT_free); | |
a94a3e0d RL |
171 | } |
172 | ||
173 | int EVP_KEYMGMT_up_ref(EVP_KEYMGMT *keymgmt) | |
174 | { | |
175 | int ref = 0; | |
176 | ||
177 | CRYPTO_UP_REF(&keymgmt->refcnt, &ref, keymgmt->lock); | |
178 | return 1; | |
179 | } | |
180 | ||
181 | void EVP_KEYMGMT_free(EVP_KEYMGMT *keymgmt) | |
182 | { | |
183 | int ref = 0; | |
184 | ||
185 | if (keymgmt == NULL) | |
186 | return; | |
187 | ||
188 | CRYPTO_DOWN_REF(&keymgmt->refcnt, &ref, keymgmt->lock); | |
189 | if (ref > 0) | |
190 | return; | |
191 | ossl_provider_free(keymgmt->prov); | |
192 | CRYPTO_THREAD_lock_free(keymgmt->lock); | |
193 | OPENSSL_free(keymgmt); | |
194 | } | |
195 | ||
196 | const OSSL_PROVIDER *EVP_KEYMGMT_provider(const EVP_KEYMGMT *keymgmt) | |
197 | { | |
198 | return keymgmt->prov; | |
199 | } | |
200 | ||
506cb0f6 RL |
201 | int EVP_KEYMGMT_number(const EVP_KEYMGMT *keymgmt) |
202 | { | |
203 | return keymgmt->name_id; | |
204 | } | |
205 | ||
251e610c RL |
206 | int EVP_KEYMGMT_is_a(const EVP_KEYMGMT *keymgmt, const char *name) |
207 | { | |
e4a1d023 | 208 | return evp_is_a(keymgmt->prov, keymgmt->name_id, NULL, name); |
251e610c RL |
209 | } |
210 | ||
211 | void EVP_KEYMGMT_do_all_provided(OPENSSL_CTX *libctx, | |
212 | void (*fn)(EVP_KEYMGMT *keymgmt, void *arg), | |
213 | void *arg) | |
214 | { | |
215 | evp_generic_do_all(libctx, OSSL_OP_KEYMGMT, | |
216 | (void (*)(void *, void *))fn, arg, | |
0ddf74bf | 217 | keymgmt_from_dispatch, |
251e610c RL |
218 | (void (*)(void *))EVP_KEYMGMT_free); |
219 | } | |
f651c727 RL |
220 | |
221 | void EVP_KEYMGMT_names_do_all(const EVP_KEYMGMT *keymgmt, | |
222 | void (*fn)(const char *name, void *data), | |
223 | void *data) | |
224 | { | |
225 | if (keymgmt->prov != NULL) | |
226 | evp_names_do_all(keymgmt->prov, keymgmt->name_id, fn, data); | |
227 | } | |
68552cde RL |
228 | |
229 | /* | |
230 | * Internal API that interfaces with the method function pointers | |
231 | */ | |
b305452f | 232 | void *evp_keymgmt_newdata(const EVP_KEYMGMT *keymgmt) |
68552cde RL |
233 | { |
234 | void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt)); | |
235 | ||
b305452f RL |
236 | /* |
237 | * TODO(3.0) 'new' is currently mandatory on its own, but when new | |
238 | * constructors appear, it won't be quite as mandatory, so we have | |
239 | * a check for future cases. | |
240 | */ | |
241 | if (keymgmt->new == NULL) | |
242 | return NULL; | |
243 | return keymgmt->new(provctx); | |
68552cde RL |
244 | } |
245 | ||
b305452f | 246 | void evp_keymgmt_freedata(const EVP_KEYMGMT *keymgmt, void *keydata) |
68552cde | 247 | { |
b305452f RL |
248 | /* This is mandatory, no need to check for its presence */ |
249 | keymgmt->free(keydata); | |
68552cde RL |
250 | } |
251 | ||
b305452f RL |
252 | int evp_keymgmt_get_params(const EVP_KEYMGMT *keymgmt, void *keydata, |
253 | OSSL_PARAM params[]) | |
68552cde | 254 | { |
b305452f | 255 | if (keymgmt->get_params == NULL) |
68552cde | 256 | return 1; |
b305452f | 257 | return keymgmt->get_params(keydata, params); |
68552cde RL |
258 | } |
259 | ||
b305452f | 260 | const OSSL_PARAM *evp_keymgmt_gettable_params(const EVP_KEYMGMT *keymgmt) |
68552cde | 261 | { |
b305452f | 262 | if (keymgmt->gettable_params == NULL) |
68552cde | 263 | return NULL; |
b305452f | 264 | return keymgmt->gettable_params(); |
68552cde RL |
265 | } |
266 | ||
4fe54d67 NT |
267 | int evp_keymgmt_set_params(const EVP_KEYMGMT *keymgmt, void *keydata, |
268 | const OSSL_PARAM params[]) | |
269 | { | |
270 | if (keymgmt->set_params == NULL) | |
271 | return 1; | |
272 | return keymgmt->set_params(keydata, params); | |
273 | } | |
274 | ||
275 | const OSSL_PARAM *evp_keymgmt_settable_params(const EVP_KEYMGMT *keymgmt) | |
276 | { | |
277 | if (keymgmt->settable_params == NULL) | |
278 | return NULL; | |
279 | return keymgmt->settable_params(); | |
280 | } | |
281 | ||
b305452f | 282 | int evp_keymgmt_has(const EVP_KEYMGMT *keymgmt, void *keydata, int selection) |
68552cde | 283 | { |
b305452f RL |
284 | /* This is mandatory, no need to check for its presence */ |
285 | return keymgmt->has(keydata, selection); | |
68552cde RL |
286 | } |
287 | ||
b305452f RL |
288 | int evp_keymgmt_validate(const EVP_KEYMGMT *keymgmt, void *keydata, |
289 | int selection) | |
68552cde | 290 | { |
b305452f RL |
291 | /* We assume valid if the implementation doesn't have a function */ |
292 | if (keymgmt->validate == NULL) | |
68552cde | 293 | return 1; |
b305452f | 294 | return keymgmt->validate(keydata, selection); |
68552cde RL |
295 | } |
296 | ||
bee5d6cd RL |
297 | int evp_keymgmt_match(const EVP_KEYMGMT *keymgmt, |
298 | const void *keydata1, const void *keydata2, | |
299 | int selection) | |
300 | { | |
301 | /* We assume no match if the implementation doesn't have a function */ | |
302 | if (keymgmt->match == NULL) | |
303 | return 0; | |
304 | return keymgmt->match(keydata1, keydata2, selection); | |
305 | } | |
306 | ||
b305452f RL |
307 | int evp_keymgmt_import(const EVP_KEYMGMT *keymgmt, void *keydata, |
308 | int selection, const OSSL_PARAM params[]) | |
68552cde | 309 | { |
b305452f RL |
310 | if (keymgmt->import == NULL) |
311 | return 0; | |
312 | return keymgmt->import(keydata, selection, params); | |
68552cde RL |
313 | } |
314 | ||
b305452f RL |
315 | const OSSL_PARAM *evp_keymgmt_import_types(const EVP_KEYMGMT *keymgmt, |
316 | int selection) | |
68552cde | 317 | { |
b305452f RL |
318 | if (keymgmt->import_types == NULL) |
319 | return NULL; | |
320 | return keymgmt->import_types(selection); | |
68552cde RL |
321 | } |
322 | ||
b305452f RL |
323 | int evp_keymgmt_export(const EVP_KEYMGMT *keymgmt, void *keydata, |
324 | int selection, OSSL_CALLBACK *param_cb, void *cbarg) | |
68552cde | 325 | { |
b305452f RL |
326 | if (keymgmt->export == NULL) |
327 | return 0; | |
328 | return keymgmt->export(keydata, selection, param_cb, cbarg); | |
68552cde RL |
329 | } |
330 | ||
b305452f RL |
331 | const OSSL_PARAM *evp_keymgmt_export_types(const EVP_KEYMGMT *keymgmt, |
332 | int selection) | |
68552cde | 333 | { |
b305452f RL |
334 | if (keymgmt->export_types == NULL) |
335 | return NULL; | |
336 | return keymgmt->export_types(selection); | |
68552cde | 337 | } |
13697f1c RL |
338 | |
339 | int evp_keymgmt_copy(const EVP_KEYMGMT *keymgmt, | |
340 | void *keydata_to, const void *keydata_from, | |
341 | int selection) | |
342 | { | |
343 | /* We assume no copy if the implementation doesn't have a function */ | |
344 | if (keymgmt->copy == NULL) | |
345 | return 0; | |
346 | return keymgmt->copy(keydata_to, keydata_from, selection); | |
347 | } |