EVP: Check that key methods aren't foreign when exporting
authorRichard Levitte <levitte@openssl.org>
Thu, 27 Feb 2020 09:51:45 +0000 (10:51 +0100)
committerRichard Levitte <levitte@openssl.org>
Mon, 9 Mar 2020 09:54:01 +0000 (10:54 +0100)
The EVP_PKEY_ASN1_METHOD function export_to() must check that the key
we're trying to export has a known libcrypto method, i.e. is a built
in RSA_METHOD, DSA_METHOD, etc.  Otherwise, the method may be defined
by the calling application, by an engine, by another library, and we
simply cannot know all the quirks hidden behind that method, if we
have access to the key data, or much anything.

Such keys are simply deemed impossible to export to provider keys,
i.e. have export_to() return 0.  This cascades back to functions like
evp_pkey_export_to_provider() and evp_pkey_upgrade_to_provider() and
their callers.  In most cases, this is fine, but if these get mixed in
with provider side keys in any function, that function will fail.

Fixes #11179
Fixes #9915

Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from https://github.com/openssl/openssl/pull/11193)

crypto/dh/dh_ameth.c
crypto/dsa/dsa_ameth.c
crypto/ec/ec_ameth.c
crypto/evp/m_sigver.c
crypto/evp/pmeth_fn.c
crypto/evp/signature.c
crypto/rsa/rsa_ameth.c

index 14c08424558d66105dae5a90e98e1245889c86a1..ecec5fbcf6d972dae3f2a8c9c883538e9e785f75 100644 (file)
@@ -20,6 +20,7 @@
 #include "dh_local.h"
 #include <openssl/bn.h>
 #include "crypto/asn1.h"
+#include "crypto/dh.h"
 #include "crypto/evp.h"
 #include <openssl/cms.h>
 #include <openssl/core_names.h>
@@ -499,6 +500,13 @@ static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
     OSSL_PARAM *params;
     int rv;
 
+    /*
+     * If the DH method is foreign, then we can't be sure of anything, and
+     * can therefore not export or pretend to export.
+     */
+    if (dh_get_method(dh) != DH_OpenSSL())
+        return 0;
+
     if (p == NULL || g == NULL)
         return 0;
 
index 9715a75d0dcf034f3bc48ecca1b44e7a626d973f..94f3f43b8ea030e362d501dfb61c9cd3596f9e51 100644 (file)
@@ -528,6 +528,13 @@ static int dsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
     OSSL_PARAM *params;
     int rv;
 
+    /*
+     * If the DSA method is foreign, then we can't be sure of anything, and
+     * can therefore not export or pretend to export.
+     */
+    if (DSA_get_method(dsa) != DSA_OpenSSL())
+        return 0;
+
     if (p == NULL || q == NULL || g == NULL)
         return 0;
 
index d6807661ffb5d911ffb29fec12b4239e88ef6416..652086a93ad9b50487fccfc174aa3877216212a3 100644 (file)
@@ -637,6 +637,13 @@ int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
             || (ecg = EC_KEY_get0_group(eckey)) == NULL)
         return 0;
 
+    /*
+     * If the EC_KEY method is foreign, then we can't be sure of anything,
+     * and can therefore not export or pretend to export.
+     */
+    if (EC_KEY_get_method(eckey) != EC_KEY_OpenSSL())
+        return 0;
+
     ossl_param_bld_init(&tmpl);
 
     /* export the domain parameters */
index 225017b5095fd54df14f0cf577c98d372b101733..4b2cb4eb35f14c15aa4b5d294351fc831531686f 100644 (file)
@@ -73,7 +73,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
      */
     ERR_set_mark();
 
-    if (locpctx->keytype == NULL)
+    if (locpctx->engine != NULL || locpctx->keytype == NULL)
         goto legacy;
 
     /*
index ca0790fcd627984eb7d618e17cdf14efa8e8e004..5d0e21ed687709bcaa2f48d3a9931f34f3217ac7 100644 (file)
@@ -38,7 +38,7 @@ static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation)
      */
     ERR_set_mark();
 
-    if (ctx->keytype == NULL || ctx->engine != NULL)
+    if (ctx->engine != NULL || ctx->keytype == NULL)
         goto legacy;
 
     /*
index c01f0766098b835c551be28dbc7eb04b5626f6ab..acbe76592f782121d9ac3545ffa93b2fcae14bbb 100644 (file)
@@ -359,7 +359,7 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation)
      */
     ERR_set_mark();
 
-    if (ctx->keytype == NULL)
+    if (ctx->engine != NULL || ctx->keytype == NULL)
         goto legacy;
 
     /*
index f34eacf552b2478c2fd25b92ed62e704da326cf7..3411b734e5e9d415c1eb06c93f90f7770b0e19e0 100644 (file)
@@ -1092,6 +1092,13 @@ static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
     OSSL_PARAM *params = NULL;
     int rv = 0;
 
+    /*
+     * If the RSA method is foreign, then we can't be sure of anything, and
+     * can therefore not export or pretend to export.
+     */
+    if (RSA_get_method(rsa) != RSA_PKCS1_OpenSSL())
+        return 0;
+
     /* Public parameters must always be present */
     if (n == NULL || e == NULL)
         goto err;