diff options
Diffstat (limited to 'crypto/encode_decode/decoder_lib.c')
-rw-r--r-- | crypto/encode_decode/decoder_lib.c | 149 |
1 files changed, 130 insertions, 19 deletions
diff --git a/crypto/encode_decode/decoder_lib.c b/crypto/encode_decode/decoder_lib.c index 2e4b7ed60b9c..ffcf3cde1155 100644 --- a/crypto/encode_decode/decoder_lib.c +++ b/crypto/encode_decode/decoder_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -18,9 +18,10 @@ #include <openssl/trace.h> #include "internal/bio.h" #include "internal/provider.h" +#include "internal/namemap.h" #include "crypto/decoder.h" #include "encoder_local.h" -#include "e_os.h" +#include "internal/e_os.h" struct decoder_process_data_st { OSSL_DECODER_CTX *ctx; @@ -209,6 +210,34 @@ int OSSL_DECODER_CTX_set_input_structure(OSSL_DECODER_CTX *ctx, return 1; } +OSSL_DECODER_INSTANCE * +ossl_decoder_instance_new_forprov(OSSL_DECODER *decoder, void *provctx, + const char *input_structure) +{ + void *decoderctx; + + if (!ossl_assert(decoder != NULL)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + decoderctx = decoder->newctx(provctx); + if (decoderctx == NULL) + return 0; + if (input_structure != NULL && decoder->set_ctx_params != NULL) { + OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END }; + + params[0] = + OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE, + (char *)input_structure, 0); + if (!decoder->set_ctx_params(decoderctx, params)) { + decoder->freectx(decoderctx); + return 0; + } + } + return ossl_decoder_instance_new(decoder, decoderctx); +} + OSSL_DECODER_INSTANCE *ossl_decoder_instance_new(OSSL_DECODER *decoder, void *decoderctx) { @@ -223,10 +252,8 @@ OSSL_DECODER_INSTANCE *ossl_decoder_instance_new(OSSL_DECODER *decoder, return 0; } - if ((decoder_inst = OPENSSL_zalloc(sizeof(*decoder_inst))) == NULL) { - ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); + if ((decoder_inst = OPENSSL_zalloc(sizeof(*decoder_inst))) == NULL) return 0; - } prov = OSSL_DECODER_get0_provider(decoder); libctx = ossl_provider_libctx(prov); @@ -241,6 +268,7 @@ OSSL_DECODER_INSTANCE *ossl_decoder_instance_new(OSSL_DECODER *decoder, /* The "input" property is mandatory */ prop = ossl_property_find_property(props, libctx, "input"); decoder_inst->input_type = ossl_property_get_string_value(libctx, prop); + decoder_inst->input_type_id = 0; if (decoder_inst->input_type == NULL) { ERR_raise_data(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROPERTY_DEFINITION, "the mandatory 'input' property is missing " @@ -281,6 +309,47 @@ void ossl_decoder_instance_free(OSSL_DECODER_INSTANCE *decoder_inst) } } +OSSL_DECODER_INSTANCE *ossl_decoder_instance_dup(const OSSL_DECODER_INSTANCE *src) +{ + OSSL_DECODER_INSTANCE *dest; + const OSSL_PROVIDER *prov; + void *provctx; + + if ((dest = OPENSSL_zalloc(sizeof(*dest))) == NULL) + return NULL; + + *dest = *src; + if (!OSSL_DECODER_up_ref(dest->decoder)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INTERNAL_ERROR); + goto err; + } + prov = OSSL_DECODER_get0_provider(dest->decoder); + provctx = OSSL_PROVIDER_get0_provider_ctx(prov); + + dest->decoderctx = dest->decoder->newctx(provctx); + if (dest->decoderctx == NULL) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INTERNAL_ERROR); + OSSL_DECODER_free(dest->decoder); + goto err; + } + + return dest; + + err: + OPENSSL_free(dest); + return NULL; +} + +void ossl_decoder_ctx_set_harderr(OSSL_DECODER_CTX *ctx) +{ + ctx->harderr = 1; +} + +int ossl_decoder_ctx_get_harderr(const OSSL_DECODER_CTX *ctx) +{ + return ctx->harderr; +} + int ossl_decoder_ctx_add_decoder_inst(OSSL_DECODER_CTX *ctx, OSSL_DECODER_INSTANCE *di) { @@ -289,7 +358,7 @@ int ossl_decoder_ctx_add_decoder_inst(OSSL_DECODER_CTX *ctx, if (ctx->decoder_insts == NULL && (ctx->decoder_insts = sk_OSSL_DECODER_INSTANCE_new_null()) == NULL) { - ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_CRYPTO_LIB); return 0; } @@ -343,6 +412,8 @@ int OSSL_DECODER_CTX_add_decoder(OSSL_DECODER_CTX *ctx, OSSL_DECODER *decoder) struct collect_extra_decoder_data_st { OSSL_DECODER_CTX *ctx; const char *output_type; + int output_type_id; + /* * 0 to check that the decoder's input type is the same as the decoder name * 1 to check that the decoder's input type differs from the decoder name @@ -370,7 +441,7 @@ static void collect_extra_decoder(OSSL_DECODER *decoder, void *arg) const OSSL_PROVIDER *prov = OSSL_DECODER_get0_provider(decoder); void *provctx = OSSL_PROVIDER_get0_provider_ctx(prov); - if (OSSL_DECODER_is_a(decoder, data->output_type)) { + if (ossl_decoder_fast_is_a(decoder, data->output_type, &data->output_type_id)) { void *decoderctx = NULL; OSSL_DECODER_INSTANCE *di = NULL; @@ -405,6 +476,20 @@ static void collect_extra_decoder(OSSL_DECODER *decoder, void *arg) if ((decoderctx = decoder->newctx(provctx)) == NULL) return; + if (decoder->set_ctx_params != NULL + && data->ctx->input_structure != NULL) { + OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END }; + const char *str = data->ctx->input_structure; + + params[0] = + OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE, + (char *)str, 0); + if (!decoder->set_ctx_params(decoderctx, params)) { + decoder->freectx(decoderctx); + return; + } + } + if ((di = ossl_decoder_instance_new(decoder, decoderctx)) == NULL) { decoder->freectx(decoderctx); return; @@ -413,8 +498,9 @@ static void collect_extra_decoder(OSSL_DECODER *decoder, void *arg) switch (data->type_check) { case IS_SAME: /* If it differs, this is not a decoder to add for now. */ - if (!OSSL_DECODER_is_a(decoder, - OSSL_DECODER_INSTANCE_get_input_type(di))) { + if (!ossl_decoder_fast_is_a(decoder, + OSSL_DECODER_INSTANCE_get_input_type(di), + &di->input_type_id)) { ossl_decoder_instance_free(di); OSSL_TRACE_BEGIN(DECODER) { BIO_printf(trc_out, @@ -425,8 +511,9 @@ static void collect_extra_decoder(OSSL_DECODER *decoder, void *arg) break; case IS_DIFFERENT: /* If it's the same, this is not a decoder to add for now. */ - if (OSSL_DECODER_is_a(decoder, - OSSL_DECODER_INSTANCE_get_input_type(di))) { + if (ossl_decoder_fast_is_a(decoder, + OSSL_DECODER_INSTANCE_get_input_type(di), + &di->input_type_id)) { ossl_decoder_instance_free(di); OSSL_TRACE_BEGIN(DECODER) { BIO_printf(trc_out, @@ -502,7 +589,7 @@ int OSSL_DECODER_CTX_add_extra(OSSL_DECODER_CTX *ctx, skdecoders = sk_OSSL_DECODER_new_null(); if (skdecoders == NULL) { - ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_CRYPTO_LIB); return 0; } OSSL_DECODER_do_all_provided(libctx, collect_all_decoders, skdecoders); @@ -534,6 +621,7 @@ int OSSL_DECODER_CTX_add_extra(OSSL_DECODER_CTX *ctx, data.output_type = OSSL_DECODER_INSTANCE_get_input_type(decoder_inst); + data.output_type_id = 0; for (j = 0; j < numdecoders; j++) collect_extra_decoder(sk_OSSL_DECODER_value(skdecoders, j), @@ -687,6 +775,8 @@ static int decoder_process(const OSSL_PARAM params[], void *arg) struct decoder_process_data_st new_data; const char *data_type = NULL; const char *data_structure = NULL; + /* Saved to restore on return, mutated in PEM->DER transition. */ + const char *start_input_type = ctx->start_input_type; /* * This is an indicator up the call stack that something was indeed @@ -777,6 +867,23 @@ static int decoder_process(const OSSL_PARAM params[], void *arg) if (p != NULL && !OSSL_PARAM_get_utf8_string_ptr(p, &data_structure)) goto end; + /* Get the new input type if there is one */ + p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_INPUT_TYPE); + if (p != NULL) { + if (!OSSL_PARAM_get_utf8_string_ptr(p, &ctx->start_input_type)) + goto end; + /* + * When switching PKCS8 from PEM to DER we decrypt the data if needed + * and then determine the algorithm OID. Likewise, with SPKI, only + * this time sans decryption. + */ + if (ctx->input_structure != NULL + && (OPENSSL_strcasecmp(ctx->input_structure, "SubjectPublicKeyInfo") == 0 + || OPENSSL_strcasecmp(data_structure, "PrivateKeyInfo") == 0 + || OPENSSL_strcasecmp(ctx->input_structure, "PrivateKeyInfo") == 0)) + data->flag_input_structure_checked = 1; + } + /* * If the data structure is "type-specific" and the data type is * given, we drop the data structure. The reasoning is that the @@ -818,7 +925,7 @@ static int decoder_process(const OSSL_PARAM params[], void *arg) } if ((cbio = ossl_core_bio_new_from_bio(bio)) == NULL) { - ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_BIO_LIB); goto end; } @@ -827,6 +934,7 @@ static int decoder_process(const OSSL_PARAM params[], void *arg) sk_OSSL_DECODER_INSTANCE_value(ctx->decoder_insts, i); OSSL_DECODER *new_decoder = OSSL_DECODER_INSTANCE_get_decoder(new_decoder_inst); + const char *new_decoder_name = NULL; void *new_decoderctx = OSSL_DECODER_INSTANCE_get_decoder_ctx(new_decoder_inst); const char *new_input_type = @@ -837,12 +945,13 @@ static int decoder_process(const OSSL_PARAM params[], void *arg) &n_i_s_was_set); OSSL_TRACE_BEGIN(DECODER) { + new_decoder_name = OSSL_DECODER_get0_name(new_decoder); BIO_printf(trc_out, "(ctx %p) %s [%u] Considering decoder instance %p (decoder %p):\n" " %s with %s\n", (void *)new_data.ctx, LEVEL, (unsigned int)i, (void *)new_decoder_inst, (void *)new_decoder, - OSSL_DECODER_get0_name(new_decoder), + new_decoder_name, OSSL_DECODER_get0_properties(new_decoder)); } OSSL_TRACE_END(DECODER); @@ -868,7 +977,8 @@ static int decoder_process(const OSSL_PARAM params[], void *arg) * |new_input_type| holds the value of the "input-type" parameter * for the decoder we're currently considering. */ - if (decoder != NULL && !OSSL_DECODER_is_a(decoder, new_input_type)) { + if (decoder != NULL && !ossl_decoder_fast_is_a(decoder, new_input_type, + &new_decoder_inst->input_type_id)) { OSSL_TRACE_BEGIN(DECODER) { BIO_printf(trc_out, "(ctx %p) %s [%u] the input type doesn't match the name of the previous decoder (%p), skipping...\n", @@ -946,9 +1056,9 @@ static int decoder_process(const OSSL_PARAM params[], void *arg) /* Recurse */ OSSL_TRACE_BEGIN(DECODER) { BIO_printf(trc_out, - "(ctx %p) %s [%u] Running decoder instance %p\n", + "(ctx %p) %s [%u] Running decoder instance %s (%p)\n", (void *)new_data.ctx, LEVEL, (unsigned int)i, - (void *)new_decoder_inst); + new_decoder_name, (void *)new_decoder_inst); } OSSL_TRACE_END(DECODER); /* @@ -968,10 +1078,10 @@ static int decoder_process(const OSSL_PARAM params[], void *arg) OSSL_TRACE_BEGIN(DECODER) { BIO_printf(trc_out, - "(ctx %p) %s [%u] Running decoder instance %p => %d" + "(ctx %p) %s [%u] Running decoder instance %s (%p) => %d" " (recursed further: %s, construct called: %s)\n", (void *)new_data.ctx, LEVEL, (unsigned int)i, - (void *)new_decoder_inst, ok, + new_decoder_name, (void *)new_decoder_inst, ok, new_data.flag_next_level_called ? "yes" : "no", new_data.flag_construct_called ? "yes" : "no"); } OSSL_TRACE_END(DECODER); @@ -996,5 +1106,6 @@ static int decoder_process(const OSSL_PARAM params[], void *arg) end: ossl_core_bio_free(cbio); BIO_free(new_data.bio); + ctx->start_input_type = start_input_type; return ok; } |