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)
This commit is contained in:
Richard Levitte 2020-01-15 01:04:37 +01:00
parent 9bb3e5fd87
commit e4a1d02300
13 changed files with 76 additions and 18 deletions

View 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;

View 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;
}

View 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)

View 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);

View 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,

View 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)

View 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,

View 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,

View 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)

View 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)

View 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

View 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.

View 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;
}