EVP: Fix calls to evp_pkey_export_to_provider()
authorRichard Levitte <levitte@openssl.org>
Wed, 15 Apr 2020 07:54:11 +0000 (09:54 +0200)
committerPauli <paul.dale@oracle.com>
Fri, 17 Apr 2020 09:50:03 +0000 (19:50 +1000)
The calls weren't quite right, as this function has changed its behaviour.
We also change the internal documentation of this function, and document
evp_pkey_downgrade().

Fixes #11549

Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/11550)

crypto/evp/keymgmt_meth.c
crypto/evp/pmeth_gn.c
crypto/evp/signature.c
doc/internal/man3/evp_pkey_export_to_provider.pod

index 7ea414e8dd52e3ff8deba70cbbed83022d568ca8..7925aeaf434df166556496f4caaeb05f62772a70 100644 (file)
@@ -313,8 +313,15 @@ void *evp_keymgmt_gen_init(const EVP_KEYMGMT *keymgmt, int selection)
 int evp_keymgmt_gen_set_template(const EVP_KEYMGMT *keymgmt, void *genctx,
                                  void *template)
 {
+    /*
+     * It's arguable if we actually should return success in this case, as
+     * it allows the caller to set a template key, which is then ignored.
+     * However, this is how the legacy methods (EVP_PKEY_METHOD) operate,
+     * so we do this in the interest of backward compatibility.
+     * TODO(3.0) Investigate if we should change this behaviour.
+     */
     if (keymgmt->gen_set_template == NULL)
-        return 0;
+        return 1;
     return keymgmt->gen_set_template(genctx, template);
 }
 
index 78ed9ec781de164520fe693decbff40c3b1cbcf5..95e3185573b5cd8f0c036d6a7b8caf5c619bd960 100644 (file)
@@ -170,8 +170,12 @@ int EVP_PKEY_gen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
             evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
                                         &tmp_keymgmt, ctx->propquery);
 
-        if (keydata == NULL)
+        if (tmp_keymgmt == NULL)
             goto not_supported;
+        /*
+         * It's ok if keydata is NULL here.  The backend is expected to deal
+         * with that as it sees fit.
+         */
         ret = evp_keymgmt_gen_set_template(ctx->keymgmt,
                                            ctx->op.keymgmt.genctx, keydata);
     }
index 1f5e570ff8f570966f7db38a4e95cd991900ec5b..2334dcfb4173e70bb4f5d9a7ddc937059bafb330 100644 (file)
@@ -369,7 +369,7 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation)
     tmp_keymgmt = ctx->keymgmt;
     provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
                                           &tmp_keymgmt, ctx->propquery);
-    if (provkey == NULL)
+    if (tmp_keymgmt == NULL)
         goto legacy;
     if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) {
         ERR_clear_last_mark();
index 31e8ad02e4f13e41d8bac7508c0da3f99bedc080..1c80365ca6c3c4945f1374e7faa6617d6902843d 100644 (file)
@@ -2,7 +2,7 @@
 
 =head1 NAME
 
-evp_pkey_export_to_provider, evp_pkey_upgrade_to_provider
+evp_pkey_export_to_provider, evp_pkey_downgrade
 - internal EVP_PKEY support functions for providers
 
 =head1 SYNOPSIS
@@ -13,9 +13,7 @@ evp_pkey_export_to_provider, evp_pkey_upgrade_to_provider
  void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx,
                                    EVP_KEYMGMT **keymgmt,
                                    const char *propquery);
- void *evp_pkey_upgrade_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx,
-                                    EVP_KEYMGMT **keymgmt,
-                                    const char *propquery);
+ int evp_pkey_downgrade(EVP_PKEY *pk);
 
 =head1 DESCRIPTION
 
@@ -31,29 +29,26 @@ default context), the name of the legacy type of I<pk>, and the I<propquery>
 If I<keymgmt> isn't NULL but I<*keymgmt> is, and the "origin" was successfully
 exported, then I<*keymgmt> is assigned the implicitly fetched B<EVP_KEYMGMT>.
 
-evp_pkey_upgrade_to_provider() exports the legacy "origin" key contained in
-I<pk> to it's provider side counterpart, then clears the legacy "origin" key
-along with other legacy data, and resets all the caches.  Otherwise, it works
-like evp_pkey_export_to_provider().
-
-I<evp_pkey_upgrade_to_provider() must be used with great care, only if there's
-no other way.>
-Most of the time, it's sufficient to use evp_pkey_export_to_provider(), but in
-case the key needs modification with data coming from a provided key, the key
-will need an upgrade.
+evp_pkey_downgrade() converts an B<EVP_PKEY> with a provider side "origin" key
+to one with a legacy "origin", if there's a corresponding legacy implementation.
+This clears the operation cache, except for the provider side "origin" key.
+This function is used in spots where provider side keys aren't yet supported,
+in an attempt to keep operating with available implementations.
 
 =head1 RETURN VALUES
 
-evp_pkey_export_to_provider() and evp_pkey_upgrade_to_provider() both return
-the provider key data that was exported if the "origin" was successfully
-exported to its target.  Otherwise, NULL is returned.
+evp_pkey_export_to_provider() returns the provider key data if there was any
+allocated.  It also either sets I<*keymgmt> to the B<EVP_KEYMGMT> associated
+with the returned key data, or NULL on error.
+
+evp_pkey_downgrade() returns 1 on success or 0 on error.
 
 =head1 NOTES
 
-Some functions calling evp_pkey_export_to_provider() or
-evp_pkey_upgrade_to_provider() may have received a const key, and may
-therefore have to cast the key to non-const form to call this function.  Since
-B<EVP_PKEY> is always dynamically allocated, this is OK.
+Some functions calling evp_pkey_export_to_provider() or evp_pkey_downgrade()
+may have received a const key, and may therefore have to cast the key to
+non-const form to call this function.  Since B<EVP_PKEY> is always dynamically
+allocated, this is OK.
 
 =head1 SEE ALSO