Path: blob/main/crypto/openssl/providers/implementations/encode_decode/decode_msblob2key.c
105332 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_KEY | OSSL_KEYMGMT_SELECT_PUBLIC_KEY)) != 0)87return 1;8889return 0;90}9192static int msblob2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,93OSSL_CALLBACK *data_cb, void *data_cbarg,94OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)95{96struct msblob2key_ctx_st *ctx = vctx;97BIO *in = ossl_bio_new_from_core_bio(ctx->provctx, cin);98const unsigned char *p;99unsigned char hdr_buf[16], *buf = NULL;100unsigned int bitlen, magic, length;101int isdss = -1;102int ispub = -1;103void *key = NULL;104int ok = 0;105106if (in == NULL)107return 0;108109if (BIO_read(in, hdr_buf, 16) != 16) {110ERR_raise(ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT);111goto next;112}113ERR_set_mark();114p = hdr_buf;115ok = ossl_do_blob_header(&p, 16, &magic, &bitlen, &isdss, &ispub) > 0;116ERR_pop_to_mark();117if (!ok)118goto next;119120ctx->selection = selection;121ok = 0; /* Assume that we fail */122123if ((isdss && ctx->desc->type != EVP_PKEY_DSA)124|| (!isdss && ctx->desc->type != EVP_PKEY_RSA))125goto next;126127length = ossl_blob_length(bitlen, isdss, ispub);128if (length > BLOB_MAX_LENGTH) {129ERR_raise(ERR_LIB_PEM, PEM_R_HEADER_TOO_LONG);130goto next;131}132buf = OPENSSL_malloc(length);133if (buf == NULL)134goto end;135p = buf;136if (BIO_read(in, buf, length) != (int)length) {137ERR_raise(ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT);138goto next;139}140141if ((selection == 0142|| (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)143&& !ispub144&& ctx->desc->read_private_key != NULL) {145struct ossl_passphrase_data_st pwdata;146147memset(&pwdata, 0, sizeof(pwdata));148if (!ossl_pw_set_ossl_passphrase_cb(&pwdata, pw_cb, pw_cbarg))149goto end;150p = buf;151key = ctx->desc->read_private_key(&p, bitlen, ispub);152if (selection != 0 && key == NULL)153goto next;154}155if (key == NULL && (selection == 0 || (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)156&& ispub157&& ctx->desc->read_public_key != NULL) {158p = buf;159key = ctx->desc->read_public_key(&p, bitlen, ispub);160if (selection != 0 && key == NULL)161goto next;162}163164if (key != NULL && ctx->desc->adjust_key != NULL)165ctx->desc->adjust_key(key, ctx);166167next:168/*169* Indicated that we successfully decoded something, or not at all.170* Ending up "empty handed" is not an error.171*/172ok = 1;173174/*175* We free resources here so it's not held up during the callback, because176* we know the process is recursive and the allocated chunks of memory177* add up.178*/179OPENSSL_free(buf);180BIO_free(in);181buf = NULL;182in = NULL;183184if (key != NULL) {185OSSL_PARAM params[4];186int object_type = OSSL_OBJECT_PKEY;187188params[0] = OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &object_type);189params[1] = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,190(char *)ctx->desc->name, 0);191/* The address of the key becomes the octet string */192params[2] = OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_REFERENCE,193&key, sizeof(key));194params[3] = OSSL_PARAM_construct_end();195196ok = data_cb(params, data_cbarg);197}198199end:200BIO_free(in);201OPENSSL_free(buf);202ctx->desc->free_key(key);203204return ok;205}206207static int208msblob2key_export_object(void *vctx,209const void *reference, size_t reference_sz,210OSSL_CALLBACK *export_cb, void *export_cbarg)211{212struct msblob2key_ctx_st *ctx = vctx;213OSSL_FUNC_keymgmt_export_fn *export = ossl_prov_get_keymgmt_export(ctx->desc->fns);214void *keydata;215216if (reference_sz == sizeof(keydata) && export != NULL) {217int selection = ctx->selection;218219if (selection == 0)220selection = OSSL_KEYMGMT_SELECT_ALL;221/* The contents of the reference is the address to our object */222keydata = *(void **)reference;223224return export(keydata, selection, export_cb, export_cbarg);225}226return 0;227}228229/* ---------------------------------------------------------------------- */230231#define dsa_decode_private_key (b2i_of_void_fn *)ossl_b2i_DSA_after_header232#define dsa_decode_public_key (b2i_of_void_fn *)ossl_b2i_DSA_after_header233#define dsa_adjust NULL234#define dsa_free (void (*)(void *)) DSA_free235236/* ---------------------------------------------------------------------- */237238#define rsa_decode_private_key (b2i_of_void_fn *)ossl_b2i_RSA_after_header239#define rsa_decode_public_key (b2i_of_void_fn *)ossl_b2i_RSA_after_header240241static void rsa_adjust(void *key, struct msblob2key_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_MSBLOB(KEYTYPE, keytype) \251static const struct keytype_desc_st mstype##2##keytype##_desc = { \252EVP_PKEY_##KEYTYPE, #KEYTYPE, \253ossl_##keytype##_keymgmt_functions, \254keytype##_decode_private_key, \255keytype##_decode_public_key, \256keytype##_adjust, \257keytype##_free \258}; \259static OSSL_FUNC_decoder_newctx_fn msblob2##keytype##_newctx; \260static void *msblob2##keytype##_newctx(void *provctx) \261{ \262return msblob2key_newctx(provctx, &mstype##2##keytype##_desc); \263} \264const OSSL_DISPATCH \265ossl_msblob_to_##keytype##_decoder_functions[] \266= { \267{ OSSL_FUNC_DECODER_NEWCTX, \268(void (*)(void))msblob2##keytype##_newctx }, \269{ OSSL_FUNC_DECODER_FREECTX, \270(void (*)(void))msblob2key_freectx }, \271{ OSSL_FUNC_DECODER_DOES_SELECTION, \272(void (*)(void))msblob2key_does_selection }, \273{ OSSL_FUNC_DECODER_DECODE, \274(void (*)(void))msblob2key_decode }, \275{ OSSL_FUNC_DECODER_EXPORT_OBJECT, \276(void (*)(void))msblob2key_export_object }, \277OSSL_DISPATCH_END \278}279280#ifndef OPENSSL_NO_DSA281IMPLEMENT_MSBLOB(DSA, dsa);282#endif283IMPLEMENT_MSBLOB(RSA, rsa);284285286