diff options
-rw-r--r-- | crypto/core_fetch.c | 8 | ||||
-rw-r--r-- | crypto/core_namemap.c | 26 | ||||
-rw-r--r-- | crypto/evp/digest.c | 27 | ||||
-rw-r--r-- | crypto/evp/evp_enc.c | 26 | ||||
-rw-r--r-- | crypto/evp/evp_fetch.c | 200 | ||||
-rw-r--r-- | crypto/evp/evp_lib.c | 4 | ||||
-rw-r--r-- | crypto/evp/evp_locl.h | 28 | ||||
-rw-r--r-- | crypto/evp/exchange.c | 12 | ||||
-rw-r--r-- | crypto/evp/kdf_lib.c | 2 | ||||
-rw-r--r-- | crypto/evp/kdf_meth.c | 12 | ||||
-rw-r--r-- | crypto/evp/keymgmt_meth.c | 32 | ||||
-rw-r--r-- | crypto/evp/mac_meth.c | 14 | ||||
-rw-r--r-- | crypto/evp/pmeth_fn.c | 12 | ||||
-rw-r--r-- | crypto/include/internal/evp_int.h | 8 | ||||
-rw-r--r-- | doc/internal/man3/evp_generic_fetch.pod | 49 | ||||
-rw-r--r-- | doc/internal/man3/ossl_method_construct.pod | 26 | ||||
-rw-r--r-- | include/internal/core.h | 5 | ||||
-rw-r--r-- | include/internal/namemap.h | 2 |
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); |