aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2020-01-15 01:04:37 +0100
committerRichard Levitte <levitte@openssl.org>2020-01-17 08:59:41 +0100
commite4a1d0230016d090ba78bc7092384315f85b0e72 (patch)
tree518e1155d0185622e42d10918b9b0ca9a2317c3a
parent9bb3e5fd87905e3e9f5f7edcc2e22d98360510ab (diff)
downloadopenssl-e4a1d0230016d090ba78bc7092384315f85b0e72.tar.gz
Modify EVP_CIPHER_is_a() and EVP_MD_is_a() to handle legacy methods too
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)
-rw-r--r--crypto/core_namemap.c2
-rw-r--r--crypto/evp/evp_fetch.c8
-rw-r--r--crypto/evp/evp_lib.c15
-rw-r--r--crypto/evp/evp_local.h3
-rw-r--r--crypto/evp/exchange.c2
-rw-r--r--crypto/evp/kdf_lib.c2
-rw-r--r--crypto/evp/keymgmt_meth.c2
-rw-r--r--crypto/evp/mac_lib.c2
-rw-r--r--crypto/evp/pmeth_fn.c2
-rw-r--r--crypto/evp/signature.c2
-rw-r--r--doc/man3/EVP_DigestInit.pod5
-rw-r--r--doc/man3/EVP_EncryptInit.pod4
-rw-r--r--test/namemap_internal_test.c45
13 files changed, 76 insertions, 18 deletions
diff --git a/crypto/core_namemap.c b/crypto/core_namemap.c
index 9a9d1a5748..4723604ee3 100644
--- a/crypto/core_namemap.c
+++ b/crypto/core_namemap.c
@@ -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;
diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c
index db47981013..5bf825d62b 100644
--- a/crypto/evp/evp_fetch.c
+++ b/crypto/evp/evp_fetch.c
@@ -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;
}
diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c
index 3c2083148e..2b51267179 100644
--- a/crypto/evp/evp_lib.c
+++ b/crypto/evp/evp_lib.c
@@ -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)
diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h
index 71051a6587..de73267c98 100644
--- a/crypto/evp/evp_local.h
+++ b/crypto/evp/evp_local.h
@@ -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);
diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c
index ade1dc373d..56896390e0 100644
--- a/crypto/evp/exchange.c
+++ b/crypto/evp/exchange.c
@@ -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,
diff --git a/crypto/evp/kdf_lib.c b/crypto/evp/kdf_lib.c
index 5ddf8560d2..84dc910858 100644
--- a/crypto/evp/kdf_lib.c
+++ b/crypto/evp/kdf_lib.c
@@ -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)
diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c
index 6318ddd3fb..03d1686cf3 100644
--- a/crypto/evp/keymgmt_meth.c
+++ b/crypto/evp/keymgmt_meth.c
@@ -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,
diff --git a/crypto/evp/mac_lib.c b/crypto/evp/mac_lib.c
index 07ed1c8749..bf52aaff8c 100644
--- a/crypto/evp/mac_lib.c
+++ b/crypto/evp/mac_lib.c
@@ -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,
diff --git a/crypto/evp/pmeth_fn.c b/crypto/evp/pmeth_fn.c
index 31422baa4c..aa226fcc7b 100644
--- a/crypto/evp/pmeth_fn.c
+++ b/crypto/evp/pmeth_fn.c
@@ -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)
diff --git a/crypto/evp/signature.c b/crypto/evp/signature.c
index 119cd322a3..1cef4649ed 100644
--- a/crypto/evp/signature.c
+++ b/crypto/evp/signature.c
@@ -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)
diff --git a/doc/man3/EVP_DigestInit.pod b/doc/man3/EVP_DigestInit.pod
index 01da721d56..ef40ae49f8 100644
--- a/doc/man3/EVP_DigestInit.pod
+++ b/doc/man3/EVP_DigestInit.pod
@@ -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
diff --git a/doc/man3/EVP_EncryptInit.pod b/doc/man3/EVP_EncryptInit.pod
index a008d0f6f6..5dc60a0801 100644
--- a/doc/man3/EVP_EncryptInit.pod
+++ b/doc/man3/EVP_EncryptInit.pod
@@ -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.
diff --git a/test/namemap_internal_test.c b/test/namemap_internal_test.c
index 263364adbd..1d4a657ac6 100644
--- a/test/namemap_internal_test.c
+++ b/test/namemap_internal_test.c
@@ -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;
}