mirror of
https://github.com/openssl/openssl.git
synced 2025-01-30 14:01:55 +08:00
EVP: Add support for comparing provided EVP_PKEYs
This adds evp_keymgmt_util_match() and affects EVP_PKEY_cmp() and EVP_PKEY_cmp_parameters(). The word 'match' was used for the new routines because many associate 'cmp' with comparison functions that allows sorting, i.e. return -1, 0 or 1 depending on the order in which the two compared elements should be sorted. EVP_PKEY_cmp() and EVP_PKEY_cmp_parameters() don't quite do that. Reviewed-by: Shane Lontis <shane.lontis@oracle.com> (Merged from https://github.com/openssl/openssl/pull/11158)
This commit is contained in:
parent
bee5d6cd3f
commit
1e9101c404
@ -223,3 +223,73 @@ int evp_keymgmt_util_has(EVP_PKEY *pk, int selection)
|
|||||||
|
|
||||||
return evp_keymgmt_has(pk->keymgmt, pk->keydata, selection);
|
return evp_keymgmt_has(pk->keymgmt, pk->keydata, selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* evp_keymgmt_util_match() doesn't just look at the provider side "origin",
|
||||||
|
* but also in the operation cache to see if there's any common keymgmt that
|
||||||
|
* supplies OP_keymgmt_match.
|
||||||
|
*
|
||||||
|
* evp_keymgmt_util_match() adheres to the return values that EVP_PKEY_cmp()
|
||||||
|
* and EVP_PKEY_cmp_parameters() return, i.e.:
|
||||||
|
*
|
||||||
|
* 1 same key
|
||||||
|
* 0 not same key
|
||||||
|
* -1 not same key type
|
||||||
|
* -2 unsupported operation
|
||||||
|
*/
|
||||||
|
int evp_keymgmt_util_match(EVP_PKEY *pk1, EVP_PKEY *pk2, int selection)
|
||||||
|
{
|
||||||
|
EVP_KEYMGMT *keymgmt1 = NULL, *keymgmt2 = NULL;
|
||||||
|
void *keydata1 = NULL, *keydata2 = NULL;
|
||||||
|
|
||||||
|
if (pk1 == NULL || pk2 == NULL) {
|
||||||
|
if (pk1 == NULL && pk2 == NULL)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
keymgmt1 = pk1->keymgmt;
|
||||||
|
keydata1 = pk1->keydata;
|
||||||
|
keymgmt2 = pk2->keymgmt;
|
||||||
|
keydata2 = pk2->keydata;
|
||||||
|
|
||||||
|
if (keymgmt1 != keymgmt2) {
|
||||||
|
void *tmp_keydata = NULL;
|
||||||
|
|
||||||
|
/* Complex case, where the keymgmt differ */
|
||||||
|
if (keymgmt1 != NULL
|
||||||
|
&& keymgmt2 != NULL
|
||||||
|
&& !match_type(keymgmt1, keymgmt2)) {
|
||||||
|
ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES);
|
||||||
|
return -1; /* Not the same type */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The key types are determined to match, so we try cross export,
|
||||||
|
* but only to keymgmt's that supply a matching function.
|
||||||
|
*/
|
||||||
|
if (keymgmt2 != NULL
|
||||||
|
&& keymgmt2->match != NULL) {
|
||||||
|
tmp_keydata = evp_keymgmt_util_export_to_provider(pk1, keymgmt2);
|
||||||
|
if (tmp_keydata != NULL) {
|
||||||
|
keymgmt1 = keymgmt2;
|
||||||
|
keydata1 = tmp_keydata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tmp_keydata == NULL
|
||||||
|
&& keymgmt1 != NULL
|
||||||
|
&& keymgmt1->match != NULL) {
|
||||||
|
tmp_keydata = evp_keymgmt_util_export_to_provider(pk2, keymgmt1);
|
||||||
|
if (tmp_keydata != NULL) {
|
||||||
|
keymgmt2 = keymgmt1;
|
||||||
|
keydata2 = tmp_keydata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we still don't have matching keymgmt implementations, we give up */
|
||||||
|
if (keymgmt1 != keymgmt2)
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
return evp_keymgmt_match(keymgmt1, keydata1, keydata2, selection);
|
||||||
|
}
|
||||||
|
@ -124,30 +124,108 @@ int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function is called for any mixture of keys except pure legacy pair.
|
||||||
|
* TODO When legacy keys are gone, we replace a call to this functions with
|
||||||
|
* a call to evp_keymgmt_util_match().
|
||||||
|
*/
|
||||||
|
static int evp_pkey_cmp_any(const EVP_PKEY *a, const EVP_PKEY *b,
|
||||||
|
int selection)
|
||||||
|
{
|
||||||
|
EVP_KEYMGMT *keymgmt1 = NULL, *keymgmt2 = NULL;
|
||||||
|
void *keydata1 = NULL, *keydata2 = NULL, *tmp_keydata = NULL;
|
||||||
|
|
||||||
|
/* If none of them are provided, this function shouldn't have been called */
|
||||||
|
if (!ossl_assert(a->keymgmt != NULL || b->keymgmt != NULL))
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
/* For purely provided keys, we just call the keymgmt utility */
|
||||||
|
if (a->keymgmt != NULL && b->keymgmt != NULL)
|
||||||
|
return evp_keymgmt_util_match((EVP_PKEY *)a, (EVP_PKEY *)b, selection);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here, we know that we have a mixture of legacy and provided keys.
|
||||||
|
* Try cross export and compare the resulting key data.
|
||||||
|
*/
|
||||||
|
keymgmt1 = a->keymgmt;
|
||||||
|
keydata1 = a->keydata;
|
||||||
|
keymgmt2 = b->keymgmt;
|
||||||
|
keydata2 = b->keydata;
|
||||||
|
|
||||||
|
if ((keymgmt1 == NULL
|
||||||
|
&& !EVP_KEYMGMT_is_a(keymgmt2, OBJ_nid2sn(a->type)))
|
||||||
|
|| (keymgmt2 == NULL
|
||||||
|
&& !EVP_KEYMGMT_is_a(keymgmt1, OBJ_nid2sn(b->type))))
|
||||||
|
return -1; /* not the same key type */
|
||||||
|
|
||||||
|
if (keymgmt2 != NULL && keymgmt2->match != NULL) {
|
||||||
|
tmp_keydata =
|
||||||
|
evp_pkey_export_to_provider((EVP_PKEY *)a, NULL, &keymgmt2, NULL);
|
||||||
|
if (tmp_keydata != NULL) {
|
||||||
|
keymgmt1 = keymgmt2;
|
||||||
|
keydata1 = tmp_keydata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tmp_keydata == NULL && keymgmt1 != NULL && keymgmt1->match != NULL) {
|
||||||
|
tmp_keydata =
|
||||||
|
evp_pkey_export_to_provider((EVP_PKEY *)b, NULL, &keymgmt1, NULL);
|
||||||
|
if (tmp_keydata != NULL) {
|
||||||
|
keymgmt2 = keymgmt1;
|
||||||
|
keydata2 = tmp_keydata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we still don't have matching keymgmt implementations, we give up */
|
||||||
|
if (keymgmt1 != keymgmt2)
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
return evp_keymgmt_match(keymgmt1, keydata1, keydata2, selection);
|
||||||
|
}
|
||||||
|
|
||||||
int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
|
int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* TODO: clean up legacy stuff from this function when legacy support
|
||||||
|
* is gone.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (a->keymgmt != NULL || b->keymgmt != NULL)
|
||||||
|
return evp_pkey_cmp_any(a, b, OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
|
||||||
|
|
||||||
|
/* All legacy keys */
|
||||||
if (a->type != b->type)
|
if (a->type != b->type)
|
||||||
return -1;
|
return -1;
|
||||||
if (a->ameth && a->ameth->param_cmp)
|
if (a->ameth != NULL && a->ameth->param_cmp != NULL)
|
||||||
return a->ameth->param_cmp(a, b);
|
return a->ameth->param_cmp(a, b);
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
|
int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* TODO: clean up legacy stuff from this function when legacy support
|
||||||
|
* is gone.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (a->keymgmt != NULL || b->keymgmt != NULL)
|
||||||
|
return evp_pkey_cmp_any(a, b,
|
||||||
|
OSSL_KEYMGMT_SELECT_ALL_PARAMETERS
|
||||||
|
| OSSL_KEYMGMT_SELECT_PUBLIC_KEY);
|
||||||
|
|
||||||
|
/* All legacy keys */
|
||||||
if (a->type != b->type)
|
if (a->type != b->type)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (a->ameth) {
|
if (a->ameth != NULL) {
|
||||||
int ret;
|
int ret;
|
||||||
/* Compare parameters if the algorithm has them */
|
/* Compare parameters if the algorithm has them */
|
||||||
if (a->ameth->param_cmp) {
|
if (a->ameth->param_cmp != NULL) {
|
||||||
ret = a->ameth->param_cmp(a, b);
|
ret = a->ameth->param_cmp(a, b);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a->ameth->pub_cmp)
|
if (a->ameth->pub_cmp != NULL)
|
||||||
return a->ameth->pub_cmp(a, b);
|
return a->ameth->pub_cmp(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -620,6 +620,7 @@ void evp_keymgmt_util_cache_keyinfo(EVP_PKEY *pk);
|
|||||||
void *evp_keymgmt_util_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
|
void *evp_keymgmt_util_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
|
||||||
int selection, const OSSL_PARAM params[]);
|
int selection, const OSSL_PARAM params[]);
|
||||||
int evp_keymgmt_util_has(EVP_PKEY *pk, int selection);
|
int evp_keymgmt_util_has(EVP_PKEY *pk, int selection);
|
||||||
|
int evp_keymgmt_util_match(EVP_PKEY *pk1, EVP_PKEY *pk2, int selection);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user