From 213a33e79fc1d0554d7cdad8496a805d6eacc77f Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Wed, 29 Sep 2021 11:05:41 +0200 Subject: Adapt our OSSL_FUNC_keymgmt_match() implementations to the EVP_PKEY_eq() fix The match function (called OSSL_FUNC_keymgmt_match() in our documentation) in our KEYMGMT implementations were interpretting the selector bits a bit too strictly, so they get a bit relaxed to make it reasonable to match diverse key contents. Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/16765) (cherry picked from commit ee22a3741e3fc27c981e7f7e9bcb8d3342b0c65a) --- providers/implementations/keymgmt/dh_kmgmt.c | 28 ++++++++++++--- providers/implementations/keymgmt/dsa_kmgmt.c | 30 ++++++++++++---- providers/implementations/keymgmt/ec_kmgmt.c | 30 +++++++++++----- providers/implementations/keymgmt/ecx_kmgmt.c | 51 +++++++++++++++++---------- providers/implementations/keymgmt/rsa_kmgmt.c | 28 ++++++++++++--- 5 files changed, 126 insertions(+), 41 deletions(-) diff --git a/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c index c4cda447bf..98eb882e3f 100644 --- a/providers/implementations/keymgmt/dh_kmgmt.c +++ b/providers/implementations/keymgmt/dh_kmgmt.c @@ -154,10 +154,30 @@ static int dh_match(const void *keydata1, const void *keydata2, int selection) if (!ossl_prov_is_running()) return 0; - if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) - ok = ok && BN_cmp(DH_get0_pub_key(dh1), DH_get0_pub_key(dh2)) == 0; - if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) - ok = ok && BN_cmp(DH_get0_priv_key(dh1), DH_get0_priv_key(dh2)) == 0; + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { + int key_checked = 0; + + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { + const BIGNUM *pa = DH_get0_pub_key(dh1); + const BIGNUM *pb = DH_get0_pub_key(dh2); + + if (pa != NULL && pb != NULL) { + ok = ok && BN_cmp(pa, pb) == 0; + key_checked = 1; + } + } + if (!key_checked + && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { + const BIGNUM *pa = DH_get0_priv_key(dh1); + const BIGNUM *pb = DH_get0_priv_key(dh2); + + if (pa != NULL && pb != NULL) { + ok = ok && BN_cmp(pa, pb) == 0; + key_checked = 1; + } + } + ok = ok && key_checked; + } if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { FFC_PARAMS *dhparams1 = ossl_dh_get0_params((DH *)dh1); FFC_PARAMS *dhparams2 = ossl_dh_get0_params((DH *)dh2); diff --git a/providers/implementations/keymgmt/dsa_kmgmt.c b/providers/implementations/keymgmt/dsa_kmgmt.c index 4f05799bb3..1e1b168f7d 100644 --- a/providers/implementations/keymgmt/dsa_kmgmt.c +++ b/providers/implementations/keymgmt/dsa_kmgmt.c @@ -154,12 +154,30 @@ static int dsa_match(const void *keydata1, const void *keydata2, int selection) if (!ossl_prov_is_running()) return 0; - if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) - ok = ok - && BN_cmp(DSA_get0_pub_key(dsa1), DSA_get0_pub_key(dsa2)) == 0; - if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) - ok = ok - && BN_cmp(DSA_get0_priv_key(dsa1), DSA_get0_priv_key(dsa2)) == 0; + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { + int key_checked = 0; + + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { + const BIGNUM *pa = DSA_get0_pub_key(dsa1); + const BIGNUM *pb = DSA_get0_pub_key(dsa2); + + if (pa != NULL && pb != NULL) { + ok = ok && BN_cmp(pa, pb) == 0; + key_checked = 1; + } + } + if (!key_checked + && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { + const BIGNUM *pa = DSA_get0_priv_key(dsa1); + const BIGNUM *pb = DSA_get0_priv_key(dsa2); + + if (pa != NULL && pb != NULL) { + ok = ok && BN_cmp(pa, pb) == 0; + key_checked = 1; + } + } + ok = ok && key_checked; + } if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { FFC_PARAMS *dsaparams1 = ossl_dsa_get0_params((DSA *)dsa1); FFC_PARAMS *dsaparams2 = ossl_dsa_get0_params((DSA *)dsa2); diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c index 24d4df543b..15b4532cd7 100644 --- a/providers/implementations/keymgmt/ec_kmgmt.c +++ b/providers/implementations/keymgmt/ec_kmgmt.c @@ -337,17 +337,29 @@ static int ec_match(const void *keydata1, const void *keydata2, int selection) if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) ok = ok && group_a != NULL && group_b != NULL && EC_GROUP_cmp(group_a, group_b, ctx) == 0; - if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { - const BIGNUM *pa = EC_KEY_get0_private_key(ec1); - const BIGNUM *pb = EC_KEY_get0_private_key(ec2); + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { + int key_checked = 0; - ok = ok && BN_cmp(pa, pb) == 0; - } - if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { - const EC_POINT *pa = EC_KEY_get0_public_key(ec1); - const EC_POINT *pb = EC_KEY_get0_public_key(ec2); + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { + const EC_POINT *pa = EC_KEY_get0_public_key(ec1); + const EC_POINT *pb = EC_KEY_get0_public_key(ec2); - ok = ok && EC_POINT_cmp(group_b, pa, pb, ctx) == 0; + if (pa != NULL && pb != NULL) { + ok = ok && EC_POINT_cmp(group_b, pa, pb, ctx) == 0; + key_checked = 1; + } + } + if (!key_checked + && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { + const BIGNUM *pa = EC_KEY_get0_private_key(ec1); + const BIGNUM *pb = EC_KEY_get0_private_key(ec2); + + if (pa != NULL && pb != NULL) { + ok = ok && BN_cmp(pa, pb) == 0; + key_checked = 1; + } + } + ok = ok && key_checked; } BN_CTX_free(ctx); return ok; diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c index b088c03b30..2be9508692 100644 --- a/providers/implementations/keymgmt/ecx_kmgmt.c +++ b/providers/implementations/keymgmt/ecx_kmgmt.c @@ -153,24 +153,39 @@ static int ecx_match(const void *keydata1, const void *keydata2, int selection) if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) ok = ok && key1->type == key2->type; - if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { - if ((key1->privkey == NULL && key2->privkey != NULL) - || (key1->privkey != NULL && key2->privkey == NULL) - || key1->type != key2->type) - ok = 0; - else - ok = ok && (key1->privkey == NULL /* implies key2->privkey == NULL */ - || CRYPTO_memcmp(key1->privkey, key2->privkey, - key1->keylen) == 0); - } - if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { - if (key1->haspubkey != key2->haspubkey - || key1->type != key2->type) - ok = 0; - else - ok = ok && (key1->haspubkey == 0 /* implies key2->haspubkey == 0 */ - || CRYPTO_memcmp(key1->pubkey, key2->pubkey, - key1->keylen) == 0); + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { + int key_checked = 0; + + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { + const unsigned char *pa = key1->haspubkey ? key1->pubkey : NULL; + const unsigned char *pb = key2->haspubkey ? key2->pubkey : NULL; + size_t pal = key1->keylen; + size_t pbl = key2->keylen; + + if (pa != NULL && pb != NULL) { + ok = ok + && key1->type == key2->type + && pal == pbl + && CRYPTO_memcmp(pa, pb, pal) == 0; + key_checked = 1; + } + } + if (!key_checked + && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { + const unsigned char *pa = key1->privkey; + const unsigned char *pb = key2->privkey; + size_t pal = key1->keylen; + size_t pbl = key2->keylen; + + if (pa != NULL && pb != NULL) { + ok = ok + && key1->type == key2->type + && pal == pbl + && CRYPTO_memcmp(pa, pb, pal) == 0; + key_checked = 1; + } + } + ok = ok && key_checked; } return ok; } diff --git a/providers/implementations/keymgmt/rsa_kmgmt.c b/providers/implementations/keymgmt/rsa_kmgmt.c index 34871629ba..b1c3011f14 100644 --- a/providers/implementations/keymgmt/rsa_kmgmt.c +++ b/providers/implementations/keymgmt/rsa_kmgmt.c @@ -143,10 +143,30 @@ static int rsa_match(const void *keydata1, const void *keydata2, int selection) /* There is always an |e| */ ok = ok && BN_cmp(RSA_get0_e(rsa1), RSA_get0_e(rsa2)) == 0; - if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) - ok = ok && BN_cmp(RSA_get0_n(rsa1), RSA_get0_n(rsa2)) == 0; - if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) - ok = ok && BN_cmp(RSA_get0_d(rsa1), RSA_get0_d(rsa2)) == 0; + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { + int key_checked = 0; + + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { + const BIGNUM *pa = RSA_get0_n(rsa1); + const BIGNUM *pb = RSA_get0_n(rsa2); + + if (pa != NULL && pb != NULL) { + ok = ok && BN_cmp(pa, pb) == 0; + key_checked = 1; + } + } + if (!key_checked + && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { + const BIGNUM *pa = RSA_get0_d(rsa1); + const BIGNUM *pb = RSA_get0_d(rsa2); + + if (pa != NULL && pb != NULL) { + ok = ok && BN_cmp(pa, pb) == 0; + key_checked = 1; + } + } + ok = ok && key_checked; + } return ok; } -- cgit v1.2.3