summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2019-05-23 03:18:04 +0200
committerRichard Levitte <levitte@openssl.org>2019-06-24 10:58:13 +0200
commit651d44183e86355b1eb9629a6a61d3da09369bbf (patch)
treed42e66ae9f3e0ddb836cfb683c32250fbd6655a1
parentAllow AES XTS decryption using duplicate keys. (diff)
downloadopenssl-651d44183e86355b1eb9629a6a61d3da09369bbf.tar.xz
openssl-651d44183e86355b1eb9629a6a61d3da09369bbf.zip
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@oracle.com> (Merged from https://github.com/openssl/openssl/pull/8967)
-rw-r--r--crypto/core_namemap.c141
-rw-r--r--crypto/evp/evp_fetch.c8
-rw-r--r--doc/internal/man3/ossl_namemap_new.pod46
-rw-r--r--include/internal/namemap.h14
4 files changed, 119 insertions, 90 deletions
diff --git a/crypto/core_namemap.c b/crypto/core_namemap.c
index 5155a22134..31dc933af1 100644
--- a/crypto/core_namemap.c
+++ b/crypto/core_namemap.c
@@ -9,43 +9,48 @@
#include "internal/namemap.h"
#include <openssl/lhash.h>
-#include <openssl/safestack.h>
-/* 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);
}
-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);
}
-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 +80,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 +97,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 +110,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 +159,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 +184,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 1c9e27db87..b039cc0547 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 07dc914fe2..8699b861b0 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 30028182fd..57423801d6 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);