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);
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 : "";
+
+ ERR_raise_data(ERR_LIB_OSSL_DECODER, ERR_R_UNSUPPORTED,
+ "No supported for the 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);
BIO *bio = data->bio;
long loc;
size_t i;
- int err, lib, reason, ok = 0;
+ 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;
data->current_decoder_inst_index);
decoder = OSSL_DECODER_INSTANCE_get_decoder(decoder_inst);
- if (ctx->construct != NULL
- && ctx->construct(decoder_inst, params, ctx->construct_data)) {
- ok = 1;
- goto end;
+ data->flag_construct_called = 0;
+ if (ctx->construct != NULL) {
+ int rv = ctx->construct(decoder_inst, params, ctx->construct_data);
+
+ data->flag_construct_called = 1;
+ ok = (rv > 0);
+ if (ok)
+ goto end;
}
/* The constructor didn't return success */
(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,
OSSL_TRACE_BEGIN(DECODER) {
BIO_printf(trc_out,
- "(ctx %p) %s [%u] Running decoder instance %p => %d\n",
+ "(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);
+ (void *)new_decoder_inst, ok,
+ new_data.flag_next_level_called ? "yes" : "no",
+ new_data.flag_construct_called ? "yes" : "no");
} OSSL_TRACE_END(DECODER);
- if (ok)
+ 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();
/*
- * These errors are assumed to come from ossl_store_handle_load_result()
- * in crypto/store/store_result.c. They are currently considered fatal
- * errors, so we preserve them in the error queue and stop.
+ * Break if the decoder implementation that we called recursed, since
+ * that indicates that it successfully decoded something.
*/
- err = ERR_peek_last_error();
- lib = ERR_GET_LIB(err);
- reason = ERR_GET_REASON(err);
- if ((lib == ERR_LIB_EVP
- && reason == EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM)
-#ifndef OPENSSL_NO_EC
- || (lib == ERR_LIB_EC && reason == EC_R_UNKNOWN_GROUP)
-#endif
- || (lib == ERR_LIB_X509 && reason == X509_R_UNSUPPORTED_ALGORITHM)
- || (lib == ERR_LIB_PKCS12
- && reason == PKCS12_R_PKCS12_CIPHERFINAL_ERROR))
- goto end;
+ if (new_data.flag_next_level_called)
+ break;
}
end:
pointer along with a pointer to application data I<cbarg>, which should be
used when a pass phrase prompt is needed.
+It's important to understand that the return value from this function is
+interpreted as follows:
+
+=over 4
+
+=item True (1)
+
+This means "carry on the decoding process", and is meaningful even though
+this function couldn't decode the input into anything, because there may be
+another decoder implementation that can decode it into something.
+
+The I<data_cb> callback should never be called when this function can't
+decode the input into anything.
+
+=item False (0)
+
+This means "stop the decoding process", and is meaningful when the input
+could be decoded into some sort of object that this function understands,
+but further treatment of that object results into errors that won't be
+possible for some other decoder implementation to get a different result.
+
+=back
+
+The conditions to stop the decoding process are at the discretion of the
+implementation.
+
=head2 Decoder parameters
The decoder implementation itself has parameters that can be used to
OSSL_FUNC_decoder_does_selection() returns 1 if the decoder implementation
supports any of the I<selection> bits, otherwise 0.
-OSSL_FUNC_decoder_decode() returns 1 on success, or 0 on failure.
+OSSL_FUNC_decoder_decode() returns 1 to signal that the decoding process
+should continue, or 0 to signal that it should stop.
=head1 SEE ALSO