aboutsummaryrefslogtreecommitdiff
path: root/crypto/encode_decode/decoder_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/encode_decode/decoder_lib.c')
-rw-r--r--crypto/encode_decode/decoder_lib.c149
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;
}