2 * Copyright 2020 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/evp.h>
13 #include <openssl/ui.h>
14 #include <openssl/decoder.h>
15 #include <openssl/safestack.h>
16 #include "crypto/evp.h"
17 #include "crypto/decoder.h"
18 #include "encoder_local.h"
20 int OSSL_DECODER_CTX_set_passphrase(OSSL_DECODER_CTX
*ctx
,
21 const unsigned char *kstr
,
24 return ossl_pw_set_passphrase(&ctx
->pwdata
, kstr
, klen
);
27 int OSSL_DECODER_CTX_set_passphrase_ui(OSSL_DECODER_CTX
*ctx
,
28 const UI_METHOD
*ui_method
,
31 return ossl_pw_set_ui_method(&ctx
->pwdata
, ui_method
, ui_data
);
34 int OSSL_DECODER_CTX_set_pem_password_cb(OSSL_DECODER_CTX
*ctx
,
35 pem_password_cb
*cb
, void *cbarg
)
37 return ossl_pw_set_pem_password_cb(&ctx
->pwdata
, cb
, cbarg
);
40 int OSSL_DECODER_CTX_set_passphrase_cb(OSSL_DECODER_CTX
*ctx
,
41 OSSL_PASSPHRASE_CALLBACK
*cb
,
44 return ossl_pw_set_ossl_passphrase_cb(&ctx
->pwdata
, cb
, cbarg
);
48 * Support for OSSL_DECODER_CTX_new_by_EVP_PKEY:
49 * The construct data, and collecting keymgmt information for it
52 DEFINE_STACK_OF(EVP_KEYMGMT
)
54 struct decoder_EVP_PKEY_data_st
{
55 char *object_type
; /* recorded object data type, may be NULL */
56 void **object
; /* Where the result should end up */
57 STACK_OF(EVP_KEYMGMT
) *keymgmts
; /* The EVP_KEYMGMTs we handle */
60 static int decoder_construct_EVP_PKEY(OSSL_DECODER_INSTANCE
*decoder_inst
,
61 const OSSL_PARAM
*params
,
64 struct decoder_EVP_PKEY_data_st
*data
= construct_data
;
65 OSSL_DECODER
*decoder
=
66 OSSL_DECODER_INSTANCE_decoder(decoder_inst
);
67 void *decoderctx
= OSSL_DECODER_INSTANCE_decoder_ctx(decoder_inst
);
70 * |object_ref| points to a provider reference to an object, its exact
71 * contents entirely opaque to us, but may be passed to any provider
72 * function that expects this (such as OSSL_FUNC_keymgmt_load().
74 * This pointer is considered volatile, i.e. whatever it points at
75 * is assumed to be freed as soon as this function returns.
77 void *object_ref
= NULL
;
78 size_t object_ref_sz
= 0;
81 p
= OSSL_PARAM_locate_const(params
, OSSL_OBJECT_PARAM_DATA_TYPE
);
83 char *object_type
= NULL
;
85 if (!OSSL_PARAM_get_utf8_string(p
, &object_type
, 0))
87 OPENSSL_free(data
->object_type
);
88 data
->object_type
= object_type
;
92 * For stuff that should end up in an EVP_PKEY, we only accept an object
93 * reference for the moment. This enforces that the key data itself
94 * remains with the provider.
96 p
= OSSL_PARAM_locate_const(params
, OSSL_OBJECT_PARAM_REFERENCE
);
97 if (p
== NULL
|| p
->data_type
!= OSSL_PARAM_OCTET_STRING
)
100 object_ref_sz
= p
->data_size
;
102 /* We may have reached one of the goals, let's find out! */
103 end_i
= sk_EVP_KEYMGMT_num(data
->keymgmts
);
104 for (i
= 0; end_i
; i
++) {
105 EVP_KEYMGMT
*keymgmt
= sk_EVP_KEYMGMT_value(data
->keymgmts
, i
);
108 * There are two ways to find a matching KEYMGMT:
110 * 1. If the object data type (recorded in |data->object_type|)
111 * is defined, by checking it using EVP_KEYMGMT_is_a().
112 * 2. If the object data type is NOT defined, by comparing the
113 * EVP_KEYMGMT and OSSL_DECODER method numbers. Since
114 * EVP_KEYMGMT and OSSL_DECODE operate with the same
115 * namemap, we know that the method numbers must match.
117 * This allows individual decoders to specify variants of keys,
118 * such as a DER to RSA decoder finding a RSA-PSS key, without
119 * having to decode the exact same DER blob into the exact same
120 * internal structure twice. This is, of course, entirely at the
121 * discretion of the decoder implementations.
123 if (data
->object_type
!= NULL
124 ? EVP_KEYMGMT_is_a(keymgmt
, data
->object_type
)
125 : EVP_KEYMGMT_number(keymgmt
) == OSSL_DECODER_number(decoder
)) {
126 EVP_PKEY
*pkey
= NULL
;
127 void *keydata
= NULL
;
128 const OSSL_PROVIDER
*keymgmt_prov
=
129 EVP_KEYMGMT_provider(keymgmt
);
130 const OSSL_PROVIDER
*decoder_prov
=
131 OSSL_DECODER_provider(decoder
);
134 * If the EVP_KEYMGMT and the OSSL_DECODER are from the
135 * same provider, we assume that the KEYMGMT has a key loading
136 * function that can handle the provider reference we hold.
138 * Otherwise, we export from the decoder and import the
139 * result in the keymgmt.
141 if (keymgmt_prov
== decoder_prov
) {
142 keydata
= evp_keymgmt_load(keymgmt
, object_ref
, object_ref_sz
);
144 struct evp_keymgmt_util_try_import_data_st import_data
;
146 import_data
.keymgmt
= keymgmt
;
147 import_data
.keydata
= NULL
;
148 import_data
.selection
= OSSL_KEYMGMT_SELECT_ALL
;
151 * No need to check for errors here, the value of
152 * |import_data.keydata| is as much an indicator.
154 (void)decoder
->export_object(decoderctx
,
155 object_ref
, object_ref_sz
,
156 &evp_keymgmt_util_try_import
,
158 keydata
= import_data
.keydata
;
159 import_data
.keydata
= NULL
;
164 evp_keymgmt_util_make_pkey(keymgmt
, keydata
)) == NULL
)
165 evp_keymgmt_freedata(keymgmt
, keydata
);
167 *data
->object
= pkey
;
173 * We successfully looked through, |*ctx->object| determines if we
174 * actually found something.
176 return (*data
->object
!= NULL
);
179 static void decoder_clean_EVP_PKEY_construct_arg(void *construct_data
)
181 struct decoder_EVP_PKEY_data_st
*data
= construct_data
;
184 sk_EVP_KEYMGMT_pop_free(data
->keymgmts
, EVP_KEYMGMT_free
);
185 OPENSSL_free(data
->object_type
);
190 struct collected_data_st
{
191 struct decoder_EVP_PKEY_data_st
*process_data
;
192 STACK_OF(OPENSSL_CSTRING
) *names
;
193 OSSL_DECODER_CTX
*ctx
;
195 unsigned int error_occured
:1;
198 static void collect_keymgmt(EVP_KEYMGMT
*keymgmt
, void *arg
)
200 struct collected_data_st
*data
= arg
;
202 if (data
->error_occured
)
205 data
->error_occured
= 1; /* Assume the worst */
207 if (!EVP_KEYMGMT_up_ref(keymgmt
) /* ref++ */)
209 if (sk_EVP_KEYMGMT_push(data
->process_data
->keymgmts
, keymgmt
) <= 0) {
210 EVP_KEYMGMT_free(keymgmt
); /* ref-- */
214 data
->error_occured
= 0; /* All is good now */
217 static void collect_name(const char *name
, void *arg
)
219 struct collected_data_st
*data
= arg
;
221 if (data
->error_occured
)
224 data
->error_occured
= 1; /* Assume the worst */
226 if (sk_OPENSSL_CSTRING_push(data
->names
, name
) <= 0)
229 data
->error_occured
= 0; /* All is good now */
232 static void collect_decoder(OSSL_DECODER
*decoder
, void *arg
)
234 struct collected_data_st
*data
= arg
;
237 if (data
->error_occured
)
240 data
->error_occured
= 1; /* Assume the worst */
241 if (data
->names
== NULL
)
244 end_i
= sk_OPENSSL_CSTRING_num(data
->names
);
245 for (i
= 0; i
< end_i
; i
++) {
246 const char *name
= sk_OPENSSL_CSTRING_value(data
->names
, i
);
248 if (!OSSL_DECODER_is_a(decoder
, name
))
250 (void)OSSL_DECODER_CTX_add_decoder(data
->ctx
, decoder
);
253 data
->error_occured
= 0; /* All is good now */
256 int ossl_decoder_ctx_setup_for_EVP_PKEY(OSSL_DECODER_CTX
*ctx
,
259 const char *propquery
)
261 struct collected_data_st
*data
= NULL
;
265 if ((data
= OPENSSL_zalloc(sizeof(*data
))) == NULL
266 || (data
->process_data
=
267 OPENSSL_zalloc(sizeof(*data
->process_data
))) == NULL
268 || (data
->process_data
->keymgmts
269 = sk_EVP_KEYMGMT_new_null()) == NULL
270 || (data
->names
= sk_OPENSSL_CSTRING_new_null()) == NULL
) {
271 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_MALLOC_FAILURE
);
274 data
->process_data
->object
= (void **)pkey
;
277 /* First, find all keymgmts to form goals */
278 EVP_KEYMGMT_do_all_provided(libctx
, collect_keymgmt
, data
);
280 if (data
->error_occured
)
283 /* Then, we collect all the keymgmt names */
284 end_i
= sk_EVP_KEYMGMT_num(data
->process_data
->keymgmts
);
285 for (i
= 0; i
< end_i
; i
++) {
286 EVP_KEYMGMT
*keymgmt
=
287 sk_EVP_KEYMGMT_value(data
->process_data
->keymgmts
, i
);
289 EVP_KEYMGMT_names_do_all(keymgmt
, collect_name
, data
);
291 if (data
->error_occured
)
296 * Finally, find all decoders that have any keymgmt of the collected
299 OSSL_DECODER_do_all_provided(libctx
, collect_decoder
, data
);
301 if (data
->error_occured
)
304 /* If we found no decoders to match the keymgmts, we err */
305 if (OSSL_DECODER_CTX_num_decoders(ctx
) == 0)
308 if (!OSSL_DECODER_CTX_set_construct(ctx
, decoder_construct_EVP_PKEY
)
309 || !OSSL_DECODER_CTX_set_construct_data(ctx
, data
->process_data
)
310 || !OSSL_DECODER_CTX_set_cleanup(ctx
,
311 decoder_clean_EVP_PKEY_construct_arg
))
314 data
->process_data
= NULL
;
318 decoder_clean_EVP_PKEY_construct_arg(data
->process_data
);
319 sk_OPENSSL_CSTRING_free(data
->names
);
325 OSSL_DECODER_CTX
*OSSL_DECODER_CTX_new_by_EVP_PKEY(EVP_PKEY
**pkey
,
326 const char *input_type
,
328 const char *propquery
)
330 OSSL_DECODER_CTX
*ctx
= NULL
;
332 if ((ctx
= OSSL_DECODER_CTX_new()) == NULL
) {
333 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_MALLOC_FAILURE
);
336 if (OSSL_DECODER_CTX_set_input_type(ctx
, input_type
)
337 && ossl_decoder_ctx_setup_for_EVP_PKEY(ctx
, pkey
, libctx
, propquery
)
338 && OSSL_DECODER_CTX_add_extra(ctx
, libctx
, propquery
))
341 OSSL_DECODER_CTX_free(ctx
);