]>
Commit | Line | Data |
---|---|---|
072a9fde | 1 | /* |
a28d06f3 | 2 | * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. |
072a9fde RL |
3 | * |
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 | |
8 | */ | |
9 | ||
10 | #include <openssl/core_names.h> | |
14c8a3d1 | 11 | #include <openssl/core_object.h> |
df65c06b | 12 | #include <openssl/provider.h> |
072a9fde | 13 | #include <openssl/evp.h> |
7524b7b7 | 14 | #include <openssl/ui.h> |
ece9304c | 15 | #include <openssl/decoder.h> |
072a9fde | 16 | #include <openssl/safestack.h> |
de5008a4 | 17 | #include <openssl/trace.h> |
072a9fde | 18 | #include "crypto/evp.h" |
63f187cf | 19 | #include "crypto/decoder.h" |
ece9304c | 20 | #include "encoder_local.h" |
df65c06b | 21 | #include "e_os.h" /* strcasecmp on Windows */ |
072a9fde | 22 | |
ece9304c RL |
23 | int OSSL_DECODER_CTX_set_passphrase(OSSL_DECODER_CTX *ctx, |
24 | const unsigned char *kstr, | |
25 | size_t klen) | |
7524b7b7 | 26 | { |
a517edec | 27 | return ossl_pw_set_passphrase(&ctx->pwdata, kstr, klen); |
7524b7b7 RL |
28 | } |
29 | ||
ece9304c RL |
30 | int OSSL_DECODER_CTX_set_passphrase_ui(OSSL_DECODER_CTX *ctx, |
31 | const UI_METHOD *ui_method, | |
32 | void *ui_data) | |
7524b7b7 | 33 | { |
a517edec | 34 | return ossl_pw_set_ui_method(&ctx->pwdata, ui_method, ui_data); |
7524b7b7 RL |
35 | } |
36 | ||
ece9304c RL |
37 | int OSSL_DECODER_CTX_set_pem_password_cb(OSSL_DECODER_CTX *ctx, |
38 | pem_password_cb *cb, void *cbarg) | |
7524b7b7 | 39 | { |
a517edec | 40 | return ossl_pw_set_pem_password_cb(&ctx->pwdata, cb, cbarg); |
7524b7b7 RL |
41 | } |
42 | ||
4fd39782 RL |
43 | int OSSL_DECODER_CTX_set_passphrase_cb(OSSL_DECODER_CTX *ctx, |
44 | OSSL_PASSPHRASE_CALLBACK *cb, | |
45 | void *cbarg) | |
46 | { | |
47 | return ossl_pw_set_ossl_passphrase_cb(&ctx->pwdata, cb, cbarg); | |
48 | } | |
49 | ||
072a9fde | 50 | /* |
fe75766c | 51 | * Support for OSSL_DECODER_CTX_new_for_pkey: |
4701f0a9 | 52 | * The construct data, and collecting keymgmt information for it |
072a9fde RL |
53 | */ |
54 | ||
55 | DEFINE_STACK_OF(EVP_KEYMGMT) | |
56 | ||
fe75766c | 57 | struct decoder_pkey_data_st { |
054cde17 RL |
58 | OSSL_LIB_CTX *libctx; |
59 | char *propq; | |
60 | ||
072a9fde RL |
61 | char *object_type; /* recorded object data type, may be NULL */ |
62 | void **object; /* Where the result should end up */ | |
072a9fde RL |
63 | }; |
64 | ||
fe75766c TM |
65 | static int decoder_construct_pkey(OSSL_DECODER_INSTANCE *decoder_inst, |
66 | const OSSL_PARAM *params, | |
67 | void *construct_data) | |
072a9fde | 68 | { |
fe75766c | 69 | struct decoder_pkey_data_st *data = construct_data; |
48b62fb3 RL |
70 | OSSL_DECODER *decoder = OSSL_DECODER_INSTANCE_get_decoder(decoder_inst); |
71 | void *decoderctx = OSSL_DECODER_INSTANCE_get_decoder_ctx(decoder_inst); | |
054cde17 | 72 | EVP_KEYMGMT *keymgmt = NULL; |
072a9fde RL |
73 | /* |
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(). | |
77 | * | |
78 | * This pointer is considered volatile, i.e. whatever it points at | |
79 | * is assumed to be freed as soon as this function returns. | |
80 | */ | |
81 | void *object_ref = NULL; | |
82 | size_t object_ref_sz = 0; | |
83 | const OSSL_PARAM *p; | |
84 | ||
14c8a3d1 | 85 | p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA_TYPE); |
072a9fde RL |
86 | if (p != NULL) { |
87 | char *object_type = NULL; | |
88 | ||
89 | if (!OSSL_PARAM_get_utf8_string(p, &object_type, 0)) | |
90 | return 0; | |
91 | OPENSSL_free(data->object_type); | |
92 | data->object_type = object_type; | |
93 | } | |
94 | ||
95 | /* | |
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. | |
99 | */ | |
14c8a3d1 | 100 | p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_REFERENCE); |
072a9fde RL |
101 | if (p == NULL || p->data_type != OSSL_PARAM_OCTET_STRING) |
102 | return 0; | |
103 | object_ref = p->data; | |
104 | object_ref_sz = p->data_size; | |
105 | ||
054cde17 RL |
106 | keymgmt = EVP_KEYMGMT_fetch(data->libctx, data->object_type, data->propq); |
107 | ||
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); | |
072a9fde RL |
113 | |
114 | /* | |
054cde17 RL |
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. | |
072a9fde | 118 | * |
054cde17 RL |
119 | * Otherwise, we export from the decoder and import the |
120 | * result in the keymgmt. | |
072a9fde | 121 | */ |
054cde17 RL |
122 | if (keymgmt_prov == decoder_prov) { |
123 | keydata = evp_keymgmt_load(keymgmt, object_ref, object_ref_sz); | |
124 | } else { | |
125 | struct evp_keymgmt_util_try_import_data_st import_data; | |
126 | ||
127 | import_data.keymgmt = keymgmt; | |
128 | import_data.keydata = NULL; | |
129 | import_data.selection = OSSL_KEYMGMT_SELECT_ALL; | |
072a9fde RL |
130 | |
131 | /* | |
054cde17 RL |
132 | * No need to check for errors here, the value of |
133 | * |import_data.keydata| is as much an indicator. | |
072a9fde | 134 | */ |
054cde17 RL |
135 | (void)decoder->export_object(decoderctx, |
136 | object_ref, object_ref_sz, | |
137 | &evp_keymgmt_util_try_import, | |
138 | &import_data); | |
139 | keydata = import_data.keydata; | |
140 | import_data.keydata = NULL; | |
072a9fde | 141 | } |
054cde17 RL |
142 | |
143 | if (keydata != NULL | |
144 | && (pkey = evp_keymgmt_util_make_pkey(keymgmt, keydata)) == NULL) | |
145 | evp_keymgmt_freedata(keymgmt, keydata); | |
146 | ||
147 | *data->object = pkey; | |
148 | ||
149 | /* | |
150 | * evp_keymgmt_util_make_pkey() increments the reference count when | |
151 | * assigning the EVP_PKEY, so we can free the keymgmt here. | |
152 | */ | |
153 | EVP_KEYMGMT_free(keymgmt); | |
072a9fde RL |
154 | } |
155 | /* | |
156 | * We successfully looked through, |*ctx->object| determines if we | |
157 | * actually found something. | |
158 | */ | |
159 | return (*data->object != NULL); | |
160 | } | |
161 | ||
fe75766c | 162 | static void decoder_clean_pkey_construct_arg(void *construct_data) |
072a9fde | 163 | { |
fe75766c | 164 | struct decoder_pkey_data_st *data = construct_data; |
072a9fde | 165 | |
3c033c5b | 166 | if (data != NULL) { |
054cde17 | 167 | OPENSSL_free(data->propq); |
3c033c5b RL |
168 | OPENSSL_free(data->object_type); |
169 | OPENSSL_free(data); | |
170 | } | |
072a9fde RL |
171 | } |
172 | ||
054cde17 RL |
173 | static void collect_name(const char *name, void *arg) |
174 | { | |
175 | STACK_OF(OPENSSL_CSTRING) *names = arg; | |
072a9fde | 176 | |
054cde17 RL |
177 | sk_OPENSSL_CSTRING_push(names, name); |
178 | } | |
072a9fde RL |
179 | |
180 | static void collect_keymgmt(EVP_KEYMGMT *keymgmt, void *arg) | |
181 | { | |
054cde17 | 182 | STACK_OF(EVP_KEYMGMT) *keymgmts = arg; |
072a9fde RL |
183 | |
184 | if (!EVP_KEYMGMT_up_ref(keymgmt) /* ref++ */) | |
185 | return; | |
054cde17 | 186 | if (sk_EVP_KEYMGMT_push(keymgmts, keymgmt) <= 0) { |
48b62fb3 | 187 | EVP_KEYMGMT_free(keymgmt); /* ref-- */ |
072a9fde RL |
188 | return; |
189 | } | |
072a9fde RL |
190 | } |
191 | ||
df65c06b RL |
192 | /* |
193 | * The input structure check is only done on the initial decoder | |
194 | * implementations. | |
195 | */ | |
054cde17 RL |
196 | static int decoder_check_input_structure(OSSL_DECODER_CTX *ctx, |
197 | OSSL_DECODER_INSTANCE *di) | |
df65c06b RL |
198 | { |
199 | int di_is_was_set = 0; | |
200 | const char *di_is = | |
201 | OSSL_DECODER_INSTANCE_get_input_structure(di, &di_is_was_set); | |
202 | ||
203 | /* | |
204 | * If caller didn't give an input structure name, the decoder is accepted | |
205 | * unconditionally with regards to the input structure. | |
206 | */ | |
207 | if (ctx->input_structure == NULL) | |
208 | return 1; | |
209 | /* | |
210 | * If the caller did give an input structure name, the decoder must have | |
211 | * a matching input structure to be accepted. | |
212 | */ | |
054cde17 | 213 | if (di_is != NULL && strcasecmp(ctx->input_structure, di_is) == 0) |
df65c06b RL |
214 | return 1; |
215 | return 0; | |
216 | } | |
217 | ||
054cde17 RL |
218 | struct collect_decoder_data_st { |
219 | STACK_OF(OPENSSL_CSTRING) *names; | |
220 | OSSL_DECODER_CTX *ctx; | |
221 | ||
222 | unsigned int error_occured:1; | |
223 | }; | |
224 | ||
ece9304c | 225 | static void collect_decoder(OSSL_DECODER *decoder, void *arg) |
fb890008 | 226 | { |
054cde17 | 227 | struct collect_decoder_data_st *data = arg; |
fb890008 | 228 | size_t i, end_i; |
df65c06b RL |
229 | const OSSL_PROVIDER *prov = OSSL_DECODER_provider(decoder); |
230 | void *provctx = OSSL_PROVIDER_get0_provider_ctx(prov); | |
fb890008 RL |
231 | |
232 | if (data->error_occured) | |
233 | return; | |
234 | ||
235 | data->error_occured = 1; /* Assume the worst */ | |
90e0e0d8 SL |
236 | if (data->names == NULL) |
237 | return; | |
fb890008 RL |
238 | |
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); | |
22365254 | 242 | void *decoderctx = NULL; |
df65c06b RL |
243 | OSSL_DECODER_INSTANCE *di = NULL; |
244 | ||
245 | if (OSSL_DECODER_is_a(decoder, name) | |
246 | /* | |
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. | |
251 | */ | |
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 */ | |
257 | decoderctx = NULL; | |
258 | ||
054cde17 | 259 | if (decoder_check_input_structure(data->ctx, di) |
df65c06b RL |
260 | && ossl_decoder_ctx_add_decoder_inst(data->ctx, di)) |
261 | di = NULL; /* If successfully added, don't free it */ | |
262 | } | |
fb890008 | 263 | |
df65c06b RL |
264 | /* Free what can be freed */ |
265 | ossl_decoder_instance_free(di); | |
266 | decoder->freectx(decoderctx); | |
fb890008 RL |
267 | } |
268 | ||
269 | data->error_occured = 0; /* All is good now */ | |
270 | } | |
271 | ||
fe75766c TM |
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) | |
072a9fde | 276 | { |
fe75766c | 277 | struct decoder_pkey_data_st *process_data = NULL; |
054cde17 RL |
278 | STACK_OF(EVP_KEYMGMT) *keymgmts = NULL; |
279 | STACK_OF(OPENSSL_CSTRING) *names = NULL; | |
63f187cf | 280 | int ok = 0; |
072a9fde | 281 | |
054cde17 RL |
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) { | |
ece9304c | 287 | ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); |
072a9fde RL |
288 | goto err; |
289 | } | |
072a9fde | 290 | |
054cde17 RL |
291 | process_data->object = (void **)pkey; |
292 | process_data->libctx = libctx; | |
072a9fde | 293 | |
054cde17 RL |
294 | /* First, find all keymgmts to form goals */ |
295 | EVP_KEYMGMT_do_all_provided(libctx, collect_keymgmt, keymgmts); | |
072a9fde | 296 | |
fb890008 | 297 | /* Then, we collect all the keymgmt names */ |
054cde17 RL |
298 | while (sk_EVP_KEYMGMT_num(keymgmts) > 0) { |
299 | EVP_KEYMGMT *keymgmt = sk_EVP_KEYMGMT_shift(keymgmts); | |
072a9fde | 300 | |
054cde17 RL |
301 | /* |
302 | * If the key type is given by the caller, we only use the matching | |
303 | * KEYMGMTs, otherwise we use them all. | |
304 | */ | |
d84f5515 MC |
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); | |
308 | goto err; | |
309 | } | |
310 | } | |
072a9fde | 311 | |
054cde17 | 312 | EVP_KEYMGMT_free(keymgmt); |
fb890008 | 313 | } |
054cde17 | 314 | sk_EVP_KEYMGMT_free(keymgmts); |
072a9fde | 315 | |
fb890008 | 316 | /* |
ece9304c | 317 | * Finally, find all decoders that have any keymgmt of the collected |
fb890008 RL |
318 | * keymgmt names |
319 | */ | |
054cde17 RL |
320 | { |
321 | struct collect_decoder_data_st collect_decoder_data = { NULL, }; | |
072a9fde | 322 | |
054cde17 RL |
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); | |
328 | ||
329 | if (collect_decoder_data.error_occured) | |
330 | goto err; | |
331 | } | |
072a9fde | 332 | |
48b62fb3 | 333 | if (OSSL_DECODER_CTX_get_num_decoders(ctx) != 0) { |
fe75766c | 334 | if (!OSSL_DECODER_CTX_set_construct(ctx, decoder_construct_pkey) |
054cde17 | 335 | || !OSSL_DECODER_CTX_set_construct_data(ctx, process_data) |
48b62fb3 | 336 | || !OSSL_DECODER_CTX_set_cleanup(ctx, |
fe75766c | 337 | decoder_clean_pkey_construct_arg)) |
48b62fb3 | 338 | goto err; |
072a9fde | 339 | |
054cde17 | 340 | process_data = NULL; /* Avoid it being freed */ |
48b62fb3 | 341 | } |
072a9fde | 342 | |
63f187cf | 343 | ok = 1; |
072a9fde | 344 | err: |
fe75766c | 345 | decoder_clean_pkey_construct_arg(process_data); |
63f187cf RL |
346 | return ok; |
347 | } | |
348 | ||
70c06aaf | 349 | OSSL_DECODER_CTX * |
fe75766c TM |
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) | |
63f187cf RL |
355 | { |
356 | OSSL_DECODER_CTX *ctx = NULL; | |
357 | ||
358 | if ((ctx = OSSL_DECODER_CTX_new()) == NULL) { | |
359 | ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); | |
360 | return NULL; | |
361 | } | |
de5008a4 RL |
362 | |
363 | OSSL_TRACE_BEGIN(DECODER) { | |
364 | BIO_printf(trc_out, | |
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); | |
370 | ||
63f187cf | 371 | if (OSSL_DECODER_CTX_set_input_type(ctx, input_type) |
df65c06b RL |
372 | && OSSL_DECODER_CTX_set_input_structure(ctx, input_structure) |
373 | && OSSL_DECODER_CTX_set_selection(ctx, selection) | |
fe75766c TM |
374 | && ossl_decoder_ctx_setup_for_pkey(ctx, pkey, keytype, |
375 | libctx, propquery) | |
de5008a4 RL |
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); | |
63f187cf | 381 | return ctx; |
de5008a4 | 382 | } |
63f187cf RL |
383 | |
384 | OSSL_DECODER_CTX_free(ctx); | |
385 | return NULL; | |
072a9fde | 386 | } |