d8c783
From 98642df4ba886818900ab7e6b23703544e6addd4 Mon Sep 17 00:00:00 2001
d8c783
From: Simo Sorce <simo@redhat.com>
d8c783
Date: Thu, 10 Nov 2022 10:46:32 -0500
d8c783
Subject: [PATCH 1/3] Propagate selection all the way on key export
d8c783
d8c783
EVP_PKEY_eq() is used to check, among other things, if a certificate
d8c783
public key corresponds to a private key. When the private key belongs to
d8c783
a provider that does not allow to export private keys this currently
d8c783
fails as the internal functions used to import/export keys ignored the
d8c783
selection given (which specifies that only the public key needs to be
d8c783
considered) and instead tries to export everything.
d8c783
d8c783
This patch allows to propagate the selection all the way down including
d8c783
adding it in the cache so that a following operation actually looking
d8c783
for other selection parameters does not mistakenly pick up an export
d8c783
containing only partial information.
d8c783
d8c783
Signed-off-by: Simo Sorce <simo@redhat.com>
d8c783
d8c783
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
d8c783
Reviewed-by: Tomas Mraz <tomas@openssl.org>
d8c783
(Merged from https://github.com/openssl/openssl/pull/19648)
d8c783
d8c783
diff --git a/crypto/evp/keymgmt_lib.c b/crypto/evp/keymgmt_lib.c
d8c783
index b06730dc7a..2d0238ee27 100644
d8c783
--- a/crypto/evp/keymgmt_lib.c
d8c783
+++ b/crypto/evp/keymgmt_lib.c
d8c783
@@ -93,7 +93,8 @@ int evp_keymgmt_util_export(const EVP_PKEY *pk, int selection,
d8c783
                               export_cb, export_cbarg);
d8c783
 }
d8c783
 
d8c783
-void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
d8c783
+void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
d8c783
+                                          int selection)
d8c783
 {
d8c783
     struct evp_keymgmt_util_try_import_data_st import_data;
d8c783
     OP_CACHE_ELEM *op;
d8c783
@@ -127,7 +128,7 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
d8c783
      */
d8c783
     if (pk->dirty_cnt == pk->dirty_cnt_copy) {
d8c783
         /* If this key is already exported to |keymgmt|, no more to do */
d8c783
-        op = evp_keymgmt_util_find_operation_cache(pk, keymgmt);
d8c783
+        op = evp_keymgmt_util_find_operation_cache(pk, keymgmt, selection);
d8c783
         if (op != NULL && op->keymgmt != NULL) {
d8c783
             void *ret = op->keydata;
d8c783
 
d8c783
@@ -157,13 +158,13 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
d8c783
     /* Setup for the export callback */
d8c783
     import_data.keydata = NULL;  /* evp_keymgmt_util_try_import will create it */
d8c783
     import_data.keymgmt = keymgmt;
d8c783
-    import_data.selection = OSSL_KEYMGMT_SELECT_ALL;
d8c783
+    import_data.selection = selection;
d8c783
 
d8c783
     /*
d8c783
      * The export function calls the callback (evp_keymgmt_util_try_import),
d8c783
      * which does the import for us.  If successful, we're done.
d8c783
      */
d8c783
-    if (!evp_keymgmt_util_export(pk, OSSL_KEYMGMT_SELECT_ALL,
d8c783
+    if (!evp_keymgmt_util_export(pk, selection,
d8c783
                                  &evp_keymgmt_util_try_import, &import_data))
d8c783
         /* If there was an error, bail out */
d8c783
         return NULL;
d8c783
@@ -173,7 +174,7 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
d8c783
         return NULL;
d8c783
     }
d8c783
     /* Check to make sure some other thread didn't get there first */
d8c783
-    op = evp_keymgmt_util_find_operation_cache(pk, keymgmt);
d8c783
+    op = evp_keymgmt_util_find_operation_cache(pk, keymgmt, selection);
d8c783
     if (op != NULL && op->keydata != NULL) {
d8c783
         void *ret = op->keydata;
d8c783
 
d8c783
@@ -196,7 +197,8 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
d8c783
         evp_keymgmt_util_clear_operation_cache(pk, 0);
d8c783
 
d8c783
     /* Add the new export to the operation cache */
d8c783
-    if (!evp_keymgmt_util_cache_keydata(pk, keymgmt, import_data.keydata)) {
d8c783
+    if (!evp_keymgmt_util_cache_keydata(pk, keymgmt, import_data.keydata,
d8c783
+                                        selection)) {
d8c783
         CRYPTO_THREAD_unlock(pk->lock);
d8c783
         evp_keymgmt_freedata(keymgmt, import_data.keydata);
d8c783
         return NULL;
d8c783
@@ -232,7 +234,8 @@ int evp_keymgmt_util_clear_operation_cache(EVP_PKEY *pk, int locking)
d8c783
 }
d8c783
 
d8c783
 OP_CACHE_ELEM *evp_keymgmt_util_find_operation_cache(EVP_PKEY *pk,
d8c783
-                                                     EVP_KEYMGMT *keymgmt)
d8c783
+                                                     EVP_KEYMGMT *keymgmt,
d8c783
+                                                     int selection)
d8c783
 {
d8c783
     int i, end = sk_OP_CACHE_ELEM_num(pk->operation_cache);
d8c783
     OP_CACHE_ELEM *p;
d8c783
@@ -243,14 +246,14 @@ OP_CACHE_ELEM *evp_keymgmt_util_find_operation_cache(EVP_PKEY *pk,
d8c783
      */
d8c783
     for (i = 0; i < end; i++) {
d8c783
         p = sk_OP_CACHE_ELEM_value(pk->operation_cache, i);
d8c783
-        if (keymgmt == p->keymgmt)
d8c783
+        if (keymgmt == p->keymgmt && (p->selection & selection) == selection)
d8c783
             return p;
d8c783
     }
d8c783
     return NULL;
d8c783
 }
d8c783
 
d8c783
-int evp_keymgmt_util_cache_keydata(EVP_PKEY *pk,
d8c783
-                                   EVP_KEYMGMT *keymgmt, void *keydata)
d8c783
+int evp_keymgmt_util_cache_keydata(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
d8c783
+                                   void *keydata, int selection)
d8c783
 {
d8c783
     OP_CACHE_ELEM *p = NULL;
d8c783
 
d8c783
@@ -266,6 +269,7 @@ int evp_keymgmt_util_cache_keydata(EVP_PKEY *pk,
d8c783
             return 0;
d8c783
         p->keydata = keydata;
d8c783
         p->keymgmt = keymgmt;
d8c783
+        p->selection = selection;
d8c783
 
d8c783
         if (!EVP_KEYMGMT_up_ref(keymgmt)) {
d8c783
             OPENSSL_free(p);
d8c783
@@ -391,7 +395,8 @@ int evp_keymgmt_util_match(EVP_PKEY *pk1, EVP_PKEY *pk2, int selection)
d8c783
             ok = 1;
d8c783
             if (keydata1 != NULL) {
d8c783
                 tmp_keydata =
d8c783
-                    evp_keymgmt_util_export_to_provider(pk1, keymgmt2);
d8c783
+                    evp_keymgmt_util_export_to_provider(pk1, keymgmt2,
d8c783
+                                                        selection);
d8c783
                 ok = (tmp_keydata != NULL);
d8c783
             }
d8c783
             if (ok) {
d8c783
@@ -411,7 +416,8 @@ int evp_keymgmt_util_match(EVP_PKEY *pk1, EVP_PKEY *pk2, int selection)
d8c783
             ok = 1;
d8c783
             if (keydata2 != NULL) {
d8c783
                 tmp_keydata =
d8c783
-                    evp_keymgmt_util_export_to_provider(pk2, keymgmt1);
d8c783
+                    evp_keymgmt_util_export_to_provider(pk2, keymgmt1,
d8c783
+                                                        selection);
d8c783
                 ok = (tmp_keydata != NULL);
d8c783
             }
d8c783
             if (ok) {
d8c783
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
d8c783
index 70d17ec37e..905e9c9ce4 100644
d8c783
--- a/crypto/evp/p_lib.c
d8c783
+++ b/crypto/evp/p_lib.c
d8c783
@@ -1822,6 +1822,7 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OSSL_LIB_CTX *libctx,
d8c783
 {
d8c783
     EVP_KEYMGMT *allocated_keymgmt = NULL;
d8c783
     EVP_KEYMGMT *tmp_keymgmt = NULL;
d8c783
+    int selection = OSSL_KEYMGMT_SELECT_ALL;
d8c783
     void *keydata = NULL;
d8c783
     int check;
d8c783
 
d8c783
@@ -1883,7 +1884,8 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OSSL_LIB_CTX *libctx,
d8c783
         if (pk->ameth->dirty_cnt(pk) == pk->dirty_cnt_copy) {
d8c783
             if (!CRYPTO_THREAD_read_lock(pk->lock))
d8c783
                 goto end;
d8c783
-            op = evp_keymgmt_util_find_operation_cache(pk, tmp_keymgmt);
d8c783
+            op = evp_keymgmt_util_find_operation_cache(pk, tmp_keymgmt,
d8c783
+                                                       selection);
d8c783
 
d8c783
             /*
d8c783
              * If |tmp_keymgmt| is present in the operation cache, it means
d8c783
@@ -1938,7 +1940,7 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OSSL_LIB_CTX *libctx,
d8c783
         EVP_KEYMGMT_free(tmp_keymgmt); /* refcnt-- */
d8c783
 
d8c783
         /* Check to make sure some other thread didn't get there first */
d8c783
-        op = evp_keymgmt_util_find_operation_cache(pk, tmp_keymgmt);
d8c783
+        op = evp_keymgmt_util_find_operation_cache(pk, tmp_keymgmt, selection);
d8c783
         if (op != NULL && op->keymgmt != NULL) {
d8c783
             void *tmp_keydata = op->keydata;
d8c783
 
d8c783
@@ -1949,7 +1951,8 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OSSL_LIB_CTX *libctx,
d8c783
         }
d8c783
 
d8c783
         /* Add the new export to the operation cache */
d8c783
-        if (!evp_keymgmt_util_cache_keydata(pk, tmp_keymgmt, keydata)) {
d8c783
+        if (!evp_keymgmt_util_cache_keydata(pk, tmp_keymgmt, keydata,
d8c783
+                                            selection)) {
d8c783
             CRYPTO_THREAD_unlock(pk->lock);
d8c783
             evp_keymgmt_freedata(tmp_keymgmt, keydata);
d8c783
             keydata = NULL;
d8c783
@@ -1964,7 +1967,7 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OSSL_LIB_CTX *libctx,
d8c783
     }
d8c783
 #endif  /* FIPS_MODULE */
d8c783
 
d8c783
-    keydata = evp_keymgmt_util_export_to_provider(pk, tmp_keymgmt);
d8c783
+    keydata = evp_keymgmt_util_export_to_provider(pk, tmp_keymgmt, selection);
d8c783
 
d8c783
  end:
d8c783
     /*
d8c783
diff --git a/include/crypto/evp.h b/include/crypto/evp.h
d8c783
index f601b72807..dbbdcccbda 100644
d8c783
--- a/include/crypto/evp.h
d8c783
+++ b/include/crypto/evp.h
d8c783
@@ -589,6 +589,7 @@ int evp_cipher_asn1_to_param_ex(EVP_CIPHER_CTX *c, ASN1_TYPE *type,
d8c783
 typedef struct {
d8c783
     EVP_KEYMGMT *keymgmt;
d8c783
     void *keydata;
d8c783
+    int selection;
d8c783
 } OP_CACHE_ELEM;
d8c783
 
d8c783
 DEFINE_STACK_OF(OP_CACHE_ELEM)
d8c783
@@ -778,12 +779,14 @@ EVP_PKEY *evp_keymgmt_util_make_pkey(EVP_KEYMGMT *keymgmt, void *keydata);
d8c783
 
d8c783
 int evp_keymgmt_util_export(const EVP_PKEY *pk, int selection,
d8c783
                             OSSL_CALLBACK *export_cb, void *export_cbarg);
d8c783
-void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt);
d8c783
+void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
d8c783
+                                          int selection);
d8c783
 OP_CACHE_ELEM *evp_keymgmt_util_find_operation_cache(EVP_PKEY *pk,
d8c783
-                                                     EVP_KEYMGMT *keymgmt);
d8c783
+                                                     EVP_KEYMGMT *keymgmt,
d8c783
+                                                     int selection);
d8c783
 int evp_keymgmt_util_clear_operation_cache(EVP_PKEY *pk, int locking);
d8c783
-int evp_keymgmt_util_cache_keydata(EVP_PKEY *pk,
d8c783
-                                   EVP_KEYMGMT *keymgmt, void *keydata);
d8c783
+int evp_keymgmt_util_cache_keydata(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
d8c783
+                                   void *keydata, int selection);
d8c783
 void evp_keymgmt_util_cache_keyinfo(EVP_PKEY *pk);
d8c783
 void *evp_keymgmt_util_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
d8c783
                                 int selection, const OSSL_PARAM params[]);
d8c783
-- 
d8c783
2.38.1
d8c783
d8c783
From 504427eb5f32108dd64ff7858012863fe47b369b Mon Sep 17 00:00:00 2001
d8c783
From: Simo Sorce <simo@redhat.com>
d8c783
Date: Thu, 10 Nov 2022 16:58:28 -0500
d8c783
Subject: [PATCH 2/3] Update documentation for keymgmt export utils
d8c783
d8c783
Change function prototypes and explain how to use the selection
d8c783
argument.
d8c783
d8c783
Signed-off-by: Simo Sorce <simo@redhat.com>
d8c783
d8c783
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
d8c783
Reviewed-by: Tomas Mraz <tomas@openssl.org>
d8c783
(Merged from https://github.com/openssl/openssl/pull/19648)
d8c783
d8c783
diff --git a/doc/internal/man3/evp_keymgmt_util_export_to_provider.pod b/doc/internal/man3/evp_keymgmt_util_export_to_provider.pod
d8c783
index 1fee9f6ff9..7099e44964 100644
d8c783
--- a/doc/internal/man3/evp_keymgmt_util_export_to_provider.pod
d8c783
+++ b/doc/internal/man3/evp_keymgmt_util_export_to_provider.pod
d8c783
@@ -20,12 +20,14 @@ OP_CACHE_ELEM
d8c783
 
d8c783
  int evp_keymgmt_util_export(const EVP_PKEY *pk, int selection,
d8c783
                              OSSL_CALLBACK *export_cb, void *export_cbarg);
d8c783
- void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt);
d8c783
+ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
d8c783
+                                           int selection);
d8c783
  OP_CACHE_ELEM *evp_keymgmt_util_find_operation_cache(EVP_PKEY *pk,
d8c783
-                                                      EVP_KEYMGMT *keymgmt);
d8c783
+                                                      EVP_KEYMGMT *keymgmt,
d8c783
+                                                      int selection);
d8c783
  int evp_keymgmt_util_clear_operation_cache(EVP_PKEY *pk, int locking);
d8c783
- int evp_keymgmt_util_cache_keydata(EVP_PKEY *pk,
d8c783
-                                    EVP_KEYMGMT *keymgmt, void *keydata);
d8c783
+ int evp_keymgmt_util_cache_keydata(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
d8c783
+                                    void *keydata, int selection);
d8c783
  void evp_keymgmt_util_cache_keyinfo(EVP_PKEY *pk);
d8c783
  void *evp_keymgmt_util_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
d8c783
                                  int selection, const OSSL_PARAM params[]);
d8c783
@@ -65,6 +67,11 @@ evp_keymgmt_util_fromdata() can be used to add key object data to a
d8c783
 given key I<target> via a B<EVP_KEYMGMT> interface.  This is used as a
d8c783
 helper for L<EVP_PKEY_fromdata(3)>.
d8c783
 
d8c783
+In all functions that take a I<selection> argument, the selection is used to
d8c783
+constraint the information requested on export. It is also used in the cache
d8c783
+so that key data is guaranteed to contain all the information requested in
d8c783
+the selection.
d8c783
+
d8c783
 =head1 RETURN VALUES
d8c783
 
d8c783
 evp_keymgmt_export_to_provider() and evp_keymgmt_util_fromdata()
d8c783
-- 
d8c783
2.38.1
d8c783
d8c783
From e5202fbd461cb6c067874987998e91c6093e5267 Mon Sep 17 00:00:00 2001
d8c783
From: Simo Sorce <simo@redhat.com>
d8c783
Date: Fri, 11 Nov 2022 12:18:26 -0500
d8c783
Subject: [PATCH 3/3] Add test for EVP_PKEY_eq
d8c783
d8c783
This tests that the comparison work even if a provider can only return
d8c783
a public key.
d8c783
d8c783
Signed-off-by: Simo Sorce <simo@redhat.com>
d8c783
d8c783
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
d8c783
Reviewed-by: Tomas Mraz <tomas@openssl.org>
d8c783
(Merged from https://github.com/openssl/openssl/pull/19648)
d8c783
d8c783
diff --git a/test/fake_rsaprov.c b/test/fake_rsaprov.c
d8c783
index d556551bb6..5e92e72d4b 100644
d8c783
--- a/test/fake_rsaprov.c
d8c783
+++ b/test/fake_rsaprov.c
d8c783
@@ -22,24 +22,34 @@ static OSSL_FUNC_keymgmt_has_fn fake_rsa_keymgmt_has;
d8c783
 static OSSL_FUNC_keymgmt_query_operation_name_fn fake_rsa_keymgmt_query;
d8c783
 static OSSL_FUNC_keymgmt_import_fn fake_rsa_keymgmt_import;
d8c783
 static OSSL_FUNC_keymgmt_import_types_fn fake_rsa_keymgmt_imptypes;
d8c783
+static OSSL_FUNC_keymgmt_export_fn fake_rsa_keymgmt_export;
d8c783
+static OSSL_FUNC_keymgmt_export_types_fn fake_rsa_keymgmt_exptypes;
d8c783
 static OSSL_FUNC_keymgmt_load_fn fake_rsa_keymgmt_load;
d8c783
 
d8c783
 static int has_selection;
d8c783
 static int imptypes_selection;
d8c783
+static int exptypes_selection;
d8c783
 static int query_id;
d8c783
 
d8c783
+struct fake_rsa_keydata {
d8c783
+    int selection;
d8c783
+    int status;
d8c783
+};
d8c783
+
d8c783
 static void *fake_rsa_keymgmt_new(void *provctx)
d8c783
 {
d8c783
-    unsigned char *keydata = OPENSSL_zalloc(1);
d8c783
+    struct fake_rsa_keydata *key;
d8c783
 
d8c783
-    TEST_ptr(keydata);
d8c783
+    if (!TEST_ptr(key = OPENSSL_zalloc(sizeof(struct fake_rsa_keydata))))
d8c783
+        return NULL;
d8c783
 
d8c783
     /* clear test globals */
d8c783
     has_selection = 0;
d8c783
     imptypes_selection = 0;
d8c783
+    exptypes_selection = 0;
d8c783
     query_id = 0;
d8c783
 
d8c783
-    return keydata;
d8c783
+    return key;
d8c783
 }
d8c783
 
d8c783
 static void fake_rsa_keymgmt_free(void *keydata)
d8c783
@@ -67,14 +77,104 @@ static const char *fake_rsa_keymgmt_query(int id)
d8c783
 static int fake_rsa_keymgmt_import(void *keydata, int selection,
d8c783
                                    const OSSL_PARAM *p)
d8c783
 {
d8c783
-    unsigned char *fake_rsa_key = keydata;
d8c783
+    struct fake_rsa_keydata *fake_rsa_key = keydata;
d8c783
 
d8c783
     /* key was imported */
d8c783
-    *fake_rsa_key = 1;
d8c783
+    fake_rsa_key->status = 1;
d8c783
 
d8c783
     return 1;
d8c783
 }
d8c783
 
d8c783
+static unsigned char fake_rsa_n[] =
d8c783
+   "\x00\xAA\x36\xAB\xCE\x88\xAC\xFD\xFF\x55\x52\x3C\x7F\xC4\x52\x3F"
d8c783
+   "\x90\xEF\xA0\x0D\xF3\x77\x4A\x25\x9F\x2E\x62\xB4\xC5\xD9\x9C\xB5"
d8c783
+   "\xAD\xB3\x00\xA0\x28\x5E\x53\x01\x93\x0E\x0C\x70\xFB\x68\x76\x93"
d8c783
+   "\x9C\xE6\x16\xCE\x62\x4A\x11\xE0\x08\x6D\x34\x1E\xBC\xAC\xA0\xA1"
d8c783
+   "\xF5";
d8c783
+
d8c783
+static unsigned char fake_rsa_e[] = "\x11";
d8c783
+
d8c783
+static unsigned char fake_rsa_d[] =
d8c783
+    "\x0A\x03\x37\x48\x62\x64\x87\x69\x5F\x5F\x30\xBC\x38\xB9\x8B\x44"
d8c783
+    "\xC2\xCD\x2D\xFF\x43\x40\x98\xCD\x20\xD8\xA1\x38\xD0\x90\xBF\x64"
d8c783
+    "\x79\x7C\x3F\xA7\xA2\xCD\xCB\x3C\xD1\xE0\xBD\xBA\x26\x54\xB4\xF9"
d8c783
+    "\xDF\x8E\x8A\xE5\x9D\x73\x3D\x9F\x33\xB3\x01\x62\x4A\xFD\x1D\x51";
d8c783
+
d8c783
+static unsigned char fake_rsa_p[] =
d8c783
+    "\x00\xD8\x40\xB4\x16\x66\xB4\x2E\x92\xEA\x0D\xA3\xB4\x32\x04\xB5"
d8c783
+    "\xCF\xCE\x33\x52\x52\x4D\x04\x16\xA5\xA4\x41\xE7\x00\xAF\x46\x12"
d8c783
+    "\x0D";
d8c783
+
d8c783
+static unsigned char fake_rsa_q[] =
d8c783
+    "\x00\xC9\x7F\xB1\xF0\x27\xF4\x53\xF6\x34\x12\x33\xEA\xAA\xD1\xD9"
d8c783
+    "\x35\x3F\x6C\x42\xD0\x88\x66\xB1\xD0\x5A\x0F\x20\x35\x02\x8B\x9D"
d8c783
+    "\x89";
d8c783
+
d8c783
+static unsigned char fake_rsa_dmp1[] =
d8c783
+    "\x59\x0B\x95\x72\xA2\xC2\xA9\xC4\x06\x05\x9D\xC2\xAB\x2F\x1D\xAF"
d8c783
+    "\xEB\x7E\x8B\x4F\x10\xA7\x54\x9E\x8E\xED\xF5\xB4\xFC\xE0\x9E\x05";
d8c783
+
d8c783
+static unsigned char fake_rsa_dmq1[] =
d8c783
+    "\x00\x8E\x3C\x05\x21\xFE\x15\xE0\xEA\x06\xA3\x6F\xF0\xF1\x0C\x99"
d8c783
+    "\x52\xC3\x5B\x7A\x75\x14\xFD\x32\x38\xB8\x0A\xAD\x52\x98\x62\x8D"
d8c783
+    "\x51";
d8c783
+
d8c783
+static unsigned char fake_rsa_iqmp[] =
d8c783
+    "\x36\x3F\xF7\x18\x9D\xA8\xE9\x0B\x1D\x34\x1F\x71\xD0\x9B\x76\xA8"
d8c783
+    "\xA9\x43\xE1\x1D\x10\xB2\x4D\x24\x9F\x2D\xEA\xFE\xF8\x0C\x18\x26";
d8c783
+
d8c783
+OSSL_PARAM *fake_rsa_key_params(int priv)
d8c783
+{
d8c783
+    if (priv) {
d8c783
+        OSSL_PARAM params[] = {
d8c783
+            OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_N, fake_rsa_n,
d8c783
+                          sizeof(fake_rsa_n) -1),
d8c783
+            OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_E, fake_rsa_e,
d8c783
+                          sizeof(fake_rsa_e) -1),
d8c783
+            OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_D, fake_rsa_d,
d8c783
+                          sizeof(fake_rsa_d) -1),
d8c783
+            OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR1, fake_rsa_p,
d8c783
+                          sizeof(fake_rsa_p) -1),
d8c783
+            OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR2, fake_rsa_q,
d8c783
+                          sizeof(fake_rsa_q) -1),
d8c783
+            OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT1, fake_rsa_dmp1,
d8c783
+                          sizeof(fake_rsa_dmp1) -1),
d8c783
+            OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT2, fake_rsa_dmq1,
d8c783
+                          sizeof(fake_rsa_dmq1) -1),
d8c783
+            OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT1, fake_rsa_iqmp,
d8c783
+                          sizeof(fake_rsa_iqmp) -1),
d8c783
+            OSSL_PARAM_END
d8c783
+        };
d8c783
+        return OSSL_PARAM_dup(params);
d8c783
+    } else {
d8c783
+        OSSL_PARAM params[] = {
d8c783
+            OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_N, fake_rsa_n,
d8c783
+                          sizeof(fake_rsa_n) -1),
d8c783
+            OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_E, fake_rsa_e,
d8c783
+                          sizeof(fake_rsa_e) -1),
d8c783
+            OSSL_PARAM_END
d8c783
+        };
d8c783
+        return OSSL_PARAM_dup(params);
d8c783
+    }
d8c783
+}
d8c783
+
d8c783
+static int fake_rsa_keymgmt_export(void *keydata, int selection,
d8c783
+                                   OSSL_CALLBACK *param_callback, void *cbarg)
d8c783
+{
d8c783
+    OSSL_PARAM *params = NULL;
d8c783
+    int ret;
d8c783
+
d8c783
+    if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY)
d8c783
+        return 0;
d8c783
+
d8c783
+    if (!TEST_ptr(params = fake_rsa_key_params(0)))
d8c783
+        return 0;
d8c783
+
d8c783
+    ret = param_callback(params, cbarg);
d8c783
+    OSSL_PARAM_free(params);
d8c783
+    return ret;
d8c783
+}
d8c783
+
d8c783
 static const OSSL_PARAM fake_rsa_import_key_types[] = {
d8c783
     OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_N, NULL, 0),
d8c783
     OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_E, NULL, 0),
d8c783
@@ -95,19 +195,33 @@ static const OSSL_PARAM *fake_rsa_keymgmt_imptypes(int selection)
d8c783
     return fake_rsa_import_key_types;
d8c783
 }
d8c783
 
d8c783
+static const OSSL_PARAM fake_rsa_export_key_types[] = {
d8c783
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_N, NULL, 0),
d8c783
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_E, NULL, 0),
d8c783
+    OSSL_PARAM_END
d8c783
+};
d8c783
+
d8c783
+static const OSSL_PARAM *fake_rsa_keymgmt_exptypes(int selection)
d8c783
+{
d8c783
+    /* record global for checking */
d8c783
+    exptypes_selection = selection;
d8c783
+
d8c783
+    return fake_rsa_export_key_types;
d8c783
+}
d8c783
+
d8c783
 static void *fake_rsa_keymgmt_load(const void *reference, size_t reference_sz)
d8c783
 {
d8c783
-    unsigned char *key = NULL;
d8c783
+    struct fake_rsa_keydata *key = NULL;
d8c783
 
d8c783
-    if (reference_sz != sizeof(key))
d8c783
+    if (reference_sz != sizeof(*key))
d8c783
         return NULL;
d8c783
 
d8c783
-    key = *(unsigned char **)reference;
d8c783
-    if (*key != 1)
d8c783
+    key = *(struct fake_rsa_keydata **)reference;
d8c783
+    if (key->status != 1)
d8c783
         return NULL;
d8c783
 
d8c783
     /* detach the reference */
d8c783
-    *(unsigned char **)reference = NULL;
d8c783
+    *(struct fake_rsa_keydata  **)reference = NULL;
d8c783
 
d8c783
     return key;
d8c783
 }
d8c783
@@ -129,7 +243,7 @@ static void *fake_rsa_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
d8c783
 {
d8c783
     unsigned char *gctx = genctx;
d8c783
     static const unsigned char inited[] = { 1 };
d8c783
-    unsigned char *keydata;
d8c783
+    struct fake_rsa_keydata *keydata;
d8c783
 
d8c783
     if (!TEST_ptr(gctx)
d8c783
         || !TEST_mem_eq(gctx, sizeof(*gctx), inited, sizeof(inited)))
d8c783
@@ -138,7 +252,7 @@ static void *fake_rsa_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
d8c783
     if (!TEST_ptr(keydata = fake_rsa_keymgmt_new(NULL)))
d8c783
         return NULL;
d8c783
 
d8c783
-    *keydata = 2;
d8c783
+    keydata->status = 2;
d8c783
     return keydata;
d8c783
 }
d8c783
 
d8c783
@@ -156,6 +270,9 @@ static const OSSL_DISPATCH fake_rsa_keymgmt_funcs[] = {
d8c783
     { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))fake_rsa_keymgmt_import },
d8c783
     { OSSL_FUNC_KEYMGMT_IMPORT_TYPES,
d8c783
         (void (*)(void))fake_rsa_keymgmt_imptypes },
d8c783
+    { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))fake_rsa_keymgmt_export },
d8c783
+    { OSSL_FUNC_KEYMGMT_EXPORT_TYPES,
d8c783
+        (void (*)(void))fake_rsa_keymgmt_exptypes },
d8c783
     { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))fake_rsa_keymgmt_load },
d8c783
     { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))fake_rsa_gen_init },
d8c783
     { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))fake_rsa_gen },
d8c783
@@ -191,14 +308,14 @@ static int fake_rsa_sig_sign_init(void *ctx, void *provkey,
d8c783
                                   const OSSL_PARAM params[])
d8c783
 {
d8c783
     unsigned char *sigctx = ctx;
d8c783
-    unsigned char *keydata = provkey;
d8c783
+    struct fake_rsa_keydata *keydata = provkey;
d8c783
 
d8c783
     /* we must have a ctx */
d8c783
     if (!TEST_ptr(sigctx))
d8c783
         return 0;
d8c783
 
d8c783
     /* we must have some initialized key */
d8c783
-    if (!TEST_ptr(keydata) || !TEST_int_gt(keydata[0], 0))
d8c783
+    if (!TEST_ptr(keydata) || !TEST_int_gt(keydata->status, 0))
d8c783
         return 0;
d8c783
 
d8c783
     /* record that sign init was called */
d8c783
@@ -289,7 +406,7 @@ static int fake_rsa_st_load(void *loaderctx,
d8c783
     unsigned char *storectx = loaderctx;
d8c783
     OSSL_PARAM params[4];
d8c783
     int object_type = OSSL_OBJECT_PKEY;
d8c783
-    void *key = NULL;
d8c783
+    struct fake_rsa_keydata *key = NULL;
d8c783
     int rv = 0;
d8c783
 
d8c783
     switch (*storectx) {
d8c783
@@ -307,7 +424,7 @@ static int fake_rsa_st_load(void *loaderctx,
d8c783
         /* The address of the key becomes the octet string */
d8c783
         params[2] =
d8c783
             OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_REFERENCE,
d8c783
-                                              &key, sizeof(key));
d8c783
+                                              &key, sizeof(*key));
d8c783
         params[3] = OSSL_PARAM_construct_end();
d8c783
         rv = object_cb(params, object_cbarg);
d8c783
         *storectx = 1;
d8c783
diff --git a/test/fake_rsaprov.h b/test/fake_rsaprov.h
d8c783
index 57de1ecf8d..190c46a285 100644
d8c783
--- a/test/fake_rsaprov.h
d8c783
+++ b/test/fake_rsaprov.h
d8c783
@@ -12,3 +12,4 @@
d8c783
 /* Fake RSA provider implementation */
d8c783
 OSSL_PROVIDER *fake_rsa_start(OSSL_LIB_CTX *libctx);
d8c783
 void fake_rsa_finish(OSSL_PROVIDER *p);
d8c783
+OSSL_PARAM *fake_rsa_key_params(int priv);
d8c783
diff --git a/test/provider_pkey_test.c b/test/provider_pkey_test.c
d8c783
index 5c398398f4..3b190baa5e 100644
d8c783
--- a/test/provider_pkey_test.c
d8c783
+++ b/test/provider_pkey_test.c
d8c783
@@ -176,6 +176,67 @@ end:
d8c783
     return ret;
d8c783
 }
d8c783
 
d8c783
+static int test_pkey_eq(void)
d8c783
+{
d8c783
+    OSSL_PROVIDER *deflt = NULL;
d8c783
+    OSSL_PROVIDER *fake_rsa = NULL;
d8c783
+    EVP_PKEY *pkey_fake = NULL;
d8c783
+    EVP_PKEY *pkey_dflt = NULL;
d8c783
+    EVP_PKEY_CTX *ctx = NULL;
d8c783
+    OSSL_PARAM *params = NULL;
d8c783
+    int ret = 0;
d8c783
+
d8c783
+    if (!TEST_ptr(fake_rsa = fake_rsa_start(libctx)))
d8c783
+        return 0;
d8c783
+
d8c783
+    if (!TEST_ptr(deflt = OSSL_PROVIDER_load(libctx, "default")))
d8c783
+        goto end;
d8c783
+
d8c783
+    /* Construct a public key for fake-rsa */
d8c783
+    if (!TEST_ptr(params = fake_rsa_key_params(0))
d8c783
+        || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA",
d8c783
+                                                      "provider=fake-rsa"))
d8c783
+        || !TEST_true(EVP_PKEY_fromdata_init(ctx))
d8c783
+        || !TEST_true(EVP_PKEY_fromdata(ctx, &pkey_fake, EVP_PKEY_PUBLIC_KEY,
d8c783
+                                        params))
d8c783
+        || !TEST_ptr(pkey_fake))
d8c783
+        goto end;
d8c783
+
d8c783
+    EVP_PKEY_CTX_free(ctx);
d8c783
+    ctx = NULL;
d8c783
+    OSSL_PARAM_free(params);
d8c783
+    params = NULL;
d8c783
+
d8c783
+    /* Construct a public key for default */
d8c783
+    if (!TEST_ptr(params = fake_rsa_key_params(0))
d8c783
+        || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA",
d8c783
+                                                      "provider=default"))
d8c783
+        || !TEST_true(EVP_PKEY_fromdata_init(ctx))
d8c783
+        || !TEST_true(EVP_PKEY_fromdata(ctx, &pkey_dflt, EVP_PKEY_PUBLIC_KEY,
d8c783
+                                        params))
d8c783
+        || !TEST_ptr(pkey_dflt))
d8c783
+        goto end;
d8c783
+
d8c783
+    EVP_PKEY_CTX_free(ctx);
d8c783
+    ctx = NULL;
d8c783
+    OSSL_PARAM_free(params);
d8c783
+    params = NULL;
d8c783
+
d8c783
+    /* now test for equality */
d8c783
+    if (!TEST_int_eq(EVP_PKEY_eq(pkey_fake, pkey_dflt), 1))
d8c783
+        goto end;
d8c783
+
d8c783
+    ret = 1;
d8c783
+end:
d8c783
+    fake_rsa_finish(fake_rsa);
d8c783
+    OSSL_PROVIDER_unload(deflt);
d8c783
+    EVP_PKEY_CTX_free(ctx);
d8c783
+    EVP_PKEY_free(pkey_fake);
d8c783
+    EVP_PKEY_free(pkey_dflt);
d8c783
+    OSSL_PARAM_free(params);
d8c783
+    return ret;
d8c783
+}
d8c783
+
d8c783
 static int test_pkey_store(int idx)
d8c783
 {
d8c783
     OSSL_PROVIDER *deflt = NULL;
d8c783
@@ -235,6 +296,7 @@ int setup_tests(void)
d8c783
 
d8c783
     ADD_TEST(test_pkey_sig);
d8c783
     ADD_TEST(test_alternative_keygen_init);
d8c783
+    ADD_TEST(test_pkey_eq);
d8c783
     ADD_ALL_TESTS(test_pkey_store, 2);
d8c783
 
d8c783
     return 1;
d8c783
-- 
d8c783
2.38.1
d8c783
d8c783
From 2fea56832780248af2aba2e4433ece2d18428515 Mon Sep 17 00:00:00 2001
d8c783
From: Simo Sorce <simo@redhat.com>
d8c783
Date: Mon, 14 Nov 2022 10:25:15 -0500
d8c783
Subject: [PATCH] Drop explicit check for engines in opt_legacy_okay
d8c783
d8c783
The providers indication should always indicate that this is not a
d8c783
legacy request.
d8c783
This makes a check for engines redundant as the default return is that
d8c783
legacy is ok if there are no explicit providers.
d8c783
d8c783
Fixes #19662
d8c783
d8c783
Signed-off-by: Simo Sorce <simo@redhat.com>
d8c783
d8c783
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
d8c783
Reviewed-by: Paul Dale <pauli@openssl.org>
d8c783
Reviewed-by: Tomas Mraz <tomas@openssl.org>
d8c783
(Merged from https://github.com/openssl/openssl/pull/19671)
d8c783
---
d8c783
 apps/lib/apps.c                    |  8 --------
d8c783
 test/recipes/20-test_legacy_okay.t | 23 +++++++++++++++++++++++
d8c783
 2 files changed, 23 insertions(+), 8 deletions(-)
d8c783
 create mode 100755 test/recipes/20-test_legacy_okay.t
d8c783
d8c783
diff --git a/apps/lib/apps.c b/apps/lib/apps.c
d8c783
index 3d52e030ab7e258f9cd983b2d9755d954cb3aee5..bbe0d009efb35fcf1a902c86cbddc61e657e57f1 100644
d8c783
--- a/apps/lib/apps.c
d8c783
+++ b/apps/lib/apps.c
d8c783
@@ -3405,14 +3405,6 @@ int opt_legacy_okay(void)
d8c783
 {
d8c783
     int provider_options = opt_provider_option_given();
d8c783
     int libctx = app_get0_libctx() != NULL || app_get0_propq() != NULL;
d8c783
-#ifndef OPENSSL_NO_ENGINE
d8c783
-    ENGINE *e = ENGINE_get_first();
d8c783
-
d8c783
-    if (e != NULL) {
d8c783
-        ENGINE_free(e);
d8c783
-        return 1;
d8c783
-    }
d8c783
-#endif
d8c783
     /*
d8c783
      * Having a provider option specified or a custom library context or
d8c783
      * property query, is a sure sign we're not using legacy.
d8c783
diff --git a/test/recipes/20-test_legacy_okay.t b/test/recipes/20-test_legacy_okay.t
d8c783
new file mode 100755
d8c783
index 0000000000000000000000000000000000000000..183499f3fd93f97e8a4a30681a9f383d2f6e0c56
d8c783
--- /dev/null
d8c783
+++ b/test/recipes/20-test_legacy_okay.t
d8c783
@@ -0,0 +1,23 @@
d8c783
+#! /usr/bin/env perl
d8c783
+# Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
d8c783
+#
d8c783
+# Licensed under the Apache License 2.0 (the "License").  You may not use
d8c783
+# this file except in compliance with the License.  You can obtain a copy
d8c783
+# in the file LICENSE in the source distribution or at
d8c783
+# https://www.openssl.org/source/license.html
d8c783
+
d8c783
+use strict;
d8c783
+use warnings;
d8c783
+
d8c783
+use OpenSSL::Test;
d8c783
+
d8c783
+setup("test_legacy");
d8c783
+
d8c783
+plan tests => 3;
d8c783
+
d8c783
+ok(run(app(['openssl', 'rand', '-out', 'rand.txt', '256'])), "Generate random file");
d8c783
+
d8c783
+ok(run(app(['openssl', 'dgst', '-sha256', 'rand.txt'])), "Generate a digest");
d8c783
+
d8c783
+ok(!run(app(['openssl', 'dgst', '-sha256', '-propquery', 'foo=1',
d8c783
+             'rand.txt'])), "Fail to generate a digest");
d8c783
-- 
d8c783
2.38.1
d8c783