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