aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2019-09-14 16:22:19 +0200
committerRichard Levitte <levitte@openssl.org>2019-09-19 14:58:17 +0200
commitf7c16d48a945e80f22f6f02550ee3fe14edb52fa (patch)
treeb6ec900293f5a14213aa1836c916ea4e11f7c260
parentf8c0218f09e190a2efb28302f6c9737efe151d27 (diff)
downloadopenssl-f7c16d48a945e80f22f6f02550ee3fe14edb52fa.tar.gz
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)
-rw-r--r--crypto/core_fetch.c8
-rw-r--r--crypto/core_namemap.c26
-rw-r--r--crypto/evp/digest.c27
-rw-r--r--crypto/evp/evp_enc.c26
-rw-r--r--crypto/evp/evp_fetch.c200
-rw-r--r--crypto/evp/evp_lib.c4
-rw-r--r--crypto/evp/evp_locl.h28
-rw-r--r--crypto/evp/exchange.c12
-rw-r--r--crypto/evp/kdf_lib.c2
-rw-r--r--crypto/evp/kdf_meth.c12
-rw-r--r--crypto/evp/keymgmt_meth.c32
-rw-r--r--crypto/evp/mac_meth.c14
-rw-r--r--crypto/evp/pmeth_fn.c12
-rw-r--r--crypto/include/internal/evp_int.h8
-rw-r--r--doc/internal/man3/evp_generic_fetch.pod49
-rw-r--r--doc/internal/man3/ossl_method_construct.pod26
-rw-r--r--include/internal/core.h5
-rw-r--r--include/internal/namemap.h2
18 files changed, 333 insertions, 160 deletions
diff --git a/crypto/core_fetch.c b/crypto/core_fetch.c
index 6e4414d831..1e0d82fb61 100644
--- a/crypto/core_fetch.c
+++ b/crypto/core_fetch.c
@@ -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);
}
diff --git a/crypto/core_namemap.c b/crypto/core_namemap.c
index d4c9419044..cf5f1e54c3 100644
--- a/crypto/core_namemap.c
+++ b/crypto/core_namemap.c
@@ -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;
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index 0da934a691..f39a443c89 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -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);
}
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
index f2511a2b28..6e509b2d13 100644
--- a/crypto/evp/evp_enc.c
+++ b/crypto/evp/evp_enc.c
@@ -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);
}
diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c
index 662195e4de..79520c0b7f 100644
--- a/crypto/evp/evp_fetch.c
+++ b/crypto/evp/evp_fetch.c
@@ -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;
- if (store == NULL
- && (store = get_default_method_store(libctx)) == NULL)
+ /*
+ * 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 ((namemap = ossl_namemap_stored(libctx)) == NULL
- || (nameid = ossl_namemap_name2num(namemap, name)) == 0
- || (methid = method_id(operation_id, nameid)) == 0)
+ if (store == NULL
+ && (store = get_default_method_store(libctx)) == NULL)
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);
+}
diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c
index eeed7359a4..000d6e9623 100644
--- a/crypto/evp/evp_lib.c
+++ b/crypto/evp/evp_lib.c
@@ -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
diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h
index fd684c4b4c..cd58ba33b5 100644
--- a/crypto/evp/evp_locl.h
+++ b/crypto/evp/evp_locl.h
@@ -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);
diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c
index 7c61a12b3b..53a25a424e 100644
--- a/crypto/evp/exchange.c
+++ b/crypto/evp/exchange.c
@@ -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);
}
diff --git a/crypto/evp/kdf_lib.c b/crypto/evp/kdf_lib.c
index 9f055a61d0..5c57cc360e 100644
--- a/crypto/evp/kdf_lib.c
+++ b/crypto/evp/kdf_lib.c
@@ -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)
diff --git a/crypto/evp/kdf_meth.c b/crypto/evp/kdf_meth.c
index c2db212710..7bcdcc7df3 100644
--- a/crypto/evp/kdf_meth.c
+++ b/crypto/evp/kdf_meth.c
@@ -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) {
diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c
index 72ef1bdb0c..c170bd676b 100644
--- a/crypto/evp/keymgmt_meth.c
+++ b/crypto/evp/keymgmt_meth.c
@@ -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);
}
diff --git a/crypto/evp/mac_meth.c b/crypto/evp/mac_meth.c
index a317127e15..3dc58c1f3b 100644
--- a/crypto/evp/mac_meth.c
+++ b/crypto/evp/mac_meth.c
@@ -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)
diff --git a/crypto/evp/pmeth_fn.c b/crypto/evp/pmeth_fn.c
index b46c92d633..34db48639a 100644
--- a/crypto/evp/pmeth_fn.c
+++ b/crypto/evp/pmeth_fn.c
@@ -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);
}
diff --git a/crypto/include/internal/evp_int.h b/crypto/include/internal/evp_int.h
index caf0ca1dd9..f1fb67207f 100644
--- a/crypto/include/internal/evp_int.h
+++ b/crypto/include/internal/evp_int.h
@@ -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;
diff --git a/doc/internal/man3/evp_generic_fetch.pod b/doc/internal/man3/evp_generic_fetch.pod
index b77391e386..6fe7bccba3 100644
--- a/doc/internal/man3/evp_generic_fetch.pod
+++ b/doc/internal/man3/evp_generic_fetch.pod
@@ -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>.
+
+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 are supposed to:
+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:
diff --git a/doc/internal/man3/ossl_method_construct.pod b/doc/internal/man3/ossl_method_construct.pod
index 9beb7942f0..a25ca4cd8c 100644
--- a/doc/internal/man3/ossl_method_construct.pod
+++ b/doc/internal/man3/ossl_method_construct.pod
@@ -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.
diff --git a/include/internal/core.h b/include/internal/core.h
index a40d3c69af..d2229e173b 100644
--- a/include/internal/core.h
+++ b/include/internal/core.h
@@ -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);
diff --git a/include/internal/namemap.h b/include/internal/namemap.h
index 57423801d6..ee69388f11 100644
--- a/include/internal/namemap.h
+++ b/include/internal/namemap.h
@@ -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);