/*
- * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-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
* https://www.openssl.org/source/license.html
*/
-#include "e_os.h" /* strcasecmp on Windows */
#include <openssl/core_names.h>
#include <openssl/bio.h>
#include <openssl/encoder.h>
#include <openssl/provider.h>
#include <openssl/trace.h>
#include "internal/bio.h"
+#include "internal/provider.h"
#include "encoder_local.h"
struct encoder_process_data_st {
OSSL_ENCODER_INSTANCE *prev_encoder_inst;
unsigned char *running_output;
size_t running_output_length;
+ /* Data type = the name of the first succeeding encoder implementation */
+ const char *data_type;
};
static int encoder_process(struct encoder_process_data_st *data);
data.bio = out;
data.current_encoder_inst_index = OSSL_ENCODER_CTX_get_num_encoders(ctx);
+ if (data.current_encoder_inst_index == 0) {
+ ERR_raise_data(ERR_LIB_OSSL_ENCODER, OSSL_ENCODER_R_ENCODER_NOT_FOUND,
+ "No encoders were found. For standard encoders you need "
+ "at least one of the default or base providers "
+ "available. Did you forget to load them?");
+ return 0;
+ }
+
return encoder_process(&data) > 0;
}
int OSSL_ENCODER_to_data(OSSL_ENCODER_CTX *ctx, unsigned char **pdata,
size_t *pdata_len)
{
- BIO *out = BIO_new(BIO_s_mem());
+ BIO *out;
BUF_MEM *buf = NULL;
int ret = 0;
return 0;
}
- if (OSSL_ENCODER_to_bio(ctx, out)
+ out = BIO_new(BIO_s_mem());
+
+ if (out != NULL
+ && OSSL_ENCODER_to_bio(ctx, out)
&& BIO_get_mem_ptr(out, &buf) > 0) {
ret = 1; /* Hope for the best. A too small buffer will clear this */
void *encoderctx)
{
OSSL_ENCODER_INSTANCE *encoder_inst = NULL;
- OSSL_PARAM params[4];
+ const OSSL_PROVIDER *prov;
+ OSSL_LIB_CTX *libctx;
+ const OSSL_PROPERTY_LIST *props;
+ const OSSL_PROPERTY_DEFINITION *prop;
if (!ossl_assert(encoder != NULL)) {
ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
- if (encoder->get_params == NULL) {
- ERR_raise(ERR_LIB_OSSL_ENCODER,
- OSSL_ENCODER_R_MISSING_GET_PARAMS);
- return 0;
- }
-
if ((encoder_inst = OPENSSL_zalloc(sizeof(*encoder_inst))) == NULL) {
ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE);
return 0;
}
- /*
- * Cache the input and output types for this encoder. The output type
- * is mandatory.
- */
- params[0] =
- OSSL_PARAM_construct_utf8_ptr(OSSL_ENCODER_PARAM_OUTPUT_TYPE,
- (char **)&encoder_inst->output_type, 0);
- params[1] =
- OSSL_PARAM_construct_utf8_ptr(OSSL_ENCODER_PARAM_OUTPUT_STRUCTURE,
- (char **)&encoder_inst->output_structure,
- 0);
- params[2] =
- OSSL_PARAM_construct_utf8_ptr(OSSL_ENCODER_PARAM_INPUT_TYPE,
- (char **)&encoder_inst->input_type, 0);
- params[3] = OSSL_PARAM_construct_end();
-
- if (!encoder->get_params(params)
- || !OSSL_PARAM_modified(¶ms[0]))
- goto err;
-
if (!OSSL_ENCODER_up_ref(encoder)) {
ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INTERNAL_ERROR);
goto err;
}
+ prov = OSSL_ENCODER_get0_provider(encoder);
+ libctx = ossl_provider_libctx(prov);
+ props = ossl_encoder_parsed_properties(encoder);
+ if (props == NULL) {
+ ERR_raise_data(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROPERTY_DEFINITION,
+ "there are no property definitions with encoder %s",
+ OSSL_ENCODER_get0_name(encoder));
+ goto err;
+ }
+
+ /* The "output" property is mandatory */
+ prop = ossl_property_find_property(props, libctx, "output");
+ encoder_inst->output_type = ossl_property_get_string_value(libctx, prop);
+ if (encoder_inst->output_type == NULL) {
+ ERR_raise_data(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROPERTY_DEFINITION,
+ "the mandatory 'output' property is missing "
+ "for encoder %s (properties: %s)",
+ OSSL_ENCODER_get0_name(encoder),
+ OSSL_ENCODER_get0_properties(encoder));
+ goto err;
+ }
+
+ /* The "structure" property is optional */
+ prop = ossl_property_find_property(props, libctx, "structure");
+ if (prop != NULL)
+ encoder_inst->output_structure
+ = ossl_property_get_string_value(libctx, prop);
+
encoder_inst->encoder = encoder;
encoder_inst->encoderctx = encoderctx;
return encoder_inst;
if (ok) {
OSSL_TRACE_BEGIN(ENCODER) {
BIO_printf(trc_out,
- "(ctx %p) Added encoder instance %p (encoder %p) with:\n",
- (void *)ctx, (void *)ei, (void *)ei->encoder);
- BIO_printf(trc_out,
- " output type: %s, output structure: %s, input type :%s\n",
- ei->output_type, ei->output_structure, ei->input_type);
+ "(ctx %p) Added encoder instance %p (encoder %p):\n"
+ " %s with %s\n",
+ (void *)ctx, (void *)ei, (void *)ei->encoder,
+ OSSL_ENCODER_get0_name(ei->encoder),
+ OSSL_ENCODER_get0_properties(ei->encoder));
} OSSL_TRACE_END(ENCODER);
}
return ok;
return 0;
}
- prov = OSSL_ENCODER_provider(encoder);
+ prov = OSSL_ENCODER_get0_provider(encoder);
provctx = OSSL_PROVIDER_get0_provider_ctx(prov);
if ((encoderctx = encoder->newctx(provctx)) == NULL
return encoder_inst->encoderctx;
}
-const char *
-OSSL_ENCODER_INSTANCE_get_input_type(OSSL_ENCODER_INSTANCE *encoder_inst)
-{
- if (encoder_inst == NULL)
- return NULL;
- return encoder_inst->input_type;
-}
-
const char *
OSSL_ENCODER_INSTANCE_get_output_type(OSSL_ENCODER_INSTANCE *encoder_inst)
{
*/
if (top) {
if (data->ctx->output_type != NULL
- && strcasecmp(current_output_type,
- data->ctx->output_type) != 0) {
+ && OPENSSL_strcasecmp(current_output_type,
+ data->ctx->output_type) != 0) {
OSSL_TRACE_BEGIN(ENCODER) {
BIO_printf(trc_out,
"[%d] Skipping because current encoder output type (%s) != desired output type (%s)\n",
*/
if (data->ctx->output_structure != NULL
&& current_output_structure != NULL) {
- if (strcasecmp(data->ctx->output_structure,
- current_output_structure) != 0) {
+ if (OPENSSL_strcasecmp(data->ctx->output_structure,
+ current_output_structure) != 0) {
OSSL_TRACE_BEGIN(ENCODER) {
BIO_printf(trc_out,
"[%d] Skipping because current encoder output structure (%s) != ctx output structure (%s)\n",
OSSL_TRACE_BEGIN(ENCODER) {
BIO_printf(trc_out,
- "[%d] Skipping because recusion level %d failed\n",
+ "[%d] Skipping because recursion level %d failed\n",
data->level, new_data.level);
} OSSL_TRACE_END(ENCODER);
}
data->ctx->construct(current_encoder_inst,
data->ctx->construct_data);
+ /* Also set the data type, using the encoder implementation name */
+ data->data_type = OSSL_ENCODER_get0_name(current_encoder);
+
/* Assume that the constructor recorded an error */
if (original_data != NULL)
ok = 1;
*/
OSSL_PARAM *abstract_p = abstract;
- const char *prev_input_type =
- OSSL_ENCODER_INSTANCE_get_input_type(data->prev_encoder_inst);
const char *prev_output_structure =
OSSL_ENCODER_INSTANCE_get_output_structure(data->prev_encoder_inst);
- if (prev_input_type != NULL)
- *abstract_p++ =
- OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,
- (char *)prev_input_type, 0);
+ *abstract_p++ =
+ OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,
+ (char *)data->data_type, 0);
if (prev_output_structure != NULL)
*abstract_p++ =
OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE,