/*
- * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-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
CRYPTO_DOWN_REF(&encoder->base.refcnt, &ref, encoder->base.lock);
if (ref > 0)
return;
+ OPENSSL_free(encoder->base.name);
ossl_provider_free(encoder->base.prov);
CRYPTO_THREAD_lock_free(encoder->base.lock);
OPENSSL_free(encoder);
static const OSSL_LIB_CTX_METHOD encoder_store_method = {
+ OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
encoder_store_new,
encoder_store_free,
};
int id; /* For get_encoder_from_store() */
const char *names; /* For get_encoder_from_store() */
const char *propquery; /* For get_encoder_from_store() */
+
+ unsigned int flag_construct_error_occurred : 1;
};
/*
}
/* Create and populate a encoder method */
-static void *encoder_from_dispatch(int id, const OSSL_ALGORITHM *algodef,
- OSSL_PROVIDER *prov)
+static void *encoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov)
{
OSSL_ENCODER *encoder = NULL;
const OSSL_DISPATCH *fns = algodef->implementation;
if ((encoder = ossl_encoder_new()) == NULL)
return NULL;
encoder->base.id = id;
+ if ((encoder->base.name = ossl_algorithm_get1_first_name(algodef)) == NULL) {
+ OSSL_ENCODER_free(encoder);
+ return NULL;
+ }
encoder->base.propdef = algodef->property_definition;
+ encoder->base.description = algodef->algorithm_description;
for (; fns->function_id != 0; fns++) {
switch (fns->function_id) {
encoder->settable_ctx_params =
OSSL_FUNC_encoder_settable_ctx_params(fns);
break;
+ case OSSL_FUNC_ENCODER_DOES_SELECTION:
+ if (encoder->does_selection == NULL)
+ encoder->does_selection =
+ OSSL_FUNC_encoder_does_selection(fns);
+ break;
case OSSL_FUNC_ENCODER_ENCODE:
if (encoder->encode == NULL)
encoder->encode = OSSL_FUNC_encoder_encode(fns);
/*
* The core fetching functionality passes the names of the implementation.
* This function is responsible to getting an identity number for them,
- * then call encoder_from_dispatch() with that identity number.
+ * then call encoder_from_algorithm() with that identity number.
*/
static void *construct_encoder(const OSSL_ALGORITHM *algodef,
- OSSL_PROVIDER *prov, void *unused)
+ OSSL_PROVIDER *prov, void *data)
{
/*
* This function is only called if get_encoder_from_store() returned
* namemap entry, this is it. Should the name already exist there, we
* know that ossl_namemap_add() will return its corresponding number.
*/
+ struct encoder_data_st *methdata = data;
OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
const char *names = algodef->algorithm_names;
void *method = NULL;
if (id != 0)
- method = encoder_from_dispatch(id, algodef, prov);
+ method = encoder_from_algorithm(id, algodef, prov);
+
+ /*
+ * Flag to indicate that there was actual construction errors. This
+ * helps inner_evp_generic_fetch() determine what error it should
+ * record on inaccessible algorithms.
+ */
+ if (method == NULL)
+ methdata->flag_construct_error_occurred = 1;
return method;
}
OSSL_METHOD_STORE *store = get_encoder_store(libctx);
OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
void *method = NULL;
+ int unsupported = 0;
- if (store == NULL || namemap == NULL)
+ if (store == NULL || namemap == NULL) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_INVALID_ARGUMENT);
return NULL;
+ }
/*
* If we have been passed neither a name_id or a name, we have an
* internal programming error.
*/
- if (!ossl_assert(id != 0 || name != NULL))
+ if (!ossl_assert(id != 0 || name != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INTERNAL_ERROR);
return NULL;
+ }
if (id == 0)
id = ossl_namemap_name2num(namemap, name);
+ /*
+ * If we haven't found the name yet, chances are that the algorithm to
+ * be fetched is unsupported.
+ */
+ if (id == 0)
+ unsupported = 1;
+
if (id == 0
|| !ossl_method_store_cache_get(store, id, properties, &method)) {
OSSL_METHOD_CONSTRUCT_METHOD mcm = {
mcmdata.id = id;
mcmdata.names = name;
mcmdata.propquery = properties;
+ mcmdata.flag_construct_error_occurred = 0;
if ((method = ossl_method_construct(libctx, OSSL_OP_ENCODER,
0 /* !force_cache */,
&mcm, &mcmdata)) != NULL) {
ossl_method_store_cache_set(store, id, properties, method,
up_ref_encoder, free_encoder);
}
+
+ /*
+ * If we never were in the constructor, the algorithm to be fetched
+ * is unsupported.
+ */
+ unsupported = !mcmdata.flag_construct_error_occurred;
+ }
+
+ if (method == NULL) {
+ int code = unsupported ? ERR_R_UNSUPPORTED : ERR_R_FETCH_FAILED;
+
+ if (name == NULL)
+ name = ossl_namemap_num2name(namemap, id, 0);
+ ERR_raise_data(ERR_LIB_OSSL_ENCODER, code,
+ "%s, Name (%s : %d), Properties (%s)",
+ ossl_lib_ctx_get_descriptor(libctx),
+ name = NULL ? "<null>" : name, id,
+ properties == NULL ? "<null>" : properties);
}
return method;
* Library of basic method functions
*/
-const OSSL_PROVIDER *OSSL_ENCODER_provider(const OSSL_ENCODER *encoder)
+const OSSL_PROVIDER *OSSL_ENCODER_get0_provider(const OSSL_ENCODER *encoder)
{
if (!ossl_assert(encoder != NULL)) {
ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
return encoder->base.prov;
}
-const char *OSSL_ENCODER_properties(const OSSL_ENCODER *encoder)
+const char *OSSL_ENCODER_get0_properties(const OSSL_ENCODER *encoder)
{
if (!ossl_assert(encoder != NULL)) {
ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
return encoder->base.propdef;
}
-int OSSL_ENCODER_number(const OSSL_ENCODER *encoder)
+int OSSL_ENCODER_get_number(const OSSL_ENCODER *encoder)
{
if (!ossl_assert(encoder != NULL)) {
ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
return encoder->base.id;
}
+const char *OSSL_ENCODER_get0_name(const OSSL_ENCODER *encoder)
+{
+ return encoder->base.name;
+}
+
+const char *OSSL_ENCODER_get0_description(const OSSL_ENCODER *encoder)
+{
+ return encoder->base.description;
+}
+
int OSSL_ENCODER_is_a(const OSSL_ENCODER *encoder, const char *name)
{
if (encoder->base.prov != NULL) {
if (id != 0)
method =
- encoder_from_dispatch(id, algodef, provider);
+ encoder_from_algorithm(id, algodef, provider);
if (method != NULL) {
data->user_fn(method, data->user_arg);
encoder_do_one, NULL, &data);
}
-void OSSL_ENCODER_names_do_all(const OSSL_ENCODER *encoder,
- void (*fn)(const char *name, void *data),
- void *data)
+int OSSL_ENCODER_names_do_all(const OSSL_ENCODER *encoder,
+ void (*fn)(const char *name, void *data),
+ void *data)
{
if (encoder == NULL)
- return;
+ return 0;
if (encoder->base.prov != NULL) {
OSSL_LIB_CTX *libctx = ossl_provider_libctx(encoder->base.prov);
OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
- ossl_namemap_doall_names(namemap, encoder->base.id, fn, data);
+ return ossl_namemap_doall_names(namemap, encoder->base.id, fn, data);
}
+
+ return 1;
}
const OSSL_PARAM *
OSSL_ENCODER_gettable_params(OSSL_ENCODER *encoder)
{
if (encoder != NULL && encoder->gettable_params != NULL) {
- void *provctx = ossl_provider_ctx(OSSL_ENCODER_provider(encoder));
+ void *provctx = ossl_provider_ctx(OSSL_ENCODER_get0_provider(encoder));
return encoder->gettable_params(provctx);
}
const OSSL_PARAM *OSSL_ENCODER_settable_ctx_params(OSSL_ENCODER *encoder)
{
if (encoder != NULL && encoder->settable_ctx_params != NULL) {
- void *provctx = ossl_provider_ctx(OSSL_ENCODER_provider(encoder));
+ void *provctx = ossl_provider_ctx(OSSL_ENCODER_get0_provider(encoder));
return encoder->settable_ctx_params(provctx);
}
int OSSL_ENCODER_CTX_set_params(OSSL_ENCODER_CTX *ctx,
const OSSL_PARAM params[])
{
+ int ok = 1;
size_t i;
size_t l;
if (encoderctx == NULL || encoder->set_ctx_params == NULL)
continue;
if (!encoder->set_ctx_params(encoderctx, params))
- return 0;
+ ok = 0;
}
- return 1;
+ return ok;
}
void OSSL_ENCODER_CTX_free(OSSL_ENCODER_CTX *ctx)