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 "e_os.h" 11e1051a39Sopenharmony_ci#include <string.h> 12e1051a39Sopenharmony_ci 13e1051a39Sopenharmony_ci#include <openssl/core.h> 14e1051a39Sopenharmony_ci#include <openssl/core_names.h> 15e1051a39Sopenharmony_ci#include <openssl/core_object.h> 16e1051a39Sopenharmony_ci#include <openssl/err.h> 17e1051a39Sopenharmony_ci#include <openssl/pkcs12.h> 18e1051a39Sopenharmony_ci#include <openssl/provider.h> 19e1051a39Sopenharmony_ci#include <openssl/decoder.h> 20e1051a39Sopenharmony_ci#include <openssl/store.h> 21e1051a39Sopenharmony_ci#include "internal/provider.h" 22e1051a39Sopenharmony_ci#include "internal/passphrase.h" 23e1051a39Sopenharmony_ci#include "crypto/evp.h" 24e1051a39Sopenharmony_ci#include "crypto/x509.h" 25e1051a39Sopenharmony_ci#include "store_local.h" 26e1051a39Sopenharmony_ci 27e1051a39Sopenharmony_ci#ifndef OSSL_OBJECT_PKCS12 28e1051a39Sopenharmony_ci/* 29e1051a39Sopenharmony_ci * The object abstraction doesn't know PKCS#12, but we want to indicate 30e1051a39Sopenharmony_ci * it anyway, so we create our own. Since the public macros use positive 31e1051a39Sopenharmony_ci * numbers, negative ones should be fine. They must never slip out from 32e1051a39Sopenharmony_ci * this translation unit anyway. 33e1051a39Sopenharmony_ci */ 34e1051a39Sopenharmony_ci# define OSSL_OBJECT_PKCS12 -1 35e1051a39Sopenharmony_ci#endif 36e1051a39Sopenharmony_ci 37e1051a39Sopenharmony_ci/* 38e1051a39Sopenharmony_ci * ossl_store_handle_load_result() is initially written to be a companion 39e1051a39Sopenharmony_ci * to our 'file:' scheme provider implementation, but has been made generic 40e1051a39Sopenharmony_ci * to serve others as well. 41e1051a39Sopenharmony_ci * 42e1051a39Sopenharmony_ci * This result handler takes any object abstraction (see provider-object(7)) 43e1051a39Sopenharmony_ci * and does the best it can with it. If the object is passed by value (not 44e1051a39Sopenharmony_ci * by reference), the contents are currently expected to be DER encoded. 45e1051a39Sopenharmony_ci * If an object type is specified, that will be respected; otherwise, this 46e1051a39Sopenharmony_ci * handler will guess the contents, by trying the following in order: 47e1051a39Sopenharmony_ci * 48e1051a39Sopenharmony_ci * 1. Decode it into an EVP_PKEY, using OSSL_DECODER. 49e1051a39Sopenharmony_ci * 2. Decode it into an X.509 certificate, using d2i_X509 / d2i_X509_AUX. 50e1051a39Sopenharmony_ci * 3. Decode it into an X.509 CRL, using d2i_X509_CRL. 51e1051a39Sopenharmony_ci * 4. Decode it into a PKCS#12 structure, using d2i_PKCS12 (*). 52e1051a39Sopenharmony_ci * 53e1051a39Sopenharmony_ci * For the 'file:' scheme implementation, this is division of labor. Since 54e1051a39Sopenharmony_ci * the libcrypto <-> provider interface currently doesn't support certain 55e1051a39Sopenharmony_ci * structures as first class objects, they must be unpacked from DER here 56e1051a39Sopenharmony_ci * rather than in the provider. The current exception is asymmetric keys, 57e1051a39Sopenharmony_ci * which can reside within the provider boundary, most of all thanks to 58e1051a39Sopenharmony_ci * OSSL_FUNC_keymgmt_load(), which allows loading the key material by 59e1051a39Sopenharmony_ci * reference. 60e1051a39Sopenharmony_ci */ 61e1051a39Sopenharmony_ci 62e1051a39Sopenharmony_cistruct extracted_param_data_st { 63e1051a39Sopenharmony_ci int object_type; 64e1051a39Sopenharmony_ci const char *data_type; 65e1051a39Sopenharmony_ci const char *data_structure; 66e1051a39Sopenharmony_ci const char *utf8_data; 67e1051a39Sopenharmony_ci const void *octet_data; 68e1051a39Sopenharmony_ci size_t octet_data_size; 69e1051a39Sopenharmony_ci const void *ref; 70e1051a39Sopenharmony_ci size_t ref_size; 71e1051a39Sopenharmony_ci const char *desc; 72e1051a39Sopenharmony_ci}; 73e1051a39Sopenharmony_ci 74e1051a39Sopenharmony_cistatic int try_name(struct extracted_param_data_st *, OSSL_STORE_INFO **); 75e1051a39Sopenharmony_cistatic int try_key(struct extracted_param_data_st *, OSSL_STORE_INFO **, 76e1051a39Sopenharmony_ci OSSL_STORE_CTX *, const OSSL_PROVIDER *, 77e1051a39Sopenharmony_ci OSSL_LIB_CTX *, const char *); 78e1051a39Sopenharmony_cistatic int try_cert(struct extracted_param_data_st *, OSSL_STORE_INFO **, 79e1051a39Sopenharmony_ci OSSL_LIB_CTX *, const char *); 80e1051a39Sopenharmony_cistatic int try_crl(struct extracted_param_data_st *, OSSL_STORE_INFO **, 81e1051a39Sopenharmony_ci OSSL_LIB_CTX *, const char *); 82e1051a39Sopenharmony_cistatic int try_pkcs12(struct extracted_param_data_st *, OSSL_STORE_INFO **, 83e1051a39Sopenharmony_ci OSSL_STORE_CTX *, OSSL_LIB_CTX *, const char *); 84e1051a39Sopenharmony_ci 85e1051a39Sopenharmony_ciint ossl_store_handle_load_result(const OSSL_PARAM params[], void *arg) 86e1051a39Sopenharmony_ci{ 87e1051a39Sopenharmony_ci struct ossl_load_result_data_st *cbdata = arg; 88e1051a39Sopenharmony_ci OSSL_STORE_INFO **v = &cbdata->v; 89e1051a39Sopenharmony_ci OSSL_STORE_CTX *ctx = cbdata->ctx; 90e1051a39Sopenharmony_ci const OSSL_PROVIDER *provider = 91e1051a39Sopenharmony_ci OSSL_STORE_LOADER_get0_provider(ctx->fetched_loader); 92e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx = ossl_provider_libctx(provider); 93e1051a39Sopenharmony_ci const char *propq = ctx->properties; 94e1051a39Sopenharmony_ci const OSSL_PARAM *p; 95e1051a39Sopenharmony_ci struct extracted_param_data_st helper_data; 96e1051a39Sopenharmony_ci 97e1051a39Sopenharmony_ci memset(&helper_data, 0, sizeof(helper_data)); 98e1051a39Sopenharmony_ci helper_data.object_type = OSSL_OBJECT_UNKNOWN; 99e1051a39Sopenharmony_ci 100e1051a39Sopenharmony_ci if ((p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_TYPE)) != NULL 101e1051a39Sopenharmony_ci && !OSSL_PARAM_get_int(p, &helper_data.object_type)) 102e1051a39Sopenharmony_ci return 0; 103e1051a39Sopenharmony_ci p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA_TYPE); 104e1051a39Sopenharmony_ci if (p != NULL 105e1051a39Sopenharmony_ci && !OSSL_PARAM_get_utf8_string_ptr(p, &helper_data.data_type)) 106e1051a39Sopenharmony_ci return 0; 107e1051a39Sopenharmony_ci p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA); 108e1051a39Sopenharmony_ci if (p != NULL 109e1051a39Sopenharmony_ci && !OSSL_PARAM_get_octet_string_ptr(p, &helper_data.octet_data, 110e1051a39Sopenharmony_ci &helper_data.octet_data_size) 111e1051a39Sopenharmony_ci && !OSSL_PARAM_get_utf8_string_ptr(p, &helper_data.utf8_data)) 112e1051a39Sopenharmony_ci return 0; 113e1051a39Sopenharmony_ci p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA_STRUCTURE); 114e1051a39Sopenharmony_ci if (p != NULL 115e1051a39Sopenharmony_ci && !OSSL_PARAM_get_utf8_string_ptr(p, &helper_data.data_structure)) 116e1051a39Sopenharmony_ci return 0; 117e1051a39Sopenharmony_ci p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_REFERENCE); 118e1051a39Sopenharmony_ci if (p != NULL && !OSSL_PARAM_get_octet_string_ptr(p, &helper_data.ref, 119e1051a39Sopenharmony_ci &helper_data.ref_size)) 120e1051a39Sopenharmony_ci return 0; 121e1051a39Sopenharmony_ci p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DESC); 122e1051a39Sopenharmony_ci if (p != NULL && !OSSL_PARAM_get_utf8_string_ptr(p, &helper_data.desc)) 123e1051a39Sopenharmony_ci return 0; 124e1051a39Sopenharmony_ci 125e1051a39Sopenharmony_ci /* 126e1051a39Sopenharmony_ci * The helper functions return 0 on actual errors, otherwise 1, even if 127e1051a39Sopenharmony_ci * they didn't fill out |*v|. 128e1051a39Sopenharmony_ci */ 129e1051a39Sopenharmony_ci ERR_set_mark(); 130e1051a39Sopenharmony_ci if (*v == NULL && !try_name(&helper_data, v)) 131e1051a39Sopenharmony_ci goto err; 132e1051a39Sopenharmony_ci ERR_pop_to_mark(); 133e1051a39Sopenharmony_ci ERR_set_mark(); 134e1051a39Sopenharmony_ci if (*v == NULL && !try_key(&helper_data, v, ctx, provider, libctx, propq)) 135e1051a39Sopenharmony_ci goto err; 136e1051a39Sopenharmony_ci ERR_pop_to_mark(); 137e1051a39Sopenharmony_ci ERR_set_mark(); 138e1051a39Sopenharmony_ci if (*v == NULL && !try_cert(&helper_data, v, libctx, propq)) 139e1051a39Sopenharmony_ci goto err; 140e1051a39Sopenharmony_ci ERR_pop_to_mark(); 141e1051a39Sopenharmony_ci ERR_set_mark(); 142e1051a39Sopenharmony_ci if (*v == NULL && !try_crl(&helper_data, v, libctx, propq)) 143e1051a39Sopenharmony_ci goto err; 144e1051a39Sopenharmony_ci ERR_pop_to_mark(); 145e1051a39Sopenharmony_ci ERR_set_mark(); 146e1051a39Sopenharmony_ci if (*v == NULL && !try_pkcs12(&helper_data, v, ctx, libctx, propq)) 147e1051a39Sopenharmony_ci goto err; 148e1051a39Sopenharmony_ci ERR_pop_to_mark(); 149e1051a39Sopenharmony_ci 150e1051a39Sopenharmony_ci if (*v == NULL) 151e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_UNSUPPORTED); 152e1051a39Sopenharmony_ci 153e1051a39Sopenharmony_ci return (*v != NULL); 154e1051a39Sopenharmony_ci err: 155e1051a39Sopenharmony_ci ERR_clear_last_mark(); 156e1051a39Sopenharmony_ci return 0; 157e1051a39Sopenharmony_ci} 158e1051a39Sopenharmony_ci 159e1051a39Sopenharmony_cistatic int try_name(struct extracted_param_data_st *data, OSSL_STORE_INFO **v) 160e1051a39Sopenharmony_ci{ 161e1051a39Sopenharmony_ci if (data->object_type == OSSL_OBJECT_NAME) { 162e1051a39Sopenharmony_ci char *newname = NULL, *newdesc = NULL; 163e1051a39Sopenharmony_ci 164e1051a39Sopenharmony_ci if (data->utf8_data == NULL) 165e1051a39Sopenharmony_ci return 0; 166e1051a39Sopenharmony_ci if ((newname = OPENSSL_strdup(data->utf8_data)) == NULL 167e1051a39Sopenharmony_ci || (data->desc != NULL 168e1051a39Sopenharmony_ci && (newdesc = OPENSSL_strdup(data->desc)) == NULL) 169e1051a39Sopenharmony_ci || (*v = OSSL_STORE_INFO_new_NAME(newname)) == NULL) { 170e1051a39Sopenharmony_ci OPENSSL_free(newname); 171e1051a39Sopenharmony_ci OPENSSL_free(newdesc); 172e1051a39Sopenharmony_ci return 0; 173e1051a39Sopenharmony_ci } 174e1051a39Sopenharmony_ci OSSL_STORE_INFO_set0_NAME_description(*v, newdesc); 175e1051a39Sopenharmony_ci } 176e1051a39Sopenharmony_ci return 1; 177e1051a39Sopenharmony_ci} 178e1051a39Sopenharmony_ci 179e1051a39Sopenharmony_ci/* 180e1051a39Sopenharmony_ci * For the rest of the object types, the provider code may not know what 181e1051a39Sopenharmony_ci * type of data it gave us, so we may need to figure that out on our own. 182e1051a39Sopenharmony_ci * Therefore, we do check for OSSL_OBJECT_UNKNOWN everywhere below, and 183e1051a39Sopenharmony_ci * only return 0 on error if the object type is known. 184e1051a39Sopenharmony_ci */ 185e1051a39Sopenharmony_ci 186e1051a39Sopenharmony_cistatic EVP_PKEY *try_key_ref(struct extracted_param_data_st *data, 187e1051a39Sopenharmony_ci OSSL_STORE_CTX *ctx, 188e1051a39Sopenharmony_ci const OSSL_PROVIDER *provider, 189e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 190e1051a39Sopenharmony_ci{ 191e1051a39Sopenharmony_ci EVP_PKEY *pk = NULL; 192e1051a39Sopenharmony_ci EVP_KEYMGMT *keymgmt = NULL; 193e1051a39Sopenharmony_ci void *keydata = NULL; 194e1051a39Sopenharmony_ci int try_fallback = 2; 195e1051a39Sopenharmony_ci 196e1051a39Sopenharmony_ci /* If we have an object reference, we must have a data type */ 197e1051a39Sopenharmony_ci if (data->data_type == NULL) 198e1051a39Sopenharmony_ci return 0; 199e1051a39Sopenharmony_ci 200e1051a39Sopenharmony_ci keymgmt = EVP_KEYMGMT_fetch(libctx, data->data_type, propq); 201e1051a39Sopenharmony_ci ERR_set_mark(); 202e1051a39Sopenharmony_ci while (keymgmt != NULL && keydata == NULL && try_fallback-- > 0) { 203e1051a39Sopenharmony_ci /* 204e1051a39Sopenharmony_ci * There are two possible cases 205e1051a39Sopenharmony_ci * 206e1051a39Sopenharmony_ci * 1. The keymgmt is from the same provider as the loader, 207e1051a39Sopenharmony_ci * so we can use evp_keymgmt_load() 208e1051a39Sopenharmony_ci * 2. The keymgmt is from another provider, then we must 209e1051a39Sopenharmony_ci * do the export/import dance. 210e1051a39Sopenharmony_ci */ 211e1051a39Sopenharmony_ci if (EVP_KEYMGMT_get0_provider(keymgmt) == provider) { 212e1051a39Sopenharmony_ci /* no point trying fallback here */ 213e1051a39Sopenharmony_ci try_fallback = 0; 214e1051a39Sopenharmony_ci keydata = evp_keymgmt_load(keymgmt, data->ref, data->ref_size); 215e1051a39Sopenharmony_ci } else { 216e1051a39Sopenharmony_ci struct evp_keymgmt_util_try_import_data_st import_data; 217e1051a39Sopenharmony_ci OSSL_FUNC_store_export_object_fn *export_object = 218e1051a39Sopenharmony_ci ctx->fetched_loader->p_export_object; 219e1051a39Sopenharmony_ci 220e1051a39Sopenharmony_ci import_data.keymgmt = keymgmt; 221e1051a39Sopenharmony_ci import_data.keydata = NULL; 222e1051a39Sopenharmony_ci import_data.selection = OSSL_KEYMGMT_SELECT_ALL; 223e1051a39Sopenharmony_ci 224e1051a39Sopenharmony_ci if (export_object != NULL) { 225e1051a39Sopenharmony_ci /* 226e1051a39Sopenharmony_ci * No need to check for errors here, the value of 227e1051a39Sopenharmony_ci * |import_data.keydata| is as much an indicator. 228e1051a39Sopenharmony_ci */ 229e1051a39Sopenharmony_ci (void)export_object(ctx->loader_ctx, 230e1051a39Sopenharmony_ci data->ref, data->ref_size, 231e1051a39Sopenharmony_ci &evp_keymgmt_util_try_import, 232e1051a39Sopenharmony_ci &import_data); 233e1051a39Sopenharmony_ci } 234e1051a39Sopenharmony_ci 235e1051a39Sopenharmony_ci keydata = import_data.keydata; 236e1051a39Sopenharmony_ci } 237e1051a39Sopenharmony_ci 238e1051a39Sopenharmony_ci if (keydata == NULL && try_fallback > 0) { 239e1051a39Sopenharmony_ci EVP_KEYMGMT_free(keymgmt); 240e1051a39Sopenharmony_ci keymgmt = evp_keymgmt_fetch_from_prov((OSSL_PROVIDER *)provider, 241e1051a39Sopenharmony_ci data->data_type, propq); 242e1051a39Sopenharmony_ci if (keymgmt != NULL) { 243e1051a39Sopenharmony_ci ERR_pop_to_mark(); 244e1051a39Sopenharmony_ci ERR_set_mark(); 245e1051a39Sopenharmony_ci } 246e1051a39Sopenharmony_ci } 247e1051a39Sopenharmony_ci } 248e1051a39Sopenharmony_ci if (keydata != NULL) { 249e1051a39Sopenharmony_ci ERR_pop_to_mark(); 250e1051a39Sopenharmony_ci pk = evp_keymgmt_util_make_pkey(keymgmt, keydata); 251e1051a39Sopenharmony_ci } else { 252e1051a39Sopenharmony_ci ERR_clear_last_mark(); 253e1051a39Sopenharmony_ci } 254e1051a39Sopenharmony_ci EVP_KEYMGMT_free(keymgmt); 255e1051a39Sopenharmony_ci 256e1051a39Sopenharmony_ci return pk; 257e1051a39Sopenharmony_ci} 258e1051a39Sopenharmony_ci 259e1051a39Sopenharmony_cistatic EVP_PKEY *try_key_value(struct extracted_param_data_st *data, 260e1051a39Sopenharmony_ci OSSL_STORE_CTX *ctx, 261e1051a39Sopenharmony_ci OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg, 262e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 263e1051a39Sopenharmony_ci{ 264e1051a39Sopenharmony_ci EVP_PKEY *pk = NULL; 265e1051a39Sopenharmony_ci OSSL_DECODER_CTX *decoderctx = NULL; 266e1051a39Sopenharmony_ci const unsigned char *pdata = data->octet_data; 267e1051a39Sopenharmony_ci size_t pdatalen = data->octet_data_size; 268e1051a39Sopenharmony_ci int selection = 0; 269e1051a39Sopenharmony_ci 270e1051a39Sopenharmony_ci switch (ctx->expected_type) { 271e1051a39Sopenharmony_ci case 0: 272e1051a39Sopenharmony_ci break; 273e1051a39Sopenharmony_ci case OSSL_STORE_INFO_PARAMS: 274e1051a39Sopenharmony_ci selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS; 275e1051a39Sopenharmony_ci break; 276e1051a39Sopenharmony_ci case OSSL_STORE_INFO_PUBKEY: 277e1051a39Sopenharmony_ci selection = 278e1051a39Sopenharmony_ci OSSL_KEYMGMT_SELECT_PUBLIC_KEY 279e1051a39Sopenharmony_ci | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS; 280e1051a39Sopenharmony_ci break; 281e1051a39Sopenharmony_ci case OSSL_STORE_INFO_PKEY: 282e1051a39Sopenharmony_ci selection = OSSL_KEYMGMT_SELECT_ALL; 283e1051a39Sopenharmony_ci break; 284e1051a39Sopenharmony_ci default: 285e1051a39Sopenharmony_ci return NULL; 286e1051a39Sopenharmony_ci } 287e1051a39Sopenharmony_ci 288e1051a39Sopenharmony_ci decoderctx = 289e1051a39Sopenharmony_ci OSSL_DECODER_CTX_new_for_pkey(&pk, NULL, data->data_structure, 290e1051a39Sopenharmony_ci data->data_type, selection, libctx, 291e1051a39Sopenharmony_ci propq); 292e1051a39Sopenharmony_ci (void)OSSL_DECODER_CTX_set_passphrase_cb(decoderctx, cb, cbarg); 293e1051a39Sopenharmony_ci 294e1051a39Sopenharmony_ci /* No error if this couldn't be decoded */ 295e1051a39Sopenharmony_ci (void)OSSL_DECODER_from_data(decoderctx, &pdata, &pdatalen); 296e1051a39Sopenharmony_ci 297e1051a39Sopenharmony_ci OSSL_DECODER_CTX_free(decoderctx); 298e1051a39Sopenharmony_ci 299e1051a39Sopenharmony_ci return pk; 300e1051a39Sopenharmony_ci} 301e1051a39Sopenharmony_ci 302e1051a39Sopenharmony_citypedef OSSL_STORE_INFO *store_info_new_fn(EVP_PKEY *); 303e1051a39Sopenharmony_ci 304e1051a39Sopenharmony_cistatic EVP_PKEY *try_key_value_legacy(struct extracted_param_data_st *data, 305e1051a39Sopenharmony_ci store_info_new_fn **store_info_new, 306e1051a39Sopenharmony_ci OSSL_STORE_CTX *ctx, 307e1051a39Sopenharmony_ci OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg, 308e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 309e1051a39Sopenharmony_ci{ 310e1051a39Sopenharmony_ci EVP_PKEY *pk = NULL; 311e1051a39Sopenharmony_ci const unsigned char *der = data->octet_data, *derp; 312e1051a39Sopenharmony_ci long der_len = (long)data->octet_data_size; 313e1051a39Sopenharmony_ci 314e1051a39Sopenharmony_ci /* Try PUBKEY first, that's a real easy target */ 315e1051a39Sopenharmony_ci if (ctx->expected_type == 0 316e1051a39Sopenharmony_ci || ctx->expected_type == OSSL_STORE_INFO_PUBKEY) { 317e1051a39Sopenharmony_ci derp = der; 318e1051a39Sopenharmony_ci pk = d2i_PUBKEY_ex(NULL, &derp, der_len, libctx, propq); 319e1051a39Sopenharmony_ci 320e1051a39Sopenharmony_ci if (pk != NULL) 321e1051a39Sopenharmony_ci *store_info_new = OSSL_STORE_INFO_new_PUBKEY; 322e1051a39Sopenharmony_ci } 323e1051a39Sopenharmony_ci 324e1051a39Sopenharmony_ci /* Try private keys next */ 325e1051a39Sopenharmony_ci if (pk == NULL 326e1051a39Sopenharmony_ci && (ctx->expected_type == 0 327e1051a39Sopenharmony_ci || ctx->expected_type == OSSL_STORE_INFO_PKEY)) { 328e1051a39Sopenharmony_ci unsigned char *new_der = NULL; 329e1051a39Sopenharmony_ci X509_SIG *p8 = NULL; 330e1051a39Sopenharmony_ci PKCS8_PRIV_KEY_INFO *p8info = NULL; 331e1051a39Sopenharmony_ci 332e1051a39Sopenharmony_ci /* See if it's an encrypted PKCS#8 and decrypt it. */ 333e1051a39Sopenharmony_ci derp = der; 334e1051a39Sopenharmony_ci p8 = d2i_X509_SIG(NULL, &derp, der_len); 335e1051a39Sopenharmony_ci 336e1051a39Sopenharmony_ci if (p8 != NULL) { 337e1051a39Sopenharmony_ci char pbuf[PEM_BUFSIZE]; 338e1051a39Sopenharmony_ci size_t plen = 0; 339e1051a39Sopenharmony_ci 340e1051a39Sopenharmony_ci if (!cb(pbuf, sizeof(pbuf), &plen, NULL, cbarg)) { 341e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_BAD_PASSWORD_READ); 342e1051a39Sopenharmony_ci } else { 343e1051a39Sopenharmony_ci const X509_ALGOR *alg = NULL; 344e1051a39Sopenharmony_ci const ASN1_OCTET_STRING *oct = NULL; 345e1051a39Sopenharmony_ci int len = 0; 346e1051a39Sopenharmony_ci 347e1051a39Sopenharmony_ci X509_SIG_get0(p8, &alg, &oct); 348e1051a39Sopenharmony_ci 349e1051a39Sopenharmony_ci /* 350e1051a39Sopenharmony_ci * No need to check the returned value, |new_der| 351e1051a39Sopenharmony_ci * will be NULL on error anyway. 352e1051a39Sopenharmony_ci */ 353e1051a39Sopenharmony_ci PKCS12_pbe_crypt(alg, pbuf, plen, 354e1051a39Sopenharmony_ci oct->data, oct->length, 355e1051a39Sopenharmony_ci &new_der, &len, 0); 356e1051a39Sopenharmony_ci der_len = len; 357e1051a39Sopenharmony_ci der = new_der; 358e1051a39Sopenharmony_ci } 359e1051a39Sopenharmony_ci X509_SIG_free(p8); 360e1051a39Sopenharmony_ci } 361e1051a39Sopenharmony_ci 362e1051a39Sopenharmony_ci /* 363e1051a39Sopenharmony_ci * If the encrypted PKCS#8 couldn't be decrypted, 364e1051a39Sopenharmony_ci * |der| is NULL 365e1051a39Sopenharmony_ci */ 366e1051a39Sopenharmony_ci if (der != NULL) { 367e1051a39Sopenharmony_ci /* Try to unpack an unencrypted PKCS#8, that's easy */ 368e1051a39Sopenharmony_ci derp = der; 369e1051a39Sopenharmony_ci p8info = d2i_PKCS8_PRIV_KEY_INFO(NULL, &derp, der_len); 370e1051a39Sopenharmony_ci 371e1051a39Sopenharmony_ci if (p8info != NULL) { 372e1051a39Sopenharmony_ci pk = EVP_PKCS82PKEY_ex(p8info, libctx, propq); 373e1051a39Sopenharmony_ci PKCS8_PRIV_KEY_INFO_free(p8info); 374e1051a39Sopenharmony_ci } 375e1051a39Sopenharmony_ci } 376e1051a39Sopenharmony_ci 377e1051a39Sopenharmony_ci if (pk != NULL) 378e1051a39Sopenharmony_ci *store_info_new = OSSL_STORE_INFO_new_PKEY; 379e1051a39Sopenharmony_ci 380e1051a39Sopenharmony_ci OPENSSL_free(new_der); 381e1051a39Sopenharmony_ci } 382e1051a39Sopenharmony_ci 383e1051a39Sopenharmony_ci return pk; 384e1051a39Sopenharmony_ci} 385e1051a39Sopenharmony_ci 386e1051a39Sopenharmony_cistatic int try_key(struct extracted_param_data_st *data, OSSL_STORE_INFO **v, 387e1051a39Sopenharmony_ci OSSL_STORE_CTX *ctx, const OSSL_PROVIDER *provider, 388e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 389e1051a39Sopenharmony_ci{ 390e1051a39Sopenharmony_ci store_info_new_fn *store_info_new = NULL; 391e1051a39Sopenharmony_ci 392e1051a39Sopenharmony_ci if (data->object_type == OSSL_OBJECT_UNKNOWN 393e1051a39Sopenharmony_ci || data->object_type == OSSL_OBJECT_PKEY) { 394e1051a39Sopenharmony_ci EVP_PKEY *pk = NULL; 395e1051a39Sopenharmony_ci 396e1051a39Sopenharmony_ci /* Prefer key by reference than key by value */ 397e1051a39Sopenharmony_ci if (data->object_type == OSSL_OBJECT_PKEY && data->ref != NULL) { 398e1051a39Sopenharmony_ci pk = try_key_ref(data, ctx, provider, libctx, propq); 399e1051a39Sopenharmony_ci 400e1051a39Sopenharmony_ci /* 401e1051a39Sopenharmony_ci * If for some reason we couldn't get a key, it's an error. 402e1051a39Sopenharmony_ci * It indicates that while decoders could make a key reference, 403e1051a39Sopenharmony_ci * the keymgmt somehow couldn't handle it, or doesn't have a 404e1051a39Sopenharmony_ci * OSSL_FUNC_keymgmt_load function. 405e1051a39Sopenharmony_ci */ 406e1051a39Sopenharmony_ci if (pk == NULL) 407e1051a39Sopenharmony_ci return 0; 408e1051a39Sopenharmony_ci } else if (data->octet_data != NULL) { 409e1051a39Sopenharmony_ci OSSL_PASSPHRASE_CALLBACK *cb = ossl_pw_passphrase_callback_dec; 410e1051a39Sopenharmony_ci void *cbarg = &ctx->pwdata; 411e1051a39Sopenharmony_ci 412e1051a39Sopenharmony_ci pk = try_key_value(data, ctx, cb, cbarg, libctx, propq); 413e1051a39Sopenharmony_ci 414e1051a39Sopenharmony_ci /* 415e1051a39Sopenharmony_ci * Desperate last maneuver, in case the decoders don't support 416e1051a39Sopenharmony_ci * the data we have, then we try on our own to at least get an 417e1051a39Sopenharmony_ci * engine provided legacy key. 418e1051a39Sopenharmony_ci * This is the same as der2key_decode() does, but in a limited 419e1051a39Sopenharmony_ci * way and within the walls of libcrypto. 420e1051a39Sopenharmony_ci */ 421e1051a39Sopenharmony_ci if (pk == NULL) 422e1051a39Sopenharmony_ci pk = try_key_value_legacy(data, &store_info_new, ctx, 423e1051a39Sopenharmony_ci cb, cbarg, libctx, propq); 424e1051a39Sopenharmony_ci } 425e1051a39Sopenharmony_ci 426e1051a39Sopenharmony_ci if (pk != NULL) { 427e1051a39Sopenharmony_ci data->object_type = OSSL_OBJECT_PKEY; 428e1051a39Sopenharmony_ci 429e1051a39Sopenharmony_ci if (store_info_new == NULL) { 430e1051a39Sopenharmony_ci /* 431e1051a39Sopenharmony_ci * We determined the object type for OSSL_STORE_INFO, which 432e1051a39Sopenharmony_ci * makes an explicit difference between an EVP_PKEY with just 433e1051a39Sopenharmony_ci * (domain) parameters and an EVP_PKEY with actual key 434e1051a39Sopenharmony_ci * material. 435e1051a39Sopenharmony_ci * The logic is that an EVP_PKEY with actual key material 436e1051a39Sopenharmony_ci * always has the public half. 437e1051a39Sopenharmony_ci */ 438e1051a39Sopenharmony_ci if (evp_keymgmt_util_has(pk, OSSL_KEYMGMT_SELECT_PRIVATE_KEY)) 439e1051a39Sopenharmony_ci store_info_new = OSSL_STORE_INFO_new_PKEY; 440e1051a39Sopenharmony_ci else if (evp_keymgmt_util_has(pk, 441e1051a39Sopenharmony_ci OSSL_KEYMGMT_SELECT_PUBLIC_KEY)) 442e1051a39Sopenharmony_ci store_info_new = OSSL_STORE_INFO_new_PUBKEY; 443e1051a39Sopenharmony_ci else 444e1051a39Sopenharmony_ci store_info_new = OSSL_STORE_INFO_new_PARAMS; 445e1051a39Sopenharmony_ci } 446e1051a39Sopenharmony_ci *v = store_info_new(pk); 447e1051a39Sopenharmony_ci } 448e1051a39Sopenharmony_ci 449e1051a39Sopenharmony_ci if (*v == NULL) 450e1051a39Sopenharmony_ci EVP_PKEY_free(pk); 451e1051a39Sopenharmony_ci } 452e1051a39Sopenharmony_ci 453e1051a39Sopenharmony_ci return 1; 454e1051a39Sopenharmony_ci} 455e1051a39Sopenharmony_ci 456e1051a39Sopenharmony_cistatic int try_cert(struct extracted_param_data_st *data, OSSL_STORE_INFO **v, 457e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 458e1051a39Sopenharmony_ci{ 459e1051a39Sopenharmony_ci if (data->object_type == OSSL_OBJECT_UNKNOWN 460e1051a39Sopenharmony_ci || data->object_type == OSSL_OBJECT_CERT) { 461e1051a39Sopenharmony_ci /* 462e1051a39Sopenharmony_ci * In most cases, we can try to interpret the serialized 463e1051a39Sopenharmony_ci * data as a trusted cert (X509 + X509_AUX) and fall back 464e1051a39Sopenharmony_ci * to reading it as a normal cert (just X509), but if 465e1051a39Sopenharmony_ci * |data_type| (the PEM name) specifically declares it as a 466e1051a39Sopenharmony_ci * trusted cert, then no fallback should be engaged. 467e1051a39Sopenharmony_ci * |ignore_trusted| tells if the fallback can be used (1) 468e1051a39Sopenharmony_ci * or not (0). 469e1051a39Sopenharmony_ci */ 470e1051a39Sopenharmony_ci int ignore_trusted = 1; 471e1051a39Sopenharmony_ci X509 *cert = X509_new_ex(libctx, propq); 472e1051a39Sopenharmony_ci 473e1051a39Sopenharmony_ci if (cert == NULL) 474e1051a39Sopenharmony_ci return 0; 475e1051a39Sopenharmony_ci 476e1051a39Sopenharmony_ci /* If we have a data type, it should be a PEM name */ 477e1051a39Sopenharmony_ci if (data->data_type != NULL 478e1051a39Sopenharmony_ci && (OPENSSL_strcasecmp(data->data_type, PEM_STRING_X509_TRUSTED) == 0)) 479e1051a39Sopenharmony_ci ignore_trusted = 0; 480e1051a39Sopenharmony_ci 481e1051a39Sopenharmony_ci if (d2i_X509_AUX(&cert, (const unsigned char **)&data->octet_data, 482e1051a39Sopenharmony_ci data->octet_data_size) == NULL 483e1051a39Sopenharmony_ci && (!ignore_trusted 484e1051a39Sopenharmony_ci || d2i_X509(&cert, (const unsigned char **)&data->octet_data, 485e1051a39Sopenharmony_ci data->octet_data_size) == NULL)) { 486e1051a39Sopenharmony_ci X509_free(cert); 487e1051a39Sopenharmony_ci cert = NULL; 488e1051a39Sopenharmony_ci } 489e1051a39Sopenharmony_ci 490e1051a39Sopenharmony_ci if (cert != NULL) { 491e1051a39Sopenharmony_ci /* We determined the object type */ 492e1051a39Sopenharmony_ci data->object_type = OSSL_OBJECT_CERT; 493e1051a39Sopenharmony_ci *v = OSSL_STORE_INFO_new_CERT(cert); 494e1051a39Sopenharmony_ci if (*v == NULL) 495e1051a39Sopenharmony_ci X509_free(cert); 496e1051a39Sopenharmony_ci } 497e1051a39Sopenharmony_ci } 498e1051a39Sopenharmony_ci 499e1051a39Sopenharmony_ci return 1; 500e1051a39Sopenharmony_ci} 501e1051a39Sopenharmony_ci 502e1051a39Sopenharmony_cistatic int try_crl(struct extracted_param_data_st *data, OSSL_STORE_INFO **v, 503e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 504e1051a39Sopenharmony_ci{ 505e1051a39Sopenharmony_ci if (data->object_type == OSSL_OBJECT_UNKNOWN 506e1051a39Sopenharmony_ci || data->object_type == OSSL_OBJECT_CRL) { 507e1051a39Sopenharmony_ci X509_CRL *crl; 508e1051a39Sopenharmony_ci 509e1051a39Sopenharmony_ci crl = d2i_X509_CRL(NULL, (const unsigned char **)&data->octet_data, 510e1051a39Sopenharmony_ci data->octet_data_size); 511e1051a39Sopenharmony_ci 512e1051a39Sopenharmony_ci if (crl != NULL) 513e1051a39Sopenharmony_ci /* We determined the object type */ 514e1051a39Sopenharmony_ci data->object_type = OSSL_OBJECT_CRL; 515e1051a39Sopenharmony_ci 516e1051a39Sopenharmony_ci if (crl != NULL && !ossl_x509_crl_set0_libctx(crl, libctx, propq)) { 517e1051a39Sopenharmony_ci X509_CRL_free(crl); 518e1051a39Sopenharmony_ci crl = NULL; 519e1051a39Sopenharmony_ci } 520e1051a39Sopenharmony_ci 521e1051a39Sopenharmony_ci if (crl != NULL) 522e1051a39Sopenharmony_ci *v = OSSL_STORE_INFO_new_CRL(crl); 523e1051a39Sopenharmony_ci if (*v == NULL) 524e1051a39Sopenharmony_ci X509_CRL_free(crl); 525e1051a39Sopenharmony_ci } 526e1051a39Sopenharmony_ci 527e1051a39Sopenharmony_ci return 1; 528e1051a39Sopenharmony_ci} 529e1051a39Sopenharmony_ci 530e1051a39Sopenharmony_cistatic int try_pkcs12(struct extracted_param_data_st *data, OSSL_STORE_INFO **v, 531e1051a39Sopenharmony_ci OSSL_STORE_CTX *ctx, 532e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 533e1051a39Sopenharmony_ci{ 534e1051a39Sopenharmony_ci int ok = 1; 535e1051a39Sopenharmony_ci 536e1051a39Sopenharmony_ci /* There is no specific object type for PKCS12 */ 537e1051a39Sopenharmony_ci if (data->object_type == OSSL_OBJECT_UNKNOWN) { 538e1051a39Sopenharmony_ci /* Initial parsing */ 539e1051a39Sopenharmony_ci PKCS12 *p12; 540e1051a39Sopenharmony_ci 541e1051a39Sopenharmony_ci p12 = d2i_PKCS12(NULL, (const unsigned char **)&data->octet_data, 542e1051a39Sopenharmony_ci data->octet_data_size); 543e1051a39Sopenharmony_ci 544e1051a39Sopenharmony_ci if (p12 != NULL) { 545e1051a39Sopenharmony_ci char *pass = NULL; 546e1051a39Sopenharmony_ci char tpass[PEM_BUFSIZE + 1]; 547e1051a39Sopenharmony_ci size_t tpass_len; 548e1051a39Sopenharmony_ci EVP_PKEY *pkey = NULL; 549e1051a39Sopenharmony_ci X509 *cert = NULL; 550e1051a39Sopenharmony_ci STACK_OF(X509) *chain = NULL; 551e1051a39Sopenharmony_ci 552e1051a39Sopenharmony_ci data->object_type = OSSL_OBJECT_PKCS12; 553e1051a39Sopenharmony_ci 554e1051a39Sopenharmony_ci ok = 0; /* Assume decryption or parse error */ 555e1051a39Sopenharmony_ci 556e1051a39Sopenharmony_ci if (PKCS12_verify_mac(p12, "", 0) 557e1051a39Sopenharmony_ci || PKCS12_verify_mac(p12, NULL, 0)) { 558e1051a39Sopenharmony_ci pass = ""; 559e1051a39Sopenharmony_ci } else { 560e1051a39Sopenharmony_ci static char prompt_info[] = "PKCS12 import pass phrase"; 561e1051a39Sopenharmony_ci OSSL_PARAM pw_params[] = { 562e1051a39Sopenharmony_ci OSSL_PARAM_utf8_string(OSSL_PASSPHRASE_PARAM_INFO, 563e1051a39Sopenharmony_ci prompt_info, 564e1051a39Sopenharmony_ci sizeof(prompt_info) - 1), 565e1051a39Sopenharmony_ci OSSL_PARAM_END 566e1051a39Sopenharmony_ci }; 567e1051a39Sopenharmony_ci 568e1051a39Sopenharmony_ci if (!ossl_pw_get_passphrase(tpass, sizeof(tpass) - 1, 569e1051a39Sopenharmony_ci &tpass_len, 570e1051a39Sopenharmony_ci pw_params, 0, &ctx->pwdata)) { 571e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_OSSL_STORE, 572e1051a39Sopenharmony_ci OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR); 573e1051a39Sopenharmony_ci goto p12_end; 574e1051a39Sopenharmony_ci } 575e1051a39Sopenharmony_ci pass = tpass; 576e1051a39Sopenharmony_ci /* 577e1051a39Sopenharmony_ci * ossl_pw_get_passphrase() does not NUL terminate but 578e1051a39Sopenharmony_ci * we must do it for PKCS12_parse() 579e1051a39Sopenharmony_ci */ 580e1051a39Sopenharmony_ci pass[tpass_len] = '\0'; 581e1051a39Sopenharmony_ci if (!PKCS12_verify_mac(p12, pass, tpass_len)) { 582e1051a39Sopenharmony_ci ERR_raise_data(ERR_LIB_OSSL_STORE, 583e1051a39Sopenharmony_ci OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC, 584e1051a39Sopenharmony_ci tpass_len == 0 ? "empty password" : 585e1051a39Sopenharmony_ci "maybe wrong password"); 586e1051a39Sopenharmony_ci goto p12_end; 587e1051a39Sopenharmony_ci } 588e1051a39Sopenharmony_ci } 589e1051a39Sopenharmony_ci 590e1051a39Sopenharmony_ci if (PKCS12_parse(p12, pass, &pkey, &cert, &chain)) { 591e1051a39Sopenharmony_ci STACK_OF(OSSL_STORE_INFO) *infos = NULL; 592e1051a39Sopenharmony_ci OSSL_STORE_INFO *osi_pkey = NULL; 593e1051a39Sopenharmony_ci OSSL_STORE_INFO *osi_cert = NULL; 594e1051a39Sopenharmony_ci OSSL_STORE_INFO *osi_ca = NULL; 595e1051a39Sopenharmony_ci 596e1051a39Sopenharmony_ci ok = 1; /* Parsing went through correctly! */ 597e1051a39Sopenharmony_ci 598e1051a39Sopenharmony_ci if ((infos = sk_OSSL_STORE_INFO_new_null()) != NULL) { 599e1051a39Sopenharmony_ci if (pkey != NULL) { 600e1051a39Sopenharmony_ci if ((osi_pkey = OSSL_STORE_INFO_new_PKEY(pkey)) != NULL 601e1051a39Sopenharmony_ci /* clearing pkey here avoids case distinctions */ 602e1051a39Sopenharmony_ci && (pkey = NULL) == NULL 603e1051a39Sopenharmony_ci && sk_OSSL_STORE_INFO_push(infos, osi_pkey) != 0) 604e1051a39Sopenharmony_ci osi_pkey = NULL; 605e1051a39Sopenharmony_ci else 606e1051a39Sopenharmony_ci ok = 0; 607e1051a39Sopenharmony_ci } 608e1051a39Sopenharmony_ci if (ok && cert != NULL) { 609e1051a39Sopenharmony_ci if ((osi_cert = OSSL_STORE_INFO_new_CERT(cert)) != NULL 610e1051a39Sopenharmony_ci /* clearing cert here avoids case distinctions */ 611e1051a39Sopenharmony_ci && (cert = NULL) == NULL 612e1051a39Sopenharmony_ci && sk_OSSL_STORE_INFO_push(infos, osi_cert) != 0) 613e1051a39Sopenharmony_ci osi_cert = NULL; 614e1051a39Sopenharmony_ci else 615e1051a39Sopenharmony_ci ok = 0; 616e1051a39Sopenharmony_ci } 617e1051a39Sopenharmony_ci while (ok && sk_X509_num(chain) > 0) { 618e1051a39Sopenharmony_ci X509 *ca = sk_X509_value(chain, 0); 619e1051a39Sopenharmony_ci 620e1051a39Sopenharmony_ci if ((osi_ca = OSSL_STORE_INFO_new_CERT(ca)) != NULL 621e1051a39Sopenharmony_ci && sk_X509_shift(chain) != NULL 622e1051a39Sopenharmony_ci && sk_OSSL_STORE_INFO_push(infos, osi_ca) != 0) 623e1051a39Sopenharmony_ci osi_ca = NULL; 624e1051a39Sopenharmony_ci else 625e1051a39Sopenharmony_ci ok = 0; 626e1051a39Sopenharmony_ci } 627e1051a39Sopenharmony_ci } 628e1051a39Sopenharmony_ci EVP_PKEY_free(pkey); 629e1051a39Sopenharmony_ci X509_free(cert); 630e1051a39Sopenharmony_ci sk_X509_pop_free(chain, X509_free); 631e1051a39Sopenharmony_ci OSSL_STORE_INFO_free(osi_pkey); 632e1051a39Sopenharmony_ci OSSL_STORE_INFO_free(osi_cert); 633e1051a39Sopenharmony_ci OSSL_STORE_INFO_free(osi_ca); 634e1051a39Sopenharmony_ci if (!ok) { 635e1051a39Sopenharmony_ci sk_OSSL_STORE_INFO_pop_free(infos, OSSL_STORE_INFO_free); 636e1051a39Sopenharmony_ci infos = NULL; 637e1051a39Sopenharmony_ci } 638e1051a39Sopenharmony_ci ctx->cached_info = infos; 639e1051a39Sopenharmony_ci } 640e1051a39Sopenharmony_ci p12_end: 641e1051a39Sopenharmony_ci OPENSSL_cleanse(tpass, sizeof(tpass)); 642e1051a39Sopenharmony_ci PKCS12_free(p12); 643e1051a39Sopenharmony_ci } 644e1051a39Sopenharmony_ci *v = sk_OSSL_STORE_INFO_shift(ctx->cached_info); 645e1051a39Sopenharmony_ci } 646e1051a39Sopenharmony_ci 647e1051a39Sopenharmony_ci return ok; 648e1051a39Sopenharmony_ci} 649