From ebfdb63d96496274106b4192fda6039cbb272bae Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Mon, 26 Oct 2020 13:06:01 +0100 Subject: [PATCH] DECODER: Add support for specifying the outermost input structure Reviewed-by: Shane Lontis (Merged from https://github.com/openssl/openssl/pull/13248) --- crypto/encode_decode/decoder_lib.c | 58 +++++++++++++++++++++++++--- crypto/encode_decode/encoder_local.h | 22 +++++++++++ include/openssl/core_names.h | 5 ++- include/openssl/decoder.h | 6 +++ util/libcrypto.num | 3 ++ 5 files changed, 87 insertions(+), 7 deletions(-) diff --git a/crypto/encode_decode/decoder_lib.c b/crypto/encode_decode/decoder_lib.c index 20350a8cd61..64e6bcc1855 100644 --- a/crypto/encode_decode/decoder_lib.c +++ b/crypto/encode_decode/decoder_lib.c @@ -98,6 +98,21 @@ int OSSL_DECODER_from_data(OSSL_DECODER_CTX *ctx, const unsigned char **pdata, return ret; } +int OSSL_DECODER_CTX_set_selection(OSSL_DECODER_CTX *ctx, int selection) +{ + if (!ossl_assert(ctx != NULL)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + /* + * 0 is a valid selection, and means that the caller leaves + * it to code to discover what the selection is. + */ + ctx->selection = selection; + return 1; +} + int OSSL_DECODER_CTX_set_input_type(OSSL_DECODER_CTX *ctx, const char *input_type) { @@ -114,11 +129,27 @@ int OSSL_DECODER_CTX_set_input_type(OSSL_DECODER_CTX *ctx, return 1; } +int OSSL_DECODER_CTX_set_input_structure(OSSL_DECODER_CTX *ctx, + const char *input_structure) +{ + if (!ossl_assert(ctx != NULL)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + /* + * NULL is a valid starting input type, and means that the caller leaves + * it to code to discover what the starting input type is. + */ + ctx->input_structure = input_structure; + return 1; +} + OSSL_DECODER_INSTANCE *ossl_decoder_instance_new(OSSL_DECODER *decoder, void *decoderctx) { OSSL_DECODER_INSTANCE *decoder_inst = NULL; - OSSL_PARAM params[2]; + OSSL_PARAM params[3]; if (!ossl_assert(decoder != NULL)) { ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); @@ -140,16 +171,22 @@ OSSL_DECODER_INSTANCE *ossl_decoder_instance_new(OSSL_DECODER *decoder, goto err; } - /* Cache the input type for this encoder */ + /* Cache the input type for this decoder */ params[0] = OSSL_PARAM_construct_utf8_ptr(OSSL_DECODER_PARAM_INPUT_TYPE, (char **)&decoder_inst->input_type, 0); - params[1] = OSSL_PARAM_construct_end(); + params[1] = + OSSL_PARAM_construct_utf8_ptr(OSSL_DECODER_PARAM_INPUT_STRUCTURE, + (char **)&decoder_inst->input_structure, + 0); + params[2] = OSSL_PARAM_construct_end(); if (!decoder->get_params(params) || !OSSL_PARAM_modified(¶ms[0])) goto err; + decoder_inst->flag_input_structure_was_set = + OSSL_PARAM_modified(¶ms[1]); decoder_inst->decoder = decoder; decoder_inst->decoderctx = decoderctx; return decoder_inst; @@ -171,7 +208,7 @@ void ossl_decoder_instance_free(OSSL_DECODER_INSTANCE *decoder_inst) } int ossl_decoder_ctx_add_decoder_inst(OSSL_DECODER_CTX *ctx, - OSSL_DECODER_INSTANCE *di) + OSSL_DECODER_INSTANCE *di) { if (ctx->decoder_insts == NULL && (ctx->decoder_insts = @@ -225,7 +262,7 @@ int OSSL_DECODER_CTX_add_extra(OSSL_DECODER_CTX *ctx, * what the existing ones want as input, and push those newly fetched * decoders on top of the same stack. * Then it does the same again, but looping over the newly fetched - * decoders, until there are no more encoders to be fetched, or + * decoders, until there are no more decoders to be fetched, or * when we have done this 10 times. * * we do this with sliding windows on the stack by keeping track of indexes @@ -439,6 +476,16 @@ OSSL_DECODER_INSTANCE_get_input_type(OSSL_DECODER_INSTANCE *decoder_inst) return decoder_inst->input_type; } +const char * +OSSL_DECODER_INSTANCE_get_input_structure(OSSL_DECODER_INSTANCE *decoder_inst, + int *was_set) +{ + if (decoder_inst == NULL) + return NULL; + *was_set = decoder_inst->flag_input_structure_was_set; + return decoder_inst->input_structure; +} + static int decoder_process(const OSSL_PARAM params[], void *arg) { struct decoder_process_data_st *data = arg; @@ -564,6 +611,7 @@ static int decoder_process(const OSSL_PARAM params[], void *arg) /* Recurse */ new_data.current_decoder_inst_index = i; ok = new_decoder->decode(new_decoderctx, (OSSL_CORE_BIO *)bio, + new_data.ctx->selection, decoder_process, &new_data, ossl_pw_passphrase_callback_dec, &new_data.ctx->pwdata); diff --git a/crypto/encode_decode/encoder_local.h b/crypto/encode_decode/encoder_local.h index a57d0cd16c5..9378393a427 100644 --- a/crypto/encode_decode/encoder_local.h +++ b/crypto/encode_decode/encoder_local.h @@ -96,6 +96,9 @@ struct ossl_decoder_instance_st { OSSL_DECODER *decoder; /* Never NULL */ void *decoderctx; /* Never NULL */ const char *input_type; /* Never NULL */ + const char *input_structure; /* May be NULL */ + + unsigned int flag_input_structure_was_set : 1; }; DEFINE_STACK_OF(OSSL_DECODER_INSTANCE) @@ -108,6 +111,25 @@ struct ossl_decoder_ctx_st { * regardless of their respective input type. */ const char *start_input_type; + /* + * The desired input structure, if that's relevant for the type of + * object being encoded. It may be used for selection of the ending + * decoder implementations in a chain, i.e. those chosen using the + * expected output data type. + */ + const char *input_structure; + /* + * Select what parts of an object are expected. This may affect what + * decoder implementations are selected, because there are structures + * that look different depending on this selection; for example, EVP_PKEY + * objects often have different encoding structures for private keys, + * public keys and key parameters. + * This selection is bit encoded, and the bits correspond to selection + * bits available with the provider side operation. For example, when + * encoding an EVP_PKEY, the OSSL_KEYMGMT_SELECT_ macros are used for + * this. + */ + int selection; /* * Decoders that are components of any current decoding path. diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h index 43be4ae145b..11a4168cc16 100644 --- a/include/openssl/core_names.h +++ b/include/openssl/core_names.h @@ -457,8 +457,9 @@ extern "C" { #define OSSL_ENCODER_PARAM_INPUT_TYPE "input-type" #define OSSL_ENCODER_PARAM_OUTPUT_TYPE "output-type" -#define OSSL_DECODER_PARAM_PROPERTIES OSSL_ALG_PARAM_PROPERTIES -#define OSSL_DECODER_PARAM_INPUT_TYPE "input-type" +#define OSSL_DECODER_PARAM_PROPERTIES OSSL_ALG_PARAM_PROPERTIES +#define OSSL_DECODER_PARAM_INPUT_TYPE "input-type" +#define OSSL_DECODER_PARAM_INPUT_STRUCTURE "input-structure" /* Passphrase callback parameters */ #define OSSL_PASSPHRASE_PARAM_INFO "info" diff --git a/include/openssl/decoder.h b/include/openssl/decoder.h index 1c6bc8e4984..8b360e6198f 100644 --- a/include/openssl/decoder.h +++ b/include/openssl/decoder.h @@ -68,8 +68,11 @@ int OSSL_DECODER_CTX_set_passphrase_ui(OSSL_DECODER_CTX *ctx, * These will discover all provided methods */ +int OSSL_DECODER_CTX_set_selection(OSSL_DECODER_CTX *ctx, int selection); int OSSL_DECODER_CTX_set_input_type(OSSL_DECODER_CTX *ctx, const char *input_type); +int OSSL_DECODER_CTX_set_input_structure(OSSL_DECODER_CTX *ctx, + const char *input_structure); int OSSL_DECODER_CTX_add_decoder(OSSL_DECODER_CTX *ctx, OSSL_DECODER *decoder); int OSSL_DECODER_CTX_add_extra(OSSL_DECODER_CTX *ctx, OSSL_LIB_CTX *libctx, const char *propq); @@ -82,6 +85,9 @@ void * OSSL_DECODER_INSTANCE_get_decoder_ctx(OSSL_DECODER_INSTANCE *decoder_inst); const char * OSSL_DECODER_INSTANCE_get_input_type(OSSL_DECODER_INSTANCE *decoder_inst); +const char * +OSSL_DECODER_INSTANCE_get_input_structure(OSSL_DECODER_INSTANCE *decoder_inst, + int *was_set); typedef int OSSL_DECODER_CONSTRUCT(OSSL_DECODER_INSTANCE *decoder_inst, const OSSL_PARAM *params, diff --git a/util/libcrypto.num b/util/libcrypto.num index 9437e30e851..40e1fcb43af 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5285,3 +5285,6 @@ EVP_PKEY_CTX_get0_libctx ? 3_0_0 EXIST::FUNCTION: EVP_PKEY_CTX_get0_propq ? 3_0_0 EXIST::FUNCTION: EVP_PKEY_set1_encoded_public_key ? 3_0_0 EXIST::FUNCTION: EVP_PKEY_get1_encoded_public_key ? 3_0_0 EXIST::FUNCTION: +OSSL_DECODER_CTX_set_selection ? 3_0_0 EXIST::FUNCTION: +OSSL_DECODER_CTX_set_input_structure ? 3_0_0 EXIST::FUNCTION: +OSSL_DECODER_INSTANCE_get_input_structure ? 3_0_0 EXIST::FUNCTION: -- 2.47.2