Implement a EVP_PKEY KDF to KDF provider bridge
[openssl.git] / crypto / evp / exchange.c
index 28e1f88..a47a0f0 100644 (file)
@@ -202,11 +202,31 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
 
     /*
      * Ensure that the key is provided, either natively, or as a cached export.
-     *  If not, go legacy
+     * If not, goto legacy
      */
     tmp_keymgmt = ctx->keymgmt;
-    provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
-                                          &tmp_keymgmt, ctx->propquery);
+    if (ctx->pkey == NULL) {
+        /*
+         * Some algorithms (e.g. legacy KDFs) don't have a pkey - so we create
+         * a blank one.
+         */
+        EVP_PKEY *pkey = EVP_PKEY_new();
+
+        if (pkey == NULL || !EVP_PKEY_set_type_by_keymgmt(pkey, tmp_keymgmt)) {
+            ERR_clear_last_mark();
+            EVP_PKEY_free(pkey);
+            ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+            goto err;
+        }
+        provkey = pkey->keydata = evp_keymgmt_newdata(tmp_keymgmt);
+        if (provkey == NULL)
+            EVP_PKEY_free(pkey);
+        else
+            ctx->pkey = pkey;
+    } else {
+        provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
+                                            &tmp_keymgmt, ctx->propquery);
+    }
     if (provkey == NULL)
         goto legacy;
     if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) {