Modify EVP_CIPHER_is_a() and EVP_MD_is_a() to handle legacy methods too
authorRichard Levitte <levitte@openssl.org>
Wed, 15 Jan 2020 00:04:37 +0000 (01:04 +0100)
committerRichard Levitte <levitte@openssl.org>
Fri, 17 Jan 2020 07:59:41 +0000 (08:59 +0100)
These functions would only handle provided methods, but there are
cases where the caller just passes along a received method without
knowing the underlying method tech, so might pass along a legacy
method.  We therefore need to have them handle this case as well so
they don't cause any unnecessary surprises.

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

13 files changed:
crypto/core_namemap.c
crypto/evp/evp_fetch.c
crypto/evp/evp_lib.c
crypto/evp/evp_local.h
crypto/evp/exchange.c
crypto/evp/kdf_lib.c
crypto/evp/keymgmt_meth.c
crypto/evp/mac_lib.c
crypto/evp/pmeth_fn.c
crypto/evp/signature.c
doc/man3/EVP_DigestInit.pod
doc/man3/EVP_EncryptInit.pod
test/namemap_internal_test.c

index 9a9d1a5748f8b769e7621a6ebf3eb3a40981c489..4723604ee335de74320e08f15ce911647dd5ff9f 100644 (file)
@@ -294,7 +294,7 @@ int ossl_namemap_add_names(OSSL_NAMEMAP *namemap, int number,
         if (number == 0) {
             number = this_number;
         } else if (this_number != number) {
-            ERR_raise_data(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR,
+            ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR,
                            "Got number %d when expecting %d",
                            this_number, number);
             return 0;
index db479810135950a4b5897f073215c413db1546e7..5bf825d62b4914e34bc9ea078f5f33646ed40587 100644 (file)
@@ -381,11 +381,17 @@ const char *evp_first_name(OSSL_PROVIDER *prov, int name_id)
     return ossl_namemap_num2name(namemap, name_id, 0);
 }
 
-int evp_is_a(OSSL_PROVIDER *prov, int number, const char *name)
+int evp_is_a(OSSL_PROVIDER *prov, int number,
+             const char *legacy_name, const char *name)
 {
+    /*
+     * For a |prov| that is NULL, the library context will be NULL
+     */
     OPENSSL_CTX *libctx = ossl_provider_library_context(prov);
     OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
 
+    if (prov == NULL)
+        number = ossl_namemap_name2num(namemap, legacy_name);
     return ossl_namemap_name2num(namemap, name) == number;
 }
 
index 3c2083148ed63d925b23d3c2ddb9b519d7938a9c..2b5126717982c08af9f63cf342ee7a0b53da1400 100644 (file)
@@ -532,14 +532,9 @@ int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx)
 
 int EVP_CIPHER_is_a(const EVP_CIPHER *cipher, const char *name)
 {
-#ifndef FIPS_MODE
-    if (cipher->prov == NULL) {
-        int nid = EVP_CIPHER_nid(cipher);
-
-        return nid == OBJ_sn2nid(name) || nid == OBJ_ln2nid(name);
-    }
-#endif
-    return evp_is_a(cipher->prov, cipher->name_id, name);
+    if (cipher->prov != NULL)
+        return evp_is_a(cipher->prov, cipher->name_id, NULL, name);
+    return evp_is_a(NULL, 0, EVP_CIPHER_name(cipher), name);
 }
 
 int EVP_CIPHER_number(const EVP_CIPHER *cipher)
@@ -578,7 +573,9 @@ int EVP_CIPHER_mode(const EVP_CIPHER *cipher)
 
 int EVP_MD_is_a(const EVP_MD *md, const char *name)
 {
-    return evp_is_a(md->prov, md->name_id, name);
+    if (md->prov != NULL)
+        return evp_is_a(md->prov, md->name_id, NULL, name);
+    return evp_is_a(NULL, 0, EVP_MD_name(md), name);
 }
 
 int EVP_MD_number(const EVP_MD *md)
index 71051a6587044ea54fcadcd9971ff9aec2f4627f..de73267c98fe1904d9ae829e1e6962e73ef5d95c 100644 (file)
@@ -270,7 +270,8 @@ void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *ctx);
 
 /* OSSL_PROVIDER * is only used to get the library context */
 const char *evp_first_name(OSSL_PROVIDER *prov, int name_id);
-int evp_is_a(OSSL_PROVIDER *prov, int number, const char *name);
+int evp_is_a(OSSL_PROVIDER *prov, int number,
+             const char *legacy_name, const char *name);
 void evp_names_do_all(OSSL_PROVIDER *prov, int number,
                       void (*fn)(const char *name, void *data),
                       void *data);
index ade1dc373dca3021aad9dbf97ffdc28c53fbbfe2..56896390e033a6dde09cb87e29a0f493474a0594 100644 (file)
@@ -380,7 +380,7 @@ int EVP_KEYEXCH_number(const EVP_KEYEXCH *keyexch)
 
 int EVP_KEYEXCH_is_a(const EVP_KEYEXCH *keyexch, const char *name)
 {
-    return evp_is_a(keyexch->prov, keyexch->name_id, name);
+    return evp_is_a(keyexch->prov, keyexch->name_id, NULL, name);
 }
 
 void EVP_KEYEXCH_do_all_provided(OPENSSL_CTX *libctx,
index 5ddf8560d2b443b50f12a7ec7b44c8716729c3a6..84dc910858a122bc6c9caea68db8dd19f25c7e9b 100644 (file)
@@ -90,7 +90,7 @@ int EVP_KDF_number(const EVP_KDF *kdf)
 
 int EVP_KDF_is_a(const EVP_KDF *kdf, const char *name)
 {
-    return evp_is_a(kdf->prov, kdf->name_id, name);
+    return evp_is_a(kdf->prov, kdf->name_id, NULL, name);
 }
 
 const OSSL_PROVIDER *EVP_KDF_provider(const EVP_KDF *kdf)
index 6318ddd3fb874d78cd47751b4b67fb57c660f321..03d1686cf3230cee4f9816317355f439e66ed3f2 100644 (file)
@@ -212,7 +212,7 @@ int EVP_KEYMGMT_number(const EVP_KEYMGMT *keymgmt)
 
 int EVP_KEYMGMT_is_a(const EVP_KEYMGMT *keymgmt, const char *name)
 {
-    return evp_is_a(keymgmt->prov, keymgmt->name_id, name);
+    return evp_is_a(keymgmt->prov, keymgmt->name_id, NULL, name);
 }
 
 void EVP_KEYMGMT_do_all_provided(OPENSSL_CTX *libctx,
index 07ed1c8749408768092f1e3984210a73f131fbe5..bf52aaff8c894de775fa2f81d90aa287217a37b2 100644 (file)
@@ -165,7 +165,7 @@ int EVP_MAC_number(const EVP_MAC *mac)
 
 int EVP_MAC_is_a(const EVP_MAC *mac, const char *name)
 {
-    return evp_is_a(mac->prov, mac->name_id, name);
+    return evp_is_a(mac->prov, mac->name_id, NULL, name);
 }
 
 void EVP_MAC_names_do_all(const EVP_MAC *mac,
index 31422baa4c3e9b37220a8ef3e193f3b3f00bcd28..aa226fcc7b0797d0b1558e8b871b569e7cfae6b3 100644 (file)
@@ -393,7 +393,7 @@ EVP_ASYM_CIPHER *EVP_ASYM_CIPHER_fetch(OPENSSL_CTX *ctx, const char *algorithm,
 
 int EVP_ASYM_CIPHER_is_a(const EVP_ASYM_CIPHER *cipher, const char *name)
 {
-    return evp_is_a(cipher->prov, cipher->name_id, name);
+    return evp_is_a(cipher->prov, cipher->name_id, NULL, name);
 }
 
 int EVP_ASYM_CIPHER_number(const EVP_ASYM_CIPHER *cipher)
index 119cd322a348b4a146dbd932d4c1c0f0f6a5a2a9..1cef4649ed49bf5c7c61a62f48009c928bb3aed8 100644 (file)
@@ -289,7 +289,7 @@ EVP_SIGNATURE *EVP_SIGNATURE_fetch(OPENSSL_CTX *ctx, const char *algorithm,
 
 int EVP_SIGNATURE_is_a(const EVP_SIGNATURE *signature, const char *name)
 {
-    return evp_is_a(signature->prov, signature->name_id, name);
+    return evp_is_a(signature->prov, signature->name_id, NULL, name);
 }
 
 int EVP_SIGNATURE_number(const EVP_SIGNATURE *signature)
index 01da721d56e9d793b28a2e9fb21346ab7a8c6f76..ef40ae49f80f94916612cbb3490049699ff81d21 100644 (file)
@@ -248,6 +248,11 @@ be initialized.
 Returns 1 if I<md> is an implementation of an algorithm that's
 identifiable with I<name>, otherwise 0.
 
+If I<md> is a legacy digest (it's the return value from the likes of
+EVP_sha256() rather than the result of an EVP_MD_fetch()), only cipher
+names registered with the default library context (see
+L<OPENSSL_CTX(3)>) will be considered.
+
 =item EVP_MD_number()
 
 Returns the internal dynamic number assigned to the I<md>.  This is
index a008d0f6f6e3b92c980465fa39bd36a4f44b1ebf..5dc60a0801cc3a83db8a1bb4ecafe2372f768124 100644 (file)
@@ -338,6 +338,10 @@ B<NID_undef>.
 
 EVP_CIPHER_is_a() returns 1 if I<cipher> is an implementation of an
 algorithm that's identifiable with I<name>, otherwise 0.
+If I<cipher> is a legacy cipher (it's the return value from the likes
+of EVP_aes128() rather than the result of an EVP_CIPHER_fetch()), only
+cipher names registered with the default library context (see
+L<OPENSSL_CTX(3)>) will be considered.
 
 EVP_CIPHER_number() returns the internal dynamic number assigned to
 the I<cipher>.  This is only useful with fetched B<EVP_CIPHER>s.
index 263364adbd6bc31a0437b4c556017dfba77ceb77..1d4a657ac67aa848ea797e99f13ecd71e36360da 100644 (file)
@@ -108,6 +108,49 @@ static int test_cipherbyname(void)
     return 1;
 }
 
+/*
+ * Test that EVP_CIPHER_is_a() responds appropriately, even for ciphers that
+ * are entirely legacy.
+ */
+static int test_cipher_is_a(void)
+{
+    EVP_CIPHER *fetched = EVP_CIPHER_fetch(NULL, "AES-256-CCM", NULL);
+    int rv = 1;
+
+    if (!TEST_ptr_ne(fetched, NULL))
+        return 0;
+    if (!TEST_true(EVP_CIPHER_is_a(fetched, "id-aes256-CCM"))
+        || !TEST_false(EVP_CIPHER_is_a(fetched, "AES-128-GCM")))
+        rv = 0;
+    if (!TEST_true(EVP_CIPHER_is_a(EVP_aes_256_gcm(), "AES-256-GCM"))
+        || !TEST_false(EVP_CIPHER_is_a(EVP_aes_256_gcm(), "AES-128-CCM")))
+        rv = 0;
+
+    EVP_CIPHER_free(fetched);
+    return rv;
+}
+
+/*
+ * Test that EVP_MD_is_a() responds appropriately, even for MDs that are
+ * entirely legacy.
+ */
+static int test_digest_is_a(void)
+{
+    EVP_MD *fetched = EVP_MD_fetch(NULL, "SHA2-512", NULL);
+    int rv = 1;
+
+    if (!TEST_ptr_ne(fetched, NULL))
+        return 0;
+    if (!TEST_true(EVP_MD_is_a(fetched, "SHA512"))
+        || !TEST_false(EVP_MD_is_a(fetched, "SHA1")))
+        rv = 0;
+    if (!TEST_true(EVP_MD_is_a(EVP_sha256(), "SHA2-256"))
+        || !TEST_false(EVP_MD_is_a(EVP_sha256(), "SHA3-256")))
+        rv = 0;
+
+    EVP_MD_free(fetched);
+    return rv;
+}
 
 int setup_tests(void)
 {
@@ -115,5 +158,7 @@ int setup_tests(void)
     ADD_TEST(test_namemap_stored);
     ADD_TEST(test_digestbyname);
     ADD_TEST(test_cipherbyname);
+    ADD_TEST(test_digest_is_a);
+    ADD_TEST(test_cipher_is_a);
     return 1;
 }