[openssl] master update

Richard Levitte levitte at openssl.org
Mon Jun 24 08:58:17 UTC 2019


The branch master has been updated
       via  a9550b74d3efdf1727005dada706cc2e12c273b8 (commit)
       via  734a462e4028e2f0136d3af0b37611138e781246 (commit)
       via  651d44183e86355b1eb9629a6a61d3da09369bbf (commit)
      from  2c840201e57e27fa9f1b26a970270a91813e32fe (commit)


- Log -----------------------------------------------------------------
commit a9550b74d3efdf1727005dada706cc2e12c273b8
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Jun 5 08:59:13 2019 +0200

    OSSL_NAMEMAP: make names case insensitive
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8967)

commit 734a462e4028e2f0136d3af0b37611138e781246
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu May 23 16:00:05 2019 +0200

    Add a namemap test
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8967)

commit 651d44183e86355b1eb9629a6a61d3da09369bbf
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu May 23 03:18:04 2019 +0200

    Replumbing: add support for multiple names per algorithm
    
    Algorithms may have multiple names, as seen in the legacy names
    database.  We need to support that as well.
    
    This implementations modifies ossl_namemap to support multiple names
    for the same identifier.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8967)

-----------------------------------------------------------------------

Summary of changes:
 crypto/core_namemap.c                              | 147 +++++++++++----------
 crypto/evp/evp_fetch.c                             |   8 +-
 doc/internal/man3/ossl_namemap_new.pod             |  46 +++++--
 include/internal/namemap.h                         |  14 +-
 test/build.info                                    |   5 +
 test/namemap_internal_test.c                       |  63 +++++++++
 ...ternal_context.t => 03-test_internal_namemap.t} |   4 +-
 7 files changed, 193 insertions(+), 94 deletions(-)
 create mode 100644 test/namemap_internal_test.c
 copy test/recipes/{02-test_internal_context.t => 03-test_internal_namemap.t} (82%)

diff --git a/crypto/core_namemap.c b/crypto/core_namemap.c
index 5155a22..d4c94190 100644
--- a/crypto/core_namemap.c
+++ b/crypto/core_namemap.c
@@ -7,45 +7,52 @@
  * https://www.openssl.org/source/license.html
  */
 
+#include "e_os.h"                /* strcasecmp */
 #include "internal/namemap.h"
 #include <openssl/lhash.h>
-#include <openssl/safestack.h>
+#include "internal/lhash.h"      /* openssl_lh_strcasehash */
 
-/* The namemap entry */
+/*-
+ * The namenum entry
+ * =================
+ */
 typedef struct {
+    char *name;
     int number;
-    const char *name;
-    char body[1];        /* Sized appropriately to contain the name */
-} NAMEMAP_ENTRY;
+} NAMENUM_ENTRY;
 
-DEFINE_LHASH_OF(NAMEMAP_ENTRY);
-DEFINE_STACK_OF(NAMEMAP_ENTRY)
+DEFINE_LHASH_OF(NAMENUM_ENTRY);
 
-/* The namemap, which provides for bidirectional indexing */
+/*-
+ * The namemap itself
+ * ==================
+ */
 
 struct ossl_namemap_st {
     /* Flags */
     unsigned int stored:1; /* If 1, it's stored in a library context */
 
     CRYPTO_RWLOCK *lock;
-    LHASH_OF(NAMEMAP_ENTRY) *namenum;  /* Name->number mapping */
-    STACK_OF(NAMEMAP_ENTRY) *numname;  /* Number->name mapping */
+    LHASH_OF(NAMENUM_ENTRY) *namenum;  /* Name->number mapping */
+    int max_number;                    /* Current max number */
 };
 
 /* LHASH callbacks */
 
-static unsigned long namemap_hash(const NAMEMAP_ENTRY *n)
+static unsigned long namenum_hash(const NAMENUM_ENTRY *n)
 {
-    return OPENSSL_LH_strhash(n->name);
+    return openssl_lh_strcasehash(n->name);
 }
 
-static int namemap_cmp(const NAMEMAP_ENTRY *a, const NAMEMAP_ENTRY *b)
+static int namenum_cmp(const NAMENUM_ENTRY *a, const NAMENUM_ENTRY *b)
 {
-    return strcmp(a->name, b->name);
+    return strcasecmp(a->name, b->name);
 }
 
-static void namemap_free(NAMEMAP_ENTRY *n)
+static void namenum_free(NAMENUM_ENTRY *n)
 {
+    if (n != NULL)
+        OPENSSL_free(n->name);
     OPENSSL_free(n);
 }
 
@@ -75,7 +82,10 @@ static const OPENSSL_CTX_METHOD stored_namemap_method = {
     stored_namemap_free,
 };
 
-/* API functions */
+/*-
+ * API functions
+ * =============
+ */
 
 OSSL_NAMEMAP *ossl_namemap_stored(OPENSSL_CTX *libctx)
 {
@@ -89,11 +99,9 @@ OSSL_NAMEMAP *ossl_namemap_new(void)
 
     if ((namemap = OPENSSL_zalloc(sizeof(*namemap))) != NULL
         && (namemap->lock = CRYPTO_THREAD_lock_new()) != NULL
-        && (namemap->numname = sk_NAMEMAP_ENTRY_new_null()) != NULL
         && (namemap->namenum =
-            lh_NAMEMAP_ENTRY_new(namemap_hash, namemap_cmp)) != NULL) {
+            lh_NAMENUM_ENTRY_new(namenum_hash, namenum_cmp)) != NULL)
         return namemap;
-    }
 
     ossl_namemap_free(namemap);
     return NULL;
@@ -104,45 +112,46 @@ void ossl_namemap_free(OSSL_NAMEMAP *namemap)
     if (namemap == NULL || namemap->stored)
         return;
 
-     /* The elements will be freed by sk_NAMEMAP_ENTRY_pop_free() */
-    lh_NAMEMAP_ENTRY_free(namemap->namenum);
-
-    sk_NAMEMAP_ENTRY_pop_free(namemap->numname, namemap_free);
+    lh_NAMENUM_ENTRY_doall(namemap->namenum, namenum_free);
+    lh_NAMENUM_ENTRY_free(namemap->namenum);
 
     CRYPTO_THREAD_lock_free(namemap->lock);
     OPENSSL_free(namemap);
 }
 
-/*
- * TODO(3.0) It isn't currently possible to have a default namemap in the
- * FIPS module because if init and cleanup constraints, so we currently
- * disable the code that would allow it when FIPS_MODE is defined.
- */
+typedef struct doall_names_data_st {
+    int number;
+    void (*fn)(const char *name, void *data);
+    void *data;
+} DOALL_NAMES_DATA;
 
-const char *ossl_namemap_name(const OSSL_NAMEMAP *namemap, int number)
+static void do_name(const NAMENUM_ENTRY *namenum, DOALL_NAMES_DATA *data)
 {
-    NAMEMAP_ENTRY *entry;
+    if (namenum->number == data->number)
+        data->fn(namenum->name, data->data);
+}
 
-#ifndef FIPS_MODE
-    if (namemap == NULL)
-        namemap = ossl_namemap_stored(NULL);
-#endif
+IMPLEMENT_LHASH_DOALL_ARG_CONST(NAMENUM_ENTRY, DOALL_NAMES_DATA);
 
-    if (namemap == NULL || number == 0)
-        return NULL;
+void ossl_namemap_doall_names(const OSSL_NAMEMAP *namemap, int number,
+                              void (*fn)(const char *name, void *data),
+                              void *data)
+{
+    DOALL_NAMES_DATA cbdata;
 
+    cbdata.number = number;
+    cbdata.fn = fn;
+    cbdata.data = data;
     CRYPTO_THREAD_read_lock(namemap->lock);
-    entry = sk_NAMEMAP_ENTRY_value(namemap->numname, number);
+    lh_NAMENUM_ENTRY_doall_DOALL_NAMES_DATA(namemap->namenum, do_name,
+                                            &cbdata);
     CRYPTO_THREAD_unlock(namemap->lock);
-
-    if (entry != NULL)
-        return entry->name;
-    return NULL;
 }
 
-int ossl_namemap_number(const OSSL_NAMEMAP *namemap, const char *name)
+int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name)
 {
-    NAMEMAP_ENTRY *entry, template;
+    NAMENUM_ENTRY *namenum_entry, namenum_tmpl;
+    int number = 0;
 
 #ifndef FIPS_MODE
     if (namemap == NULL)
@@ -152,21 +161,22 @@ int ossl_namemap_number(const OSSL_NAMEMAP *namemap, const char *name)
     if (namemap == NULL)
         return 0;
 
-    template.name = name;
+    namenum_tmpl.name = (char *)name;
+    namenum_tmpl.number = 0;
     CRYPTO_THREAD_read_lock(namemap->lock);
-    entry = lh_NAMEMAP_ENTRY_retrieve(namemap->namenum, &template);
+    namenum_entry =
+        lh_NAMENUM_ENTRY_retrieve(namemap->namenum, &namenum_tmpl);
+    if (namenum_entry != NULL)
+        number = namenum_entry->number;
     CRYPTO_THREAD_unlock(namemap->lock);
 
-    if (entry == NULL)
-        return 0;
-
-    return entry->number;
+    return number;
 }
 
-int ossl_namemap_add(OSSL_NAMEMAP *namemap, const char *name)
+int ossl_namemap_add(OSSL_NAMEMAP *namemap, int number, const char *name)
 {
-    NAMEMAP_ENTRY *entry;
-    int number;
+    NAMENUM_ENTRY *namenum = NULL;
+    int tmp_number;
 
 #ifndef FIPS_MODE
     if (namemap == NULL)
@@ -176,36 +186,29 @@ int ossl_namemap_add(OSSL_NAMEMAP *namemap, const char *name)
     if (name == NULL || namemap == NULL)
         return 0;
 
-    if ((number = ossl_namemap_number(namemap, name)) != 0)
-        return number;           /* Pretend success */
-
-    if ((entry = OPENSSL_zalloc(sizeof(*entry) + strlen(name))) == NULL)
-        goto err;
-
-    strcpy(entry->body, name);
-    entry->name = entry->body;
+    if ((tmp_number = ossl_namemap_name2num(namemap, name)) != 0)
+        return tmp_number;       /* Pretend success */
 
     CRYPTO_THREAD_write_lock(namemap->lock);
 
-    entry->number = sk_NAMEMAP_ENTRY_push(namemap->numname, entry);
-
-    if (entry->number == 0)
+    if ((namenum = OPENSSL_zalloc(sizeof(*namenum))) == NULL
+        || (namenum->name = OPENSSL_strdup(name)) == NULL)
         goto err;
 
-    (void)lh_NAMEMAP_ENTRY_insert(namemap->namenum, entry);
-    if (lh_NAMEMAP_ENTRY_error(namemap->namenum))
+    namenum->number = tmp_number =
+        number != 0 ? number : ++namemap->max_number;
+    (void)lh_NAMENUM_ENTRY_insert(namemap->namenum, namenum);
+
+    if (lh_NAMENUM_ENTRY_error(namemap->namenum))
         goto err;
 
     CRYPTO_THREAD_unlock(namemap->lock);
 
-    return entry->number;
+    return tmp_number;
 
  err:
-    if (entry != NULL) {
-        if (entry->number != 0)
-            (void)sk_NAMEMAP_ENTRY_pop(namemap->numname);
-        lh_NAMEMAP_ENTRY_delete(namemap->namenum, entry);
-        CRYPTO_THREAD_unlock(namemap->lock);
-    }
+    namenum_free(namenum);
+
+    CRYPTO_THREAD_unlock(namemap->lock);
     return 0;
 }
diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c
index 1c9e27d..b039cc0 100644
--- a/crypto/evp/evp_fetch.c
+++ b/crypto/evp/evp_fetch.c
@@ -99,7 +99,7 @@ static void *get_method_from_store(OPENSSL_CTX *libctx, void *store,
         return NULL;
 
     if ((namemap = ossl_namemap_stored(libctx)) == NULL
-        || (nameid = ossl_namemap_add(namemap, name)) == 0
+        || (nameid = ossl_namemap_name2num(namemap, name)) == 0
         || (methid = method_id(operation_id, nameid)) == 0)
         return NULL;
 
@@ -123,7 +123,7 @@ static int put_method_in_store(OPENSSL_CTX *libctx, void *store,
     uint32_t methid;
 
     if ((namemap = ossl_namemap_stored(methdata->libctx)) == NULL
-        || (nameid = ossl_namemap_add(namemap, name)) == 0
+        || (nameid = ossl_namemap_add(namemap, 0, name)) == 0
         || (methid = method_id(operation_id, nameid)) == 0)
         return 0;
 
@@ -181,7 +181,7 @@ void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
      * 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_number(namemap, name)) != 0
+    if ((nameid = ossl_namemap_name2num(namemap, name)) != 0
         && (methid = method_id(operation_id, nameid)) == 0)
         return NULL;
 
@@ -214,7 +214,7 @@ void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
              * already been calculated in get_method_from_store() and
              * put_method_in_store() above.
              */
-            nameid = ossl_namemap_number(namemap, name);
+            nameid = ossl_namemap_name2num(namemap, name);
             methid = method_id(operation_id, nameid);
             ossl_method_store_cache_set(store, methid, properties, method);
         }
diff --git a/doc/internal/man3/ossl_namemap_new.pod b/doc/internal/man3/ossl_namemap_new.pod
index 07dc914..8699b86 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_add, ossl_namemap_name, ossl_namemap_number
+ossl_namemap_add, ossl_namemap_name2num, ossl_namemap_doall_names
 - internal number E<lt>-E<gt> name map
 
 =head1 SYNOPSIS
@@ -15,15 +15,18 @@ ossl_namemap_add, ossl_namemap_name, ossl_namemap_number
  OSSL_NAMEMAP *ossl_namemap_new(void);
  void ossl_namemap_free(OSSL_NAMEMAP *namemap);
 
- int ossl_namemap_add(OSSL_NAMEMAP *namemap, const char *name);
- const char *ossl_namemap_name(const OSSL_NAMEMAP *namemap, int number);
- int ossl_namemap_number(const OSSL_NAMEMAP *namemap, const char *name);
+ int ossl_namemap_add(OSSL_NAMEMAP *namemap, int number, const char *name);
+
+ int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name);
+ void ossl_namemap_doall_names(const OSSL_NAMEMAP *namemap, int number,
+                               void (*fn)(const char *name, void *data),
+                               void *data);
 
 =head1 DESCRIPTION
 
-A B<OSSL_NAMEMAP> is a simple number E<lt>-E<gt> name map, which can
-be used to give any arbitrary name (any string) a unique dynamic
-identity that is valid throughout the lifetime of the associated
+A B<OSSL_NAMEMAP> is a one-to-many number E<lt>-E<gt> names map, which
+can be used to give any arbitrary set of names (any string) a unique
+dynamic identity that is valid throughout the lifetime of the associated
 library context.
 
 ossl_namemap_new() and ossl_namemap_free() construct and destruct a
@@ -38,11 +41,19 @@ ossl_namemap_free().
 
 ossl_namemap_add() 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>.
+If the given I<number> is non-zero, the I<name> is added to the set of
+names already associated with that number.
 
-ossl_namemap_name() finds the name corresponding to the given number.
+ossl_namemap_name2num() finds the number corresponding to the given
+I<name>.
 
-ossl_namemap_number() finds the number corresponding to the given
-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.
 
 =head1 RETURN VALUES
 
@@ -52,12 +63,21 @@ B<OSSL_NAMEMAP>, or NULL on error.
 ossl_namemap_add() returns the number associated with the added
 string, or zero on error.
 
-ossl_namemap_name() returns a pointer to the name corresponding to the
-given number, or NULL if it's undefined in the given B<OSSL_NAMEMAP>.
+ossl_namemap_num2names() returns a pointer to a NULL-terminated list of
+pointers to the names corresponding to the given number, or NULL if
+it's undefined in the given B<OSSL_NAMEMAP>.
 
-ossl_namemap_number() returns the number corresponding to the given
+ossl_namemap_name2num() returns the number corresponding to the given
 name, or 0 if it's undefined in the given B<OSSL_NAMEMAP>.
 
+=head1 NOTES
+
+The result from ossl_namemap_num2names() isn't thread safe, other threads
+dealing with the same namemap may cause the list of names to change
+location.
+It is therefore strongly recommended to only use the result in code
+guarded by a thread lock.
+
 =head1 HISTORY
 
 The functions described here were all added in OpenSSL 3.0.
diff --git a/include/internal/namemap.h b/include/internal/namemap.h
index 3002818..5742380 100644
--- a/include/internal/namemap.h
+++ b/include/internal/namemap.h
@@ -16,6 +16,14 @@ OSSL_NAMEMAP *ossl_namemap_stored(OPENSSL_CTX *libctx);
 OSSL_NAMEMAP *ossl_namemap_new(void);
 void ossl_namemap_free(OSSL_NAMEMAP *namemap);
 
-int ossl_namemap_add(OSSL_NAMEMAP *namemap, const char *name);
-const char *ossl_namemap_name(const OSSL_NAMEMAP *namemap, int number);
-int ossl_namemap_number(const OSSL_NAMEMAP *namemap, const char *name);
+int ossl_namemap_add(OSSL_NAMEMAP *namemap, int number, const char *name);
+
+/*
+ * The number<->name relationship is 1<->many
+ * Therefore, the name->number mapping is a simple function, while the
+ * number->name mapping is an iterator.
+ */
+int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name);
+void ossl_namemap_doall_names(const OSSL_NAMEMAP *namemap, int number,
+                              void (*fn)(const char *name, void *data),
+                              void *data);
diff --git a/test/build.info b/test/build.info
index 272c439..1cf604e 100644
--- a/test/build.info
+++ b/test/build.info
@@ -642,6 +642,11 @@ IF[{- !$disabled{tests} -}]
   SOURCE[params_test]=params_test.c
   INCLUDE[params_test]=.. ../include ../apps/include
   DEPEND[params_test]=../libcrypto.a libtestutil.a
+
+  PROGRAMS{noinst}=namemap_internal_test
+  SOURCE[namemap_internal_test]=namemap_internal_test.c
+  INCLUDE[namemap_internal_test]=.. ../include ../apps/include
+  DEPEND[namemap_internal_test]=../libcrypto.a libtestutil.a
 ENDIF
 
 {-
diff --git a/test/namemap_internal_test.c b/test/namemap_internal_test.c
new file mode 100644
index 0000000..1aee01e
--- /dev/null
+++ b/test/namemap_internal_test.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/namemap.h"
+#include "testutil.h"
+
+#define NAME1 "name1"
+#define NAME2 "name2"
+#define ALIAS1 "alias1"
+#define ALIAS1_UC "ALIAS1"
+
+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 check1 = ossl_namemap_name2num(nm, NAME1);
+    int check2 = ossl_namemap_name2num(nm, NAME2);
+    int check3 = ossl_namemap_name2num(nm, ALIAS1);
+    int check4 = ossl_namemap_name2num(nm, ALIAS1_UC);
+    int false1 = ossl_namemap_name2num(nm, "foo");
+
+    return TEST_int_ne(num1, 0)
+        && TEST_int_ne(num2, 0)
+        && TEST_int_eq(num1, num3)
+        && TEST_int_eq(num3, num4)
+        && TEST_int_eq(num1, check1)
+        && TEST_int_eq(num2, check2)
+        && TEST_int_eq(num3, check3)
+        && TEST_int_eq(num4, check4)
+        && TEST_int_eq(false1, 0);
+}
+
+static int test_namemap_independent(void)
+{
+    OSSL_NAMEMAP *nm = ossl_namemap_new();
+    int ok = nm != NULL && test_namemap(nm);
+
+    ossl_namemap_free(nm);
+    return ok;
+}
+
+static int test_namemap_stored(void)
+{
+    OSSL_NAMEMAP *nm = ossl_namemap_stored(NULL);
+
+    return nm != NULL
+        && test_namemap(nm);
+}
+
+int setup_tests(void)
+{
+    ADD_TEST(test_namemap_independent);
+    ADD_TEST(test_namemap_stored);
+    return 1;
+}
diff --git a/test/recipes/02-test_internal_context.t b/test/recipes/03-test_internal_namemap.t
similarity index 82%
copy from test/recipes/02-test_internal_context.t
copy to test/recipes/03-test_internal_namemap.t
index c4c9904..9214242 100644
--- a/test/recipes/02-test_internal_context.t
+++ b/test/recipes/03-test_internal_namemap.t
@@ -11,6 +11,6 @@ use OpenSSL::Test;              # get 'plan'
 use OpenSSL::Test::Simple;
 use OpenSSL::Test::Utils;
 
-setup("test_internal_context");
+setup("test_internal_namemap");
 
-simple_test("test_internal_context", "context_internal_test");
+simple_test("test_internal_namemap", "namemap_internal_test");


More information about the openssl-commits mailing list