summaryrefslogtreecommitdiffstats
path: root/crypto/evp/kem.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/evp/kem.c')
-rw-r--r--crypto/evp/kem.c56
1 files changed, 36 insertions, 20 deletions
diff --git a/crypto/evp/kem.c b/crypto/evp/kem.c
index cb904a6b26..0640e31144 100644
--- a/crypto/evp/kem.c
+++ b/crypto/evp/kem.c
@@ -35,37 +35,49 @@ static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation,
ctx->operation = operation;
/*
- * Ensure that the key is provided, either natively, or as a cached export.
+ * Try to derive the supported kem from |ctx->keymgmt|.
*/
- tmp_keymgmt = ctx->keymgmt;
- provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
- &tmp_keymgmt, ctx->propquery);
- if (provkey == NULL
- || !EVP_KEYMGMT_up_ref(tmp_keymgmt)) {
+ if (!ossl_assert(ctx->pkey->keymgmt == NULL
+ || ctx->pkey->keymgmt == ctx->keymgmt)) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ supported_kem = evp_keymgmt_util_query_operation_name(ctx->keymgmt,
+ OSSL_OP_KEM);
+ if (supported_kem == NULL) {
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_kem = ctx->keymgmt->query_operation_name(OSSL_OP_KEM);
-
- /*
- * If we didn't get a supported kem, assume there is one with the
- * same name as the key type.
- */
- if (supported_kem == NULL)
- supported_kem = ctx->keytype;
kem = EVP_KEM_fetch(ctx->libctx, supported_kem, ctx->propquery);
- if (kem == NULL
- || (EVP_KEYMGMT_get0_provider(ctx->keymgmt) != EVP_KEM_get0_provider(kem))) {
+ if (kem == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
ret = -2;
goto err;
}
+ /*
+ * Ensure that the key is provided, either natively, or as a cached export.
+ * We start by fetching the keymgmt with the same name as |ctx->pkey|,
+ * but from the provider of the kem method, using the same property
+ * query as when fetching the kem method.
+ * With the keymgmt we found (if we did), we try to export |ctx->pkey|
+ * to it (evp_pkey_export_to_provider() is smart enough to only actually
+
+ * export it if |tmp_keymgmt| is different from |ctx->pkey|'s keymgmt)
+ */
+ tmp_keymgmt
+ = evp_keymgmt_fetch_from_prov(EVP_KEM_get0_provider(kem),
+ EVP_KEYMGMT_get0_name(ctx->keymgmt),
+ ctx->propquery);
+ if (tmp_keymgmt != NULL)
+ provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
+ &tmp_keymgmt, ctx->propquery);
+ if (provkey == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+
ctx->op.encap.kem = kem;
ctx->op.encap.algctx = kem->newctx(ossl_provider_ctx(kem->prov));
if (ctx->op.encap.algctx == NULL) {
@@ -96,6 +108,9 @@ static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation,
goto err;
}
+ EVP_KEYMGMT_free(tmp_keymgmt);
+ tmp_keymgmt = NULL;
+
if (ret > 0)
return 1;
err:
@@ -103,6 +118,7 @@ static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation,
evp_pkey_ctx_free_old_ops(ctx);
ctx->operation = EVP_PKEY_OP_UNDEFINED;
}
+ EVP_KEYMGMT_free(tmp_keymgmt);
return ret;
}