2 * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
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
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"
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.
22 static int match_type(const EVP_KEYMGMT
*keymgmt1
, const EVP_KEYMGMT
*keymgmt2
)
24 const char *name2
= EVP_KEYMGMT_get0_name(keymgmt2
);
26 return EVP_KEYMGMT_is_a(keymgmt1
, name2
);
29 int evp_keymgmt_util_try_import(const OSSL_PARAM params
[], void *arg
)
31 struct evp_keymgmt_util_try_import_data_st
*data
= arg
;
32 int delete_on_error
= 0;
34 /* Just in time creation of keydata */
35 if (data
->keydata
== NULL
) {
36 if ((data
->keydata
= evp_keymgmt_newdata(data
->keymgmt
)) == NULL
) {
37 ERR_raise(ERR_LIB_EVP
, ERR_R_EVP_LIB
);
44 * It's fine if there was no data to transfer, we just end up with an
45 * empty destination key.
47 if (params
[0].key
== NULL
)
50 if (evp_keymgmt_import(data
->keymgmt
, data
->keydata
, data
->selection
,
53 if (delete_on_error
) {
54 evp_keymgmt_freedata(data
->keymgmt
, data
->keydata
);
60 int evp_keymgmt_util_assign_pkey(EVP_PKEY
*pkey
, EVP_KEYMGMT
*keymgmt
,
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
);
68 pkey
->keydata
= keydata
;
69 evp_keymgmt_util_cache_keyinfo(pkey
);
73 EVP_PKEY
*evp_keymgmt_util_make_pkey(EVP_KEYMGMT
*keymgmt
, void *keydata
)
75 EVP_PKEY
*pkey
= NULL
;
79 || (pkey
= EVP_PKEY_new()) == NULL
80 || !evp_keymgmt_util_assign_pkey(pkey
, keymgmt
, keydata
)) {
87 int evp_keymgmt_util_export(const EVP_PKEY
*pk
, int selection
,
88 OSSL_CALLBACK
*export_cb
, void *export_cbarg
)
90 if (pk
== NULL
|| export_cb
== NULL
)
92 return evp_keymgmt_export(pk
->keymgmt
, pk
->keydata
, selection
,
93 export_cb
, export_cbarg
);
96 void *evp_keymgmt_util_export_to_provider(EVP_PKEY
*pk
, EVP_KEYMGMT
*keymgmt
,
99 struct evp_keymgmt_util_try_import_data_st import_data
;
102 /* Export to where? */
106 /* If we have an unassigned key, give up */
107 if (pk
->keydata
== NULL
)
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
117 if (pk
->keymgmt
== keymgmt
118 || (pk
->keymgmt
->name_id
== keymgmt
->name_id
119 && pk
->keymgmt
->prov
== keymgmt
->prov
))
122 if (!CRYPTO_THREAD_read_lock(pk
->lock
))
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.
129 if (pk
->dirty_cnt
== pk
->dirty_cnt_copy
) {
130 /* If this key is already exported to |keymgmt|, no more to do */
131 op
= evp_keymgmt_util_find_operation_cache(pk
, keymgmt
, selection
);
132 if (op
!= NULL
&& op
->keymgmt
!= NULL
) {
133 void *ret
= op
->keydata
;
135 CRYPTO_THREAD_unlock(pk
->lock
);
139 CRYPTO_THREAD_unlock(pk
->lock
);
141 /* If the "origin" |keymgmt| doesn't support exporting, give up */
142 if (pk
->keymgmt
->export
== NULL
)
146 * Make sure that the type of the keymgmt to export to matches the type
149 if (!ossl_assert(match_type(pk
->keymgmt
, keymgmt
)))
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.
158 /* Setup for the export callback */
159 import_data
.keydata
= NULL
; /* evp_keymgmt_util_try_import will create it */
160 import_data
.keymgmt
= keymgmt
;
161 import_data
.selection
= selection
;
164 * The export function calls the callback (evp_keymgmt_util_try_import),
165 * which does the import for us. If successful, we're done.
167 if (!evp_keymgmt_util_export(pk
, selection
,
168 &evp_keymgmt_util_try_import
, &import_data
))
169 /* If there was an error, bail out */
172 if (!CRYPTO_THREAD_write_lock(pk
->lock
)) {
173 evp_keymgmt_freedata(keymgmt
, import_data
.keydata
);
176 /* Check to make sure some other thread didn't get there first */
177 op
= evp_keymgmt_util_find_operation_cache(pk
, keymgmt
, selection
);
178 if (op
!= NULL
&& op
->keydata
!= NULL
) {
179 void *ret
= op
->keydata
;
181 CRYPTO_THREAD_unlock(pk
->lock
);
184 * Another thread seemms to have already exported this so we abandon
185 * all the work we just did.
187 evp_keymgmt_freedata(keymgmt
, import_data
.keydata
);
193 * If the dirty counter changed since last time, then clear the
194 * operation cache. In that case, we know that |i| is zero.
196 if (pk
->dirty_cnt
!= pk
->dirty_cnt_copy
)
197 evp_keymgmt_util_clear_operation_cache(pk
);
199 /* Add the new export to the operation cache */
200 if (!evp_keymgmt_util_cache_keydata(pk
, keymgmt
, import_data
.keydata
,
202 CRYPTO_THREAD_unlock(pk
->lock
);
203 evp_keymgmt_freedata(keymgmt
, import_data
.keydata
);
207 /* Synchronize the dirty count */
208 pk
->dirty_cnt_copy
= pk
->dirty_cnt
;
210 CRYPTO_THREAD_unlock(pk
->lock
);
212 return import_data
.keydata
;
215 static void op_cache_free(OP_CACHE_ELEM
*e
)
217 evp_keymgmt_freedata(e
->keymgmt
, e
->keydata
);
218 EVP_KEYMGMT_free(e
->keymgmt
);
222 int evp_keymgmt_util_clear_operation_cache(EVP_PKEY
*pk
)
225 sk_OP_CACHE_ELEM_pop_free(pk
->operation_cache
, op_cache_free
);
226 pk
->operation_cache
= NULL
;
232 OP_CACHE_ELEM
*evp_keymgmt_util_find_operation_cache(EVP_PKEY
*pk
,
233 EVP_KEYMGMT
*keymgmt
,
236 int i
, end
= sk_OP_CACHE_ELEM_num(pk
->operation_cache
);
240 * A comparison and sk_P_CACHE_ELEM_find() are avoided to not cause
241 * problems when we've only a read lock.
242 * A keymgmt is a match if the |keymgmt| pointers are identical or if the
243 * provider and the name ID match
245 for (i
= 0; i
< end
; i
++) {
246 p
= sk_OP_CACHE_ELEM_value(pk
->operation_cache
, i
);
247 if ((p
->selection
& selection
) == selection
248 && (keymgmt
== p
->keymgmt
249 || (keymgmt
->name_id
== p
->keymgmt
->name_id
250 && keymgmt
->prov
== p
->keymgmt
->prov
)))
256 int evp_keymgmt_util_cache_keydata(EVP_PKEY
*pk
, EVP_KEYMGMT
*keymgmt
,
257 void *keydata
, int selection
)
259 OP_CACHE_ELEM
*p
= NULL
;
261 if (keydata
!= NULL
) {
262 if (pk
->operation_cache
== NULL
) {
263 pk
->operation_cache
= sk_OP_CACHE_ELEM_new_null();
264 if (pk
->operation_cache
== NULL
)
268 p
= OPENSSL_malloc(sizeof(*p
));
271 p
->keydata
= keydata
;
272 p
->keymgmt
= keymgmt
;
273 p
->selection
= selection
;
275 if (!EVP_KEYMGMT_up_ref(keymgmt
)) {
280 if (!sk_OP_CACHE_ELEM_push(pk
->operation_cache
, p
)) {
281 EVP_KEYMGMT_free(keymgmt
);
289 void evp_keymgmt_util_cache_keyinfo(EVP_PKEY
*pk
)
292 * Cache information about the provider "origin" key.
294 * This services functions like EVP_PKEY_get_size, EVP_PKEY_get_bits, etc
296 if (pk
->keydata
!= NULL
) {
298 int security_bits
= 0;
300 OSSL_PARAM params
[4];
302 params
[0] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_BITS
, &bits
);
303 params
[1] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_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
;
315 void *evp_keymgmt_util_fromdata(EVP_PKEY
*target
, EVP_KEYMGMT
*keymgmt
,
316 int selection
, const OSSL_PARAM params
[])
318 void *keydata
= NULL
;
320 if ((keydata
= evp_keymgmt_newdata(keymgmt
)) == NULL
321 || !evp_keymgmt_import(keymgmt
, keydata
, selection
, params
)
322 || !evp_keymgmt_util_assign_pkey(target
, keymgmt
, keydata
)) {
323 evp_keymgmt_freedata(keymgmt
, keydata
);
329 int evp_keymgmt_util_has(EVP_PKEY
*pk
, int selection
)
331 /* Check if key is even assigned */
332 if (pk
->keymgmt
== NULL
)
335 return evp_keymgmt_has(pk
->keymgmt
, pk
->keydata
, selection
);
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.
343 * evp_keymgmt_util_match() adheres to the return values that EVP_PKEY_eq()
344 * and EVP_PKEY_parameters_eq() return, i.e.:
348 * -1 not same key type
349 * -2 unsupported operation
351 int evp_keymgmt_util_match(EVP_PKEY
*pk1
, EVP_PKEY
*pk2
, int selection
)
353 EVP_KEYMGMT
*keymgmt1
= NULL
, *keymgmt2
= NULL
;
354 void *keydata1
= NULL
, *keydata2
= NULL
;
356 if (pk1
== NULL
|| pk2
== NULL
) {
357 if (pk1
== NULL
&& pk2
== NULL
)
362 keymgmt1
= pk1
->keymgmt
;
363 keydata1
= pk1
->keydata
;
364 keymgmt2
= pk2
->keymgmt
;
365 keydata2
= pk2
->keydata
;
367 if (keymgmt1
!= keymgmt2
) {
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().
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.
380 /* Complex case, where the keymgmt differ */
383 && !match_type(keymgmt1
, keymgmt2
)) {
384 ERR_raise(ERR_LIB_EVP
, EVP_R_DIFFERENT_KEY_TYPES
);
385 return -1; /* Not the same type */
389 * The key types are determined to match, so we try cross export,
390 * but only to keymgmt's that supply a matching function.
393 && keymgmt2
->match
!= NULL
) {
394 void *tmp_keydata
= NULL
;
397 if (keydata1
!= NULL
) {
399 evp_keymgmt_util_export_to_provider(pk1
, keymgmt2
,
401 ok
= (tmp_keydata
!= NULL
);
405 keydata1
= tmp_keydata
;
409 * If we've successfully cross exported one way, there's no point
410 * doing it the other way, hence the |!ok| check.
414 && keymgmt1
->match
!= NULL
) {
415 void *tmp_keydata
= NULL
;
418 if (keydata2
!= NULL
) {
420 evp_keymgmt_util_export_to_provider(pk2
, keymgmt1
,
422 ok
= (tmp_keydata
!= NULL
);
426 keydata2
= tmp_keydata
;
431 /* If we still don't have matching keymgmt implementations, we give up */
432 if (keymgmt1
!= keymgmt2
)
435 /* If both keydata are NULL, then they're the same key */
436 if (keydata1
== NULL
&& keydata2
== NULL
)
438 /* If only one of the keydata is NULL, then they're different keys */
439 if (keydata1
== NULL
|| keydata2
== NULL
)
441 /* If both keydata are non-NULL, we let the backend decide */
442 return evp_keymgmt_match(keymgmt1
, keydata1
, keydata2
, selection
);
445 int evp_keymgmt_util_copy(EVP_PKEY
*to
, EVP_PKEY
*from
, int selection
)
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
;
451 /* An unassigned key can't be copied */
452 if (from
== NULL
|| from
->keydata
== NULL
)
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.
460 if (to_keymgmt
== NULL
)
461 to_keymgmt
= from
->keymgmt
;
463 if (to_keymgmt
== from
->keymgmt
&& to_keymgmt
->dup
!= NULL
464 && to_keydata
== NULL
) {
465 to_keydata
= alloc_keydata
= evp_keymgmt_dup(to_keymgmt
,
468 if (to_keydata
== NULL
)
470 } else if (match_type(to_keymgmt
, from
->keymgmt
)) {
471 struct evp_keymgmt_util_try_import_data_st import_data
;
473 import_data
.keymgmt
= to_keymgmt
;
474 import_data
.keydata
= to_keydata
;
475 import_data
.selection
= selection
;
477 if (!evp_keymgmt_util_export(from
, selection
,
478 &evp_keymgmt_util_try_import
,
483 * In case to_keydata was previously unallocated,
484 * evp_keymgmt_util_try_import() may have created it for us.
486 if (to_keydata
== NULL
)
487 to_keydata
= alloc_keydata
= import_data
.keydata
;
489 ERR_raise(ERR_LIB_EVP
, EVP_R_DIFFERENT_KEY_TYPES
);
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.
502 if (to
->keymgmt
== NULL
503 && !EVP_PKEY_set_type_by_keymgmt(to
, to_keymgmt
)) {
504 evp_keymgmt_freedata(to_keymgmt
, alloc_keydata
);
507 to
->keydata
= to_keydata
;
508 evp_keymgmt_util_cache_keyinfo(to
);
513 void *evp_keymgmt_util_gen(EVP_PKEY
*target
, EVP_KEYMGMT
*keymgmt
,
514 void *genctx
, OSSL_CALLBACK
*cb
, void *cbarg
)
516 void *keydata
= NULL
;
518 if ((keydata
= evp_keymgmt_gen(keymgmt
, genctx
, cb
, cbarg
)) == NULL
519 || !evp_keymgmt_util_assign_pkey(target
, keymgmt
, keydata
)) {
520 evp_keymgmt_freedata(keymgmt
, keydata
);
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.
533 int evp_keymgmt_util_get_deflt_digest_name(EVP_KEYMGMT
*keymgmt
,
535 char *mdname
, size_t mdname_sz
)
537 OSSL_PARAM params
[3];
538 char mddefault
[100] = "";
539 char mdmandatory
[100] = "";
544 OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST
,
545 mddefault
, sizeof(mddefault
));
547 OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST
,
549 sizeof(mdmandatory
));
550 params
[2] = OSSL_PARAM_construct_end();
552 if (!evp_keymgmt_get_params(keymgmt
, keydata
, params
))
555 if (OSSL_PARAM_modified(params
+ 1)) {
556 if (params
[1].return_size
<= 1) /* Only a NUL byte */
559 result
= mdmandatory
;
561 } else if (OSSL_PARAM_modified(params
)) {
562 if (params
[0].return_size
<= 1) /* Only a NUL byte */
569 OPENSSL_strlcpy(mdname
, result
, mdname_sz
);
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.
578 const char *evp_keymgmt_util_query_operation_name(EVP_KEYMGMT
*keymgmt
,
581 const char *name
= NULL
;
583 if (keymgmt
!= NULL
) {
584 if (keymgmt
->query_operation_name
!= NULL
)
585 name
= keymgmt
->query_operation_name(op_id
);
587 name
= EVP_KEYMGMT_get0_name(keymgmt
);