]>
Commit | Line | Data |
---|---|---|
70a1f7b4 | 1 | /* |
da1c088f | 2 | * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. |
70a1f7b4 RL |
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 | ||
6508e858 | 10 | #include <openssl/core_names.h> |
70a1f7b4 RL |
11 | #include "internal/cryptlib.h" |
12 | #include "internal/nelem.h" | |
25f2138b | 13 | #include "crypto/evp.h" |
1640d48c | 14 | #include "internal/core.h" |
70a1f7b4 | 15 | #include "internal/provider.h" |
706457b7 | 16 | #include "evp_local.h" |
70a1f7b4 | 17 | |
3f7ce7f1 RL |
18 | /* |
19 | * match_type() checks if two EVP_KEYMGMT are matching key types. This | |
20 | * function assumes that the caller has made all the necessary NULL checks. | |
21 | */ | |
22 | static int match_type(const EVP_KEYMGMT *keymgmt1, const EVP_KEYMGMT *keymgmt2) | |
23 | { | |
ed576acd | 24 | const char *name2 = EVP_KEYMGMT_get0_name(keymgmt2); |
3f7ce7f1 RL |
25 | |
26 | return EVP_KEYMGMT_is_a(keymgmt1, name2); | |
27 | } | |
28 | ||
af836c22 | 29 | int evp_keymgmt_util_try_import(const OSSL_PARAM params[], void *arg) |
651101e1 | 30 | { |
af836c22 | 31 | struct evp_keymgmt_util_try_import_data_st *data = arg; |
e36a4dc4 | 32 | int delete_on_error = 0; |
70a1f7b4 | 33 | |
11391da2 | 34 | /* Just in time creation of keydata */ |
e36a4dc4 RL |
35 | if (data->keydata == NULL) { |
36 | if ((data->keydata = evp_keymgmt_newdata(data->keymgmt)) == NULL) { | |
e077455e | 37 | ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); |
e36a4dc4 RL |
38 | return 0; |
39 | } | |
40 | delete_on_error = 1; | |
11391da2 MC |
41 | } |
42 | ||
adc9f731 RL |
43 | /* |
44 | * It's fine if there was no data to transfer, we just end up with an | |
45 | * empty destination key. | |
46 | */ | |
47 | if (params[0].key == NULL) | |
48 | return 1; | |
49 | ||
e36a4dc4 RL |
50 | if (evp_keymgmt_import(data->keymgmt, data->keydata, data->selection, |
51 | params)) | |
52 | return 1; | |
53 | if (delete_on_error) { | |
54 | evp_keymgmt_freedata(data->keymgmt, data->keydata); | |
55 | data->keydata = NULL; | |
56 | } | |
57 | return 0; | |
70a1f7b4 RL |
58 | } |
59 | ||
af836c22 RL |
60 | int evp_keymgmt_util_assign_pkey(EVP_PKEY *pkey, EVP_KEYMGMT *keymgmt, |
61 | void *keydata) | |
62 | { | |
63 | if (pkey == NULL || keymgmt == NULL || keydata == NULL | |
64 | || !EVP_PKEY_set_type_by_keymgmt(pkey, keymgmt)) { | |
65 | ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); | |
66 | return 0; | |
67 | } | |
68 | pkey->keydata = keydata; | |
69 | evp_keymgmt_util_cache_keyinfo(pkey); | |
70 | return 1; | |
71 | } | |
72 | ||
73 | EVP_PKEY *evp_keymgmt_util_make_pkey(EVP_KEYMGMT *keymgmt, void *keydata) | |
74 | { | |
75 | EVP_PKEY *pkey = NULL; | |
76 | ||
77 | if (keymgmt == NULL | |
78 | || keydata == NULL | |
79 | || (pkey = EVP_PKEY_new()) == NULL | |
80 | || !evp_keymgmt_util_assign_pkey(pkey, keymgmt, keydata)) { | |
81 | EVP_PKEY_free(pkey); | |
82 | return NULL; | |
83 | } | |
84 | return pkey; | |
85 | } | |
86 | ||
655f73ce RL |
87 | int evp_keymgmt_util_export(const EVP_PKEY *pk, int selection, |
88 | OSSL_CALLBACK *export_cb, void *export_cbarg) | |
89 | { | |
a732a4c3 SL |
90 | if (pk == NULL || export_cb == NULL) |
91 | return 0; | |
655f73ce RL |
92 | return evp_keymgmt_export(pk->keymgmt, pk->keydata, selection, |
93 | export_cb, export_cbarg); | |
94 | } | |
95 | ||
98642df4 SS |
96 | void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt, |
97 | int selection) | |
70a1f7b4 | 98 | { |
af836c22 | 99 | struct evp_keymgmt_util_try_import_data_st import_data; |
64954e2f | 100 | OP_CACHE_ELEM *op; |
70a1f7b4 | 101 | |
3f7ce7f1 RL |
102 | /* Export to where? */ |
103 | if (keymgmt == NULL) | |
104 | return NULL; | |
70a1f7b4 | 105 | |
3f7ce7f1 | 106 | /* If we have an unassigned key, give up */ |
adc9f731 | 107 | if (pk->keydata == NULL) |
3f7ce7f1 | 108 | return NULL; |
70a1f7b4 | 109 | |
1af9b646 P |
110 | /* |
111 | * If |keymgmt| matches the "origin" |keymgmt|, there is no more to do. | |
112 | * The "origin" is determined by the |keymgmt| pointers being identical | |
113 | * or when the provider and the name ID match. The latter case handles the | |
114 | * situation where the fetch cache is flushed and a "new" key manager is | |
115 | * created. | |
116 | */ | |
117 | if (pk->keymgmt == keymgmt | |
118 | || (pk->keymgmt->name_id == keymgmt->name_id | |
119 | && pk->keymgmt->prov == keymgmt->prov)) | |
3c6ed955 RL |
120 | return pk->keydata; |
121 | ||
cd3f8c1b RS |
122 | if (!CRYPTO_THREAD_read_lock(pk->lock)) |
123 | return NULL; | |
f4a3799c RL |
124 | /* |
125 | * If the provider native "origin" hasn't changed since last time, we | |
64954e2f P |
126 | * try to find our keymgmt in the operation cache. If it has changed |
127 | * and our keymgmt isn't found, we will clear the cache further down. | |
f4a3799c RL |
128 | */ |
129 | if (pk->dirty_cnt == pk->dirty_cnt_copy) { | |
130 | /* If this key is already exported to |keymgmt|, no more to do */ | |
98642df4 | 131 | op = evp_keymgmt_util_find_operation_cache(pk, keymgmt, selection); |
64954e2f P |
132 | if (op != NULL && op->keymgmt != NULL) { |
133 | void *ret = op->keydata; | |
f4a3799c RL |
134 | |
135 | CRYPTO_THREAD_unlock(pk->lock); | |
136 | return ret; | |
137 | } | |
0b07db6f MC |
138 | } |
139 | CRYPTO_THREAD_unlock(pk->lock); | |
3c6ed955 RL |
140 | |
141 | /* If the "origin" |keymgmt| doesn't support exporting, give up */ | |
3c6ed955 RL |
142 | if (pk->keymgmt->export == NULL) |
143 | return NULL; | |
3f7ce7f1 | 144 | |
3f7ce7f1 RL |
145 | /* |
146 | * Make sure that the type of the keymgmt to export to matches the type | |
3c6ed955 | 147 | * of the "origin" |
3f7ce7f1 | 148 | */ |
3c6ed955 | 149 | if (!ossl_assert(match_type(pk->keymgmt, keymgmt))) |
3f7ce7f1 | 150 | return NULL; |
70a1f7b4 | 151 | |
3f7ce7f1 RL |
152 | /* |
153 | * We look at the already cached provider keys, and import from the | |
154 | * first that supports it (i.e. use its export function), and export | |
155 | * the imported data to the new provider. | |
156 | */ | |
157 | ||
158 | /* Setup for the export callback */ | |
af836c22 | 159 | import_data.keydata = NULL; /* evp_keymgmt_util_try_import will create it */ |
3f7ce7f1 | 160 | import_data.keymgmt = keymgmt; |
98642df4 | 161 | import_data.selection = selection; |
3f7ce7f1 | 162 | |
3c6ed955 | 163 | /* |
af836c22 RL |
164 | * The export function calls the callback (evp_keymgmt_util_try_import), |
165 | * which does the import for us. If successful, we're done. | |
3c6ed955 | 166 | */ |
98642df4 | 167 | if (!evp_keymgmt_util_export(pk, selection, |
e36a4dc4 | 168 | &evp_keymgmt_util_try_import, &import_data)) |
3f7ce7f1 | 169 | /* If there was an error, bail out */ |
3f7ce7f1 | 170 | return NULL; |
70a1f7b4 | 171 | |
cd3f8c1b RS |
172 | if (!CRYPTO_THREAD_write_lock(pk->lock)) { |
173 | evp_keymgmt_freedata(keymgmt, import_data.keydata); | |
174 | return NULL; | |
175 | } | |
0b07db6f | 176 | /* Check to make sure some other thread didn't get there first */ |
98642df4 | 177 | op = evp_keymgmt_util_find_operation_cache(pk, keymgmt, selection); |
64954e2f P |
178 | if (op != NULL && op->keydata != NULL) { |
179 | void *ret = op->keydata; | |
0b07db6f MC |
180 | |
181 | CRYPTO_THREAD_unlock(pk->lock); | |
182 | ||
183 | /* | |
184 | * Another thread seemms to have already exported this so we abandon | |
185 | * all the work we just did. | |
186 | */ | |
187 | evp_keymgmt_freedata(keymgmt, import_data.keydata); | |
188 | ||
189 | return ret; | |
190 | } | |
191 | ||
f4a3799c RL |
192 | /* |
193 | * If the dirty counter changed since last time, then clear the | |
194 | * operation cache. In that case, we know that |i| is zero. | |
195 | */ | |
196 | if (pk->dirty_cnt != pk->dirty_cnt_copy) | |
36424806 | 197 | evp_keymgmt_util_clear_operation_cache(pk); |
f4a3799c | 198 | |
3c6ed955 | 199 | /* Add the new export to the operation cache */ |
98642df4 SS |
200 | if (!evp_keymgmt_util_cache_keydata(pk, keymgmt, import_data.keydata, |
201 | selection)) { | |
fb0f65ff | 202 | CRYPTO_THREAD_unlock(pk->lock); |
adc9f731 | 203 | evp_keymgmt_freedata(keymgmt, import_data.keydata); |
d5e66eab | 204 | return NULL; |
3c6ed955 | 205 | } |
02f060d1 | 206 | |
f4a3799c RL |
207 | /* Synchronize the dirty count */ |
208 | pk->dirty_cnt_copy = pk->dirty_cnt; | |
209 | ||
0b07db6f MC |
210 | CRYPTO_THREAD_unlock(pk->lock); |
211 | ||
adc9f731 | 212 | return import_data.keydata; |
70a1f7b4 | 213 | } |
4cae07fe | 214 | |
64954e2f | 215 | static void op_cache_free(OP_CACHE_ELEM *e) |
4cae07fe | 216 | { |
64954e2f P |
217 | evp_keymgmt_freedata(e->keymgmt, e->keydata); |
218 | EVP_KEYMGMT_free(e->keymgmt); | |
219 | OPENSSL_free(e); | |
220 | } | |
4cae07fe | 221 | |
36424806 | 222 | int evp_keymgmt_util_clear_operation_cache(EVP_PKEY *pk) |
64954e2f | 223 | { |
4cae07fe | 224 | if (pk != NULL) { |
64954e2f P |
225 | sk_OP_CACHE_ELEM_pop_free(pk->operation_cache, op_cache_free); |
226 | pk->operation_cache = NULL; | |
6508e858 | 227 | } |
0b07db6f MC |
228 | |
229 | return 1; | |
6508e858 RL |
230 | } |
231 | ||
64954e2f | 232 | OP_CACHE_ELEM *evp_keymgmt_util_find_operation_cache(EVP_PKEY *pk, |
98642df4 SS |
233 | EVP_KEYMGMT *keymgmt, |
234 | int selection) | |
3f7ce7f1 | 235 | { |
64954e2f P |
236 | int i, end = sk_OP_CACHE_ELEM_num(pk->operation_cache); |
237 | OP_CACHE_ELEM *p; | |
3f7ce7f1 | 238 | |
64954e2f P |
239 | /* |
240 | * A comparison and sk_P_CACHE_ELEM_find() are avoided to not cause | |
241 | * problems when we've only a read lock. | |
dc9bc6c8 MC |
242 | * A keymgmt is a match if the |keymgmt| pointers are identical or if the |
243 | * provider and the name ID match | |
64954e2f P |
244 | */ |
245 | for (i = 0; i < end; i++) { | |
246 | p = sk_OP_CACHE_ELEM_value(pk->operation_cache, i); | |
dc9bc6c8 MC |
247 | if ((p->selection & selection) == selection |
248 | && (keymgmt == p->keymgmt | |
249 | || (keymgmt->name_id == p->keymgmt->name_id | |
250 | && keymgmt->prov == p->keymgmt->prov))) | |
64954e2f | 251 | return p; |
3f7ce7f1 | 252 | } |
64954e2f | 253 | return NULL; |
3f7ce7f1 RL |
254 | } |
255 | ||
98642df4 SS |
256 | int evp_keymgmt_util_cache_keydata(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt, |
257 | void *keydata, int selection) | |
6508e858 | 258 | { |
64954e2f P |
259 | OP_CACHE_ELEM *p = NULL; |
260 | ||
b305452f | 261 | if (keydata != NULL) { |
64954e2f P |
262 | if (pk->operation_cache == NULL) { |
263 | pk->operation_cache = sk_OP_CACHE_ELEM_new_null(); | |
264 | if (pk->operation_cache == NULL) | |
265 | return 0; | |
266 | } | |
267 | ||
268 | p = OPENSSL_malloc(sizeof(*p)); | |
269 | if (p == NULL) | |
3c6ed955 | 270 | return 0; |
64954e2f P |
271 | p->keydata = keydata; |
272 | p->keymgmt = keymgmt; | |
98642df4 | 273 | p->selection = selection; |
0b07db6f | 274 | |
64954e2f P |
275 | if (!EVP_KEYMGMT_up_ref(keymgmt)) { |
276 | OPENSSL_free(p); | |
277 | return 0; | |
278 | } | |
279 | ||
280 | if (!sk_OP_CACHE_ELEM_push(pk->operation_cache, p)) { | |
281 | EVP_KEYMGMT_free(keymgmt); | |
282 | OPENSSL_free(p); | |
283 | return 0; | |
284 | } | |
3c6ed955 RL |
285 | } |
286 | return 1; | |
287 | } | |
288 | ||
289 | void evp_keymgmt_util_cache_keyinfo(EVP_PKEY *pk) | |
290 | { | |
291 | /* | |
292 | * Cache information about the provider "origin" key. | |
293 | * | |
ed576acd | 294 | * This services functions like EVP_PKEY_get_size, EVP_PKEY_get_bits, etc |
3c6ed955 | 295 | */ |
adc9f731 | 296 | if (pk->keydata != NULL) { |
3c6ed955 RL |
297 | int bits = 0; |
298 | int security_bits = 0; | |
299 | int size = 0; | |
300 | OSSL_PARAM params[4]; | |
301 | ||
302 | params[0] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_BITS, &bits); | |
303 | params[1] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_SECURITY_BITS, | |
304 | &security_bits); | |
305 | params[2] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_MAX_SIZE, &size); | |
306 | params[3] = OSSL_PARAM_construct_end(); | |
307 | if (evp_keymgmt_get_params(pk->keymgmt, pk->keydata, params)) { | |
308 | pk->cache.size = size; | |
309 | pk->cache.bits = bits; | |
310 | pk->cache.security_bits = security_bits; | |
6508e858 | 311 | } |
4cae07fe RL |
312 | } |
313 | } | |
fa9faf01 | 314 | |
68552cde | 315 | void *evp_keymgmt_util_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt, |
b305452f | 316 | int selection, const OSSL_PARAM params[]) |
46e2dd05 | 317 | { |
8243d8d1 | 318 | void *keydata = NULL; |
46e2dd05 | 319 | |
8243d8d1 RL |
320 | if ((keydata = evp_keymgmt_newdata(keymgmt)) == NULL |
321 | || !evp_keymgmt_import(keymgmt, keydata, selection, params) | |
af836c22 | 322 | || !evp_keymgmt_util_assign_pkey(target, keymgmt, keydata)) { |
8243d8d1 RL |
323 | evp_keymgmt_freedata(keymgmt, keydata); |
324 | keydata = NULL; | |
325 | } | |
b305452f | 326 | return keydata; |
46e2dd05 | 327 | } |
157ded39 RL |
328 | |
329 | int evp_keymgmt_util_has(EVP_PKEY *pk, int selection) | |
330 | { | |
331 | /* Check if key is even assigned */ | |
332 | if (pk->keymgmt == NULL) | |
333 | return 0; | |
334 | ||
335 | return evp_keymgmt_has(pk->keymgmt, pk->keydata, selection); | |
336 | } | |
1e9101c4 RL |
337 | |
338 | /* | |
339 | * evp_keymgmt_util_match() doesn't just look at the provider side "origin", | |
340 | * but also in the operation cache to see if there's any common keymgmt that | |
341 | * supplies OP_keymgmt_match. | |
342 | * | |
c74aaa39 DDO |
343 | * evp_keymgmt_util_match() adheres to the return values that EVP_PKEY_eq() |
344 | * and EVP_PKEY_parameters_eq() return, i.e.: | |
1e9101c4 RL |
345 | * |
346 | * 1 same key | |
347 | * 0 not same key | |
348 | * -1 not same key type | |
349 | * -2 unsupported operation | |
350 | */ | |
351 | int evp_keymgmt_util_match(EVP_PKEY *pk1, EVP_PKEY *pk2, int selection) | |
352 | { | |
353 | EVP_KEYMGMT *keymgmt1 = NULL, *keymgmt2 = NULL; | |
354 | void *keydata1 = NULL, *keydata2 = NULL; | |
355 | ||
356 | if (pk1 == NULL || pk2 == NULL) { | |
357 | if (pk1 == NULL && pk2 == NULL) | |
358 | return 1; | |
359 | return 0; | |
360 | } | |
361 | ||
362 | keymgmt1 = pk1->keymgmt; | |
363 | keydata1 = pk1->keydata; | |
364 | keymgmt2 = pk2->keymgmt; | |
365 | keydata2 = pk2->keydata; | |
366 | ||
367 | if (keymgmt1 != keymgmt2) { | |
adc9f731 RL |
368 | /* |
369 | * The condition for a successful cross export is that the | |
370 | * keydata to be exported is NULL (typed, but otherwise empty | |
371 | * EVP_PKEY), or that it was possible to export it with | |
372 | * evp_keymgmt_util_export_to_provider(). | |
373 | * | |
374 | * We use |ok| to determine if it's ok to cross export one way, | |
375 | * but also to determine if we should attempt a cross export | |
376 | * the other way. There's no point doing it both ways. | |
377 | */ | |
37b85073 | 378 | int ok = 0; |
1e9101c4 RL |
379 | |
380 | /* Complex case, where the keymgmt differ */ | |
381 | if (keymgmt1 != NULL | |
382 | && keymgmt2 != NULL | |
383 | && !match_type(keymgmt1, keymgmt2)) { | |
384 | ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES); | |
385 | return -1; /* Not the same type */ | |
386 | } | |
387 | ||
388 | /* | |
389 | * The key types are determined to match, so we try cross export, | |
390 | * but only to keymgmt's that supply a matching function. | |
391 | */ | |
392 | if (keymgmt2 != NULL | |
393 | && keymgmt2->match != NULL) { | |
adc9f731 RL |
394 | void *tmp_keydata = NULL; |
395 | ||
396 | ok = 1; | |
397 | if (keydata1 != NULL) { | |
398 | tmp_keydata = | |
98642df4 SS |
399 | evp_keymgmt_util_export_to_provider(pk1, keymgmt2, |
400 | selection); | |
adc9f731 RL |
401 | ok = (tmp_keydata != NULL); |
402 | } | |
403 | if (ok) { | |
1e9101c4 RL |
404 | keymgmt1 = keymgmt2; |
405 | keydata1 = tmp_keydata; | |
406 | } | |
407 | } | |
adc9f731 | 408 | /* |
8243d8d1 | 409 | * If we've successfully cross exported one way, there's no point |
adc9f731 RL |
410 | * doing it the other way, hence the |!ok| check. |
411 | */ | |
412 | if (!ok | |
1e9101c4 RL |
413 | && keymgmt1 != NULL |
414 | && keymgmt1->match != NULL) { | |
adc9f731 RL |
415 | void *tmp_keydata = NULL; |
416 | ||
417 | ok = 1; | |
418 | if (keydata2 != NULL) { | |
419 | tmp_keydata = | |
98642df4 SS |
420 | evp_keymgmt_util_export_to_provider(pk2, keymgmt1, |
421 | selection); | |
adc9f731 RL |
422 | ok = (tmp_keydata != NULL); |
423 | } | |
424 | if (ok) { | |
1e9101c4 RL |
425 | keymgmt2 = keymgmt1; |
426 | keydata2 = tmp_keydata; | |
427 | } | |
428 | } | |
429 | } | |
430 | ||
431 | /* If we still don't have matching keymgmt implementations, we give up */ | |
432 | if (keymgmt1 != keymgmt2) | |
433 | return -2; | |
434 | ||
adc9f731 RL |
435 | /* If both keydata are NULL, then they're the same key */ |
436 | if (keydata1 == NULL && keydata2 == NULL) | |
437 | return 1; | |
438 | /* If only one of the keydata is NULL, then they're different keys */ | |
439 | if (keydata1 == NULL || keydata2 == NULL) | |
440 | return 0; | |
441 | /* If both keydata are non-NULL, we let the backend decide */ | |
1e9101c4 RL |
442 | return evp_keymgmt_match(keymgmt1, keydata1, keydata2, selection); |
443 | } | |
ff3b59e1 RL |
444 | |
445 | int evp_keymgmt_util_copy(EVP_PKEY *to, EVP_PKEY *from, int selection) | |
446 | { | |
447 | /* Save copies of pointers we want to play with without affecting |to| */ | |
448 | EVP_KEYMGMT *to_keymgmt = to->keymgmt; | |
449 | void *to_keydata = to->keydata, *alloc_keydata = NULL; | |
450 | ||
451 | /* An unassigned key can't be copied */ | |
adc9f731 | 452 | if (from == NULL || from->keydata == NULL) |
ff3b59e1 RL |
453 | return 0; |
454 | ||
036ee370 RL |
455 | /* |
456 | * If |to| is unassigned, ensure it gets the same KEYMGMT as |from|, | |
457 | * Note that the final setting of KEYMGMT is done further down, with | |
458 | * EVP_PKEY_set_type_by_keymgmt(); we don't want to do that prematurely. | |
459 | */ | |
460 | if (to_keymgmt == NULL) | |
461 | to_keymgmt = from->keymgmt; | |
462 | ||
85fcc3fb TM |
463 | if (to_keymgmt == from->keymgmt && to_keymgmt->dup != NULL |
464 | && to_keydata == NULL) { | |
b4f447c0 TM |
465 | to_keydata = alloc_keydata = evp_keymgmt_dup(to_keymgmt, |
466 | from->keydata, | |
467 | selection); | |
4a9fe33c TM |
468 | if (to_keydata == NULL) |
469 | return 0; | |
ff3b59e1 | 470 | } else if (match_type(to_keymgmt, from->keymgmt)) { |
af836c22 | 471 | struct evp_keymgmt_util_try_import_data_st import_data; |
ff3b59e1 RL |
472 | |
473 | import_data.keymgmt = to_keymgmt; | |
474 | import_data.keydata = to_keydata; | |
475 | import_data.selection = selection; | |
476 | ||
655f73ce RL |
477 | if (!evp_keymgmt_util_export(from, selection, |
478 | &evp_keymgmt_util_try_import, | |
e08993ea | 479 | &import_data)) |
ff3b59e1 | 480 | return 0; |
adc9f731 RL |
481 | |
482 | /* | |
af836c22 RL |
483 | * In case to_keydata was previously unallocated, |
484 | * evp_keymgmt_util_try_import() may have created it for us. | |
adc9f731 | 485 | */ |
036ee370 RL |
486 | if (to_keydata == NULL) |
487 | to_keydata = alloc_keydata = import_data.keydata; | |
ff3b59e1 RL |
488 | } else { |
489 | ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES); | |
490 | return 0; | |
491 | } | |
492 | ||
af836c22 RL |
493 | /* |
494 | * We only need to set the |to| type when its |keymgmt| isn't set. | |
495 | * We can then just set its |keydata| to what we have, which might | |
496 | * be exactly what it had when entering this function. | |
497 | * This is a bit different from using evp_keymgmt_util_assign_pkey(), | |
498 | * which isn't as careful with |to|'s original |keymgmt|, since it's | |
499 | * meant to forcibly reassign an EVP_PKEY no matter what, which is | |
500 | * why we don't use that one here. | |
501 | */ | |
ff3b59e1 | 502 | if (to->keymgmt == NULL |
8243d8d1 | 503 | && !EVP_PKEY_set_type_by_keymgmt(to, to_keymgmt)) { |
ff3b59e1 RL |
504 | evp_keymgmt_freedata(to_keymgmt, alloc_keydata); |
505 | return 0; | |
506 | } | |
ff3b59e1 RL |
507 | to->keydata = to_keydata; |
508 | evp_keymgmt_util_cache_keyinfo(to); | |
509 | ||
510 | return 1; | |
511 | } | |
62924755 RL |
512 | |
513 | void *evp_keymgmt_util_gen(EVP_PKEY *target, EVP_KEYMGMT *keymgmt, | |
514 | void *genctx, OSSL_CALLBACK *cb, void *cbarg) | |
515 | { | |
8243d8d1 | 516 | void *keydata = NULL; |
62924755 | 517 | |
8243d8d1 | 518 | if ((keydata = evp_keymgmt_gen(keymgmt, genctx, cb, cbarg)) == NULL |
af836c22 | 519 | || !evp_keymgmt_util_assign_pkey(target, keymgmt, keydata)) { |
8243d8d1 RL |
520 | evp_keymgmt_freedata(keymgmt, keydata); |
521 | keydata = NULL; | |
522 | } | |
62924755 RL |
523 | |
524 | return keydata; | |
525 | } | |
3b924da0 RL |
526 | |
527 | /* | |
528 | * Returns the same numbers as EVP_PKEY_get_default_digest_name() | |
529 | * When the string from the EVP_KEYMGMT implementation is "", we use | |
530 | * SN_undef, since that corresponds to what EVP_PKEY_get_default_nid() | |
531 | * returns for no digest. | |
532 | */ | |
533 | int evp_keymgmt_util_get_deflt_digest_name(EVP_KEYMGMT *keymgmt, | |
534 | void *keydata, | |
535 | char *mdname, size_t mdname_sz) | |
536 | { | |
537 | OSSL_PARAM params[3]; | |
538 | char mddefault[100] = ""; | |
539 | char mdmandatory[100] = ""; | |
540 | char *result = NULL; | |
541 | int rv = -2; | |
542 | ||
543 | params[0] = | |
544 | OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, | |
545 | mddefault, sizeof(mddefault)); | |
3b924da0 RL |
546 | params[1] = |
547 | OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, | |
548 | mdmandatory, | |
549 | sizeof(mdmandatory)); | |
3b924da0 RL |
550 | params[2] = OSSL_PARAM_construct_end(); |
551 | ||
552 | if (!evp_keymgmt_get_params(keymgmt, keydata, params)) | |
553 | return 0; | |
554 | ||
54b47afe P |
555 | if (OSSL_PARAM_modified(params + 1)) { |
556 | if (params[1].return_size <= 1) /* Only a NUL byte */ | |
3b924da0 RL |
557 | result = SN_undef; |
558 | else | |
559 | result = mdmandatory; | |
560 | rv = 2; | |
54b47afe P |
561 | } else if (OSSL_PARAM_modified(params)) { |
562 | if (params[0].return_size <= 1) /* Only a NUL byte */ | |
3b924da0 RL |
563 | result = SN_undef; |
564 | else | |
565 | result = mddefault; | |
566 | rv = 1; | |
567 | } | |
568 | if (rv > 0) | |
569 | OPENSSL_strlcpy(mdname, result, mdname_sz); | |
570 | return rv; | |
571 | } | |
5246183e RL |
572 | |
573 | /* | |
574 | * If |keymgmt| has the method function |query_operation_name|, use it to get | |
575 | * the name of a supported operation identity. Otherwise, return the keytype, | |
576 | * assuming that it works as a default operation name. | |
577 | */ | |
578 | const char *evp_keymgmt_util_query_operation_name(EVP_KEYMGMT *keymgmt, | |
579 | int op_id) | |
580 | { | |
581 | const char *name = NULL; | |
582 | ||
583 | if (keymgmt != NULL) { | |
584 | if (keymgmt->query_operation_name != NULL) | |
585 | name = keymgmt->query_operation_name(op_id); | |
586 | if (name == NULL) | |
587 | name = EVP_KEYMGMT_get0_name(keymgmt); | |
588 | } | |
589 | return name; | |
590 | } |