CORE: ossl_namemap_add_names(): new function to add multiple names
authorRichard Levitte <levitte@openssl.org>
Fri, 8 Nov 2019 23:18:05 +0000 (00:18 +0100)
committerRichard Levitte <levitte@openssl.org>
Fri, 29 Nov 2019 19:42:12 +0000 (20:42 +0100)
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 <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10394)

crypto/core_namemap.c
crypto/cpt_err.c
crypto/err/openssl.txt
crypto/evp/evp_fetch.c
doc/internal/man3/ossl_namemap_new.pod
include/internal/namemap.h
include/openssl/cryptoerr.h
test/namemap_internal_test.c

index 9b19d60db3051c481e12aad90a38a9db806004a8..39356076e5d9257f4ce3348c62c238f0c1e7a22a 100644 (file)
@@ -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;
 }
index 0028b329a32199a14485a036b8a511786aac4271..0201f31e61da30fd0593838a070e231c4343dedc 100644 (file)
 #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),
index 9c0f94413a2d0273f5ef05a90218da22a755a24a..b103f8605b96cd5e299f7523c514255232fb5a37 100644 (file)
@@ -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
index 69ca6a03004ac5fbe7c4fb771be2bac434304212..ff4e96a8237f98f6a9e08db0de762ec6683b9148 100644 (file)
@@ -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)
index b66fd91957a8bb686e02550302a37d322df15932..e041510c4ab4b237be20e0d00672d0648827ed38 100644 (file)
@@ -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<lt>-E<gt> 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<OSSL_NAMEMAP> is a one-to-many number E<lt>-E<gt> names map, which
@@ -49,7 +52,7 @@ given library context.
 The returned B<OSSL_NAMEMAP> 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<number> is zero, a new number will be allocated to
 identify this I<name>.
@@ -59,18 +62,23 @@ names already associated with that number.
 ossl_namemap_name2num() finds the number corresponding to the given
 I<name>.
 
-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<name_len> 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<number> in the given I<namemap> and calls the function I<fn> for
 each of them.
 I<fn> is also passed the I<data> 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<names>,
+separated by I<separator>, and adds each to the I<namemap>, all with
+the same number.  If some of them already exist in the I<namemap>,
+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<OSSL_NAMEMAP>, or NULL on error.
 ossl_namemap_empty() returns 1 if the B<OSSL_NAMEMAP> 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>.
 
+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
index f977606ca6badcf9a543c9b9b861d8ba0e332b0d..d33f4b0d4e5e9d46cf7ee4d547a80ebd2c40913a 100644 (file)
@@ -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);
index 43b7aa5a2283b2d8e80b05b13a160ce50045efa0..ae146c4079cac4c1fbf57e5366d70f805ecdb151 100644 (file)
@@ -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
index 16bc571265d8925fdb2070b9b8cae2825398e42d..0b67cb1d3fe39344bffb55c3ae180c203c3cae91 100644 (file)
 
 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");