/*
* Copyright 2020-2022 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 "internal/namemap.h"
#include "crypto/decoder.h"
#include "encoder_local.h"
#include "internal/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;
unsigned int flag_input_structure_checked : 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;
unsigned long lasterr;
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;
}
lasterr = ERR_peek_last_error();
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 (ERR_peek_last_error() == lasterr || ERR_peek_error() == 0)
/* Prevent spurious decoding error but add at least something */
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