1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <openssl/core_names.h> 11e1051a39Sopenharmony_ci#include <openssl/core_object.h> 12e1051a39Sopenharmony_ci#include <openssl/provider.h> 13e1051a39Sopenharmony_ci#include <openssl/evp.h> 14e1051a39Sopenharmony_ci#include <openssl/ui.h> 15e1051a39Sopenharmony_ci#include <openssl/decoder.h> 16e1051a39Sopenharmony_ci#include <openssl/safestack.h> 17e1051a39Sopenharmony_ci#include <openssl/trace.h> 18e1051a39Sopenharmony_ci#include "crypto/evp.h" 19e1051a39Sopenharmony_ci#include "crypto/decoder.h" 20e1051a39Sopenharmony_ci#include "encoder_local.h" 21e1051a39Sopenharmony_ci 22e1051a39Sopenharmony_ciint OSSL_DECODER_CTX_set_passphrase(OSSL_DECODER_CTX *ctx, 23e1051a39Sopenharmony_ci const unsigned char *kstr, 24e1051a39Sopenharmony_ci size_t klen) 25e1051a39Sopenharmony_ci{ 26e1051a39Sopenharmony_ci return ossl_pw_set_passphrase(&ctx->pwdata, kstr, klen); 27e1051a39Sopenharmony_ci} 28e1051a39Sopenharmony_ci 29e1051a39Sopenharmony_ciint OSSL_DECODER_CTX_set_passphrase_ui(OSSL_DECODER_CTX *ctx, 30e1051a39Sopenharmony_ci const UI_METHOD *ui_method, 31e1051a39Sopenharmony_ci void *ui_data) 32e1051a39Sopenharmony_ci{ 33e1051a39Sopenharmony_ci return ossl_pw_set_ui_method(&ctx->pwdata, ui_method, ui_data); 34e1051a39Sopenharmony_ci} 35e1051a39Sopenharmony_ci 36e1051a39Sopenharmony_ciint OSSL_DECODER_CTX_set_pem_password_cb(OSSL_DECODER_CTX *ctx, 37e1051a39Sopenharmony_ci pem_password_cb *cb, void *cbarg) 38e1051a39Sopenharmony_ci{ 39e1051a39Sopenharmony_ci return ossl_pw_set_pem_password_cb(&ctx->pwdata, cb, cbarg); 40e1051a39Sopenharmony_ci} 41e1051a39Sopenharmony_ci 42e1051a39Sopenharmony_ciint OSSL_DECODER_CTX_set_passphrase_cb(OSSL_DECODER_CTX *ctx, 43e1051a39Sopenharmony_ci OSSL_PASSPHRASE_CALLBACK *cb, 44e1051a39Sopenharmony_ci void *cbarg) 45e1051a39Sopenharmony_ci{ 46e1051a39Sopenharmony_ci return ossl_pw_set_ossl_passphrase_cb(&ctx->pwdata, cb, cbarg); 47e1051a39Sopenharmony_ci} 48e1051a39Sopenharmony_ci 49e1051a39Sopenharmony_ci/* 50e1051a39Sopenharmony_ci * Support for OSSL_DECODER_CTX_new_for_pkey: 51e1051a39Sopenharmony_ci * The construct data, and collecting keymgmt information for it 52e1051a39Sopenharmony_ci */ 53e1051a39Sopenharmony_ci 54e1051a39Sopenharmony_ciDEFINE_STACK_OF(EVP_KEYMGMT) 55e1051a39Sopenharmony_ci 56e1051a39Sopenharmony_cistruct decoder_pkey_data_st { 57e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx; 58e1051a39Sopenharmony_ci char *propq; 59e1051a39Sopenharmony_ci int selection; 60e1051a39Sopenharmony_ci 61e1051a39Sopenharmony_ci STACK_OF(EVP_KEYMGMT) *keymgmts; 62e1051a39Sopenharmony_ci char *object_type; /* recorded object data type, may be NULL */ 63e1051a39Sopenharmony_ci void **object; /* Where the result should end up */ 64e1051a39Sopenharmony_ci}; 65e1051a39Sopenharmony_ci 66e1051a39Sopenharmony_cistatic int decoder_construct_pkey(OSSL_DECODER_INSTANCE *decoder_inst, 67e1051a39Sopenharmony_ci const OSSL_PARAM *params, 68e1051a39Sopenharmony_ci void *construct_data) 69e1051a39Sopenharmony_ci{ 70e1051a39Sopenharmony_ci struct decoder_pkey_data_st *data = construct_data; 71e1051a39Sopenharmony_ci OSSL_DECODER *decoder = OSSL_DECODER_INSTANCE_get_decoder(decoder_inst); 72e1051a39Sopenharmony_ci void *decoderctx = OSSL_DECODER_INSTANCE_get_decoder_ctx(decoder_inst); 73e1051a39Sopenharmony_ci const OSSL_PROVIDER *decoder_prov = OSSL_DECODER_get0_provider(decoder); 74e1051a39Sopenharmony_ci EVP_KEYMGMT *keymgmt = NULL; 75e1051a39Sopenharmony_ci const OSSL_PROVIDER *keymgmt_prov = NULL; 76e1051a39Sopenharmony_ci int i, end; 77e1051a39Sopenharmony_ci /* 78e1051a39Sopenharmony_ci * |object_ref| points to a provider reference to an object, its exact 79e1051a39Sopenharmony_ci * contents entirely opaque to us, but may be passed to any provider 80e1051a39Sopenharmony_ci * function that expects this (such as OSSL_FUNC_keymgmt_load(). 81e1051a39Sopenharmony_ci * 82e1051a39Sopenharmony_ci * This pointer is considered volatile, i.e. whatever it points at 83e1051a39Sopenharmony_ci * is assumed to be freed as soon as this function returns. 84e1051a39Sopenharmony_ci */ 85e1051a39Sopenharmony_ci void *object_ref = NULL; 86e1051a39Sopenharmony_ci size_t object_ref_sz = 0; 87e1051a39Sopenharmony_ci const OSSL_PARAM *p; 88e1051a39Sopenharmony_ci 89e1051a39Sopenharmony_ci p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA_TYPE); 90e1051a39Sopenharmony_ci if (p != NULL) { 91e1051a39Sopenharmony_ci char *object_type = NULL; 92e1051a39Sopenharmony_ci 93e1051a39Sopenharmony_ci if (!OSSL_PARAM_get_utf8_string(p, &object_type, 0)) 94e1051a39Sopenharmony_ci return 0; 95e1051a39Sopenharmony_ci OPENSSL_free(data->object_type); 96e1051a39Sopenharmony_ci data->object_type = object_type; 97e1051a39Sopenharmony_ci } 98e1051a39Sopenharmony_ci 99e1051a39Sopenharmony_ci /* 100e1051a39Sopenharmony_ci * For stuff that should end up in an EVP_PKEY, we only accept an object 101e1051a39Sopenharmony_ci * reference for the moment. This enforces that the key data itself 102e1051a39Sopenharmony_ci * remains with the provider. 103e1051a39Sopenharmony_ci */ 104e1051a39Sopenharmony_ci p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_REFERENCE); 105e1051a39Sopenharmony_ci if (p == NULL || p->data_type != OSSL_PARAM_OCTET_STRING) 106e1051a39Sopenharmony_ci return 0; 107e1051a39Sopenharmony_ci object_ref = p->data; 108e1051a39Sopenharmony_ci object_ref_sz = p->data_size; 109e1051a39Sopenharmony_ci 110e1051a39Sopenharmony_ci /* 111e1051a39Sopenharmony_ci * First, we try to find a keymgmt that comes from the same provider as 112e1051a39Sopenharmony_ci * the decoder that passed the params. 113e1051a39Sopenharmony_ci */ 114e1051a39Sopenharmony_ci end = sk_EVP_KEYMGMT_num(data->keymgmts); 115e1051a39Sopenharmony_ci for (i = 0; i < end; i++) { 116e1051a39Sopenharmony_ci keymgmt = sk_EVP_KEYMGMT_value(data->keymgmts, i); 117e1051a39Sopenharmony_ci keymgmt_prov = EVP_KEYMGMT_get0_provider(keymgmt); 118e1051a39Sopenharmony_ci 119e1051a39Sopenharmony_ci if (keymgmt_prov == decoder_prov 120e1051a39Sopenharmony_ci && evp_keymgmt_has_load(keymgmt) 121e1051a39Sopenharmony_ci && EVP_KEYMGMT_is_a(keymgmt, data->object_type)) 122e1051a39Sopenharmony_ci break; 123e1051a39Sopenharmony_ci } 124e1051a39Sopenharmony_ci if (i < end) { 125e1051a39Sopenharmony_ci /* To allow it to be freed further down */ 126e1051a39Sopenharmony_ci if (!EVP_KEYMGMT_up_ref(keymgmt)) 127e1051a39Sopenharmony_ci return 0; 128e1051a39Sopenharmony_ci } else if ((keymgmt = EVP_KEYMGMT_fetch(data->libctx, 129e1051a39Sopenharmony_ci data->object_type, 130e1051a39Sopenharmony_ci data->propq)) != NULL) { 131e1051a39Sopenharmony_ci keymgmt_prov = EVP_KEYMGMT_get0_provider(keymgmt); 132e1051a39Sopenharmony_ci } 133e1051a39Sopenharmony_ci 134e1051a39Sopenharmony_ci if (keymgmt != NULL) { 135e1051a39Sopenharmony_ci EVP_PKEY *pkey = NULL; 136e1051a39Sopenharmony_ci void *keydata = NULL; 137e1051a39Sopenharmony_ci 138e1051a39Sopenharmony_ci /* 139e1051a39Sopenharmony_ci * If the EVP_KEYMGMT and the OSSL_DECODER are from the 140e1051a39Sopenharmony_ci * same provider, we assume that the KEYMGMT has a key loading 141e1051a39Sopenharmony_ci * function that can handle the provider reference we hold. 142e1051a39Sopenharmony_ci * 143e1051a39Sopenharmony_ci * Otherwise, we export from the decoder and import the 144e1051a39Sopenharmony_ci * result in the keymgmt. 145e1051a39Sopenharmony_ci */ 146e1051a39Sopenharmony_ci if (keymgmt_prov == decoder_prov) { 147e1051a39Sopenharmony_ci keydata = evp_keymgmt_load(keymgmt, object_ref, object_ref_sz); 148e1051a39Sopenharmony_ci } else { 149e1051a39Sopenharmony_ci struct evp_keymgmt_util_try_import_data_st import_data; 150e1051a39Sopenharmony_ci 151e1051a39Sopenharmony_ci import_data.keymgmt = keymgmt; 152e1051a39Sopenharmony_ci import_data.keydata = NULL; 153e1051a39Sopenharmony_ci import_data.selection = data->selection; 154e1051a39Sopenharmony_ci 155e1051a39Sopenharmony_ci /* 156e1051a39Sopenharmony_ci * No need to check for errors here, the value of 157e1051a39Sopenharmony_ci * |import_data.keydata| is as much an indicator. 158e1051a39Sopenharmony_ci */ 159e1051a39Sopenharmony_ci (void)decoder->export_object(decoderctx, 160e1051a39Sopenharmony_ci object_ref, object_ref_sz, 161e1051a39Sopenharmony_ci &evp_keymgmt_util_try_import, 162e1051a39Sopenharmony_ci &import_data); 163e1051a39Sopenharmony_ci keydata = import_data.keydata; 164e1051a39Sopenharmony_ci import_data.keydata = NULL; 165e1051a39Sopenharmony_ci } 166e1051a39Sopenharmony_ci 167e1051a39Sopenharmony_ci if (keydata != NULL 168e1051a39Sopenharmony_ci && (pkey = evp_keymgmt_util_make_pkey(keymgmt, keydata)) == NULL) 169e1051a39Sopenharmony_ci evp_keymgmt_freedata(keymgmt, keydata); 170e1051a39Sopenharmony_ci 171e1051a39Sopenharmony_ci *data->object = pkey; 172e1051a39Sopenharmony_ci 173e1051a39Sopenharmony_ci /* 174e1051a39Sopenharmony_ci * evp_keymgmt_util_make_pkey() increments the reference count when 175e1051a39Sopenharmony_ci * assigning the EVP_PKEY, so we can free the keymgmt here. 176e1051a39Sopenharmony_ci */ 177e1051a39Sopenharmony_ci EVP_KEYMGMT_free(keymgmt); 178e1051a39Sopenharmony_ci } 179e1051a39Sopenharmony_ci /* 180e1051a39Sopenharmony_ci * We successfully looked through, |*ctx->object| determines if we 181e1051a39Sopenharmony_ci * actually found something. 182e1051a39Sopenharmony_ci */ 183e1051a39Sopenharmony_ci return (*data->object != NULL); 184e1051a39Sopenharmony_ci} 185e1051a39Sopenharmony_ci 186e1051a39Sopenharmony_cistatic void decoder_clean_pkey_construct_arg(void *construct_data) 187e1051a39Sopenharmony_ci{ 188e1051a39Sopenharmony_ci struct decoder_pkey_data_st *data = construct_data; 189e1051a39Sopenharmony_ci 190e1051a39Sopenharmony_ci if (data != NULL) { 191e1051a39Sopenharmony_ci sk_EVP_KEYMGMT_pop_free(data->keymgmts, EVP_KEYMGMT_free); 192e1051a39Sopenharmony_ci OPENSSL_free(data->propq); 193e1051a39Sopenharmony_ci OPENSSL_free(data->object_type); 194e1051a39Sopenharmony_ci OPENSSL_free(data); 195e1051a39Sopenharmony_ci } 196e1051a39Sopenharmony_ci} 197e1051a39Sopenharmony_ci 198e1051a39Sopenharmony_cistatic void collect_name(const char *name, void *arg) 199e1051a39Sopenharmony_ci{ 200e1051a39Sopenharmony_ci STACK_OF(OPENSSL_CSTRING) *names = arg; 201e1051a39Sopenharmony_ci 202e1051a39Sopenharmony_ci sk_OPENSSL_CSTRING_push(names, name); 203e1051a39Sopenharmony_ci} 204e1051a39Sopenharmony_ci 205e1051a39Sopenharmony_cistatic void collect_keymgmt(EVP_KEYMGMT *keymgmt, void *arg) 206e1051a39Sopenharmony_ci{ 207e1051a39Sopenharmony_ci STACK_OF(EVP_KEYMGMT) *keymgmts = arg; 208e1051a39Sopenharmony_ci 209e1051a39Sopenharmony_ci if (!EVP_KEYMGMT_up_ref(keymgmt) /* ref++ */) 210e1051a39Sopenharmony_ci return; 211e1051a39Sopenharmony_ci if (sk_EVP_KEYMGMT_push(keymgmts, keymgmt) <= 0) { 212e1051a39Sopenharmony_ci EVP_KEYMGMT_free(keymgmt); /* ref-- */ 213e1051a39Sopenharmony_ci return; 214e1051a39Sopenharmony_ci } 215e1051a39Sopenharmony_ci} 216e1051a39Sopenharmony_ci 217e1051a39Sopenharmony_cistruct collect_decoder_data_st { 218e1051a39Sopenharmony_ci STACK_OF(OPENSSL_CSTRING) *names; 219e1051a39Sopenharmony_ci OSSL_DECODER_CTX *ctx; 220e1051a39Sopenharmony_ci 221e1051a39Sopenharmony_ci int total; 222e1051a39Sopenharmony_ci unsigned int error_occurred:1; 223e1051a39Sopenharmony_ci}; 224e1051a39Sopenharmony_ci 225e1051a39Sopenharmony_cistatic void collect_decoder(OSSL_DECODER *decoder, void *arg) 226e1051a39Sopenharmony_ci{ 227e1051a39Sopenharmony_ci struct collect_decoder_data_st *data = arg; 228e1051a39Sopenharmony_ci size_t i, end_i; 229e1051a39Sopenharmony_ci const OSSL_PROVIDER *prov = OSSL_DECODER_get0_provider(decoder); 230e1051a39Sopenharmony_ci void *provctx = OSSL_PROVIDER_get0_provider_ctx(prov); 231e1051a39Sopenharmony_ci 232e1051a39Sopenharmony_ci if (data->error_occurred) 233e1051a39Sopenharmony_ci return; 234e1051a39Sopenharmony_ci 235e1051a39Sopenharmony_ci if (data->names == NULL) { 236e1051a39Sopenharmony_ci data->error_occurred = 1; 237e1051a39Sopenharmony_ci return; 238e1051a39Sopenharmony_ci } 239e1051a39Sopenharmony_ci 240e1051a39Sopenharmony_ci /* 241e1051a39Sopenharmony_ci * Either the caller didn't give a selection, or if they did, 242e1051a39Sopenharmony_ci * the decoder must tell us if it supports that selection to 243e1051a39Sopenharmony_ci * be accepted. If the decoder doesn't have |does_selection|, 244e1051a39Sopenharmony_ci * it's seen as taking anything. 245e1051a39Sopenharmony_ci */ 246e1051a39Sopenharmony_ci if (decoder->does_selection != NULL 247e1051a39Sopenharmony_ci && !decoder->does_selection(provctx, data->ctx->selection)) 248e1051a39Sopenharmony_ci return; 249e1051a39Sopenharmony_ci 250e1051a39Sopenharmony_ci OSSL_TRACE_BEGIN(DECODER) { 251e1051a39Sopenharmony_ci BIO_printf(trc_out, 252e1051a39Sopenharmony_ci "(ctx %p) Checking out decoder %p:\n" 253e1051a39Sopenharmony_ci " %s with %s\n", 254e1051a39Sopenharmony_ci (void *)data->ctx, (void *)decoder, 255e1051a39Sopenharmony_ci OSSL_DECODER_get0_name(decoder), 256e1051a39Sopenharmony_ci OSSL_DECODER_get0_properties(decoder)); 257e1051a39Sopenharmony_ci } OSSL_TRACE_END(DECODER); 258e1051a39Sopenharmony_ci 259e1051a39Sopenharmony_ci end_i = sk_OPENSSL_CSTRING_num(data->names); 260e1051a39Sopenharmony_ci for (i = 0; i < end_i; i++) { 261e1051a39Sopenharmony_ci const char *name = sk_OPENSSL_CSTRING_value(data->names, i); 262e1051a39Sopenharmony_ci 263e1051a39Sopenharmony_ci if (OSSL_DECODER_is_a(decoder, name)) { 264e1051a39Sopenharmony_ci void *decoderctx = NULL; 265e1051a39Sopenharmony_ci OSSL_DECODER_INSTANCE *di = NULL; 266e1051a39Sopenharmony_ci 267e1051a39Sopenharmony_ci if ((decoderctx = decoder->newctx(provctx)) == NULL) { 268e1051a39Sopenharmony_ci data->error_occurred = 1; 269e1051a39Sopenharmony_ci return; 270e1051a39Sopenharmony_ci } 271e1051a39Sopenharmony_ci if ((di = ossl_decoder_instance_new(decoder, decoderctx)) == NULL) { 272e1051a39Sopenharmony_ci decoder->freectx(decoderctx); 273e1051a39Sopenharmony_ci data->error_occurred = 1; 274e1051a39Sopenharmony_ci return; 275e1051a39Sopenharmony_ci } 276e1051a39Sopenharmony_ci 277e1051a39Sopenharmony_ci OSSL_TRACE_BEGIN(DECODER) { 278e1051a39Sopenharmony_ci BIO_printf(trc_out, 279e1051a39Sopenharmony_ci "(ctx %p) Checking out decoder %p:\n" 280e1051a39Sopenharmony_ci " %s with %s\n", 281e1051a39Sopenharmony_ci (void *)data->ctx, (void *)decoder, 282e1051a39Sopenharmony_ci OSSL_DECODER_get0_name(decoder), 283e1051a39Sopenharmony_ci OSSL_DECODER_get0_properties(decoder)); 284e1051a39Sopenharmony_ci } OSSL_TRACE_END(DECODER); 285e1051a39Sopenharmony_ci 286e1051a39Sopenharmony_ci if (!ossl_decoder_ctx_add_decoder_inst(data->ctx, di)) { 287e1051a39Sopenharmony_ci ossl_decoder_instance_free(di); 288e1051a39Sopenharmony_ci data->error_occurred = 1; 289e1051a39Sopenharmony_ci return; 290e1051a39Sopenharmony_ci } 291e1051a39Sopenharmony_ci data->total++; 292e1051a39Sopenharmony_ci 293e1051a39Sopenharmony_ci /* Success */ 294e1051a39Sopenharmony_ci return; 295e1051a39Sopenharmony_ci } 296e1051a39Sopenharmony_ci } 297e1051a39Sopenharmony_ci 298e1051a39Sopenharmony_ci /* Decoder not suitable - but not a fatal error */ 299e1051a39Sopenharmony_ci data->error_occurred = 0; 300e1051a39Sopenharmony_ci} 301e1051a39Sopenharmony_ci 302e1051a39Sopenharmony_ciint ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx, 303e1051a39Sopenharmony_ci EVP_PKEY **pkey, const char *keytype, 304e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, 305e1051a39Sopenharmony_ci const char *propquery) 306e1051a39Sopenharmony_ci{ 307e1051a39Sopenharmony_ci struct decoder_pkey_data_st *process_data = NULL; 308e1051a39Sopenharmony_ci STACK_OF(OPENSSL_CSTRING) *names = NULL; 309e1051a39Sopenharmony_ci const char *input_type = ctx->start_input_type; 310e1051a39Sopenharmony_ci const char *input_structure = ctx->input_structure; 311e1051a39Sopenharmony_ci int ok = 0; 312e1051a39Sopenharmony_ci int isecoid = 0; 313e1051a39Sopenharmony_ci int i, end; 314e1051a39Sopenharmony_ci 315e1051a39Sopenharmony_ci if (keytype != NULL 316e1051a39Sopenharmony_ci && (strcmp(keytype, "id-ecPublicKey") == 0 317e1051a39Sopenharmony_ci || strcmp(keytype, "1.2.840.10045.2.1") == 0)) 318e1051a39Sopenharmony_ci isecoid = 1; 319e1051a39Sopenharmony_ci 320e1051a39Sopenharmony_ci OSSL_TRACE_BEGIN(DECODER) { 321e1051a39Sopenharmony_ci BIO_printf(trc_out, 322e1051a39Sopenharmony_ci "(ctx %p) Looking for decoders producing %s%s%s%s%s%s\n", 323e1051a39Sopenharmony_ci (void *)ctx, 324e1051a39Sopenharmony_ci keytype != NULL ? keytype : "", 325e1051a39Sopenharmony_ci keytype != NULL ? " keys" : "keys of any type", 326e1051a39Sopenharmony_ci input_type != NULL ? " from " : "", 327e1051a39Sopenharmony_ci input_type != NULL ? input_type : "", 328e1051a39Sopenharmony_ci input_structure != NULL ? " with " : "", 329e1051a39Sopenharmony_ci input_structure != NULL ? input_structure : ""); 330e1051a39Sopenharmony_ci } OSSL_TRACE_END(DECODER); 331e1051a39Sopenharmony_ci 332e1051a39Sopenharmony_ci if ((process_data = OPENSSL_zalloc(sizeof(*process_data))) == NULL 333e1051a39Sopenharmony_ci || (propquery != NULL 334e1051a39Sopenharmony_ci && (process_data->propq = OPENSSL_strdup(propquery)) == NULL) 335e1051a39Sopenharmony_ci || (process_data->keymgmts = sk_EVP_KEYMGMT_new_null()) == NULL 336e1051a39Sopenharmony_ci || (names = sk_OPENSSL_CSTRING_new_null()) == NULL) { 337e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); 338e1051a39Sopenharmony_ci goto err; 339e1051a39Sopenharmony_ci } 340e1051a39Sopenharmony_ci 341e1051a39Sopenharmony_ci process_data->object = (void **)pkey; 342e1051a39Sopenharmony_ci process_data->libctx = libctx; 343e1051a39Sopenharmony_ci process_data->selection = ctx->selection; 344e1051a39Sopenharmony_ci 345e1051a39Sopenharmony_ci /* First, find all keymgmts to form goals */ 346e1051a39Sopenharmony_ci EVP_KEYMGMT_do_all_provided(libctx, collect_keymgmt, 347e1051a39Sopenharmony_ci process_data->keymgmts); 348e1051a39Sopenharmony_ci 349e1051a39Sopenharmony_ci /* Then, we collect all the keymgmt names */ 350e1051a39Sopenharmony_ci end = sk_EVP_KEYMGMT_num(process_data->keymgmts); 351e1051a39Sopenharmony_ci for (i = 0; i < end; i++) { 352e1051a39Sopenharmony_ci EVP_KEYMGMT *keymgmt = sk_EVP_KEYMGMT_value(process_data->keymgmts, i); 353e1051a39Sopenharmony_ci 354e1051a39Sopenharmony_ci /* 355e1051a39Sopenharmony_ci * If the key type is given by the caller, we only use the matching 356e1051a39Sopenharmony_ci * KEYMGMTs, otherwise we use them all. 357e1051a39Sopenharmony_ci * We have to special case SM2 here because of its abuse of the EC OID. 358e1051a39Sopenharmony_ci * The EC OID can be used to identify an EC key or an SM2 key - so if 359e1051a39Sopenharmony_ci * we have seen that OID we try both key types 360e1051a39Sopenharmony_ci */ 361e1051a39Sopenharmony_ci if (keytype == NULL 362e1051a39Sopenharmony_ci || EVP_KEYMGMT_is_a(keymgmt, keytype) 363e1051a39Sopenharmony_ci || (isecoid && EVP_KEYMGMT_is_a(keymgmt, "SM2"))) { 364e1051a39Sopenharmony_ci if (!EVP_KEYMGMT_names_do_all(keymgmt, collect_name, names)) { 365e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INTERNAL_ERROR); 366e1051a39Sopenharmony_ci goto err; 367e1051a39Sopenharmony_ci } 368e1051a39Sopenharmony_ci } 369e1051a39Sopenharmony_ci } 370e1051a39Sopenharmony_ci 371e1051a39Sopenharmony_ci OSSL_TRACE_BEGIN(DECODER) { 372e1051a39Sopenharmony_ci end = sk_OPENSSL_CSTRING_num(names); 373e1051a39Sopenharmony_ci BIO_printf(trc_out, 374e1051a39Sopenharmony_ci " Found %d keytypes (possibly with duplicates)", 375e1051a39Sopenharmony_ci end); 376e1051a39Sopenharmony_ci for (i = 0; i < end; i++) 377e1051a39Sopenharmony_ci BIO_printf(trc_out, "%s%s", 378e1051a39Sopenharmony_ci i == 0 ? ": " : ", ", 379e1051a39Sopenharmony_ci sk_OPENSSL_CSTRING_value(names, i)); 380e1051a39Sopenharmony_ci BIO_printf(trc_out, "\n"); 381e1051a39Sopenharmony_ci } OSSL_TRACE_END(DECODER); 382e1051a39Sopenharmony_ci 383e1051a39Sopenharmony_ci /* 384e1051a39Sopenharmony_ci * Finally, find all decoders that have any keymgmt of the collected 385e1051a39Sopenharmony_ci * keymgmt names 386e1051a39Sopenharmony_ci */ 387e1051a39Sopenharmony_ci { 388e1051a39Sopenharmony_ci struct collect_decoder_data_st collect_decoder_data = { NULL, }; 389e1051a39Sopenharmony_ci 390e1051a39Sopenharmony_ci collect_decoder_data.names = names; 391e1051a39Sopenharmony_ci collect_decoder_data.ctx = ctx; 392e1051a39Sopenharmony_ci OSSL_DECODER_do_all_provided(libctx, 393e1051a39Sopenharmony_ci collect_decoder, &collect_decoder_data); 394e1051a39Sopenharmony_ci sk_OPENSSL_CSTRING_free(names); 395e1051a39Sopenharmony_ci names = NULL; 396e1051a39Sopenharmony_ci 397e1051a39Sopenharmony_ci if (collect_decoder_data.error_occurred) 398e1051a39Sopenharmony_ci goto err; 399e1051a39Sopenharmony_ci 400e1051a39Sopenharmony_ci OSSL_TRACE_BEGIN(DECODER) { 401e1051a39Sopenharmony_ci BIO_printf(trc_out, 402e1051a39Sopenharmony_ci "(ctx %p) Got %d decoders producing keys\n", 403e1051a39Sopenharmony_ci (void *)ctx, collect_decoder_data.total); 404e1051a39Sopenharmony_ci } OSSL_TRACE_END(DECODER); 405e1051a39Sopenharmony_ci } 406e1051a39Sopenharmony_ci 407e1051a39Sopenharmony_ci if (OSSL_DECODER_CTX_get_num_decoders(ctx) != 0) { 408e1051a39Sopenharmony_ci if (!OSSL_DECODER_CTX_set_construct(ctx, decoder_construct_pkey) 409e1051a39Sopenharmony_ci || !OSSL_DECODER_CTX_set_construct_data(ctx, process_data) 410e1051a39Sopenharmony_ci || !OSSL_DECODER_CTX_set_cleanup(ctx, 411e1051a39Sopenharmony_ci decoder_clean_pkey_construct_arg)) 412e1051a39Sopenharmony_ci goto err; 413e1051a39Sopenharmony_ci 414e1051a39Sopenharmony_ci process_data = NULL; /* Avoid it being freed */ 415e1051a39Sopenharmony_ci } 416e1051a39Sopenharmony_ci 417e1051a39Sopenharmony_ci ok = 1; 418e1051a39Sopenharmony_ci err: 419e1051a39Sopenharmony_ci decoder_clean_pkey_construct_arg(process_data); 420e1051a39Sopenharmony_ci sk_OPENSSL_CSTRING_free(names); 421e1051a39Sopenharmony_ci 422e1051a39Sopenharmony_ci return ok; 423e1051a39Sopenharmony_ci} 424e1051a39Sopenharmony_ci 425e1051a39Sopenharmony_ciOSSL_DECODER_CTX * 426e1051a39Sopenharmony_ciOSSL_DECODER_CTX_new_for_pkey(EVP_PKEY **pkey, 427e1051a39Sopenharmony_ci const char *input_type, 428e1051a39Sopenharmony_ci const char *input_structure, 429e1051a39Sopenharmony_ci const char *keytype, int selection, 430e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propquery) 431e1051a39Sopenharmony_ci{ 432e1051a39Sopenharmony_ci OSSL_DECODER_CTX *ctx = NULL; 433e1051a39Sopenharmony_ci 434e1051a39Sopenharmony_ci if ((ctx = OSSL_DECODER_CTX_new()) == NULL) { 435e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); 436e1051a39Sopenharmony_ci return NULL; 437e1051a39Sopenharmony_ci } 438e1051a39Sopenharmony_ci 439e1051a39Sopenharmony_ci OSSL_TRACE_BEGIN(DECODER) { 440e1051a39Sopenharmony_ci BIO_printf(trc_out, 441e1051a39Sopenharmony_ci "(ctx %p) Looking for %s decoders with selection %d\n", 442e1051a39Sopenharmony_ci (void *)ctx, keytype, selection); 443e1051a39Sopenharmony_ci BIO_printf(trc_out, " input type: %s, input structure: %s\n", 444e1051a39Sopenharmony_ci input_type, input_structure); 445e1051a39Sopenharmony_ci } OSSL_TRACE_END(DECODER); 446e1051a39Sopenharmony_ci 447e1051a39Sopenharmony_ci if (OSSL_DECODER_CTX_set_input_type(ctx, input_type) 448e1051a39Sopenharmony_ci && OSSL_DECODER_CTX_set_input_structure(ctx, input_structure) 449e1051a39Sopenharmony_ci && OSSL_DECODER_CTX_set_selection(ctx, selection) 450e1051a39Sopenharmony_ci && ossl_decoder_ctx_setup_for_pkey(ctx, pkey, keytype, 451e1051a39Sopenharmony_ci libctx, propquery) 452e1051a39Sopenharmony_ci && OSSL_DECODER_CTX_add_extra(ctx, libctx, propquery)) { 453e1051a39Sopenharmony_ci OSSL_TRACE_BEGIN(DECODER) { 454e1051a39Sopenharmony_ci BIO_printf(trc_out, "(ctx %p) Got %d decoders\n", 455e1051a39Sopenharmony_ci (void *)ctx, OSSL_DECODER_CTX_get_num_decoders(ctx)); 456e1051a39Sopenharmony_ci } OSSL_TRACE_END(DECODER); 457e1051a39Sopenharmony_ci return ctx; 458e1051a39Sopenharmony_ci } 459e1051a39Sopenharmony_ci 460e1051a39Sopenharmony_ci OSSL_DECODER_CTX_free(ctx); 461e1051a39Sopenharmony_ci return NULL; 462e1051a39Sopenharmony_ci} 463