Move the stored namemap pre-population to namemap construction
authorRichard Levitte <levitte@openssl.org>
Wed, 15 Jan 2020 00:10:42 +0000 (01:10 +0100)
committerRichard Levitte <levitte@openssl.org>
Thu, 16 Jan 2020 16:29:36 +0000 (17:29 +0100)
Prepopulation of the stored namemap from the legacy method object
database happened on first EVP fetch.  However, there are moments when
that prepopulation needs to happen even though no fetching has been
performed yet.  We therefore move pre-population to happen when the
namemap is constructed.

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10846)

crypto/core_namemap.c
crypto/evp/evp_fetch.c

index 39356076e5d9257f4ce3348c62c238f0c1e7a22a..9a9d1a5748f8b769e7621a6ebf3eb3a40981c489 100644 (file)
@@ -89,38 +89,6 @@ static const OPENSSL_CTX_METHOD stored_namemap_method = {
  * =============
  */
 
-OSSL_NAMEMAP *ossl_namemap_stored(OPENSSL_CTX *libctx)
-{
-    return openssl_ctx_get_data(libctx, OPENSSL_CTX_NAMEMAP_INDEX,
-                                &stored_namemap_method);
-}
-
-OSSL_NAMEMAP *ossl_namemap_new(void)
-{
-    OSSL_NAMEMAP *namemap;
-
-    if ((namemap = OPENSSL_zalloc(sizeof(*namemap))) != NULL
-        && (namemap->lock = CRYPTO_THREAD_lock_new()) != NULL
-        && (namemap->namenum =
-            lh_NAMENUM_ENTRY_new(namenum_hash, namenum_cmp)) != NULL)
-        return namemap;
-
-    ossl_namemap_free(namemap);
-    return NULL;
-}
-
-void ossl_namemap_free(OSSL_NAMEMAP *namemap)
-{
-    if (namemap == NULL || namemap->stored)
-        return;
-
-    lh_NAMENUM_ENTRY_doall(namemap->namenum, namenum_free);
-    lh_NAMENUM_ENTRY_free(namemap->namenum);
-
-    CRYPTO_THREAD_lock_free(namemap->lock);
-    OPENSSL_free(namemap);
-}
-
 int ossl_namemap_empty(OSSL_NAMEMAP *namemap)
 {
     int rv = 0;
@@ -335,3 +303,107 @@ int ossl_namemap_add_names(OSSL_NAMEMAP *namemap, int number,
 
     return number;
 }
+
+/*-
+ * Pre-population
+ * ==============
+ */
+
+#ifndef FIPS_MODE
+#include <openssl/evp.h>
+
+/* 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_name(arg, 0, main_name);
+
+    /*
+     * We could check that the returned value is the same as main_id,
+     * but since this is a void function, there's no sane way to report
+     * the error.  The best we can do is trust ourselve to keep the legacy
+     * method database conflict free.
+     *
+     * This registers any alias with the same number as the main name.
+     * Should it be that the current |on| *has* the main name, this is
+     * simply a no-op.
+     */
+    if (alias != NULL) {
+        (void)ossl_namemap_add_name(arg, main_id, alias);
+    }
+}
+
+static void get_legacy_cipher_names(const OBJ_NAME *on, void *arg)
+{
+    const EVP_CIPHER *cipher = (void *)OBJ_NAME_get(on->name, on->type);
+
+    get_legacy_evp_names(EVP_CIPHER_name(cipher), on->name, arg);
+}
+
+static void get_legacy_md_names(const OBJ_NAME *on, void *arg)
+{
+    const EVP_MD *md = (void *)OBJ_NAME_get(on->name, on->type);
+    /* We don't want the pkey_type names, so we need some extra care */
+    int snid, lnid;
+
+    snid = OBJ_sn2nid(on->name);
+    lnid = OBJ_ln2nid(on->name);
+    if (snid != EVP_MD_pkey_type(md) && lnid != EVP_MD_pkey_type(md))
+        get_legacy_evp_names(EVP_MD_name(md), on->name, arg);
+    else
+        get_legacy_evp_names(EVP_MD_name(md), NULL, arg);
+}
+#endif
+
+/*-
+ * Constructors / destructors
+ * ==========================
+ */
+
+OSSL_NAMEMAP *ossl_namemap_stored(OPENSSL_CTX *libctx)
+{
+    OSSL_NAMEMAP *namemap =
+        openssl_ctx_get_data(libctx, OPENSSL_CTX_NAMEMAP_INDEX,
+                             &stored_namemap_method);
+
+#ifndef FIPS_MODE
+    if (namemap != NULL && ossl_namemap_empty(namemap)) {
+        /* Before pilfering, we make sure the legacy database is populated */
+        OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
+                            | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
+
+        OBJ_NAME_do_all(OBJ_NAME_TYPE_CIPHER_METH,
+                        get_legacy_cipher_names, namemap);
+        OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH,
+                        get_legacy_md_names, namemap);
+    }
+#endif
+
+    return namemap;
+}
+
+OSSL_NAMEMAP *ossl_namemap_new(void)
+{
+    OSSL_NAMEMAP *namemap;
+
+    if ((namemap = OPENSSL_zalloc(sizeof(*namemap))) != NULL
+        && (namemap->lock = CRYPTO_THREAD_lock_new()) != NULL
+        && (namemap->namenum =
+            lh_NAMENUM_ENTRY_new(namenum_hash, namenum_cmp)) != NULL)
+        return namemap;
+
+    ossl_namemap_free(namemap);
+    return NULL;
+}
+
+void ossl_namemap_free(OSSL_NAMEMAP *namemap)
+{
+    if (namemap == NULL || namemap->stored)
+        return;
+
+    lh_NAMENUM_ENTRY_doall(namemap->namenum, namenum_free);
+    lh_NAMENUM_ENTRY_free(namemap->namenum);
+
+    CRYPTO_THREAD_lock_free(namemap->lock);
+    OPENSSL_free(namemap);
+}
index b2040e06f48a82fd16e76267aef166ef8f8ca0a2..db479810135950a4b5897f073215c413db1546e7 100644 (file)
@@ -52,69 +52,6 @@ struct evp_method_data_st {
     void (*destruct_method)(void *method);
 };
 
-#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_name(arg, 0, main_name);
-
-    /*
-     * We could check that the returned value is the same as main_id,
-     * but since this is a void function, there's no sane way to report
-     * the error.  The best we can do is trust ourselve to keep the legacy
-     * method database conflict free.
-     *
-     * This registers any alias with the same number as the main name.
-     * Should it be that the current |on| *has* the main name, this is
-     * simply a no-op.
-     */
-    if (alias != NULL)
-        (void)ossl_namemap_add_name(arg, main_id, alias);
-}
-
-static void get_legacy_cipher_names(const OBJ_NAME *on, void *arg)
-{
-    const EVP_CIPHER *cipher = (void *)OBJ_NAME_get(on->name, on->type);
-
-    get_legacy_evp_names(EVP_CIPHER_name(cipher), on->name, arg);
-}
-
-static void get_legacy_md_names(const OBJ_NAME *on, void *arg)
-{
-    const EVP_MD *md = (void *)OBJ_NAME_get(on->name, on->type);
-    /* We don't want the pkey_type names, so we need some extra care */
-    int snid, lnid;
-
-    snid = OBJ_sn2nid(on->name);
-    lnid = OBJ_ln2nid(on->name);
-    if (snid != EVP_MD_pkey_type(md) && lnid != EVP_MD_pkey_type(md))
-        get_legacy_evp_names(EVP_MD_name(md), on->name, arg);
-    else
-        get_legacy_evp_names(EVP_MD_name(md), NULL, arg);
-}
-#endif
-
-static OSSL_NAMEMAP *get_prepopulated_namemap(OPENSSL_CTX *libctx)
-{
-    OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
-
-#ifndef FIPS_MODE
-    if (namemap != NULL && ossl_namemap_empty(namemap)) {
-        /* Before pilfering, we make sure the legacy database is populated */
-        OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
-                            |OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
-
-        OBJ_NAME_do_all(OBJ_NAME_TYPE_CIPHER_METH,
-                        get_legacy_cipher_names, namemap);
-        OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH,
-                        get_legacy_md_names, namemap);
-    }
-#endif
-
-    return namemap;
-}
-
 /*
  * Generic routines to fetch / create EVP methods with ossl_method_construct()
  */
@@ -273,7 +210,7 @@ inner_evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
                         void (*free_method)(void *))
 {
     OSSL_METHOD_STORE *store = get_evp_method_store(libctx);
-    OSSL_NAMEMAP *namemap = get_prepopulated_namemap(libctx);
+    OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
     uint32_t meth_id = 0;
     void *method = NULL;