Path: blob/main/crypto/openssl/providers/implementations/encode_decode/decode_epki2pki.c
48383 views
/*1* Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89#include <openssl/core.h>10#include <openssl/core_dispatch.h>11#include <openssl/core_names.h>12#include <openssl/core_object.h>13#include <openssl/asn1.h>14#include <openssl/err.h>15#include <openssl/objects.h>16#include <openssl/pkcs12.h>17#include <openssl/x509.h>18#include <openssl/proverr.h>19#include "internal/asn1.h"20#include "internal/sizes.h"21#include "prov/bio.h"22#include "prov/decoders.h"23#include "prov/implementations.h"24#include "endecoder_local.h"2526static OSSL_FUNC_decoder_newctx_fn epki2pki_newctx;27static OSSL_FUNC_decoder_freectx_fn epki2pki_freectx;28static OSSL_FUNC_decoder_decode_fn epki2pki_decode;29static OSSL_FUNC_decoder_settable_ctx_params_fn epki2pki_settable_ctx_params;30static OSSL_FUNC_decoder_set_ctx_params_fn epki2pki_set_ctx_params;3132/*33* Context used for EncryptedPrivateKeyInfo to PrivateKeyInfo decoding.34*/35struct epki2pki_ctx_st {36PROV_CTX *provctx;37char propq[OSSL_MAX_PROPQUERY_SIZE];38};3940static void *epki2pki_newctx(void *provctx)41{42struct epki2pki_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));4344if (ctx != NULL)45ctx->provctx = provctx;46return ctx;47}4849static void epki2pki_freectx(void *vctx)50{51struct epki2pki_ctx_st *ctx = vctx;5253OPENSSL_free(ctx);54}5556static const OSSL_PARAM *epki2pki_settable_ctx_params(ossl_unused void *provctx)57{58static const OSSL_PARAM settables[] = {59OSSL_PARAM_utf8_string(OSSL_DECODER_PARAM_PROPERTIES, NULL, 0),60OSSL_PARAM_END61};62return settables;63}6465static int epki2pki_set_ctx_params(void *vctx, const OSSL_PARAM params[])66{67struct epki2pki_ctx_st *ctx = vctx;68const OSSL_PARAM *p;69char *str = ctx->propq;7071p = OSSL_PARAM_locate_const(params, OSSL_DECODER_PARAM_PROPERTIES);72if (p != NULL && !OSSL_PARAM_get_utf8_string(p, &str, sizeof(ctx->propq)))73return 0;7475return 1;76}7778/*79* The selection parameter in epki2pki_decode() is not used by this function80* because it's not relevant just to decode EncryptedPrivateKeyInfo to81* PrivateKeyInfo.82*/83static int epki2pki_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,84OSSL_CALLBACK *data_cb, void *data_cbarg,85OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)86{87struct epki2pki_ctx_st *ctx = vctx;88BUF_MEM *mem = NULL;89unsigned char *der = NULL;90long der_len = 0;91BIO *in = ossl_bio_new_from_core_bio(ctx->provctx, cin);92int ok = 0;9394if (in == NULL)95return 0;9697ok = (asn1_d2i_read_bio(in, &mem) >= 0);98BIO_free(in);99100/* We return "empty handed". This is not an error. */101if (!ok)102return 1;103104der = (unsigned char *)mem->data;105der_len = (long)mem->length;106OPENSSL_free(mem);107108ok = ossl_epki2pki_der_decode(der, der_len, selection, data_cb, data_cbarg,109pw_cb, pw_cbarg, PROV_LIBCTX_OF(ctx->provctx),110ctx->propq);111OPENSSL_free(der);112return ok;113}114115int ossl_epki2pki_der_decode(unsigned char *der, long der_len, int selection,116OSSL_CALLBACK *data_cb, void *data_cbarg,117OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg,118OSSL_LIB_CTX *libctx, const char *propq)119{120const unsigned char *pder = der;121unsigned char *new_der = NULL;122X509_SIG *p8 = NULL;123PKCS8_PRIV_KEY_INFO *p8inf = NULL;124const X509_ALGOR *alg = NULL;125int ok = 1; /* Assume good */126127ERR_set_mark();128if ((p8 = d2i_X509_SIG(NULL, &pder, der_len)) != NULL) {129char pbuf[1024];130size_t plen = 0;131132ERR_clear_last_mark();133134if (!pw_cb(pbuf, sizeof(pbuf), &plen, NULL, pw_cbarg)) {135ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PASSPHRASE);136ok = 0;137} else {138const ASN1_OCTET_STRING *oct;139int new_der_len = 0;140141X509_SIG_get0(p8, &alg, &oct);142if (!PKCS12_pbe_crypt_ex(alg, pbuf, plen,143oct->data, oct->length,144&new_der, &new_der_len, 0,145libctx, propq)) {146ok = 0;147} else {148der = new_der;149der_len = new_der_len;150}151alg = NULL;152}153X509_SIG_free(p8);154} else {155ERR_pop_to_mark();156}157158ERR_set_mark();159pder = der;160p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &pder, der_len);161ERR_pop_to_mark();162163if (p8inf != NULL && PKCS8_pkey_get0(NULL, NULL, NULL, &alg, p8inf)) {164/*165* We have something and recognised it as PrivateKeyInfo, so let's166* pass all the applicable data to the callback.167*/168char keytype[OSSL_MAX_NAME_SIZE];169OSSL_PARAM params[6], *p = params;170int objtype = OSSL_OBJECT_PKEY;171172OBJ_obj2txt(keytype, sizeof(keytype), alg->algorithm, 0);173174*p++ = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,175keytype, 0);176*p++ = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_INPUT_TYPE,177"DER", 0);178*p++ = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE,179"PrivateKeyInfo", 0);180*p++ = OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA,181der, der_len);182*p++ = OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &objtype);183*p = OSSL_PARAM_construct_end();184185ok = data_cb(params, data_cbarg);186}187PKCS8_PRIV_KEY_INFO_free(p8inf);188OPENSSL_free(new_der);189return ok;190}191192const OSSL_DISPATCH ossl_EncryptedPrivateKeyInfo_der_to_der_decoder_functions[] = {193{ OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))epki2pki_newctx },194{ OSSL_FUNC_DECODER_FREECTX, (void (*)(void))epki2pki_freectx },195{ OSSL_FUNC_DECODER_DECODE, (void (*)(void))epki2pki_decode },196{ OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS,197(void (*)(void))epki2pki_settable_ctx_params },198{ OSSL_FUNC_DECODER_SET_CTX_PARAMS,199(void (*)(void))epki2pki_set_ctx_params },200OSSL_DISPATCH_END201};202203204