Ensure EVP_get_digestbyname() and EVP_get_cipherbyname() know all aliases
authorMatt Caswell <matt@openssl.org>
Fri, 1 Nov 2019 14:13:49 +0000 (14:13 +0000)
committerMatt Caswell <matt@openssl.org>
Wed, 6 Nov 2019 10:11:31 +0000 (10:11 +0000)
Now that we have an EVP namemap containing all aliases that providers
know about for any given algorithm, it is possible that an application
attempts to look up a digest or a cipher via EVP_get_digestbyname() or
EVP_get_cipherbyname() with an algorithm name that is unknown to the
legacy method database. Therefore we extend those functions to
additionally check the aliases in the namemap when searching for a
method in the event that our initial lookup attempt fails.

Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from https://github.com/openssl/openssl/pull/10324)

crypto/evp/names.c
crypto/evp/pmeth_lib.c
include/crypto/evp.h

index 901899a..5eb7a39 100644 (file)
@@ -8,11 +8,12 @@
  */
 
 #include <stdio.h>
-#include "internal/cryptlib.h"
 #include <openssl/evp.h>
 #include <openssl/kdf.h>
-#include "crypto/objects.h"
 #include <openssl/x509.h>
+#include "internal/cryptlib.h"
+#include "internal/namemap.h"
+#include "crypto/objects.h"
 #include "crypto/evp.h"
 
 int EVP_add_cipher(const EVP_CIPHER *c)
@@ -56,26 +57,94 @@ int EVP_add_digest(const EVP_MD *md)
     return r;
 }
 
+static void cipher_from_name(const char *name, void *data)
+{
+    const EVP_CIPHER **cipher = data;
+
+    if (*cipher != NULL)
+        return;
+
+    *cipher = (const EVP_CIPHER *)OBJ_NAME_get(name, OBJ_NAME_TYPE_CIPHER_METH);
+}
+
 const EVP_CIPHER *EVP_get_cipherbyname(const char *name)
+{
+    return evp_get_cipherbyname_ex(NULL, name);
+}
+
+const EVP_CIPHER *evp_get_cipherbyname_ex(OPENSSL_CTX *libctx, const char *name)
 {
     const EVP_CIPHER *cp;
+    OSSL_NAMEMAP *namemap;
+    int id;
 
     if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL))
         return NULL;
 
     cp = (const EVP_CIPHER *)OBJ_NAME_get(name, OBJ_NAME_TYPE_CIPHER_METH);
+
+    if (cp != NULL)
+        return cp;
+
+    /*
+     * It's not in the method database, but it might be there under a different
+     * name. So we check for aliases in the EVP namemap and try all of those
+     * in turn.
+     */
+
+    namemap = ossl_namemap_stored(libctx);
+    id = ossl_namemap_name2num(namemap, name);
+    if (id == 0)
+        return NULL;
+
+    ossl_namemap_doall_names(namemap, id, cipher_from_name, &cp);
+
     return cp;
 }
 
+static void digest_from_name(const char *name, void *data)
+{
+    const EVP_MD **md = data;
+
+    if (*md != NULL)
+        return;
+
+    *md = (const EVP_MD *)OBJ_NAME_get(name, OBJ_NAME_TYPE_MD_METH);
+}
+
 const EVP_MD *EVP_get_digestbyname(const char *name)
 {
-    const EVP_MD *cp;
+    return evp_get_digestbyname_ex(NULL, name);
+}
+
+const EVP_MD *evp_get_digestbyname_ex(OPENSSL_CTX *libctx, const char *name)
+{
+    const EVP_MD *dp;
+    OSSL_NAMEMAP *namemap;
+    int id;
 
     if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL))
         return NULL;
 
-    cp = (const EVP_MD *)OBJ_NAME_get(name, OBJ_NAME_TYPE_MD_METH);
-    return cp;
+    dp = (const EVP_MD *)OBJ_NAME_get(name, OBJ_NAME_TYPE_MD_METH);
+
+    if (dp != NULL)
+        return dp;
+
+    /*
+     * It's not in the method database, but it might be there under a different
+     * name. So we check for aliases in the EVP namemap and try all of those
+     * in turn.
+     */
+
+    namemap = ossl_namemap_stored(libctx);
+    id = ossl_namemap_name2num(namemap, name);
+    if (id == 0)
+        return NULL;
+
+    ossl_namemap_doall_names(namemap, id, digest_from_name, &dp);
+
+    return dp;
 }
 
 void evp_cleanup_int(void)
index cc0707e..30cff95 100644 (file)
@@ -594,7 +594,7 @@ int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **md)
     if (!EVP_PKEY_CTX_get_params(ctx, sig_md_params))
         return 0;
 
-    tmp = EVP_get_digestbyname(name);
+    tmp = evp_get_digestbyname_ex(ctx->libctx, name);
     if (tmp == NULL)
         return 0;
 
index dfbcf14..8f8def2 100644 (file)
@@ -622,3 +622,6 @@ void evp_encode_ctx_set_flags(EVP_ENCODE_CTX *ctx, unsigned int flags);
 #define EVP_ENCODE_CTX_NO_NEWLINES          1
 /* Use the SRP base64 alphabet instead of the standard one */
 #define EVP_ENCODE_CTX_USE_SRP_ALPHABET     2
+
+const EVP_CIPHER *evp_get_cipherbyname_ex(OPENSSL_CTX *libctx, const char *name);
+const EVP_MD *evp_get_digestbyname_ex(OPENSSL_CTX *libctx, const char *name);