In provider implemented methods, save the name number, not the name string

Multiple names per implementation is already supported in the namemap,
but hasn't been used yet.  However, as soon as we have multiple names,
we will get an issue with what name should be saved in the method.

The solution is to not save the name itself, but rather the number
it's associated with.  This number is supposed to be unique for each
set of names, and we assume that algorithm names are globally unique,
i.e. there can be no name overlap between different algorithm types.

Incidently, it was also found that the 'get' function used by
ossl_construct_method() doesn't need all the parameters it was given;
most of what it needs, it can now get through the data structure given
by the caller of ossl_construct_method().  As a consequence,
ossl_construct_method() itself doesn't need all the parameters it was
given either.

There are some added internal functions that are expected to disappear
as soon as legacy code is removed, such as evp_first_name() and
ossl_namemap_num2name().

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9897)
This commit is contained in:
Richard Levitte 2019-09-14 16:22:19 +02:00
parent f8c0218f09
commit f7c16d48a9
18 changed files with 333 additions and 160 deletions

View File

@ -66,15 +66,12 @@ static void ossl_method_construct_this(OSSL_PROVIDER *provider,
}
void *ossl_method_construct(OPENSSL_CTX *libctx, int operation_id,
const char *name, const char *propquery,
int force_store,
OSSL_METHOD_CONSTRUCT_METHOD *mcm, void *mcm_data)
{
void *method = NULL;
if ((method =
mcm->get(libctx, NULL, operation_id, name, propquery, mcm_data))
== NULL) {
if ((method = mcm->get(libctx, NULL, mcm_data)) == NULL) {
struct construct_data_st cbdata;
/*
@ -92,8 +89,7 @@ void *ossl_method_construct(OPENSSL_CTX *libctx, int operation_id,
ossl_algorithm_do_all(libctx, operation_id, NULL,
ossl_method_construct_this, &cbdata);
method = mcm->get(libctx, cbdata.store, operation_id, name,
propquery, mcm_data);
method = mcm->get(libctx, cbdata.store, mcm_data);
mcm->dealloc_tmp_store(cbdata.store);
}

View File

@ -173,6 +173,32 @@ int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name)
return number;
}
struct num2name_data_st {
size_t idx; /* Countdown */
const char *name; /* Result */
};
static void do_num2name(const char *name, void *vdata)
{
struct num2name_data_st *data = vdata;
if (data->idx > 0)
data->idx--;
else if (data->name == NULL)
data->name = name;
}
const char *ossl_namemap_num2name(const OSSL_NAMEMAP *namemap, int number,
size_t idx)
{
struct num2name_data_st data;
data.idx = idx;
data.name = NULL;
ossl_namemap_doall_names(namemap, number, do_num2name, &data);
return data.name;
}
int ossl_namemap_add(OSSL_NAMEMAP *namemap, int number, const char *name)
{
NAMENUM_ENTRY *namenum = NULL;

View File

@ -636,29 +636,31 @@ EVP_MD *evp_md_new(void)
return md;
}
static void *evp_md_from_dispatch(const char *name, const OSSL_DISPATCH *fns,
static void *evp_md_from_dispatch(int name_id,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov, void *unused)
{
EVP_MD *md = NULL;
int fncnt = 0;
/* EVP_MD_fetch() will set the legacy NID if available */
if ((md = evp_md_new()) == NULL
|| (md->name = OPENSSL_strdup(name)) == NULL) {
EVP_MD_free(md);
if ((md = evp_md_new()) == NULL) {
EVPerr(0, ERR_R_MALLOC_FAILURE);
return NULL;
}
md->name_id = name_id;
#ifndef FIPS_MODE
/*
* FIPS module note: since internal fetches will be entirely
* provider based, we know that none of its code depends on legacy
* NIDs or any functionality that use them.
*
* TODO(3.x) get rid of the need for legacy NIDs
*/
md->type = OBJ_sn2nid(name);
{
/*
* FIPS module note: since internal fetches will be entirely
* provider based, we know that none of its code depends on legacy
* NIDs or any functionality that use them.
*
* TODO(3.x) get rid of the need for legacy NIDs
*/
md->type = OBJ_sn2nid(evp_first_name(prov, name_id));
}
#endif
for (; fns->function_id != 0; fns++) {
@ -789,7 +791,6 @@ void EVP_MD_free(EVP_MD *md)
if (i > 0)
return;
ossl_provider_free(md->prov);
OPENSSL_free(md->name);
CRYPTO_THREAD_lock_free(md->lock);
OPENSSL_free(md);
}

View File

@ -1281,7 +1281,7 @@ EVP_CIPHER *evp_cipher_new(void)
return cipher;
}
static void *evp_cipher_from_dispatch(const char *name,
static void *evp_cipher_from_dispatch(const int name_id,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov,
void *unused)
@ -1289,22 +1289,23 @@ static void *evp_cipher_from_dispatch(const char *name,
EVP_CIPHER *cipher = NULL;
int fnciphcnt = 0, fnctxcnt = 0;
if ((cipher = evp_cipher_new()) == NULL
|| (cipher->name = OPENSSL_strdup(name)) == NULL) {
EVP_CIPHER_free(cipher);
if ((cipher = evp_cipher_new()) == NULL) {
EVPerr(0, ERR_R_MALLOC_FAILURE);
return NULL;
}
cipher->name_id = name_id;
#ifndef FIPS_MODE
/*
* FIPS module note: since internal fetches will be entirely
* provider based, we know that none of its code depends on legacy
* NIDs or any functionality that use them.
*
* TODO(3.x) get rid of the need for legacy NIDs
*/
cipher->nid = OBJ_sn2nid(name);
{
/*
* FIPS module note: since internal fetches will be entirely
* provider based, we know that none of its code depends on legacy
* NIDs or any functionality that use them.
*
* TODO(3.x) get rid of the need for legacy NIDs
*/
cipher->nid = OBJ_sn2nid(evp_first_name(prov, name_id));
}
#endif
for (; fns->function_id != 0; fns++) {
@ -1449,7 +1450,6 @@ void EVP_CIPHER_free(EVP_CIPHER *cipher)
if (i > 0)
return;
ossl_provider_free(cipher->prov);
OPENSSL_free(cipher->name);
CRYPTO_THREAD_lock_free(cipher->lock);
OPENSSL_free(cipher);
}

View File

@ -15,6 +15,7 @@
#include "internal/thread_once.h"
#include "internal/property.h"
#include "internal/core.h"
#include "internal/provider.h"
#include "internal/namemap.h"
#include "internal/evp_int.h" /* evp_locl.h needs it */
#include "evp_locl.h"
@ -38,9 +39,12 @@ static const OPENSSL_CTX_METHOD default_method_store_method = {
/* Data to be passed through ossl_method_construct() */
struct method_data_st {
OPENSSL_CTX *libctx;
const char *name;
OSSL_METHOD_CONSTRUCT_METHOD *mcm;
void *(*method_from_dispatch)(const char *, const OSSL_DISPATCH *,
int operation_id; /* For get_method_from_store() */
int name_id; /* For get_method_from_store() */
const char *name; /* For get_method_from_store() */
const char *propquery; /* For get_method_from_store() */
void *(*method_from_dispatch)(int name_id, const OSSL_DISPATCH *,
OSSL_PROVIDER *, void *);
void *method_data;
int (*refcnt_up_method)(void *method);
@ -78,7 +82,7 @@ static OSSL_METHOD_STORE *get_default_method_store(OPENSSL_CTX *libctx)
* | name identity | op id |
* +------------------------+--------+
*/
static uint32_t method_id(unsigned int operation_id, unsigned int name_id)
static uint32_t method_id(unsigned int operation_id, int name_id)
{
if (!ossl_assert(name_id < (1 << 24) || operation_id < (1 << 8))
|| !ossl_assert(name_id > 0 && operation_id > 0))
@ -87,25 +91,36 @@ static uint32_t method_id(unsigned int operation_id, unsigned int name_id)
}
static void *get_method_from_store(OPENSSL_CTX *libctx, void *store,
int operation_id, const char *name,
const char *propquery, void *data)
void *data)
{
struct method_data_st *methdata = data;
void *method = NULL;
OSSL_NAMEMAP *namemap;
int nameid;
uint32_t methid;
int name_id;
uint32_t meth_id;
/*
* get_method_from_store() is only called to try and get the method
* that evp_generic_fetch() is asking for, and the operation id as
* well as the name or name id are passed via methdata.
*/
if ((name_id = methdata->name_id) == 0) {
OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
if (namemap == 0)
return NULL;
name_id = ossl_namemap_name2num(namemap, methdata->name);
}
if (name_id == 0
|| (meth_id = method_id(methdata->operation_id, name_id)) == 0)
return NULL;
if (store == NULL
&& (store = get_default_method_store(libctx)) == NULL)
return NULL;
if ((namemap = ossl_namemap_stored(libctx)) == NULL
|| (nameid = ossl_namemap_name2num(namemap, name)) == 0
|| (methid = method_id(operation_id, nameid)) == 0)
return NULL;
(void)ossl_method_store_fetch(store, methid, propquery, &method);
(void)ossl_method_store_fetch(store, meth_id, methdata->propquery,
&method);
if (method != NULL
&& !methdata->refcnt_up_method(method)) {
@ -121,29 +136,52 @@ static int put_method_in_store(OPENSSL_CTX *libctx, void *store,
{
struct method_data_st *methdata = data;
OSSL_NAMEMAP *namemap;
int nameid;
uint32_t methid;
int name_id;
uint32_t meth_id;
if ((namemap = ossl_namemap_stored(methdata->libctx)) == NULL
|| (nameid = ossl_namemap_add(namemap, 0, name)) == 0
|| (methid = method_id(operation_id, nameid)) == 0)
/*
* put_method_in_store() is only called with a method that was
* successfully created by construct_method() below, which means
* the name should already be stored in the namemap, so just use it.
*/
if ((namemap = ossl_namemap_stored(libctx)) == NULL
|| (name_id = ossl_namemap_name2num(namemap, name)) == 0
|| (meth_id = method_id(operation_id, name_id)) == 0)
return 0;
if (store == NULL
&& (store = get_default_method_store(libctx)) == NULL)
return 0;
return ossl_method_store_add(store, prov, methid, propdef, method,
return ossl_method_store_add(store, prov, meth_id, propdef, method,
methdata->refcnt_up_method,
methdata->destruct_method);
}
/*
* The core fetching functionality passes the name of the implementation.
* This function is responsible to getting an identity number for it.
*/
static void *construct_method(const char *name, const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov, void *data)
{
/*
* This function is only called if get_method_from_store() returned
* NULL, so it's safe to say that of all the spots to create a new
* namemap entry, this is it. Should the name already exist there, we
* know that ossl_namemap_add() will return its corresponding number.
*
* TODO(3.0): If this function gets an array of names instead of just
* one, we need to check through all the names to see if at least one
* of them has an associated number, and use that. If several names
* have associated numbers that differ from each other, it's an error.
*/
struct method_data_st *methdata = data;
OPENSSL_CTX *libctx = ossl_provider_library_context(prov);
OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
int name_id = ossl_namemap_add(namemap, 0, name);
return methdata->method_from_dispatch(name, fns, prov,
return methdata->method_from_dispatch(name_id, fns, prov,
methdata->method_data);
}
@ -154,20 +192,20 @@ static void destruct_method(void *method, void *data)
methdata->destruct_method(method);
}
void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
const char *name, const char *properties,
void *(*new_method)(const char *name,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov,
void *method_data),
void *method_data,
int (*up_ref_method)(void *),
void (*free_method)(void *))
static void *inner_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
int name_id, const char *name,
const char *properties,
void *(*new_method)(int name_id,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov,
void *method_data),
void *method_data,
int (*up_ref_method)(void *),
void (*free_method)(void *))
{
OSSL_METHOD_STORE *store = get_default_method_store(libctx);
OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
int nameid = 0;
uint32_t methid = 0;
uint32_t meth_id = 0;
void *method = NULL;
if (store == NULL || namemap == NULL)
@ -181,17 +219,28 @@ void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
return NULL;
/*
* If we have been passed neither a name_id or a name, we have an
* internal programming error.
*/
if (!ossl_assert(name_id != 0 || name != NULL))
return NULL;
/* If we haven't received a name id yet, try to get one for the name */
if (name_id == 0)
name_id = ossl_namemap_name2num(namemap, name);
/*
* If we have a name id, calculate a method id with method_id().
*
* method_id returns 0 if we have too many operations (more than
* about 2^8) or too many names (more than about 2^24). In that
* case, we can't create any new method.
*/
if ((nameid = ossl_namemap_name2num(namemap, name)) != 0
&& (methid = method_id(operation_id, nameid)) == 0)
if (name_id != 0 && (meth_id = method_id(operation_id, name_id)) == 0)
return NULL;
if (nameid == 0
|| !ossl_method_store_cache_get(store, methid, properties,
&method)) {
if (meth_id == 0
|| !ossl_method_store_cache_get(store, meth_id, properties, &method)) {
OSSL_METHOD_CONSTRUCT_METHOD mcm = {
alloc_tmp_method_store,
dealloc_tmp_method_store,
@ -204,24 +253,28 @@ void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
mcmdata.mcm = &mcm;
mcmdata.libctx = libctx;
mcmdata.operation_id = operation_id;
mcmdata.name_id = name_id;
mcmdata.name = name;
mcmdata.propquery = properties;
mcmdata.method_from_dispatch = new_method;
mcmdata.destruct_method = free_method;
mcmdata.refcnt_up_method = up_ref_method;
mcmdata.destruct_method = free_method;
mcmdata.method_data = method_data;
if ((method = ossl_method_construct(libctx, operation_id, name,
properties, 0 /* !force_cache */,
if ((method = ossl_method_construct(libctx, operation_id,
0 /* !force_cache */,
&mcm, &mcmdata)) != NULL) {
/*
* If construction did create a method for us, we know that
* there is a correct nameid and methodid, since those have
* there is a correct name_id and methodid, since those have
* already been calculated in get_method_from_store() and
* put_method_in_store() above.
*/
nameid = ossl_namemap_name2num(namemap, name);
methid = method_id(operation_id, nameid);
ossl_method_store_cache_set(store, methid, properties, method);
if (name_id == 0)
name_id = ossl_namemap_name2num(namemap, name);
meth_id = method_id(operation_id, name_id);
ossl_method_store_cache_set(store, meth_id, properties, method);
}
} else {
up_ref_method(method);
@ -230,6 +283,45 @@ void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
return method;
}
void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
const char *name, const char *properties,
void *(*new_method)(int name_id,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov,
void *method_data),
void *method_data,
int (*up_ref_method)(void *),
void (*free_method)(void *))
{
return inner_generic_fetch(libctx,
operation_id, 0, name, properties,
new_method, method_data,
up_ref_method, free_method);
}
/*
* evp_generic_fetch_by_number() is special, and only returns methods for
* already known names, i.e. it refuses to work if no name_id can be found
* (it's considered an internal programming error).
* This is meant to be used when one method needs to fetch an associated
* other method.
*/
void *evp_generic_fetch_by_number(OPENSSL_CTX *libctx, int operation_id,
int name_id, const char *properties,
void *(*new_method)(int name_id,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov,
void *method_data),
void *method_data,
int (*up_ref_method)(void *),
void (*free_method)(void *))
{
return inner_generic_fetch(libctx,
operation_id, name_id, NULL, properties,
new_method, method_data,
up_ref_method, free_method);
}
int EVP_set_default_properties(OPENSSL_CTX *libctx, const char *propq)
{
OSSL_METHOD_STORE *store = get_default_method_store(libctx);
@ -243,7 +335,7 @@ int EVP_set_default_properties(OPENSSL_CTX *libctx, const char *propq)
struct do_all_data_st {
void (*user_fn)(void *method, void *arg);
void *user_arg;
void *(*new_method)(const char *name, const OSSL_DISPATCH *fns,
void *(*new_method)(const int name_id, const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov, void *method_data);
void (*free_method)(void *);
};
@ -252,8 +344,14 @@ static void do_one(OSSL_PROVIDER *provider, const OSSL_ALGORITHM *algo,
int no_store, void *vdata)
{
struct do_all_data_st *data = vdata;
void *method = data->new_method(algo->algorithm_name,
algo->implementation, provider, NULL);
OPENSSL_CTX *libctx = ossl_provider_library_context(provider);
OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
int name_id = ossl_namemap_add(namemap, 0, algo->algorithm_name);
void *method = NULL;
if (name_id != 0)
method = data->new_method(name_id, algo->implementation, provider,
NULL);
if (method != NULL) {
data->user_fn(method, data->user_arg);
@ -264,7 +362,7 @@ static void do_one(OSSL_PROVIDER *provider, const OSSL_ALGORITHM *algo,
void evp_generic_do_all(OPENSSL_CTX *libctx, int operation_id,
void (*user_fn)(void *method, void *arg),
void *user_arg,
void *(*new_method)(const char *name,
void *(*new_method)(int name_id,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov,
void *method_data),
@ -279,3 +377,11 @@ void evp_generic_do_all(OPENSSL_CTX *libctx, int operation_id,
data.user_arg = user_arg;
ossl_algorithm_do_all(libctx, operation_id, method_data, do_one, &data);
}
const char *evp_first_name(OSSL_PROVIDER *prov, int name_id)
{
OPENSSL_CTX *libctx = ossl_provider_library_context(prov);
OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
return ossl_namemap_num2name(namemap, name_id, 0);
}

View File

@ -451,7 +451,7 @@ int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx)
const char *EVP_CIPHER_name(const EVP_CIPHER *cipher)
{
if (cipher->prov != NULL)
return cipher->name;
return evp_first_name(cipher->prov, cipher->name_id);
#ifndef FIPS_MODE
return OBJ_nid2sn(EVP_CIPHER_nid(cipher));
#else
@ -479,7 +479,7 @@ int EVP_CIPHER_mode(const EVP_CIPHER *cipher)
const char *EVP_MD_name(const EVP_MD *md)
{
if (md->prov != NULL)
return md->name;
return evp_first_name(md->prov, md->name_id);
#ifndef FIPS_MODE
return OBJ_nid2sn(EVP_MD_nid(md));
#else

View File

@ -68,7 +68,7 @@ struct evp_kdf_ctx_st {
struct evp_keymgmt_st {
int id; /* libcrypto internal */
char *name;
int name_id;
OSSL_PROVIDER *prov;
CRYPTO_REF_COUNT refcnt;
CRYPTO_RWLOCK *lock;
@ -97,7 +97,7 @@ struct keymgmt_data_st {
};
struct evp_keyexch_st {
char *name;
int name_id;
OSSL_PROVIDER *prov;
CRYPTO_REF_COUNT refcnt;
CRYPTO_RWLOCK *lock;
@ -115,7 +115,7 @@ struct evp_keyexch_st {
} /* EVP_KEYEXCH */;
struct evp_signature_st {
char *name;
int name_id;
OSSL_PROVIDER *prov;
CRYPTO_REF_COUNT refcnt;
CRYPTO_RWLOCK *lock;
@ -167,24 +167,37 @@ int is_partially_overlapping(const void *ptr1, const void *ptr2, int len);
#include <openssl/core.h>
void *evp_generic_fetch(OPENSSL_CTX *ctx, int operation_id,
const char *algorithm, const char *properties,
void *(*new_method)(const char *name,
const char *name, const char *properties,
void *(*new_method)(int name_id,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov,
void *method_data),
void *method_data,
int (*up_ref_method)(void *),
void (*free_method)(void *));
void *evp_generic_fetch_by_number(OPENSSL_CTX *ctx, int operation_id,
int name_id, const char *properties,
void *(*new_method)(int name_id,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov,
void *method_data),
void *method_data,
int (*up_ref_method)(void *),
void (*free_method)(void *));
void evp_generic_do_all(OPENSSL_CTX *libctx, int operation_id,
void (*user_fn)(void *method, void *arg),
void *user_arg,
void *(*new_method)(const char *name,
void *(*new_method)(int name_id,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov,
void *method_data),
void *method_data,
void (*free_method)(void *));
/* Internal fetchers for method types that are to be combined with others */
EVP_KEYMGMT *evp_keymgmt_fetch_by_number(OPENSSL_CTX *ctx, int name_id,
const char *properties);
/* Internal structure constructors for fetched methods */
EVP_MD *evp_md_new(void);
EVP_CIPHER *evp_cipher_new(void);
@ -234,3 +247,6 @@ OSSL_PARAM *evp_pkey_to_param(EVP_PKEY *pkey, size_t *sz);
}
void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *ctx);
/* OSSL_PROVIDER * is only used to get the library context */
const char *evp_first_name(OSSL_PROVIDER *prov, int name_id);

View File

@ -32,7 +32,7 @@ static EVP_KEYEXCH *evp_keyexch_new(OSSL_PROVIDER *prov)
return exchange;
}
static void *evp_keyexch_from_dispatch(const char *name,
static void *evp_keyexch_from_dispatch(int name_id,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov,
void *vkeymgmt_data)
@ -47,8 +47,9 @@ static void *evp_keyexch_from_dispatch(const char *name,
* provider matches.
*/
struct keymgmt_data_st *keymgmt_data = vkeymgmt_data;
EVP_KEYMGMT *keymgmt = EVP_KEYMGMT_fetch(keymgmt_data->ctx, name,
keymgmt_data->properties);
EVP_KEYMGMT *keymgmt =
evp_keymgmt_fetch_by_number(keymgmt_data->ctx, name_id,
keymgmt_data->properties);
EVP_KEYEXCH *exchange = NULL;
int fncnt = 0, paramfncnt = 0;
@ -57,12 +58,12 @@ static void *evp_keyexch_from_dispatch(const char *name,
goto err;
}
if ((exchange = evp_keyexch_new(prov)) == NULL
|| (exchange->name = OPENSSL_strdup(name)) == NULL) {
if ((exchange = evp_keyexch_new(prov)) == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
goto err;
}
exchange->name_id = name_id;
exchange->keymgmt = keymgmt;
keymgmt = NULL; /* avoid double free on failure below */
@ -148,7 +149,6 @@ void EVP_KEYEXCH_free(EVP_KEYEXCH *exchange)
return;
EVP_KEYMGMT_free(exchange->keymgmt);
ossl_provider_free(exchange->prov);
OPENSSL_free(exchange->name);
CRYPTO_THREAD_lock_free(exchange->lock);
OPENSSL_free(exchange);
}

View File

@ -85,7 +85,7 @@ EVP_KDF_CTX *EVP_KDF_CTX_dup(const EVP_KDF_CTX *src)
const char *EVP_KDF_name(const EVP_KDF *kdf)
{
return kdf->name;
return evp_first_name(kdf->prov, kdf->name_id);
}
const OSSL_PROVIDER *EVP_KDF_provider(const EVP_KDF *kdf)

View File

@ -33,7 +33,6 @@ static void evp_kdf_free(void *vkdf){
CRYPTO_DOWN_REF(&kdf->refcnt, &ref, kdf->lock);
if (ref <= 0) {
ossl_provider_free(kdf->prov);
OPENSSL_free(kdf->name);
CRYPTO_THREAD_lock_free(kdf->lock);
OPENSSL_free(kdf);
}
@ -53,18 +52,19 @@ static void *evp_kdf_new(void)
return kdf;
}
static void *evp_kdf_from_dispatch(const char *name, const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov, void *method_data)
static void *evp_kdf_from_dispatch(int name_id,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov,
void *method_data)
{
EVP_KDF *kdf = NULL;
int fnkdfcnt = 0, fnctxcnt = 0;
if ((kdf = evp_kdf_new()) == NULL
|| (kdf->name = OPENSSL_strdup(name)) == NULL) {
evp_kdf_free(kdf);
if ((kdf = evp_kdf_new()) == NULL) {
EVPerr(0, ERR_R_MALLOC_FAILURE);
return NULL;
}
kdf->name_id = name_id;
for (; fns->function_id != 0; fns++) {
switch (fns->function_id) {

View File

@ -33,16 +33,18 @@ static void *keymgmt_new(void)
return keymgmt;
}
static void *keymgmt_from_dispatch(const char *name, const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov, void *unused)
static void *keymgmt_from_dispatch(int name_id,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov,
void *unused)
{
EVP_KEYMGMT *keymgmt = NULL;
if ((keymgmt = keymgmt_new()) == NULL
|| (keymgmt->name = OPENSSL_strdup(name)) == NULL) {
if ((keymgmt = keymgmt_new()) == NULL) {
EVP_KEYMGMT_free(keymgmt);
return NULL;
}
keymgmt->name_id = name_id;
for (; fns->function_id != 0; fns++) {
switch (fns->function_id) {
@ -151,16 +153,23 @@ static void *keymgmt_from_dispatch(const char *name, const OSSL_DISPATCH *fns,
return keymgmt;
}
EVP_KEYMGMT *evp_keymgmt_fetch_by_number(OPENSSL_CTX *ctx, int name_id,
const char *properties)
{
return evp_generic_fetch_by_number(ctx,
OSSL_OP_KEYMGMT, name_id, properties,
keymgmt_from_dispatch, NULL,
(int (*)(void *))EVP_KEYMGMT_up_ref,
(void (*)(void *))EVP_KEYMGMT_free);
}
EVP_KEYMGMT *EVP_KEYMGMT_fetch(OPENSSL_CTX *ctx, const char *algorithm,
const char *properties)
{
EVP_KEYMGMT *keymgmt =
evp_generic_fetch(ctx, OSSL_OP_KEYMGMT, algorithm, properties,
keymgmt_from_dispatch, NULL,
(int (*)(void *))EVP_KEYMGMT_up_ref,
(void (*)(void *))EVP_KEYMGMT_free);
return keymgmt;
return evp_generic_fetch(ctx, OSSL_OP_KEYMGMT, algorithm, properties,
keymgmt_from_dispatch, NULL,
(int (*)(void *))EVP_KEYMGMT_up_ref,
(void (*)(void *))EVP_KEYMGMT_free);
}
int EVP_KEYMGMT_up_ref(EVP_KEYMGMT *keymgmt)
@ -182,7 +191,6 @@ void EVP_KEYMGMT_free(EVP_KEYMGMT *keymgmt)
if (ref > 0)
return;
ossl_provider_free(keymgmt->prov);
OPENSSL_free(keymgmt->name);
CRYPTO_THREAD_lock_free(keymgmt->lock);
OPENSSL_free(keymgmt);
}

View File

@ -27,7 +27,6 @@ static void evp_mac_free(void *vmac)
if (ref > 0)
return;
ossl_provider_free(mac->prov);
OPENSSL_free(mac->name);
CRYPTO_THREAD_lock_free(mac->lock);
OPENSSL_free(mac);
}
@ -47,18 +46,19 @@ static void *evp_mac_new(void)
return mac;
}
static void *evp_mac_from_dispatch(const char *name, const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov, void *unused)
static void *evp_mac_from_dispatch(int name_id,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov,
void *unused)
{
EVP_MAC *mac = NULL;
int fnmaccnt = 0, fnctxcnt = 0;
if ((mac = evp_mac_new()) == NULL
|| (mac->name = OPENSSL_strdup(name)) == NULL) {
EVP_MAC_free(mac);
if ((mac = evp_mac_new()) == NULL) {
EVPerr(0, ERR_R_MALLOC_FAILURE);
return NULL;
}
mac->name_id = name_id;
for (; fns->function_id != 0; fns++) {
switch (fns->function_id) {
@ -170,7 +170,7 @@ void EVP_MAC_free(EVP_MAC *mac)
const char *EVP_MAC_name(const EVP_MAC *mac)
{
return mac->name;
return evp_first_name(mac->prov, mac->name_id);
}
const OSSL_PROVIDER *EVP_MAC_provider(const EVP_MAC *mac)

View File

@ -32,7 +32,7 @@ static EVP_SIGNATURE *evp_signature_new(OSSL_PROVIDER *prov)
return signature;
}
static void *evp_signature_from_dispatch(const char *name,
static void *evp_signature_from_dispatch(int name_id,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov,
void *vkeymgmt_data)
@ -47,8 +47,9 @@ static void *evp_signature_from_dispatch(const char *name,
* provider matches.
*/
struct keymgmt_data_st *keymgmt_data = vkeymgmt_data;
EVP_KEYMGMT *keymgmt = EVP_KEYMGMT_fetch(keymgmt_data->ctx, name,
keymgmt_data->properties);
EVP_KEYMGMT *keymgmt =
evp_keymgmt_fetch_by_number(keymgmt_data->ctx, name_id,
keymgmt_data->properties);
EVP_SIGNATURE *signature = NULL;
int ctxfncnt = 0, signfncnt = 0, verifyfncnt = 0, verifyrecfncnt = 0;
int gparamfncnt = 0, sparamfncnt = 0;
@ -58,12 +59,12 @@ static void *evp_signature_from_dispatch(const char *name,
goto err;
}
if ((signature = evp_signature_new(prov)) == NULL
|| (signature->name = OPENSSL_strdup(name)) == NULL) {
if ((signature = evp_signature_new(prov)) == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
goto err;
}
signature->name_id = name_id;
signature->keymgmt = keymgmt;
keymgmt = NULL; /* avoid double free on failure below */
@ -189,7 +190,6 @@ void EVP_SIGNATURE_free(EVP_SIGNATURE *signature)
return;
EVP_KEYMGMT_free(signature->keymgmt);
ossl_provider_free(signature->prov);
OPENSSL_free(signature->name);
CRYPTO_THREAD_lock_free(signature->lock);
OPENSSL_free(signature);
}

View File

@ -130,7 +130,7 @@ extern const EVP_PKEY_METHOD siphash_pkey_meth;
struct evp_mac_st {
OSSL_PROVIDER *prov;
char *name;
int name_id;
CRYPTO_REF_COUNT refcnt;
CRYPTO_RWLOCK *lock;
@ -152,7 +152,7 @@ struct evp_mac_st {
struct evp_kdf_st {
OSSL_PROVIDER *prov;
char *name;
int name_id;
CRYPTO_REF_COUNT refcnt;
CRYPTO_RWLOCK *lock;
@ -199,7 +199,7 @@ struct evp_md_st {
/* New structure members */
/* TODO(3.0): Remove above comment when legacy has gone */
char *name;
int name_id;
OSSL_PROVIDER *prov;
CRYPTO_REF_COUNT refcnt;
CRYPTO_RWLOCK *lock;
@ -252,7 +252,7 @@ struct evp_cipher_st {
/* New structure members */
/* TODO(3.0): Remove above comment when legacy has gone */
char *name;
int name_id;
OSSL_PROVIDER *prov;
CRYPTO_REF_COUNT refcnt;
CRYPTO_RWLOCK *lock;

View File

@ -2,7 +2,8 @@
=head1 NAME
evp_generic_fetch - generic algorithm fetcher and method creator for EVP
evp_generic_fetch, evp_generic_fetch_by_number
- generic algorithm fetchers and method creators for EVP
=head1 SYNOPSIS
@ -11,7 +12,7 @@ evp_generic_fetch - generic algorithm fetcher and method creator for EVP
void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
const char *name, const char *properties,
void *(*new_method)(const char *name,
void *(*new_method)(int name_id,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov,
void *method_data),
@ -19,23 +20,42 @@ evp_generic_fetch - generic algorithm fetcher and method creator for EVP
int (*up_ref_method)(void *),
void (*free_method)(void *));
void *evp_generic_fetch_by_number(OPENSSL_CTX *ctx, int operation_id,
int name_id, const char *properties,
void *(*new_method)(int name_id,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov,
void *method_data),
void *method_data,
int (*up_ref_method)(void *),
void (*free_method)(void *));
=head1 DESCRIPTION
evp_generic_fetch() calls ossl_method_construct() with the given
C<libctx>, C<operation_id>, C<name>, and C<properties> and uses
I<libctx>, I<operation_id>, I<name>, and I<properties> and uses
it to create an EVP method with the help of the functions
C<new_method>, C<up_ref_method>, and C<free_method>.
I<new_method>, I<up_ref_method>, and I<free_method>.
The three functions are supposed to:
evp_generic_fetch_by_number() does the same thing as evp_generic_fetch(),
but takes a I<name_id> instead of a number.
I<name_id> must always be non-zero; as a matter of fact, it being zero
is considered a programming error.
This is meant to be used when one method needs to fetch an associated
other method, and is typically called from inside the given function
I<new_method>.
The three functions I<new_method>, I<up_ref_method>, and
I<free_method> are supposed to:
=over 4
=item new_method()
creates an internal method from function pointers found in the
dispatch table C<fns>.
The algorithm I<name>, provider I<prov>, and I<method_data> are
also passed to be used as new_method() sees fit.
dispatch table I<fns>, with name identity I<name_id>.
The provider I<prov> and I<method_data> are also passed to be used as
new_method() sees fit.
=item up_ref_method()
@ -55,10 +75,10 @@ evp_generic_fetch() returns a method on success, or B<NULL> on error.
=head1 EXAMPLES
This is a short example of the fictitious EVP API and operation called
C<EVP_FOO>.
B<EVP_FOO>.
To begin with, let's assume something like this in
C<include/openssl/core_numbers.h>:
F<include/openssl/core_numbers.h>:
#define OSSL_OP_FOO 100
@ -80,6 +100,7 @@ And here's the implementation of the FOO method fetcher:
/* typedef struct evp_foo_st EVP_FOO */
struct evp_foo_st {
OSSL_PROVIDER *prov;
int name_id;
CRYPTO_REF_COUNT refcnt;
OSSL_OP_foo_newctx_fn *newctx;
OSSL_OP_foo_init_fn *init;
@ -92,14 +113,18 @@ And here's the implementation of the FOO method fetcher:
* In this example, we have a public method creator and destructor.
* It's not absolutely necessary, but is in the spirit of OpenSSL.
*/
EVP_FOO *EVP_FOO_meth_from_dispatch(const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov)
EVP_FOO *EVP_FOO_meth_from_dispatch(int name_id,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov,
void *data)
{
EVP_FOO *foo = NULL;
if ((foo = OPENSSL_zalloc(sizeof(*foo))) == NULL)
return NULL;
foo->name_id = name_id;
for (; fns->function_id != 0; fns++) {
switch (fns->function_id) {
case OSSL_OP_FOO_NEWCTX_FUNC:

View File

@ -15,13 +15,11 @@ OSSL_METHOD_CONSTRUCT_METHOD, ossl_method_construct
/* Remove a store */
void (*dealloc_tmp_store)(void *store);
/* Get an already existing method from a store */
void *(*get)(OPENSSL_CTX *libctx, void *store,
int operation_id, const char *name, const char *propquery,
void *data);
void *(*get)(OPENSSL_CTX *libctx, void *store, void *data);
/* Store a method in a store */
int (*put)(OPENSSL_CTX *libctx, void *store, void *method,
int operation_id, const char *name, const char *propdef,
void *data);
const OSSL_PROVIDER *prov, int operation_id, const char *name,
const char *propdef, void *data);
/* Construct a new method */
void *(*construct)(const char *name, const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov, void *data);
@ -31,7 +29,6 @@ OSSL_METHOD_CONSTRUCT_METHOD, ossl_method_construct
typedef struct ossl_method_construct_method OSSL_METHOD_CONSTRUCT_METHOD;
void *ossl_method_construct(OPENSSL_CTX *ctx, int operation_id,
const char *name, const char *properties,
int force_cache,
OSSL_METHOD_CONSTRUCT_METHOD *mcm, void *mcm_data);
@ -58,11 +55,10 @@ It's important to keep in mind that a method is identified by three things:
=head2 Functions
ossl_method_construct() creates a method by asking all available
providers for a dispatch table given an I<operation_id>, an algorithm
I<name> and a set of I<properties>, and then calling the appropriate
functions given by the sub-system specific method creator through
I<mcm> and the data in I<mcm_data> (which is passed by
ossl_method_construct()).
providers for a dispatch table given an I<operation_id>, and then
calling the appropriate functions given by the sub-system specific
method creator through I<mcm> and the data in I<mcm_data> (which is
passed by ossl_method_construct()).
This function assumes that the sub-system method creator implements
reference counting and acts accordingly (i.e. it will call the
@ -98,10 +94,10 @@ B<NULL> is a valid value and means that a sub-system default store
must be used.
This default store should be stored in the library context I<libctx>.
The method to be looked up should be identified with the given
I<operation_id>, I<name>, the provided property query I<propquery>
and data from I<data> (which is the I<mcm_data> that was passed to
ossl_construct_method()).
The method to be looked up should be identified with data found in I<data>
(which is the I<mcm_data> that was passed to ossl_construct_method()).
In other words, the ossl_method_construct() caller is entirely responsible
for ensuring the necesssary data is made available.
This function is expected to increment the method's reference count.

View File

@ -32,9 +32,7 @@ typedef struct ossl_method_construct_method_st {
/* Remove a store */
void (*dealloc_tmp_store)(void *store);
/* Get an already existing method from a store */
void *(*get)(OPENSSL_CTX *libctx, void *store,
int operation_id, const char *name, const char *propquery,
void *data);
void *(*get)(OPENSSL_CTX *libctx, void *store, void *data);
/* Store a method in a store */
int (*put)(OPENSSL_CTX *libctx, void *store, void *method,
const OSSL_PROVIDER *prov, int operation_id, const char *name,
@ -47,7 +45,6 @@ typedef struct ossl_method_construct_method_st {
} OSSL_METHOD_CONSTRUCT_METHOD;
void *ossl_method_construct(OPENSSL_CTX *ctx, int operation_id,
const char *name, const char *properties,
int force_cache,
OSSL_METHOD_CONSTRUCT_METHOD *mcm, void *mcm_data);

View File

@ -24,6 +24,8 @@ int ossl_namemap_add(OSSL_NAMEMAP *namemap, int number, const char *name);
* number->name mapping is an iterator.
*/
int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name);
const char *ossl_namemap_num2name(const OSSL_NAMEMAP *namemap, int number,
size_t idx);
void ossl_namemap_doall_names(const OSSL_NAMEMAP *namemap, int number,
void (*fn)(const char *name, void *data),
void *data);