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/evp.h>
12 #include <openssl/ui.h>
13 #include <openssl/decoder.h>
14 #include <openssl/safestack.h>
15 #include "crypto/evp.h"
16 #include "encoder_local.h"
18 int OSSL_DECODER_CTX_set_passphrase(OSSL_DECODER_CTX
*ctx
,
19 const unsigned char *kstr
,
22 if (!ossl_assert(ctx
!= NULL
)) {
23 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_PASSED_NULL_PARAMETER
);
27 OPENSSL_clear_free(ctx
->cached_passphrase
, ctx
->cached_passphrase_len
);
28 ctx
->cached_passphrase
= NULL
;
29 ctx
->cached_passphrase_len
= 0;
32 ctx
->cached_passphrase
= OPENSSL_zalloc(1);
33 ctx
->cached_passphrase_len
= 0;
35 ctx
->cached_passphrase
= OPENSSL_memdup(kstr
, klen
);
36 ctx
->cached_passphrase_len
= klen
;
38 if (ctx
->cached_passphrase
== NULL
) {
39 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_MALLOC_FAILURE
);
43 ctx
->flag_user_passphrase
= 1;
47 static void decoder_ctx_reset_passphrase_ui(OSSL_DECODER_CTX
*ctx
)
49 UI_destroy_method(ctx
->allocated_ui_method
);
50 ctx
->allocated_ui_method
= NULL
;
51 ctx
->ui_method
= NULL
;
55 int OSSL_DECODER_CTX_set_passphrase_ui(OSSL_DECODER_CTX
*ctx
,
56 const UI_METHOD
*ui_method
,
59 if (!ossl_assert(ctx
!= NULL
)) {
60 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_PASSED_NULL_PARAMETER
);
64 decoder_ctx_reset_passphrase_ui(ctx
);
65 ctx
->ui_method
= ui_method
;
66 ctx
->ui_data
= ui_data
;
70 int OSSL_DECODER_CTX_set_pem_password_cb(OSSL_DECODER_CTX
*ctx
,
71 pem_password_cb
*cb
, void *cbarg
)
73 UI_METHOD
*ui_method
= NULL
;
75 if (!ossl_assert(ctx
!= NULL
)) {
76 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_PASSED_NULL_PARAMETER
);
81 * If |cb| is NULL, it means the caller wants to reset previous
82 * password callback info. Otherwise, we only set the new data
83 * if a new UI_METHOD could be created for this sort of callback.
86 || (ui_method
= UI_UTIL_wrap_read_pem_callback(cb
, 0)) != NULL
) {
87 decoder_ctx_reset_passphrase_ui(ctx
);
88 ctx
->ui_method
= ctx
->allocated_ui_method
= ui_method
;
90 ctx
->passphrase_cb
= ossl_decoder_passphrase_in_cb
;
98 * Support for OSSL_DECODER_CTX_new_by_EVP_PKEY:
99 * The construct data, and collecting keymgmt information for it
102 DEFINE_STACK_OF(EVP_KEYMGMT
)
104 struct decoder_EVP_PKEY_data_st
{
105 char *object_type
; /* recorded object data type, may be NULL */
106 void **object
; /* Where the result should end up */
107 STACK_OF(EVP_KEYMGMT
) *keymgmts
; /* The EVP_KEYMGMTs we handle */
110 static int decoder_construct_EVP_PKEY(OSSL_DECODER_INSTANCE
*decoder_inst
,
111 const OSSL_PARAM
*params
,
112 void *construct_data
)
114 struct decoder_EVP_PKEY_data_st
*data
= construct_data
;
115 OSSL_DECODER
*decoder
=
116 OSSL_DECODER_INSTANCE_decoder(decoder_inst
);
117 void *deserctx
= OSSL_DECODER_INSTANCE_decoder_ctx(decoder_inst
);
120 * |object_ref| points to a provider reference to an object, its exact
121 * contents entirely opaque to us, but may be passed to any provider
122 * function that expects this (such as OSSL_FUNC_keymgmt_load().
124 * This pointer is considered volatile, i.e. whatever it points at
125 * is assumed to be freed as soon as this function returns.
127 void *object_ref
= NULL
;
128 size_t object_ref_sz
= 0;
131 p
= OSSL_PARAM_locate_const(params
, OSSL_DECODER_PARAM_DATA_TYPE
);
133 char *object_type
= NULL
;
135 if (!OSSL_PARAM_get_utf8_string(p
, &object_type
, 0))
137 OPENSSL_free(data
->object_type
);
138 data
->object_type
= object_type
;
142 * For stuff that should end up in an EVP_PKEY, we only accept an object
143 * reference for the moment. This enforces that the key data itself
144 * remains with the provider.
146 p
= OSSL_PARAM_locate_const(params
, OSSL_DECODER_PARAM_REFERENCE
);
147 if (p
== NULL
|| p
->data_type
!= OSSL_PARAM_OCTET_STRING
)
149 object_ref
= p
->data
;
150 object_ref_sz
= p
->data_size
;
152 /* We may have reached one of the goals, let's find out! */
153 end_i
= sk_EVP_KEYMGMT_num(data
->keymgmts
);
154 for (i
= 0; end_i
; i
++) {
155 EVP_KEYMGMT
*keymgmt
= sk_EVP_KEYMGMT_value(data
->keymgmts
, i
);
158 * There are two ways to find a matching KEYMGMT:
160 * 1. If the object data type (recorded in |data->object_type|)
161 * is defined, by checking it using EVP_KEYMGMT_is_a().
162 * 2. If the object data type is NOT defined, by comparing the
163 * EVP_KEYMGMT and OSSL_DECODER method numbers. Since
164 * EVP_KEYMGMT and OSSL_DECODE operate with the same
165 * namemap, we know that the method numbers must match.
167 * This allows individual decoders to specify variants of keys,
168 * such as a DER to RSA decoder finding a RSA-PSS key, without
169 * having to decode the exact same DER blob into the exact same
170 * internal structure twice. This is, of course, entirely at the
171 * discretion of the decoder implementations.
173 if (data
->object_type
!= NULL
174 ? EVP_KEYMGMT_is_a(keymgmt
, data
->object_type
)
175 : EVP_KEYMGMT_number(keymgmt
) == OSSL_DECODER_number(decoder
)) {
176 EVP_PKEY
*pkey
= NULL
;
177 void *keydata
= NULL
;
178 const OSSL_PROVIDER
*keymgmt_prov
=
179 EVP_KEYMGMT_provider(keymgmt
);
180 const OSSL_PROVIDER
*decoder_prov
=
181 OSSL_DECODER_provider(decoder
);
184 * If the EVP_KEYMGMT and the OSSL_DECODER are from the
185 * same provider, we assume that the KEYMGMT has a key loading
186 * function that can handle the provider reference we hold.
188 * Otherwise, we export from the decoder and import the
189 * result in the keymgmt.
191 if (keymgmt_prov
== decoder_prov
) {
192 keydata
= evp_keymgmt_load(keymgmt
, object_ref
, object_ref_sz
);
194 struct evp_keymgmt_util_try_import_data_st import_data
;
196 import_data
.keymgmt
= keymgmt
;
197 import_data
.keydata
= NULL
;
198 import_data
.selection
= OSSL_KEYMGMT_SELECT_ALL
;
201 * No need to check for errors here, the value of
202 * |import_data.keydata| is as much an indicator.
204 (void)decoder
->export_object(deserctx
, object_ref
, object_ref_sz
,
205 &evp_keymgmt_util_try_import
,
207 keydata
= import_data
.keydata
;
208 import_data
.keydata
= NULL
;
213 evp_keymgmt_util_make_pkey(keymgmt
, keydata
)) == NULL
)
214 evp_keymgmt_freedata(keymgmt
, keydata
);
216 *data
->object
= pkey
;
222 * We successfully looked through, |*ctx->object| determines if we
223 * actually found something.
225 return (*data
->object
!= NULL
);
228 static void decoder_clean_EVP_PKEY_construct_arg(void *construct_data
)
230 struct decoder_EVP_PKEY_data_st
*data
= construct_data
;
233 sk_EVP_KEYMGMT_pop_free(data
->keymgmts
, EVP_KEYMGMT_free
);
234 OPENSSL_free(data
->object_type
);
239 DEFINE_STACK_OF_CSTRING()
241 struct collected_data_st
{
242 struct decoder_EVP_PKEY_data_st
*process_data
;
243 STACK_OF(OPENSSL_CSTRING
) *names
;
244 OSSL_DECODER_CTX
*ctx
;
246 unsigned int error_occured
:1;
249 static void collect_keymgmt(EVP_KEYMGMT
*keymgmt
, void *arg
)
251 struct collected_data_st
*data
= arg
;
253 if (data
->error_occured
)
256 data
->error_occured
= 1; /* Assume the worst */
258 if (!EVP_KEYMGMT_up_ref(keymgmt
) /* ref++ */)
260 if (sk_EVP_KEYMGMT_push(data
->process_data
->keymgmts
, keymgmt
) <= 0) {
261 EVP_KEYMGMT_free(keymgmt
); /* ref-- */
265 data
->error_occured
= 0; /* All is good now */
268 static void collect_name(const char *name
, void *arg
)
270 struct collected_data_st
*data
= arg
;
272 if (data
->error_occured
)
275 data
->error_occured
= 1; /* Assume the worst */
277 if (sk_OPENSSL_CSTRING_push(data
->names
, name
) <= 0)
280 data
->error_occured
= 0; /* All is good now */
283 static void collect_decoder(OSSL_DECODER
*decoder
, void *arg
)
285 struct collected_data_st
*data
= arg
;
288 if (data
->error_occured
)
291 data
->error_occured
= 1; /* Assume the worst */
293 end_i
= sk_OPENSSL_CSTRING_num(data
->names
);
294 for (i
= 0; i
< end_i
; i
++) {
295 const char *name
= sk_OPENSSL_CSTRING_value(data
->names
, i
);
297 if (!OSSL_DECODER_is_a(decoder
, name
))
299 (void)OSSL_DECODER_CTX_add_decoder(data
->ctx
, decoder
);
302 data
->error_occured
= 0; /* All is good now */
305 OSSL_DECODER_CTX
*OSSL_DECODER_CTX_new_by_EVP_PKEY(EVP_PKEY
**pkey
,
306 const char *input_type
,
308 const char *propquery
)
310 OSSL_DECODER_CTX
*ctx
= NULL
;
311 struct collected_data_st
*data
= NULL
;
314 if ((ctx
= OSSL_DECODER_CTX_new()) == NULL
315 || (data
= OPENSSL_zalloc(sizeof(*data
))) == NULL
316 || (data
->process_data
=
317 OPENSSL_zalloc(sizeof(*data
->process_data
))) == NULL
318 || (data
->process_data
->keymgmts
319 = sk_EVP_KEYMGMT_new_null()) == NULL
320 || (data
->names
= sk_OPENSSL_CSTRING_new_null()) == NULL
) {
321 ERR_raise(ERR_LIB_OSSL_DECODER
, ERR_R_MALLOC_FAILURE
);
324 data
->process_data
->object
= (void **)pkey
;
326 OSSL_DECODER_CTX_set_input_type(ctx
, input_type
);
328 /* First, find all keymgmts to form goals */
329 EVP_KEYMGMT_do_all_provided(libctx
, collect_keymgmt
, data
);
331 if (data
->error_occured
)
334 /* Then, we collect all the keymgmt names */
335 end_i
= sk_EVP_KEYMGMT_num(data
->process_data
->keymgmts
);
336 for (i
= 0; i
< end_i
; i
++) {
337 EVP_KEYMGMT
*keymgmt
=
338 sk_EVP_KEYMGMT_value(data
->process_data
->keymgmts
, i
);
340 EVP_KEYMGMT_names_do_all(keymgmt
, collect_name
, data
);
342 if (data
->error_occured
)
347 * Finally, find all decoders that have any keymgmt of the collected
350 OSSL_DECODER_do_all_provided(libctx
, collect_decoder
, data
);
352 if (data
->error_occured
)
355 /* If we found no decoders to match the keymgmts, we err */
356 if (OSSL_DECODER_CTX_num_decoders(ctx
) == 0)
359 /* Finally, collect extra decoders based on what we already have */
360 (void)OSSL_DECODER_CTX_add_extra(ctx
, libctx
, propquery
);
362 if (!OSSL_DECODER_CTX_set_construct(ctx
, decoder_construct_EVP_PKEY
)
363 || !OSSL_DECODER_CTX_set_construct_data(ctx
, data
->process_data
)
364 || !OSSL_DECODER_CTX_set_cleanup(ctx
,
365 decoder_clean_EVP_PKEY_construct_arg
))
368 data
->process_data
= NULL
;
370 decoder_clean_EVP_PKEY_construct_arg(data
->process_data
);
371 sk_OPENSSL_CSTRING_free(data
->names
);