Path: blob/main/crypto/openssl/providers/implementations/encode_decode/encode_key2blob.c
48383 views
/*1* Copyright 2021-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 for internal use.11*/12#include "internal/deprecated.h"1314#include <openssl/core.h>15#include <openssl/core_dispatch.h>16#include <openssl/core_names.h>17#include <openssl/params.h>18#include <openssl/err.h>19#include <openssl/evp.h>20#include <openssl/ec.h>21#include "internal/passphrase.h"22#include "internal/nelem.h"23#include "prov/implementations.h"24#include "prov/bio.h"25#include "prov/provider_ctx.h"26#include "endecoder_local.h"2728static int write_blob(void *provctx, OSSL_CORE_BIO *cout,29void *data, int len)30{31BIO *out = ossl_bio_new_from_core_bio(provctx, cout);32int ret;3334if (out == NULL)35return 0;36ret = BIO_write(out, data, len);3738BIO_free(out);39return ret;40}4142static OSSL_FUNC_encoder_newctx_fn key2blob_newctx;43static OSSL_FUNC_encoder_freectx_fn key2blob_freectx;4445static void *key2blob_newctx(void *provctx)46{47return provctx;48}4950static void key2blob_freectx(void *vctx)51{52}5354static int key2blob_check_selection(int selection, int selection_mask)55{56/*57* The selections are kinda sorta "levels", i.e. each selection given58* here is assumed to include those following.59*/60int checks[] = {61OSSL_KEYMGMT_SELECT_PRIVATE_KEY,62OSSL_KEYMGMT_SELECT_PUBLIC_KEY,63OSSL_KEYMGMT_SELECT_ALL_PARAMETERS64};65size_t i;6667/* The decoder implementations made here support guessing */68if (selection == 0)69return 1;7071for (i = 0; i < OSSL_NELEM(checks); i++) {72int check1 = (selection & checks[i]) != 0;73int check2 = (selection_mask & checks[i]) != 0;7475/*76* If the caller asked for the currently checked bit(s), return77* whether the decoder description says it's supported.78*/79if (check1)80return check2;81}8283/* This should be dead code, but just to be safe... */84return 0;85}8687static int key2blob_encode(void *vctx, const void *key, int selection,88OSSL_CORE_BIO *cout)89{90int pubkey_len = 0, ok = 0;91unsigned char *pubkey = NULL;9293pubkey_len = i2o_ECPublicKey(key, &pubkey);94if (pubkey_len > 0 && pubkey != NULL)95ok = write_blob(vctx, cout, pubkey, pubkey_len);96OPENSSL_free(pubkey);97return ok;98}99100/*101* MAKE_BLOB_ENCODER() Makes an OSSL_DISPATCH table for a particular key->blob102* encoder103*104* impl: The keytype to encode105* type: The C structure type holding the key data106* selection_name: The acceptable selections. This translates into107* the macro EVP_PKEY_##selection_name.108*109* The selection is understood as a "level" rather than an exact set of110* requests from the caller. The encoder has to decide what contents fit111* the encoded format. For example, the EC public key blob will only contain112* the encoded public key itself, no matter if the selection bits include113* OSSL_KEYMGMT_SELECT_PARAMETERS or not. However, if the selection includes114* OSSL_KEYMGMT_SELECT_PRIVATE_KEY, the same encoder will simply refuse to115* cooperate, because it cannot output the private key.116*117* EVP_PKEY_##selection_name are convenience macros that combine "typical"118* OSSL_KEYMGMT_SELECT_ macros for a certain type of EVP_PKEY content.119*/120#define MAKE_BLOB_ENCODER(impl, type, selection_name) \121static OSSL_FUNC_encoder_import_object_fn \122impl##2blob_import_object; \123static OSSL_FUNC_encoder_free_object_fn impl##2blob_free_object; \124static OSSL_FUNC_encoder_does_selection_fn \125impl##2blob_does_selection; \126static OSSL_FUNC_encoder_encode_fn impl##2blob_encode; \127\128static void *impl##2blob_import_object(void *ctx, int selection, \129const OSSL_PARAM params[]) \130{ \131return ossl_prov_import_key(ossl_##impl##_keymgmt_functions, \132ctx, selection, params); \133} \134static void impl##2blob_free_object(void *key) \135{ \136ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key); \137} \138static int impl##2blob_does_selection(void *ctx, int selection) \139{ \140return key2blob_check_selection(selection, \141EVP_PKEY_##selection_name); \142} \143static int impl##2blob_encode(void *vctx, OSSL_CORE_BIO *cout, \144const void *key, \145const OSSL_PARAM key_abstract[], \146int selection, \147OSSL_PASSPHRASE_CALLBACK *cb, \148void *cbarg) \149{ \150/* We don't deal with abstract objects */ \151if (key_abstract != NULL) { \152ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); \153return 0; \154} \155return key2blob_encode(vctx, key, selection, cout); \156} \157const OSSL_DISPATCH ossl_##impl##_to_blob_encoder_functions[] = { \158{ OSSL_FUNC_ENCODER_NEWCTX, \159(void (*)(void))key2blob_newctx }, \160{ OSSL_FUNC_ENCODER_FREECTX, \161(void (*)(void))key2blob_freectx }, \162{ OSSL_FUNC_ENCODER_DOES_SELECTION, \163(void (*)(void))impl##2blob_does_selection }, \164{ OSSL_FUNC_ENCODER_IMPORT_OBJECT, \165(void (*)(void))impl##2blob_import_object }, \166{ OSSL_FUNC_ENCODER_FREE_OBJECT, \167(void (*)(void))impl##2blob_free_object }, \168{ OSSL_FUNC_ENCODER_ENCODE, \169(void (*)(void))impl##2blob_encode }, \170OSSL_DISPATCH_END \171}172173#ifndef OPENSSL_NO_EC174MAKE_BLOB_ENCODER(ec, ec, PUBLIC_KEY);175# ifndef OPENSSL_NO_SM2176MAKE_BLOB_ENCODER(sm2, ec, PUBLIC_KEY);177# endif178#endif179180181