2 * Copyright 2020-2021 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 "encoder_local.h"
21 #include "e_os.h" /* strcasecmp on Windows */
23 int OSSL_DECODER_CTX_set_passphrase(OSSL_DECODER_CTX
*ctx
,
24 const unsigned char *kstr
,
27 return ossl_pw_set_passphrase(&ctx
->pwdata
, kstr
, klen
);
30 int OSSL_DECODER_CTX_set_passphrase_ui(OSSL_DECODER_CTX
*ctx
,
31 const UI_METHOD
*ui_method
,
34 return ossl_pw_set_ui_method(&ctx
->pwdata
, ui_method
, ui_data
);
37 int OSSL_DECODER_CTX_set_pem_password_cb(OSSL_DECODER_CTX
*ctx
,
38 pem_password_cb
*cb
, void *cbarg
)
40 return ossl_pw_set_pem_password_cb(&ctx
->pwdata
, cb
, cbarg
);
43 int OSSL_DECODER_CTX_set_passphrase_cb(OSSL_DECODER_CTX
*ctx
,
44 OSSL_PASSPHRASE_CALLBACK
*cb
,
47 return ossl_pw_set_ossl_passphrase_cb(&ctx
->pwdata
, cb
, cbarg
);
51 * Support for OSSL_DECODER_CTX_new_for_pkey:
52 * The construct data, and collecting keymgmt information for it
55 DEFINE_STACK_OF(EVP_KEYMGMT
)
57 struct decoder_pkey_data_st
{
61 char *object_type
; /* recorded object data type, may be NULL */
62 void **object
; /* Where the result should end up */
65 static int decoder_construct_pkey(OSSL_DECODER_INSTANCE
*decoder_inst
,
66 const OSSL_PARAM
*params
,
69 struct decoder_pkey_data_st
*data
= construct_data
;
70 OSSL_DECODER
*decoder
= OSSL_DECODER_INSTANCE_get_decoder(decoder_inst
);
71 void *decoderctx
= OSSL_DECODER_INSTANCE_get_decoder_ctx(decoder_inst
);
72 EVP_KEYMGMT
*keymgmt
= NULL
;
74 * |object_ref| points to a provider reference to an object, its exact
75 * contents entirely opaque to us, but may be passed to any provider
76 * function that expects this (such as OSSL_FUNC_keymgmt_load().
78 * This pointer is considered volatile, i.e. whatever it points at
79 * is assumed to be freed as soon as this function returns.
81 void *object_ref
= NULL
;
82 size_t object_ref_sz
= 0;
85 p
= OSSL_PARAM_locate_const(params
, OSSL_OBJECT_PARAM_DATA_TYPE
);
87 char *object_type
= NULL
;
89 if (!OSSL_PARAM_get_utf8_string(p
, &object_type
, 0))
91 OPENSSL_free(data
->object_type
);
92 data
->object_type
= object_type
;
96 * For stuff that should end up in an EVP_PKEY, we only accept an object
97 * reference for the moment. This enforces that the key data itself
98 * remains with the provider.
100 p
= OSSL_PARAM_locate_const(params
, OSSL_OBJECT_PARAM_REFERENCE
);
101 if (p
== NULL
|| p
->data_type
!= OSSL_PARAM_OCTET_STRING
)
103 object_ref
= p
->data
;
104 object_ref_sz
= p
->data_size
;
106 keymgmt
= EVP_KEYMGMT_fetch(data
->libctx
, data
->object_type
, data
->propq
);
108 if (keymgmt
!= NULL
) {
109 EVP_PKEY
*pkey
= NULL
;
110 void *keydata
= NULL
;
111 const OSSL_PROVIDER
*keymgmt_prov
= EVP_KEYMGMT_provider(keymgmt
);
112 const OSSL_PROVIDER
*decoder_prov
= OSSL_DECODER_provider(decoder
);
115 * If the EVP_KEYMGMT and the OSSL_DECODER are from the
116 * same provider, we assume that the KEYMGMT has a key loading
117 * function that can handle the provider reference we hold.
119 * Otherwise, we export from the decoder and import the
120 * result in the keymgmt.
122 if (keymgmt_prov
== decoder_prov
) {
123 keydata
= evp_keymgmt_load(keymgmt
, object_ref
, object_ref_sz
);
125 struct evp_keymgmt_util_try_import_data_st import_data
;
127 import_data
.keymgmt
= keymgmt
;
128 import_data
.keydata
= NULL
;
129 import_data
.selection
= OSSL_KEYMGMT_SELECT_ALL
;
132 * No need to check for errors here, the value of
133 * |import_data.keydata| is as much an indicator.
135 (void)decoder
->export_object(decoderctx
,
136 object_ref
, object_ref_sz
,
137 &evp_keymgmt_util_try_import
,
139 keydata
= import_data
.keydata
;
140 import_data
.keydata
= NULL
;
144 && (pkey
= evp_keymgmt_util_make_pkey(keymgmt
, keydata
)) == NULL
)
145 evp_keymgmt_freedata(keymgmt
, keydata
);
147 *data
->object
= pkey
;
150 * evp_keymgmt_util_make_pkey() increments the reference count when
151 * assigning the EVP_PKEY, so we can free the keymgmt here.
153 EVP_KEYMGMT_free(keymgmt
);
156 * We successfully looked through, |*ctx->object| determines if we
157 * actually found something.
159 return (*data
->object
!= NULL
);
162 static void decoder_clean_pkey_construct_arg(void *construct_data
)
164 struct decoder_pkey_data_st
*data
= construct_data
;
167 OPENSSL_free(data
->propq
);
168 OPENSSL_free(data
->object_type
);
173 static void collect_name(const char *name
, void *arg
)
175 STACK_OF(OPENSSL_CSTRING
) *names
= arg
;
177 sk_OPENSSL_CSTRING_push(names
, name
);
180 static void collect_keymgmt(EVP_KEYMGMT
*keymgmt
, void *arg
)
182 STACK_OF(EVP_KEYMGMT
) *keymgmts
= arg
;
184 if (!EVP_KEYMGMT_up_ref(keymgmt
) /* ref++ */)
186 if (sk_EVP_KEYMGMT_push(keymgmts
, keymgmt
) <= 0) {
187 EVP_KEYMGMT_free(keymgmt
); /* ref-- */
193 * The input structure check is only done on the initial decoder
196 static int decoder_check_input_structure(OSSL_DECODER_CTX
*ctx
,
197 OSSL_DECODER_INSTANCE
*di
)
199 int di_is_was_set
= 0;
201 OSSL_DECODER_INSTANCE_get_input_structure(di
, &di_is_was_set
);
204 * If caller didn't give an input structure name, the decoder is accepted
205 * unconditionally with regards to the input structure.
207 if (ctx
->input_structure
== NULL
)
210 * If the caller did give an input structure name, the decoder must have
211 * a matching input structure to be accepted.
213 if (di_is
!= NULL
&& strcasecmp(ctx
->input_structure
, di_is
) == 0)
218 struct collect_decoder_data_st
{
219 STACK_OF(OPENSSL_CSTRING
) *names
;
220 OSSL_DECODER_CTX
*ctx
;
222 unsigned int error_occured
:1;
225 static void collect_decoder(OSSL_DECODER
*decoder
, void *arg
)
227 struct collect_decoder_data_st
*data
= arg
;
229 const OSSL_PROVIDER
*prov
= OSSL_DECODER_provider(decoder
);
230 void *provctx
= OSSL_PROVIDER_get0_provider_ctx(prov
);
232 if (data
->error_occured
)
235 data
->error_occured
= 1; /* Assume the worst */
236 if (data
->names
== NULL
)
239 end_i
= sk_OPENSSL_CSTRING_num(data
->names
);
240 for (i
= 0; i
< end_i
; i
++) {
241 const char *name
= sk_OPENSSL_CSTRING_value(data
->names
, i
);
242 void *decoderctx
= NULL
;
243 OSSL_DECODER_INSTANCE
*di
= NULL
;
245 if (OSSL_DECODER_is_a(decoder
, name
)
247 * Either the caller didn't give a selection, or if they did,
248 * the decoder must tell us if it supports that selection to
249 * be accepted. If the decoder doesn't have |does_selection|,
250 * it's seen as taking anything.
252 && (decoder
->does_selection
== NULL
253 || decoder
->does_selection(provctx
, data
->ctx
->selection
))
254 && (decoderctx
= decoder
->newctx(provctx
)) != NULL
255 && (di
= ossl_decoder_instance_new(decoder
, decoderctx
)) != NULL
) {
256 /* If successful so far, don't free these directly */
259 if (decoder_check_input_structure(data
->ctx
, di
)
260 && ossl_decoder_ctx_add_decoder_inst(data
->ctx
, di
))
261 di
= NULL
; /* If successfully added, don't free it */
264 /* Free what can be freed */
265 ossl_decoder_instance_free(di
);
266 decoder
->freectx(decoderctx
);
269 data
->error_occured
= 0; /* All is good now */
272 int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX
*ctx
,
273 EVP_PKEY
**pkey
, const char *keytype
,
274 OSSL_LIB_CTX
*libctx
,
275 const char *propquery
)
277 struct decoder_pkey_data_st
*process_data
= NULL
;
278 STACK_OF(EVP_KEYMGMT
) *keymgmts
= NULL
;
279 STACK_OF(OPENSSL_CSTRING
) *names
= NULL
;
282 if ((process_data
= OPENSSL_zalloc(sizeof(*process_data
))) == NULL
283 || (propquery
!= NULL
284 && (process_data
->propq
= OPENSSL_strdup(propquery
)) == NULL
)
285 || (keymgmts
= sk_EVP_KEYMGMT_new_null()) == NULL
286 || (names
= sk_OPENSSL_CSTRING_new_null()) == NULL
) {
287 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_MALLOC_FAILURE
);
291 process_data
->object
= (void **)pkey
;
292 process_data
->libctx
= libctx
;
294 /* First, find all keymgmts to form goals */
295 EVP_KEYMGMT_do_all_provided(libctx
, collect_keymgmt
, keymgmts
);
297 /* Then, we collect all the keymgmt names */
298 while (sk_EVP_KEYMGMT_num(keymgmts
) > 0) {
299 EVP_KEYMGMT
*keymgmt
= sk_EVP_KEYMGMT_shift(keymgmts
);
302 * If the key type is given by the caller, we only use the matching
303 * KEYMGMTs, otherwise we use them all.
305 if (keytype
== NULL
|| EVP_KEYMGMT_is_a(keymgmt
, keytype
)) {
306 if (!EVP_KEYMGMT_names_do_all(keymgmt
, collect_name
, names
)) {
307 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_INTERNAL_ERROR
);
312 EVP_KEYMGMT_free(keymgmt
);
314 sk_EVP_KEYMGMT_free(keymgmts
);
317 * Finally, find all decoders that have any keymgmt of the collected
321 struct collect_decoder_data_st collect_decoder_data
= { NULL
, };
323 collect_decoder_data
.names
= names
;
324 collect_decoder_data
.ctx
= ctx
;
325 OSSL_DECODER_do_all_provided(libctx
,
326 collect_decoder
, &collect_decoder_data
);
327 sk_OPENSSL_CSTRING_free(names
);
329 if (collect_decoder_data
.error_occured
)
333 if (OSSL_DECODER_CTX_get_num_decoders(ctx
) != 0) {
334 if (!OSSL_DECODER_CTX_set_construct(ctx
, decoder_construct_pkey
)
335 || !OSSL_DECODER_CTX_set_construct_data(ctx
, process_data
)
336 || !OSSL_DECODER_CTX_set_cleanup(ctx
,
337 decoder_clean_pkey_construct_arg
))
340 process_data
= NULL
; /* Avoid it being freed */
345 decoder_clean_pkey_construct_arg(process_data
);
350 OSSL_DECODER_CTX_new_for_pkey(EVP_PKEY
**pkey
,
351 const char *input_type
,
352 const char *input_structure
,
353 const char *keytype
, int selection
,
354 OSSL_LIB_CTX
*libctx
, const char *propquery
)
356 OSSL_DECODER_CTX
*ctx
= NULL
;
358 if ((ctx
= OSSL_DECODER_CTX_new()) == NULL
) {
359 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_MALLOC_FAILURE
);
363 OSSL_TRACE_BEGIN(DECODER
) {
365 "(ctx %p) Looking for %s decoders with selection %d\n",
366 (void *)ctx
, keytype
, selection
);
367 BIO_printf(trc_out
, " input type: %s, input structure: %s\n",
368 input_type
, input_structure
);
369 } OSSL_TRACE_END(DECODER
);
371 if (OSSL_DECODER_CTX_set_input_type(ctx
, input_type
)
372 && OSSL_DECODER_CTX_set_input_structure(ctx
, input_structure
)
373 && OSSL_DECODER_CTX_set_selection(ctx
, selection
)
374 && ossl_decoder_ctx_setup_for_pkey(ctx
, pkey
, keytype
,
376 && OSSL_DECODER_CTX_add_extra(ctx
, libctx
, propquery
)) {
377 OSSL_TRACE_BEGIN(DECODER
) {
378 BIO_printf(trc_out
, "(ctx %p) Got %d decoders\n",
379 (void *)ctx
, OSSL_DECODER_CTX_get_num_decoders(ctx
));
380 } OSSL_TRACE_END(DECODER
);
384 OSSL_DECODER_CTX_free(ctx
);