/*
 * Copyright 2020-2021 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
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

#include <openssl/core_names.h>
#include <openssl/bio.h>
#include <openssl/params.h>
#include <openssl/provider.h>
#include <openssl/evperr.h>
#include <openssl/ecerr.h>
#include <openssl/pkcs12err.h>
#include <openssl/x509err.h>
#include <openssl/trace.h>
#include "internal/bio.h"
#include "internal/provider.h"
#include "crypto/decoder.h"
#include "encoder_local.h"
#include "e_os.h"

struct decoder_process_data_st {
    OSSL_DECODER_CTX *ctx;

    /* Current BIO */
    BIO *bio;

    /* Index of the current decoder instance to be processed */
    size_t current_decoder_inst_index;
    /* For tracing, count recursion level */
    size_t recursion;

    /*-
     * Flags
     */
    unsigned int flag_next_level_called : 1;
    unsigned int flag_construct_called : 1;
};

static int decoder_process(const OSSL_PARAM params[], void *arg);

int OSSL_DECODER_from_bio(OSSL_DECODER_CTX *ctx, BIO *in)
{
    struct decoder_process_data_st data;
    int ok = 0;
    BIO *new_bio = NULL;

    if (in == NULL) {
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
        return 0;
    }

    if (OSSL_DECODER_CTX_get_num_decoders(ctx) == 0) {
        ERR_raise_data(ERR_LIB_OSSL_DECODER, OSSL_DECODER_R_DECODER_NOT_FOUND,
                       "No decoders were found. For standard decoders you need "
                       "at least one of the default or base providers "
                       "available. Did you forget to load them?");
        return 0;
    }

    if (BIO_tell(in) < 0) {
        new_bio = BIO_new(BIO_f_readbuffer());
        if (new_bio == NULL)
            return 0;
        in = BIO_push(new_bio, in);
    }
    memset(&data, 0, sizeof(data));
    data.ctx = ctx;
    data.bio = in;

    /* Enable passphrase caching */
    (void)ossl_pw_enable_passphrase_caching(&ctx->pwdata);

    ok = decoder_process(NULL, &data);

    if (!data.flag_construct_called) {
        const char *spaces
            = ctx->start_input_type != NULL && ctx->input_structure != NULL
            ? " " : "";
        const char *input_type_label
            = ctx->start_input_type != NULL ? "Input type: " : "";
        const char *input_structure_label
            = ctx->input_structure != NULL ? "Input structure: " : "";
        const char *comma
            = ctx->start_input_type != NULL && ctx->input_structure != NULL
            ? ", " : "";
        const char *input_type
            = ctx->start_input_type != NULL ? ctx->start_input_type : "";
        const char *input_structure
            = ctx->input_structure != NULL ? ctx->input_structure : "";

        if (BIO_eof(in) == 0 || ERR_peek_error() == 0)
            /* Prevent spurious decoding error */
            ERR_raise_data(ERR_LIB_OSSL_DECODER, ERR_R_UNSUPPORTED,
                           "No supported data to decode. %s%s%s%s%s%s",
                           spaces, input_type_label, input_type, comma,
                           input_structure_label, input_structure);
        ok = 0;
    }

    /* Clear any internally cached passphrase */
    (void)ossl_pw_clear_passphrase_cache(&ctx->pwdata);

    if (new_bio != NULL) {
        BIO_pop(new_bio);
        BIO_free(new_bio);
    }
    return ok;
}

#ifndef OPENSSL_NO_STDIO
static BIO *bio_from_file(FILE *fp)
{
    BIO *b;

    if ((b = BIO_new(BIO_s_file())) == NULL) {
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_BIO_LIB);
        return NULL;
    }
    BIO_set_fp(b, fp, BIO_NOCLOSE);
    return b;
}

int OSSL_DECODER_from_fp(OSSL_DECODER_CTX *ctx, FILE *fp)
{
    BIO *b = bio_from_file(fp);
    int ret = 0;

    if (b != NULL)
        ret = OSSL_DECODER_from_bio(ctx, b);

    BIO_free(b);
    return ret;
}
#endif

int OSSL_DECODER_from_data(OSSL_DECODER_CTX *ctx, const unsigned char **pdata,
                           size_t *pdata_len)
{
    BIO *membio;
    int ret = 0;

    if (pdata == NULL || *pdata == NULL || pdata_len == NULL) {
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
        return 0;
    }

    membio = BIO_new_mem_buf(*pdata, (int)*pdata_len);
    if (OSSL_DECODER_from_bio(ctx, membio)) {
        *pdata_len = (size_t)BIO_get_mem_data(membio, pdata);
        ret = 1;
    }
    BIO_free(membio);

    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)
{
    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->start_input_type = input_type;
    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 structure, and means that the caller
     * leaves it to code to discover what the starting input structure 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;
    const OSSL_PROVIDER *prov;
    OSSL_LIB_CTX *libctx;
    const OSSL_PROPERTY_LIST *props;
    const OSSL_PROPERTY_DEFINITION *prop;

    if (!ossl_assert(decoder != NULL)) {
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
        return 0;
    }

    if ((decoder_inst = OPENSSL_zalloc(sizeof(*decoder_inst))) == NULL) {
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
        return 0;
    }
    if (!OSSL_DECODER_up_ref(decoder)) {
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INTERNAL_ERROR);
        goto err;
    }

    prov = OSSL_DECODER_get0_provider(decoder);
    libctx = ossl_provider_libctx(prov);
    props = ossl_decoder_parsed_properties(decoder);
    if (props == NULL) {
        ERR_raise_data(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROPERTY_DEFINITION,
                       "there are no property definitions with decoder %s",
                       OSSL_DECODER_get0_name(decoder));
        goto err;
    }

    /* The "input" property is mandatory */
    prop = ossl_property_find_property(props, libctx, "input");
    decoder_inst->input_type = ossl_property_get_string_value(libctx, prop);
    if (decoder_inst->input_type == NULL) {
        ERR_raise_data(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROPERTY_DEFINITION,
                       "the mandatory 'input' property is missing "
                       "for decoder %s (properties: %s)",
                       OSSL_DECODER_get0_name(decoder),
                       OSSL_DECODER_get0_properties(decoder));
        goto err;
    }

    /* The "structure" property is optional */
    prop = ossl_property_find_property(props, libctx, "structure");
    if (prop != NULL) {
        decoder_inst->input_structure
            = ossl_property_get_string_value(libctx, prop);
    }

    decoder_inst->decoder = decoder;
    decoder_inst->decoderctx = decoderctx;
    return decoder_inst;
 err:
    ossl_decoder_instance_free(decoder_inst);
    return NULL;
}

void ossl_decoder_instance_free(OSSL_DECODER_INSTANCE *decoder_inst)
{
    if (decoder_inst != NULL) {
        if (decoder_inst->decoder != NULL)
            decoder_inst->decoder->freectx(decoder_inst->decoderctx);
        decoder_inst->decoderctx = NULL;
        OSSL_DECODER_free(decoder_inst->decoder);
        decoder_inst->decoder = NULL;
        OPENSSL_free(decoder_inst);
    }
}

int ossl_decoder_ctx_add_decoder_inst(OSSL_DECODER_CTX *ctx,
                                      OSSL_DECODER_INSTANCE *di)
{
    int ok;

    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);
        return 0;
    }

    ok = (sk_OSSL_DECODER_INSTANCE_push(ctx->decoder_insts, di) > 0);
    if (ok) {
        OSSL_TRACE_BEGIN(DECODER) {
            BIO_printf(trc_out,
                       "(ctx %p) Added decoder instance %p for decoder %p\n"
                       "    %s with %s\n",
                       (void *)ctx, (void *)di, (void *)di->decoder,
                       OSSL_DECODER_get0_name(di->decoder),
                       OSSL_DECODER_get0_properties(di->decoder));
        } OSSL_TRACE_END(DECODER);
    }
    return ok;
}

int OSSL_DECODER_CTX_add_decoder(OSSL_DECODER_CTX *ctx, OSSL_DECODER *decoder)
{
    OSSL_DECODER_INSTANCE *decoder_inst = NULL;
    const OSSL_PROVIDER *prov = NULL;
    void *decoderctx = NULL;
    void *provctx = NULL;

    if (!ossl_assert(ctx != NULL) || !ossl_assert(decoder != NULL)) {
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
        return 0;
    }

    prov = OSSL_DECODER_get0_provider(decoder);
    provctx = OSSL_PROVIDER_get0_provider_ctx(prov);

    if ((decoderctx = decoder->newctx(provctx)) == NULL
        || (decoder_inst =
            ossl_decoder_instance_new(decoder, decoderctx)) == NULL)
        goto err;
    /* Avoid double free of decoderctx on further errors */
    decoderctx = NULL;

    if (!ossl_decoder_ctx_add_decoder_inst(ctx, decoder_inst))
        goto err;

    return 1;
 err:
    ossl_decoder_instance_free(decoder_inst);
    if (decoderctx != NULL)
        decoder->freectx(decoderctx);
    return 0;
}

struct collect_extra_decoder_data_st {
    OSSL_DECODER_CTX *ctx;
    const char *output_type;
    /*
     * 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
     */
    enum { IS_SAME = 0, IS_DIFFERENT = 1 } type_check;
    size_t w_prev_start, w_prev_end; /* "previous" decoders */
    size_t w_new_start, w_new_end;   /* "new" decoders */
};

DEFINE_STACK_OF(OSSL_DECODER)

static void collect_all_decoders(OSSL_DECODER *decoder, void *arg)
{
    STACK_OF(OSSL_DECODER) *skdecoders = arg;

    if (OSSL_DECODER_up_ref(decoder))
        sk_OSSL_DECODER_push(skdecoders, decoder);
}

static void collect_extra_decoder(OSSL_DECODER *decoder, void *arg)
{
    struct collect_extra_decoder_data_st *data = arg;
    size_t j;
    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)) {
        void *decoderctx = NULL;
        OSSL_DECODER_INSTANCE *di = NULL;

        OSSL_TRACE_BEGIN(DECODER) {
            BIO_printf(trc_out,
                       "(ctx %p) [%d] Checking out decoder %p:\n"
                       "    %s with %s\n",
                       (void *)data->ctx, data->type_check, (void *)decoder,
                       OSSL_DECODER_get0_name(decoder),
                       OSSL_DECODER_get0_properties(decoder));
        } OSSL_TRACE_END(DECODER);

        /*
         * Check that we don't already have this decoder in our stack,
         * starting with the previous windows but also looking at what
         * we have added in the current window.
         */
        for (j = data->w_prev_start; j < data->w_new_end; j++) {
            OSSL_DECODER_INSTANCE *check_inst =
                sk_OSSL_DECODER_INSTANCE_value(data->ctx->decoder_insts, j);

            if (decoder->base.algodef == check_inst->decoder->base.algodef) {
                /* We found it, so don't do anything more */
                OSSL_TRACE_BEGIN(DECODER) {
                    BIO_printf(trc_out,
                               "    REJECTED: already exists in the chain\n");
                } OSSL_TRACE_END(DECODER);
                return;
            }
        }

        if ((decoderctx = decoder->newctx(provctx)) == NULL)
            return;

        if ((di = ossl_decoder_instance_new(decoder, decoderctx)) == NULL) {
            decoder->freectx(decoderctx);
            return;
        }

        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))) {
                ossl_decoder_instance_free(di);
                OSSL_TRACE_BEGIN(DECODER) {
                    BIO_printf(trc_out,
                               "    REJECTED: input type doesn't match output type\n");
                } OSSL_TRACE_END(DECODER);
                return;
            }
            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))) {
                ossl_decoder_instance_free(di);
                OSSL_TRACE_BEGIN(DECODER) {
                    BIO_printf(trc_out,
                               "    REJECTED: input type matches output type\n");
                } OSSL_TRACE_END(DECODER);
                return;
            }
            break;
        }

        /*
         * Apart from keeping w_new_end up to date, We don't care about
         * errors here.  If it doesn't collect, then it doesn't...
         */
        if (!ossl_decoder_ctx_add_decoder_inst(data->ctx, di)) {
            ossl_decoder_instance_free(di);
            return;
        }

        data->w_new_end++;
    }
}

int OSSL_DECODER_CTX_add_extra(OSSL_DECODER_CTX *ctx,
                               OSSL_LIB_CTX *libctx, const char *propq)
{
    /*
     * This function goes through existing decoder methods in
     * |ctx->decoder_insts|, and tries to fetch new decoders that produce
     * 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 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
     * and of the end.
     *
     * +----------------+
     * |   DER to RSA   | <--- w_prev_start
     * +----------------+
     * |   DER to DSA   |
     * +----------------+
     * |   DER to DH    |
     * +----------------+
     * |   PEM to DER   | <--- w_prev_end, w_new_start
     * +----------------+
     *                    <--- w_new_end
     */
    struct collect_extra_decoder_data_st data;
    size_t depth = 0; /* Counts the number of iterations */
    size_t count; /* Calculates how many were added in each iteration */
    size_t numdecoders;
    STACK_OF(OSSL_DECODER) *skdecoders;

    if (!ossl_assert(ctx != NULL)) {
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
        return 0;
    }

    /*
     * If there is no stack of OSSL_DECODER_INSTANCE, we have nothing
     * more to add.  That's fine.
     */
    if (ctx->decoder_insts == NULL)
        return 1;

    OSSL_TRACE_BEGIN(DECODER) {
        BIO_printf(trc_out, "(ctx %p) Looking for extra decoders\n",
                   (void *)ctx);
    } OSSL_TRACE_END(DECODER);


    skdecoders = sk_OSSL_DECODER_new_null();
    if (skdecoders == NULL) {
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
        return 0;
    }
    OSSL_DECODER_do_all_provided(libctx, collect_all_decoders, skdecoders);
    numdecoders = sk_OSSL_DECODER_num(skdecoders);

    memset(&data, 0, sizeof(data));
    data.ctx = ctx;
    data.w_prev_start = 0;
    data.w_prev_end = sk_OSSL_DECODER_INSTANCE_num(ctx->decoder_insts);
    do {
        size_t i, j;

        data.w_new_start = data.w_new_end = data.w_prev_end;

        /*
         * Two iterations:
         * 0.  All decoders that have the same name as their input type.
         *     This allows for decoders that unwrap some data in a specific
         *     encoding, and pass the result on with the same encoding.
         * 1.  All decoders that a different name than their input type.
         */
        for (data.type_check = IS_SAME;
             data.type_check <= IS_DIFFERENT;
             data.type_check++) {
            for (i = data.w_prev_start; i < data.w_prev_end; i++) {
                OSSL_DECODER_INSTANCE *decoder_inst =
                    sk_OSSL_DECODER_INSTANCE_value(ctx->decoder_insts, i);

                data.output_type
                    = OSSL_DECODER_INSTANCE_get_input_type(decoder_inst);


                for (j = 0; j < numdecoders; j++)
                    collect_extra_decoder(sk_OSSL_DECODER_value(skdecoders, j),
                                          &data);
            }
        }
        /* How many were added in this iteration */
        count = data.w_new_end - data.w_new_start;

        /* Slide the "previous decoder" windows */
        data.w_prev_start = data.w_new_start;
        data.w_prev_end = data.w_new_end;

        depth++;
    } while (count != 0 && depth <= 10);

    sk_OSSL_DECODER_pop_free(skdecoders, OSSL_DECODER_free);
    return 1;
}

int OSSL_DECODER_CTX_get_num_decoders(OSSL_DECODER_CTX *ctx)
{
    if (ctx == NULL || ctx->decoder_insts == NULL)
        return 0;
    return sk_OSSL_DECODER_INSTANCE_num(ctx->decoder_insts);
}

int OSSL_DECODER_CTX_set_construct(OSSL_DECODER_CTX *ctx,
                                   OSSL_DECODER_CONSTRUCT *construct)
{
    if (!ossl_assert(ctx != NULL)) {
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
        return 0;
    }
    ctx->construct = construct;
    return 1;
}

int OSSL_DECODER_CTX_set_construct_data(OSSL_DECODER_CTX *ctx,
                                        void *construct_data)
{
    if (!ossl_assert(ctx != NULL)) {
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
        return 0;
    }
    ctx->construct_data = construct_data;
    return 1;
}

int OSSL_DECODER_CTX_set_cleanup(OSSL_DECODER_CTX *ctx,
                                 OSSL_DECODER_CLEANUP *cleanup)
{
    if (!ossl_assert(ctx != NULL)) {
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
        return 0;
    }
    ctx->cleanup = cleanup;
    return 1;
}

OSSL_DECODER_CONSTRUCT *
OSSL_DECODER_CTX_get_construct(OSSL_DECODER_CTX *ctx)
{
    if (ctx == NULL)
        return NULL;
    return ctx->construct;
}

void *OSSL_DECODER_CTX_get_construct_data(OSSL_DECODER_CTX *ctx)
{
    if (ctx == NULL)
        return NULL;
    return ctx->construct_data;
}

OSSL_DECODER_CLEANUP *
OSSL_DECODER_CTX_get_cleanup(OSSL_DECODER_CTX *ctx)
{
    if (ctx == NULL)
        return NULL;
    return ctx->cleanup;
}

int OSSL_DECODER_export(OSSL_DECODER_INSTANCE *decoder_inst,
                        void *reference, size_t reference_sz,
                        OSSL_CALLBACK *export_cb, void *export_cbarg)
{
    OSSL_DECODER *decoder = NULL;
    void *decoderctx = NULL;

    if (!(ossl_assert(decoder_inst != NULL)
          && ossl_assert(reference != NULL)
          && ossl_assert(export_cb != NULL)
          && ossl_assert(export_cbarg != NULL))) {
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
        return 0;
    }

    decoder = OSSL_DECODER_INSTANCE_get_decoder(decoder_inst);
    decoderctx = OSSL_DECODER_INSTANCE_get_decoder_ctx(decoder_inst);
    return decoder->export_object(decoderctx, reference, reference_sz,
                                  export_cb, export_cbarg);
}

OSSL_DECODER *
OSSL_DECODER_INSTANCE_get_decoder(OSSL_DECODER_INSTANCE *decoder_inst)
{
    if (decoder_inst == NULL)
        return NULL;
    return decoder_inst->decoder;
}

void *
OSSL_DECODER_INSTANCE_get_decoder_ctx(OSSL_DECODER_INSTANCE *decoder_inst)
{
    if (decoder_inst == NULL)
        return NULL;
    return decoder_inst->decoderctx;
}

const char *
OSSL_DECODER_INSTANCE_get_input_type(OSSL_DECODER_INSTANCE *decoder_inst)
{
    if (decoder_inst == NULL)
        return NULL;
    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;
    OSSL_DECODER_CTX *ctx = data->ctx;
    OSSL_DECODER_INSTANCE *decoder_inst = NULL;
    OSSL_DECODER *decoder = NULL;
    OSSL_CORE_BIO *cbio = NULL;
    BIO *bio = data->bio;
    long loc;
    size_t i;
    int ok = 0;
    /* For recursions */
    struct decoder_process_data_st new_data;
    const char *data_type = NULL;
    const char *data_structure = NULL;

    /*
     * This is an indicator up the call stack that something was indeed
     * decoded, leading to a recursive call of this function.
     */
    data->flag_next_level_called = 1;

    memset(&new_data, 0, sizeof(new_data));
    new_data.ctx = data->ctx;
    new_data.recursion = data->recursion + 1;

#define LEVEL_STR ">>>>>>>>>>>>>>>>"
#define LEVEL (new_data.recursion < sizeof(LEVEL_STR)                   \
               ? &LEVEL_STR[sizeof(LEVEL_STR) - new_data.recursion - 1] \
               : LEVEL_STR "...")

    if (params == NULL) {
        /* First iteration, where we prepare for what is to come */

        OSSL_TRACE_BEGIN(DECODER) {
            BIO_printf(trc_out,
                       "(ctx %p) starting to walk the decoder chain\n",
                       (void *)new_data.ctx);
        } OSSL_TRACE_END(DECODER);

        data->current_decoder_inst_index =
            OSSL_DECODER_CTX_get_num_decoders(ctx);

        bio = data->bio;
    } else {
        const OSSL_PARAM *p;
        const char *trace_data_structure;

        decoder_inst =
            sk_OSSL_DECODER_INSTANCE_value(ctx->decoder_insts,
                                           data->current_decoder_inst_index);
        decoder = OSSL_DECODER_INSTANCE_get_decoder(decoder_inst);

        data->flag_construct_called = 0;
        if (ctx->construct != NULL) {
            int rv;

            OSSL_TRACE_BEGIN(DECODER) {
                BIO_printf(trc_out,
                           "(ctx %p) %s Running constructor\n",
                           (void *)new_data.ctx, LEVEL);
            } OSSL_TRACE_END(DECODER);

            rv = ctx->construct(decoder_inst, params, ctx->construct_data);

            OSSL_TRACE_BEGIN(DECODER) {
                BIO_printf(trc_out,
                           "(ctx %p) %s Running constructor => %d\n",
                           (void *)new_data.ctx, LEVEL, rv);
            } OSSL_TRACE_END(DECODER);

            data->flag_construct_called = 1;
            ok = (rv > 0);
            if (ok)
                goto end;
        }

        /* The constructor didn't return success */

        /*
         * so we try to use the object we got and feed it to any next
         * decoder that will take it.  Object references are not
         * allowed for this.
         * If this data isn't present, decoding has failed.
         */

        p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA);
        if (p == NULL || p->data_type != OSSL_PARAM_OCTET_STRING)
            goto end;
        new_data.bio = BIO_new_mem_buf(p->data, (int)p->data_size);
        if (new_data.bio == NULL)
            goto end;
        bio = new_data.bio;

        /* Get the data type if there is one */
        p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA_TYPE);
        if (p != NULL && !OSSL_PARAM_get_utf8_string_ptr(p, &data_type))
            goto end;

        /* Get the data structure if there is one */
        p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA_STRUCTURE);
        if (p != NULL && !OSSL_PARAM_get_utf8_string_ptr(p, &data_structure))
            goto end;

        /*
         * If the data structure is "type-specific" and the data type is
         * given, we drop the data structure.  The reasoning is that the
         * data type is already enough to find the applicable next decoder,
         * so an additional "type-specific" data structure is extraneous.
         *
         * Furthermore, if the OSSL_DECODER caller asked for a type specific
         * structure under another name, such as "DH", we get a mismatch
         * if the data structure we just received is "type-specific".
         * There's only so much you can do without infusing this code with
         * too special knowledge.
         */
        trace_data_structure = data_structure;
        if (data_type != NULL && data_structure != NULL
            && strcasecmp(data_structure, "type-specific") == 0)
            data_structure = NULL;

        OSSL_TRACE_BEGIN(DECODER) {
            BIO_printf(trc_out,
                       "(ctx %p) %s incoming from previous decoder (%p):\n"
                       "    data type: %s, data structure: %s%s\n",
                       (void *)new_data.ctx, LEVEL, (void *)decoder,
                       data_type, trace_data_structure,
                       (trace_data_structure == data_structure
                        ? "" : " (dropped)"));
        } OSSL_TRACE_END(DECODER);
    }

    /*
     * If we have no more decoders to look through at this point,
     * we failed
     */
    if (data->current_decoder_inst_index == 0)
        goto end;

    if ((loc = BIO_tell(bio)) < 0) {
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_BIO_LIB);
        goto end;
    }

    if ((cbio = ossl_core_bio_new_from_bio(bio)) == NULL) {
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
        goto end;
    }

    for (i = data->current_decoder_inst_index; i-- > 0;) {
        OSSL_DECODER_INSTANCE *new_decoder_inst =
            sk_OSSL_DECODER_INSTANCE_value(ctx->decoder_insts, i);
        OSSL_DECODER *new_decoder =
            OSSL_DECODER_INSTANCE_get_decoder(new_decoder_inst);
        void *new_decoderctx =
            OSSL_DECODER_INSTANCE_get_decoder_ctx(new_decoder_inst);
        const char *new_input_type =
            OSSL_DECODER_INSTANCE_get_input_type(new_decoder_inst);
        int n_i_s_was_set = 0;   /* We don't care here */
        const char *new_input_structure =
            OSSL_DECODER_INSTANCE_get_input_structure(new_decoder_inst,
                                                      &n_i_s_was_set);

        OSSL_TRACE_BEGIN(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),
                       OSSL_DECODER_get0_properties(new_decoder));
        } OSSL_TRACE_END(DECODER);

        /*
         * If |decoder| is NULL, it means we've just started, and the caller
         * may have specified what it expects the initial input to be.  If
         * that's the case, we do this extra check.
         */
        if (decoder == NULL && ctx->start_input_type != NULL
            && strcasecmp(ctx->start_input_type, new_input_type) != 0) {
            OSSL_TRACE_BEGIN(DECODER) {
                BIO_printf(trc_out,
                           "(ctx %p) %s [%u] the start input type '%s' doesn't match the input type of the considered decoder, skipping...\n",
                           (void *)new_data.ctx, LEVEL, (unsigned int)i,
                           ctx->start_input_type);
            } OSSL_TRACE_END(DECODER);
            continue;
        }

        /*
         * If we have a previous decoder, we check that the input type
         * of the next to be used matches the type of this previous one.
         * |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)) {
            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",
                           (void *)new_data.ctx, LEVEL, (unsigned int)i,
                           (void *)decoder);
            } OSSL_TRACE_END(DECODER);
            continue;
        }

        /*
         * If the previous decoder gave us a data type, we check to see
         * if that matches the decoder we're currently considering.
         */
        if (data_type != NULL && !OSSL_DECODER_is_a(new_decoder, data_type)) {
            OSSL_TRACE_BEGIN(DECODER) {
                BIO_printf(trc_out,
                           "(ctx %p) %s [%u] the previous decoder's data type doesn't match the name of the considered decoder, skipping...\n",
                           (void *)new_data.ctx, LEVEL, (unsigned int)i);
            } OSSL_TRACE_END(DECODER);
            continue;
        }

        /*
         * If the previous decoder gave us a data structure name, we check
         * to see that it matches the input data structure of the decoder
         * we're currently considering.
         */
        if (data_structure != NULL
            && (new_input_structure == NULL
                || strcasecmp(data_structure, new_input_structure) != 0)) {
            OSSL_TRACE_BEGIN(DECODER) {
                BIO_printf(trc_out,
                           "(ctx %p) %s [%u] the previous decoder's data structure doesn't match the input structure of the considered decoder, skipping...\n",
                           (void *)new_data.ctx, LEVEL, (unsigned int)i);
            } OSSL_TRACE_END(DECODER);
            continue;
        }

        /*
         * Checking the return value of BIO_reset() or BIO_seek() is unsafe.
         * Furthermore, BIO_reset() is unsafe to use if the source BIO happens
         * to be a BIO_s_mem(), because the earlier BIO_tell() gives us zero
         * no matter where we are in the underlying buffer we're reading from.
         *
         * So, we simply do a BIO_seek(), and use BIO_tell() that we're back
         * at the same position.  This is a best effort attempt, but BIO_seek()
         * and BIO_tell() should come as a pair...
         */
        (void)BIO_seek(bio, loc);
        if (BIO_tell(bio) != loc)
            goto end;

        /* Recurse */
        OSSL_TRACE_BEGIN(DECODER) {
            BIO_printf(trc_out,
                       "(ctx %p) %s [%u] Running decoder instance %p\n",
                       (void *)new_data.ctx, LEVEL, (unsigned int)i,
                       (void *)new_decoder_inst);
        } OSSL_TRACE_END(DECODER);

        /*
         * We only care about errors reported from decoder implementations
         * if it returns false (i.e. there was a fatal error).
         */
        ERR_set_mark();

        new_data.current_decoder_inst_index = i;
        ok = new_decoder->decode(new_decoderctx, cbio,
                                 new_data.ctx->selection,
                                 decoder_process, &new_data,
                                 ossl_pw_passphrase_callback_dec,
                                 &new_data.ctx->pwdata);

        OSSL_TRACE_BEGIN(DECODER) {
            BIO_printf(trc_out,
                       "(ctx %p) %s [%u] Running decoder instance %p => %d"
                       " (recursed further: %s, construct called: %s)\n",
                       (void *)new_data.ctx, LEVEL, (unsigned int)i,
                       (void *)new_decoder_inst, ok,
                       new_data.flag_next_level_called ? "yes" : "no",
                       new_data.flag_construct_called ? "yes" : "no");
        } OSSL_TRACE_END(DECODER);

        data->flag_construct_called = new_data.flag_construct_called;

        /* Break on error or if we tried to construct an object already */
        if (!ok || data->flag_construct_called) {
            ERR_clear_last_mark();
            break;
        }
        ERR_pop_to_mark();

        /*
         * Break if the decoder implementation that we called recursed, since
         * that indicates that it successfully decoded something.
         */
        if (new_data.flag_next_level_called)
            break;
    }

 end:
    ossl_core_bio_free(cbio);
    BIO_free(new_data.bio);
    return ok;
}
