Path: blob/main/crypto/openssl/providers/implementations/encode_decode/decode_msblob2key.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/pem.h> /* For public PVK functions */23#include <openssl/x509.h>24#include <openssl/err.h>25#include "internal/passphrase.h"26#include "crypto/pem.h" /* For internal PVK and "blob" headers */27#include "crypto/rsa.h"28#include "prov/bio.h"29#include "prov/implementations.h"30#include "endecoder_local.h"3132struct msblob2key_ctx_st; /* Forward declaration */33typedef void *b2i_of_void_fn(const unsigned char **in, unsigned int bitlen,34int ispub);35typedef void adjust_key_fn(void *, struct msblob2key_ctx_st *ctx);36typedef void free_key_fn(void *);37struct keytype_desc_st {38int type; /* EVP key type */39const char *name; /* Keytype */40const OSSL_DISPATCH *fns; /* Keymgmt (to pilfer functions from) */4142b2i_of_void_fn *read_private_key;43b2i_of_void_fn *read_public_key;44adjust_key_fn *adjust_key;45free_key_fn *free_key;46};4748static OSSL_FUNC_decoder_freectx_fn msblob2key_freectx;49static OSSL_FUNC_decoder_decode_fn msblob2key_decode;50static OSSL_FUNC_decoder_export_object_fn msblob2key_export_object;5152/*53* Context used for DER to key decoding.54*/55struct msblob2key_ctx_st {56PROV_CTX *provctx;57const struct keytype_desc_st *desc;58/* The selection that is passed to msblob2key_decode() */59int selection;60};6162static struct msblob2key_ctx_st *63msblob2key_newctx(void *provctx, const struct keytype_desc_st *desc)64{65struct msblob2key_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));6667if (ctx != NULL) {68ctx->provctx = provctx;69ctx->desc = desc;70}71return ctx;72}7374static void msblob2key_freectx(void *vctx)75{76struct msblob2key_ctx_st *ctx = vctx;7778OPENSSL_free(ctx);79}8081static int msblob2key_does_selection(void *provctx, int selection)82{83if (selection == 0)84return 1;8586if ((selection & (OSSL_KEYMGMT_SELECT_PRIVATE_KEY87| OSSL_KEYMGMT_SELECT_PUBLIC_KEY)) != 0)88return 1;8990return 0;91}9293static int msblob2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,94OSSL_CALLBACK *data_cb, void *data_cbarg,95OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)96{97struct msblob2key_ctx_st *ctx = vctx;98BIO *in = ossl_bio_new_from_core_bio(ctx->provctx, cin);99const unsigned char *p;100unsigned char hdr_buf[16], *buf = NULL;101unsigned int bitlen, magic, length;102int isdss = -1;103int ispub = -1;104void *key = NULL;105int ok = 0;106107if (in == NULL)108return 0;109110if (BIO_read(in, hdr_buf, 16) != 16) {111ERR_raise(ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT);112goto next;113}114ERR_set_mark();115p = hdr_buf;116ok = ossl_do_blob_header(&p, 16, &magic, &bitlen, &isdss, &ispub) > 0;117ERR_pop_to_mark();118if (!ok)119goto next;120121ctx->selection = selection;122ok = 0; /* Assume that we fail */123124if ((isdss && ctx->desc->type != EVP_PKEY_DSA)125|| (!isdss && ctx->desc->type != EVP_PKEY_RSA))126goto next;127128length = ossl_blob_length(bitlen, isdss, ispub);129if (length > BLOB_MAX_LENGTH) {130ERR_raise(ERR_LIB_PEM, PEM_R_HEADER_TOO_LONG);131goto next;132}133buf = OPENSSL_malloc(length);134if (buf == NULL)135goto end;136p = buf;137if (BIO_read(in, buf, length) != (int)length) {138ERR_raise(ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT);139goto next;140}141142if ((selection == 0143|| (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)144&& !ispub145&& ctx->desc->read_private_key != NULL) {146struct ossl_passphrase_data_st pwdata;147148memset(&pwdata, 0, sizeof(pwdata));149if (!ossl_pw_set_ossl_passphrase_cb(&pwdata, pw_cb, pw_cbarg))150goto end;151p = buf;152key = ctx->desc->read_private_key(&p, bitlen, ispub);153if (selection != 0 && key == NULL)154goto next;155}156if (key == NULL && (selection == 0157|| (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)158&& ispub159&& ctx->desc->read_public_key != NULL) {160p = buf;161key = ctx->desc->read_public_key(&p, bitlen, ispub);162if (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*/181OPENSSL_free(buf);182BIO_free(in);183buf = NULL;184in = NULL;185186if (key != NULL) {187OSSL_PARAM params[4];188int object_type = OSSL_OBJECT_PKEY;189190params[0] =191OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &object_type);192params[1] =193OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,194(char *)ctx->desc->name, 0);195/* The address of the key becomes the octet string */196params[2] =197OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_REFERENCE,198&key, sizeof(key));199params[3] = OSSL_PARAM_construct_end();200201ok = data_cb(params, data_cbarg);202}203204end:205BIO_free(in);206OPENSSL_free(buf);207ctx->desc->free_key(key);208209return ok;210}211212static int213msblob2key_export_object(void *vctx,214const void *reference, size_t reference_sz,215OSSL_CALLBACK *export_cb, void *export_cbarg)216{217struct msblob2key_ctx_st *ctx = vctx;218OSSL_FUNC_keymgmt_export_fn *export =219ossl_prov_get_keymgmt_export(ctx->desc->fns);220void *keydata;221222if (reference_sz == sizeof(keydata) && export != NULL) {223int selection = ctx->selection;224225if (selection == 0)226selection = OSSL_KEYMGMT_SELECT_ALL;227/* The contents of the reference is the address to our object */228keydata = *(void **)reference;229230return export(keydata, selection, export_cb, export_cbarg);231}232return 0;233}234235/* ---------------------------------------------------------------------- */236237#define dsa_decode_private_key (b2i_of_void_fn *)ossl_b2i_DSA_after_header238#define dsa_decode_public_key (b2i_of_void_fn *)ossl_b2i_DSA_after_header239#define dsa_adjust NULL240#define dsa_free (void (*)(void *))DSA_free241242/* ---------------------------------------------------------------------- */243244#define rsa_decode_private_key (b2i_of_void_fn *)ossl_b2i_RSA_after_header245#define rsa_decode_public_key (b2i_of_void_fn *)ossl_b2i_RSA_after_header246247static void rsa_adjust(void *key, struct msblob2key_ctx_st *ctx)248{249ossl_rsa_set0_libctx(key, PROV_LIBCTX_OF(ctx->provctx));250}251252#define rsa_free (void (*)(void *))RSA_free253254/* ---------------------------------------------------------------------- */255256#define IMPLEMENT_MSBLOB(KEYTYPE, keytype) \257static const struct keytype_desc_st mstype##2##keytype##_desc = { \258EVP_PKEY_##KEYTYPE, #KEYTYPE, \259ossl_##keytype##_keymgmt_functions, \260keytype##_decode_private_key, \261keytype##_decode_public_key, \262keytype##_adjust, \263keytype##_free \264}; \265static OSSL_FUNC_decoder_newctx_fn msblob2##keytype##_newctx; \266static void *msblob2##keytype##_newctx(void *provctx) \267{ \268return msblob2key_newctx(provctx, &mstype##2##keytype##_desc); \269} \270const OSSL_DISPATCH \271ossl_msblob_to_##keytype##_decoder_functions[] = { \272{ OSSL_FUNC_DECODER_NEWCTX, \273(void (*)(void))msblob2##keytype##_newctx }, \274{ OSSL_FUNC_DECODER_FREECTX, \275(void (*)(void))msblob2key_freectx }, \276{ OSSL_FUNC_DECODER_DOES_SELECTION, \277(void (*)(void))msblob2key_does_selection }, \278{ OSSL_FUNC_DECODER_DECODE, \279(void (*)(void))msblob2key_decode }, \280{ OSSL_FUNC_DECODER_EXPORT_OBJECT, \281(void (*)(void))msblob2key_export_object }, \282OSSL_DISPATCH_END \283}284285#ifndef OPENSSL_NO_DSA286IMPLEMENT_MSBLOB(DSA, dsa);287#endif288IMPLEMENT_MSBLOB(RSA, rsa);289290291