2 * Copyright 2020-2023 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 <openssl/core_object.h>
12 #include <openssl/provider.h>
13 #include <openssl/evp.h>
14 #include <openssl/ui.h>
15 #include <openssl/decoder.h>
16 #include <openssl/safestack.h>
17 #include <openssl/trace.h>
18 #include "crypto/evp.h"
19 #include "crypto/decoder.h"
20 #include "crypto/evp/evp_local.h"
21 #include "crypto/lhash.h"
22 #include "encoder_local.h"
23 #include "internal/namemap.h"
24 #include "internal/sizes.h"
26 int OSSL_DECODER_CTX_set_passphrase(OSSL_DECODER_CTX
*ctx
,
27 const unsigned char *kstr
,
30 return ossl_pw_set_passphrase(&ctx
->pwdata
, kstr
, klen
);
33 int OSSL_DECODER_CTX_set_passphrase_ui(OSSL_DECODER_CTX
*ctx
,
34 const UI_METHOD
*ui_method
,
37 return ossl_pw_set_ui_method(&ctx
->pwdata
, ui_method
, ui_data
);
40 int OSSL_DECODER_CTX_set_pem_password_cb(OSSL_DECODER_CTX
*ctx
,
41 pem_password_cb
*cb
, void *cbarg
)
43 return ossl_pw_set_pem_password_cb(&ctx
->pwdata
, cb
, cbarg
);
46 int OSSL_DECODER_CTX_set_passphrase_cb(OSSL_DECODER_CTX
*ctx
,
47 OSSL_PASSPHRASE_CALLBACK
*cb
,
50 return ossl_pw_set_ossl_passphrase_cb(&ctx
->pwdata
, cb
, cbarg
);
54 * Support for OSSL_DECODER_CTX_new_for_pkey:
55 * The construct data, and collecting keymgmt information for it
58 DEFINE_STACK_OF(EVP_KEYMGMT
)
60 struct decoder_pkey_data_st
{
65 STACK_OF(EVP_KEYMGMT
) *keymgmts
;
66 char *object_type
; /* recorded object data type, may be NULL */
67 void **object
; /* Where the result should end up */
70 static int decoder_construct_pkey(OSSL_DECODER_INSTANCE
*decoder_inst
,
71 const OSSL_PARAM
*params
,
74 struct decoder_pkey_data_st
*data
= construct_data
;
75 OSSL_DECODER
*decoder
= OSSL_DECODER_INSTANCE_get_decoder(decoder_inst
);
76 void *decoderctx
= OSSL_DECODER_INSTANCE_get_decoder_ctx(decoder_inst
);
77 const OSSL_PROVIDER
*decoder_prov
= OSSL_DECODER_get0_provider(decoder
);
78 EVP_KEYMGMT
*keymgmt
= NULL
;
79 const OSSL_PROVIDER
*keymgmt_prov
= NULL
;
82 * |object_ref| points to a provider reference to an object, its exact
83 * contents entirely opaque to us, but may be passed to any provider
84 * function that expects this (such as OSSL_FUNC_keymgmt_load().
86 * This pointer is considered volatile, i.e. whatever it points at
87 * is assumed to be freed as soon as this function returns.
89 void *object_ref
= NULL
;
90 size_t object_ref_sz
= 0;
93 p
= OSSL_PARAM_locate_const(params
, OSSL_OBJECT_PARAM_DATA_TYPE
);
95 char *object_type
= NULL
;
97 if (!OSSL_PARAM_get_utf8_string(p
, &object_type
, 0))
99 OPENSSL_free(data
->object_type
);
100 data
->object_type
= object_type
;
104 * For stuff that should end up in an EVP_PKEY, we only accept an object
105 * reference for the moment. This enforces that the key data itself
106 * remains with the provider.
108 p
= OSSL_PARAM_locate_const(params
, OSSL_OBJECT_PARAM_REFERENCE
);
109 if (p
== NULL
|| p
->data_type
!= OSSL_PARAM_OCTET_STRING
)
111 object_ref
= p
->data
;
112 object_ref_sz
= p
->data_size
;
115 * First, we try to find a keymgmt that comes from the same provider as
116 * the decoder that passed the params.
118 end
= sk_EVP_KEYMGMT_num(data
->keymgmts
);
119 for (i
= 0; i
< end
; i
++) {
120 keymgmt
= sk_EVP_KEYMGMT_value(data
->keymgmts
, i
);
121 keymgmt_prov
= EVP_KEYMGMT_get0_provider(keymgmt
);
123 if (keymgmt_prov
== decoder_prov
124 && evp_keymgmt_has_load(keymgmt
)
125 && EVP_KEYMGMT_is_a(keymgmt
, data
->object_type
))
129 /* To allow it to be freed further down */
130 if (!EVP_KEYMGMT_up_ref(keymgmt
))
132 } else if ((keymgmt
= EVP_KEYMGMT_fetch(data
->libctx
,
134 data
->propq
)) != NULL
) {
135 keymgmt_prov
= EVP_KEYMGMT_get0_provider(keymgmt
);
138 if (keymgmt
!= NULL
) {
139 EVP_PKEY
*pkey
= NULL
;
140 void *keydata
= NULL
;
143 * If the EVP_KEYMGMT and the OSSL_DECODER are from the
144 * same provider, we assume that the KEYMGMT has a key loading
145 * function that can handle the provider reference we hold.
147 * Otherwise, we export from the decoder and import the
148 * result in the keymgmt.
150 if (keymgmt_prov
== decoder_prov
) {
151 keydata
= evp_keymgmt_load(keymgmt
, object_ref
, object_ref_sz
);
153 struct evp_keymgmt_util_try_import_data_st import_data
;
155 import_data
.keymgmt
= keymgmt
;
156 import_data
.keydata
= NULL
;
157 if (data
->selection
== 0)
158 /* import/export functions do not tolerate 0 selection */
159 import_data
.selection
= OSSL_KEYMGMT_SELECT_ALL
;
161 import_data
.selection
= data
->selection
;
164 * No need to check for errors here, the value of
165 * |import_data.keydata| is as much an indicator.
167 (void)decoder
->export_object(decoderctx
,
168 object_ref
, object_ref_sz
,
169 &evp_keymgmt_util_try_import
,
171 keydata
= import_data
.keydata
;
172 import_data
.keydata
= NULL
;
176 && (pkey
= evp_keymgmt_util_make_pkey(keymgmt
, keydata
)) == NULL
)
177 evp_keymgmt_freedata(keymgmt
, keydata
);
179 *data
->object
= pkey
;
182 * evp_keymgmt_util_make_pkey() increments the reference count when
183 * assigning the EVP_PKEY, so we can free the keymgmt here.
185 EVP_KEYMGMT_free(keymgmt
);
188 * We successfully looked through, |*ctx->object| determines if we
189 * actually found something.
191 return (*data
->object
!= NULL
);
194 static void decoder_clean_pkey_construct_arg(void *construct_data
)
196 struct decoder_pkey_data_st
*data
= construct_data
;
199 sk_EVP_KEYMGMT_pop_free(data
->keymgmts
, EVP_KEYMGMT_free
);
200 OPENSSL_free(data
->propq
);
201 OPENSSL_free(data
->object_type
);
206 struct collect_data_st
{
207 OSSL_LIB_CTX
*libctx
;
208 OSSL_DECODER_CTX
*ctx
;
210 const char *keytype
; /* the keytype requested, if any */
211 int keytype_id
; /* if keytype_resolved is set, keymgmt name_id; else 0 */
212 int sm2_id
; /* if keytype_resolved is set and EC, SM2 name_id; else 0 */
213 int total
; /* number of matching results */
215 char keytype_resolved
;
217 STACK_OF(EVP_KEYMGMT
) *keymgmts
;
220 static void collect_decoder_keymgmt(EVP_KEYMGMT
*keymgmt
, OSSL_DECODER
*decoder
,
221 void *provctx
, struct collect_data_st
*data
)
223 void *decoderctx
= NULL
;
224 OSSL_DECODER_INSTANCE
*di
= NULL
;
227 * We already checked the EVP_KEYMGMT is applicable in check_keymgmt so we
228 * don't check it again here.
231 if (keymgmt
->name_id
!= decoder
->base
.id
)
232 /* Mismatch is not an error, continue. */
235 if ((decoderctx
= decoder
->newctx(provctx
)) == NULL
) {
236 data
->error_occurred
= 1;
240 if ((di
= ossl_decoder_instance_new(decoder
, decoderctx
)) == NULL
) {
241 decoder
->freectx(decoderctx
);
242 data
->error_occurred
= 1;
246 OSSL_TRACE_BEGIN(DECODER
) {
248 "(ctx %p) Checking out decoder %p:\n"
250 (void *)data
->ctx
, (void *)decoder
,
251 OSSL_DECODER_get0_name(decoder
),
252 OSSL_DECODER_get0_properties(decoder
));
253 } OSSL_TRACE_END(DECODER
);
255 if (!ossl_decoder_ctx_add_decoder_inst(data
->ctx
, di
)) {
256 ossl_decoder_instance_free(di
);
257 data
->error_occurred
= 1;
264 static void collect_decoder(OSSL_DECODER
*decoder
, void *arg
)
266 struct collect_data_st
*data
= arg
;
267 STACK_OF(EVP_KEYMGMT
) *keymgmts
= data
->keymgmts
;
269 EVP_KEYMGMT
*keymgmt
;
270 const OSSL_PROVIDER
*prov
;
273 if (data
->error_occurred
)
276 prov
= OSSL_DECODER_get0_provider(decoder
);
277 provctx
= OSSL_PROVIDER_get0_provider_ctx(prov
);
280 * Either the caller didn't give us a selection, or if they did, the decoder
281 * must tell us if it supports that selection to be accepted. If the decoder
282 * doesn't have |does_selection|, it's seen as taking anything.
284 if (decoder
->does_selection
!= NULL
285 && !decoder
->does_selection(provctx
, data
->ctx
->selection
))
288 OSSL_TRACE_BEGIN(DECODER
) {
290 "(ctx %p) Checking out decoder %p:\n"
292 (void *)data
->ctx
, (void *)decoder
,
293 OSSL_DECODER_get0_name(decoder
),
294 OSSL_DECODER_get0_properties(decoder
));
295 } OSSL_TRACE_END(DECODER
);
297 end_i
= sk_EVP_KEYMGMT_num(keymgmts
);
298 for (i
= 0; i
< end_i
; ++i
) {
299 keymgmt
= sk_EVP_KEYMGMT_value(keymgmts
, i
);
301 collect_decoder_keymgmt(keymgmt
, decoder
, provctx
, data
);
302 if (data
->error_occurred
)
308 * Is this EVP_KEYMGMT applicable given the key type given in the call to
309 * ossl_decoder_ctx_setup_for_pkey (if any)?
311 static int check_keymgmt(EVP_KEYMGMT
*keymgmt
, struct collect_data_st
*data
)
313 /* If no keytype was specified, everything matches. */
314 if (data
->keytype
== NULL
)
317 if (!data
->keytype_resolved
) {
318 /* We haven't cached the IDs from the keytype string yet. */
319 OSSL_NAMEMAP
*namemap
= ossl_namemap_stored(data
->libctx
);
320 data
->keytype_id
= ossl_namemap_name2num(namemap
, data
->keytype
);
323 * If keytype is a value ambiguously used for both EC and SM2,
324 * collect the ID for SM2 as well.
326 if (data
->keytype_id
!= 0
327 && (strcmp(data
->keytype
, "id-ecPublicKey") == 0
328 || strcmp(data
->keytype
, "1.2.840.10045.2.1") == 0))
329 data
->sm2_id
= ossl_namemap_name2num(namemap
, "SM2");
332 * If keytype_id is zero the name was not found, but we still
333 * set keytype_resolved to avoid trying all this again.
335 data
->keytype_resolved
= 1;
338 /* Specified keytype could not be resolved, so nothing matches. */
339 if (data
->keytype_id
== 0)
342 /* Does not match the keytype specified, so skip. */
343 if (keymgmt
->name_id
!= data
->keytype_id
344 && keymgmt
->name_id
!= data
->sm2_id
)
350 static void collect_keymgmt(EVP_KEYMGMT
*keymgmt
, void *arg
)
352 struct collect_data_st
*data
= arg
;
354 if (!check_keymgmt(keymgmt
, data
))
358 * We have to ref EVP_KEYMGMT here because in the success case,
359 * data->keymgmts is referenced by the constructor we register in the
360 * OSSL_DECODER_CTX. The registered cleanup function
361 * (decoder_clean_pkey_construct_arg) unrefs every element of the stack and
364 if (!EVP_KEYMGMT_up_ref(keymgmt
))
367 if (sk_EVP_KEYMGMT_push(data
->keymgmts
, keymgmt
) <= 0) {
368 EVP_KEYMGMT_free(keymgmt
);
369 data
->error_occurred
= 1;
374 * This function does the actual binding of decoders to the OSSL_DECODER_CTX. It
375 * searches for decoders matching 'keytype', which is a string like "RSA", "DH",
376 * etc. If 'keytype' is NULL, decoders for all keytypes are bound.
378 static int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX
*ctx
,
380 OSSL_LIB_CTX
*libctx
,
381 const char *propquery
)
384 struct decoder_pkey_data_st
*process_data
= NULL
;
385 struct collect_data_st collect_data
= { NULL
};
386 STACK_OF(EVP_KEYMGMT
) *keymgmts
= NULL
;
388 OSSL_TRACE_BEGIN(DECODER
) {
389 const char *input_type
= ctx
->start_input_type
;
390 const char *input_structure
= ctx
->input_structure
;
393 "(ctx %p) Looking for decoders producing %s%s%s%s%s%s\n",
395 keytype
!= NULL
? keytype
: "",
396 keytype
!= NULL
? " keys" : "keys of any type",
397 input_type
!= NULL
? " from " : "",
398 input_type
!= NULL
? input_type
: "",
399 input_structure
!= NULL
? " with " : "",
400 input_structure
!= NULL
? input_structure
: "");
401 } OSSL_TRACE_END(DECODER
);
404 if ((process_data
= OPENSSL_zalloc(sizeof(*process_data
))) == NULL
)
406 if ((propquery
!= NULL
407 && (process_data
->propq
= OPENSSL_strdup(propquery
)) == NULL
))
410 /* Allocate our list of EVP_KEYMGMTs. */
411 keymgmts
= sk_EVP_KEYMGMT_new_null();
412 if (keymgmts
== NULL
) {
413 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_CRYPTO_LIB
);
417 process_data
->object
= NULL
;
418 process_data
->libctx
= libctx
;
419 process_data
->selection
= ctx
->selection
;
420 process_data
->keymgmts
= keymgmts
;
423 * Enumerate all keymgmts into a stack.
425 * We could nest EVP_KEYMGMT_do_all_provided inside
426 * OSSL_DECODER_do_all_provided or vice versa but these functions become
427 * bottlenecks if called repeatedly, which is why we collect the
428 * EVP_KEYMGMTs into a stack here and call both functions only once.
430 * We resolve the keytype string to a name ID so we don't have to resolve it
431 * multiple times, avoiding repeated calls to EVP_KEYMGMT_is_a, which is a
432 * performance bottleneck. However, we do this lazily on the first call to
433 * collect_keymgmt made by EVP_KEYMGMT_do_all_provided, rather than do it
434 * upfront, as this ensures that the names for all loaded providers have
435 * been registered by the time we try to resolve the keytype string.
437 collect_data
.ctx
= ctx
;
438 collect_data
.libctx
= libctx
;
439 collect_data
.keymgmts
= keymgmts
;
440 collect_data
.keytype
= keytype
;
441 EVP_KEYMGMT_do_all_provided(libctx
, collect_keymgmt
, &collect_data
);
443 if (collect_data
.error_occurred
)
446 /* Enumerate all matching decoders. */
447 OSSL_DECODER_do_all_provided(libctx
, collect_decoder
, &collect_data
);
449 if (collect_data
.error_occurred
)
452 OSSL_TRACE_BEGIN(DECODER
) {
454 "(ctx %p) Got %d decoders producing keys\n",
455 (void *)ctx
, collect_data
.total
);
456 } OSSL_TRACE_END(DECODER
);
459 * Finish initializing the decoder context. If one or more decoders matched
460 * above then the number of decoders attached to the OSSL_DECODER_CTX will
461 * be nonzero. Else nothing was found and we do nothing.
463 if (OSSL_DECODER_CTX_get_num_decoders(ctx
) != 0) {
464 if (!OSSL_DECODER_CTX_set_construct(ctx
, decoder_construct_pkey
)
465 || !OSSL_DECODER_CTX_set_construct_data(ctx
, process_data
)
466 || !OSSL_DECODER_CTX_set_cleanup(ctx
,
467 decoder_clean_pkey_construct_arg
))
470 process_data
= NULL
; /* Avoid it being freed */
475 decoder_clean_pkey_construct_arg(process_data
);
479 /* Only const here because deep_copy requires it */
480 static EVP_KEYMGMT
*keymgmt_dup(const EVP_KEYMGMT
*keymgmt
)
482 if (!EVP_KEYMGMT_up_ref((EVP_KEYMGMT
*)keymgmt
))
485 return (EVP_KEYMGMT
*)keymgmt
;
489 * Duplicates a template OSSL_DECODER_CTX that has been setup for an EVP_PKEY
490 * operation and sets up the duplicate for a new operation.
491 * It does not duplicate the pwdata on the assumption that this does not form
492 * part of the template. That is set up later.
494 static OSSL_DECODER_CTX
*
495 ossl_decoder_ctx_for_pkey_dup(OSSL_DECODER_CTX
*src
,
497 const char *input_type
,
498 const char *input_structure
)
500 OSSL_DECODER_CTX
*dest
;
501 struct decoder_pkey_data_st
*process_data_src
, *process_data_dest
= NULL
;
506 if ((dest
= OSSL_DECODER_CTX_new()) == NULL
) {
507 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_OSSL_DECODER_LIB
);
511 if (!OSSL_DECODER_CTX_set_input_type(dest
, input_type
)
512 || !OSSL_DECODER_CTX_set_input_structure(dest
, input_structure
)) {
513 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_OSSL_DECODER_LIB
);
516 dest
->selection
= src
->selection
;
518 if (src
->decoder_insts
!= NULL
) {
520 = sk_OSSL_DECODER_INSTANCE_deep_copy(src
->decoder_insts
,
521 ossl_decoder_instance_dup
,
522 ossl_decoder_instance_free
);
523 if (dest
->decoder_insts
== NULL
) {
524 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_OSSL_DECODER_LIB
);
529 if (!OSSL_DECODER_CTX_set_construct(dest
,
530 OSSL_DECODER_CTX_get_construct(src
))) {
531 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_OSSL_DECODER_LIB
);
535 process_data_src
= OSSL_DECODER_CTX_get_construct_data(src
);
536 if (process_data_src
!= NULL
) {
537 process_data_dest
= OPENSSL_zalloc(sizeof(*process_data_dest
));
538 if (process_data_dest
== NULL
) {
539 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_CRYPTO_LIB
);
542 if (process_data_src
->propq
!= NULL
) {
543 process_data_dest
->propq
= OPENSSL_strdup(process_data_src
->propq
);
544 if (process_data_dest
->propq
== NULL
) {
545 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_CRYPTO_LIB
);
550 if (process_data_src
->keymgmts
!= NULL
) {
551 process_data_dest
->keymgmts
552 = sk_EVP_KEYMGMT_deep_copy(process_data_src
->keymgmts
,
555 if (process_data_dest
->keymgmts
== NULL
) {
556 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_EVP_LIB
);
561 process_data_dest
->object
= (void **)pkey
;
562 process_data_dest
->libctx
= process_data_src
->libctx
;
563 process_data_dest
->selection
= process_data_src
->selection
;
564 if (!OSSL_DECODER_CTX_set_construct_data(dest
, process_data_dest
)) {
565 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_OSSL_DECODER_LIB
);
568 process_data_dest
= NULL
;
571 if (!OSSL_DECODER_CTX_set_cleanup(dest
,
572 OSSL_DECODER_CTX_get_cleanup(src
))) {
573 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_OSSL_DECODER_LIB
);
579 if (process_data_dest
!= NULL
) {
580 OPENSSL_free(process_data_dest
->propq
);
581 sk_EVP_KEYMGMT_pop_free(process_data_dest
->keymgmts
, EVP_KEYMGMT_free
);
582 OPENSSL_free(process_data_dest
);
584 OSSL_DECODER_CTX_free(dest
);
590 char *input_structure
;
594 OSSL_DECODER_CTX
*template;
595 } DECODER_CACHE_ENTRY
;
597 DEFINE_LHASH_OF_EX(DECODER_CACHE_ENTRY
);
601 LHASH_OF(DECODER_CACHE_ENTRY
) *hashtable
;
604 static void decoder_cache_entry_free(DECODER_CACHE_ENTRY
*entry
)
608 OPENSSL_free(entry
->input_type
);
609 OPENSSL_free(entry
->input_structure
);
610 OPENSSL_free(entry
->keytype
);
611 OPENSSL_free(entry
->propquery
);
612 OSSL_DECODER_CTX_free(entry
->template);
616 static unsigned long decoder_cache_entry_hash(const DECODER_CACHE_ENTRY
*cache
)
618 unsigned long hash
= 17;
621 + (cache
->propquery
== NULL
622 ? 0 : ossl_lh_strcasehash(cache
->propquery
));
624 + (cache
->input_structure
== NULL
625 ? 0 : ossl_lh_strcasehash(cache
->input_structure
));
627 + (cache
->input_type
== NULL
628 ? 0 : ossl_lh_strcasehash(cache
->input_type
));
630 + (cache
->keytype
== NULL
631 ? 0 : ossl_lh_strcasehash(cache
->keytype
));
633 hash
^= cache
->selection
;
638 static ossl_inline
int nullstrcmp(const char *a
, const char *b
, int casecmp
)
640 if (a
== NULL
|| b
== NULL
) {
651 return OPENSSL_strcasecmp(a
, b
);
657 static int decoder_cache_entry_cmp(const DECODER_CACHE_ENTRY
*a
,
658 const DECODER_CACHE_ENTRY
*b
)
662 if (a
->selection
!= b
->selection
)
663 return (a
->selection
< b
->selection
) ? -1 : 1;
665 cmp
= nullstrcmp(a
->keytype
, b
->keytype
, 1);
669 cmp
= nullstrcmp(a
->input_type
, b
->input_type
, 1);
673 cmp
= nullstrcmp(a
->input_structure
, b
->input_structure
, 1);
677 cmp
= nullstrcmp(a
->propquery
, b
->propquery
, 0);
682 void *ossl_decoder_cache_new(OSSL_LIB_CTX
*ctx
)
684 DECODER_CACHE
*cache
= OPENSSL_malloc(sizeof(*cache
));
689 cache
->lock
= CRYPTO_THREAD_lock_new();
690 if (cache
->lock
== NULL
) {
694 cache
->hashtable
= lh_DECODER_CACHE_ENTRY_new(decoder_cache_entry_hash
,
695 decoder_cache_entry_cmp
);
696 if (cache
->hashtable
== NULL
) {
697 CRYPTO_THREAD_lock_free(cache
->lock
);
705 void ossl_decoder_cache_free(void *vcache
)
707 DECODER_CACHE
*cache
= (DECODER_CACHE
*)vcache
;
709 lh_DECODER_CACHE_ENTRY_doall(cache
->hashtable
, decoder_cache_entry_free
);
710 lh_DECODER_CACHE_ENTRY_free(cache
->hashtable
);
711 CRYPTO_THREAD_lock_free(cache
->lock
);
716 * Called whenever a provider gets activated/deactivated. In that case the
717 * decoders that are available might change so we flush our cache.
719 int ossl_decoder_cache_flush(OSSL_LIB_CTX
*libctx
)
722 = ossl_lib_ctx_get_data(libctx
, OSSL_LIB_CTX_DECODER_CACHE_INDEX
);
728 if (!CRYPTO_THREAD_write_lock(cache
->lock
)) {
729 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_OSSL_DECODER_LIB
);
733 lh_DECODER_CACHE_ENTRY_doall(cache
->hashtable
, decoder_cache_entry_free
);
734 lh_DECODER_CACHE_ENTRY_flush(cache
->hashtable
);
736 CRYPTO_THREAD_unlock(cache
->lock
);
741 OSSL_DECODER_CTX_new_for_pkey(EVP_PKEY
**pkey
,
742 const char *input_type
,
743 const char *input_structure
,
744 const char *keytype
, int selection
,
745 OSSL_LIB_CTX
*libctx
, const char *propquery
)
747 OSSL_DECODER_CTX
*ctx
= NULL
;
748 OSSL_PARAM decoder_params
[] = {
753 = ossl_lib_ctx_get_data(libctx
, OSSL_LIB_CTX_DECODER_CACHE_INDEX
);
754 DECODER_CACHE_ENTRY cacheent
, *res
, *newcache
= NULL
;
757 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_OSSL_DECODER_LIB
);
760 if (propquery
!= NULL
)
761 decoder_params
[0] = OSSL_PARAM_construct_utf8_string(OSSL_DECODER_PARAM_PROPERTIES
,
762 (char *)propquery
, 0);
764 /* It is safe to cast away the const here */
765 cacheent
.input_type
= (char *)input_type
;
766 cacheent
.input_structure
= (char *)input_structure
;
767 cacheent
.keytype
= (char *)keytype
;
768 cacheent
.selection
= selection
;
769 cacheent
.propquery
= (char *)propquery
;
771 if (!CRYPTO_THREAD_read_lock(cache
->lock
)) {
772 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_CRYPTO_LIB
);
776 /* First see if we have a template OSSL_DECODER_CTX */
777 res
= lh_DECODER_CACHE_ENTRY_retrieve(cache
->hashtable
, &cacheent
);
781 * There is no template so we will have to construct one. This will be
782 * time consuming so release the lock and we will later upgrade it to a
785 CRYPTO_THREAD_unlock(cache
->lock
);
787 if ((ctx
= OSSL_DECODER_CTX_new()) == NULL
) {
788 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_OSSL_DECODER_LIB
);
792 OSSL_TRACE_BEGIN(DECODER
) {
794 "(ctx %p) Looking for %s decoders with selection %d\n",
795 (void *)ctx
, keytype
, selection
);
796 BIO_printf(trc_out
, " input type: %s, input structure: %s\n",
797 input_type
, input_structure
);
798 } OSSL_TRACE_END(DECODER
);
800 if (OSSL_DECODER_CTX_set_input_type(ctx
, input_type
)
801 && OSSL_DECODER_CTX_set_input_structure(ctx
, input_structure
)
802 && OSSL_DECODER_CTX_set_selection(ctx
, selection
)
803 && ossl_decoder_ctx_setup_for_pkey(ctx
, keytype
, libctx
, propquery
)
804 && OSSL_DECODER_CTX_add_extra(ctx
, libctx
, propquery
)
805 && (propquery
== NULL
806 || OSSL_DECODER_CTX_set_params(ctx
, decoder_params
))) {
807 OSSL_TRACE_BEGIN(DECODER
) {
808 BIO_printf(trc_out
, "(ctx %p) Got %d decoders\n",
809 (void *)ctx
, OSSL_DECODER_CTX_get_num_decoders(ctx
));
810 } OSSL_TRACE_END(DECODER
);
812 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_OSSL_DECODER_LIB
);
813 OSSL_DECODER_CTX_free(ctx
);
817 newcache
= OPENSSL_zalloc(sizeof(*newcache
));
818 if (newcache
== NULL
) {
819 OSSL_DECODER_CTX_free(ctx
);
823 if (input_type
!= NULL
) {
824 newcache
->input_type
= OPENSSL_strdup(input_type
);
825 if (newcache
->input_type
== NULL
)
828 if (input_structure
!= NULL
) {
829 newcache
->input_structure
= OPENSSL_strdup(input_structure
);
830 if (newcache
->input_structure
== NULL
)
833 if (keytype
!= NULL
) {
834 newcache
->keytype
= OPENSSL_strdup(keytype
);
835 if (newcache
->keytype
== NULL
)
838 if (propquery
!= NULL
) {
839 newcache
->propquery
= OPENSSL_strdup(propquery
);
840 if (newcache
->propquery
== NULL
)
843 newcache
->selection
= selection
;
844 newcache
->template = ctx
;
846 if (!CRYPTO_THREAD_write_lock(cache
->lock
)) {
848 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_CRYPTO_LIB
);
851 res
= lh_DECODER_CACHE_ENTRY_retrieve(cache
->hashtable
, &cacheent
);
853 (void)lh_DECODER_CACHE_ENTRY_insert(cache
->hashtable
, newcache
);
854 if (lh_DECODER_CACHE_ENTRY_error(cache
->hashtable
)) {
856 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_CRYPTO_LIB
);
861 * We raced with another thread to construct this and lost. Free
862 * what we just created and use the entry from the hashtable instead
864 decoder_cache_entry_free(newcache
);
871 ctx
= ossl_decoder_ctx_for_pkey_dup(ctx
, pkey
, input_type
, input_structure
);
872 CRYPTO_THREAD_unlock(cache
->lock
);
876 decoder_cache_entry_free(newcache
);
877 OSSL_DECODER_CTX_free(ctx
);