[openssl] master update

Richard Levitte levitte at openssl.org
Fri Feb 7 08:38:22 UTC 2020


The branch master has been updated
       via  273a67e345567e4dc95bd962605a3e34532f2649 (commit)
       via  32b0645cf9f1e5c11ed1cb0fc1ff1dcd47541a93 (commit)
       via  72ec9648fee5612a9cf83ed2df1c6c0e240fa7de (commit)
       via  8dd5c603b60d8dd2907fea6c9cdefff20b787845 (commit)
       via  b305452f69fc97c586f2f9310014e332ae1d5cd5 (commit)
       via  68552cdef7631191e77315e0faeb42c6893cafe3 (commit)
      from  bd2ff9e8674b34a7547a7fa75b81b6b36f60dbb8 (commit)


- Log -----------------------------------------------------------------
commit 273a67e345567e4dc95bd962605a3e34532f2649
Author: Richard Levitte <levitte at openssl.org>
Date:   Tue Feb 4 17:49:28 2020 +0100

    KEYMGMT: Require both get_params and gettable_params, or none
    
    The same go for the pairs import + import_types and export + export_types.
    
    This required some additional changes in our KEYMGMT implementations.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11006)

commit 32b0645cf9f1e5c11ed1cb0fc1ff1dcd47541a93
Author: Richard Levitte <levitte at openssl.org>
Date:   Mon Feb 3 16:36:24 2020 +0100

    Adapt existing SERIALIZER implementations to the redesigned interface
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11006)

commit 72ec9648fee5612a9cf83ed2df1c6c0e240fa7de
Author: Richard Levitte <levitte at openssl.org>
Date:   Mon Feb 3 15:36:15 2020 +0100

    Adapt test/keymgmt_internal_test.c to the redesigned interface
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11006)

commit 8dd5c603b60d8dd2907fea6c9cdefff20b787845
Author: Richard Levitte <levitte at openssl.org>
Date:   Mon Feb 3 12:00:53 2020 +0100

    Adapt existing KEYMGMT implementations to the redesigned interface
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11006)

commit b305452f69fc97c586f2f9310014e332ae1d5cd5
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Feb 2 18:56:07 2020 +0100

    Redesign the KEYMGMT libcrypto <-> provider interface - the basics
    
    The KEYMGMT libcrypto <-> provider interface currently makes a few
    assumptions:
    
    1.  provider side domain parameters and key data isn't mutable. In
        other words, as soon as a key has been created in any (loaded,
        imported data, ...), it's set in stone.
    2.  provider side domain parameters can be strictly separated from the
        key data.
    
    This does work for the most part, but there are places where that's a
    bit too rigid for the functionality that the EVP_PKEY API delivers.
    Key data needs to be mutable to allow the flexibility that functions
    like EVP_PKEY_copy_parameters promise, as well as to provide the
    combinations of data that an EVP_PKEY is generally assumed to be able
    to hold:
    
    - domain parameters only
    - public key only
    - public key + private key
    - domain parameters + public key
    - domain parameters + public key + private key
    
    To remedy all this, we:
    
    1.  let go of the distinction between domain parameters and key
        material proper in the libcrypto <-> provider interface.
    
        As a consequence, functions that still need it gain a selection
        argument, which is a set of bits that indicate what parts of the
        key object are to be considered in a specific call.  This allows
        a reduction of very similar functions into one.
    
    2.  Rework the libcrypto <-> provider interface so provider side key
        objects are created and destructed with a separate function, and
        get their data filled and extracted in through import and export.
    
    (future work will see other key object constructors and other
    functions to fill them with data)
    
    Fixes #10979
    
    squash! Redesign the KEYMGMT libcrypto <-> provider interface - the basics
    
    Remedy 1 needs a rewrite:
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11006)

commit 68552cdef7631191e77315e0faeb42c6893cafe3
Author: Richard Levitte <levitte at openssl.org>
Date:   Mon Feb 3 05:42:48 2020 +0100

    Reorganize the internal evp_keymgmt functions
    
    Some of the evp_keymgmt_ functions are just wrappers around the
    EVP_KEYMGMT function pointers.  We move those from keymgmt_lib.c to
    keymgmt_meth.c.
    
    Other evp_keymgmt_ functions are utility functions to help the rest of
    the EVP functions.  Since their names are easily confused with the
    functions that were moved to keymgmt_meth.c, we rename them so they
    all start with evp_keymgmt_util_.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11006)

-----------------------------------------------------------------------

Summary of changes:
 crypto/dh/dh_ameth.c                               |  44 ++-
 crypto/dsa/dsa_ameth.c                             |  42 ++-
 crypto/dsa/dsa_lib.c                               |  50 ++--
 crypto/evp/evp_local.h                             |  46 +--
 crypto/evp/exchange.c                              |   4 +-
 crypto/evp/keymgmt_lib.c                           | 308 +++++----------------
 crypto/evp/keymgmt_meth.c                          | 270 +++++++++---------
 crypto/evp/m_sigver.c                              |   2 +-
 crypto/evp/p_lib.c                                 |  21 +-
 crypto/evp/pmeth_check.c                           |  30 +-
 crypto/evp/pmeth_fn.c                              |   2 +-
 crypto/evp/pmeth_gn.c                              |  22 +-
 crypto/evp/signature.c                             |   2 +-
 crypto/rsa/rsa_ameth.c                             |  54 ++--
 crypto/serializer/serializer_local.h               |   2 +
 crypto/serializer/serializer_pkey.c                |  58 ++--
 .../man3/evp_keymgmt_export_to_provider.pod        |  56 ----
 doc/internal/man3/evp_keymgmt_freekey.pod          | 109 --------
 doc/internal/man3/evp_keymgmt_newdata.pod          |  93 +++++++
 .../man3/evp_keymgmt_util_export_to_provider.pod   |  71 +++++
 doc/internal/man3/evp_pkey_make_provided.pod       |   5 +-
 doc/man3/EVP_PKEY_check.pod                        |   2 +-
 doc/man3/EVP_PKEY_fromdata.pod                     |   6 +-
 doc/man3/OSSL_SERIALIZER_CTX_new_by_EVP_PKEY.pod   |   4 +-
 doc/man3/d2i_PrivateKey.pod                        |   4 +-
 doc/man7/provider-keymgmt.pod                      | 295 +++++++++++---------
 doc/man7/provider-serializer.pod                   |   6 +-
 include/crypto/asn1.h                              |   4 +-
 include/crypto/evp.h                               |  96 +++----
 include/internal/property.h                        |   3 +
 include/openssl/core_numbers.h                     | 180 ++++++------
 include/openssl/serializer.h                       |   4 +-
 providers/defltprov.c                              |  12 +-
 providers/implementations/keymgmt/dh_kmgmt.c       | 209 +++++++++-----
 providers/implementations/keymgmt/dsa_kmgmt.c      | 206 +++++++++-----
 providers/implementations/keymgmt/rsa_kmgmt.c      | 169 +++++++----
 .../serializers/serializer_common.c                |  26 +-
 .../implementations/serializers/serializer_dh.c    |  16 +-
 .../serializers/serializer_dh_param.c              |  55 ++--
 .../serializers/serializer_dh_priv.c               |  62 +++--
 .../serializers/serializer_dh_pub.c                |  51 ++--
 .../implementations/serializers/serializer_dsa.c   |  14 +-
 .../serializers/serializer_dsa_param.c             |  63 +++--
 .../serializers/serializer_dsa_priv.c              |  51 ++--
 .../serializers/serializer_dsa_pub.c               |  51 ++--
 .../implementations/serializers/serializer_local.h |  16 +-
 .../implementations/serializers/serializer_rsa.c   |  14 +-
 .../serializers/serializer_rsa_priv.c              |  51 ++--
 .../serializers/serializer_rsa_pub.c               |  51 ++--
 test/keymgmt_internal_test.c                       |  10 +-
 50 files changed, 1594 insertions(+), 1428 deletions(-)
 delete mode 100644 doc/internal/man3/evp_keymgmt_export_to_provider.pod
 delete mode 100644 doc/internal/man3/evp_keymgmt_freekey.pod
 create mode 100644 doc/internal/man3/evp_keymgmt_newdata.pod
 create mode 100644 doc/internal/man3/evp_keymgmt_util_export_to_provider.pod

diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c
index fd241831dc..4f74ab6f4a 100644
--- a/crypto/dh/dh_ameth.c
+++ b/crypto/dh/dh_ameth.c
@@ -482,51 +482,47 @@ static size_t dh_pkey_dirty_cnt(const EVP_PKEY *pkey)
     return pkey->pkey.dh->dirty_cnt;
 }
 
-static void *dh_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
-                               int want_domainparams)
+static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
+                             EVP_KEYMGMT *to_keymgmt)
 {
-    DH *dh = pk->pkey.dh;
+    DH *dh = from->pkey.dh;
     OSSL_PARAM_BLD tmpl;
     const BIGNUM *p = DH_get0_p(dh), *g = DH_get0_g(dh), *q = DH_get0_q(dh);
     const BIGNUM *pub_key = DH_get0_pub_key(dh);
     const BIGNUM *priv_key = DH_get0_priv_key(dh);
     OSSL_PARAM *params;
-    void *provdata = NULL;
+    int rv;
 
     if (p == NULL || g == NULL)
-        return NULL;
+        return 0;
 
     ossl_param_bld_init(&tmpl);
     if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_P, p)
         || !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_G, g))
-        return NULL;
+        return 0;
     if (q != NULL) {
         if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_Q, q))
-            return NULL;
+            return 0;
     }
-
-    if (!want_domainparams) {
-        /* A key must at least have a public part. */
-        if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DH_PUB_KEY,
-                                    pub_key))
-            return NULL;
-
-        if (priv_key != NULL) {
-            if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DH_PRIV_KEY,
-                                        priv_key))
-                return NULL;
-        }
+    /* A key must at least have a public part. */
+    if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DH_PUB_KEY, pub_key))
+        return 0;
+    if (priv_key != NULL) {
+        if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DH_PRIV_KEY,
+                                    priv_key))
+            return 0;
     }
 
-    params = ossl_param_bld_to_param(&tmpl);
+    if ((params = ossl_param_bld_to_param(&tmpl)) == NULL)
+        return 0;
 
     /* We export, the provider imports */
-    provdata = want_domainparams
-        ? evp_keymgmt_importdomparams(keymgmt, params)
-        : evp_keymgmt_importkey(keymgmt, params);
+    rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL,
+                            params);
 
     ossl_param_bld_free(params);
-    return provdata;
+
+    return rv;
 }
 
 const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c
index 510b204b2d..9d1b89717c 100644
--- a/crypto/dsa/dsa_ameth.c
+++ b/crypto/dsa/dsa_ameth.c
@@ -511,48 +511,44 @@ static size_t dsa_pkey_dirty_cnt(const EVP_PKEY *pkey)
     return pkey->pkey.dsa->dirty_cnt;
 }
 
-static void *dsa_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
-                                int want_domainparams)
+static int dsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
+                              EVP_KEYMGMT *to_keymgmt)
 {
-    DSA *dsa = pk->pkey.dsa;
+    DSA *dsa = from->pkey.dsa;
     OSSL_PARAM_BLD tmpl;
     const BIGNUM *p = DSA_get0_p(dsa), *g = DSA_get0_g(dsa);
     const BIGNUM *q = DSA_get0_q(dsa), *pub_key = DSA_get0_pub_key(dsa);
     const BIGNUM *priv_key = DSA_get0_priv_key(dsa);
     OSSL_PARAM *params;
-    void *provdata = NULL;
+    int rv;
 
     if (p == NULL || q == NULL || g == NULL)
-        return NULL;
+        return 0;
 
     ossl_param_bld_init(&tmpl);
     if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_P, p)
         || !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_Q, q)
         || !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_G, g))
-        return NULL;
-
-    if (!want_domainparams) {
-        /* A key must at least have a public part. */
-        if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DSA_PUB_KEY,
-                                    pub_key))
-            return NULL;
-
-        if (priv_key != NULL) {
-            if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DSA_PRIV_KEY,
-                                        priv_key))
-                return NULL;
-        }
+        return 0;
+    if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DSA_PUB_KEY,
+                                pub_key))
+        return 0;
+    if (priv_key != NULL) {
+        if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DSA_PRIV_KEY,
+                                    priv_key))
+            return 0;
     }
 
-    params = ossl_param_bld_to_param(&tmpl);
+    if ((params = ossl_param_bld_to_param(&tmpl)) == NULL)
+        return 0;
 
     /* We export, the provider imports */
-    provdata = want_domainparams
-        ? evp_keymgmt_importdomparams(keymgmt, params)
-        : evp_keymgmt_importkey(keymgmt, params);
+    rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL,
+                            params);
 
     ossl_param_bld_free(params);
-    return provdata;
+
+    return rv;
 }
 
 /* NB these are sorted in pkey_id order, lowest first */
diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c
index 469746e65d..334ee747dd 100644
--- a/crypto/dsa/dsa_lib.c
+++ b/crypto/dsa/dsa_lib.c
@@ -75,31 +75,6 @@ DH *DSA_dup_DH(const DSA *r)
 }
 # endif /*  OPENSSL_NO_DH */
 
-const BIGNUM *DSA_get0_p(const DSA *d)
-{
-    return d->params.p;
-}
-
-const BIGNUM *DSA_get0_q(const DSA *d)
-{
-    return d->params.q;
-}
-
-const BIGNUM *DSA_get0_g(const DSA *d)
-{
-    return d->params.g;
-}
-
-const BIGNUM *DSA_get0_pub_key(const DSA *d)
-{
-    return d->pub_key;
-}
-
-const BIGNUM *DSA_get0_priv_key(const DSA *d)
-{
-    return d->priv_key;
-}
-
 void DSA_clear_flags(DSA *d, int flags)
 {
     d->flags &= ~flags;
@@ -278,6 +253,31 @@ int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
     return 1;
 }
 
+const BIGNUM *DSA_get0_p(const DSA *d)
+{
+    return d->params.p;
+}
+
+const BIGNUM *DSA_get0_q(const DSA *d)
+{
+    return d->params.q;
+}
+
+const BIGNUM *DSA_get0_g(const DSA *d)
+{
+    return d->params.g;
+}
+
+const BIGNUM *DSA_get0_pub_key(const DSA *d)
+{
+    return d->pub_key;
+}
+
+const BIGNUM *DSA_get0_priv_key(const DSA *d)
+{
+    return d->priv_key;
+}
+
 void DSA_get0_key(const DSA *d,
                   const BIGNUM **pub_key, const BIGNUM **priv_key)
 {
diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h
index 5f34aaeb23..95dd1c036e 100644
--- a/crypto/evp/evp_local.h
+++ b/crypto/evp/evp_local.h
@@ -73,39 +73,24 @@ struct evp_keymgmt_st {
     CRYPTO_REF_COUNT refcnt;
     CRYPTO_RWLOCK *lock;
 
-    /* Domain parameter routines */
-    OSSL_OP_keymgmt_importdomparams_fn *importdomparams;
-    OSSL_OP_keymgmt_gendomparams_fn *gendomparams;
-    OSSL_OP_keymgmt_freedomparams_fn *freedomparams;
-    OSSL_OP_keymgmt_exportdomparams_fn *exportdomparams;
-    OSSL_OP_keymgmt_importdomparam_types_fn *importdomparam_types;
-    OSSL_OP_keymgmt_exportdomparam_types_fn *exportdomparam_types;
-    OSSL_OP_keymgmt_get_domparam_params_fn *get_domparam_params;
-    OSSL_OP_keymgmt_gettable_domparam_params_fn *gettable_domparam_params;
-    OSSL_OP_keymgmt_validate_domparams_fn *validatedomparams;
-
-    /* Key routines */
-    OSSL_OP_keymgmt_importkey_fn *importkey;
-    OSSL_OP_keymgmt_genkey_fn *genkey;
-    OSSL_OP_keymgmt_loadkey_fn *loadkey;
-    OSSL_OP_keymgmt_freekey_fn *freekey;
-    OSSL_OP_keymgmt_exportkey_fn *exportkey;
-    OSSL_OP_keymgmt_importkey_types_fn *importkey_types;
-    OSSL_OP_keymgmt_exportkey_types_fn *exportkey_types;
-    OSSL_OP_keymgmt_get_key_params_fn *get_key_params;
-    OSSL_OP_keymgmt_gettable_key_params_fn *gettable_key_params;
+    /* Constructor(s), destructor, information */
+    OSSL_OP_keymgmt_new_fn *new;
+    OSSL_OP_keymgmt_free_fn *free;
+    OSSL_OP_keymgmt_get_params_fn *get_params;
+    OSSL_OP_keymgmt_gettable_params_fn *gettable_params;
 
+    /* Key object checking */
     OSSL_OP_keymgmt_query_operation_name_fn *query_operation_name;
-    OSSL_OP_keymgmt_validate_public_fn *validatepublic;
-    OSSL_OP_keymgmt_validate_private_fn *validateprivate;
-    OSSL_OP_keymgmt_validate_pairwise_fn *validatepairwise;
+    OSSL_OP_keymgmt_has_fn *has;
+    OSSL_OP_keymgmt_validate_fn *validate;
+
+    /* Import and export routines */
+    OSSL_OP_keymgmt_import_fn *import;
+    OSSL_OP_keymgmt_import_types_fn *import_types;
+    OSSL_OP_keymgmt_export_fn *export;
+    OSSL_OP_keymgmt_export_types_fn *export_types;
 } /* EVP_KEYMGMT */ ;
 
-struct keymgmt_data_st {
-    OPENSSL_CTX *ctx;
-    const char *properties;
-};
-
 struct evp_keyexch_st {
     int name_id;
     OSSL_PROVIDER *prov;
@@ -286,5 +271,4 @@ void evp_names_do_all(OSSL_PROVIDER *prov, int number,
                       void *data);
 int evp_cipher_cache_constants(EVP_CIPHER *cipher);
 void *evp_pkey_make_provided(EVP_PKEY *pk, OPENSSL_CTX *libctx,
-                             EVP_KEYMGMT **keymgmt, const char *propquery,
-                             int domainparams);
+                             EVP_KEYMGMT **keymgmt, const char *propquery);
diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c
index 1f87c59343..14ed4dbe8e 100644
--- a/crypto/evp/exchange.c
+++ b/crypto/evp/exchange.c
@@ -187,7 +187,7 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
     /* 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);
+                                     &tmp_keymgmt, ctx->propquery);
     if (provkey == NULL)
         goto legacy;
     if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) {
@@ -293,7 +293,7 @@ int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
         return -2;
     }
 
-    provkey = evp_keymgmt_export_to_provider(peer, ctx->keymgmt, 0);
+    provkey = evp_keymgmt_util_export_to_provider(peer, ctx->keymgmt);
     /* If export failed, legacy may be able to pick it up */
     if (provkey == NULL)
         goto legacy;
diff --git a/crypto/evp/keymgmt_lib.c b/crypto/evp/keymgmt_lib.c
index 6990c0cdaa..812bdcb560 100644
--- a/crypto/evp/keymgmt_lib.c
+++ b/crypto/evp/keymgmt_lib.c
@@ -17,25 +17,23 @@
 #include "evp_local.h"
 
 struct import_data_st {
-    void *provctx;
-    void *(*importfn)(const EVP_KEYMGMT *keymgmt, const OSSL_PARAM params[]);
+    EVP_KEYMGMT *keymgmt;
+    void *keydata;
 
-    /* Result */
-    void *provdata;
+    int selection;
 };
 
 static int try_import(const OSSL_PARAM params[], void *arg)
 {
     struct import_data_st *data = arg;
 
-    data->provdata = data->importfn(data->provctx, params);
-    return data->provdata != NULL;
+    return evp_keymgmt_import(data->keymgmt, data->keydata, data->selection,
+                              params);
 }
 
-void *evp_keymgmt_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
-                                     int want_domainparams)
+void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
 {
-    void *provdata = NULL;
+    void *keydata = NULL;
     size_t i, j;
 
     /*
@@ -51,7 +49,7 @@ void *evp_keymgmt_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
             return NULL;
 
         if (pk->ameth->dirty_cnt(pk) != pk->dirty_cnt_copy)
-            evp_keymgmt_clear_pkey_cache(pk);
+            evp_keymgmt_util_clear_pkey_cache(pk);
     }
 
     /*
@@ -61,25 +59,28 @@ void *evp_keymgmt_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
     for (i = 0;
          i < OSSL_NELEM(pk->pkeys) && pk->pkeys[i].keymgmt != NULL;
          i++) {
-        if (keymgmt == pk->pkeys[i].keymgmt
-            && want_domainparams == pk->pkeys[i].domainparams)
-            return pk->pkeys[i].provdata;
+        if (keymgmt == pk->pkeys[i].keymgmt)
+            return pk->pkeys[i].keydata;
     }
 
+    if ((keydata = evp_keymgmt_newdata(keymgmt)) == NULL)
+        return NULL;
+
     if (pk->pkey.ptr != NULL) {
         /* There is a legacy key, try to export that one to the provider */
 
-        /* If the legacy key doesn't have an export function, give up */
-        if (pk->ameth->export_to == NULL)
+        /*
+         * If the legacy key doesn't have an export function or the export
+         * function fails, give up
+         */
+        if (pk->ameth->export_to == NULL
+            || !pk->ameth->export_to(pk, keydata, keymgmt)) {
+            evp_keymgmt_freedata(keymgmt, keydata);
             return NULL;
+        }
 
-        /* Otherwise, simply use it. */
-        provdata = pk->ameth->export_to(pk, keymgmt, want_domainparams);
-
-        /* Synchronize the dirty count, but only if we exported successfully */
-        if (provdata != NULL)
-            pk->dirty_cnt_copy = pk->ameth->dirty_cnt(pk);
-
+        /* Synchronize the dirty count */
+        pk->dirty_cnt_copy = pk->ameth->dirty_cnt(pk);
     } else {
         /*
          * Here, there is no legacy key, so we look at the already cached
@@ -91,42 +92,33 @@ void *evp_keymgmt_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
         /* Setup for the export callback */
         struct import_data_st import_data;
 
-        import_data.importfn =
-            want_domainparams
-            ? evp_keymgmt_importdomparams
-            : evp_keymgmt_importkey;
-        import_data.provdata = NULL;
-
-        /*
-         * If the given keymgmt doesn't have an import function, give up
-         */
-        if (import_data.importfn == NULL)
-            return NULL;
+        import_data.keydata = keydata;
+        import_data.keymgmt = keymgmt;
+        import_data.selection = OSSL_KEYMGMT_SELECT_ALL;
 
         for (j = 0; j < i && pk->pkeys[j].keymgmt != NULL; j++) {
-            int (*exportfn)(const EVP_KEYMGMT *keymgmt, void *provdata,
-                            OSSL_CALLBACK *cb, void *cbarg) =
-                want_domainparams
-                ? evp_keymgmt_exportdomparams
-                : evp_keymgmt_exportkey;
-
-            if (exportfn != NULL) {
-                import_data.provctx =
-                    ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
-
-                /*
-                 * The export function calls the callback (try_import), which
-                 * does the import for us.
-                 * Even though we got a success return, we double check that
-                 * we actually got something, just in case some implementation
-                 * forgets to check the return value.
-
-                 */
-                if (exportfn(pk->pkeys[j].keymgmt, pk->pkeys[j].provdata,
-                             &try_import, &import_data)
-                    && (provdata = import_data.provdata) != NULL)
-                    break;
-            }
+            EVP_KEYMGMT *exp_keymgmt = pk->pkeys[i].keymgmt;
+            void *exp_keydata = pk->pkeys[i].keydata;
+
+            /*
+             * TODO(3.0) consider an evp_keymgmt_export() return value that
+             * indicates that the method is unsupported.
+             */
+            if (exp_keymgmt->export == NULL)
+                continue;
+
+            /*
+             * The export function calls the callback (try_import), which
+             * does the import for us.  If successful, we're done.
+             */
+            if (evp_keymgmt_export(exp_keymgmt, exp_keydata,
+                                   OSSL_KEYMGMT_SELECT_ALL,
+                                   &try_import, &import_data))
+                break;
+
+            /* If there was an error, bail out */
+            evp_keymgmt_freedata(keymgmt, keydata);
+            return NULL;
         }
     }
 
@@ -138,12 +130,12 @@ void *evp_keymgmt_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
     if (!ossl_assert(i < OSSL_NELEM(pk->pkeys)))
         return NULL;
 
-    evp_keymgmt_cache_pkey(pk, i, keymgmt, provdata, want_domainparams);
+    evp_keymgmt_util_cache_pkey(pk, i, keymgmt, keydata);
 
-    return provdata;
+    return keydata;
 }
 
-void evp_keymgmt_clear_pkey_cache(EVP_PKEY *pk)
+void evp_keymgmt_util_clear_pkey_cache(EVP_PKEY *pk)
 {
     size_t i;
 
@@ -152,14 +144,11 @@ void evp_keymgmt_clear_pkey_cache(EVP_PKEY *pk)
              i < OSSL_NELEM(pk->pkeys) && pk->pkeys[i].keymgmt != NULL;
              i++) {
             EVP_KEYMGMT *keymgmt = pk->pkeys[i].keymgmt;
-            void *provdata = pk->pkeys[i].provdata;
+            void *keydata = pk->pkeys[i].keydata;
 
             pk->pkeys[i].keymgmt = NULL;
-            pk->pkeys[i].provdata = NULL;
-            if (pk->pkeys[i].domainparams)
-                evp_keymgmt_freedomparams(keymgmt, provdata);
-            else
-                evp_keymgmt_freekey(keymgmt, provdata);
+            pk->pkeys[i].keydata = NULL;
+            evp_keymgmt_freedata(keymgmt, keydata);
             EVP_KEYMGMT_free(keymgmt);
         }
 
@@ -169,23 +158,21 @@ void evp_keymgmt_clear_pkey_cache(EVP_PKEY *pk)
     }
 }
 
-void evp_keymgmt_cache_pkey(EVP_PKEY *pk, size_t index, EVP_KEYMGMT *keymgmt,
-                            void *provdata, int domainparams)
+void evp_keymgmt_util_cache_pkey(EVP_PKEY *pk, size_t index,
+                                 EVP_KEYMGMT *keymgmt, void *keydata)
 {
-    if (provdata != NULL) {
+    if (keydata != NULL) {
         EVP_KEYMGMT_up_ref(keymgmt);
+        pk->pkeys[index].keydata = keydata;
         pk->pkeys[index].keymgmt = keymgmt;
-        pk->pkeys[index].provdata = provdata;
-        pk->pkeys[index].domainparams = domainparams;
 
         /*
-         * Cache information about the domain parameters or key.  Only needed
-         * for the "original" provider side key.
+         * Cache information about the key object.  Only needed for the
+         * "original" provider side key.
          *
          * This services functions like EVP_PKEY_size, EVP_PKEY_bits, etc
          */
         if (index == 0) {
-            int ok;
             int bits = 0;
             int security_bits = 0;
             int size = 0;
@@ -194,12 +181,10 @@ void evp_keymgmt_cache_pkey(EVP_PKEY *pk, size_t index, EVP_KEYMGMT *keymgmt,
             params[0] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_BITS, &bits);
             params[1] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_SECURITY_BITS,
                                                  &security_bits);
-            params[2] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_MAX_SIZE, &size);
+            params[2] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_MAX_SIZE,
+                                                 &size);
             params[3] = OSSL_PARAM_construct_end();
-            ok = domainparams
-                ? evp_keymgmt_get_domparam_params(keymgmt, provdata, params)
-                : evp_keymgmt_get_key_params(keymgmt, provdata, params);
-            if (ok) {
+            if (evp_keymgmt_get_params(keymgmt, keydata, params)) {
                 pk->cache.size = size;
                 pk->cache.bits = bits;
                 pk->cache.security_bits = security_bits;
@@ -208,164 +193,21 @@ void evp_keymgmt_cache_pkey(EVP_PKEY *pk, size_t index, EVP_KEYMGMT *keymgmt,
     }
 }
 
-void *evp_keymgmt_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
-                           const OSSL_PARAM params[], int domainparams)
-{
-    void *provdata = domainparams
-        ? evp_keymgmt_importdomparams(keymgmt, params)
-        : evp_keymgmt_importkey(keymgmt, params);
-
-    evp_keymgmt_clear_pkey_cache(target);
-    evp_keymgmt_cache_pkey(target, 0, keymgmt, provdata, domainparams);
-
-    return provdata;
-}
-
-/* internal functions */
-/* TODO(3.0) decide if these should be public or internal */
-void *evp_keymgmt_importdomparams(const EVP_KEYMGMT *keymgmt,
-                                  const OSSL_PARAM params[])
+void *evp_keymgmt_util_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
+                                int selection, const OSSL_PARAM params[])
 {
-    void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
-
-    return keymgmt->importdomparams(provctx, params);
-}
-
-void *evp_keymgmt_gendomparams(const EVP_KEYMGMT *keymgmt,
-                               const OSSL_PARAM params[])
-{
-    void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
-
-    return keymgmt->gendomparams(provctx, params);
-}
-
-void evp_keymgmt_freedomparams(const EVP_KEYMGMT *keymgmt,
-                               void *provdomparams)
-{
-    keymgmt->freedomparams(provdomparams);
-}
-
-int evp_keymgmt_exportdomparams(const EVP_KEYMGMT *keymgmt,
-                                void *provdomparams,
-                                OSSL_CALLBACK *param_cb, void *cbarg)
-{
-    return keymgmt->exportdomparams(provdomparams, param_cb, cbarg);
-}
-
-const OSSL_PARAM *evp_keymgmt_importdomparam_types(const EVP_KEYMGMT *keymgmt)
-{
-    return keymgmt->importdomparam_types();
-}
-
-/*
- * TODO(v3.0) investigate if we need this function.  'openssl provider' may
- * be a caller...
- */
-const OSSL_PARAM *evp_keymgmt_exportdomparam_types(const EVP_KEYMGMT *keymgmt)
-{
-    return keymgmt->exportdomparam_types();
-}
-
-int evp_keymgmt_get_domparam_params(const EVP_KEYMGMT *keymgmt,
-                                     void *provdomparams, OSSL_PARAM params[])
-{
-    if (keymgmt->get_domparam_params == NULL)
-        return 1;
-    return keymgmt->get_domparam_params(provdomparams, params);
-}
-
-const OSSL_PARAM *
-evp_keymgmt_gettable_domparam_params(const EVP_KEYMGMT *keymgmt)
-{
-    if (keymgmt->gettable_domparam_params == NULL)
-        return NULL;
-    return keymgmt->gettable_domparam_params();
-}
+    void *keydata = evp_keymgmt_newdata(keymgmt);
 
+    if (keydata != NULL) {
+        if (!evp_keymgmt_import(keymgmt, keydata, selection, params)) {
+            evp_keymgmt_freedata(keymgmt, keydata);
+            return NULL;
+        }
 
-void *evp_keymgmt_importkey(const EVP_KEYMGMT *keymgmt,
-                            const OSSL_PARAM params[])
-{
-    void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
-
-    return keymgmt->importkey(provctx, params);
-}
-
-void *evp_keymgmt_genkey(const EVP_KEYMGMT *keymgmt, void *domparams,
-                         const OSSL_PARAM params[])
-{
-    void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
-
-    return keymgmt->genkey(provctx, domparams, params);
-}
-
-void *evp_keymgmt_loadkey(const EVP_KEYMGMT *keymgmt,
-                          void *id, size_t idlen)
-{
-    void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
-
-    return keymgmt->loadkey(provctx, id, idlen);
-}
-
-void evp_keymgmt_freekey(const EVP_KEYMGMT *keymgmt, void *provkey)
-{
-    keymgmt->freekey(provkey);
-}
-
-int evp_keymgmt_exportkey(const EVP_KEYMGMT *keymgmt, void *provkey,
-                          OSSL_CALLBACK *param_cb, void *cbarg)
-{
-    return keymgmt->exportkey(provkey, param_cb, cbarg);
-}
-
-const OSSL_PARAM *evp_keymgmt_importkey_types(const EVP_KEYMGMT *keymgmt)
-{
-    return keymgmt->importkey_types();
-}
-
-/*
- * TODO(v3.0) investigate if we need this function.  'openssl provider' may
- * be a caller...
- */
-const OSSL_PARAM *evp_keymgmt_exportkey_types(const EVP_KEYMGMT *keymgmt)
-{
-    return keymgmt->exportkey_types();
-}
-
-int evp_keymgmt_get_key_params(const EVP_KEYMGMT *keymgmt,
-                               void *provkey, OSSL_PARAM params[])
-{
-    if (keymgmt->get_key_params == NULL)
-        return 1;
-    return keymgmt->get_key_params(provkey, params);
-}
-
-const OSSL_PARAM *evp_keymgmt_gettable_key_params(const EVP_KEYMGMT *keymgmt)
-{
-    if (keymgmt->gettable_key_params == NULL)
-        return NULL;
-    return keymgmt->gettable_key_params();
-}
-
-int evp_keymgmt_validate_domparams(const EVP_KEYMGMT *keymgmt, void *provkey)
-{
-    /* if domainparams are not supported - then pass */
-    if (keymgmt->validatedomparams == NULL)
-        return 1;
-    return keymgmt->validatedomparams(provkey);
-}
 
-int evp_keymgmt_validate_public(const EVP_KEYMGMT *keymgmt, void *provkey)
-{
-    return keymgmt->validatepublic(provkey);
-}
-
-int evp_keymgmt_validate_private(const EVP_KEYMGMT *keymgmt, void *provkey)
-{
-    return keymgmt->validateprivate(provkey);
-}
+        evp_keymgmt_util_clear_pkey_cache(target);
+        evp_keymgmt_util_cache_pkey(target, 0, keymgmt, keydata);
+    }
 
-int evp_keymgmt_validate_pairwise(const EVP_KEYMGMT *keymgmt, void *provkey)
-{
-    return keymgmt->validatepairwise(provkey);
+    return keydata;
 }
diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c
index e9e7f89744..b2395815c8 100644
--- a/crypto/evp/keymgmt_meth.c
+++ b/crypto/evp/keymgmt_meth.c
@@ -38,6 +38,7 @@ static void *keymgmt_from_dispatch(int name_id,
                                    OSSL_PROVIDER *prov)
 {
     EVP_KEYMGMT *keymgmt = NULL;
+    int paramfncnt = 0, importfncnt = 0, exportfncnt = 0;
 
     if ((keymgmt = keymgmt_new()) == NULL) {
         EVP_KEYMGMT_free(keymgmt);
@@ -47,154 +48,80 @@ static void *keymgmt_from_dispatch(int name_id,
 
     for (; fns->function_id != 0; fns++) {
         switch (fns->function_id) {
-        case OSSL_FUNC_KEYMGMT_IMPORTDOMPARAMS:
-            if (keymgmt->importdomparams != NULL)
-                break;
-            keymgmt->importdomparams =
-                OSSL_get_OP_keymgmt_importdomparams(fns);
+        case OSSL_FUNC_KEYMGMT_NEW:
+            if (keymgmt->new == NULL)
+                keymgmt->new = OSSL_get_OP_keymgmt_new(fns);
             break;
-        case OSSL_FUNC_KEYMGMT_GENDOMPARAMS:
-            if (keymgmt->gendomparams != NULL)
-                break;
-            keymgmt->gendomparams = OSSL_get_OP_keymgmt_gendomparams(fns);
+        case OSSL_FUNC_KEYMGMT_FREE:
+            if (keymgmt->free == NULL)
+                keymgmt->free = OSSL_get_OP_keymgmt_free(fns);
             break;
-        case OSSL_FUNC_KEYMGMT_FREEDOMPARAMS:
-            if (keymgmt->freedomparams != NULL)
-                break;
-            keymgmt->freedomparams = OSSL_get_OP_keymgmt_freedomparams(fns);
+        case OSSL_FUNC_KEYMGMT_GET_PARAMS:
+            if (keymgmt->get_params == NULL) {
+                paramfncnt++;
+                keymgmt->get_params = OSSL_get_OP_keymgmt_get_params(fns);
+            }
             break;
-        case OSSL_FUNC_KEYMGMT_EXPORTDOMPARAMS:
-            if (keymgmt->exportdomparams != NULL)
-                break;
-            keymgmt->exportdomparams =
-                OSSL_get_OP_keymgmt_exportdomparams(fns);
+        case OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS:
+            if (keymgmt->gettable_params == NULL) {
+                paramfncnt++;
+                keymgmt->gettable_params =
+                    OSSL_get_OP_keymgmt_gettable_params(fns);
+            }
             break;
-        case OSSL_FUNC_KEYMGMT_IMPORTDOMPARAM_TYPES:
-            if (keymgmt->importdomparam_types != NULL)
-                break;
-            keymgmt->importdomparam_types =
-                OSSL_get_OP_keymgmt_importdomparam_types(fns);
-            break;
-        case OSSL_FUNC_KEYMGMT_EXPORTDOMPARAM_TYPES:
-            if (keymgmt->exportdomparam_types != NULL)
-                break;
-            keymgmt->exportdomparam_types =
-                OSSL_get_OP_keymgmt_exportdomparam_types(fns);
-            break;
-        case OSSL_FUNC_KEYMGMT_GET_DOMPARAM_PARAMS:
-            if (keymgmt->get_domparam_params == NULL)
-                keymgmt->get_domparam_params =
-                    OSSL_get_OP_keymgmt_get_domparam_params(fns);
-            break;
-        case OSSL_FUNC_KEYMGMT_GETTABLE_DOMPARAM_PARAMS:
-            if (keymgmt->gettable_domparam_params == NULL)
-                keymgmt->gettable_domparam_params =
-                    OSSL_get_OP_keymgmt_gettable_domparam_params(fns);
-            break;
-        case OSSL_FUNC_KEYMGMT_IMPORTKEY:
-            if (keymgmt->importkey != NULL)
-                break;
-            keymgmt->importkey = OSSL_get_OP_keymgmt_importkey(fns);
-            break;
-        case OSSL_FUNC_KEYMGMT_GENKEY:
-            if (keymgmt->genkey != NULL)
-                break;
-            keymgmt->genkey = OSSL_get_OP_keymgmt_genkey(fns);
-            break;
-        case OSSL_FUNC_KEYMGMT_LOADKEY:
-            if (keymgmt->loadkey != NULL)
-                break;
-            keymgmt->loadkey = OSSL_get_OP_keymgmt_loadkey(fns);
-            break;
-        case OSSL_FUNC_KEYMGMT_FREEKEY:
-            if (keymgmt->freekey != NULL)
-                break;
-            keymgmt->freekey = OSSL_get_OP_keymgmt_freekey(fns);
-            break;
-        case OSSL_FUNC_KEYMGMT_EXPORTKEY:
-            if (keymgmt->exportkey != NULL)
-                break;
-            keymgmt->exportkey = OSSL_get_OP_keymgmt_exportkey(fns);
-            break;
-        case OSSL_FUNC_KEYMGMT_IMPORTKEY_TYPES:
-            if (keymgmt->importkey_types != NULL)
-                break;
-            keymgmt->importkey_types =
-                OSSL_get_OP_keymgmt_importkey_types(fns);
-            break;
-        case OSSL_FUNC_KEYMGMT_EXPORTKEY_TYPES:
-            if (keymgmt->exportkey_types != NULL)
-                break;
-            keymgmt->exportkey_types =
-                OSSL_get_OP_keymgmt_exportkey_types(fns);
-            break;
-        case OSSL_FUNC_KEYMGMT_GET_KEY_PARAMS:
-            if (keymgmt->get_key_params == NULL)
-                keymgmt->get_key_params =
-                    OSSL_get_OP_keymgmt_get_key_params(fns);
+        case OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME:
+            if (keymgmt->query_operation_name == NULL)
+                keymgmt->query_operation_name =
+                    OSSL_get_OP_keymgmt_query_operation_name(fns);
             break;
-        case OSSL_FUNC_KEYMGMT_GETTABLE_KEY_PARAMS:
-            if (keymgmt->gettable_key_params == NULL)
-                keymgmt->gettable_key_params =
-                    OSSL_get_OP_keymgmt_gettable_key_params(fns);
+        case OSSL_FUNC_KEYMGMT_HAS:
+            if (keymgmt->has == NULL)
+                keymgmt->has = OSSL_get_OP_keymgmt_has(fns);
             break;
-        case OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME:
-            if (keymgmt->query_operation_name != NULL)
-                break;
-            keymgmt->query_operation_name =
-                OSSL_get_OP_keymgmt_query_operation_name(fns);
+        case OSSL_FUNC_KEYMGMT_VALIDATE:
+            if (keymgmt->validate == NULL)
+                keymgmt->validate = OSSL_get_OP_keymgmt_validate(fns);
             break;
-        case OSSL_FUNC_KEYMGMT_VALIDATE_DOMPARAMS:
-            if (keymgmt->validatedomparams != NULL)
-                break;
-            keymgmt->validatedomparams =
-                OSSL_get_OP_keymgmt_validate_domparams(fns);
+        case OSSL_FUNC_KEYMGMT_IMPORT:
+            if (keymgmt->import == NULL) {
+                importfncnt++;
+                keymgmt->import = OSSL_get_OP_keymgmt_import(fns);
+            }
             break;
-        case OSSL_FUNC_KEYMGMT_VALIDATE_PUBLIC:
-            if (keymgmt->validatepublic != NULL)
-                break;
-            keymgmt->validatepublic =
-                OSSL_get_OP_keymgmt_validate_public(fns);
+        case OSSL_FUNC_KEYMGMT_IMPORT_TYPES:
+            if (keymgmt->import_types == NULL) {
+                importfncnt++;
+                keymgmt->import_types = OSSL_get_OP_keymgmt_import_types(fns);
+            }
             break;
-        case OSSL_FUNC_KEYMGMT_VALIDATE_PRIVATE:
-            if (keymgmt->validateprivate != NULL)
-                break;
-            keymgmt->validateprivate =
-                OSSL_get_OP_keymgmt_validate_private(fns);
+        case OSSL_FUNC_KEYMGMT_EXPORT:
+            if (keymgmt->export == NULL) {
+                exportfncnt++;
+                keymgmt->export = OSSL_get_OP_keymgmt_export(fns);
+            }
             break;
-        case OSSL_FUNC_KEYMGMT_VALIDATE_PAIRWISE:
-            if (keymgmt->validatepairwise != NULL)
-                break;
-            keymgmt->validatepairwise =
-                OSSL_get_OP_keymgmt_validate_pairwise(fns);
+        case OSSL_FUNC_KEYMGMT_EXPORT_TYPES:
+            if (keymgmt->export_types == NULL) {
+                exportfncnt++;
+                keymgmt->export_types = OSSL_get_OP_keymgmt_export_types(fns);
+            }
             break;
         }
     }
     /*
      * Try to check that the method is sensible.
+     * At least one constructor and the destructor are MANDATORY
+     * The functions 'has' is MANDATORY
      * It makes no sense being able to free stuff if you can't create it.
      * It makes no sense providing OSSL_PARAM descriptors for import and
      * export if you can't import or export.
      */
-    if ((keymgmt->freedomparams != NULL
-         && (keymgmt->importdomparams == NULL
-             && keymgmt->gendomparams == NULL))
-        || (keymgmt->freekey != NULL
-            && (keymgmt->importkey == NULL
-                && keymgmt->genkey == NULL
-                && keymgmt->loadkey == NULL))
-        || (keymgmt->importdomparam_types != NULL
-            && keymgmt->importdomparams == NULL)
-        || (keymgmt->exportdomparam_types != NULL
-            && keymgmt->exportdomparams == NULL)
-        || (keymgmt->gettable_domparam_params != NULL
-            && keymgmt->get_domparam_params == NULL)
-        || (keymgmt->importkey_types != NULL
-            && keymgmt->importkey == NULL)
-        || (keymgmt->exportkey_types != NULL
-            && keymgmt->exportkey == NULL)
-        || (keymgmt->gettable_key_params != NULL
-            && keymgmt->get_key_params == NULL)) {
+    if (keymgmt->free == NULL
+        || keymgmt->new == NULL
+        || keymgmt->has == NULL
+        || (paramfncnt != 0 && paramfncnt != 2)
+        || (importfncnt != 0 && importfncnt != 2)
+        || (exportfncnt != 0 && exportfncnt != 2)) {
         EVP_KEYMGMT_free(keymgmt);
         EVPerr(0, EVP_R_INVALID_PROVIDER_FUNCTIONS);
         return NULL;
@@ -280,3 +207,88 @@ void EVP_KEYMGMT_names_do_all(const EVP_KEYMGMT *keymgmt,
     if (keymgmt->prov != NULL)
         evp_names_do_all(keymgmt->prov, keymgmt->name_id, fn, data);
 }
+
+/*
+ * Internal API that interfaces with the method function pointers
+ */
+void *evp_keymgmt_newdata(const EVP_KEYMGMT *keymgmt)
+{
+    void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
+
+    /*
+     * TODO(3.0) 'new' is currently mandatory on its own, but when new
+     * constructors appear, it won't be quite as mandatory, so we have
+     * a check for future cases.
+     */
+    if (keymgmt->new == NULL)
+        return NULL;
+    return keymgmt->new(provctx);
+}
+
+void evp_keymgmt_freedata(const EVP_KEYMGMT *keymgmt, void *keydata)
+{
+    /* This is mandatory, no need to check for its presence */
+    keymgmt->free(keydata);
+}
+
+int evp_keymgmt_get_params(const EVP_KEYMGMT *keymgmt, void *keydata,
+                           OSSL_PARAM params[])
+{
+    if (keymgmt->get_params == NULL)
+        return 1;
+    return keymgmt->get_params(keydata, params);
+}
+
+const OSSL_PARAM *evp_keymgmt_gettable_params(const EVP_KEYMGMT *keymgmt)
+{
+    if (keymgmt->gettable_params == NULL)
+        return NULL;
+    return keymgmt->gettable_params();
+}
+
+int evp_keymgmt_has(const EVP_KEYMGMT *keymgmt, void *keydata, int selection)
+{
+    /* This is mandatory, no need to check for its presence */
+    return keymgmt->has(keydata, selection);
+}
+
+int evp_keymgmt_validate(const EVP_KEYMGMT *keymgmt, void *keydata,
+                         int selection)
+{
+    /* We assume valid if the implementation doesn't have a function */
+    if (keymgmt->validate == NULL)
+        return 1;
+    return keymgmt->validate(keydata, selection);
+}
+
+int evp_keymgmt_import(const EVP_KEYMGMT *keymgmt, void *keydata,
+                       int selection, const OSSL_PARAM params[])
+{
+    if (keymgmt->import == NULL)
+        return 0;
+    return keymgmt->import(keydata, selection, params);
+}
+
+const OSSL_PARAM *evp_keymgmt_import_types(const EVP_KEYMGMT *keymgmt,
+                                           int selection)
+{
+    if (keymgmt->import_types == NULL)
+        return NULL;
+    return keymgmt->import_types(selection);
+}
+
+int evp_keymgmt_export(const EVP_KEYMGMT *keymgmt, void *keydata,
+                       int selection, OSSL_CALLBACK *param_cb, void *cbarg)
+{
+    if (keymgmt->export == NULL)
+        return 0;
+    return keymgmt->export(keydata, selection, param_cb, cbarg);
+}
+
+const OSSL_PARAM *evp_keymgmt_export_types(const EVP_KEYMGMT *keymgmt,
+                                           int selection)
+{
+    if (keymgmt->export_types == NULL)
+        return NULL;
+    return keymgmt->export_types(selection);
+}
diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c
index 05dc46e3b1..1ea5669c02 100644
--- a/crypto/evp/m_sigver.c
+++ b/crypto/evp/m_sigver.c
@@ -67,7 +67,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
     /* Ensure that the key is provided.  If not, go legacy */
     tmp_keymgmt = locpctx->keymgmt;
     provkey = evp_pkey_make_provided(locpctx->pkey, locpctx->libctx,
-                                     &tmp_keymgmt, locpctx->propquery, 0);
+                                     &tmp_keymgmt, locpctx->propquery);
     if (provkey == NULL)
         goto legacy;
     if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) {
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index 0a3c86d63a..95dd96e86b 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -760,9 +760,9 @@ int EVP_PKEY_get_default_digest_name(EVP_PKEY *pkey,
                                              mdmandatory,
                                              sizeof(mdmandatory));
         params[2] = OSSL_PARAM_construct_end();
-        if (!evp_keymgmt_get_key_params(pkey->pkeys[0].keymgmt,
-                                        pkey->pkeys[0].provdata,
-                                        params))
+        if (!evp_keymgmt_get_params(pkey->pkeys[0].keymgmt,
+                                    pkey->pkeys[0].keydata,
+                                    params))
             return 0;
         if (mdmandatory[0] != '\0') {
             OPENSSL_strlcpy(mdname, mdmandatory, mdname_sz);
@@ -864,7 +864,7 @@ static void evp_pkey_free_it(EVP_PKEY *x)
 {
     /* internal function; x is never NULL */
 
-    evp_keymgmt_clear_pkey_cache(x);
+    evp_keymgmt_util_clear_pkey_cache(x);
 
     if (x->ameth && x->ameth->pkey_free) {
         x->ameth->pkey_free(x);
@@ -910,12 +910,11 @@ int EVP_PKEY_size(const EVP_PKEY *pkey)
 }
 
 void *evp_pkey_make_provided(EVP_PKEY *pk, OPENSSL_CTX *libctx,
-                             EVP_KEYMGMT **keymgmt, const char *propquery,
-                             int domainparams)
+                             EVP_KEYMGMT **keymgmt, const char *propquery)
 {
     EVP_KEYMGMT *allocated_keymgmt = NULL;
     EVP_KEYMGMT *tmp_keymgmt = NULL;
-    void *provdata = NULL;
+    void *keydata = NULL;
 
     if (pk == NULL)
         return NULL;
@@ -935,20 +934,20 @@ void *evp_pkey_make_provided(EVP_PKEY *pk, OPENSSL_CTX *libctx,
     }
 
     if (tmp_keymgmt != NULL)
-        provdata =
-            evp_keymgmt_export_to_provider(pk, tmp_keymgmt, domainparams);
+        keydata =
+            evp_keymgmt_util_export_to_provider(pk, tmp_keymgmt);
 
     /*
      * If nothing was exported, |tmp_keymgmt| might point at a freed
      * EVP_KEYMGMT, so we clear it to be safe.  It shouldn't be useful for
      * the caller either way in that case.
      */
-    if (provdata == NULL)
+    if (keydata == NULL)
         tmp_keymgmt = NULL;
 
     if (keymgmt != NULL)
         *keymgmt = tmp_keymgmt;
 
     EVP_KEYMGMT_free(allocated_keymgmt);
-    return provdata;
+    return keydata;
 }
diff --git a/crypto/evp/pmeth_check.c b/crypto/evp/pmeth_check.c
index 19f200a3ce..1186ad2b12 100644
--- a/crypto/evp/pmeth_check.c
+++ b/crypto/evp/pmeth_check.c
@@ -29,10 +29,11 @@ int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx)
     }
 
     keymgmt = pkey->pkeys[0].keymgmt;
-    key = pkey->pkeys[0].provdata;
+    key = pkey->pkeys[0].keydata;
 
     if (key != NULL && keymgmt != NULL)
-        return evp_keymgmt_validate_public(keymgmt, key);
+        return evp_keymgmt_validate(keymgmt, key,
+                                    OSSL_KEYMGMT_SELECT_PUBLIC_KEY);
 
     /* legacy */
     /* call customized public key check function first */
@@ -61,10 +62,11 @@ int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx)
     }
 
     keymgmt = pkey->pkeys[0].keymgmt;
-    key = pkey->pkeys[0].provdata;
+    key = pkey->pkeys[0].keydata;
 
     if (key != NULL && keymgmt != NULL)
-        return evp_keymgmt_validate_domparams(keymgmt, key);
+        return evp_keymgmt_validate(keymgmt, key,
+                                    OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
 
     /* call customized param check function first */
     if (ctx->pmeth->param_check != NULL)
@@ -93,10 +95,11 @@ int EVP_PKEY_private_check(EVP_PKEY_CTX *ctx)
     }
 
     keymgmt = pkey->pkeys[0].keymgmt;
-    key = pkey->pkeys[0].provdata;
+    key = pkey->pkeys[0].keydata;
 
     if (key != NULL && keymgmt != NULL)
-        return evp_keymgmt_validate_private(keymgmt, key);
+        return evp_keymgmt_validate(keymgmt, key,
+                                    OSSL_KEYMGMT_SELECT_PRIVATE_KEY);
     /* not supported for legacy keys */
     return -2;
 }
@@ -113,10 +116,10 @@ int EVP_PKEY_pairwise_check(EVP_PKEY_CTX *ctx)
     }
 
     keymgmt = pkey->pkeys[0].keymgmt;
-    key = pkey->pkeys[0].provdata;
+    key = pkey->pkeys[0].keydata;
 
     if (key != NULL && keymgmt != NULL)
-        return evp_keymgmt_validate_pairwise(keymgmt, key);
+        return evp_keymgmt_validate(keymgmt, key, OSSL_KEYMGMT_SELECT_KEYPAIR);
     /* not supported for legacy keys */
     return -2;
 }
@@ -133,14 +136,11 @@ int EVP_PKEY_check(EVP_PKEY_CTX *ctx)
     }
 
     keymgmt = pkey->pkeys[0].keymgmt;
-    key = pkey->pkeys[0].provdata;
+    key = pkey->pkeys[0].keydata;
+
+    if (key != NULL && keymgmt != NULL)
+        return evp_keymgmt_validate(keymgmt, key, OSSL_KEYMGMT_SELECT_ALL);
 
-    if (key != NULL && keymgmt != NULL) {
-        return evp_keymgmt_validate_domparams(keymgmt, key)
-               && evp_keymgmt_validate_public(keymgmt, key)
-               && evp_keymgmt_validate_private(keymgmt, key)
-               && evp_keymgmt_validate_pairwise(keymgmt, key);
-    }
     /* legacy */
     /* call customized check function first */
     if (ctx->pmeth->check != NULL)
diff --git a/crypto/evp/pmeth_fn.c b/crypto/evp/pmeth_fn.c
index 34cde67668..0b5af8e136 100644
--- a/crypto/evp/pmeth_fn.c
+++ b/crypto/evp/pmeth_fn.c
@@ -44,7 +44,7 @@ static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation)
     /* 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);
+                                     &tmp_keymgmt, ctx->propquery);
     if (provkey == NULL)
         goto legacy;
     if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) {
diff --git a/crypto/evp/pmeth_gn.c b/crypto/evp/pmeth_gn.c
index a093337e62..4bea1a1b86 100644
--- a/crypto/evp/pmeth_gn.c
+++ b/crypto/evp/pmeth_gn.c
@@ -208,7 +208,8 @@ int EVP_PKEY_key_fromdata_init(EVP_PKEY_CTX *ctx)
 
 int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, OSSL_PARAM params[])
 {
-    void *provdata = NULL;
+    void *keydata = NULL;
+    int selection;
 
     if (ctx == NULL || (ctx->operation & EVP_PKEY_OP_TYPE_FROMDATA) == 0) {
         ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
@@ -226,13 +227,16 @@ int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, OSSL_PARAM params[])
         return -1;
     }
 
-    provdata =
-        evp_keymgmt_fromdata(*ppkey, ctx->keymgmt, params,
-                             ctx->operation == EVP_PKEY_OP_PARAMFROMDATA);
+    if (ctx->operation == EVP_PKEY_OP_PARAMFROMDATA)
+        selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;
+    else
+        selection = OSSL_KEYMGMT_SELECT_KEYPAIR;
+    keydata = evp_keymgmt_util_fromdata(*ppkey, ctx->keymgmt, selection,
+                                        params);
 
-    if (provdata == NULL)
+    if (keydata == NULL)
         return 0;
-    /* provdata is cached in *ppkey, so we need not bother with it further */
+    /* keydata is cached in *ppkey, so we need not bother with it further */
     return 1;
 }
 
@@ -247,7 +251,8 @@ const OSSL_PARAM *EVP_PKEY_param_fromdata_settable(EVP_PKEY_CTX *ctx)
 {
     /* We call fromdata_init to get ctx->keymgmt populated */
     if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED))
-        return evp_keymgmt_importdomparam_types(ctx->keymgmt);
+        return evp_keymgmt_import_types(ctx->keymgmt,
+                                        OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
     return NULL;
 }
 
@@ -255,6 +260,7 @@ const OSSL_PARAM *EVP_PKEY_key_fromdata_settable(EVP_PKEY_CTX *ctx)
 {
     /* We call fromdata_init to get ctx->keymgmt populated */
     if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED))
-        return evp_keymgmt_importdomparam_types(ctx->keymgmt);
+        return evp_keymgmt_import_types(ctx->keymgmt,
+                                        OSSL_KEYMGMT_SELECT_KEYPAIR);
     return NULL;
 }
diff --git a/crypto/evp/signature.c b/crypto/evp/signature.c
index 7c6828b3b3..ca9d91efc5 100644
--- a/crypto/evp/signature.c
+++ b/crypto/evp/signature.c
@@ -345,7 +345,7 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation)
     /* 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);
+                                     &tmp_keymgmt, ctx->propquery);
     if (provkey == NULL)
         goto legacy;
     if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) {
diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c
index 485ac35a6f..a94cb54b5e 100644
--- a/crypto/rsa/rsa_ameth.c
+++ b/crypto/rsa/rsa_ameth.c
@@ -1074,40 +1074,42 @@ static size_t rsa_pkey_dirty_cnt(const EVP_PKEY *pkey)
 
 DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
 
-static void *rsa_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
-                                int want_domainparams)
+static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
+                              EVP_KEYMGMT *to_keymgmt)
 {
-    RSA *rsa = pk->pkey.rsa;
+    RSA *rsa = from->pkey.rsa;
     OSSL_PARAM_BLD tmpl;
     const BIGNUM *n = RSA_get0_n(rsa), *e = RSA_get0_e(rsa);
     const BIGNUM *d = RSA_get0_d(rsa);
     STACK_OF(BIGNUM_const) *primes = NULL, *exps = NULL, *coeffs = NULL;
     int numprimes = 0, numexps = 0, numcoeffs = 0;
     OSSL_PARAM *params = NULL;
-    void *provkey = NULL;
+    int rv = 0;
 
-    /*
-     * There are no domain parameters for RSA keys, or rather, they are
-     * included in the key data itself.
-     */
-    if (want_domainparams)
+    /* Public parameters must always be present */
+    if (n == NULL || e == NULL)
         goto err;
 
-    /* Get all the primes and CRT params */
-    if ((primes = sk_BIGNUM_const_new_null()) == NULL
-        || (exps = sk_BIGNUM_const_new_null()) == NULL
-        || (coeffs = sk_BIGNUM_const_new_null()) == NULL)
-        goto err;
+    ossl_param_bld_init(&tmpl);
 
-    if (!rsa_get0_all_params(rsa, primes, exps, coeffs))
+    /* |e| and |n| are always present */
+    if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_E, e))
         goto err;
-
-    /* Public parameters must always be present */
-    if (n == NULL || e == NULL)
+    if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_N, n))
         goto err;
 
     if (d != NULL) {
-        /* It's a private key, so we should have everything else too */
+        int i;
+
+        /* Get all the primes and CRT params */
+        if ((primes = sk_BIGNUM_const_new_null()) == NULL
+            || (exps = sk_BIGNUM_const_new_null()) == NULL
+            || (coeffs = sk_BIGNUM_const_new_null()) == NULL)
+            goto err;
+
+        if (!rsa_get0_all_params(rsa, primes, exps, coeffs))
+            goto err;
+
         numprimes = sk_BIGNUM_const_num(primes);
         numexps = sk_BIGNUM_const_num(exps);
         numcoeffs = sk_BIGNUM_const_num(coeffs);
@@ -1120,15 +1122,6 @@ static void *rsa_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
                          + numprimes + numexps + numcoeffs
                          <= OSSL_PARAM_BLD_MAX))
             goto err;
-    }
-
-    ossl_param_bld_init(&tmpl);
-    if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_N, n)
-        || !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_E, e))
-        goto err;
-
-    if (d != NULL) {
-        int i;
 
         if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_D, d))
             goto err;
@@ -1162,14 +1155,15 @@ static void *rsa_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
         goto err;
 
     /* We export, the provider imports */
-    provkey = evp_keymgmt_importkey(keymgmt, params);
+    rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL,
+                            params);
 
  err:
     sk_BIGNUM_const_free(primes);
     sk_BIGNUM_const_free(exps);
     sk_BIGNUM_const_free(coeffs);
     ossl_param_bld_free(params);
-    return provkey;
+    return rv;
 }
 
 const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = {
diff --git a/crypto/serializer/serializer_local.h b/crypto/serializer/serializer_local.h
index 9ee0eb8244..7a66472f51 100644
--- a/crypto/serializer/serializer_local.h
+++ b/crypto/serializer/serializer_local.h
@@ -32,6 +32,8 @@ struct ossl_serializer_ctx_st {
     OSSL_SERIALIZER *ser;
     void *serctx;
 
+    int selection;
+
     /*
      * |object| is the libcrypto object to handle.
      * |do_output| must have intimate knowledge of this object.
diff --git a/crypto/serializer/serializer_pkey.c b/crypto/serializer/serializer_pkey.c
index d3c3362f66..3b0cc3ac86 100644
--- a/crypto/serializer/serializer_pkey.c
+++ b/crypto/serializer/serializer_pkey.c
@@ -96,13 +96,6 @@ struct selected_serializer_st {
     const OSSL_PROVIDER *desired_provider;
     const char *propquery;
 
-    /*
-     * When selecting serializers, we need to check the intended use.
-     * This is governed by the |domainparams| flag in the EVP_PKEY,
-     * we must just make sure to filter on 'type=domainparams' accordingly.
-     */
-    int want_domainparams;
-
     /*
      * Serializers offer two functions, one that handles object data in
      * the form of a OSSL_PARAM array, and one that directly handles a
@@ -122,36 +115,12 @@ static void select_serializer(const char *name, void *data)
 {
     struct selected_serializer_st *d = data;
     OSSL_SERIALIZER *s = NULL;
-    OSSL_PROPERTY_LIST *check =
-        d->want_domainparams
-        ? ossl_parse_query(d->libctx, "type=domainparams")
-        : NULL;
 
     /* No need to look further if we already have the more desirable option */
     if (d->desired != NULL)
         return;
 
     if ((s = OSSL_SERIALIZER_fetch(d->libctx, name, d->propquery)) != NULL) {
-        /*
-         * Extra check if domain parameters are explicitly specified:
-         * only accept serializers that have the "type=domainparams"
-         * property.
-         *
-         * For data that isn't marked as domain parameters, a domain
-         * parameters serializer is still acceptable, because a key
-         * may hold domain parameters too.
-         */
-        if (d->want_domainparams) {
-            OSSL_PROPERTY_LIST *current_props =
-                ossl_parse_property(d->libctx, OSSL_SERIALIZER_properties(s));
-            int check_cnt = ossl_property_match_count(check, current_props);
-
-            if (check_cnt == 0) {
-                OSSL_SERIALIZER_free(s);
-                return;
-            }
-        }
-
         if (d->first == NULL && s->serialize_data != NULL) {
             d->first = s;
         } else if (OSSL_SERIALIZER_provider(s) == d->desired_provider
@@ -298,8 +267,7 @@ static int serializer_write_cb(const OSSL_PARAM params[], void *arg)
 static int serializer_EVP_PKEY_to_bio(OSSL_SERIALIZER_CTX *ctx, BIO *out)
 {
     const EVP_PKEY *pkey = ctx->object;
-    void *provdata = pkey->pkeys[0].provdata;
-    int domainparams = pkey->pkeys[0].domainparams;
+    void *keydata = pkey->pkeys[0].keydata;
     EVP_KEYMGMT *keymgmt = pkey->pkeys[0].keymgmt;
 
     /*
@@ -319,15 +287,11 @@ static int serializer_EVP_PKEY_to_bio(OSSL_SERIALIZER_CTX *ctx, BIO *out)
         write_data.ctx = ctx;
         write_data.out = out;
 
-        if (domainparams)
-            return evp_keymgmt_exportdomparams(keymgmt, provdata,
-                                               serializer_write_cb,
-                                               &write_data);
-        return evp_keymgmt_exportkey(keymgmt, provdata,
-                                     serializer_write_cb, &write_data);
+        return evp_keymgmt_export(keymgmt, keydata, ctx->selection,
+                                  &serializer_write_cb, &write_data);
     }
 
-    return ctx->ser->serialize_object(ctx->serctx, provdata, out,
+    return ctx->ser->serialize_object(ctx->serctx, keydata, out,
                                       serializer_passphrase_out_cb, ctx);
 }
 
@@ -343,6 +307,7 @@ OSSL_SERIALIZER_CTX *OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(const EVP_PKEY *pkey,
     OSSL_SERIALIZER_CTX *ctx = NULL;
     OSSL_SERIALIZER *ser = NULL;
     EVP_KEYMGMT *keymgmt = pkey->pkeys[0].keymgmt;
+    int selection = OSSL_KEYMGMT_SELECT_ALL;
 
     if (!ossl_assert(pkey != NULL && propquery != NULL)) {
         ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER);
@@ -353,12 +318,14 @@ OSSL_SERIALIZER_CTX *OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(const EVP_PKEY *pkey,
         const OSSL_PROVIDER *desired_prov = EVP_KEYMGMT_provider(keymgmt);
         OPENSSL_CTX *libctx = ossl_provider_library_context(desired_prov);
         struct selected_serializer_st sel_data;
+        OSSL_PROPERTY_LIST *check =
+            ossl_parse_query(libctx, "type=parameters");
+        OSSL_PROPERTY_LIST *current_props = NULL;
 
         memset(&sel_data, 0, sizeof(sel_data));
         sel_data.libctx = libctx;
         sel_data.desired_provider = desired_prov;
         sel_data.propquery = propquery;
-        sel_data.want_domainparams = pkey->pkeys[0].domainparams;
         EVP_KEYMGMT_names_do_all(keymgmt, select_serializer, &sel_data);
 
         if (sel_data.desired != NULL) {
@@ -370,6 +337,14 @@ OSSL_SERIALIZER_CTX *OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(const EVP_PKEY *pkey,
         }
         OSSL_SERIALIZER_free(sel_data.first);
         OSSL_SERIALIZER_free(sel_data.desired);
+
+        current_props =
+            ossl_parse_property(libctx, OSSL_SERIALIZER_properties(ser));
+        if (ossl_property_match_count(check, current_props) > 0)
+            selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;
+
+        ossl_property_free(current_props);
+        ossl_property_free(check);
     }
 
     ctx = OSSL_SERIALIZER_CTX_new(ser); /* refcnt(ser)++ */
@@ -377,6 +352,7 @@ OSSL_SERIALIZER_CTX *OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(const EVP_PKEY *pkey,
 
     if (ctx != NULL) {
         /* Setup for OSSL_SERIALIZE_to_bio() */
+        ctx->selection = selection;
         ctx->object = pkey;
         ctx->do_output = serializer_EVP_PKEY_to_bio;
     }
diff --git a/doc/internal/man3/evp_keymgmt_export_to_provider.pod b/doc/internal/man3/evp_keymgmt_export_to_provider.pod
deleted file mode 100644
index 2cb40940b4..0000000000
--- a/doc/internal/man3/evp_keymgmt_export_to_provider.pod
+++ /dev/null
@@ -1,56 +0,0 @@
-=pod
-
-=head1 NAME
-
-evp_keymgmt_export_to_provider,
-evp_keymgmt_clear_pkey_cache
-- key material provider export for EVP
-
-=head1 SYNOPSIS
-
- #include "crypto/evp.h"
-
- void *evp_keymgmt_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt);
- void evp_keymgmt_clear_pkey_cache(EVP_PKEY *pk);
-
-=head1 DESCRIPTION
-
-evp_keymgmt_export_to_provider() exports the key material from the
-given key I<pk> to a provider via a B<EVP_KEYMGMT> interface, if this
-hasn't already been done.
-It maintains a cache of provider key references in I<pk> to keep track
-of all such exports.
-
-If I<pk> has an assigned legacy key, a check is done to see if any of
-its key material has changed since last export, i.e. the legacy key's
-is_dirty() method returns 1.
-If it has, the cache of already exported keys is cleared, and a new
-export is made with the new key material.
-
-evp_keymgmt_clear_pkey_cache() can be used to explicitly clear the
-cache of provider key references.
-
-=head1 RETURN VALUES
-
-evp_keymgmt_export_to_provider() returns a pointer to the appropriate
-provider side key (created or found again), or NULL on error.
-
-=head1 NOTES
-
-"Legacy key" is the term used for any key that has been assigned to an
-B<EVP_PKEY> with EVP_PKEY_assign_RSA() and similar functions.
-
-=head1 SEE ALSO
-
-L<EVP_PKEY_ASN1_METHOD(3)>, L<EVP_PKEY_assign_RSA(3)>
-
-=head1 COPYRIGHT
-
-Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the Apache License 2.0 (the "License").  You may not use
-this file except in compliance with the License.  You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/internal/man3/evp_keymgmt_freekey.pod b/doc/internal/man3/evp_keymgmt_freekey.pod
deleted file mode 100644
index 8be73aee81..0000000000
--- a/doc/internal/man3/evp_keymgmt_freekey.pod
+++ /dev/null
@@ -1,109 +0,0 @@
-=pod
-
-=head1 NAME
-
-evp_keymgmt_importdomparams, evp_keymgmt_gendomparams,
-evp_keymgmt_freedomparams,
-evp_keymgmt_exportdomparams,
-evp_keymgmt_importdomparams_types, evp_keymgmt_exportdomparams_types,
-evp_keymgmt_importkey, evp_keymgmt_genkey, evp_keymgmt_loadkey,
-evp_keymgmt_freekey,
-evp_keymgmt_exportkey,
-evp_keymgmt_importkey_types, evp_keymgmt_exportkey_types
-- internal KEYMGMT support functions
-
-=head1 SYNOPSIS
-
- #include "crypto/evp.h"
-
- void *evp_keymgmt_importdomparams(const EVP_KEYMGMT *keymgmt,
-                                const OSSL_PARAM params[]);
- void *evp_keymgmt_gendomparams(const EVP_KEYMGMT *keymgmt,
-                             const OSSL_PARAM params[]);
- void evp_keymgmt_freedomparams(const EVP_KEYMGMT *keymgmt, void *provdomparams);
- int evp_keymgmt_exportdomparams(const EVP_KEYMGMT *keymgmt,
-                              void *provdomparams, OSSL_PARAM params[]);
- const OSSL_PARAM *evp_keymgmt_importdomparams_types(const EVP_KEYMGMT *keymgmt);
- const OSSL_PARAM *evp_keymgmt_exportdomparams_types(const EVP_KEYMGMT *keymgmt);
-
- void *evp_keymgmt_importkey(const EVP_KEYMGMT *keymgmt,
-                             const OSSL_PARAM params[]);
- void *evp_keymgmt_genkey(const EVP_KEYMGMT *keymgmt, void *domparams,
-                          const OSSL_PARAM params[]);
- void *evp_keymgmt_loadkey(const EVP_KEYMGMT *keymgmt,
-                           void *id, size_t idlen);
- void evp_keymgmt_freekey(const EVP_KEYMGMT *keymgmt, void *provkey);
- int evp_keymgmt_exportkey(const EVP_KEYMGMT *keymgmt, void *provkey,
-                           OSSL_PARAM params[]);
- const OSSL_PARAM *evp_keymgmt_importkey_types(const EVP_KEYMGMT *keymgmt);
- const OSSL_PARAM *evp_keymgmt_exportkey_types(const EVP_KEYMGMT *keymgmt);
-
-=head1 DESCRIPTION
-
-All these functions are helpers to call the provider's corresponding
-function.
-
-evp_keymgmt_importdomparams() calls the method's importdomparams() function.
-
-evp_keymgmt_gendomparams() calls the method's gendomparams() function.
-
-evp_keymgmt_freedomparams() calls the method's freedomparams() function.
-
-evp_keymgmt_exportdomparams() calls the method's exportdomparams()
-function.
-
-evp_keymgmt_importdomparams_types() calls the method's
-importdomparams_types() function.
-
-evp_keymgmt_exportdomparams_types() calls the method's
-exportdomparams_types() function.
-
-evp_keymgmt_importkey() calls the method's importkey()
-function.
-
-evp_keymgmt_genkey() calls the method's genkey() function.
-
-evp_keymgmt_loadkey() calls the method's loadkey() function.
-
-evp_keymgmt_freekey() calls the method's freekey() function.
-
-evp_keymgmt_exportkey() calls the method's exportkey()
-function.
-
-evp_keymgmt_importkey_types() calls the method's importkey_types() function.
-
-evp_keymgmt_exportkey_types() calls the method's exportkey_types() function.
-
-=head1 RETURN VALUES
-
-evp_keymgmt_importdomparams(), evp_keymgmt_gendomparams() return a pointer
-to a provider owned set of domparams parameters, or NULL on error.
-
-evp_keymgmt_importkey(), evp_keymgmt_genkey(), evp_keymgmt_loadkey() return
-a pointer to a provider owned key, or NULL on error.
-
-evp_keymgmt_exportdomparams() and evp_keymgmt_exportkey() return 1 on success,
-or 0 on error.
-
-evp_keymgmt_importdomparams_types(), evp_keymgmt_exportdomparams_types()
-return parameter descriptor for importing and exporting domparams
-parameters, or NULL if there are no such descriptors.
-
-evp_keymgmt_importkey_types() and evp_keymgmt_exportkey_types()
-return parameter descriptor for importing and exporting keys, or NULL
-if there are no such descriptors.
-
-=head1 HISTORY
-
-The functions described here were all added in OpenSSL 3.0.
-
-=head1 COPYRIGHT
-
-Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the Apache License 2.0 (the "License").  You may not use
-this file except in compliance with the License.  You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/internal/man3/evp_keymgmt_newdata.pod b/doc/internal/man3/evp_keymgmt_newdata.pod
new file mode 100644
index 0000000000..861f57f7f5
--- /dev/null
+++ b/doc/internal/man3/evp_keymgmt_newdata.pod
@@ -0,0 +1,93 @@
+=pod
+
+=head1 NAME
+
+evp_keymgmt_newdata, evp_keymgmt_freedata,
+evp_keymgmt_get_params, evp_keymgmt_gettable_params,
+evp_keymgmt_has, evp_keymgmt_validate,
+evp_keymgmt_import, evp_keymgmt_import_types,
+evp_keymgmt_export, evp_keymgmt_export_types
+- internal KEYMGMT interface functions
+
+=head1 SYNOPSIS
+
+ #include "crypto/evp.h"
+
+ void *evp_keymgmt_newdata(const EVP_KEYMGMT *keymgmt);
+ void evp_keymgmt_freedata(const EVP_KEYMGMT *keymgmt, void *keyddata);
+ int evp_keymgmt_get_params(const EVP_KEYMGMT *keymgmt,
+                            void *keydata, OSSL_PARAM params[]);
+ const OSSL_PARAM *evp_keymgmt_gettable_params(const EVP_KEYMGMT *keymgmt);
+ 
+ 
+ int evp_keymgmt_has(const EVP_KEYMGMT *keymgmt, void *keyddata, int selection);
+ int evp_keymgmt_validate(const EVP_KEYMGMT *keymgmt, void *keydata,
+                          int selection);
+ 
+ int evp_keymgmt_import(const EVP_KEYMGMT *keymgmt, void *keydata,
+                        int selection, const OSSL_PARAM params[]);
+ const OSSL_PARAM *evp_keymgmt_import_types(const EVP_KEYMGMT *keymgmt,
+                                            int selection);
+ int evp_keymgmt_export(const EVP_KEYMGMT *keymgmt, void *keydata,
+                        int selection, OSSL_CALLBACK *param_cb, void *cbarg);
+ const OSSL_PARAM *evp_keymgmt_export_types(const EVP_KEYMGMT *keymgmt,
+                                            int selection);
+
+=head1 DESCRIPTION
+
+All these functions are helpers to call the provider's corresponding
+function.  They all have in common that they take a B<EVP_KEYMGMT> as
+first argument, which they also retrieve a provider context from when
+needed.  The rest of the arguments are simply passed on to the
+function they wrap around.
+
+evp_keymgmt_newdata() calls the method's new() function.
+
+evp_keymgmt_freedata() calls the method's free() function.
+
+(the name evp_keymgmt_freedata() was chosen to avoid a clash with
+EVP_KEYMGMT_free() on case insensitive systems, the name
+evp_keymgmt_newdata() was chosen for consistency)
+
+evp_keymgmt_get_params() calls the method's get_params() function.
+
+evp_keymgmt_gettable_params() calls the method's gettable_params()
+function.
+
+evp_keymgmt_has() calls the method's has() function.
+
+evp_keymgmt_validate() calls the method's validate() function.
+
+evp_keymgmt_import() calls the method's import() function.
+
+evp_keymgmt_import_types() calls the method's import_types() function.
+
+evp_keymgmt_export() calls the method's export() function.
+
+evp_keymgmt_export_types() calls the method's export_types() function.
+
+=head1 RETURN VALUES
+
+evp_keymgmt_newdata() returns a pointer to a provider side key object,
+or NULL on error.
+
+evp_keymgmt_gettable_params(), evp_keymgmt_import_types(), and
+evp_keymgmt_export_types() return parameter descriptor for importing
+and exporting key data, or NULL if there are no such descriptors.
+
+All other functions return 1 on success and 0 on error.
+
+=head1 HISTORY
+
+The functions described here were all added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/evp_keymgmt_util_export_to_provider.pod b/doc/internal/man3/evp_keymgmt_util_export_to_provider.pod
new file mode 100644
index 0000000000..38e71334c8
--- /dev/null
+++ b/doc/internal/man3/evp_keymgmt_util_export_to_provider.pod
@@ -0,0 +1,71 @@
+=pod
+
+=head1 NAME
+
+evp_keymgmt_util_export_to_provider,
+evp_keymgmt_util_clear_pkey_cache,
+evp_keymgmt_util_cache_pkey,
+evp_keymgmt_util_fromdata
+- internal KEYMGMT utility functions
+
+=head1 SYNOPSIS
+
+ #include "crypto/evp.h"
+
+ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt);
+ void evp_keymgmt_util_clear_pkey_cache(EVP_PKEY *pk);
+ void evp_keymgmt_util_cache_pkey(EVP_PKEY *pk, size_t index,
+                                  EVP_KEYMGMT *keymgmt, void *keydata);
+ void *evp_keymgmt_util_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
+                                 int selection, const OSSL_PARAM params[]);
+
+=head1 DESCRIPTION
+
+evp_keymgmt_util_export_to_provider() exports the key material from
+the given key I<pk> to a provider via a B<EVP_KEYMGMT> interface, if
+this hasn't already been done.
+It maintains a cache of provider key references in I<pk> to keep track
+of all such exports.
+
+If I<pk> has an assigned legacy key, a check is done to see if any of
+its key material has changed since last export, i.e. the legacy key's
+is_dirty() method returns 1.
+If it has, the cache of already exported keys is cleared, and a new
+export is made with the new key material.
+
+evp_keymgmt_util_clear_pkey_cache() can be used to explicitly clear
+the cache of provider key references.
+
+evp_keymgmt_util_cache_pkey() can be used to assign a provider key
+object to a specific cache slot in the given I<target>.
+I<Use with extreme care>.
+
+evp_keymgmt_util_fromdata() can be used to add key object data to a
+given key I<target> via a B<EVP_KEYMGMT> interface.  This is used as a
+helper for L<EVP_PKEY_fromdata(3)>.
+
+=head1 RETURN VALUES
+
+evp_keymgmt_export_to_provider() and evp_keymgmt_util_fromdata()
+return a pointer to the appropriate provider side key (created or
+found again), or NULL on error.
+
+=head1 NOTES
+
+"Legacy key" is the term used for any key that has been assigned to an
+B<EVP_PKEY> with EVP_PKEY_assign_RSA() and similar functions.
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_ASN1_METHOD(3)>, L<EVP_PKEY_assign_RSA(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/evp_pkey_make_provided.pod b/doc/internal/man3/evp_pkey_make_provided.pod
index e5dde78c4f..12cbe0c365 100644
--- a/doc/internal/man3/evp_pkey_make_provided.pod
+++ b/doc/internal/man3/evp_pkey_make_provided.pod
@@ -10,8 +10,7 @@ evp_pkey_make_provided - internal EVP_PKEY support functions for providers
  #include "evp_local.h"
 
  void *evp_pkey_make_provided(EVP_PKEY *pk, OPENSSL_CTX *libctx,
-                              EVP_KEYMGMT **keymgmt, const char *propquery,
-                              int domainparams);
+                              EVP_KEYMGMT **keymgmt, const char *propquery);
 
 =head1 DESCRIPTION
 
@@ -24,8 +23,6 @@ used for exporting.  If not (I<*keymgmt> is NULL), then this function will
 fetch an B<EVP_KEYMGMT> implicitly, using I<propquery> as property query string.
 As output from this function, I<*keymgmt> will be assigned the B<EVP_KEYMGMT>
 that was used, if the export was successful, otherwise it will be assigned NULL.
-I<domainparams> decides if I<pk> should be considered domain parameters or the
-actual key.
 
 =head1 RETURN VALUES
 
diff --git a/doc/man3/EVP_PKEY_check.pod b/doc/man3/EVP_PKEY_check.pod
index 95b57a3fb8..2398b61b64 100644
--- a/doc/man3/EVP_PKEY_check.pod
+++ b/doc/man3/EVP_PKEY_check.pod
@@ -18,7 +18,7 @@ EVP_PKEY_private_check, EVP_PKEY_pairwise_check
 
 =head1 DESCRIPTION
 
-EVP_PKEY_param_check() validates the domain parameters component of the key
+EVP_PKEY_param_check() validates the parameters component of the key
 given by B<ctx>.
 
 EVP_PKEY_public_check() validates the public component of the key given by B<ctx>.
diff --git a/doc/man3/EVP_PKEY_fromdata.pod b/doc/man3/EVP_PKEY_fromdata.pod
index 0e3dc5c29f..ed8c668e90 100644
--- a/doc/man3/EVP_PKEY_fromdata.pod
+++ b/doc/man3/EVP_PKEY_fromdata.pod
@@ -4,7 +4,7 @@
 
 EVP_PKEY_param_fromdata_init, EVP_PKEY_key_fromdata_init, EVP_PKEY_fromdata,
 EVP_PKEY_param_fromdata_settable, EVP_PKEY_key_fromdata_settable
-- functions to create domain parameters and keys from user data
+- functions to create key parameters and keys from user data
 
 =head1 SYNOPSIS
 
@@ -19,12 +19,12 @@ EVP_PKEY_param_fromdata_settable, EVP_PKEY_key_fromdata_settable
 =head1 DESCRIPTION
 
 EVP_PKEY_param_fromdata_init() initializes a public key algorithm context
-for creating domain parameters from user data.
+for creating key parameters from user data.
 
 EVP_PKEY_key_fromdata_init() initializes a public key algorithm context for
 creating a key from user data.
 
-EVP_PKEY_fromdata() creates domain parameters or a key, given data from
+EVP_PKEY_fromdata() creates key parameters or a key, given data from
 I<params> and a context that's been initialized with
 EVP_PKEY_param_fromdata_init() or EVP_PKEY_key_fromdata_init().  The result is
 written to I<*ppkey>.
diff --git a/doc/man3/OSSL_SERIALIZER_CTX_new_by_EVP_PKEY.pod b/doc/man3/OSSL_SERIALIZER_CTX_new_by_EVP_PKEY.pod
index caa9294bcc..8cc7cfbf30 100644
--- a/doc/man3/OSSL_SERIALIZER_CTX_new_by_EVP_PKEY.pod
+++ b/doc/man3/OSSL_SERIALIZER_CTX_new_by_EVP_PKEY.pod
@@ -36,11 +36,11 @@ OSSL_SERIALIZER_Parameters_TO_TEXT_PQ
 
  #define OSSL_SERIALIZER_PUBKEY_TO_PEM_PQ "format=pem,type=public"
  #define OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ "format=pem,type=private"
- #define OSSL_SERIALIZER_Parameters_TO_PEM_PQ "format=pem,type=domainparams"
+ #define OSSL_SERIALIZER_Parameters_TO_PEM_PQ "format=pem,type=parameters"
 
  #define OSSL_SERIALIZER_PUBKEY_TO_TEXT_PQ "format=text,type=public"
  #define OSSL_SERIALIZER_PrivateKey_TO_TEXT_PQ "format=text,type=private"
- #define OSSL_SERIALIZER_Parameters_TO_TEXT_PQ "format=text,type=domainparams"
+ #define OSSL_SERIALIZER_Parameters_TO_TEXT_PQ "format=text,type=parameters"
 
 =head1 DESCRIPTION
 
diff --git a/doc/man3/d2i_PrivateKey.pod b/doc/man3/d2i_PrivateKey.pod
index dc3618eb53..4b7a326c0d 100644
--- a/doc/man3/d2i_PrivateKey.pod
+++ b/doc/man3/d2i_PrivateKey.pod
@@ -36,7 +36,7 @@ use any key specific format or PKCS#8 unencrypted PrivateKeyInfo format. The
 B<type> parameter should be a public key algorithm constant such as
 B<EVP_PKEY_RSA>. An error occurs if the decoded key does not match B<type>.
 d2i_PublicKey() does the same for public keys.
-d2i_KeyParams() does the same for domain parameter keys.
+d2i_KeyParams() does the same for key parameters.
 
 d2i_AutoPrivateKey() is similar to d2i_PrivateKey() except it attempts to
 automatically detect the private key format.
@@ -44,7 +44,7 @@ automatically detect the private key format.
 i2d_PrivateKey() encodes B<key>. It uses a key specific format or, if none is
 defined for that key type, PKCS#8 unencrypted PrivateKeyInfo format.
 i2d_PublicKey() does the same for public keys.
-i2d_KeyParams() does the same for domain parameter keys.
+i2d_KeyParams() does the same for key parameters.
 These functions are similar to the d2i_X509() functions; see L<d2i_X509(3)>.
 
 =head1 NOTES
diff --git a/doc/man7/provider-keymgmt.pod b/doc/man7/provider-keymgmt.pod
index 94427de89f..e9e4de5622 100644
--- a/doc/man7/provider-keymgmt.pod
+++ b/doc/man7/provider-keymgmt.pod
@@ -14,47 +14,29 @@ provider-keymgmt - The KEYMGMT library E<lt>-E<gt> provider functions
   * pointers in OSSL_DISPATCH arrays.
   */
 
- /* Key domain parameter creation and destruction */
- void *OP_keymgmt_importdomparams(void *provctx, const OSSL_PARAM params[]);
- void *OP_keymgmt_gendomparams(void *provctx, const OSSL_PARAM params[]);
- void OP_keymgmt_freedomparams(void *domparams);
+ /* Key object (keydata) creation and destruction */
+ void *OP_keymgmt_new(void *provctx);
+ void OP_keymgmt_free(void *keydata);
 
- /* Key domain parameter export */
- int OP_keymgmt_exportdomparams(void *domparams, OSSL_PARAM params[]);
+ /* Key object information */
+ int OP_keymgmt_get_params(void *keydata, OSSL_PARAM params[]);
+ const OSSL_PARAM *OP_keymgmt_gettable_params(void);
 
- /* Key domain parameter discovery */
- const OSSL_PARAM *OP_keymgmt_importdomparam_types(void);
- const OSSL_PARAM *OP_keymgmt_exportdomparam_types(void);
+ /* Key object content checks */
+ int OP_keymgmt_has(void *keydata, int selection);
 
- /* Key domain parameter information */
- int OP_keymgmt_get_domparam_params(void *domparams, OSSL_PARAM params[]);
- const OSSL_PARAM *OP_keymgmt_gettable_domparam_params(void);
-
- /* Key domain parameter validation */
- int OP_keymgmt_validate_domparams(void *key);
-
- /* Key creation and destruction */
- void *OP_keymgmt_importkey(void *provctx, const OSSL_PARAM params[]);
- void *OP_keymgmt_genkey(void *provctx,
-                         void *domparams, const OSSL_PARAM genkeyparams[]);
- void *OP_keymgmt_loadkey(void *provctx, void *id, size_t idlen);
- void OP_keymgmt_freekey(void *key);
-
- /* Key export */
- int OP_keymgmt_exportkey(void *key, OSSL_PARAM params[]);
-
- /* Key discovery */
- const OSSL_PARAM *OP_keymgmt_importkey_types(void);
- const OSSL_PARAM *OP_keymgmt_exportkey_types(void);
+ /* Discovery of supported operations */
+ const char *OP_keymgmt_query_operation_name(int operation_id);
 
- /* Key information */
- int OP_keymgmt_get_key_params(void *key, OSSL_PARAM params[]);
- const OSSL_PARAM *OP_keymgmt_gettable_key_params(void);
+ /* Key object import and export functions */
+ int OP_keymgmt_import(int selection, void *keydata, const OSSL_PARAM params[]);
+ const OSSL_PARAM *OP_keymgmt_import_types, (int selection);
+ int OP_keymgmt_export(int selection, void *keydata,
+                       OSSL_CALLBACK *param_cb, void *cbarg);
+ const OSSL_PARAM *OP_keymgmt_export_types(int selection);
 
- /* Key validation */
- int OP_keymgmt_validate_public(void *key);
- int OP_keymgmt_validate_private(void *key);
- int OP_keymgmt_validate_pairwise(void *key);
+ /* Key object validation */
+ int OP_keymgmt_validate(void *keydata, int selection);
 
  /* Discovery of supported operations */
  const char *OP_keymgmt_query_operation_name(int operation_id);
@@ -70,8 +52,7 @@ works with in tandem, they must belong to the same provider.
 The OpenSSL libraries will ensure that they do.
 
 The primary responsibility of the KEYMGMT operation is to hold the
-provider side domain parameters and keys for the OpenSSL library
-EVP_PKEY structure.
+provider side key data for the OpenSSL library EVP_PKEY structure.
 
 All "functions" mentioned here are passed as function pointers between
 F<libcrypto> and the provider in B<OSSL_DISPATCH> arrays via
@@ -83,133 +64,147 @@ All these "functions" have a corresponding function type definition
 named B<OSSL_{name}_fn>, and a helper function to retrieve the
 function pointer from a B<OSSL_DISPATCH> element named
 B<OSSL_get_{name}>.
-For example, the "function" OP_keymgmt_importdomparams() has these:
+For example, the "function" OP_keymgmt_new() has these:
 
- typedef void *
-     (OSSL_OP_keymgmt_importdomparams_fn)(void *provctx,
-                                          const OSSL_PARAM params[]);
- static ossl_inline OSSL_OP_keymgmt_importdomparams_fn
-     OSSL_get_OP_keymgmt_importdomparams(const OSSL_DISPATCH *opf);
+ typedef void *(OSSL_OP_keymgmt_new_fn)(void *provctx);
+ static ossl_inline OSSL_OP_keymgmt_new_fn
+     OSSL_get_OP_keymgmt_new(const OSSL_DISPATCH *opf);
 
 B<OSSL_DISPATCH> arrays are indexed by numbers that are provided as
 macros in L<openssl-core_numbers.h(7)>, as follows:
 
- OP_keymgmt_importdomparams      OSSL_FUNC_KEYMGMT_IMPORTDOMPARAMS
- OP_keymgmt_gendomparams         OSSL_FUNC_KEYMGMT_GENDOMPARAMS
- OP_keymgmt_freedomparams        OSSL_FUNC_KEYMGMT_FREEDOMPARAMS
- OP_keymgmt_exportdomparams      OSSL_FUNC_KEYMGMT_EXPORTDOMPARAMS
- OP_keymgmt_importdomparam_types OSSL_FUNC_KEYMGMT_IMPORTDOMPARAM_TYPES
- OP_keymgmt_exportdomparam_types OSSL_FUNC_KEYMGMT_EXPORTDOMPARAM_TYPES
- OP_keymgmt_get_domparam_params  OSSL_FUNC_KEYMGMT_GET_DOMPARAM_PARAMS
- OP_keymgmt_gettable_domparam_params
-                                 OSSL_FUNC_KEYMGMT_GETTABLE_DOMPARAM_PARAMS
-
- OP_keymgmt_importkey            OSSL_FUNC_KEYMGMT_IMPORTKEY
- OP_keymgmt_genkey               OSSL_FUNC_KEYMGMT_GENKEY
- OP_keymgmt_loadkey              OSSL_FUNC_KEYMGMT_LOADKEY
- OP_keymgmt_freekey              OSSL_FUNC_KEYMGMT_FREEKEY
- OP_keymgmt_exportkey            OSSL_FUNC_KEYMGMT_EXPORTKEY
- OP_keymgmt_importkey_types      OSSL_FUNC_KEYMGMT_IMPORTKEY_TYPES
- OP_keymgmt_exportkey_types      OSSL_FUNC_KEYMGMT_EXPORTKEY_TYPES
- OP_keymgmt_get_key_params       OSSL_FUNC_KEYMGMT_GET_KEY_PARAMS
- OP_keymgmt_gettable_key_params  OSSL_FUNC_KEYMGMT_GETTABLE_KEY_PARAMS
+ OP_keymgmt_new                  OSSL_FUNC_KEYMGMT_NEW
+ OP_keymgmt_free                 OSSL_FUNC_KEYMGMT_FREE
+
+ OP_keymgmt_get_params           OSSL_FUNC_KEYMGMT_GET_PARAMS
+ OP_keymgmt_gettable_params      OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS
 
  OP_keymgmt_query_operation_name OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME
 
- OP_keymgmt_validate_domparams   OSSL_FUNC_KEYMGMT_VALIDATE_DOMPARAMS
- OP_keymgmt_validate_public      OSSL_FUNC_KEYMGMT_VALIDATE_PUBLIC
- OP_keymgmt_validate_private     OSSL_FUNC_KEYMGMT_VALIDATE_PRIVATE
- OP_keymgmt_validate_pairwise    OSSL_FUNC_KEYMGMT_VALIDATE_PAIRWISE
+ OP_keymgmt_has                  OSSL_FUNC_KEYMGMT_HAS
+ OP_keymgmt_validate             OSSL_FUNC_KEYMGMT_VALIDATE
 
-=head2 Domain Parameter Functions
+ OP_keymgmt_import               OSSL_FUNC_KEYMGMT_IMPORT
+ OP_keymgmt_import_types         OSSL_FUNC_KEYMGMT_IMPORT_TYPES
+ OP_keymgmt_export               OSSL_FUNC_KEYMGMT_EXPORT
+ OP_keymgmt_export_types         OSSL_FUNC_KEYMGMT_EXPORT_TYPES
 
-OP_keymgmt_importdomparams() should create a provider side structure
-for domain parameters, with values taken from the passed B<OSSL_PARAM>
-array I<params>.
 
-OP_keymgmt_gendomparams() should generate domain parameters and create
-a provider side structure for them.
-Values of the passed B<OSSL_PARAM> array I<params> should be used as
-input for parameter generation.
+=head2 Key Objects
 
-OP_keymgmt_freedomparams() should free the passed provider side domain
-parameter structure I<domparams>.
+A key object is a collection of data for an asymmetric key, and is
+represented as I<keydata> in this manual.
 
-OP_keymgmt_exportdomparams() should extract values from the passed
-provider side domain parameter structure I<domparams> into the passed
-B<OSSL_PARAM> I<params>.
-Only the values specified in I<params> should be extracted.
+The exact contents of a key object are defined by the provider, and it
+is assumed that different operations in one and the same provider use
+the exact same structure to represent this collection of data, so that
+for example, a key object that has been created using the KEYMGMT
+interface that we document here can be passed as is to other provider
+operations, such as OP_signature_sign_init() (see
+L<provider-signature(7)>).
 
-OP_keymgmt_importdomparam_types() should return a constant array of
-descriptor B<OSSL_PARAM>, for parameters that OP_keymgmt_importdomparams()
-can handle.
+With some of the KEYMGMT functions, it's possible to select a specific
+subset of data to handle, governed by the bits in a I<selection>
+indicator.  The bits are:
+
+=over 4
 
-OP_keymgmt_exportdomparam_types() should return a constant array of
-descriptor B<OSSL_PARAM>, for parameters that can be exported with
-OP_keymgmt_exportdomparams().
+=item B<OSSL_KEYMGMT_SELECT_PRIVATE_KEY>
 
-OP_keymgmt_get_domparam_params() should extract information data
-associated with the given I<domparams>,
-see L</Information Parameters>.
+Indicating that the private key data in a key object should be
+considered.
 
-OP_keymgmt_gettable_domparam_params() should return a constant array
-of descriptor B<OSSL_PARAM>, for parameters that
-OP_keymgmt_get_domparam_params() can handle.
+=item B<OSSL_KEYMGMT_SELECT_PUBLIC_KEY>
 
-OP_keymgmt_validate_domparams() should return a value of 1 if the
-domain parameters are valid, or 0 for invalid.
+Indicating that the public key data in a key object should be
+considered.
 
-=head2 Key functions
+=item B<OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS>
 
-OP_keymgmt_importkey() should create a provider side structure
-for keys, with values taken from the passed B<OSSL_PARAM> array
-I<params>.
+Indicating that the domain parameters in a key object should be
+considered.
 
-OP_keymgmt_genkey() should generate keys and create a provider side
-structure for them.
-Values from the passed domain parameters I<domparams> as well as from
-the passed B<OSSL_PARAM> array I<params> should be used as input for
-key generation.
+=item B<OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS>
 
-OP_keymgmt_loadkey() should return a provider side key structure with
-a key loaded from a location known only to the provider, identitified
-with the identity I<id> of size I<idlen>.
-This identity is internal to the provider and is retrieved from the
-provider through other means.
+Indicating that other parameters in a key object should be
+considered.
 
-=for comment Right now, OP_keymgmt_loadkey is useless, but will be
-useful as soon as we have a OSSL_STORE interface
+Other parameters are key parameters that don't fit any other
+classification.  In other words, this particular selector bit works as
+a last resort bit bucket selector.
 
-OP_keymgmt_freekey() should free the passed I<key>.
+=back
 
-OP_keymgmt_exportkey() should extract values from the passed
-provider side key I<key> into the passed B<OSSL_PARAM> I<params>.
-Only the values specified in I<params> should be extracted.
+Some selector bits have also been combined for easier use:
 
-OP_keymgmt_importkey_types() should return a constant array of
-descriptor B<OSSL_PARAM>, for parameters that OP_keymgmt_importkey()
-can handle.
+=over 4
+
+=item B<OSSL_KEYMGMT_SELECT_ALL_PARAMETERS>
+
+Indicating that all key object parameters should be considered,
+regardless of their more granular classification.
 
-OP_keymgmt_exportkey_types() should return a constant array of
-descriptor B<OSSL_PARAM>, for parameters that can be exported with
-OP_keymgmt_exportkeys().
+=for comment This should used by EVP functions such as
+EVP_PKEY_copy_parameters() and EVP_PKEY_cmp_parameters()
 
-OP_keymgmt_get_key_params() should extract information data associated
-with the given I<key>, see L</Information Parameters>.
+This is a combination of B<OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS> and
+B<OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS>.
 
-OP_keymgmt_gettable_key_params() should return a constant array of
-descriptor B<OSSL_PARAM>, for parameters that
-OP_keymgmt_get_key_params() can handle.
+=for comment If more parameter categories are added, they should be
+mentioned here too.
 
-OP_keymgmt_validate_public() should return 1 if the public component of the
-key is valid, or 0 if invalid.
-OP_keymgmt_validate_private() should return 1 if the private component of the
-key is valid, or 0 if invalid.
-OP_keymgmt_validate_pairwise() should return 1 if the the pairwise consistency
-of the key is valid, or 0 if invalid.
+=item B<OSSL_KEYMGMT_SELECT_KEYPAIR>
 
+Indicating that both the whole key pair in a key object should be
+considered, i.e. the combination of public and private key.
+
+This is a combination of B<OSSL_KEYMGMT_SELECT_PRIVATE_KEY> and
+B<OSSL_KEYMGMT_SELECT_PUBLIC_KEY>.
+
+=item B<OSSL_KEYMGMT_SELECT_ALL>
+
+Indicating that everything in a key object should be considered.
+
+=back
 
-=head2 Supported operations
+The exact interpretation of those bits or how they combine is left to
+each function where you can specify a selector.
+
+=for comment One might think that a combination of bits means that all
+the selected data subsets must be considered, but then you have to
+consider that when comparing key objects (future function), an
+implementation might opt to not compare the private key if it has
+compared the public key, since a match of one half implies a match of
+the other half.
+
+=head2 Constructing and Destructing Functions
+
+OP_keymgmt_new() should create a provider side key object.  The
+provider context I<provctx> is passed and may be incorporated in the
+key object, but that is not mandatory.
+
+OP_keymgmt_free() should free the passed I<keydata>.
+
+The constructor and destructor are mandatory, a KEYMGMT implementation
+without them will not be accepted.
+
+=for comment when new constructors appear, it's sufficient if only one
+of them is present.  The remark above will have to change to reflect
+that.
+
+=head2 Key Object Information Functions
+
+OP_keymgmt_get_params() should extract information data associated
+with the given I<keydata>, see L</Information Parameters>.
+
+OP_keymgmt_gettable_params() should return a constant array of
+descriptor B<OSSL_PARAM>, for parameters that OP_keymgmt_get_params()
+can handle.
+
+If OP_keymgmt_gettable_params() is present, OP_keymgmt_get_params()
+must also be present.
+
+=head2 Key Object Checking Functions
 
 OP_keymgmt_query_operation_name() should return the name of the
 supported algorithm for the operation I<operation_id>.  This is
@@ -219,13 +214,43 @@ returns NULL, the caller is free to assume that there's an algorithm
 from the same provider, of the same name as the one used to fetch the
 keymgmt and try to use that.
 
+OP_keymgmt_has() should check whether the given I<keydata> the subsets
+of data indicated by the I<selector>.  A combination of several
+selector bits must consider all those subsets, not just one.  An
+implementation is, however, free to consider an empty subset of data
+to still be a valid subset.
+
+OP_keymgmt_validate() should check if the I<keydata> contains valid
+data subsets indicated by I<selection>.  Some combined selections of
+data subsets may cause validation of the combined data.
+For example, the combination of B<OSSL_KEYMGMT_SELECT_PRIVATE_KEY> and
+B<OSSL_KEYMGMT_SELECT_PUBLIC_KEY> (or B<OSSL_KEYMGMT_SELECT_KEYPAIR>
+for short) is expected to check that the pairwise consistency of
+I<keydata> is valid.
+
+=head2 Key Object Import and Export Functions
+
+OP_keymgmt_import() should import data indicated by I<selection> into
+I<keydata> with values taken from the B<OSSL_PARAM> array I<params>.
+
+OP_keymgmt_export() should extract values indicated by I<selection>
+from I<keydata>, create an B<OSSL_PARAM> array with them and call
+I<param_cb> with that array as well as the given I<cbarg>.
+
+OP_keymgmt_import_types() should return a constant array of descriptor
+B<OSSL_PARAM> for data indicated by I<selection>, for parameters that
+OP_keymgmt_import() can handle.
+
+OP_keymgmt_export_types() should return a constant array of descriptor
+B<OSSL_PARAM> for data indicated by I<selection>, that the
+OP_keymgmt_export() callback can expect to receive.
+
 =head2 Information Parameters
 
 See L<OSSL_PARAM(3)> for further details on the parameters structure.
 
 Parameters currently recognised by built-in keymgmt algorithms'
-OP_keymgmt_get_domparams_params() and OP_keymgmt_get_key_params()
-are:
+OP_keymgmt_get_params:
 
 =over 4
 
diff --git a/doc/man7/provider-serializer.pod b/doc/man7/provider-serializer.pod
index b23a8b64e2..121eb336e0 100644
--- a/doc/man7/provider-serializer.pod
+++ b/doc/man7/provider-serializer.pod
@@ -127,7 +127,7 @@ formatted data.
 
 With objects that have multiple purposes, this can be used to specify
 the purpose type.  The currently known use cases are asymmetric keys
-and domain parameters, where the type can be one of:
+and key parameters, where the type can be one of:
 
 =over 4
 
@@ -141,9 +141,9 @@ key.
 An implementation with that format property value outputs a public
 key.
 
-=item domainparams
+=item parameters
 
-An implementation with that format property value outputs domain
+An implementation with that format property value outputs key
 parameters.
 
 =back
diff --git a/include/crypto/asn1.h b/include/crypto/asn1.h
index 2581619831..0e7e9ba3d4 100644
--- a/include/crypto/asn1.h
+++ b/include/crypto/asn1.h
@@ -70,8 +70,8 @@ struct evp_pkey_asn1_method_st {
      */
     /* Exports to providers */
     size_t (*dirty_cnt) (const EVP_PKEY *pk);
-    void *(*export_to) (const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
-                        int want_domainparams);
+    int (*export_to) (const EVP_PKEY *pk, void *to_keydata,
+                      EVP_KEYMGMT *to_keymgmt);
 } /* EVP_PKEY_ASN1_METHOD */ ;
 
 DEFINE_STACK_OF_CONST(EVP_PKEY_ASN1_METHOD)
diff --git a/include/crypto/evp.h b/include/crypto/evp.h
index 5d6f70be78..6903cc656a 100644
--- a/include/crypto/evp.h
+++ b/include/crypto/evp.h
@@ -548,17 +548,15 @@ struct evp_pkey_st {
 
     /* == Provider attributes == */
     /*
-     * To support transparent export/import between providers that
-     * support the methods for it, and still not having to do the
-     * export/import every time a key or domain params are used, we
-     * maintain a cache of imported key / domain params, indexed by
-     * provider address.  pkeys[0] is *always* the "original" data.
+     * To support transparent export/import between providers that support
+     * the methods for it, and still not having to do the export/import
+     * every time a key object is changed, we maintain a cache of imported
+     * key objects, indexed by keymgmt address.  pkeys[0] is *always* the
+     * "original" data unless we have a legacy key attached.
      */
     struct {
         EVP_KEYMGMT *keymgmt;
-        void *provdata;
-        /* 0 = provdata is a key, 1 = provdata is domain params */
-        int domainparams;
+        void *keydata;
     } pkeys[10];
     /*
      * If there is a legacy key assigned to this structure, we keep
@@ -566,7 +564,7 @@ struct evp_pkey_st {
      */
     size_t dirty_cnt_copy;
 
-    /* Cache of domain parameter / key information */
+    /* Cache of key object information */
     struct {
         int bits;
         int security_bits;
@@ -593,55 +591,39 @@ void openssl_add_all_digests_int(void);
 void evp_cleanup_int(void);
 void evp_app_cleanup_int(void);
 
-/* KEYMGMT helper functions */
-void *evp_keymgmt_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
-                                     int domainparams);
-void evp_keymgmt_clear_pkey_cache(EVP_PKEY *pk);
-void evp_keymgmt_cache_pkey(EVP_PKEY *pk, size_t index, EVP_KEYMGMT *keymgmt,
-                            void *provdata, int domainparams);
-void *evp_keymgmt_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
-                           const OSSL_PARAM params[], int domainparams);
-
-
-/* KEYMGMT provider interface functions */
-void *evp_keymgmt_importdomparams(const EVP_KEYMGMT *keymgmt,
-                                  const OSSL_PARAM params[]);
-void *evp_keymgmt_gendomparams(const EVP_KEYMGMT *keymgmt,
-                            const OSSL_PARAM params[]);
-void evp_keymgmt_freedomparams(const EVP_KEYMGMT *keymgmt,
-                               void *provdomparams);
-int evp_keymgmt_exportdomparams(const EVP_KEYMGMT *keymgmt,
-                                void *provdomparams,
-                                OSSL_CALLBACK *param_cb, void *cbarg);
-const OSSL_PARAM *
-evp_keymgmt_importdomparam_types(const EVP_KEYMGMT *keymgmt);
-const OSSL_PARAM *
-evp_keymgmt_exportdomparam_types(const EVP_KEYMGMT *keymgmt);
-int evp_keymgmt_get_domparam_params(const EVP_KEYMGMT *keymgmt,
-                                    void *provdomparam, OSSL_PARAM params[]);
-const OSSL_PARAM *
-evp_keymgmt_gettable_domparam_params(const EVP_KEYMGMT *keymgmt);
-
-void *evp_keymgmt_importkey(const EVP_KEYMGMT *keymgmt,
-                            const OSSL_PARAM params[]);
-void *evp_keymgmt_genkey(const EVP_KEYMGMT *keymgmt, void *domparams,
-                         const OSSL_PARAM params[]);
-void *evp_keymgmt_loadkey(const EVP_KEYMGMT *keymgmt,
-                          void *id, size_t idlen);
-void evp_keymgmt_freekey(const EVP_KEYMGMT *keymgmt, void *provkey);
-int evp_keymgmt_exportkey(const EVP_KEYMGMT *keymgmt, void *provkey,
-                          OSSL_CALLBACK *param_cb, void *cbarg);
-const OSSL_PARAM *evp_keymgmt_importkey_types(const EVP_KEYMGMT *keymgmt);
-const OSSL_PARAM *evp_keymgmt_exportkey_types(const EVP_KEYMGMT *keymgmt);
-int evp_keymgmt_get_key_params(const EVP_KEYMGMT *keymgmt,
-                               void *provkey, OSSL_PARAM params[]);
-const OSSL_PARAM *evp_keymgmt_gettable_key_params(const EVP_KEYMGMT *keymgmt);
-
-int evp_keymgmt_validate_domparams(const EVP_KEYMGMT *keymgmt, void *provkey);
-int evp_keymgmt_validate_public(const EVP_KEYMGMT *keymgmt, void *provkey);
-int evp_keymgmt_validate_private(const EVP_KEYMGMT *keymgmt, void *provkey);
-int evp_keymgmt_validate_pairwise(const EVP_KEYMGMT *keymgmt, void *provkey);
+/*
+ * KEYMGMT utility functions
+ */
+void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt);
+void evp_keymgmt_util_clear_pkey_cache(EVP_PKEY *pk);
+void evp_keymgmt_util_cache_pkey(EVP_PKEY *pk, size_t index,
+                                 EVP_KEYMGMT *keymgmt, void *keydata);
+void *evp_keymgmt_util_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
+                                int selection, const OSSL_PARAM params[]);
+
 
+/*
+ * KEYMGMT provider interface functions
+ */
+void *evp_keymgmt_newdata(const EVP_KEYMGMT *keymgmt);
+void evp_keymgmt_freedata(const EVP_KEYMGMT *keymgmt, void *keyddata);
+int evp_keymgmt_get_params(const EVP_KEYMGMT *keymgmt,
+                           void *keydata, OSSL_PARAM params[]);
+const OSSL_PARAM *evp_keymgmt_gettable_params(const EVP_KEYMGMT *keymgmt);
+
+
+int evp_keymgmt_has(const EVP_KEYMGMT *keymgmt, void *keyddata, int selection);
+int evp_keymgmt_validate(const EVP_KEYMGMT *keymgmt, void *keydata,
+                         int selection);
+
+int evp_keymgmt_import(const EVP_KEYMGMT *keymgmt, void *keydata,
+                       int selection, const OSSL_PARAM params[]);
+const OSSL_PARAM *evp_keymgmt_import_types(const EVP_KEYMGMT *keymgmt,
+                                           int selection);
+int evp_keymgmt_export(const EVP_KEYMGMT *keymgmt, void *keydata,
+                       int selection, OSSL_CALLBACK *param_cb, void *cbarg);
+const OSSL_PARAM *evp_keymgmt_export_types(const EVP_KEYMGMT *keymgmt,
+                                           int selection);
 
 /* Pulling defines out of C source files */
 
diff --git a/include/internal/property.h b/include/internal/property.h
index 1c40351e83..b84e1802a2 100644
--- a/include/internal/property.h
+++ b/include/internal/property.h
@@ -26,6 +26,9 @@ OSSL_PROPERTY_LIST *ossl_parse_query(OPENSSL_CTX *ctx, const char *s);
 /* Property checker of query vs definition */
 int ossl_property_match_count(const OSSL_PROPERTY_LIST *query,
                               const OSSL_PROPERTY_LIST *defn);
+/* Free a parsed property list */
+void ossl_property_free(OSSL_PROPERTY_LIST *p);
+
 
 /* Implementation store functions */
 OSSL_METHOD_STORE *ossl_method_store_new(OPENSSL_CTX *ctx);
diff --git a/include/openssl/core_numbers.h b/include/openssl/core_numbers.h
index ecee173d09..547aeb5858 100644
--- a/include/openssl/core_numbers.h
+++ b/include/openssl/core_numbers.h
@@ -333,109 +333,93 @@ OSSL_CORE_MAKE_FUNC(int, OP_kdf_set_ctx_params,
 /*-
  * Key management
  *
- * Key domain parameter references can be created in several manners:
- * - by importing the domain parameter material via an OSSL_PARAM array.
- * - by generating key domain parameters, given input via an OSSL_PARAM
- *   array.
+ * The Key Management takes care of provider side key objects, and includes
+ * all current functionality to create them, destroy them, set parameters
+ * and key material, etc, essentially everything that manipulates the keys
+ * themselves and their parameters.
  *
- * Key references can be created in several manners:
- * - by importing the key material via an OSSL_PARAM array.
- * - by generating a key, given optional domain parameters and
- *   additional keygen parameters.
- *   If domain parameters are given, they must have been generated using
- *   the domain parameter generator functions.
- *   If the domain parameters comes from a different provider, results
- *   are undefined.
- *   THE CALLER MUST ENSURE THAT CORRECT DOMAIN PARAMETERS ARE USED.
- * - by loading an internal key, given a binary blob that forms an identity.
- *   THE CALLER MUST ENSURE THAT A CORRECT IDENTITY IS USED.
+ * The key objects are commonly refered to as |keydata|, and it MUST be able
+ * to contain parameters if the key has any, the public key and the private
+ * key.  All parts are optional, but their presence determines what can be
+ * done with the key object in terms of encryption, signature, and so on.
+ * The assumption from libcrypto is that the key object contains any of the
+ * following data combinations:
+ *
+ * - parameters only
+ * - public key only
+ * - public key + private key
+ * - parameters + public key
+ * - parameters + public key + private key
+ *
+ * What "parameters", "public key" and "private key" means in detail is left
+ * to the implementation.  In the case of DH and DSA, they would typically
+ * include domain parameters, while for certain variants of RSA, they would
+ * typically include PSS or OAEP parameters.
+ *
+ * Key objects are created with OP_keymgmt_new() and destroyed with
+ * Op_keymgmt_free().  Key objects can have data filled in with
+ * OP_keymgmt_import().
+ *
+ * Three functions are made available to check what selection of data is
+ * present in a key object: OP_keymgmt_has_parameters(),
+ * OP_keymgmt_has_public_key(), and OP_keymgmt_has_private_key(),
  */
 
-/* Key domain parameter creation and destruction */
-# define OSSL_FUNC_KEYMGMT_IMPORTDOMPARAMS           1
-# define OSSL_FUNC_KEYMGMT_GENDOMPARAMS              2
-# define OSSL_FUNC_KEYMGMT_FREEDOMPARAMS             3
-OSSL_CORE_MAKE_FUNC(void *, OP_keymgmt_importdomparams,
-                    (void *provctx, const OSSL_PARAM params[]))
-OSSL_CORE_MAKE_FUNC(void *, OP_keymgmt_gendomparams,
-                    (void *provctx, const OSSL_PARAM params[]))
-OSSL_CORE_MAKE_FUNC(void, OP_keymgmt_freedomparams, (void *domparams))
-
-/* Key domain parameter export */
-# define OSSL_FUNC_KEYMGMT_EXPORTDOMPARAMS           4
-OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_exportdomparams,
-                    (void *domparams, OSSL_CALLBACK *param_cb, void *cbarg))
-
-/* Key domain parameter discovery */
-/*
- * TODO(v3.0) investigate if we need OP_keymgmt_exportdomparam_types.
- * 'openssl provider' may be a caller...
- */
-# define OSSL_FUNC_KEYMGMT_IMPORTDOMPARAM_TYPES      5
-# define OSSL_FUNC_KEYMGMT_EXPORTDOMPARAM_TYPES      6
-OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_keymgmt_importdomparam_types,
-                    (void))
-OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_keymgmt_exportdomparam_types,
-                    (void))
-
-/* Key domain parameter information */
-#define OSSL_FUNC_KEYMGMT_GET_DOMPARAM_PARAMS        7
-#define OSSL_FUNC_KEYMGMT_GETTABLE_DOMPARAM_PARAMS   8
-OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_get_domparam_params,
-                    (void *domparam, OSSL_PARAM params[]))
-OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_keymgmt_gettable_domparam_params,
-                    (void))
-
-/* Key creation and destruction */
-# define OSSL_FUNC_KEYMGMT_IMPORTKEY                20
-# define OSSL_FUNC_KEYMGMT_GENKEY                   21
-# define OSSL_FUNC_KEYMGMT_LOADKEY                  22
-# define OSSL_FUNC_KEYMGMT_FREEKEY                  23
-OSSL_CORE_MAKE_FUNC(void *, OP_keymgmt_importkey,
-                    (void *provctx, const OSSL_PARAM params[]))
-OSSL_CORE_MAKE_FUNC(void *, OP_keymgmt_genkey,
-                    (void *provctx,
-                     void *domparams, const OSSL_PARAM genkeyparams[]))
-OSSL_CORE_MAKE_FUNC(void *, OP_keymgmt_loadkey,
-                    (void *provctx, void *id, size_t idlen))
-OSSL_CORE_MAKE_FUNC(void, OP_keymgmt_freekey, (void *key))
-
-/* Key export */
-# define OSSL_FUNC_KEYMGMT_EXPORTKEY                24
-OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_exportkey,
-                    (void *key, OSSL_CALLBACK *param_cb, void *cbarg))
-
-/* Key discovery */
-/*
- * TODO(v3.0) investigate if we need OP_keymgmt_exportkey_types.
- * 'openssl provider' may be a caller...
- */
-# define OSSL_FUNC_KEYMGMT_IMPORTKEY_TYPES          25
-# define OSSL_FUNC_KEYMGMT_EXPORTKEY_TYPES          26
-OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_keymgmt_importkey_types, (void))
-OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_keymgmt_exportkey_types, (void))
-
-/* Key information */
-# define OSSL_FUNC_KEYMGMT_GET_KEY_PARAMS           27
-# define OSSL_FUNC_KEYMGMT_GETTABLE_KEY_PARAMS      28
-OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_get_key_params,
-                    (void *key, OSSL_PARAM params[]))
-OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_keymgmt_gettable_key_params, (void))
-
-/* Discovery of supported operations */
-# define OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME     40
-OSSL_CORE_MAKE_FUNC(const char *,OP_keymgmt_query_operation_name,
+/* Key data subset selection - individual bits */
+# define OSSL_KEYMGMT_SELECT_PRIVATE_KEY            0x01
+# define OSSL_KEYMGMT_SELECT_PUBLIC_KEY             0x02
+# define OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS      0x04
+# define OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS       0x80
+
+/* Key data subset selection - combinations */
+# define OSSL_KEYMGMT_SELECT_ALL_PARAMETERS     \
+    ( OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS     \
+      | OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS)
+# define OSSL_KEYMGMT_SELECT_KEYPAIR            \
+    ( OSSL_KEYMGMT_SELECT_PRIVATE_KEY | OSSL_KEYMGMT_SELECT_PUBLIC_KEY )
+# define OSSL_KEYMGMT_SELECT_ALL                \
+    ( OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS )
+
+/* Basic key object creation, destruction */
+# define OSSL_FUNC_KEYMGMT_NEW                         1
+# define OSSL_FUNC_KEYMGMT_FREE                        9
+OSSL_CORE_MAKE_FUNC(void *, OP_keymgmt_new, (void *provctx))
+OSSL_CORE_MAKE_FUNC(void, OP_keymgmt_free, (void *keydata))
+
+/* Key object information, with discovery */
+#define OSSL_FUNC_KEYMGMT_GET_PARAMS                  10
+#define OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS             11
+OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_get_params,
+                    (void *keydata, OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_keymgmt_gettable_params, (void))
+
+/* Key checks - discovery of supported operations */
+# define OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME       20
+OSSL_CORE_MAKE_FUNC(const char *, OP_keymgmt_query_operation_name,
                     (int operation_id))
 
-/* Key validation */
-# define OSSL_FUNC_KEYMGMT_VALIDATE_DOMPARAMS       29
-# define OSSL_FUNC_KEYMGMT_VALIDATE_PUBLIC          30
-# define OSSL_FUNC_KEYMGMT_VALIDATE_PRIVATE         31
-# define OSSL_FUNC_KEYMGMT_VALIDATE_PAIRWISE        32
-OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_validate_domparams, (void *key))
-OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_validate_public, (void *key))
-OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_validate_private, (void *key))
-OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_validate_pairwise, (void *key))
+/* Key checks - key data content checks */
+# define OSSL_FUNC_KEYMGMT_HAS                        21
+OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_has, (void *keydata, int selection))
+
+/* Key checks - validation */
+# define OSSL_FUNC_KEYMGMT_VALIDATE                   22
+OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_validate, (void *keydata, int selection))
+
+/* Import and export functions, with ddiscovery */
+# define OSSL_FUNC_KEYMGMT_IMPORT                     40
+# define OSSL_FUNC_KEYMGMT_IMPORT_TYPES               41
+# define OSSL_FUNC_KEYMGMT_EXPORT                     42
+# define OSSL_FUNC_KEYMGMT_EXPORT_TYPES               43
+OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_import,
+                    (void *keydata, int selection, const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_keymgmt_import_types,
+                    (int selection))
+OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_export,
+                    (void *keydata, int selection,
+                     OSSL_CALLBACK *param_cb, void *cbarg))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_keymgmt_export_types,
+                    (int selection))
 
 /* Key Exchange */
 
diff --git a/include/openssl/serializer.h b/include/openssl/serializer.h
index 2629a13ccd..c37939f813 100644
--- a/include/openssl/serializer.h
+++ b/include/openssl/serializer.h
@@ -87,12 +87,12 @@ OSSL_SERIALIZER_CTX *OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(const EVP_PKEY *pkey,
  */
 # define OSSL_SERIALIZER_PUBKEY_TO_PEM_PQ "format=pem,type=public"
 # define OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ "format=pem,type=private"
-# define OSSL_SERIALIZER_Parameters_TO_PEM_PQ "format=pem,type=domainparams"
+# define OSSL_SERIALIZER_Parameters_TO_PEM_PQ "format=pem,type=parameters"
 
 /* Corresponding macros for text output */
 # define OSSL_SERIALIZER_PUBKEY_TO_TEXT_PQ "format=text,type=public"
 # define OSSL_SERIALIZER_PrivateKey_TO_TEXT_PQ "format=text,type=private"
-# define OSSL_SERIALIZER_Parameters_TO_TEXT_PQ "format=text,type=domainparams"
+# define OSSL_SERIALIZER_Parameters_TO_TEXT_PQ "format=text,type=parameters"
 
 # ifdef __cplusplus
 }
diff --git a/providers/defltprov.c b/providers/defltprov.c
index 166281fae3..8d89322825 100644
--- a/providers/defltprov.c
+++ b/providers/defltprov.c
@@ -417,19 +417,19 @@ static const OSSL_ALGORITHM deflt_serializer[] = {
       dh_priv_text_serializer_functions },
     { "DH", "default=yes,format=text,type=public",
       dh_pub_text_serializer_functions },
-    { "DH", "default=yes,format=text,type=domainparams",
+    { "DH", "default=yes,format=text,type=parameters",
       dh_param_text_serializer_functions },
     { "DH", "default=yes,format=der,type=private",
       dh_priv_der_serializer_functions },
     { "DH", "default=yes,format=der,type=public",
       dh_pub_der_serializer_functions },
-    { "DH", "default=yes,format=der,type=domainparams",
+    { "DH", "default=yes,format=der,type=parameters",
       dh_param_der_serializer_functions },
     { "DH", "default=yes,format=pem,type=private",
       dh_priv_pem_serializer_functions },
     { "DH", "default=yes,format=pem,type=public",
       dh_pub_pem_serializer_functions },
-    { "DH", "default=yes,format=pem,type=domainparams",
+    { "DH", "default=yes,format=pem,type=parameters",
       dh_param_pem_serializer_functions },
 #endif
 
@@ -438,19 +438,19 @@ static const OSSL_ALGORITHM deflt_serializer[] = {
       dsa_priv_text_serializer_functions },
     { "DSA", "default=yes,format=text,type=public",
       dsa_pub_text_serializer_functions },
-    { "DSA", "default=yes,format=text,type=domainparams",
+    { "DSA", "default=yes,format=text,type=parameters",
       dsa_param_text_serializer_functions },
     { "DSA", "default=yes,format=der,type=private",
       dsa_priv_der_serializer_functions },
     { "DSA", "default=yes,format=der,type=public",
       dsa_pub_der_serializer_functions },
-    { "DSA", "default=yes,format=der,type=domainparams",
+    { "DSA", "default=yes,format=der,type=parameters",
       dsa_param_der_serializer_functions },
     { "DSA", "default=yes,format=pem,type=private",
       dsa_priv_pem_serializer_functions },
     { "DSA", "default=yes,format=pem,type=public",
       dsa_pub_pem_serializer_functions },
-    { "DSA", "default=yes,format=pem,type=domainparams",
+    { "DSA", "default=yes,format=pem,type=parameters",
       dsa_param_pem_serializer_functions },
 #endif
 
diff --git a/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c
index c385d81044..44791a13e4 100644
--- a/providers/implementations/keymgmt/dh_kmgmt.c
+++ b/providers/implementations/keymgmt/dh_kmgmt.c
@@ -13,15 +13,22 @@
 #include <openssl/dh.h>
 #include <openssl/params.h>
 #include "internal/param_build.h"
+#include "crypto/dh.h"
 #include "prov/implementations.h"
 #include "prov/providercommon.h"
 
-static OSSL_OP_keymgmt_importdomparams_fn dh_importdomparams;
-static OSSL_OP_keymgmt_exportdomparams_fn dh_exportdomparams;
-static OSSL_OP_keymgmt_get_key_params_fn dh_get_domparam_params;
-static OSSL_OP_keymgmt_importkey_fn dh_importkey;
-static OSSL_OP_keymgmt_exportkey_fn dh_exportkey;
-static OSSL_OP_keymgmt_get_key_params_fn dh_get_key_params;
+static OSSL_OP_keymgmt_new_fn dh_newdata;
+static OSSL_OP_keymgmt_free_fn dh_freedata;
+static OSSL_OP_keymgmt_get_params_fn dh_get_params;
+static OSSL_OP_keymgmt_gettable_params_fn dh_gettable_params;
+static OSSL_OP_keymgmt_has_fn dh_has;
+static OSSL_OP_keymgmt_import_fn dh_import;
+static OSSL_OP_keymgmt_import_types_fn dh_import_types;
+static OSSL_OP_keymgmt_export_fn dh_export;
+static OSSL_OP_keymgmt_export_types_fn dh_export_types;
+
+#define DH_POSSIBLE_SELECTIONS                 \
+    (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)
 
 static int params_to_domparams(DH *dh, const OSSL_PARAM params[])
 {
@@ -128,70 +135,132 @@ static int key_to_params(DH *dh, OSSL_PARAM_BLD *tmpl)
     return 1;
 }
 
-static void *dh_importdomparams(void *provctx, const OSSL_PARAM params[])
+static void *dh_newdata(void *provctx)
 {
-    DH *dh;
-
-    if ((dh = DH_new()) == NULL
-        || !params_to_domparams(dh, params)) {
-        DH_free(dh);
-        dh = NULL;
-    }
-    return dh;
+    return DH_new();
 }
 
-static int dh_exportdomparams(void *domparams, OSSL_CALLBACK *param_cb,
-                              void *cbarg)
+static void dh_freedata(void *keydata)
 {
-    DH *dh = domparams;
-    OSSL_PARAM_BLD tmpl;
-    OSSL_PARAM *params = NULL;
-    int ret;
+    DH_free(keydata);
+}
 
-    ossl_param_bld_init(&tmpl);
-    if (dh == NULL
-        || !domparams_to_params(dh, &tmpl)
-        || (params = ossl_param_bld_to_param(&tmpl)) == NULL)
-        return 0;
-    ret = param_cb(params, cbarg);
-    ossl_param_bld_free(params);
-    return ret;
+static int dh_has(void *keydata, int selection)
+{
+    DH *dh = keydata;
+    int ok = 0;
+
+    if ((selection & DH_POSSIBLE_SELECTIONS) != 0)
+        ok = 1;
+
+    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+        ok = ok && (DH_get0_pub_key(dh) != NULL);
+    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+        ok = ok && (DH_get0_priv_key(dh) != NULL);
+    if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
+        ok = ok && (DH_get0_p(dh) != NULL && DH_get0_g(dh) != NULL);
+    return ok;
 }
 
-static void *dh_importkey(void *provctx, const OSSL_PARAM params[])
+static int dh_import(void *keydata, int selection, const OSSL_PARAM params[])
 {
-    DH *dh;
-
-    if ((dh = DH_new()) == NULL
-        || !params_to_key(dh, params)) {
-        DH_free(dh);
-        dh = NULL;
-    }
-    return dh;
+    DH *dh = keydata;
+    int ok = 0;
+
+    if (dh == NULL)
+        return 0;
+
+    if ((selection & DH_POSSIBLE_SELECTIONS) != 0)
+        ok = 1;
+
+    if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
+        ok = ok && params_to_domparams(dh, params);
+    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
+        ok = ok && params_to_key(dh, params);
+
+    return ok;
 }
 
-static int dh_exportkey(void *key, OSSL_CALLBACK *param_cb, void *cbarg)
+static int dh_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
+                     void *cbarg)
 {
-    DH *dh = key;
+    DH *dh = keydata;
     OSSL_PARAM_BLD tmpl;
     OSSL_PARAM *params = NULL;
-    int ret;
+    int ok = 1;
+
+    if (dh == NULL)
+        return 0;
 
     ossl_param_bld_init(&tmpl);
-    if (dh == NULL
-        || !key_to_params(dh, &tmpl)
+
+    if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
+        ok = ok && domparams_to_params(dh, &tmpl);
+    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
+        ok = ok && key_to_params(dh, &tmpl);
+
+    if (!ok
         || (params = ossl_param_bld_to_param(&tmpl)) == NULL)
         return 0;
-    ret = param_cb(params, cbarg);
+
+    ok = param_cb(params, cbarg);
     ossl_param_bld_free(params);
-    return ret;
+    return ok;
 }
 
-/*
- * Same function for domain parameters and for keys.
- * "dpk" = "domain parameters & keys"
- */
-static ossl_inline int dh_get_dpk_params(void *key, OSSL_PARAM params[])
+/* IMEXPORT = IMPORT + EXPORT */
+
+# define DH_IMEXPORTABLE_PARAMETERS                     \
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_P, NULL, 0),      \
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_G, NULL, 0)
+# define DH_IMEXPORTABLE_PUBLIC_KEY                     \
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_DH_PUB_KEY, NULL, 0)
+# define DH_IMEXPORTABLE_PRIVATE_KEY                    \
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_DH_PRIV_KEY, NULL, 0)
+static const OSSL_PARAM dh_all_types[] = {
+    DH_IMEXPORTABLE_PARAMETERS,
+    DH_IMEXPORTABLE_PUBLIC_KEY,
+    DH_IMEXPORTABLE_PRIVATE_KEY,
+    OSSL_PARAM_END
+};
+static const OSSL_PARAM dh_parameter_types[] = {
+    DH_IMEXPORTABLE_PARAMETERS,
+    OSSL_PARAM_END
+};
+static const OSSL_PARAM dh_key_types[] = {
+    DH_IMEXPORTABLE_PUBLIC_KEY,
+    DH_IMEXPORTABLE_PRIVATE_KEY,
+    OSSL_PARAM_END
+};
+static const OSSL_PARAM *dh_types[] = {
+    NULL,                        /* Index 0 = none of them */
+    dh_parameter_types,          /* Index 1 = parameter types */
+    dh_key_types,                /* Index 2 = key types */
+    dh_all_types                 /* Index 3 = 1 + 2 */
+};
+
+static const OSSL_PARAM *dh_imexport_types(int selection)
+{
+    int type_select = 0;
+
+    if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
+        type_select += 1;
+    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
+        type_select += 2;
+    return dh_types[type_select];
+}
+
+static const OSSL_PARAM *dh_import_types(int selection)
+{
+    return dh_imexport_types(selection);
+}
+
+static const OSSL_PARAM *dh_export_types(int selection)
+{
+    return dh_imexport_types(selection);
+}
+
+static ossl_inline int dh_get_params(void *key, OSSL_PARAM params[])
 {
     DH *dh = key;
     OSSL_PARAM *p;
@@ -208,33 +277,27 @@ static ossl_inline int dh_get_dpk_params(void *key, OSSL_PARAM params[])
     return 1;
 }
 
-/*
- * We have wrapper functions to make sure we get signatures right, see
- * the forward declarations at the beginning of this file.
- */
-static int dh_get_domparam_params(void *domparams, OSSL_PARAM params[])
-{
-    return dh_get_dpk_params(domparams, params);
-}
+static const OSSL_PARAM dh_params[] = {
+    OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
+    OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
+    OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
+    OSSL_PARAM_END
+};
 
-static int dh_get_key_params(void *key, OSSL_PARAM params[])
+static const OSSL_PARAM *dh_gettable_params(void)
 {
-    return dh_get_dpk_params(key, params);
+    return dh_params;
 }
 
 const OSSL_DISPATCH dh_keymgmt_functions[] = {
-    /*
-     * TODO(3.0) When implementing OSSL_FUNC_KEYMGMT_GENKEY, remember to also
-     * implement OSSL_FUNC_KEYMGMT_EXPORTKEY.
-     */
-    { OSSL_FUNC_KEYMGMT_IMPORTDOMPARAMS, (void (*)(void))dh_importdomparams },
-    { OSSL_FUNC_KEYMGMT_EXPORTDOMPARAMS, (void (*)(void))dh_exportdomparams },
-    { OSSL_FUNC_KEYMGMT_GET_DOMPARAM_PARAMS,
-      (void (*) (void))dh_get_domparam_params },
-    { OSSL_FUNC_KEYMGMT_FREEDOMPARAMS, (void (*)(void))DH_free },
-    { OSSL_FUNC_KEYMGMT_IMPORTKEY, (void (*)(void))dh_importkey },
-    { OSSL_FUNC_KEYMGMT_EXPORTKEY, (void (*)(void))dh_exportkey },
-    { OSSL_FUNC_KEYMGMT_FREEKEY, (void (*)(void))DH_free },
-    { OSSL_FUNC_KEYMGMT_GET_KEY_PARAMS,  (void (*) (void))dh_get_key_params },
+    { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dh_newdata },
+    { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))dh_freedata },
+    { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dh_get_params },
+    { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dh_gettable_params },
+    { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dh_has },
+    { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dh_import },
+    { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dh_import_types },
+    { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dh_export },
+    { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dh_export_types },
     { 0, NULL }
 };
diff --git a/providers/implementations/keymgmt/dsa_kmgmt.c b/providers/implementations/keymgmt/dsa_kmgmt.c
index 5a53a439d9..f5bbc5260b 100644
--- a/providers/implementations/keymgmt/dsa_kmgmt.c
+++ b/providers/implementations/keymgmt/dsa_kmgmt.c
@@ -12,19 +12,25 @@
 #include <openssl/bn.h>
 #include <openssl/params.h>
 #include "internal/param_build.h"
+#include "crypto/dsa.h"
 #include "prov/implementations.h"
 #include "prov/providercommon.h"
 #include "prov/provider_ctx.h"
 #include "crypto/dsa.h"
 
-static OSSL_OP_keymgmt_importdomparams_fn dsa_importdomparams;
-static OSSL_OP_keymgmt_exportdomparams_fn dsa_exportdomparams;
-static OSSL_OP_keymgmt_get_domparam_params_fn dsa_get_domparam_params;
-static OSSL_OP_keymgmt_importkey_fn dsa_importkey;
-static OSSL_OP_keymgmt_exportkey_fn dsa_exportkey;
-static OSSL_OP_keymgmt_get_key_params_fn dsa_get_key_params;
+static OSSL_OP_keymgmt_new_fn dsa_newdata;
+static OSSL_OP_keymgmt_free_fn dsa_freedata;
+static OSSL_OP_keymgmt_get_params_fn dsa_get_params;
+static OSSL_OP_keymgmt_gettable_params_fn dsa_gettable_params;
+static OSSL_OP_keymgmt_has_fn dsa_has;
+static OSSL_OP_keymgmt_import_fn dsa_import;
+static OSSL_OP_keymgmt_import_types_fn dsa_import_types;
+static OSSL_OP_keymgmt_export_fn dsa_export;
+static OSSL_OP_keymgmt_export_types_fn dsa_export_types;
 
 #define DSA_DEFAULT_MD "SHA256"
+#define DSA_POSSIBLE_SELECTIONS                 \
+    (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)
 
 static int params_to_domparams(DSA *dsa, const OSSL_PARAM params[])
 {
@@ -136,70 +142,133 @@ static int key_to_params(DSA *dsa, OSSL_PARAM_BLD *tmpl)
     return 1;
 }
 
-static void *dsa_importdomparams(void *provctx, const OSSL_PARAM params[])
+static void *dsa_newdata(void *provctx)
 {
-    DSA *dsa;
-
-    if ((dsa = DSA_new()) == NULL
-        || !params_to_domparams(dsa, params)) {
-        DSA_free(dsa);
-        dsa = NULL;
-    }
-    return dsa;
+    return DSA_new();
 }
 
-static int dsa_exportdomparams(void *domparams,
-                               OSSL_CALLBACK *param_cb, void *cbarg)
+static void dsa_freedata(void *keydata)
 {
-    DSA *dsa = domparams;
-    OSSL_PARAM_BLD tmpl;
-    OSSL_PARAM *params = NULL;
-    int ret;
+    DSA_free(keydata);
+}
 
-    ossl_param_bld_init(&tmpl);
-    if (dsa == NULL
-        || !domparams_to_params(dsa, &tmpl)
-        || (params = ossl_param_bld_to_param(&tmpl)) == NULL)
-        return 0;
-    ret = param_cb(params, cbarg);
-    ossl_param_bld_free(params);
-    return ret;
+static int dsa_has(void *keydata, int selection)
+{
+    DSA *dsa = keydata;
+    int ok = 0;
+
+    if ((selection & DSA_POSSIBLE_SELECTIONS) != 0)
+        ok = 1;
+
+    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+        ok = ok && (DSA_get0_pub_key(dsa) != NULL);
+    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+        ok = ok && (DSA_get0_priv_key(dsa) != NULL);
+    if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
+        ok = ok && (DSA_get0_p(dsa) != NULL && DSA_get0_g(dsa) != NULL);
+    return ok;
 }
 
-static void *dsa_importkey(void *provctx, const OSSL_PARAM params[])
+static int dsa_import(void *keydata, int selection, const OSSL_PARAM params[])
 {
-    DSA *dsa;
-
-    if ((dsa = DSA_new()) == NULL
-        || !params_to_key(dsa, params)) {
-        DSA_free(dsa);
-        dsa = NULL;
-    }
-    return dsa;
+    DSA *dsa = keydata;
+    int ok = 0;
+
+    if (dsa == NULL)
+        return 0;
+
+    if ((selection & DSA_POSSIBLE_SELECTIONS) != 0)
+        ok = 1;
+
+    if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
+        ok = ok && params_to_domparams(dsa, params);
+    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
+        ok = ok && params_to_key(dsa, params);
+
+    return ok;
 }
 
-static int dsa_exportkey(void *key, OSSL_CALLBACK *param_cb, void *cbarg)
+static int dsa_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
+                      void *cbarg)
 {
-    DSA *dsa = key;
+    DSA *dsa = keydata;
     OSSL_PARAM_BLD tmpl;
     OSSL_PARAM *params = NULL;
-    int ret;
+    int ok = 1;
+
+    if (dsa == NULL)
+        return 0;
 
     ossl_param_bld_init(&tmpl);
-    if (dsa == NULL
-        || !key_to_params(dsa, &tmpl)
+
+    if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
+        ok = ok && domparams_to_params(dsa, &tmpl);
+    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
+        ok = ok && key_to_params(dsa, &tmpl);
+
+    if (!ok
         || (params = ossl_param_bld_to_param(&tmpl)) == NULL)
         return 0;
-    ret = param_cb(params, cbarg);
+
+    ok = param_cb(params, cbarg);
     ossl_param_bld_free(params);
-    return ret;
+    return ok;
 }
 
-/*
- * Same function for domain parameters and for keys.
- * "dpk" = "domain parameters & keys"
- */
-static ossl_inline int dsa_get_dpk_params(void *key, OSSL_PARAM params[])
+/* IMEXPORT = IMPORT + EXPORT */
+
+# define DSA_IMEXPORTABLE_PARAMETERS                    \
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_P, NULL, 0),      \
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_Q, NULL, 0),      \
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_G, NULL, 0)
+# define DSA_IMEXPORTABLE_PUBLIC_KEY                    \
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_DSA_PUB_KEY, NULL, 0)
+# define DSA_IMEXPORTABLE_PRIVATE_KEY                   \
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_DSA_PRIV_KEY, NULL, 0)
+static const OSSL_PARAM dsa_all_types[] = {
+    DSA_IMEXPORTABLE_PARAMETERS,
+    DSA_IMEXPORTABLE_PUBLIC_KEY,
+    DSA_IMEXPORTABLE_PRIVATE_KEY,
+    OSSL_PARAM_END
+};
+static const OSSL_PARAM dsa_parameter_types[] = {
+    DSA_IMEXPORTABLE_PARAMETERS,
+    OSSL_PARAM_END
+};
+static const OSSL_PARAM dsa_key_types[] = {
+    DSA_IMEXPORTABLE_PUBLIC_KEY,
+    DSA_IMEXPORTABLE_PRIVATE_KEY,
+    OSSL_PARAM_END
+};
+static const OSSL_PARAM *dsa_types[] = {
+    NULL,                        /* Index 0 = none of them */
+    dsa_parameter_types,          /* Index 1 = parameter types */
+    dsa_key_types,                /* Index 2 = key types */
+    dsa_all_types                 /* Index 3 = 1 + 2 */
+};
+
+static const OSSL_PARAM *dsa_imexport_types(int selection)
+{
+    int type_select = 0;
+
+    if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
+        type_select += 1;
+    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
+        type_select += 2;
+    return dsa_types[type_select];
+}
+
+static const OSSL_PARAM *dsa_import_types(int selection)
+{
+    return dsa_imexport_types(selection);
+}
+
+static const OSSL_PARAM *dsa_export_types(int selection)
+{
+    return dsa_imexport_types(selection);
+}
+
+static ossl_inline int dsa_get_params(void *key, OSSL_PARAM params[])
 {
     DSA *dsa = key;
     OSSL_PARAM *p;
@@ -219,29 +288,28 @@ static ossl_inline int dsa_get_dpk_params(void *key, OSSL_PARAM params[])
     return 1;
 }
 
-/*
- * We have wrapper functions to make sure we get signatures right, see
- * the forward declarations at the beginning of this file.
- */
-static int dsa_get_domparam_params(void *domparams, OSSL_PARAM params[])
-{
-    return dsa_get_dpk_params(domparams, params);
-}
+static const OSSL_PARAM dsa_params[] = {
+    OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
+    OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
+    OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
+    OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0),
+    OSSL_PARAM_END
+};
 
-static int dsa_get_key_params(void *key, OSSL_PARAM params[])
+static const OSSL_PARAM *dsa_gettable_params(void)
 {
-    return dsa_get_dpk_params(key, params);
+    return dsa_params;
 }
 
 const OSSL_DISPATCH dsa_keymgmt_functions[] = {
-    { OSSL_FUNC_KEYMGMT_IMPORTDOMPARAMS, (void (*)(void))dsa_importdomparams },
-    { OSSL_FUNC_KEYMGMT_EXPORTDOMPARAMS, (void (*)(void))dsa_exportdomparams },
-    { OSSL_FUNC_KEYMGMT_FREEDOMPARAMS, (void (*)(void))DSA_free },
-    { OSSL_FUNC_KEYMGMT_GET_DOMPARAM_PARAMS,
-      (void (*) (void))dsa_get_domparam_params },
-    { OSSL_FUNC_KEYMGMT_IMPORTKEY, (void (*)(void))dsa_importkey },
-    { OSSL_FUNC_KEYMGMT_EXPORTKEY, (void (*)(void))dsa_exportkey },
-    { OSSL_FUNC_KEYMGMT_FREEKEY, (void (*)(void))DSA_free },
-    { OSSL_FUNC_KEYMGMT_GET_KEY_PARAMS,  (void (*) (void))dsa_get_key_params },
+    { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dsa_newdata },
+    { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))dsa_freedata },
+    { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dsa_get_params },
+    { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dsa_gettable_params },
+    { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dsa_has },
+    { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dsa_import },
+    { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dsa_import_types },
+    { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dsa_export },
+    { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dsa_export_types },
     { 0, NULL }
 };
diff --git a/providers/implementations/keymgmt/rsa_kmgmt.c b/providers/implementations/keymgmt/rsa_kmgmt.c
index e205a412f3..6ab695ea7b 100644
--- a/providers/implementations/keymgmt/rsa_kmgmt.c
+++ b/providers/implementations/keymgmt/rsa_kmgmt.c
@@ -20,14 +20,20 @@
 #include "prov/providercommon.h"
 #include "crypto/rsa.h"
 
-static OSSL_OP_keymgmt_importkey_fn rsa_importkey;
-static OSSL_OP_keymgmt_exportkey_fn rsa_exportkey;
-static OSSL_OP_keymgmt_get_key_params_fn rsa_get_key_params;
-static OSSL_OP_keymgmt_validate_public_fn rsa_validatekey_public;
-static OSSL_OP_keymgmt_validate_private_fn rsa_validatekey_private;
-static OSSL_OP_keymgmt_validate_pairwise_fn rsa_validatekey_pairwise;
+static OSSL_OP_keymgmt_new_fn rsa_newdata;
+static OSSL_OP_keymgmt_free_fn rsa_freedata;
+static OSSL_OP_keymgmt_get_params_fn rsa_get_params;
+static OSSL_OP_keymgmt_gettable_params_fn rsa_gettable_params;
+static OSSL_OP_keymgmt_has_fn rsa_has;
+static OSSL_OP_keymgmt_validate_fn rsa_validate;
+static OSSL_OP_keymgmt_import_fn rsa_import;
+static OSSL_OP_keymgmt_import_types_fn rsa_import_types;
+static OSSL_OP_keymgmt_export_fn rsa_export;
+static OSSL_OP_keymgmt_export_types_fn rsa_export_types;
 
 #define RSA_DEFAULT_MD "SHA256"
+#define RSA_POSSIBLE_SELECTIONS                 \
+    (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS)
 
 DEFINE_STACK_OF(BIGNUM)
 DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
@@ -162,33 +168,73 @@ static int key_to_params(RSA *rsa, OSSL_PARAM_BLD *tmpl)
     return ret;
 }
 
-static void *rsa_importkey(void *provctx, const OSSL_PARAM params[])
+static void *rsa_newdata(void *provctx)
 {
-    RSA *rsa;
+    return RSA_new();
+}
 
-    if ((rsa = RSA_new()) == NULL
-        || !params_to_key(rsa, params)) {
-        RSA_free(rsa);
-        rsa = NULL;
-    }
-    return rsa;
+static void rsa_freedata(void *keydata)
+{
+    RSA_free(keydata);
 }
 
-static int rsa_exportkey(void *key, OSSL_CALLBACK *param_callback, void *cbarg)
+static int rsa_has(void *keydata, int selection)
 {
-    RSA *rsa = key;
+    RSA *rsa = keydata;
+    int ok = 0;
+
+    if ((selection & RSA_POSSIBLE_SELECTIONS) != 0)
+        ok = 1;
+
+    ok = ok && (RSA_get0_e(rsa) != NULL);
+    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+        ok = ok && (RSA_get0_n(rsa) != NULL);
+    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+        ok = ok && (RSA_get0_d(rsa) != NULL);
+    return ok;
+}
+
+static int rsa_import(void *keydata, int selection, const OSSL_PARAM params[])
+{
+    RSA *rsa = keydata;
+    int ok = 1;
+
+    if (rsa == NULL)
+        return 0;
+
+    /* TODO(3.0) PSS and OAEP should bring on parameters */
+
+    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
+        ok = ok && params_to_key(rsa, params);
+
+    return ok;
+}
+
+static int rsa_export(void *keydata, int selection,
+                      OSSL_CALLBACK *param_callback, void *cbarg)
+{
+    RSA *rsa = keydata;
     OSSL_PARAM_BLD tmpl;
     OSSL_PARAM *params = NULL;
-    int ret;
+    int ok = 1;
+
+    if (rsa == NULL)
+        return 0;
+
+    /* TODO(3.0) PSS and OAEP should bring on parameters */
 
     ossl_param_bld_init(&tmpl);
-    if (rsa == NULL
-        || !key_to_params(rsa, &tmpl)
+
+    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
+        ok = ok && key_to_params(rsa, &tmpl);
+
+    if (!ok
         || (params = ossl_param_bld_to_param(&tmpl)) == NULL)
         return 0;
-    ret = param_callback(params, cbarg);
+
+    ok = param_callback(params, cbarg);
     ossl_param_bld_free(params);
-    return ret;
+    return ok;
 }
 
 /*
@@ -242,17 +288,25 @@ static const OSSL_PARAM rsa_key_types[] = {
  * so we at least pretend to have some limits.
  */
 
-static const OSSL_PARAM *rsa_exportkey_types(void)
+static const OSSL_PARAM *rsa_imexport_types(int selection)
 {
-    return rsa_key_types;
+    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
+        return rsa_key_types;
+    return NULL;
 }
 
-static const OSSL_PARAM *rsa_importkey_types(void)
+static const OSSL_PARAM *rsa_import_types(int selection)
 {
-    return rsa_key_types;
+    return rsa_imexport_types(selection);
 }
 
-static int rsa_get_key_params(void *key, OSSL_PARAM params[])
+
+static const OSSL_PARAM *rsa_export_types(int selection)
+{
+    return rsa_imexport_types(selection);
+}
+
+static int rsa_get_params(void *key, OSSL_PARAM params[])
 {
     RSA *rsa = key;
     OSSL_PARAM *p;
@@ -291,39 +345,50 @@ static int rsa_get_key_params(void *key, OSSL_PARAM params[])
     return 1;
 }
 
-static int rsa_validatekey_public(void *key)
-{
-    RSA *rsa = key;
-
-    return rsa_validate_public(rsa);
-}
+static const OSSL_PARAM rsa_params[] = {
+    OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
+    OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
+    OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
+    OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0),
+    OSSL_PARAM_END
+};
 
-static int rsa_validatekey_private(void *key)
+static const OSSL_PARAM *rsa_gettable_params(void)
 {
-    RSA *rsa = key;
-
-    return rsa_validate_private(rsa);
+    return rsa_params;
 }
 
-static int rsa_validatekey_pairwise(void *key)
+static int rsa_validate(void *keydata, int selection)
 {
-    RSA *rsa = key;
-
-    return rsa_validate_pairwise(rsa);
+    RSA *rsa = keydata;
+    int ok = 0;
+
+    if ((selection & RSA_POSSIBLE_SELECTIONS) != 0)
+        ok = 1;
+
+    /* If the whole key is selected, we do a pairwise validation */
+    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR)
+        == OSSL_KEYMGMT_SELECT_KEYPAIR) {
+        ok = ok && rsa_validate_pairwise(rsa);
+    } else {
+        if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+            ok = ok && rsa_validate_private(rsa);
+        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+            ok = ok && rsa_validate_public(rsa);
+    }
+    return ok;
 }
 
 const OSSL_DISPATCH rsa_keymgmt_functions[] = {
-    { OSSL_FUNC_KEYMGMT_IMPORTKEY, (void (*)(void))rsa_importkey },
-    { OSSL_FUNC_KEYMGMT_IMPORTKEY_TYPES, (void (*)(void))rsa_importkey_types },
-    { OSSL_FUNC_KEYMGMT_EXPORTKEY, (void (*)(void))rsa_exportkey },
-    { OSSL_FUNC_KEYMGMT_EXPORTKEY_TYPES, (void (*)(void))rsa_exportkey_types },
-    { OSSL_FUNC_KEYMGMT_FREEKEY, (void (*)(void))RSA_free },
-    { OSSL_FUNC_KEYMGMT_GET_KEY_PARAMS,  (void (*) (void))rsa_get_key_params },
-    { OSSL_FUNC_KEYMGMT_VALIDATE_PUBLIC,
-          (void (*)(void))rsa_validatekey_public },
-    { OSSL_FUNC_KEYMGMT_VALIDATE_PRIVATE,
-          (void (*)(void))rsa_validatekey_private },
-    { OSSL_FUNC_KEYMGMT_VALIDATE_PAIRWISE,
-          (void (*)(void))rsa_validatekey_pairwise },
+    { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))rsa_newdata },
+    { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))rsa_freedata },
+    { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))rsa_get_params },
+    { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))rsa_gettable_params },
+    { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))rsa_has },
+    { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))rsa_validate },
+    { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))rsa_import },
+    { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))rsa_import_types },
+    { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))rsa_export },
+    { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))rsa_export_types },
     { 0, NULL }
 };
diff --git a/providers/implementations/serializers/serializer_common.c b/providers/implementations/serializers/serializer_common.c
index cc6f17908c..daceb11b8c 100644
--- a/providers/implementations/serializers/serializer_common.c
+++ b/providers/implementations/serializers/serializer_common.c
@@ -112,12 +112,32 @@ static X509_PUBKEY *ossl_prov_pubkey_from_obj(const void *obj, int obj_nid,
     return xpk;
 }
 
-OSSL_OP_keymgmt_importkey_fn *ossl_prov_get_importkey(const OSSL_DISPATCH *fns)
+OSSL_OP_keymgmt_new_fn *ossl_prov_get_keymgmt_new(const OSSL_DISPATCH *fns)
 {
     /* Pilfer the keymgmt dispatch table */
     for (; fns->function_id != 0; fns++)
-        if (fns->function_id == OSSL_FUNC_KEYMGMT_IMPORTKEY)
-            return OSSL_get_OP_keymgmt_importkey(fns);
+        if (fns->function_id == OSSL_FUNC_KEYMGMT_NEW)
+            return OSSL_get_OP_keymgmt_new(fns);
+
+    return NULL;
+}
+
+OSSL_OP_keymgmt_free_fn *ossl_prov_get_keymgmt_free(const OSSL_DISPATCH *fns)
+{
+    /* Pilfer the keymgmt dispatch table */
+    for (; fns->function_id != 0; fns++)
+        if (fns->function_id == OSSL_FUNC_KEYMGMT_FREE)
+            return OSSL_get_OP_keymgmt_free(fns);
+
+    return NULL;
+}
+
+OSSL_OP_keymgmt_import_fn *ossl_prov_get_keymgmt_import(const OSSL_DISPATCH *fns)
+{
+    /* Pilfer the keymgmt dispatch table */
+    for (; fns->function_id != 0; fns++)
+        if (fns->function_id == OSSL_FUNC_KEYMGMT_IMPORT)
+            return OSSL_get_OP_keymgmt_import(fns);
 
     return NULL;
 }
diff --git a/providers/implementations/serializers/serializer_dh.c b/providers/implementations/serializers/serializer_dh.c
index 313fae0e30..da74e221ef 100644
--- a/providers/implementations/serializers/serializer_dh.c
+++ b/providers/implementations/serializers/serializer_dh.c
@@ -14,9 +14,19 @@
 #include "prov/providercommonerr.h" /* PROV_R_BN_ERROR */
 #include "serializer_local.h"
 
-OSSL_OP_keymgmt_importkey_fn *ossl_prov_get_dh_importkey(void)
+OSSL_OP_keymgmt_new_fn *ossl_prov_get_keymgmt_dh_new(void)
 {
-    return ossl_prov_get_importkey(dh_keymgmt_functions);
+    return ossl_prov_get_keymgmt_new(dh_keymgmt_functions);
+}
+
+OSSL_OP_keymgmt_free_fn *ossl_prov_get_keymgmt_dh_free(void)
+{
+    return ossl_prov_get_keymgmt_free(dh_keymgmt_functions);
+}
+
+OSSL_OP_keymgmt_import_fn *ossl_prov_get_keymgmt_dh_import(void)
+{
+    return ossl_prov_get_keymgmt_import(dh_keymgmt_functions);
 }
 
 int ossl_prov_print_dh(BIO *out, DH *dh, enum dh_print_type type)
@@ -51,7 +61,7 @@ int ossl_prov_print_dh(BIO *out, DH *dh, enum dh_print_type type)
     }
 
     p = DH_get0_p(dh);
-    g = DH_get0_p(dh);
+    g = DH_get0_g(dh);
     if (p == NULL || g == NULL)
         goto null_err;
 
diff --git a/providers/implementations/serializers/serializer_dh_param.c b/providers/implementations/serializers/serializer_dh_param.c
index ca3371e19f..b445a25220 100644
--- a/providers/implementations/serializers/serializer_dh_param.c
+++ b/providers/implementations/serializers/serializer_dh_param.c
@@ -45,15 +45,20 @@ static void dh_param_freectx(void *ctx)
 static int dh_param_der_data(void *ctx, const OSSL_PARAM params[], BIO *out,
                              OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
-    OSSL_OP_keymgmt_importkey_fn *dh_importkey =
-        ossl_prov_get_dh_importkey();
+    OSSL_OP_keymgmt_new_fn *dh_new = ossl_prov_get_keymgmt_dh_new();
+    OSSL_OP_keymgmt_free_fn *dh_free = ossl_prov_get_keymgmt_dh_free();
+    OSSL_OP_keymgmt_import_fn *dh_import = ossl_prov_get_keymgmt_dh_import();
     int ok = 0;
 
-    if (dh_importkey != NULL) {
-        DH *dh = dh_importkey(ctx, params); /* ctx == provctx */
+    if (dh_import != NULL) {
+        DH *dh;
 
-        ok = dh_param_der(ctx, dh, out, cb, cbarg);
-        DH_free(dh);
+        /* ctx == provctx */
+        if ((dh = dh_new(ctx)) != NULL
+            && dh_import(dh, OSSL_KEYMGMT_SELECT_ALL_PARAMETERS, params)
+            && dh_param_der(ctx, dh, out, cb, cbarg))
+            ok = 1;
+        dh_free(dh);
     }
     return ok;
 }
@@ -66,17 +71,22 @@ static int dh_param_der(void *ctx, void *dh, BIO *out,
 
 /* Public key : PEM */
 static int dh_param_pem_data(void *ctx, const OSSL_PARAM params[], BIO *out,
-                            OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+                             OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
-    OSSL_OP_keymgmt_importkey_fn *dh_importkey =
-        ossl_prov_get_dh_importkey();
+    OSSL_OP_keymgmt_new_fn *dh_new = ossl_prov_get_keymgmt_dh_new();
+    OSSL_OP_keymgmt_free_fn *dh_free = ossl_prov_get_keymgmt_dh_free();
+    OSSL_OP_keymgmt_import_fn *dh_import = ossl_prov_get_keymgmt_dh_import();
     int ok = 0;
 
-    if (dh_importkey != NULL) {
-        DH *dh = dh_importkey(ctx, params); /* ctx == provctx */
+    if (dh_import != NULL) {
+        DH *dh;
 
-        ok = dh_param_pem(ctx, dh, out, cb, cbarg);
-        DH_free(dh);
+        /* ctx == provctx */
+        if ((dh = dh_new(ctx)) != NULL
+            && dh_import(dh, OSSL_KEYMGMT_SELECT_ALL_PARAMETERS, params)
+            && dh_param_pem(ctx, dh, out, cb, cbarg))
+            ok = 1;
+        dh_free(dh);
     }
     return ok;
 }
@@ -88,17 +98,22 @@ static int dh_param_pem(void *ctx, void *dh, BIO *out,
 }
 
 static int dh_param_print_data(void *ctx, const OSSL_PARAM params[], BIO *out,
-                              OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+                               OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
-    OSSL_OP_keymgmt_importkey_fn *dh_importkey =
-        ossl_prov_get_dh_importkey();
+    OSSL_OP_keymgmt_new_fn *dh_new = ossl_prov_get_keymgmt_dh_new();
+    OSSL_OP_keymgmt_free_fn *dh_free = ossl_prov_get_keymgmt_dh_free();
+    OSSL_OP_keymgmt_import_fn *dh_import = ossl_prov_get_keymgmt_dh_import();
     int ok = 0;
 
-    if (dh_importkey != NULL) {
-        DH *dh = dh_importkey(ctx, params); /* ctx == provctx */
+    if (dh_import != NULL) {
+        DH *dh;
 
-        ok = dh_param_print(ctx, dh, out, cb, cbarg);
-        DH_free(dh);
+        /* ctx == provctx */
+        if ((dh = dh_new(ctx)) != NULL
+            && dh_import(dh, OSSL_KEYMGMT_SELECT_ALL_PARAMETERS, params)
+            && dh_param_print(ctx, dh, out, cb, cbarg))
+            ok = 1;
+        dh_free(dh);
     }
     return ok;
 }
diff --git a/providers/implementations/serializers/serializer_dh_priv.c b/providers/implementations/serializers/serializer_dh_priv.c
index a6427dc867..c22f5341b7 100644
--- a/providers/implementations/serializers/serializer_dh_priv.c
+++ b/providers/implementations/serializers/serializer_dh_priv.c
@@ -112,18 +112,22 @@ static int dh_priv_set_ctx_params(void *vctx, const OSSL_PARAM params[])
 
 /* Private key : DER */
 static int dh_priv_der_data(void *vctx, const OSSL_PARAM params[], BIO *out,
-                             OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+                            OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
     struct dh_priv_ctx_st *ctx = vctx;
-    OSSL_OP_keymgmt_importkey_fn *dh_importkey =
-        ossl_prov_get_dh_importkey();
+    OSSL_OP_keymgmt_new_fn *dh_new = ossl_prov_get_keymgmt_dh_new();
+    OSSL_OP_keymgmt_free_fn *dh_free = ossl_prov_get_keymgmt_dh_free();
+    OSSL_OP_keymgmt_import_fn *dh_import = ossl_prov_get_keymgmt_dh_import();
     int ok = 0;
 
-    if (dh_importkey != NULL) {
-        DH *dh = dh_importkey(ctx->provctx, params);
+    if (dh_import != NULL) {
+        DH *dh;
 
-        ok = dh_priv_der(ctx, dh, out, cb, cbarg);
-        DH_free(dh);
+        if ((dh = dh_new(ctx->provctx)) != NULL
+            && dh_import(dh, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && dh_priv_der(ctx, dh, out, cb, cbarg))
+            ok = 1;
+        dh_free(dh);
     }
     return ok;
 }
@@ -147,24 +151,28 @@ static int dh_priv_der(void *vctx, void *dh, BIO *out,
 
 /* Private key : PEM */
 static int dh_pem_priv_data(void *vctx, const OSSL_PARAM params[], BIO *out,
-                             OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+                            OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
     struct dh_priv_ctx_st *ctx = vctx;
-    OSSL_OP_keymgmt_importkey_fn *dh_importkey =
-        ossl_prov_get_dh_importkey();
+    OSSL_OP_keymgmt_new_fn *dh_new = ossl_prov_get_keymgmt_dh_new();
+    OSSL_OP_keymgmt_free_fn *dh_free = ossl_prov_get_keymgmt_dh_free();
+    OSSL_OP_keymgmt_import_fn *dh_import = ossl_prov_get_keymgmt_dh_import();
     int ok = 0;
 
-    if (dh_importkey != NULL) {
-        DH *dh = dh_importkey(ctx, params);
+    if (dh_import != NULL) {
+        DH *dh;
 
-        ok = dh_pem_priv(ctx->provctx, dh, out, cb, cbarg);
-        DH_free(dh);
+        if ((dh = dh_new(ctx->provctx)) != NULL
+            && dh_import(dh, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && dh_pem_priv(ctx->provctx, dh, out, cb, cbarg))
+            ok = 1;
+        dh_free(dh);
     }
     return ok;
 }
 
 static int dh_pem_priv(void *vctx, void *dh, BIO *out,
-                        OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+                       OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
     struct dh_priv_ctx_st *ctx = vctx;
     int ret;
@@ -192,25 +200,29 @@ static void dh_print_freectx(void *ctx)
 {
 }
 
-static int dh_priv_print_data(void *provctx, const OSSL_PARAM params[],
-                               BIO *out,
-                               OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+static int dh_priv_print_data(void *vctx, const OSSL_PARAM params[], BIO *out,
+                              OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
-    OSSL_OP_keymgmt_importkey_fn *dh_importkey =
-        ossl_prov_get_dh_importkey();
+    struct dh_priv_ctx_st *ctx = vctx;
+    OSSL_OP_keymgmt_new_fn *dh_new = ossl_prov_get_keymgmt_dh_new();
+    OSSL_OP_keymgmt_free_fn *dh_free = ossl_prov_get_keymgmt_dh_free();
+    OSSL_OP_keymgmt_import_fn *dh_import = ossl_prov_get_keymgmt_dh_import();
     int ok = 0;
 
-    if (dh_importkey != NULL) {
-        DH *dh = dh_importkey(provctx, params); /* ctx == provctx */
+    if (dh_import != NULL) {
+        DH *dh;
 
-        ok = dh_priv_print(provctx, dh, out, cb, cbarg);
-        DH_free(dh);
+        if ((dh = dh_new(ctx->provctx)) != NULL
+            && dh_import(dh, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && dh_priv_print(ctx, dh, out, cb, cbarg))
+            ok = 1;
+        dh_free(dh);
     }
     return ok;
 }
 
 static int dh_priv_print(void *ctx, void *dh, BIO *out,
-                          OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+                         OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
     return ossl_prov_print_dh(out, dh, dh_print_priv);
 }
diff --git a/providers/implementations/serializers/serializer_dh_pub.c b/providers/implementations/serializers/serializer_dh_pub.c
index 73095c8fd1..9e8d46f252 100644
--- a/providers/implementations/serializers/serializer_dh_pub.c
+++ b/providers/implementations/serializers/serializer_dh_pub.c
@@ -45,15 +45,20 @@ static void dh_pub_freectx(void *ctx)
 static int dh_pub_der_data(void *ctx, const OSSL_PARAM params[], BIO *out,
                             OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
-    OSSL_OP_keymgmt_importkey_fn *dh_importkey =
-        ossl_prov_get_dh_importkey();
+    OSSL_OP_keymgmt_new_fn *dh_new = ossl_prov_get_keymgmt_dh_new();
+    OSSL_OP_keymgmt_free_fn *dh_free = ossl_prov_get_keymgmt_dh_free();
+    OSSL_OP_keymgmt_import_fn *dh_import = ossl_prov_get_keymgmt_dh_import();
     int ok = 0;
 
-    if (dh_importkey != NULL) {
-        DH *dh = dh_importkey(ctx, params); /* ctx == provctx */
+    if (dh_import != NULL) {
+        DH *dh;
 
-        ok = dh_pub_der(ctx, dh, out, cb, cbarg);
-        DH_free(dh);
+        /* ctx == provctx */
+        if ((dh = dh_new(ctx)) != NULL
+            && dh_import(dh, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && dh_pub_der(ctx, dh, out, cb, cbarg))
+            ok = 1;
+        dh_free(dh);
     }
     return ok;
 }
@@ -70,15 +75,20 @@ static int dh_pub_der(void *ctx, void *dh, BIO *out,
 static int dh_pub_pem_data(void *ctx, const OSSL_PARAM params[], BIO *out,
                             OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
-    OSSL_OP_keymgmt_importkey_fn *dh_importkey =
-        ossl_prov_get_dh_importkey();
+    OSSL_OP_keymgmt_new_fn *dh_new = ossl_prov_get_keymgmt_dh_new();
+    OSSL_OP_keymgmt_free_fn *dh_free = ossl_prov_get_keymgmt_dh_free();
+    OSSL_OP_keymgmt_import_fn *dh_import = ossl_prov_get_keymgmt_dh_import();
     int ok = 0;
 
-    if (dh_importkey != NULL) {
-        DH *dh = dh_importkey(ctx, params); /* ctx == provctx */
+    if (dh_import != NULL) {
+        DH *dh;
 
-        ok = dh_pub_pem(ctx, dh, out, cb, cbarg);
-        DH_free(dh);
+        /* ctx == provctx */
+        if ((dh = dh_new(ctx)) != NULL
+            && dh_import(dh, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && dh_pub_pem(ctx, dh, out, cb, cbarg))
+            ok = 1;
+        dh_free(dh);
     }
     return ok;
 }
@@ -95,15 +105,20 @@ static int dh_pub_pem(void *ctx, void *dh, BIO *out,
 static int dh_pub_print_data(void *ctx, const OSSL_PARAM params[], BIO *out,
                               OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
-    OSSL_OP_keymgmt_importkey_fn *dh_importkey =
-        ossl_prov_get_dh_importkey();
+    OSSL_OP_keymgmt_new_fn *dh_new = ossl_prov_get_keymgmt_dh_new();
+    OSSL_OP_keymgmt_free_fn *dh_free = ossl_prov_get_keymgmt_dh_free();
+    OSSL_OP_keymgmt_import_fn *dh_import = ossl_prov_get_keymgmt_dh_import();
     int ok = 0;
 
-    if (dh_importkey != NULL) {
-        DH *dh = dh_importkey(ctx, params); /* ctx == provctx */
+    if (dh_import != NULL) {
+        DH *dh;
 
-        ok = dh_pub_print(ctx, dh, out, cb, cbarg);
-        DH_free(dh);
+        /* ctx == provctx */
+        if ((dh = dh_new(ctx)) != NULL
+            && dh_import(dh, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && dh_pub_print(ctx, dh, out, cb, cbarg))
+            ok = 1;
+        dh_free(dh);
     }
     return ok;
 }
diff --git a/providers/implementations/serializers/serializer_dsa.c b/providers/implementations/serializers/serializer_dsa.c
index 7578c4ef2e..e24d66fc82 100644
--- a/providers/implementations/serializers/serializer_dsa.c
+++ b/providers/implementations/serializers/serializer_dsa.c
@@ -14,9 +14,19 @@
 #include "prov/providercommonerr.h" /* PROV_R_BN_ERROR */
 #include "serializer_local.h"
 
-OSSL_OP_keymgmt_importkey_fn *ossl_prov_get_dsa_importkey(void)
+OSSL_OP_keymgmt_new_fn *ossl_prov_get_keymgmt_dsa_new(void)
 {
-    return ossl_prov_get_importkey(dsa_keymgmt_functions);
+    return ossl_prov_get_keymgmt_new(dsa_keymgmt_functions);
+}
+
+OSSL_OP_keymgmt_free_fn *ossl_prov_get_keymgmt_dsa_free(void)
+{
+    return ossl_prov_get_keymgmt_free(dsa_keymgmt_functions);
+}
+
+OSSL_OP_keymgmt_import_fn *ossl_prov_get_keymgmt_dsa_import(void)
+{
+    return ossl_prov_get_keymgmt_import(dsa_keymgmt_functions);
 }
 
 int ossl_prov_print_dsa(BIO *out, DSA *dsa, enum dsa_print_type type)
diff --git a/providers/implementations/serializers/serializer_dsa_param.c b/providers/implementations/serializers/serializer_dsa_param.c
index 3a108f61ad..59549887af 100644
--- a/providers/implementations/serializers/serializer_dsa_param.c
+++ b/providers/implementations/serializers/serializer_dsa_param.c
@@ -43,68 +43,83 @@ static void dsa_param_freectx(void *ctx)
 
 /* Public key : DER */
 static int dsa_param_der_data(void *ctx, const OSSL_PARAM params[], BIO *out,
-                             OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+                              OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
-    OSSL_OP_keymgmt_importkey_fn *dsa_importkey =
-        ossl_prov_get_dsa_importkey();
+    OSSL_OP_keymgmt_new_fn *dsa_new = ossl_prov_get_keymgmt_dsa_new();
+    OSSL_OP_keymgmt_free_fn *dsa_free = ossl_prov_get_keymgmt_dsa_free();
+    OSSL_OP_keymgmt_import_fn *dsa_import = ossl_prov_get_keymgmt_dsa_import();
     int ok = 0;
 
-    if (dsa_importkey != NULL) {
-        DSA *dsa = dsa_importkey(ctx, params); /* ctx == provctx */
+    if (dsa_import != NULL) {
+        DSA *dsa;
 
-        ok = dsa_param_der(ctx, dsa, out, cb, cbarg);
-        DSA_free(dsa);
+        /* ctx == provctx */
+        if ((dsa = dsa_new(ctx)) != NULL
+            && dsa_import(dsa, OSSL_KEYMGMT_SELECT_ALL_PARAMETERS, params)
+            && dsa_param_der(ctx, dsa, out, cb, cbarg))
+            ok = 1;
+        dsa_free(dsa);
     }
     return ok;
 }
 
 static int dsa_param_der(void *ctx, void *dsa, BIO *out,
-                        OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+                         OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
     return i2d_DSAparams_bio(out, dsa);
 }
 
 /* Public key : PEM */
 static int dsa_param_pem_data(void *ctx, const OSSL_PARAM params[], BIO *out,
-                            OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+                              OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
-    OSSL_OP_keymgmt_importkey_fn *dsa_importkey =
-        ossl_prov_get_dsa_importkey();
+    OSSL_OP_keymgmt_new_fn *dsa_new = ossl_prov_get_keymgmt_dsa_new();
+    OSSL_OP_keymgmt_free_fn *dsa_free = ossl_prov_get_keymgmt_dsa_free();
+    OSSL_OP_keymgmt_import_fn *dsa_import = ossl_prov_get_keymgmt_dsa_import();
     int ok = 0;
 
-    if (dsa_importkey != NULL) {
-        DSA *dsa = dsa_importkey(ctx, params); /* ctx == provctx */
+    if (dsa_import != NULL) {
+        DSA *dsa;
 
-        ok = dsa_param_pem(ctx, dsa, out, cb, cbarg);
-        DSA_free(dsa);
+        /* ctx == provctx */
+        if ((dsa = dsa_new(ctx)) != NULL
+            && dsa_import(dsa, OSSL_KEYMGMT_SELECT_ALL_PARAMETERS, params)
+            && dsa_param_pem(ctx, dsa, out, cb, cbarg))
+            ok = 1;
+        dsa_free(dsa);
     }
     return ok;
 }
 
 static int dsa_param_pem(void *ctx, void *dsa, BIO *out,
-                       OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+                         OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
     return PEM_write_bio_DSAparams(out, dsa);
 }
 
 static int dsa_param_print_data(void *ctx, const OSSL_PARAM params[], BIO *out,
-                              OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+                                OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
-    OSSL_OP_keymgmt_importkey_fn *dsa_importkey =
-        ossl_prov_get_dsa_importkey();
+    OSSL_OP_keymgmt_new_fn *dsa_new = ossl_prov_get_keymgmt_dsa_new();
+    OSSL_OP_keymgmt_free_fn *dsa_free = ossl_prov_get_keymgmt_dsa_free();
+    OSSL_OP_keymgmt_import_fn *dsa_import = ossl_prov_get_keymgmt_dsa_import();
     int ok = 0;
 
-    if (dsa_importkey != NULL) {
-        DSA *dsa = dsa_importkey(ctx, params); /* ctx == provctx */
+    if (dsa_import != NULL) {
+        DSA *dsa;
 
-        ok = dsa_param_print(ctx, dsa, out, cb, cbarg);
-        DSA_free(dsa);
+        /* ctx == provctx */
+        if ((dsa = dsa_new(ctx)) != NULL
+            && dsa_import(dsa, OSSL_KEYMGMT_SELECT_ALL_PARAMETERS, params)
+            && dsa_param_print(ctx, dsa, out, cb, cbarg))
+            ok = 1;
+        dsa_free(dsa);
     }
     return ok;
 }
 
 static int dsa_param_print(void *ctx, void *dsa, BIO *out,
-                         OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+                           OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
     return ossl_prov_print_dsa(out, dsa, dsa_print_params);
 }
diff --git a/providers/implementations/serializers/serializer_dsa_priv.c b/providers/implementations/serializers/serializer_dsa_priv.c
index fc0a340ca2..f3a9ef8f87 100644
--- a/providers/implementations/serializers/serializer_dsa_priv.c
+++ b/providers/implementations/serializers/serializer_dsa_priv.c
@@ -115,15 +115,19 @@ static int dsa_priv_der_data(void *vctx, const OSSL_PARAM params[], BIO *out,
                              OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
     struct dsa_priv_ctx_st *ctx = vctx;
-    OSSL_OP_keymgmt_importkey_fn *dsa_importkey =
-        ossl_prov_get_dsa_importkey();
+    OSSL_OP_keymgmt_new_fn *dsa_new = ossl_prov_get_keymgmt_dsa_new();
+    OSSL_OP_keymgmt_free_fn *dsa_free = ossl_prov_get_keymgmt_dsa_free();
+    OSSL_OP_keymgmt_import_fn *dsa_import = ossl_prov_get_keymgmt_dsa_import();
     int ok = 0;
 
-    if (dsa_importkey != NULL) {
-        DSA *dsa = dsa_importkey(ctx->provctx, params);
+    if (dsa_import != NULL) {
+        DSA *dsa;
 
-        ok = dsa_priv_der(ctx, dsa, out, cb, cbarg);
-        DSA_free(dsa);
+        if ((dsa = dsa_new(ctx->provctx)) != NULL
+            && dsa_import(dsa, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && dsa_priv_der(ctx, dsa, out, cb, cbarg))
+            ok = 1;
+        dsa_free(dsa);
     }
     return ok;
 }
@@ -147,15 +151,19 @@ static int dsa_pem_priv_data(void *vctx, const OSSL_PARAM params[], BIO *out,
                              OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
     struct dsa_priv_ctx_st *ctx = vctx;
-    OSSL_OP_keymgmt_importkey_fn *dsa_importkey =
-        ossl_prov_get_dsa_importkey();
+    OSSL_OP_keymgmt_new_fn *dsa_new = ossl_prov_get_keymgmt_dsa_new();
+    OSSL_OP_keymgmt_free_fn *dsa_free = ossl_prov_get_keymgmt_dsa_free();
+    OSSL_OP_keymgmt_import_fn *dsa_import = ossl_prov_get_keymgmt_dsa_import();
     int ok = 0;
 
-    if (dsa_importkey != NULL) {
-        DSA *dsa = dsa_importkey(ctx, params);
+    if (dsa_import != NULL) {
+        DSA *dsa;
 
-        ok = dsa_pem_priv(ctx->provctx, dsa, out, cb, cbarg);
-        DSA_free(dsa);
+        if ((dsa = dsa_new(ctx->provctx)) != NULL
+            && dsa_import(dsa, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && dsa_pem_priv(ctx, dsa, out, cb, cbarg))
+            ok = 1;
+        dsa_free(dsa);
     }
     return ok;
 }
@@ -186,19 +194,24 @@ static void dsa_print_freectx(void *ctx)
 {
 }
 
-static int dsa_priv_print_data(void *provctx, const OSSL_PARAM params[],
+static int dsa_priv_print_data(void *vctx, const OSSL_PARAM params[],
                                BIO *out,
                                OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
-    OSSL_OP_keymgmt_importkey_fn *dsa_importkey =
-        ossl_prov_get_dsa_importkey();
+    struct dsa_priv_ctx_st *ctx = vctx;
+    OSSL_OP_keymgmt_new_fn *dsa_new = ossl_prov_get_keymgmt_dsa_new();
+    OSSL_OP_keymgmt_free_fn *dsa_free = ossl_prov_get_keymgmt_dsa_free();
+    OSSL_OP_keymgmt_import_fn *dsa_import = ossl_prov_get_keymgmt_dsa_import();
     int ok = 0;
 
-    if (dsa_importkey != NULL) {
-        DSA *dsa = dsa_importkey(provctx, params); /* ctx == provctx */
+    if (dsa_import != NULL) {
+        DSA *dsa;
 
-        ok = dsa_priv_print(provctx, dsa, out, cb, cbarg);
-        DSA_free(dsa);
+        if ((dsa = dsa_new(ctx->provctx)) != NULL
+            && dsa_import(dsa, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && dsa_priv_print(ctx, dsa, out, cb, cbarg))
+            ok = 1;
+        dsa_free(dsa);
     }
     return ok;
 }
diff --git a/providers/implementations/serializers/serializer_dsa_pub.c b/providers/implementations/serializers/serializer_dsa_pub.c
index 0901718a93..933f1efa4b 100644
--- a/providers/implementations/serializers/serializer_dsa_pub.c
+++ b/providers/implementations/serializers/serializer_dsa_pub.c
@@ -45,15 +45,20 @@ static void dsa_pub_freectx(void *ctx)
 static int dsa_pub_der_data(void *ctx, const OSSL_PARAM params[], BIO *out,
                             OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
-    OSSL_OP_keymgmt_importkey_fn *dsa_importkey =
-        ossl_prov_get_dsa_importkey();
+    OSSL_OP_keymgmt_new_fn *dsa_new = ossl_prov_get_keymgmt_dsa_new();
+    OSSL_OP_keymgmt_free_fn *dsa_free = ossl_prov_get_keymgmt_dsa_free();
+    OSSL_OP_keymgmt_import_fn *dsa_import = ossl_prov_get_keymgmt_dsa_import();
     int ok = 0;
 
-    if (dsa_importkey != NULL) {
-        DSA *dsa = dsa_importkey(ctx, params); /* ctx == provctx */
+    if (dsa_import != NULL) {
+        DSA *dsa;
 
-        ok = dsa_pub_der(ctx, dsa, out, cb, cbarg);
-        DSA_free(dsa);
+        /* ctx == provctx */
+        if ((dsa = dsa_new(ctx)) != NULL
+            && dsa_import(dsa, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && dsa_pub_der(ctx, dsa, out, cb, cbarg))
+            ok = 1;
+        dsa_free(dsa);
     }
     return ok;
 }
@@ -82,15 +87,20 @@ static int dsa_pub_der(void *ctx, void *dsa, BIO *out,
 static int dsa_pub_pem_data(void *ctx, const OSSL_PARAM params[], BIO *out,
                             OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
-    OSSL_OP_keymgmt_importkey_fn *dsa_importkey =
-        ossl_prov_get_dsa_importkey();
+    OSSL_OP_keymgmt_new_fn *dsa_new = ossl_prov_get_keymgmt_dsa_new();
+    OSSL_OP_keymgmt_free_fn *dsa_free = ossl_prov_get_keymgmt_dsa_free();
+    OSSL_OP_keymgmt_import_fn *dsa_import = ossl_prov_get_keymgmt_dsa_import();
     int ok = 0;
 
-    if (dsa_importkey != NULL) {
-        DSA *dsa = dsa_importkey(ctx, params); /* ctx == provctx */
+    if (dsa_import != NULL) {
+        DSA *dsa;
 
-        ok = dsa_pub_pem(ctx, dsa, out, cb, cbarg);
-        DSA_free(dsa);
+        /* ctx == provctx */
+        if ((dsa = dsa_new(ctx)) != NULL
+            && dsa_import(dsa, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && dsa_pub_pem(ctx, dsa, out, cb, cbarg))
+            ok = 1;
+        dsa_free(dsa);
     }
     return ok;
 }
@@ -106,15 +116,20 @@ static int dsa_pub_pem(void *ctx, void *dsa, BIO *out,
 static int dsa_pub_print_data(void *ctx, const OSSL_PARAM params[], BIO *out,
                               OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
-    OSSL_OP_keymgmt_importkey_fn *dsa_importkey =
-        ossl_prov_get_dsa_importkey();
+    OSSL_OP_keymgmt_new_fn *dsa_new = ossl_prov_get_keymgmt_dsa_new();
+    OSSL_OP_keymgmt_free_fn *dsa_free = ossl_prov_get_keymgmt_dsa_free();
+    OSSL_OP_keymgmt_import_fn *dsa_import = ossl_prov_get_keymgmt_dsa_import();
     int ok = 0;
 
-    if (dsa_importkey != NULL) {
-        DSA *dsa = dsa_importkey(ctx, params); /* ctx == provctx */
+    if (dsa_import != NULL) {
+        DSA *dsa;
 
-        ok = dsa_pub_print(ctx, dsa, out, cb, cbarg);
-        DSA_free(dsa);
+        /* ctx == provctx */
+        if ((dsa = dsa_new(ctx)) != NULL
+            && dsa_import(dsa, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && dsa_pub_print(ctx, dsa, out, cb, cbarg))
+            ok = 1;
+        dsa_free(dsa);
     }
     return ok;
 }
diff --git a/providers/implementations/serializers/serializer_local.h b/providers/implementations/serializers/serializer_local.h
index 8507a740a2..801d221da6 100644
--- a/providers/implementations/serializers/serializer_local.h
+++ b/providers/implementations/serializers/serializer_local.h
@@ -30,11 +30,19 @@ struct pkcs8_encrypt_ctx_st {
     void *cbarg;
 };
 
-OSSL_OP_keymgmt_importkey_fn *ossl_prov_get_importkey(const OSSL_DISPATCH *fns);
+OSSL_OP_keymgmt_new_fn *ossl_prov_get_keymgmt_new(const OSSL_DISPATCH *fns);
+OSSL_OP_keymgmt_free_fn *ossl_prov_get_keymgmt_free(const OSSL_DISPATCH *fns);
+OSSL_OP_keymgmt_import_fn *ossl_prov_get_keymgmt_import(const OSSL_DISPATCH *fns);
 
-OSSL_OP_keymgmt_importkey_fn *ossl_prov_get_rsa_importkey(void);
-OSSL_OP_keymgmt_importkey_fn *ossl_prov_get_dh_importkey(void);
-OSSL_OP_keymgmt_importkey_fn *ossl_prov_get_dsa_importkey(void);
+OSSL_OP_keymgmt_new_fn *ossl_prov_get_keymgmt_rsa_new(void);
+OSSL_OP_keymgmt_free_fn *ossl_prov_get_keymgmt_rsa_free(void);
+OSSL_OP_keymgmt_import_fn *ossl_prov_get_keymgmt_rsa_import(void);
+OSSL_OP_keymgmt_new_fn *ossl_prov_get_keymgmt_dh_new(void);
+OSSL_OP_keymgmt_free_fn *ossl_prov_get_keymgmt_dh_free(void);
+OSSL_OP_keymgmt_import_fn *ossl_prov_get_keymgmt_dh_import(void);
+OSSL_OP_keymgmt_new_fn *ossl_prov_get_keymgmt_dsa_new(void);
+OSSL_OP_keymgmt_free_fn *ossl_prov_get_keymgmt_dsa_free(void);
+OSSL_OP_keymgmt_import_fn *ossl_prov_get_keymgmt_dsa_import(void);
 
 int ossl_prov_prepare_dh_params(const void *dh, int nid,
                                 ASN1_STRING **pstr, int *pstrtype);
diff --git a/providers/implementations/serializers/serializer_rsa.c b/providers/implementations/serializers/serializer_rsa.c
index ac8e4a2bbe..9aaefb56bc 100644
--- a/providers/implementations/serializers/serializer_rsa.c
+++ b/providers/implementations/serializers/serializer_rsa.c
@@ -14,9 +14,19 @@
 
 DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
 
-OSSL_OP_keymgmt_importkey_fn *ossl_prov_get_rsa_importkey(void)
+OSSL_OP_keymgmt_new_fn *ossl_prov_get_keymgmt_rsa_new(void)
 {
-    return ossl_prov_get_importkey(rsa_keymgmt_functions);
+    return ossl_prov_get_keymgmt_new(rsa_keymgmt_functions);
+}
+
+OSSL_OP_keymgmt_free_fn *ossl_prov_get_keymgmt_rsa_free(void)
+{
+    return ossl_prov_get_keymgmt_free(rsa_keymgmt_functions);
+}
+
+OSSL_OP_keymgmt_import_fn *ossl_prov_get_keymgmt_rsa_import(void)
+{
+    return ossl_prov_get_keymgmt_import(rsa_keymgmt_functions);
 }
 
 int ossl_prov_print_rsa(BIO *out, RSA *rsa, int priv)
diff --git a/providers/implementations/serializers/serializer_rsa_priv.c b/providers/implementations/serializers/serializer_rsa_priv.c
index 3d16e43a4b..c236739e0e 100644
--- a/providers/implementations/serializers/serializer_rsa_priv.c
+++ b/providers/implementations/serializers/serializer_rsa_priv.c
@@ -143,15 +143,19 @@ static int rsa_priv_der_data(void *vctx, const OSSL_PARAM params[], BIO *out,
                              OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
     struct rsa_priv_ctx_st *ctx = vctx;
-    OSSL_OP_keymgmt_importkey_fn *rsa_importkey =
-        ossl_prov_get_rsa_importkey();
+    OSSL_OP_keymgmt_new_fn *rsa_new = ossl_prov_get_keymgmt_rsa_new();
+    OSSL_OP_keymgmt_free_fn *rsa_free = ossl_prov_get_keymgmt_rsa_free();
+    OSSL_OP_keymgmt_import_fn *rsa_import = ossl_prov_get_keymgmt_rsa_import();
     int ok = 0;
 
-    if (rsa_importkey != NULL) {
-        RSA *rsa = rsa_importkey(ctx->provctx, params);
+    if (rsa_import != NULL) {
+        RSA *rsa;
 
-        ok = rsa_priv_der(vctx, rsa, out, cb, cbarg);
-        RSA_free(rsa);
+        if ((rsa = rsa_new(ctx->provctx)) != NULL
+            && rsa_import(rsa, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && rsa_priv_der(ctx, rsa, out, cb, cbarg))
+            ok = 1;
+        rsa_free(rsa);
     }
     return ok;
 }
@@ -178,15 +182,19 @@ static int rsa_pem_priv_data(void *vctx, const OSSL_PARAM params[], BIO *out,
                              OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
     struct rsa_priv_ctx_st *ctx = vctx;
-    OSSL_OP_keymgmt_importkey_fn *rsa_importkey =
-        ossl_prov_get_rsa_importkey();
+    OSSL_OP_keymgmt_new_fn *rsa_new = ossl_prov_get_keymgmt_rsa_new();
+    OSSL_OP_keymgmt_free_fn *rsa_free = ossl_prov_get_keymgmt_rsa_free();
+    OSSL_OP_keymgmt_import_fn *rsa_import = ossl_prov_get_keymgmt_rsa_import();
     int ok = 0;
 
-    if (rsa_importkey != NULL) {
-        RSA *rsa = rsa_importkey(ctx, params);
+    if (rsa_import != NULL) {
+        RSA *rsa;
 
-        ok = rsa_pem_priv(vctx, rsa, out, cb, cbarg);
-        RSA_free(rsa);
+        if ((rsa = rsa_new(ctx->provctx)) != NULL
+            && rsa_import(rsa, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && rsa_pem_priv(ctx, rsa, out, cb, cbarg))
+            ok = 1;
+        rsa_free(rsa);
     }
     return ok;
 }
@@ -220,19 +228,24 @@ static void rsa_print_freectx(void *ctx)
 {
 }
 
-static int rsa_priv_print_data(void *provctx, const OSSL_PARAM params[],
+static int rsa_priv_print_data(void *vctx, const OSSL_PARAM params[],
                                BIO *out,
                                OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
-    OSSL_OP_keymgmt_importkey_fn *rsa_importkey =
-        ossl_prov_get_rsa_importkey();
+    struct rsa_priv_ctx_st *ctx = vctx;
+    OSSL_OP_keymgmt_new_fn *rsa_new = ossl_prov_get_keymgmt_rsa_new();
+    OSSL_OP_keymgmt_free_fn *rsa_free = ossl_prov_get_keymgmt_rsa_free();
+    OSSL_OP_keymgmt_import_fn *rsa_import = ossl_prov_get_keymgmt_rsa_import();
     int ok = 0;
 
-    if (rsa_importkey != NULL) {
-        RSA *rsa = rsa_importkey(provctx, params); /* ctx == provctx */
+    if (rsa_import != NULL) {
+        RSA *rsa;
 
-        ok = rsa_priv_print(provctx, rsa, out, cb, cbarg);
-        RSA_free(rsa);
+        if ((rsa = rsa_new(ctx->provctx)) != NULL
+            && rsa_import(rsa, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && rsa_priv_print(ctx, rsa, out, cb, cbarg))
+            ok = 1;
+        rsa_free(rsa);
     }
     return ok;
 }
diff --git a/providers/implementations/serializers/serializer_rsa_pub.c b/providers/implementations/serializers/serializer_rsa_pub.c
index c975499d7c..f7eccf7624 100644
--- a/providers/implementations/serializers/serializer_rsa_pub.c
+++ b/providers/implementations/serializers/serializer_rsa_pub.c
@@ -45,15 +45,20 @@ static void rsa_pub_freectx(void *ctx)
 static int rsa_pub_der_data(void *ctx, const OSSL_PARAM params[], BIO *out,
                             OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
-    OSSL_OP_keymgmt_importkey_fn *rsa_importkey =
-        ossl_prov_get_rsa_importkey();
+    OSSL_OP_keymgmt_new_fn *rsa_new = ossl_prov_get_keymgmt_rsa_new();
+    OSSL_OP_keymgmt_free_fn *rsa_free = ossl_prov_get_keymgmt_rsa_free();
+    OSSL_OP_keymgmt_import_fn *rsa_import = ossl_prov_get_keymgmt_rsa_import();
     int ok = 0;
 
-    if (rsa_importkey != NULL) {
-        RSA *rsa = rsa_importkey(ctx, params); /* ctx == provctx */
+    if (rsa_import != NULL) {
+        RSA *rsa;
 
-        ok = rsa_pub_der(ctx, rsa, out, cb, cbarg);
-        RSA_free(rsa);
+        /* ctx == provctx */
+        if ((rsa = rsa_new(ctx)) != NULL
+            && rsa_import(rsa, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && rsa_pub_der(ctx, rsa, out, cb, cbarg))
+            ok = 1;
+        rsa_free(rsa);
     }
     return ok;
 }
@@ -68,15 +73,20 @@ static int rsa_pub_der(void *ctx, void *rsa, BIO *out,
 static int rsa_pub_pem_data(void *ctx, const OSSL_PARAM params[], BIO *out,
                             OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
-    OSSL_OP_keymgmt_importkey_fn *rsa_importkey =
-        ossl_prov_get_rsa_importkey();
+    OSSL_OP_keymgmt_new_fn *rsa_new = ossl_prov_get_keymgmt_rsa_new();
+    OSSL_OP_keymgmt_free_fn *rsa_free = ossl_prov_get_keymgmt_rsa_free();
+    OSSL_OP_keymgmt_import_fn *rsa_import = ossl_prov_get_keymgmt_rsa_import();
     int ok = 0;
 
-    if (rsa_importkey != NULL) {
-        RSA *rsa = rsa_importkey(ctx, params); /* ctx == provctx */
+    if (rsa_import != NULL) {
+        RSA *rsa;
 
-        ok = rsa_pub_pem(ctx, rsa, out, cb, cbarg);
-        RSA_free(rsa);
+        /* ctx == provctx */
+        if ((rsa = rsa_new(ctx)) != NULL
+            && rsa_import(rsa, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && rsa_pub_pem(ctx, rsa, out, cb, cbarg))
+            ok = 1;
+        rsa_free(rsa);
     }
     return ok;
 }
@@ -90,15 +100,20 @@ static int rsa_pub_pem(void *ctx, void *rsa, BIO *out,
 static int rsa_pub_print_data(void *ctx, const OSSL_PARAM params[], BIO *out,
                               OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
-    OSSL_OP_keymgmt_importkey_fn *rsa_importkey =
-        ossl_prov_get_rsa_importkey();
+    OSSL_OP_keymgmt_new_fn *rsa_new = ossl_prov_get_keymgmt_rsa_new();
+    OSSL_OP_keymgmt_free_fn *rsa_free = ossl_prov_get_keymgmt_rsa_free();
+    OSSL_OP_keymgmt_import_fn *rsa_import = ossl_prov_get_keymgmt_rsa_import();
     int ok = 0;
 
-    if (rsa_importkey != NULL) {
-        RSA *rsa = rsa_importkey(ctx, params); /* ctx == provctx */
+    if (rsa_import != NULL) {
+        RSA *rsa;
 
-        ok = rsa_pub_print(ctx, rsa, out, cb, cbarg);
-        RSA_free(rsa);
+        /* ctx == provctx */
+        if ((rsa = rsa_new(ctx)) != NULL
+            && rsa_import(rsa, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && rsa_pub_print(ctx, rsa, out, cb, cbarg))
+            ok = 1;
+        rsa_free(rsa);
     }
     return ok;
 }
diff --git a/test/keymgmt_internal_test.c b/test/keymgmt_internal_test.c
index e621412390..ad2e1deb5c 100644
--- a/test/keymgmt_internal_test.c
+++ b/test/keymgmt_internal_test.c
@@ -145,7 +145,7 @@ static int test_pass_rsa(FIXTURE *fixture)
     BIGNUM *bn1 = NULL, *bn2 = NULL, *bn3 = NULL;
     EVP_PKEY *pk = NULL;
     EVP_KEYMGMT *km1 = NULL, *km2 = NULL;
-    void *provdata = NULL;
+    void *provkey = NULL;
     /*
      * 32-bit RSA key, extracted from this command,
      * executed with OpenSSL 1.0.2:
@@ -207,11 +207,13 @@ static int test_pass_rsa(FIXTURE *fixture)
         || !TEST_ptr_ne(km1, km2))
         goto err;
 
-    if (!TEST_ptr(evp_keymgmt_export_to_provider(pk, km1, 0))
-        || !TEST_ptr(provdata = evp_keymgmt_export_to_provider(pk, km2, 0)))
+    if (!TEST_ptr(evp_keymgmt_util_export_to_provider(pk, km1))
+        || !TEST_ptr(provkey = evp_keymgmt_util_export_to_provider(pk, km2)))
         goto err;
 
-    if (!TEST_true(evp_keymgmt_exportkey(km2, provdata, &export_cb, keydata)))
+    if (!TEST_true(evp_keymgmt_export(km2, provkey,
+                                      OSSL_KEYMGMT_SELECT_KEYPAIR,
+                                      &export_cb, keydata)))
         goto err;
 
     /*


More information about the openssl-commits mailing list