Commit 00022fdfad for openssl.org

commit 00022fdfad6bb72ac5dadd1864e5985ff6f3bec4
Author: Matt Caswell <matt@openssl.org>
Date:   Thu Dec 11 16:14:13 2025 +0000

    Remove references to the pmeth field in an EVP_PKEY_CTX

    We don't set this field anymore so we should remove all usage of it.

    Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
    Reviewed-by: Paul Yang <paulyang.inf@gmail.com>
    (Merged from https://github.com/openssl/openssl/pull/29384)

diff --git a/crypto/evp/asymcipher.c b/crypto/evp/asymcipher.c
index 652303483d..b76a144e8a 100644
--- a/crypto/evp/asymcipher.c
+++ b/crypto/evp/asymcipher.c
@@ -50,7 +50,7 @@ static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation,
     ERR_set_mark();

     if (evp_pkey_ctx_is_legacy(ctx))
-        goto legacy;
+        goto err;

     if (ctx->pkey == NULL) {
         ERR_clear_last_mark();
@@ -116,7 +116,7 @@ static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation,
             cipher = evp_asym_cipher_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
                 supported_ciph, ctx->propquery);
             if (cipher == NULL)
-                goto legacy;
+                goto err;
             break;
         }
         if (cipher == NULL)
@@ -144,7 +144,7 @@ static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation,

     if (provkey == NULL) {
         EVP_ASYM_CIPHER_free(cipher);
-        goto legacy;
+        goto err;
     }

     ERR_pop_to_mark();
@@ -189,35 +189,6 @@ static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation,
     EVP_KEYMGMT_free(tmp_keymgmt);
     return 1;

-legacy:
-    /*
-     * If we don't have the full support we need with provided methods,
-     * let's go see if legacy does.
-     */
-    ERR_pop_to_mark();
-    EVP_KEYMGMT_free(tmp_keymgmt);
-    tmp_keymgmt = NULL;
-
-    if (ctx->pmeth == NULL || ctx->pmeth->encrypt == NULL) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-        return -2;
-    }
-    switch (ctx->operation) {
-    case EVP_PKEY_OP_ENCRYPT:
-        if (ctx->pmeth->encrypt_init == NULL)
-            return 1;
-        ret = ctx->pmeth->encrypt_init(ctx);
-        break;
-    case EVP_PKEY_OP_DECRYPT:
-        if (ctx->pmeth->decrypt_init == NULL)
-            return 1;
-        ret = ctx->pmeth->decrypt_init(ctx);
-        break;
-    default:
-        ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
-        ret = -1;
-    }
-
 err:
     if (ret <= 0) {
         evp_pkey_ctx_free_old_ops(ctx);
@@ -255,9 +226,10 @@ int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx,
         return -1;
     }

-    if (ctx->op.ciph.algctx == NULL)
-        goto legacy;
-
+    if (ctx->op.ciph.algctx == NULL) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }
     cipher = ctx->op.ciph.cipher;
     desc = cipher->description != NULL ? cipher->description : "";
     ERR_set_mark();
@@ -267,13 +239,6 @@ int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx,
             "%s encrypt:%s", cipher->type_name, desc);
     ERR_clear_last_mark();
     return ret;
-
-legacy:
-    if (ctx->pmeth == NULL || ctx->pmeth->encrypt == NULL) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-        return -2;
-    }
-    M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_ENCRYPT) return ctx->pmeth->encrypt(ctx, out, outlen, in, inlen);
 }

 int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx)
@@ -304,8 +269,10 @@ int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
         return -1;
     }

-    if (ctx->op.ciph.algctx == NULL)
-        goto legacy;
+    if (ctx->op.ciph.algctx == NULL) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }

     cipher = ctx->op.ciph.cipher;
     desc = cipher->description != NULL ? cipher->description : "";
@@ -317,13 +284,6 @@ int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
     ERR_clear_last_mark();

     return ret;
-
-legacy:
-    if (ctx->pmeth == NULL || ctx->pmeth->decrypt == NULL) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-        return -2;
-    }
-    M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_DECRYPT) return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen);
 }

 /* decrypt to new buffer of dynamic size, checking any pre-determined size */
diff --git a/crypto/evp/ctrl_params_translate.c b/crypto/evp/ctrl_params_translate.c
index d4bbc6cf72..5371e21fc4 100644
--- a/crypto/evp/ctrl_params_translate.c
+++ b/crypto/evp/ctrl_params_translate.c
@@ -2718,11 +2718,6 @@ int evp_pkey_ctx_ctrl_to_param(EVP_PKEY_CTX *pctx,
         return -2;
     }

-    if (pctx->pmeth != NULL
-        && pctx->pmeth->pkey_id != translation->keytype1
-        && pctx->pmeth->pkey_id != translation->keytype2)
-        return -1;
-
     if (translation->fixup_args != NULL)
         fixup = translation->fixup_args;
     ctx.action_type = translation->action_type;
diff --git a/crypto/evp/dh_ctrl.c b/crypto/evp/dh_ctrl.c
index 48f454cee2..7d07d0d520 100644
--- a/crypto/evp/dh_ctrl.c
+++ b/crypto/evp/dh_ctrl.c
@@ -25,8 +25,8 @@ static int dh_paramgen_check(EVP_PKEY_CTX *ctx)
     }
     /* If key type not DH return error */
     if (evp_pkey_ctx_is_legacy(ctx)
-        && ctx->pmeth->pkey_id != EVP_PKEY_DH
-        && ctx->pmeth->pkey_id != EVP_PKEY_DHX)
+        && ctx->legacy_keytype != EVP_PKEY_DH
+        && ctx->legacy_keytype != EVP_PKEY_DHX)
         return -1;
     return 1;
 }
@@ -40,8 +40,8 @@ static int dh_param_derive_check(EVP_PKEY_CTX *ctx)
     }
     /* If key type not DH return error */
     if (evp_pkey_ctx_is_legacy(ctx)
-        && ctx->pmeth->pkey_id != EVP_PKEY_DH
-        && ctx->pmeth->pkey_id != EVP_PKEY_DHX)
+        && ctx->legacy_keytype != EVP_PKEY_DH
+        && ctx->legacy_keytype != EVP_PKEY_DHX)
         return -1;
     return 1;
 }
diff --git a/crypto/evp/dsa_ctrl.c b/crypto/evp/dsa_ctrl.c
index af1b055ee4..8490a1fe82 100644
--- a/crypto/evp/dsa_ctrl.c
+++ b/crypto/evp/dsa_ctrl.c
@@ -22,7 +22,7 @@ static int dsa_paramgen_check(EVP_PKEY_CTX *ctx)
         return -2;
     }
     /* If key type not DSA return error */
-    if (ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_DSA)
+    if (ctx->legacy_keytype != EVP_PKEY_DSA)
         return -1;
     return 1;
 }
diff --git a/crypto/evp/ec_ctrl.c b/crypto/evp/ec_ctrl.c
index 096f7f18d7..be772003e1 100644
--- a/crypto/evp/ec_ctrl.c
+++ b/crypto/evp/ec_ctrl.c
@@ -30,7 +30,7 @@ static ossl_inline int evp_pkey_ctx_getset_ecdh_param_checks(const EVP_PKEY_CTX

     /* If key type not EC return error */
     if (evp_pkey_ctx_is_legacy(ctx)
-        && ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_EC)
+        && ctx->legacy_keytype != EVP_PKEY_EC)
         return -1;

     return 1;
diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h
index 1eb9e46a8f..c5d55f05e5 100644
--- a/crypto/evp/evp_local.h
+++ b/crypto/evp/evp_local.h
@@ -381,24 +381,6 @@ int evp_do_md_ctx_setparams(const EVP_MD *md, void *provctx,

 OSSL_PARAM *evp_pkey_to_param(EVP_PKEY *pkey, size_t *sz);

-#define M_check_autoarg(ctx, arg, arglen, err)                               \
-    if (ctx->pmeth->flags & EVP_PKEY_FLAG_AUTOARGLEN) {                      \
-        size_t pksize = (size_t)EVP_PKEY_get_size(ctx->pkey);                \
-                                                                             \
-        if (pksize == 0) {                                                   \
-            ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY); /*ckerr_ignore*/      \
-            return 0;                                                        \
-        }                                                                    \
-        if (arg == NULL) {                                                   \
-            *arglen = pksize;                                                \
-            return 1;                                                        \
-        }                                                                    \
-        if (*arglen < pksize) {                                              \
-            ERR_raise(ERR_LIB_EVP, EVP_R_BUFFER_TOO_SMALL); /*ckerr_ignore*/ \
-            return 0;                                                        \
-        }                                                                    \
-    }
-
 void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *ctx);
 void evp_cipher_free_int(EVP_CIPHER *md);

diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c
index de2c966638..bd1b8f6d3e 100644
--- a/crypto/evp/exchange.c
+++ b/crypto/evp/exchange.c
@@ -232,7 +232,7 @@ int EVP_PKEY_derive_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
     ERR_set_mark();

     if (evp_pkey_ctx_is_legacy(ctx))
-        goto legacy;
+        goto err;

     /*
      * Some algorithms (e.g. legacy KDFs) don't have a pkey - so we create
@@ -307,8 +307,11 @@ int EVP_PKEY_derive_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
             tmp_prov = EVP_KEYMGMT_get0_provider(ctx->keymgmt);
             exchange = evp_keyexch_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
                 supported_exch, ctx->propquery);
-            if (exchange == NULL)
-                goto legacy;
+            if (exchange == NULL) {
+                ERR_pop_to_mark();
+                ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+                return -2;
+            }
             break;
         }
         if (exchange == NULL)
@@ -334,14 +337,14 @@ int EVP_PKEY_derive_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
     }

     if (provkey == NULL) {
+        ERR_pop_to_mark();
         EVP_KEYEXCH_free(exchange);
-        goto legacy;
+        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
     }

     ERR_pop_to_mark();

-    /* No more legacy from here down to legacy: */
-
     /* A Coverity false positive with up_ref/down_ref and free */
     /* coverity[use_after_free] */
     ctx->op.kex.exchange = exchange;
@@ -362,30 +365,6 @@ err:
     ctx->operation = EVP_PKEY_OP_UNDEFINED;
     EVP_KEYMGMT_free(tmp_keymgmt);
     return 0;
-
-legacy:
-    /*
-     * If we don't have the full support we need with provided methods,
-     * let's go see if legacy does.
-     */
-    ERR_pop_to_mark();
-
-#ifdef FIPS_MODULE
-    return 0;
-#else
-    if (ctx->pmeth == NULL || ctx->pmeth->derive == NULL) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-        return -2;
-    }
-
-    if (ctx->pmeth->derive_init == NULL)
-        return 1;
-    ret = ctx->pmeth->derive_init(ctx);
-    if (ret <= 0)
-        ctx->operation = EVP_PKEY_OP_UNDEFINED;
-    EVP_KEYMGMT_free(tmp_keymgmt);
-    return ret;
-#endif
 }

 int EVP_PKEY_derive_set_peer_ex(EVP_PKEY_CTX *ctx, EVP_PKEY *peer,
@@ -401,8 +380,10 @@ int EVP_PKEY_derive_set_peer_ex(EVP_PKEY_CTX *ctx, EVP_PKEY *peer,
         return -1;
     }

-    if (!EVP_PKEY_CTX_IS_DERIVE_OP(ctx) || ctx->op.kex.algctx == NULL)
-        goto legacy;
+    if (!EVP_PKEY_CTX_IS_DERIVE_OP(ctx) || ctx->op.kex.algctx == NULL) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }

     if (ctx->op.kex.exchange->set_peer == NULL) {
         ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
@@ -432,79 +413,24 @@ int EVP_PKEY_derive_set_peer_ex(EVP_PKEY_CTX *ctx, EVP_PKEY *peer,
                                                                        EVP_KEYEXCH_get0_provider(ctx->op.kex.exchange),
         EVP_KEYMGMT_get0_name(ctx->keymgmt),
         ctx->propquery);
-    if (tmp_keymgmt != NULL)
-        /* A Coverity issue with up_ref/down_ref and free */
-        /* coverity[pass_freed_arg] */
-        provkey = evp_pkey_export_to_provider(peer, ctx->libctx,
-            &tmp_keymgmt, ctx->propquery);
-    EVP_KEYMGMT_free(tmp_keymgmt_tofree);
-
-    /*
-     * If making the key provided wasn't possible, legacy may be able to pick
-     * it up
-     */
-    if (provkey == NULL)
-        goto legacy;
-    ret = ctx->op.kex.exchange->set_peer(ctx->op.kex.algctx, provkey);
-    if (ret <= 0)
-        return ret;
-    goto common;
-
-legacy:
-#ifdef FIPS_MODULE
-    return ret;
-#else
-    if (ctx->pmeth == NULL
-        || !(ctx->pmeth->derive != NULL
-            || ctx->pmeth->encrypt != NULL
-            || ctx->pmeth->decrypt != NULL)
-        || ctx->pmeth->ctrl == NULL) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-        return -2;
-    }
-    if (ctx->operation != EVP_PKEY_OP_DERIVE
-        && ctx->operation != EVP_PKEY_OP_ENCRYPT
-        && ctx->operation != EVP_PKEY_OP_DECRYPT) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
-        return -1;
-    }
-
-    ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 0, peer);
-
-    if (ret <= 0)
-        return ret;
-
-    if (ret == 2)
-        return 1;
-
-    if (ctx->pkey == NULL) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET);
-        return -1;
-    }
-
-    if (ctx->pkey->type != peer->type) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES);
+    if (tmp_keymgmt == NULL) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEYMGMT_AVAILABLE);
         return -1;
     }
+    /* A Coverity issue with up_ref/down_ref and free */
+    /* coverity[pass_freed_arg] */
+    provkey = evp_pkey_export_to_provider(peer, ctx->libctx,
+        &tmp_keymgmt, ctx->propquery);
+    EVP_KEYMGMT_free(tmp_keymgmt_tofree);

-    /*
-     * For clarity.  The error is if parameters in peer are
-     * present (!missing) but don't match.  EVP_PKEY_parameters_eq may return
-     * 1 (match), 0 (don't match) and -2 (comparison is not defined).  -1
-     * (different key types) is impossible here because it is checked earlier.
-     * -2 is OK for us here, as well as 1, so we can check for 0 only.
-     */
-    if (!EVP_PKEY_missing_parameters(peer) && !EVP_PKEY_parameters_eq(ctx->pkey, peer)) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_PARAMETERS);
+    if (provkey == NULL) {
+        ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
         return -1;
     }
-
-    ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer);
+    ret = ctx->op.kex.exchange->set_peer(ctx->op.kex.algctx, provkey);
     if (ret <= 0)
         return ret;
-#endif

-common:
     if (!EVP_PKEY_up_ref(peer))
         return -1;

@@ -533,20 +459,15 @@ int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *pkeylen)
         return -1;
     }

-    if (ctx->op.kex.algctx == NULL)
-        goto legacy;
+    if (ctx->op.kex.algctx == NULL) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }

     ret = ctx->op.kex.exchange->derive(ctx->op.kex.algctx, key, pkeylen,
         key != NULL ? *pkeylen : 0);

     return ret;
-legacy:
-    if (ctx->pmeth == NULL || ctx->pmeth->derive == NULL) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-        return -2;
-    }
-
-    M_check_autoarg(ctx, key, pkeylen, EVP_F_EVP_PKEY_DERIVE) return ctx->pmeth->derive(ctx, key, pkeylen);
 }

 EVP_SKEY *EVP_PKEY_derive_SKEY(EVP_PKEY_CTX *ctx, EVP_SKEYMGMT *mgmt,
diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c
index d37f8a0f77..1162810cd5 100644
--- a/crypto/evp/m_sigver.c
+++ b/crypto/evp/m_sigver.c
@@ -17,12 +17,6 @@
 #include "internal/common.h"
 #include "evp_local.h"

-static int update(EVP_MD_CTX *ctx, const void *data, size_t datalen)
-{
-    ERR_raise(ERR_LIB_EVP, EVP_R_ONLY_ONESHOT_SUPPORTED);
-    return 0;
-}
-
 /*
  * If we get the "NULL" md then the name comes back as "UNDEF". We want to use
  * NULL for this.
@@ -67,7 +61,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
     ERR_set_mark();

     if (evp_pkey_ctx_is_legacy(locpctx))
-        goto legacy;
+        goto notsupported;

     /* do not reinitialize if pkey is set or operation is different */
     if (reinit
@@ -151,7 +145,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
             signature = evp_signature_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
                 supported_sig, locpctx->propquery);
             if (signature == NULL)
-                goto legacy;
+                goto notsupported;
             break;
         }
         if (signature == NULL)
@@ -271,8 +265,13 @@ reinitialize:
      * If the operation was not a success and no digest was found, an error
      * needs to be raised.
      */
-    if (ret > 0 || mdname != NULL)
-        goto end;
+    if (ret > 0 || mdname != NULL) {
+        if (ret > 0)
+            ret = evp_pkey_ctx_use_cached_data(locpctx);
+
+        EVP_KEYMGMT_free(tmp_keymgmt);
+        return ret > 0 ? 1 : 0;
+    }
     if (type == NULL) /* This check is redundant but clarifies matters */
         ERR_raise(ERR_LIB_EVP, EVP_R_NO_DEFAULT_DIGEST);
     ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
@@ -285,85 +284,14 @@ err:
     EVP_KEYMGMT_free(tmp_keymgmt);
     return 0;

-legacy:
-    /*
-     * If we don't have the full support we need with provided methods,
-     * let's go see if legacy does.
-     */
+notsupported:
     ERR_pop_to_mark();
     EVP_KEYMGMT_free(tmp_keymgmt);
-    tmp_keymgmt = NULL;
-
-    if (type == NULL && mdname != NULL)
-        type = evp_get_digestbyname_ex(locpctx->libctx, mdname);
-
-    if (ctx->pctx->pmeth == NULL) {
-        ERR_raise_data(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE,
-            ver ? "%s digest_verify_init" : "%s digest_sign_init",
-            EVP_PKEY_get0_type_name(locpctx->pkey));
-        return 0;
-    }
-
-    if (!(ctx->pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM)) {

-        if (type == NULL) {
-            int def_nid;
-            if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) > 0)
-                type = EVP_get_digestbynid(def_nid);
-        }
-
-        if (type == NULL) {
-            ERR_raise(ERR_LIB_EVP, EVP_R_NO_DEFAULT_DIGEST);
-            return 0;
-        }
-    }
-
-    if (ver) {
-        if (ctx->pctx->pmeth->verifyctx_init) {
-            if (ctx->pctx->pmeth->verifyctx_init(ctx->pctx, ctx) <= 0)
-                return 0;
-            ctx->pctx->operation = EVP_PKEY_OP_VERIFYCTX;
-        } else if (ctx->pctx->pmeth->digestverify != 0) {
-            ctx->pctx->operation = EVP_PKEY_OP_VERIFY;
-            ctx->update = update;
-        } else if (EVP_PKEY_verify_init(ctx->pctx) <= 0) {
-            return 0;
-        }
-    } else {
-        if (ctx->pctx->pmeth->signctx_init) {
-            if (ctx->pctx->pmeth->signctx_init(ctx->pctx, ctx) <= 0)
-                return 0;
-            ctx->pctx->operation = EVP_PKEY_OP_SIGNCTX;
-        } else if (ctx->pctx->pmeth->digestsign != 0) {
-            ctx->pctx->operation = EVP_PKEY_OP_SIGN;
-            ctx->update = update;
-        } else if (EVP_PKEY_sign_init(ctx->pctx) <= 0) {
-            return 0;
-        }
-    }
-    if (EVP_PKEY_CTX_set_signature_md(ctx->pctx, type) <= 0)
-        return 0;
-    if (pctx)
-        *pctx = ctx->pctx;
-    if (ctx->pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM)
-        return 1;
-    if (!EVP_DigestInit_ex(ctx, type, NULL))
-        return 0;
-    /*
-     * This indicates the current algorithm requires
-     * special treatment before hashing the tbs-message.
-     */
-    ctx->pctx->flag_call_digest_custom = 0;
-    if (ctx->pctx->pmeth->digest_custom != NULL)
-        ctx->pctx->flag_call_digest_custom = 1;
-
-    ret = 1;
-end:
-    if (ret > 0)
-        ret = evp_pkey_ctx_use_cached_data(locpctx);
-
-    EVP_KEYMGMT_free(tmp_keymgmt);
-    return ret > 0 ? 1 : 0;
+    ERR_raise_data(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE,
+        ver ? "%s digest_verify_init" : "%s digest_sign_init",
+        EVP_PKEY_get0_type_name(locpctx->pkey));
+    return 0;
 }

 int EVP_DigestSignInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
@@ -414,11 +342,15 @@ int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
         return 0;
     }

-    if (pctx == NULL
-        || pctx->operation != EVP_PKEY_OP_SIGNCTX
+    if (pctx == NULL)
+        return EVP_DigestUpdate(ctx, data, dsize);
+
+    if (pctx->operation != EVP_PKEY_OP_SIGNCTX
         || pctx->op.sig.algctx == NULL
-        || pctx->op.sig.signature == NULL)
-        goto legacy;
+        || pctx->op.sig.signature == NULL) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+        return 0;
+    }

     signature = pctx->op.sig.signature;
     desc = signature->description != NULL ? signature->description : "";
@@ -435,21 +367,6 @@ int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
             "%s digest_sign_update:%s", signature->type_name, desc);
     ERR_clear_last_mark();
     return ret;
-
-legacy:
-    if (pctx != NULL) {
-        if (pctx->pmeth == NULL) {
-            ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
-            return 0;
-        }
-        /* do_sigver_init() checked that |digest_custom| is non-NULL */
-        if (pctx->flag_call_digest_custom
-            && !ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx))
-            return 0;
-        pctx->flag_call_digest_custom = 0;
-    }
-
-    return EVP_DigestUpdate(ctx, data, dsize);
 }

 int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
@@ -468,7 +385,7 @@ int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
         || pctx->operation != EVP_PKEY_OP_VERIFYCTX
         || pctx->op.sig.algctx == NULL
         || pctx->op.sig.signature == NULL)
-        goto legacy;
+        return EVP_DigestUpdate(ctx, data, dsize);

     signature = pctx->op.sig.signature;
     desc = signature->description != NULL ? signature->description : "";
@@ -485,17 +402,6 @@ int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
             "%s digest_verify_update:%s", signature->type_name, desc);
     ERR_clear_last_mark();
     return ret;
-
-legacy:
-    if (pctx != NULL) {
-        /* do_sigver_init() checked that |digest_custom| is non-NULL */
-        if (pctx->flag_call_digest_custom
-            && !ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx))
-            return 0;
-        pctx->flag_call_digest_custom = 0;
-    }
-
-    return EVP_DigestUpdate(ctx, data, dsize);
 }

 int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
@@ -503,7 +409,6 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
 {
     EVP_SIGNATURE *signature;
     const char *desc;
-    int sctx = 0;
     int r = 0;
     EVP_PKEY_CTX *dctx = NULL, *pctx = ctx->pctx;

@@ -515,8 +420,10 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
     if (pctx == NULL
         || pctx->operation != EVP_PKEY_OP_SIGNCTX
         || pctx->op.sig.algctx == NULL
-        || pctx->op.sig.signature == NULL)
-        goto legacy;
+        || pctx->op.sig.signature == NULL) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+        return 0;
+    }

     signature = pctx->op.sig.signature;
     desc = signature->description != NULL ? signature->description : "";
@@ -545,79 +452,6 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
     else
         EVP_PKEY_CTX_free(dctx);
     return r;
-
-legacy:
-    if (pctx == NULL || pctx->pmeth == NULL) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
-        return 0;
-    }
-
-    /* do_sigver_init() checked that |digest_custom| is non-NULL */
-    if (pctx->flag_call_digest_custom
-        && !ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx))
-        return 0;
-    pctx->flag_call_digest_custom = 0;
-
-    if (pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) {
-        if (sigret == NULL)
-            return pctx->pmeth->signctx(pctx, sigret, siglen, ctx);
-        if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISE) != 0) {
-            r = pctx->pmeth->signctx(pctx, sigret, siglen, ctx);
-            ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
-        } else {
-            dctx = EVP_PKEY_CTX_dup(pctx);
-            if (dctx == NULL)
-                return 0;
-            r = dctx->pmeth->signctx(dctx, sigret, siglen, ctx);
-            EVP_PKEY_CTX_free(dctx);
-        }
-        return r;
-    }
-    if (pctx->pmeth->signctx != NULL)
-        sctx = 1;
-    else
-        sctx = 0;
-    if (sigret != NULL) {
-        unsigned char md[EVP_MAX_MD_SIZE];
-        unsigned int mdlen = 0;
-
-        if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) {
-            if (sctx)
-                r = pctx->pmeth->signctx(pctx, sigret, siglen, ctx);
-            else
-                r = EVP_DigestFinal_ex(ctx, md, &mdlen);
-        } else {
-            EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new();
-
-            if (tmp_ctx == NULL)
-                return 0;
-            if (!EVP_MD_CTX_copy_ex(tmp_ctx, ctx)) {
-                EVP_MD_CTX_free(tmp_ctx);
-                return 0;
-            }
-            if (sctx)
-                r = tmp_ctx->pctx->pmeth->signctx(tmp_ctx->pctx,
-                    sigret, siglen, tmp_ctx);
-            else
-                r = EVP_DigestFinal_ex(tmp_ctx, md, &mdlen);
-            EVP_MD_CTX_free(tmp_ctx);
-        }
-        if (sctx || !r)
-            return r;
-        if (EVP_PKEY_sign(pctx, sigret, siglen, md, mdlen) <= 0)
-            return 0;
-    } else {
-        if (sctx) {
-            if (pctx->pmeth->signctx(pctx, sigret, siglen, ctx) <= 0)
-                return 0;
-        } else {
-            int s = EVP_MD_get_size(ctx->digest);
-
-            if (s <= 0 || EVP_PKEY_sign(pctx, sigret, siglen, NULL, s) <= 0)
-                return 0;
-        }
-    }
-    return 1;
 }

 int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen,
@@ -655,10 +489,6 @@ int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen,
             ERR_clear_last_mark();
             return ret;
         }
-    } else {
-        /* legacy */
-        if (pctx->pmeth != NULL && pctx->pmeth->digestsign != NULL)
-            return pctx->pmeth->digestsign(ctx, sigret, siglen, tbs, tbslen);
     }

     if (sigret != NULL && EVP_DigestSignUpdate(ctx, tbs, tbslen) <= 0)
@@ -671,9 +501,6 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
 {
     EVP_SIGNATURE *signature;
     const char *desc;
-    int vctx = 0;
-    unsigned int mdlen = 0;
-    unsigned char md[EVP_MAX_MD_SIZE];
     int r = 0;
     EVP_PKEY_CTX *dctx = NULL, *pctx = ctx->pctx;

@@ -685,8 +512,10 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
     if (pctx == NULL
         || pctx->operation != EVP_PKEY_OP_VERIFYCTX
         || pctx->op.sig.algctx == NULL
-        || pctx->op.sig.signature == NULL)
-        goto legacy;
+        || pctx->op.sig.signature == NULL) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+        return 0;
+    }

     signature = pctx->op.sig.signature;
     desc = signature->description != NULL ? signature->description : "";
@@ -714,47 +543,6 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
     else
         EVP_PKEY_CTX_free(dctx);
     return r;
-
-legacy:
-    if (pctx == NULL || pctx->pmeth == NULL) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
-        return 0;
-    }
-
-    /* do_sigver_init() checked that |digest_custom| is non-NULL */
-    if (pctx->flag_call_digest_custom
-        && !ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx))
-        return 0;
-    pctx->flag_call_digest_custom = 0;
-
-    if (pctx->pmeth->verifyctx != NULL)
-        vctx = 1;
-    else
-        vctx = 0;
-    if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) {
-        if (vctx) {
-            r = pctx->pmeth->verifyctx(pctx, sig, (int)siglen, ctx);
-            ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
-        } else
-            r = EVP_DigestFinal_ex(ctx, md, &mdlen);
-    } else {
-        EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new();
-        if (tmp_ctx == NULL)
-            return -1;
-        if (!EVP_MD_CTX_copy_ex(tmp_ctx, ctx)) {
-            EVP_MD_CTX_free(tmp_ctx);
-            return -1;
-        }
-        if (vctx)
-            r = tmp_ctx->pctx->pmeth->verifyctx(tmp_ctx->pctx,
-                sig, (int)siglen, tmp_ctx);
-        else
-            r = EVP_DigestFinal_ex(tmp_ctx, md, &mdlen);
-        EVP_MD_CTX_free(tmp_ctx);
-    }
-    if (vctx || !r)
-        return r;
-    return EVP_PKEY_verify(pctx, sig, siglen, md, mdlen);
 }

 int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret,
@@ -789,11 +577,8 @@ int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret,
             ERR_clear_last_mark();
             return ret;
         }
-    } else {
-        /* legacy */
-        if (pctx->pmeth != NULL && pctx->pmeth->digestverify != NULL)
-            return pctx->pmeth->digestverify(ctx, sigret, siglen, tbs, tbslen);
     }
+
     if (EVP_DigestVerifyUpdate(ctx, tbs, tbslen) <= 0)
         return -1;
     return EVP_DigestVerifyFinal(ctx, sigret, siglen);
diff --git a/crypto/evp/pmeth_check.c b/crypto/evp/pmeth_check.c
index ebab82809c..376998e5ac 100644
--- a/crypto/evp/pmeth_check.c
+++ b/crypto/evp/pmeth_check.c
@@ -59,22 +59,6 @@ static int evp_pkey_public_check_combined(EVP_PKEY_CTX *ctx, int checktype)
         != -1)
         return ok;

-    if (pkey->type == EVP_PKEY_NONE)
-        goto not_supported;
-
-#ifndef FIPS_MODULE
-    /* legacy */
-    /* call customized public key check function first */
-    if (ctx->pmeth->public_check != NULL)
-        return ctx->pmeth->public_check(pkey);
-
-    /* use default public key check function in ameth */
-    if (pkey->ameth == NULL || pkey->ameth->pkey_public_check == NULL)
-        goto not_supported;
-
-    return pkey->ameth->pkey_public_check(pkey);
-#endif
-not_supported:
     ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
     return -2;
 }
@@ -105,22 +89,6 @@ static int evp_pkey_param_check_combined(EVP_PKEY_CTX *ctx, int checktype)
         != -1)
         return ok;

-    if (pkey->type == EVP_PKEY_NONE)
-        goto not_supported;
-
-#ifndef FIPS_MODULE
-    /* legacy */
-    /* call customized param check function first */
-    if (ctx->pmeth->param_check != NULL)
-        return ctx->pmeth->param_check(pkey);
-
-    /* use default param check function in ameth */
-    if (pkey->ameth == NULL || pkey->ameth->pkey_param_check == NULL)
-        goto not_supported;
-
-    return pkey->ameth->pkey_param_check(pkey);
-#endif
-not_supported:
     ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
     return -2;
 }
@@ -175,22 +143,6 @@ int EVP_PKEY_pairwise_check(EVP_PKEY_CTX *ctx)
         != -1)
         return ok;

-    if (pkey->type == EVP_PKEY_NONE)
-        goto not_supported;
-
-#ifndef FIPS_MODULE
-    /* legacy */
-    /* call customized check function first */
-    if (ctx->pmeth->check != NULL)
-        return ctx->pmeth->check(pkey);
-
-    /* use default check function in ameth */
-    if (pkey->ameth == NULL || pkey->ameth->pkey_check == NULL)
-        goto not_supported;
-
-    return pkey->ameth->pkey_check(pkey);
-#endif
-not_supported:
     ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
     return -2;
 }
diff --git a/crypto/evp/pmeth_gn.c b/crypto/evp/pmeth_gn.c
index 0351990a78..c8ca005e94 100644
--- a/crypto/evp/pmeth_gn.c
+++ b/crypto/evp/pmeth_gn.c
@@ -34,7 +34,7 @@ static int gen_init(EVP_PKEY_CTX *ctx, int operation)
     ctx->operation = operation;

     if (ctx->keymgmt == NULL || ctx->keymgmt->gen_init == NULL)
-        goto legacy;
+        goto not_supported;

     switch (operation) {
     case EVP_PKEY_OP_PARAMGEN:
@@ -53,30 +53,6 @@ static int gen_init(EVP_PKEY_CTX *ctx, int operation)
         ret = 1;
     goto end;

-legacy:
-#ifdef FIPS_MODULE
-    goto not_supported;
-#else
-    if (ctx->pmeth == NULL
-        || (operation == EVP_PKEY_OP_PARAMGEN
-            && ctx->pmeth->paramgen == NULL)
-        || (operation == EVP_PKEY_OP_KEYGEN
-            && ctx->pmeth->keygen == NULL))
-        goto not_supported;
-
-    ret = 1;
-    switch (operation) {
-    case EVP_PKEY_OP_PARAMGEN:
-        if (ctx->pmeth->paramgen_init != NULL)
-            ret = ctx->pmeth->paramgen_init(ctx);
-        break;
-    case EVP_PKEY_OP_KEYGEN:
-        if (ctx->pmeth->keygen_init != NULL)
-            ret = ctx->pmeth->keygen_init(ctx);
-        break;
-    }
-#endif
-
 end:
     if (ret <= 0 && ctx != NULL) {
         evp_pkey_ctx_free_old_ops(ctx);
@@ -149,7 +125,7 @@ int EVP_PKEY_generate(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
     }

     if (ctx->op.keymgmt.genctx == NULL)
-        goto legacy;
+        goto not_supported;

     /*
      * Assigning gentmp to ctx->keygen_info is something our legacy
@@ -203,33 +179,6 @@ int EVP_PKEY_generate(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)

     goto end;

-legacy:
-#ifdef FIPS_MODULE
-    goto not_supported;
-#else
-    /*
-     * If we get here then we're using legacy paramgen/keygen. In that case
-     * the pkey in ctx (if there is one) had better not be provided (because the
-     * legacy methods may not know how to handle it). However we can only get
-     * here if ctx->op.keymgmt.genctx == NULL, but that should never be the case
-     * if ctx->pkey is provided because we don't allow this when we initialise
-     * the ctx.
-     */
-    if (ctx->pkey != NULL && !ossl_assert(!evp_pkey_is_provided(ctx->pkey)))
-        goto not_accessible;
-
-    switch (ctx->operation) {
-    case EVP_PKEY_OP_PARAMGEN:
-        ret = ctx->pmeth->paramgen(ctx, *ppkey);
-        break;
-    case EVP_PKEY_OP_KEYGEN:
-        ret = ctx->pmeth->keygen(ctx, *ppkey);
-        break;
-    default:
-        goto not_supported;
-    }
-#endif
-
 end:
     if (ret <= 0) {
         if (allocated_pkey != NULL)
@@ -246,12 +195,6 @@ not_initialized:
     ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
     ret = -1;
     goto end;
-#ifndef FIPS_MODULE
-not_accessible:
-    ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS);
-    ret = -1;
-    goto end;
-#endif
 }

 int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index 22e7259b2d..cfc5648d26 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -43,9 +43,6 @@ static void evp_pkey_ctx_free_cached_data(EVP_PKEY_CTX *ctx,
     int cmd, const char *name);
 static void evp_pkey_ctx_free_all_cached_data(EVP_PKEY_CTX *ctx);

-typedef const EVP_PKEY_METHOD *(*pmeth_fn)(void);
-typedef int sk_cmp_fn_type(const char *const *a, const char *const *b);
-
 #endif /* FIPS_MODULE */

 int evp_pkey_ctx_state(const EVP_PKEY_CTX *ctx)
@@ -71,7 +68,6 @@ int evp_pkey_ctx_state(const EVP_PKEY_CTX *ctx)
 static EVP_PKEY_CTX *int_ctx_new(OSSL_LIB_CTX *libctx, EVP_PKEY *pkey,
     const char *keytype, const char *propquery,
     int id)
-
 {
     EVP_PKEY_CTX *ret = NULL;
     EVP_KEYMGMT *keymgmt = NULL;
@@ -107,10 +103,7 @@ static EVP_PKEY_CTX *int_ctx_new(OSSL_LIB_CTX *libctx, EVP_PKEY *pkey,

     /* END legacy */
 #endif /* FIPS_MODULE */
-    /*
-     * If there's no app supplied pmeth and there's a name, we try
-     * fetching a provider implementation.
-     */
+    /* We try fetching a provider implementation. */
     if (keytype != NULL) {
         /*
          * If |pkey| is given and is provided, we take a reference to its
@@ -244,8 +237,6 @@ void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx)
 {
     if (ctx == NULL)
         return;
-    if (ctx->pmeth && ctx->pmeth->cleanup)
-        ctx->pmeth->cleanup(ctx);

     evp_pkey_ctx_free_old_ops(ctx);
 #ifndef FIPS_MODULE
@@ -393,36 +384,29 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx)
         goto err;
     }

-    rctx->pmeth = pctx->pmeth;
-
     if (pctx->peerkey != NULL && !EVP_PKEY_up_ref(pctx->peerkey))
         goto err;

     rctx->peerkey = pctx->peerkey;

-    if (pctx->pmeth == NULL) {
-        if (rctx->operation == EVP_PKEY_OP_UNDEFINED) {
-            EVP_KEYMGMT *tmp_keymgmt = pctx->keymgmt;
-            void *provkey;
-
-            if (pctx->pkey == NULL)
-                return rctx;
+    if (rctx->operation == EVP_PKEY_OP_UNDEFINED) {
+        EVP_KEYMGMT *tmp_keymgmt = pctx->keymgmt;
+        void *provkey;

-            provkey = evp_pkey_export_to_provider(pctx->pkey, pctx->libctx,
-                &tmp_keymgmt, pctx->propquery);
-            if (provkey == NULL)
-                goto err;
-            if (!EVP_KEYMGMT_up_ref(tmp_keymgmt))
-                goto err;
-            EVP_KEYMGMT_free(rctx->keymgmt);
-            rctx->keymgmt = tmp_keymgmt;
+        if (pctx->pkey == NULL)
             return rctx;
-        }
-    } else if (pctx->pmeth->copy(rctx, pctx) > 0) {
+
+        provkey = evp_pkey_export_to_provider(pctx->pkey, pctx->libctx,
+            &tmp_keymgmt, pctx->propquery);
+        if (provkey == NULL)
+            goto err;
+        if (!EVP_KEYMGMT_up_ref(tmp_keymgmt))
+            goto err;
+        EVP_KEYMGMT_free(rctx->keymgmt);
+        rctx->keymgmt = tmp_keymgmt;
         return rctx;
     }
 err:
-    rctx->pmeth = NULL;
     EVP_PKEY_CTX_free(rctx);
     return NULL;
 }
@@ -432,7 +416,7 @@ int EVP_PKEY_CTX_is_a(EVP_PKEY_CTX *ctx, const char *keytype)
 {
 #ifndef FIPS_MODULE
     if (evp_pkey_ctx_is_legacy(ctx))
-        return (ctx->pmeth->pkey_id == evp_pkey_name2type(keytype));
+        return (ctx->legacy_keytype == evp_pkey_name2type(keytype));
 #endif
     return EVP_KEYMGMT_is_a(ctx->keymgmt, keytype);
 }
@@ -1064,21 +1048,14 @@ static int evp_pkey_ctx_ctrl_int(EVP_PKEY_CTX *ctx, int keytype, int optype,
 {
     int ret = 0;

-    /*
-     * If the method has a |digest_custom| function, we can relax the
-     * operation type check, since this can be called before the operation
-     * is initialized.
-     */
-    if (ctx->pmeth == NULL || ctx->pmeth->digest_custom == NULL) {
-        if (ctx->operation == EVP_PKEY_OP_UNDEFINED) {
-            ERR_raise(ERR_LIB_EVP, EVP_R_NO_OPERATION_SET);
-            return -1;
-        }
+    if (ctx->operation == EVP_PKEY_OP_UNDEFINED) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_NO_OPERATION_SET);
+        return -1;
+    }

-        if ((optype != -1) && !(ctx->operation & optype)) {
-            ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
-            return -1;
-        }
+    if ((optype != -1) && !(ctx->operation & optype)) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
+        return -1;
     }

     switch (evp_pkey_ctx_state(ctx)) {
@@ -1086,18 +1063,8 @@ static int evp_pkey_ctx_ctrl_int(EVP_PKEY_CTX *ctx, int keytype, int optype,
         return evp_pkey_ctx_ctrl_to_param(ctx, keytype, optype, cmd, p1, p2);
     case EVP_PKEY_STATE_UNKNOWN:
     case EVP_PKEY_STATE_LEGACY:
-        if (ctx->pmeth == NULL || ctx->pmeth->ctrl == NULL) {
-            ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
-            return -2;
-        }
-        if ((keytype != -1) && (ctx->pmeth->pkey_id != keytype))
-            return -1;
-
-        ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2);
-
-        if (ret == -2)
-            ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
-        break;
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        return -2;
     }
     return ret;
 }
@@ -1151,17 +1118,8 @@ static int evp_pkey_ctx_ctrl_str_int(EVP_PKEY_CTX *ctx,
         return evp_pkey_ctx_ctrl_str_to_param(ctx, name, value);
     case EVP_PKEY_STATE_UNKNOWN:
     case EVP_PKEY_STATE_LEGACY:
-        if (ctx == NULL || ctx->pmeth == NULL || ctx->pmeth->ctrl_str == NULL) {
-            ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
-            return -2;
-        }
-        if (strcmp(name, "digest") == 0)
-            ret = EVP_PKEY_CTX_md(ctx,
-                EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
-                EVP_PKEY_CTRL_MD, value);
-        else
-            ret = ctx->pmeth->ctrl_str(ctx, name, value);
-        break;
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        return -2;
     }

     return ret;
@@ -1241,15 +1199,8 @@ static int evp_pkey_ctx_store_cached_data(EVP_PKEY_CTX *ctx,
             break;
         case EVP_PKEY_STATE_UNKNOWN:
         case EVP_PKEY_STATE_LEGACY:
-            if (ctx->pmeth == NULL) {
-                ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
-                return -2;
-            }
-            if (EVP_PKEY_type(ctx->pmeth->pkey_id) != EVP_PKEY_type(keytype)) {
-                ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
-                return -1;
-            }
-            break;
+            ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+            return -2;
         }
     }
     if (optype != -1 && (ctx->operation & optype) == 0) {
@@ -1357,7 +1308,7 @@ int EVP_PKEY_CTX_str2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *str)
     len = strlen(str);
     if (len > INT_MAX)
         return -1;
-    return ctx->pmeth->ctrl(ctx, cmd, (int)len, (void *)str);
+    return EVP_PKEY_CTX_ctrl(ctx, -1, -1, cmd, (int)len, (void *)str);
 }

 int EVP_PKEY_CTX_hex2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *hex)
@@ -1370,7 +1321,7 @@ int EVP_PKEY_CTX_hex2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *hex)
     if (bin == NULL)
         return 0;
     if (binlen <= INT_MAX)
-        rv = ctx->pmeth->ctrl(ctx, cmd, binlen, bin);
+        rv = EVP_PKEY_CTX_ctrl(ctx, -1, -1, cmd, binlen, bin);
     OPENSSL_free(bin);
     return rv;
 }
diff --git a/crypto/evp/signature.c b/crypto/evp/signature.c
index c7fbb6e706..d742106a8a 100644
--- a/crypto/evp/signature.c
+++ b/crypto/evp/signature.c
@@ -678,7 +678,7 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, EVP_SIGNATURE *signature,
         ERR_set_mark();

         if (evp_pkey_ctx_is_legacy(ctx))
-            goto legacy;
+            goto notsupported;

         if (ctx->pkey == NULL) {
             ERR_clear_last_mark();
@@ -743,7 +743,7 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, EVP_SIGNATURE *signature,
                 signature = evp_signature_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
                     supported_sig, ctx->propquery);
                 if (signature == NULL)
-                    goto legacy;
+                    goto notsupported;
                 break;
             }
             if (signature == NULL)
@@ -771,7 +771,7 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, EVP_SIGNATURE *signature,

         if (provkey == NULL) {
             EVP_SIGNATURE_free(signature);
-            goto legacy;
+            goto notsupported;
         }

         ERR_pop_to_mark();
@@ -847,7 +847,7 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, EVP_SIGNATURE *signature,
     }
     goto end;

-legacy:
+notsupported:
     /*
      * If we don't have the full support we need with provided methods,
      * let's go see if legacy does.
@@ -856,37 +856,9 @@ legacy:
     EVP_KEYMGMT_free(tmp_keymgmt);
     tmp_keymgmt = NULL;

-    if (ctx->pmeth == NULL
-        || (operation == EVP_PKEY_OP_SIGN && ctx->pmeth->sign == NULL)
-        || (operation == EVP_PKEY_OP_VERIFY && ctx->pmeth->verify == NULL)
-        || (operation == EVP_PKEY_OP_VERIFYRECOVER
-            && ctx->pmeth->verify_recover == NULL)) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-        return -2;
-    }
+    ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+    return -2;

-    switch (operation) {
-    case EVP_PKEY_OP_SIGN:
-        if (ctx->pmeth->sign_init == NULL)
-            return 1;
-        ret = ctx->pmeth->sign_init(ctx);
-        break;
-    case EVP_PKEY_OP_VERIFY:
-        if (ctx->pmeth->verify_init == NULL)
-            return 1;
-        ret = ctx->pmeth->verify_init(ctx);
-        break;
-    case EVP_PKEY_OP_VERIFYRECOVER:
-        if (ctx->pmeth->verify_recover_init == NULL)
-            return 1;
-        ret = ctx->pmeth->verify_recover_init(ctx);
-        break;
-    default:
-        ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
-        goto err;
-    }
-    if (ret <= 0)
-        goto err;
 end:
 #ifndef FIPS_MODULE
     if (ret > 0)
@@ -1008,8 +980,10 @@ int EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
         return -1;
     }

-    if (ctx->op.sig.algctx == NULL)
-        goto legacy;
+    if (ctx->op.sig.algctx == NULL) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }

     signature = ctx->op.sig.signature;
     desc = signature->description != NULL ? signature->description : "";
@@ -1025,14 +999,6 @@ int EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
         ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
             "%s sign:%s", signature->type_name, desc);
     return ret;
-legacy:
-
-    if (ctx->pmeth == NULL || ctx->pmeth->sign == NULL) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-        return -2;
-    }
-
-    M_check_autoarg(ctx, sig, siglen, EVP_F_EVP_PKEY_SIGN) return ctx->pmeth->sign(ctx, sig, siglen, tbs, tbslen);
 }

 int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx)
@@ -1161,8 +1127,10 @@ int EVP_PKEY_verify(EVP_PKEY_CTX *ctx,
         return -1;
     }

-    if (ctx->op.sig.algctx == NULL)
-        goto legacy;
+    if (ctx->op.sig.algctx == NULL) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }

     signature = ctx->op.sig.signature;
     desc = signature->description != NULL ? signature->description : "";
@@ -1179,13 +1147,6 @@ int EVP_PKEY_verify(EVP_PKEY_CTX *ctx,
             "%s verify:%s", signature->type_name, desc);

     return ret;
-legacy:
-    if (ctx->pmeth == NULL || ctx->pmeth->verify == NULL) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-        return -2;
-    }
-
-    return ctx->pmeth->verify(ctx, sig, siglen, tbs, tbslen);
 }

 int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx)
@@ -1223,8 +1184,10 @@ int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx,
         return -1;
     }

-    if (ctx->op.sig.algctx == NULL)
-        goto legacy;
+    if (ctx->op.sig.algctx == NULL) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }

     signature = ctx->op.sig.signature;
     desc = signature->description != NULL ? signature->description : "";
@@ -1240,10 +1203,4 @@ int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx,
         ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
             "%s verify_recover:%s", signature->type_name, desc);
     return ret;
-legacy:
-    if (ctx->pmeth == NULL || ctx->pmeth->verify_recover == NULL) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-        return -2;
-    }
-    M_check_autoarg(ctx, rout, routlen, EVP_F_EVP_PKEY_VERIFY_RECOVER) return ctx->pmeth->verify_recover(ctx, rout, routlen, sig, siglen);
 }
diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c
index 2781cf82d2..e6b16162dd 100644
--- a/crypto/rsa/rsa_lib.c
+++ b/crypto/rsa/rsa_lib.c
@@ -709,9 +709,9 @@ int RSA_get_version(RSA *r)
 int RSA_pkey_ctx_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2)
 {
     /* If key type not RSA or RSA-PSS return error */
-    if (ctx != NULL && ctx->pmeth != NULL
-        && ctx->pmeth->pkey_id != EVP_PKEY_RSA
-        && ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
+    if (ctx == NULL
+        || (ctx->legacy_keytype != EVP_PKEY_RSA
+            && ctx->legacy_keytype != EVP_PKEY_RSA_PSS))
         return -1;
     return EVP_PKEY_CTX_ctrl(ctx, -1, optype, cmd, p1, p2);
 }
diff --git a/crypto/rsa/rsa_local.h b/crypto/rsa/rsa_local.h
index b41bb34c27..7ea7ee6541 100644
--- a/crypto/rsa/rsa_local.h
+++ b/crypto/rsa/rsa_local.h
@@ -144,9 +144,8 @@ struct rsa_meth_st {
         BIGNUM *e, BN_GENCB *cb);
 };

-/* Macros to test if a pkey or ctx is for a PSS key */
+/* Macro to test if a pkey is for a PSS key */
 #define pkey_is_pss(pkey) (pkey->ameth->pkey_id == EVP_PKEY_RSA_PSS)
-#define pkey_ctx_is_pss(ctx) (ctx->pmeth->pkey_id == EVP_PKEY_RSA_PSS)
 int ossl_rsa_multiprime_derive(RSA *rsa, int bits, int primes,
     BIGNUM *e_value,
     STACK_OF(BIGNUM) *factors, STACK_OF(BIGNUM) *exps,
diff --git a/include/crypto/evp.h b/include/crypto/evp.h
index 40d92d2852..1141ca994e 100644
--- a/include/crypto/evp.h
+++ b/include/crypto/evp.h
@@ -119,16 +119,12 @@ struct evp_pkey_ctx_st {

     /* EVP_PKEY identity */
     int legacy_keytype;
-    /* Method associated with this operation */
-    const EVP_PKEY_METHOD *pmeth;
     /* Key: may be NULL */
     EVP_PKEY *pkey;
     /* Peer key for key agreement, may be NULL */
     EVP_PKEY *peerkey;
     /* Algorithm specific data */
     void *data;
-    /* Indicator if digest_custom needs to be called */
-    unsigned int flag_call_digest_custom : 1;
     /*
      * Used to support taking custody of memory in the case of a provider being
      * used with the deprecated EVP_PKEY_CTX_set_rsa_keygen_pubexp() API. This