[openssl] openssl-3.0 update

Richard Levitte levitte at openssl.org
Mon Dec 13 06:58:41 UTC 2021


The branch openssl-3.0 has been updated
       via  bfa90fcaeaef775d0dfa5da3c0ad7da9f09fb60d (commit)
       via  cfe271e2b89658e6980e7d054bde9c164f2e8687 (commit)
       via  fc87d5dad26b4ad3351ed006024f9c48deebccb5 (commit)
       via  213a33e79fc1d0554d7cdad8496a805d6eacc77f (commit)
       via  9aaa943f0a9f9cc2b6610d40619423cc5614dc38 (commit)
      from  bfda2e0d85fcc521544920b7bbe45c87b425ae90 (commit)


- Log -----------------------------------------------------------------
commit bfa90fcaeaef775d0dfa5da3c0ad7da9f09fb60d
Author: Richard Levitte <levitte at openssl.org>
Date:   Fri Dec 10 13:18:42 2021 +0100

    test/evp_extra_test.c: Add EVP_PKEY comparisons in test_EC_priv_pub()
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/16765)
    
    (cherry picked from commit edc8566f475d63278d5f85cd25f324cf2fe9aaf9)

commit cfe271e2b89658e6980e7d054bde9c164f2e8687
Author: Richard Levitte <levitte at openssl.org>
Date:   Fri Dec 10 13:15:10 2021 +0100

    test/evp_extra_test.c: Refactor test_fromdata()
    
    test_fromdata() turns out to be a bit inflexible, so we split it into
    two functions, make_key_fromdata() and test_selection(), and adjust
    test_EVP_PKEY_ffc_priv_pub() and test_EC_priv_pub() accordingly.  This
    allows us to check the resulting keys further, not only to check that
    the bits we expect are there, but also that the bits that we expect
    not to be there to actually not be there!
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/16765)
    
    (cherry picked from commit 5fbe15fd3b7c90a0cfb9f00be16225d8ed18b0dd)

commit fc87d5dad26b4ad3351ed006024f9c48deebccb5
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Sep 29 13:45:55 2021 +0200

    Enhance the explanation of selector bits in provider-keymgmt(7)
    
    This uncovers what has been a mere comment in an attempt to clarify
    that the use of selector bits is very much at the discretion of the
    provider implementation.
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/16765)
    
    (cherry picked from commit e67254e4c3d82b1b8f5102bc4a0e7914f0b87ef0)

commit 213a33e79fc1d0554d7cdad8496a805d6eacc77f
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Sep 29 11:05:41 2021 +0200

    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 <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/16765)
    
    (cherry picked from commit ee22a3741e3fc27c981e7f7e9bcb8d3342b0c65a)

commit 9aaa943f0a9f9cc2b6610d40619423cc5614dc38
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Sep 29 10:58:21 2021 +0200

    Fix EVP_PKEY_eq() to be possible to use with strictly private keys
    
    EVP_PKEY_eq() assumed that an EVP_PKEY always has the public key
    component if it has a private key component.  However, this assumption
    no longer strictly holds true, at least for provider backed keys.
    EVP_PKEY_eq() therefore needs to be modified to specify that the
    private key should be checked too (at the discretion of what's
    reasonable for the implementation doing the actual comparison).
    
    Fixes #16267
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/16765)
    
    (cherry picked from commit f3ba62653815b2f7991103cdbea1ac155c8c916a)

-----------------------------------------------------------------------

Summary of changes:
 crypto/evp/p_lib.c                            |   2 +-
 doc/man3/EVP_PKEY_copy_parameters.pod         |  40 +++++--
 doc/man7/provider-keymgmt.pod                 |  11 +-
 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 ++++-
 test/evp_extra_test.c                         | 150 ++++++++++++++++++--------
 9 files changed, 272 insertions(+), 98 deletions(-)

diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index 2552dd702a..27138af564 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -343,7 +343,7 @@ int EVP_PKEY_eq(const EVP_PKEY *a, const EVP_PKEY *b)
 
     if (a->keymgmt != NULL || b->keymgmt != NULL)
         return evp_pkey_cmp_any(a, b, (SELECT_PARAMETERS
-                                       | OSSL_KEYMGMT_SELECT_PUBLIC_KEY));
+                                       | OSSL_KEYMGMT_SELECT_KEYPAIR));
 
     /* All legacy keys */
     if (a->type != b->type)
diff --git a/doc/man3/EVP_PKEY_copy_parameters.pod b/doc/man3/EVP_PKEY_copy_parameters.pod
index 46ce8be19b..adb5c2084e 100644
--- a/doc/man3/EVP_PKEY_copy_parameters.pod
+++ b/doc/man3/EVP_PKEY_copy_parameters.pod
@@ -37,8 +37,8 @@ in B<from> and B<to> are both present and match this function has no effect.
 The function EVP_PKEY_parameters_eq() checks the parameters of keys
 B<a> and B<b> for equality.
 
-The function EVP_PKEY_eq() checks the public key components and parameters
-(if present) of keys B<a> and B<b> for equality.
+The function EVP_PKEY_eq() checks the keys B<a> and B<b> for equality,
+including their parameters if they are available.
 
 =head1 NOTES
 
@@ -47,14 +47,40 @@ EVP_PKEY_copy_parameters() is to handle public keys in certificates where the
 parameters are sometimes omitted from a public key if they are inherited from
 the CA that signed it.
 
-Since OpenSSL private keys contain public key components too the function
-EVP_PKEY_eq() can also be used to determine if a private key matches
-a public key.
-
 The deprecated functions EVP_PKEY_cmp() and EVP_PKEY_cmp_parameters() differ in
-their return values  compared to other _cmp() functions. They are aliases for
+their return values compared to other _cmp() functions. They are aliases for
 EVP_PKEY_eq() and EVP_PKEY_parameters_eq().
 
+The function EVP_PKEY_cmp() previously only checked the key parameters
+(if there are any) and the public key, assuming that there always was
+a public key and that private key equality could be derived from that.
+Because it's no longer assumed that the private key in an L<EVP_PKEY(3)> is
+always accompanied by a public key, the comparison can not rely on public
+key comparison alone.
+
+Instead, EVP_PKEY_eq() (and therefore also EVP_PKEY_cmp()) now compares:
+
+=over 4
+
+=item 1.
+
+the key parameters (if there are any)
+
+=item 2.
+
+the public keys or the private keys of the two B<EVP_PKEY>s, depending on
+what they both contain.
+
+=back
+
+=begin comment
+
+Exactly what is compared is ultimately at the discretion of the provider
+that holds the key, as they will compare what makes sense to them that fits
+the selector bits they are passed.
+
+=end comment
+
 =head1 RETURN VALUES
 
 The function EVP_PKEY_missing_parameters() returns 1 if the public key
diff --git a/doc/man7/provider-keymgmt.pod b/doc/man7/provider-keymgmt.pod
index b0397b4103..fc8d995f44 100644
--- a/doc/man7/provider-keymgmt.pod
+++ b/doc/man7/provider-keymgmt.pod
@@ -200,12 +200,11 @@ Indicating that everything in a key object should be considered.
 The exact interpretation of those bits or how they combine is left to
 each function where you can specify a selector.
 
-=for comment One might think that a combination of bits means that all
-the selected data subsets must be considered, but then you have to
-consider that when comparing key objects (future function), an
-implementation might opt to not compare the private key if it has
-compared the public key, since a match of one half implies a match of
-the other half.
+It's left to the provider implementation to decide what is reasonable
+to do with regards to received selector bits and how to do it.
+Among others, an implementation of OSSL_FUNC_keymgmt_match() might opt
+to not compare the private half if it has compared the public half,
+since a match of one half implies a match of the other half.
 
 =head2 Constructing and Destructing Functions
 
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;
 }
 
diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c
index e6582315c0..47ef35ca67 100644
--- a/test/evp_extra_test.c
+++ b/test/evp_extra_test.c
@@ -679,25 +679,35 @@ err:
 }
 
 #if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC)
-static int test_fromdata(char *keytype, int selection, OSSL_PARAM *params)
+static EVP_PKEY *make_key_fromdata(char *keytype, OSSL_PARAM *params)
 {
     EVP_PKEY_CTX *pctx = NULL;
-    EVP_PKEY *pkey = NULL;
-    int testresult = 0;
-    int ret;
-    BIO *bio = BIO_new(BIO_s_mem());
+    EVP_PKEY *tmp_pkey = NULL, *pkey = NULL;
 
     if (!TEST_ptr(pctx = EVP_PKEY_CTX_new_from_name(testctx, keytype, testpropq)))
         goto err;
     if (!TEST_int_gt(EVP_PKEY_fromdata_init(pctx), 0)
-        || !TEST_int_gt(EVP_PKEY_fromdata(pctx, &pkey, EVP_PKEY_KEYPAIR,
+        || !TEST_int_gt(EVP_PKEY_fromdata(pctx, &tmp_pkey, EVP_PKEY_KEYPAIR,
                                           params), 0))
         goto err;
 
-    if (!TEST_ptr(pkey))
+    if (!TEST_ptr(tmp_pkey))
         goto err;
 
-    /* Check we can use the resulting key */
+    pkey = tmp_pkey;
+    tmp_pkey = NULL;
+ err:
+    EVP_PKEY_free(tmp_pkey);
+    EVP_PKEY_CTX_free(pctx);
+    return pkey;
+}
+
+static int test_selection(EVP_PKEY *pkey, int selection)
+{
+    int testresult = 0;
+    int ret;
+    BIO *bio = BIO_new(BIO_s_mem());
+
     ret = PEM_write_bio_PUBKEY(bio, pkey);
     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
         if (!TEST_true(ret))
@@ -718,8 +728,6 @@ static int test_fromdata(char *keytype, int selection, OSSL_PARAM *params)
 
     testresult = 1;
  err:
-    EVP_PKEY_free(pkey);
-    EVP_PKEY_CTX_free(pctx);
     BIO_free(bio);
 
     return testresult;
@@ -735,6 +743,10 @@ static int test_EVP_PKEY_ffc_priv_pub(char *keytype)
 {
     OSSL_PARAM_BLD *bld = NULL;
     OSSL_PARAM *params = NULL;
+    EVP_PKEY *just_params = NULL;
+    EVP_PKEY *params_and_priv = NULL;
+    EVP_PKEY *params_and_pub = NULL;
+    EVP_PKEY *params_and_keypair = NULL;
     BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub = NULL, *priv = NULL;
     int ret = 0;
 
@@ -755,14 +767,18 @@ static int test_EVP_PKEY_ffc_priv_pub(char *keytype)
         || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_Q, q))
         || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, g)))
         goto err;
-    if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld)))
+    if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))
+        || !TEST_ptr(just_params = make_key_fromdata(keytype, params)))
         goto err;
 
-    if (!test_fromdata(keytype, OSSL_KEYMGMT_SELECT_ALL_PARAMETERS, params))
-        goto err;
     OSSL_PARAM_free(params);
-    params = NULL;
     OSSL_PARAM_BLD_free(bld);
+    params = NULL;
+    bld = NULL;
+
+    if (!test_selection(just_params, OSSL_KEYMGMT_SELECT_ALL_PARAMETERS)
+        || test_selection(just_params, OSSL_KEYMGMT_SELECT_KEYPAIR))
+        goto err;
 
     /* Test priv and !pub */
     if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
@@ -772,14 +788,18 @@ static int test_EVP_PKEY_ffc_priv_pub(char *keytype)
         || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY,
                                              priv)))
         goto err;
-    if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld)))
+    if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))
+        || !TEST_ptr(params_and_priv = make_key_fromdata(keytype, params)))
         goto err;
 
-    if (!test_fromdata(keytype, OSSL_KEYMGMT_SELECT_PRIVATE_KEY, params))
-        goto err;
     OSSL_PARAM_free(params);
-    params = NULL;
     OSSL_PARAM_BLD_free(bld);
+    params = NULL;
+    bld = NULL;
+
+    if (!test_selection(params_and_priv, OSSL_KEYMGMT_SELECT_PRIVATE_KEY)
+        || test_selection(params_and_priv, OSSL_KEYMGMT_SELECT_PUBLIC_KEY))
+        goto err;
 
     /* Test !priv and pub */
     if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
@@ -789,14 +809,18 @@ static int test_EVP_PKEY_ffc_priv_pub(char *keytype)
         || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY,
                                              pub)))
         goto err;
-    if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld)))
+    if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))
+        || !TEST_ptr(params_and_pub = make_key_fromdata(keytype, params)))
         goto err;
 
-    if (!test_fromdata(keytype, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, params))
-        goto err;
     OSSL_PARAM_free(params);
-    params = NULL;
     OSSL_PARAM_BLD_free(bld);
+    params = NULL;
+    bld = NULL;
+
+    if (!test_selection(params_and_pub, OSSL_KEYMGMT_SELECT_PUBLIC_KEY)
+        || test_selection(params_and_pub, OSSL_KEYMGMT_SELECT_PRIVATE_KEY))
+        goto err;
 
     /* Test priv and pub */
     if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
@@ -808,16 +832,21 @@ static int test_EVP_PKEY_ffc_priv_pub(char *keytype)
         || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY,
                                              priv)))
         goto err;
-    if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld)))
+    if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))
+        || !TEST_ptr(params_and_keypair = make_key_fromdata(keytype, params)))
         goto err;
 
-    if (!test_fromdata(keytype, EVP_PKEY_KEYPAIR, params))
+    if (!test_selection(params_and_keypair, EVP_PKEY_KEYPAIR))
         goto err;
 
     ret = 1;
  err:
     OSSL_PARAM_free(params);
     OSSL_PARAM_BLD_free(bld);
+    EVP_PKEY_free(just_params);
+    EVP_PKEY_free(params_and_priv);
+    EVP_PKEY_free(params_and_pub);
+    EVP_PKEY_free(params_and_keypair);
     BN_free(p);
     BN_free(q);
     BN_free(g);
@@ -851,6 +880,10 @@ static int test_EC_priv_pub(void)
 {
     OSSL_PARAM_BLD *bld = NULL;
     OSSL_PARAM *params = NULL;
+    EVP_PKEY *just_params = NULL;
+    EVP_PKEY *params_and_priv = NULL;
+    EVP_PKEY *params_and_pub = NULL;
+    EVP_PKEY *params_and_keypair = NULL;
     BIGNUM *priv = NULL;
     int ret = 0;
 
@@ -867,14 +900,18 @@ static int test_EC_priv_pub(void)
                                                       OSSL_PKEY_PARAM_GROUP_NAME,
                                                       "P-256", 0)))
         goto err;
-    if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld)))
+    if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))
+        || !TEST_ptr(just_params = make_key_fromdata("EC", params)))
         goto err;
 
-    if (!test_fromdata("EC", OSSL_KEYMGMT_SELECT_ALL_PARAMETERS, params))
-        goto err;
     OSSL_PARAM_free(params);
-    params = NULL;
     OSSL_PARAM_BLD_free(bld);
+    params = NULL;
+    bld = NULL;
+
+    if (!test_selection(just_params, OSSL_KEYMGMT_SELECT_ALL_PARAMETERS)
+        || test_selection(just_params, OSSL_KEYMGMT_SELECT_KEYPAIR))
+        goto err;
 
     /* Test priv and !pub */
     if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
@@ -884,20 +921,24 @@ static int test_EC_priv_pub(void)
         || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY,
                                              priv)))
         goto err;
-    if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld)))
+    if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))
+        || !TEST_ptr(params_and_priv = make_key_fromdata("EC", params)))
         goto err;
 
+    OSSL_PARAM_free(params);
+    OSSL_PARAM_BLD_free(bld);
+    params = NULL;
+    bld = NULL;
+
     /*
-     * We indicate only parameters here. The "EVP_PKEY_fromdata" call will do
-     * the private key anyway, but the subsequent PEM_write_bio_PrivateKey_ex
-     * call is expected to fail because PEM_write_bio_PrivateKey_ex does not
-     * support exporting a private EC key without a corresponding public key
+     * We indicate only parameters here, in spite of having built a key that
+     * has a private part, because the PEM_write_bio_PrivateKey_ex call is
+     * expected to fail because it does not support exporting a private EC
+     * key without a corresponding public key
      */
-    if (!test_fromdata("EC", OSSL_KEYMGMT_SELECT_ALL_PARAMETERS, params))
+    if (!test_selection(params_and_priv, OSSL_KEYMGMT_SELECT_ALL_PARAMETERS)
+        || test_selection(params_and_priv, OSSL_KEYMGMT_SELECT_PUBLIC_KEY))
         goto err;
-    OSSL_PARAM_free(params);
-    params = NULL;
-    OSSL_PARAM_BLD_free(bld);
 
     /* Test !priv and pub */
     if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
@@ -908,14 +949,18 @@ static int test_EC_priv_pub(void)
                                                        OSSL_PKEY_PARAM_PUB_KEY,
                                                        ec_pub, sizeof(ec_pub))))
         goto err;
-    if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld)))
+    if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))
+        || !TEST_ptr(params_and_pub = make_key_fromdata("EC", params)))
         goto err;
 
-    if (!test_fromdata("EC", OSSL_KEYMGMT_SELECT_PUBLIC_KEY, params))
-        goto err;
     OSSL_PARAM_free(params);
-    params = NULL;
     OSSL_PARAM_BLD_free(bld);
+    params = NULL;
+    bld = NULL;
+
+    if (!test_selection(params_and_pub, OSSL_KEYMGMT_SELECT_PUBLIC_KEY)
+        || test_selection(params_and_pub, OSSL_KEYMGMT_SELECT_PRIVATE_KEY))
+        goto err;
 
     /* Test priv and pub */
     if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
@@ -928,16 +973,35 @@ static int test_EC_priv_pub(void)
         || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY,
                                              priv)))
         goto err;
-    if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld)))
+    if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))
+        || !TEST_ptr(params_and_keypair = make_key_fromdata("EC", params)))
+        goto err;
+
+    if (!test_selection(params_and_keypair, EVP_PKEY_KEYPAIR))
         goto err;
 
-    if (!test_fromdata("EC", EVP_PKEY_KEYPAIR, params))
+    /* Try key equality */
+    if (!TEST_int_gt(EVP_PKEY_parameters_eq(just_params, just_params), 0)
+        || !TEST_int_gt(EVP_PKEY_parameters_eq(just_params, params_and_pub),
+                        0)
+        || !TEST_int_gt(EVP_PKEY_parameters_eq(just_params, params_and_priv),
+                        0)
+        || !TEST_int_gt(EVP_PKEY_parameters_eq(just_params, params_and_keypair),
+                        0)
+        || !TEST_int_gt(EVP_PKEY_eq(params_and_pub, params_and_pub), 0)
+        || !TEST_int_gt(EVP_PKEY_eq(params_and_priv, params_and_priv), 0)
+        || !TEST_int_gt(EVP_PKEY_eq(params_and_keypair, params_and_pub), 0)
+        || !TEST_int_gt(EVP_PKEY_eq(params_and_keypair, params_and_priv), 0))
         goto err;
 
     ret = 1;
  err:
     OSSL_PARAM_free(params);
     OSSL_PARAM_BLD_free(bld);
+    EVP_PKEY_free(just_params);
+    EVP_PKEY_free(params_and_priv);
+    EVP_PKEY_free(params_and_pub);
+    EVP_PKEY_free(params_and_keypair);
     BN_free(priv);
 
     return ret;


More information about the openssl-commits mailing list