From: Richard Levitte Date: Fri, 8 Nov 2019 23:18:05 +0000 (+0100) Subject: CORE: ossl_namemap_add_names(): new function to add multiple names X-Git-Tag: openssl-3.0.0-alpha1~887 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=3d83c7353630450a4ce4fffc9c75693565e094c2;p=oweals%2Fopenssl.git CORE: ossl_namemap_add_names(): new function to add multiple names This was originally the private add_names_to_namemap() in crypto/evp/evp_fetch.c, but made more generally useful. To make for more consistent function naming, ossl_namemap_add() and ossl_namemap_add_n() are renamed to ossl_namemap_add_name() and ossl_namemap_add_name_n(). Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/10394) --- diff --git a/crypto/core_namemap.c b/crypto/core_namemap.c index 9b19d60db3..39356076e5 100644 --- a/crypto/core_namemap.c +++ b/crypto/core_namemap.c @@ -224,8 +224,8 @@ const char *ossl_namemap_num2name(const OSSL_NAMEMAP *namemap, int number, return data.name; } -int ossl_namemap_add_n(OSSL_NAMEMAP *namemap, int number, - const char *name, size_t name_len) +int ossl_namemap_add_name_n(OSSL_NAMEMAP *namemap, int number, + const char *name, size_t name_len) { NAMENUM_ENTRY *namenum = NULL; int tmp_number; @@ -265,10 +265,73 @@ int ossl_namemap_add_n(OSSL_NAMEMAP *namemap, int number, return 0; } -int ossl_namemap_add(OSSL_NAMEMAP *namemap, int number, const char *name) +int ossl_namemap_add_name(OSSL_NAMEMAP *namemap, int number, const char *name) { if (name == NULL) return 0; - return ossl_namemap_add_n(namemap, number, name, strlen(name)); + return ossl_namemap_add_name_n(namemap, number, name, strlen(name)); +} + +int ossl_namemap_add_names(OSSL_NAMEMAP *namemap, int number, + const char *names, const char separator) +{ + const char *p, *q; + size_t l; + + /* Check that we have a namemap */ + if (!ossl_assert(namemap != NULL)) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + /* + * Check that no name is an empty string, and that all names have at + * most one numeric identity together. + */ + for (p = names; *p != '\0'; p = (q == NULL ? p + l : q + 1)) { + int this_number; + + if ((q = strchr(p, separator)) == NULL) + l = strlen(p); /* offset to \0 */ + else + l = q - p; /* offset to the next separator */ + + this_number = ossl_namemap_name2num_n(namemap, p, l); + + if (*p == '\0' || *p == separator) { + ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_BAD_ALGORITHM_NAME); + return 0; + } + if (number == 0) { + number = this_number; + } else if (this_number != 0 && this_number != number) { + ERR_raise_data(ERR_LIB_CRYPTO, CRYPTO_R_CONFLICTING_NAMES, + "\"%.*s\" has an existing different identity %d (from \"%s\")", + l, p, this_number, names); + return 0; + } + } + + /* Now that we have checked, register all names */ + for (p = names; *p != '\0'; p = (q == NULL ? p + l : q + 1)) { + int this_number; + + if ((q = strchr(p, separator)) == NULL) + l = strlen(p); /* offset to \0 */ + else + l = q - p; /* offset to the next separator */ + + this_number = ossl_namemap_add_name_n(namemap, number, p, l); + if (number == 0) { + number = this_number; + } else if (this_number != number) { + ERR_raise_data(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR, + "Got number %d when expecting %d", + this_number, number); + return 0; + } + } + + return number; } diff --git a/crypto/cpt_err.c b/crypto/cpt_err.c index 0028b329a3..0201f31e61 100644 --- a/crypto/cpt_err.c +++ b/crypto/cpt_err.c @@ -14,6 +14,10 @@ #ifndef OPENSSL_NO_ERR static const ERR_STRING_DATA CRYPTO_str_reasons[] = { + {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_BAD_ALGORITHM_NAME), + "bad algorithm name"}, + {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_CONFLICTING_NAMES), + "conflicting names"}, {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_FIPS_MODE_NOT_SUPPORTED), "fips mode not supported"}, {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_ILLEGAL_HEX_DIGIT), diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 9c0f94413a..b103f8605b 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -2206,6 +2206,8 @@ CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO:115:\ unsupported method for creating popo CRMF_R_UNSUPPORTED_POPO_METHOD:116:unsupported popo method CRMF_R_UNSUPPORTED_POPO_NOT_ACCEPTED:117:unsupported popo not accepted +CRYPTO_R_BAD_ALGORITHM_NAME:117:bad algorithm name +CRYPTO_R_CONFLICTING_NAMES:118:conflicting names CRYPTO_R_FIPS_MODE_NOT_SUPPORTED:101:fips mode not supported CRYPTO_R_ILLEGAL_HEX_DIGIT:102:illegal hex digit CRYPTO_R_INSUFFICIENT_DATA_SPACE:106:insufficient data space diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c index 69ca6a0300..ff4e96a823 100644 --- a/crypto/evp/evp_fetch.c +++ b/crypto/evp/evp_fetch.c @@ -52,75 +52,12 @@ struct evp_method_data_st { void (*destruct_method)(void *method); }; -static int add_names_to_namemap(OSSL_NAMEMAP *namemap, - const char *names) -{ - const char *p, *q; - size_t l; - int id = 0; - - /* Check that we have a namemap and that there is at least one name */ - if (namemap == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - /* - * Check that no name is an empty string, and that all names have at - * most one numeric identity together. - */ - for (p = names; *p != '\0'; p = (q == NULL ? p + l : q + 1)) { - int this_id; - - if ((q = strchr(p, NAME_SEPARATOR)) == NULL) - l = strlen(p); /* offset to \0 */ - else - l = q - p; /* offset to the next separator */ - - this_id = ossl_namemap_name2num_n(namemap, p, l); - - if (*p == '\0' || *p == NAME_SEPARATOR) { - ERR_raise(ERR_LIB_EVP, EVP_R_BAD_ALGORITHM_NAME); - return 0; - } - if (id == 0) - id = this_id; - else if (this_id != 0 && this_id != id) { - ERR_raise_data(ERR_LIB_EVP, EVP_R_CONFLICTING_ALGORITHM_NAME, - "\"%.*s\" has an existing different identity %d (from \"%s\")", - l, p, this_id, names); - return 0; - } - } - - /* Now that we have checked, register all names */ - for (p = names; *p != '\0'; p = (q == NULL ? p + l : q + 1)) { - int this_id; - - if ((q = strchr(p, NAME_SEPARATOR)) == NULL) - l = strlen(p); /* offset to \0 */ - else - l = q - p; /* offset to the next separator */ - - this_id = ossl_namemap_add_n(namemap, id, p, l); - if (id == 0) - id = this_id; - else if (this_id != id) { - ERR_raise_data(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR, - "Got id %d when expecting %d", this_id, id); - return 0; - } - } - - return id; -} - #ifndef FIPS_MODE /* Creates an initial namemap with names found in the legacy method db */ static void get_legacy_evp_names(const char *main_name, const char *alias, void *arg) { - int main_id = ossl_namemap_add(arg, 0, main_name); + int main_id = ossl_namemap_add_name(arg, 0, main_name); /* * We could check that the returned value is the same as main_id, @@ -133,7 +70,7 @@ static void get_legacy_evp_names(const char *main_name, const char *alias, * simply a no-op. */ if (alias != NULL) - (void)ossl_namemap_add(arg, main_id, alias); + (void)ossl_namemap_add_name(arg, main_id, alias); } static void get_legacy_cipher_names(const OBJ_NAME *on, void *arg) @@ -303,12 +240,13 @@ static void *construct_evp_method(const char *names, const OSSL_DISPATCH *fns, * This function is only called if get_evp_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. + * know that ossl_namemap_add_name() will return its corresponding + * number. */ struct evp_method_data_st *methdata = data; OPENSSL_CTX *libctx = ossl_provider_library_context(prov); OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); - int name_id = add_names_to_namemap(namemap, names); + int name_id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR); if (name_id == 0) return NULL; @@ -466,7 +404,8 @@ static void do_one(OSSL_PROVIDER *provider, const OSSL_ALGORITHM *algo, struct do_all_data_st *data = vdata; OPENSSL_CTX *libctx = ossl_provider_library_context(provider); OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); - int name_id = add_names_to_namemap(namemap, algo->algorithm_names); + int name_id = ossl_namemap_add_names(namemap, 0, algo->algorithm_names, + NAME_SEPARATOR); void *method = NULL; if (name_id != 0) diff --git a/doc/internal/man3/ossl_namemap_new.pod b/doc/internal/man3/ossl_namemap_new.pod index b66fd91957..e041510c4a 100644 --- a/doc/internal/man3/ossl_namemap_new.pod +++ b/doc/internal/man3/ossl_namemap_new.pod @@ -3,7 +3,7 @@ =head1 NAME ossl_namemap_new, ossl_namemap_free, ossl_namemap_stored, ossl_namemap_empty, -ossl_namemap_add, ossl_namemap_add_n, +ossl_namemap_add_name, ossl_namemap_add_name_n, ossl_namemap_add_names, ossl_namemap_name2num, ossl_namemap_name2num_n, ossl_namemap_doall_names - internal number E-E name map @@ -18,9 +18,9 @@ ossl_namemap_doall_names void ossl_namemap_free(OSSL_NAMEMAP *namemap); int ossl_namemap_empty(OSSL_NAMEMAP *namemap); - int ossl_namemap_add(OSSL_NAMEMAP *namemap, int number, const char *name); - int ossl_namemap_add_n(OSSL_NAMEMAP *namemap, int number, - const char *name, size_t name_len); + int ossl_namemap_add_name(OSSL_NAMEMAP *namemap, int number, const char *name); + int ossl_namemap_add_name_n(OSSL_NAMEMAP *namemap, int number, + const char *name, size_t name_len); int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name); int ossl_namemap_name2num_n(const OSSL_NAMEMAP *namemap, @@ -29,6 +29,9 @@ ossl_namemap_doall_names void (*fn)(const char *name, void *data), void *data); + int ossl_namemap_add_names(OSSL_NAMEMAP *namemap, int number, + const char *names, const char separator); + =head1 DESCRIPTION A B is a one-to-many number E-E names map, which @@ -49,7 +52,7 @@ given library context. The returned B can't be destructed using ossl_namemap_free(). -ossl_namemap_add() adds a new name to the namemap if it's not already +ossl_namemap_add_name() adds a new name to the namemap if it's not already present. If the given I is zero, a new number will be allocated to identify this I. @@ -59,18 +62,23 @@ names already associated with that number. ossl_namemap_name2num() finds the number corresponding to the given I. -ossl_namemap_add_n() and ossl_namemap_name2num_n() do the same thing -as ossl_namemap_add() and ossl_namemap_name2num(), but take a string +ossl_namemap_add_name_n() and ossl_namemap_name2num_n() do the same thing +as ossl_namemap_add_name() and ossl_namemap_name2num(), but take a string length I as well, allowing the caller to use a fragment of a string as a name. - ossl_namemap_doall_names() walks through all names associated with I in the given I and calls the function I for each of them. I is also passed the I argument, which allows any caller to pass extra data for that function to use. +ossl_namemap_add_names() divides up a set of names given in I, +separated by I, and adds each to the I, all with +the same number. If some of them already exist in the I, +they must all have the same associated number, which will be adopted +for any name that doesn't exist yet. + =head1 RETURN VALUES ossl_namemap_new() and ossl_namemap_stored() return the pointer to a @@ -79,8 +87,8 @@ B, or NULL on error. ossl_namemap_empty() returns 1 if the B is NULL or empty, or 0 if it's not empty. -ossl_namemap_add() and ossl_namemap_add_n() return the number associated -with the added string, or zero on error. +ossl_namemap_add_name() and ossl_namemap_add_name_n() return the number +associated with the added string, or zero on error. ossl_namemap_num2names() returns a pointer to a NULL-terminated list of pointers to the names corresponding to the given number, or NULL if @@ -90,6 +98,9 @@ ossl_namemap_name2num() and ossl_namemap_name2num_n() return the number corresponding to the given name, or 0 if it's undefined in the given B. +ossl_namemap_add_names() returns the number associated with the added +names, or zero on error. + =head1 NOTES The result from ossl_namemap_num2names() isn't thread safe, other threads diff --git a/include/internal/namemap.h b/include/internal/namemap.h index f977606ca6..d33f4b0d4e 100644 --- a/include/internal/namemap.h +++ b/include/internal/namemap.h @@ -17,9 +17,9 @@ OSSL_NAMEMAP *ossl_namemap_new(void); void ossl_namemap_free(OSSL_NAMEMAP *namemap); int ossl_namemap_empty(OSSL_NAMEMAP *namemap); -int ossl_namemap_add(OSSL_NAMEMAP *namemap, int number, const char *name); -int ossl_namemap_add_n(OSSL_NAMEMAP *namemap, int number, - const char *name, size_t name_len); +int ossl_namemap_add_name(OSSL_NAMEMAP *namemap, int number, const char *name); +int ossl_namemap_add_name_n(OSSL_NAMEMAP *namemap, int number, + const char *name, size_t name_len); /* * The number<->name relationship is 1<->many @@ -34,3 +34,10 @@ const char *ossl_namemap_num2name(const OSSL_NAMEMAP *namemap, int number, void ossl_namemap_doall_names(const OSSL_NAMEMAP *namemap, int number, void (*fn)(const char *name, void *data), void *data); + +/* + * A utility that handles several names in a string, divided by a given + * separator. + */ +int ossl_namemap_add_names(OSSL_NAMEMAP *namemap, int number, + const char *names, const char separator); diff --git a/include/openssl/cryptoerr.h b/include/openssl/cryptoerr.h index 43b7aa5a22..ae146c4079 100644 --- a/include/openssl/cryptoerr.h +++ b/include/openssl/cryptoerr.h @@ -83,6 +83,8 @@ int ERR_load_CRYPTO_strings(void); /* * CRYPTO reason codes. */ +# define CRYPTO_R_BAD_ALGORITHM_NAME 117 +# define CRYPTO_R_CONFLICTING_NAMES 118 # define CRYPTO_R_FIPS_MODE_NOT_SUPPORTED 101 # define CRYPTO_R_ILLEGAL_HEX_DIGIT 102 # define CRYPTO_R_INSUFFICIENT_DATA_SPACE 106 diff --git a/test/namemap_internal_test.c b/test/namemap_internal_test.c index 16bc571265..0b67cb1d3f 100644 --- a/test/namemap_internal_test.c +++ b/test/namemap_internal_test.c @@ -18,10 +18,10 @@ static int test_namemap(OSSL_NAMEMAP *nm) { - int num1 = ossl_namemap_add(nm, 0, NAME1); - int num2 = ossl_namemap_add(nm, 0, NAME2); - int num3 = ossl_namemap_add(nm, num1, ALIAS1); - int num4 = ossl_namemap_add(nm, 0, ALIAS1_UC); + int num1 = ossl_namemap_add_name(nm, 0, NAME1); + int num2 = ossl_namemap_add_name(nm, 0, NAME2); + int num3 = ossl_namemap_add_name(nm, num1, ALIAS1); + int num4 = ossl_namemap_add_name(nm, 0, ALIAS1_UC); int check1 = ossl_namemap_name2num(nm, NAME1); int check2 = ossl_namemap_name2num(nm, NAME2); int check3 = ossl_namemap_name2num(nm, ALIAS1); @@ -66,10 +66,10 @@ static int test_digestbyname(void) OSSL_NAMEMAP *nm = ossl_namemap_stored(NULL); const EVP_MD *sha256, *foo; - id = ossl_namemap_add(nm, 0, "SHA256"); + id = ossl_namemap_add_name(nm, 0, "SHA256"); if (!TEST_int_ne(id, 0)) return 0; - if (!TEST_int_eq(ossl_namemap_add(nm, id, "foo"), id)) + if (!TEST_int_eq(ossl_namemap_add_name(nm, id, "foo"), id)) return 0; sha256 = EVP_get_digestbyname("SHA256"); @@ -92,10 +92,10 @@ static int test_cipherbyname(void) OSSL_NAMEMAP *nm = ossl_namemap_stored(NULL); const EVP_CIPHER *aes128, *bar; - id = ossl_namemap_add(nm, 0, "AES-128-CBC"); + id = ossl_namemap_add_name(nm, 0, "AES-128-CBC"); if (!TEST_int_ne(id, 0)) return 0; - if (!TEST_int_eq(ossl_namemap_add(nm, id, "bar"), id)) + if (!TEST_int_eq(ossl_namemap_add_name(nm, id, "bar"), id)) return 0; aes128 = EVP_get_cipherbyname("AES-128-CBC");