]> git.ipfire.org Git - thirdparty/openssl.git/blobdiff - crypto/evp/exchange.c
EVP: Add evp_pkey_make_provided() and refactor around it
[thirdparty/openssl.git] / crypto / evp / exchange.c
index 56896390e033a6dde09cb87e29a0f493474a0594..9bb241fe145e7c07a2d643cc46d06bf5362c49b7 100644 (file)
@@ -164,6 +164,8 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
     int ret;
     void *provkey = NULL;
     EVP_KEYEXCH *exchange = NULL;
+    EVP_KEYMGMT *tmp_keymgmt = NULL;
+    const char *supported_exch = NULL;
 
     if (ctx == NULL) {
         EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
@@ -176,33 +178,36 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
     if (ctx->engine != NULL || ctx->keytype == NULL)
         goto legacy;
 
-    if (ctx->keymgmt == NULL)
-        ctx->keymgmt =
-            EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype, ctx->propquery);
-    if (ctx->keymgmt != NULL) {
-        const char *supported_exch = NULL;
+    /* Ensure that the key is provided.  If not, go legacy */
+    tmp_keymgmt = ctx->keymgmt;
+    provkey = evp_pkey_make_provided(ctx->pkey, ctx->libctx,
+                                     &tmp_keymgmt, ctx->propquery, 0);
+    if (provkey == NULL)
+        goto legacy;
+    if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+        goto err;
+    }
+    EVP_KEYMGMT_free(ctx->keymgmt);
+    ctx->keymgmt = tmp_keymgmt;
 
-        if (ctx->keymgmt->query_operation_name != NULL)
-            supported_exch =
-                ctx->keymgmt->query_operation_name(OSSL_OP_KEYEXCH);
+    if (ctx->keymgmt->query_operation_name != NULL)
+        supported_exch = ctx->keymgmt->query_operation_name(OSSL_OP_KEYEXCH);
 
-        /*
-         * If we didn't get a supported exch, assume there is one with the
-         * same name as the key type.
-         */
-        if (supported_exch == NULL)
-            supported_exch = ctx->keytype;
+    /*
+     * If we didn't get a supported exch, assume there is one with the
+     * same name as the key type.
+     */
+    if (supported_exch == NULL)
+        supported_exch = ctx->keytype;
 
-        /*
-         * Because we cleared out old ops, we shouldn't need to worry about
-         * checking if exchange is already there.
-         */
-        exchange =
-            EVP_KEYEXCH_fetch(ctx->libctx, supported_exch, ctx->propquery);
-    }
+    /*
+     * Because we cleared out old ops, we shouldn't need to worry about
+     * checking if exchange is already there.
+     */
+    exchange = EVP_KEYEXCH_fetch(ctx->libctx, supported_exch, ctx->propquery);
 
-    if (ctx->keymgmt == NULL
-        || exchange == NULL
+    if (exchange == NULL
         || (EVP_KEYMGMT_provider(ctx->keymgmt)
             != EVP_KEYEXCH_provider(exchange))) {
         /*
@@ -217,13 +222,6 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
 
 
     ctx->op.kex.exchange = exchange;
-
-    if (ctx->pkey != NULL) {
-        provkey = evp_keymgmt_export_to_provider(ctx->pkey, ctx->keymgmt, 0);
-        /* If export failed, legacy may be able to pick it up */
-        if (provkey == NULL)
-            goto legacy;
-    }
     ctx->op.kex.exchprovctx = exchange->newctx(ossl_provider_ctx(exchange->prov));
     if (ctx->op.kex.exchprovctx == NULL) {
         /* The provider key can stay in the cache */