Path: blob/main/crypto/openssl/providers/implementations/encode_decode/decode_pvk2key.c
48383 views
/*1* Copyright 2020-2023 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/*10* low level APIs are deprecated for public use, but still ok for11* internal use.12*/13#include "internal/deprecated.h"1415#include <string.h>1617#include <openssl/core_dispatch.h>18#include <openssl/core_names.h>19#include <openssl/core_object.h>20#include <openssl/crypto.h>21#include <openssl/params.h>22#include <openssl/err.h>23#include <openssl/pem.h> /* For public PVK functions */24#include <openssl/x509.h>25#include "internal/passphrase.h"26#include "internal/sizes.h"27#include "crypto/pem.h" /* For internal PVK and "blob" headers */28#include "crypto/rsa.h"29#include "prov/bio.h"30#include "prov/implementations.h"31#include "endecoder_local.h"3233struct pvk2key_ctx_st; /* Forward declaration */34typedef int check_key_fn(void *, struct pvk2key_ctx_st *ctx);35typedef void adjust_key_fn(void *, struct pvk2key_ctx_st *ctx);36typedef void *b2i_PVK_of_bio_pw_fn(BIO *in, pem_password_cb *cb, void *u,37OSSL_LIB_CTX *libctx, const char *propq);38typedef void free_key_fn(void *);39struct keytype_desc_st {40int type; /* EVP key type */41const char *name; /* Keytype */42const OSSL_DISPATCH *fns; /* Keymgmt (to pilfer functions from) */4344b2i_PVK_of_bio_pw_fn *read_private_key;45adjust_key_fn *adjust_key;46free_key_fn *free_key;47};4849static OSSL_FUNC_decoder_freectx_fn pvk2key_freectx;50static OSSL_FUNC_decoder_decode_fn pvk2key_decode;51static OSSL_FUNC_decoder_export_object_fn pvk2key_export_object;52static OSSL_FUNC_decoder_settable_ctx_params_fn pvk2key_settable_ctx_params;53static OSSL_FUNC_decoder_set_ctx_params_fn pvk2key_set_ctx_params;5455/*56* Context used for DER to key decoding.57*/58struct pvk2key_ctx_st {59PROV_CTX *provctx;60char propq[OSSL_MAX_PROPQUERY_SIZE];61const struct keytype_desc_st *desc;62/* The selection that is passed to der2key_decode() */63int selection;64};6566static struct pvk2key_ctx_st *67pvk2key_newctx(void *provctx, const struct keytype_desc_st *desc)68{69struct pvk2key_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));7071if (ctx != NULL) {72ctx->provctx = provctx;73ctx->desc = desc;74}75return ctx;76}7778static void pvk2key_freectx(void *vctx)79{80struct pvk2key_ctx_st *ctx = vctx;8182OPENSSL_free(ctx);83}8485static const OSSL_PARAM *pvk2key_settable_ctx_params(ossl_unused void *provctx)86{87static const OSSL_PARAM settables[] = {88OSSL_PARAM_utf8_string(OSSL_DECODER_PARAM_PROPERTIES, NULL, 0),89OSSL_PARAM_END,90};91return settables;92}9394static int pvk2key_set_ctx_params(void *vctx, const OSSL_PARAM params[])95{96struct pvk2key_ctx_st *ctx = vctx;97const OSSL_PARAM *p;98char *str = ctx->propq;99100p = OSSL_PARAM_locate_const(params, OSSL_DECODER_PARAM_PROPERTIES);101if (p != NULL && !OSSL_PARAM_get_utf8_string(p, &str, sizeof(ctx->propq)))102return 0;103104return 1;105}106107static int pvk2key_does_selection(void *provctx, int selection)108{109if (selection == 0)110return 1;111112if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)113return 1;114115return 0;116}117118static int pvk2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,119OSSL_CALLBACK *data_cb, void *data_cbarg,120OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)121{122struct pvk2key_ctx_st *ctx = vctx;123BIO *in = ossl_bio_new_from_core_bio(ctx->provctx, cin);124void *key = NULL;125int ok = 0;126127if (in == NULL)128return 0;129130ctx->selection = selection;131132if ((selection == 0133|| (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)134&& ctx->desc->read_private_key != NULL) {135struct ossl_passphrase_data_st pwdata;136int err, lib, reason;137138memset(&pwdata, 0, sizeof(pwdata));139if (!ossl_pw_set_ossl_passphrase_cb(&pwdata, pw_cb, pw_cbarg))140goto end;141142key = ctx->desc->read_private_key(in, ossl_pw_pvk_password, &pwdata,143PROV_LIBCTX_OF(ctx->provctx),144ctx->propq);145146/*147* Because the PVK API doesn't have a separate decrypt call, we need148* to check the error queue for certain well known errors that are149* considered fatal and which we pass through, while the rest gets150* thrown away.151*/152err = ERR_peek_last_error();153lib = ERR_GET_LIB(err);154reason = ERR_GET_REASON(err);155if (lib == ERR_LIB_PEM156&& (reason == PEM_R_BAD_PASSWORD_READ157|| reason == PEM_R_BAD_DECRYPT)) {158ERR_clear_last_mark();159goto end;160}161162if (selection != 0 && key == NULL)163goto next;164}165166if (key != NULL && ctx->desc->adjust_key != NULL)167ctx->desc->adjust_key(key, ctx);168169next:170/*171* Indicated that we successfully decoded something, or not at all.172* Ending up "empty handed" is not an error.173*/174ok = 1;175176/*177* We free resources here so it's not held up during the callback, because178* we know the process is recursive and the allocated chunks of memory179* add up.180*/181BIO_free(in);182in = NULL;183184if (key != NULL) {185OSSL_PARAM params[4];186int object_type = OSSL_OBJECT_PKEY;187188params[0] =189OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &object_type);190params[1] =191OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,192(char *)ctx->desc->name, 0);193/* The address of the key becomes the octet string */194params[2] =195OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_REFERENCE,196&key, sizeof(key));197params[3] = OSSL_PARAM_construct_end();198199ok = data_cb(params, data_cbarg);200}201202end:203BIO_free(in);204ctx->desc->free_key(key);205206return ok;207}208209static int pvk2key_export_object(void *vctx,210const void *reference, size_t reference_sz,211OSSL_CALLBACK *export_cb, void *export_cbarg)212{213struct pvk2key_ctx_st *ctx = vctx;214OSSL_FUNC_keymgmt_export_fn *export =215ossl_prov_get_keymgmt_export(ctx->desc->fns);216void *keydata;217218if (reference_sz == sizeof(keydata) && export != NULL) {219int selection = ctx->selection;220221if (selection == 0)222selection = OSSL_KEYMGMT_SELECT_ALL;223/* The contents of the reference is the address to our object */224keydata = *(void **)reference;225226return export(keydata, selection, export_cb, export_cbarg);227}228return 0;229}230231/* ---------------------------------------------------------------------- */232233#define dsa_private_key_bio (b2i_PVK_of_bio_pw_fn *)b2i_DSA_PVK_bio_ex234#define dsa_adjust NULL235#define dsa_free (void (*)(void *))DSA_free236237/* ---------------------------------------------------------------------- */238239#define rsa_private_key_bio (b2i_PVK_of_bio_pw_fn *)b2i_RSA_PVK_bio_ex240241static void rsa_adjust(void *key, struct pvk2key_ctx_st *ctx)242{243ossl_rsa_set0_libctx(key, PROV_LIBCTX_OF(ctx->provctx));244}245246#define rsa_free (void (*)(void *))RSA_free247248/* ---------------------------------------------------------------------- */249250#define IMPLEMENT_MS(KEYTYPE, keytype) \251static const struct keytype_desc_st \252pvk2##keytype##_desc = { \253EVP_PKEY_##KEYTYPE, #KEYTYPE, \254ossl_##keytype##_keymgmt_functions, \255keytype##_private_key_bio, \256keytype##_adjust, \257keytype##_free \258}; \259static OSSL_FUNC_decoder_newctx_fn pvk2##keytype##_newctx; \260static void *pvk2##keytype##_newctx(void *provctx) \261{ \262return pvk2key_newctx(provctx, &pvk2##keytype##_desc); \263} \264const OSSL_DISPATCH \265ossl_##pvk_to_##keytype##_decoder_functions[] = { \266{ OSSL_FUNC_DECODER_NEWCTX, \267(void (*)(void))pvk2##keytype##_newctx }, \268{ OSSL_FUNC_DECODER_FREECTX, \269(void (*)(void))pvk2key_freectx }, \270{ OSSL_FUNC_DECODER_DOES_SELECTION, \271(void (*)(void))pvk2key_does_selection }, \272{ OSSL_FUNC_DECODER_DECODE, \273(void (*)(void))pvk2key_decode }, \274{ OSSL_FUNC_DECODER_EXPORT_OBJECT, \275(void (*)(void))pvk2key_export_object }, \276{ OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS, \277(void (*)(void))pvk2key_settable_ctx_params }, \278{ OSSL_FUNC_DECODER_SET_CTX_PARAMS, \279(void (*)(void))pvk2key_set_ctx_params }, \280OSSL_DISPATCH_END \281}282283#ifndef OPENSSL_NO_DSA284IMPLEMENT_MS(DSA, dsa);285#endif286IMPLEMENT_MS(RSA, rsa);287288289