[openssl] master update

Richard Levitte levitte at openssl.org
Mon Jul 22 04:25:50 UTC 2019


The branch master has been updated
       via  fa9faf010460f5fe0722a65f9d496221c2f41f7b (commit)
       via  4cae07fef3b24bee1646f6085c52175ef3755d5b (commit)
       via  d0ea49a820e02713bbe8892a333f2552da633b16 (commit)
       via  70a1f7b4d7a0611508f45ef884472b9d84cbe108 (commit)
       via  a94a3e0d91378b5c478f687a0dbc51914d4ed497 (commit)
      from  7312ef3fc4a7d391272f3ba8075eabf81a229ad2 (commit)


- Log -----------------------------------------------------------------
commit fa9faf010460f5fe0722a65f9d496221c2f41f7b
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Jul 11 12:52:16 2019 +0200

    Add an internal API to access the KEYMGMT provider functions
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9312)

commit 4cae07fef3b24bee1646f6085c52175ef3755d5b
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Jul 10 14:30:55 2019 +0200

    Add evp_keymgmt_clear_pkey_cache() and use it
    
    This function clears the cache of provider key references, and is used
    in evp_keymgmt_export_to_provider() when the internal key is dirty, as
    well as by EVP_PKEY_free_it().
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9312)

commit d0ea49a820e02713bbe8892a333f2552da633b16
Author: Richard Levitte <levitte at openssl.org>
Date:   Tue Jul 9 17:31:24 2019 +0200

    Adapt int_ctx_new() to use with providers
    
    This affects all its callers: EVP_PKEY_CTX_new(), EVP_PKEY_CTX_new_id().
    They are now possible to called with "zero" values, i.e.:
    
        EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(NULL, NULL);
    
    or
    
        EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(0, NULL);
    
    This is suitable for provider use, as the key functionality is tied
    with its keys, and the operation time is determined by the init
    functions the EVP_PKEY_CTX is used with.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9312)

commit 70a1f7b4d7a0611508f45ef884472b9d84cbe108
Author: Richard Levitte <levitte at openssl.org>
Date:   Sat Jul 6 21:57:15 2019 +0200

    Add evp_keymgmt_export_to_provider(), for key transfer between providers
    
    This function is used to transport private key materia from whatever
    is already attached to the EVP_PKEY to the new provider, using key
    data export and import functionality.
    
    If a legacy lower level key has been assigned to the EVP_PKEY, we use
    its data to create a provider side key, and thereby have a bridge
    between old style public key types and the EVP_PKEY on providers.
    
    If successful, this function returns a reference to the appropriate
    provider side data for the key.
    
    This can be used by any operation that wants to use this key.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9312)

commit a94a3e0d91378b5c478f687a0dbc51914d4ed497
Author: Richard Levitte <levitte at openssl.org>
Date:   Fri Jul 5 00:31:42 2019 +0200

    Add basic EVP_KEYMGMT API and libcrypto <-> provider interface
    
    The idea with the key management "operation" is to support the
    following set of functionality:
    
    - Key domain parameter generation
    - Key domain parameter import
    - Key domain parameter export
    
    - Key generation
    - Key import
    - Key export
    - Key loading (HSM / hidden key support)
    
    With that set of function, we can support handling domain parameters
    on one provider, key handling on another, and key usage on a third,
    with transparent export / import of applicable data.  Of course, if a
    provider doesn't offer export / import functionality, then all
    operations surrounding a key must be performed with the same
    provider.
    
    This method also avoids having to do anything special with legacy
    assignment of libcrypto key structures, i.e. EVP_PKEY_assign_RSA().
    They will simply be used as keys to be exported from whenever they are
    used with provider based operations.
    
    This change only adds the EVP_KEYMGMT API and the libcrypto <->
    provider interface.  Further changes will integrate them into existing
    libcrypto functionality.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9312)

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

Summary of changes:
 crypto/evp/build.info                              |   3 +-
 crypto/evp/evp_locl.h                              |  27 +-
 crypto/evp/keymgmt_lib.c                           | 288 +++++++++++++++++++++
 crypto/evp/keymgmt_meth.c                          | 189 ++++++++++++++
 crypto/evp/p_lib.c                                 |   3 +
 crypto/evp/pmeth_lib.c                             |  16 +-
 crypto/include/internal/asn1_int.h                 |   8 +
 crypto/include/internal/evp_int.h                  |  57 +++-
 .../man3/evp_keymgmt_export_to_provider.pod        |  56 ++++
 doc/internal/man3/evp_keymgmt_freekey.pod          | 109 ++++++++
 doc/man3/EVP_KEYMGMT.pod                           |  84 ++++++
 doc/man3/EVP_PKEY_ASN1_METHOD.pod                  |  10 +
 include/openssl/core_numbers.h                     |  73 +++++-
 include/openssl/evp.h                              |   6 +
 include/openssl/ossl_typ.h                         |   2 +
 util/libcrypto.num                                 |   4 +
 util/private.num                                   |   1 +
 17 files changed, 928 insertions(+), 8 deletions(-)
 create mode 100644 crypto/evp/keymgmt_lib.c
 create mode 100644 crypto/evp/keymgmt_meth.c
 create mode 100644 doc/internal/man3/evp_keymgmt_export_to_provider.pod
 create mode 100644 doc/internal/man3/evp_keymgmt_freekey.pod
 create mode 100644 doc/man3/EVP_KEYMGMT.pod

diff --git a/crypto/evp/build.info b/crypto/evp/build.info
index 5030f3f..c650c28 100644
--- a/crypto/evp/build.info
+++ b/crypto/evp/build.info
@@ -1,5 +1,6 @@
 LIBS=../../libcrypto
-$COMMON=digest.c evp_enc.c evp_lib.c evp_fetch.c cmeth_lib.c evp_utils.c
+$COMMON=digest.c evp_enc.c evp_lib.c evp_fetch.c cmeth_lib.c evp_utils.c \
+        keymgmt_meth.c keymgmt_lib.c
 SOURCE[../../libcrypto]=$COMMON\
         encode.c evp_key.c evp_cnf.c \
         e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\
diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h
index 8aeb5d4..740c159 100644
--- a/crypto/evp/evp_locl.h
+++ b/crypto/evp/evp_locl.h
@@ -62,6 +62,32 @@ struct evp_kdf_ctx_st {
     EVP_KDF_IMPL *impl;          /* Algorithm-specific data */
 } /* EVP_KDF_CTX */ ;
 
+struct evp_keymgmt_st {
+    int id;                      /* libcrypto internal */
+
+    const char *name;
+    OSSL_PROVIDER *prov;
+    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;
+
+    /* 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;
+} /* EVP_KEYMGMT */ ;
+
 struct evp_keyexch_st {
     OSSL_PROVIDER *prov;
     CRYPTO_REF_COUNT refcnt;
@@ -76,7 +102,6 @@ struct evp_keyexch_st {
     OSSL_OP_keyexch_set_params_fn *set_params;
 } /* EVP_KEYEXCH */;
 
-
 int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
                              int passlen, ASN1_TYPE *param,
                              const EVP_CIPHER *c, const EVP_MD *md,
diff --git a/crypto/evp/keymgmt_lib.c b/crypto/evp/keymgmt_lib.c
new file mode 100644
index 0000000..8ee28fb
--- /dev/null
+++ b/crypto/evp/keymgmt_lib.c
@@ -0,0 +1,288 @@
+/*
+ * 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
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/cryptlib.h"
+#include "internal/nelem.h"
+#include "internal/evp_int.h"
+#include "internal/asn1_int.h"
+#include "internal/provider.h"
+#include "evp_locl.h"
+
+static OSSL_PARAM *paramdefs_to_params(const OSSL_PARAM *paramdefs)
+{
+    size_t cnt;
+    const OSSL_PARAM *p;
+    OSSL_PARAM *params, *q;
+
+    for (cnt = 1, p = paramdefs; p->key != NULL; p++, cnt++)
+        continue;
+
+    params = OPENSSL_zalloc(cnt * sizeof(*params));
+
+    for (p = paramdefs, q = params; ; p++, q++) {
+        *q = *p;
+        if (p->key == NULL)
+            break;
+
+        q->data = NULL;          /* In case the provider used it */
+        q->return_size = 0;
+    }
+
+    return params;
+}
+
+typedef union align_block_un {
+    OSSL_UNION_ALIGN;
+} ALIGN_BLOCK;
+
+#define ALIGN_SIZE  sizeof(ALIGN_BLOCK)
+
+static void *allocate_params_space(OSSL_PARAM *params)
+{
+    unsigned char *data = NULL;
+    size_t space;
+    OSSL_PARAM *p;
+
+    for (space = 0, p = params; p->key != NULL; p++)
+        space += ((p->return_size + ALIGN_SIZE - 1) / ALIGN_SIZE) * ALIGN_SIZE;
+
+    data = OPENSSL_zalloc(space);
+
+    for (space = 0, p = params; p->key != NULL; p++) {
+        p->data = data + space;
+        space += ((p->return_size + ALIGN_SIZE - 1) / ALIGN_SIZE) * ALIGN_SIZE;
+    }
+
+    return data;
+}
+
+void *evp_keymgmt_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
+{
+    void *provkey = NULL;
+    size_t i, j;
+
+    /*
+     * If there is an underlying legacy key and it has changed, invalidate
+     * the cache of provider keys.
+     */
+    if (pk->pkey.ptr != NULL) {
+        /*
+         * If there is no dirty counter, this key can't be used with
+         * providers.
+         */
+        if (pk->ameth->dirty_cnt == NULL)
+            return NULL;
+
+        if (pk->ameth->dirty_cnt(pk) != pk->dirty_cnt_copy)
+            evp_keymgmt_clear_pkey_cache(pk);
+    }
+
+    /*
+     * See if we have exported to this provider already.
+     * If we have, return immediately.
+     */
+    for (i = 0;
+         i < OSSL_NELEM(pk->pkeys) && pk->pkeys[i].keymgmt != NULL;
+         i++) {
+        if (keymgmt == pk->pkeys[i].keymgmt)
+            return pk->pkeys[i].provkey;
+    }
+
+    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)
+            return NULL;
+
+        /* Otherwise, simply use it */
+        provkey = pk->ameth->export_to(pk, keymgmt);
+
+        /* Synchronize the dirty count, but only if we exported successfully */
+        if (provkey != NULL)
+            pk->dirty_cnt_copy = pk->ameth->dirty_cnt(pk);
+
+    } else {
+        /*
+         * Here, there is no legacy key, so we look at the already cached
+         * provider keys, and import from the first that supports it
+         * (i.e. use its export function), and export the imported data to
+         * the new provider.
+         */
+
+        /*
+         * If the given keymgmt doesn't have an import function, give up
+         */
+        if (keymgmt->importkey == NULL)
+            return NULL;
+
+        for (j = 0; j < i && pk->pkeys[j].keymgmt != NULL; j++) {
+            if (pk->pkeys[j].keymgmt->exportkey != NULL) {
+                const OSSL_PARAM *paramdefs = NULL;
+                OSSL_PARAM *params = NULL;
+                void *data = NULL;
+                void *provctx =
+                    ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
+
+                paramdefs = pk->pkeys[j].keymgmt->exportkey_types();
+                /*
+                 * All params have 'data' set to NULL.  In that case,
+                 * the exportkey call should just fill in 'return_size'
+                 * in all applicable params.
+                 */
+                params = paramdefs_to_params(paramdefs);
+                /* Get 'return_size' filled */
+                pk->pkeys[j].keymgmt->exportkey(pk->pkeys[j].provkey, params);
+
+                /*
+                 * Allocate space and assign 'data' to point into the
+                 * data block
+                 */
+                data = allocate_params_space(params);
+
+                /*
+                 * Call the exportkey function a second time, to get
+                 * the data filled
+                 */
+                pk->pkeys[j].keymgmt->exportkey(pk->pkeys[j].provkey, params);
+
+                /*
+                 * We should have all the data at this point, so import
+                 * into the new provider and hope to get a key back.
+                 */
+                provkey = keymgmt->importkey(provctx, params);
+                OPENSSL_free(params);
+                OPENSSL_free(data);
+
+                if (provkey != NULL)
+                    break;
+            }
+        }
+    }
+
+    /*
+     * TODO(3.0) Right now, we assume we have ample space.  We will
+     * have to think about a cache aging scheme, though, if |i| indexes
+     * outside the array.
+     */
+    j = ossl_assert(i < OSSL_NELEM(pk->pkeys));
+
+    if (provkey != NULL) {
+        EVP_KEYMGMT_up_ref(keymgmt);
+        pk->pkeys[i].keymgmt = keymgmt;
+        pk->pkeys[i].provkey = provkey;
+    }
+    return provkey;
+}
+
+void evp_keymgmt_clear_pkey_cache(EVP_PKEY *pk)
+{
+    size_t i;
+
+    if (pk != NULL) {
+        for (i = 0;
+             i < OSSL_NELEM(pk->pkeys) && pk->pkeys[i].keymgmt != NULL;
+             i++) {
+            EVP_KEYMGMT *keymgmt = pk->pkeys[i].keymgmt;
+            void *provkey = pk->pkeys[i].provkey;
+
+            pk->pkeys[i].keymgmt = NULL;
+            pk->pkeys[i].provkey = NULL;
+            keymgmt->freekey(provkey);
+            EVP_KEYMGMT_free(keymgmt);
+        }
+    }
+}
+
+
+/* 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 *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_PARAM params[])
+{
+    return keymgmt->exportdomparams(provdomparams, params);
+}
+
+const OSSL_PARAM *evp_keymgmt_importdomparam_types(const EVP_KEYMGMT *keymgmt)
+{
+    return keymgmt->importdomparam_types();
+}
+
+const OSSL_PARAM *evp_keymgmt_exportdomparam_types(const EVP_KEYMGMT *keymgmt)
+{
+    return keymgmt->exportdomparam_types();
+}
+
+
+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_PARAM params[])
+{
+    return keymgmt->exportkey(provkey, params);
+}
+
+const OSSL_PARAM *evp_keymgmt_importkey_types(const EVP_KEYMGMT *keymgmt)
+{
+    return keymgmt->importkey_types();
+}
+
+const OSSL_PARAM *evp_keymgmt_exportkey_types(const EVP_KEYMGMT *keymgmt)
+{
+    return keymgmt->exportkey_types();
+}
diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c
new file mode 100644
index 0000000..9723820
--- /dev/null
+++ b/crypto/evp/keymgmt_meth.c
@@ -0,0 +1,189 @@
+/*
+ * 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
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/core_numbers.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include "internal/provider.h"
+#include "internal/refcount.h"
+#include "internal/evp_int.h"
+#include "evp_locl.h"
+
+
+static void *keymgmt_new(void)
+{
+    EVP_KEYMGMT *keymgmt = NULL;
+
+    if ((keymgmt = OPENSSL_zalloc(sizeof(*keymgmt))) == NULL
+        || (keymgmt->lock = CRYPTO_THREAD_lock_new()) == NULL) {
+        EVP_KEYMGMT_free(keymgmt);
+        return NULL;
+    }
+
+    keymgmt->refcnt = 1;
+
+    return keymgmt;
+}
+
+static void *keymgmt_from_dispatch(const OSSL_DISPATCH *fns,
+                                   OSSL_PROVIDER *prov)
+{
+    EVP_KEYMGMT *keymgmt = NULL;
+
+    if ((keymgmt = keymgmt_new()) == NULL)
+        return NULL;
+
+    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);
+            break;
+        case OSSL_FUNC_KEYMGMT_GENDOMPARAMS:
+            if (keymgmt->gendomparams != NULL)
+                break;
+            keymgmt->gendomparams = OSSL_get_OP_keymgmt_gendomparams(fns);
+            break;
+        case OSSL_FUNC_KEYMGMT_FREEDOMPARAMS:
+            if (keymgmt->freedomparams != NULL)
+                break;
+            keymgmt->freedomparams = OSSL_get_OP_keymgmt_freedomparams(fns);
+            break;
+        case OSSL_FUNC_KEYMGMT_EXPORTDOMPARAMS:
+            if (keymgmt->exportdomparams != NULL)
+                break;
+            keymgmt->exportdomparams =
+                OSSL_get_OP_keymgmt_exportdomparams(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_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;
+        }
+    }
+    /*
+     * Try to check that the method is sensible.
+     * 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->importkey_types != NULL
+            && keymgmt->importkey == NULL)
+        || (keymgmt->exportkey_types != NULL
+            && keymgmt->exportkey == NULL)) {
+        EVP_KEYMGMT_free(keymgmt);
+        EVPerr(0, EVP_R_INVALID_PROVIDER_FUNCTIONS);
+        return NULL;
+    }
+    keymgmt->prov = prov;
+    if (prov != NULL)
+        ossl_provider_up_ref(prov);
+
+    return keymgmt;
+}
+
+EVP_KEYMGMT *EVP_KEYMGMT_fetch(OPENSSL_CTX *ctx, const char *algorithm,
+                               const char *properties)
+{
+    EVP_KEYMGMT *keymgmt =
+        evp_generic_fetch(ctx, OSSL_OP_KEYMGMT, algorithm, properties,
+                          keymgmt_from_dispatch,
+                          (int (*)(void *))EVP_KEYMGMT_up_ref,
+                          (void (*)(void *))EVP_KEYMGMT_free);
+
+    return keymgmt;
+}
+
+int EVP_KEYMGMT_up_ref(EVP_KEYMGMT *keymgmt)
+{
+    int ref = 0;
+
+    CRYPTO_UP_REF(&keymgmt->refcnt, &ref, keymgmt->lock);
+    return 1;
+}
+
+void EVP_KEYMGMT_free(EVP_KEYMGMT *keymgmt)
+{
+    int ref = 0;
+
+    if (keymgmt == NULL)
+        return;
+
+    CRYPTO_DOWN_REF(&keymgmt->refcnt, &ref, keymgmt->lock);
+    if (ref > 0)
+        return;
+    ossl_provider_free(keymgmt->prov);
+    CRYPTO_THREAD_lock_free(keymgmt->lock);
+    OPENSSL_free(keymgmt);
+}
+
+const OSSL_PROVIDER *EVP_KEYMGMT_provider(const EVP_KEYMGMT *keymgmt)
+{
+    return keymgmt->prov;
+}
+
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index c6ebfe6..653693e 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -613,6 +613,9 @@ void EVP_PKEY_free(EVP_PKEY *x)
 static void EVP_PKEY_free_it(EVP_PKEY *x)
 {
     /* internal function; x is never NULL */
+
+    evp_keymgmt_clear_pkey_cache(x);
+
     if (x->ameth && x->ameth->pkey_free) {
         x->ameth->pkey_free(x);
         x->pkey.ptr = NULL;
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index 169b056..cc26f06 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -1,3 +1,4 @@
+
 /*
  * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
  *
@@ -106,8 +107,17 @@ const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type)
 static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
 {
     EVP_PKEY_CTX *ret;
-    const EVP_PKEY_METHOD *pmeth;
+    const EVP_PKEY_METHOD *pmeth = NULL;
+
+    /*
+     * When using providers, the context is bound to the algo implementation
+     * later.
+     */
+    if (pkey == NULL && e == NULL && id == -1)
+        goto common;
 
+    /* TODO(3.0) Legacy code should be removed when all is provider based */
+    /* BEGIN legacy */
     if (id == -1) {
         if (pkey == NULL)
             return 0;
@@ -143,7 +153,9 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
         EVPerr(EVP_F_INT_CTX_NEW, EVP_R_UNSUPPORTED_ALGORITHM);
         return NULL;
     }
+    /* END legacy */
 
+ common:
     ret = OPENSSL_zalloc(sizeof(*ret));
     if (ret == NULL) {
 #ifndef OPENSSL_NO_ENGINE
@@ -159,7 +171,7 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
     if (pkey != NULL)
         EVP_PKEY_up_ref(pkey);
 
-    if (pmeth->init) {
+    if (pmeth != NULL && pmeth->init) {
         if (pmeth->init(ret) <= 0) {
             ret->pmeth = NULL;
             EVP_PKEY_CTX_free(ret);
diff --git a/crypto/include/internal/asn1_int.h b/crypto/include/internal/asn1_int.h
index 1f62063..674fa70 100644
--- a/crypto/include/internal/asn1_int.h
+++ b/crypto/include/internal/asn1_int.h
@@ -63,6 +63,14 @@ struct evp_pkey_asn1_method_st {
     int (*set_pub_key) (EVP_PKEY *pk, const unsigned char *pub, size_t len);
     int (*get_priv_key) (const EVP_PKEY *pk, unsigned char *priv, size_t *len);
     int (*get_pub_key) (const EVP_PKEY *pk, unsigned char *pub, size_t *len);
+
+    /*
+     * TODO: Make sure these functions are defined for key types that are
+     * implemented in providers.
+     */
+    /* Exports to providers */
+    size_t (*dirty_cnt) (const EVP_PKEY *pk);
+    void *(*export_to) (const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt);
 } /* EVP_PKEY_ASN1_METHOD */ ;
 
 DEFINE_STACK_OF_CONST(EVP_PKEY_ASN1_METHOD)
diff --git a/crypto/include/internal/evp_int.h b/crypto/include/internal/evp_int.h
index 71833fa..50ed933 100644
--- a/crypto/include/internal/evp_int.h
+++ b/crypto/include/internal/evp_int.h
@@ -504,9 +504,9 @@ typedef struct {
  * method, as in, can it do arbitrary encryption....
  */
 struct evp_pkey_st {
+    /* == Legacy attributes == */
     int type;
     int save_type;
-    CRYPTO_REF_COUNT references;
     const EVP_PKEY_ASN1_METHOD *ameth;
     ENGINE *engine;
     ENGINE *pmeth_engine; /* If not NULL public key ENGINE to use */
@@ -526,9 +526,30 @@ struct evp_pkey_st {
         ECX_KEY *ecx;           /* X25519, X448, Ed25519, Ed448 */
 # endif
     } pkey;
-    int save_parameters;
-    STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
+
+    /* == Common attributes == */
+    CRYPTO_REF_COUNT references;
     CRYPTO_RWLOCK *lock;
+    STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
+    int save_parameters;
+
+    /* == 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 is used, we maintain a cache
+     * of imported key, indexed by provider address.
+     * pkeys[0] is *always* the "original" key.
+     */
+    struct {
+        EVP_KEYMGMT *keymgmt;
+        void *provkey;
+    } pkeys[10];
+    /*
+     * If there is a legacy key assigned to this structure, we keep
+     * a copy of that key's dirty count.
+     */
+    size_t dirty_cnt_copy;
 } /* EVP_PKEY */ ;
 
 
@@ -539,6 +560,36 @@ void openssl_add_all_kdfs_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);
+void evp_keymgmt_clear_pkey_cache(EVP_PKEY *pk);
+
+/* 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_PARAM params[]);
+const OSSL_PARAM *
+evp_keymgmt_importdomparam_types(const EVP_KEYMGMT *keymgmt);
+const OSSL_PARAM *
+evp_keymgmt_exportdomparam_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);
+
 /* Pulling defines out of C source files */
 
 #define EVP_RC4_KEY_SIZE 16
diff --git a/doc/internal/man3/evp_keymgmt_export_to_provider.pod b/doc/internal/man3/evp_keymgmt_export_to_provider.pod
new file mode 100644
index 0000000..72b766f
--- /dev/null
+++ b/doc/internal/man3/evp_keymgmt_export_to_provider.pod
@@ -0,0 +1,56 @@
+=pod
+
+=head1 NAME
+
+evp_keymgmt_export_to_provider,
+evp_keymgmt_clear_pkey_cache
+- key material provider export for EVP
+
+=head1 SYNOPSIS
+
+ #include "internal/evp_int.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
new file mode 100644
index 0000000..597c34b
--- /dev/null
+++ b/doc/internal/man3/evp_keymgmt_freekey.pod
@@ -0,0 +1,109 @@
+=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 "internal/evp_int.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/man3/EVP_KEYMGMT.pod b/doc/man3/EVP_KEYMGMT.pod
new file mode 100644
index 0000000..ab209da
--- /dev/null
+++ b/doc/man3/EVP_KEYMGMT.pod
@@ -0,0 +1,84 @@
+=pod
+
+=head1 NAME
+
+EVP_KEYMGMT,
+EVP_KEYMGMT_fetch,
+EVP_KEYMGMT_up_ref,
+EVP_KEYMGMT_free,
+EVP_KEYMGMT_provider
+- EVP key management routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ typedef struct evp_keymgmt_st EVP_KEYMGMT;
+
+ EVP_KEYMGMT *EVP_KEYMGMT_fetch(OPENSSL_CTX *ctx, const char *algorithm,
+                                const char *properties);
+ int EVP_KEYMGMT_up_ref(EVP_KEYMGMT *keymgmt);
+ void EVP_KEYMGMT_free(EVP_KEYMGMT *keymgmt);
+ const OSSL_PROVIDER *EVP_KEYMGMT_provider(const EVP_KEYMGMT *keymgmt);
+
+=head1 DESCRIPTION
+
+B<EVP_KEYMGMT> is a method object that represents key management
+implementations for different cryptographic algorithms.
+This method object provides functionality to have providers import key
+material from the outside, as well as export key material to the
+outside.
+Most of the functionality can only be used internally and has no
+public interface, this object is simply passed into other functions
+when needed.
+
+EVP_KEYMGMT_fetch() looks for an algorithm within the provider that
+has been loaded into the B<OPENSSL_CTX> given by I<ctx>, having the
+name given by I<algorithm> and the properties given by I<properties>.
+
+EVP_KEYMGMT_up_ref() increments the reference count for the given
+B<EVP_KEYMGMT> I<keymgmt>.
+
+EVP_KEYMGMT_free() decrements the reference count for the given
+B<EVP_KEYMGMT> I<keymgmt>, and when the count reaches zero, frees it.
+
+EVP_KEYMGMT_provider() returns the provider that has this particular
+implementation.
+
+=head1 NOTES
+
+EVP_KEYMGMT_fetch() may be called implicitly by other fetching
+functions, using the same library context and properties.
+Any other API that uses keys will typically do this.
+
+=head1 RETURN VALUES
+
+EVP_KEYMGMT_fetch() returns a pointer to the key management
+implementation represented by an EVP_KEYMGMT object, or NULL on
+error.
+
+EVP_KEYMGMT_up_ref() returns 1 on success, or 0 on error.
+
+EVP_KEYMGMT_free() doesn't return any value.
+
+EVP_KEYMGMT_provider() returns a pointer to a provider object, or NULL
+on error.
+
+=head1 SEE ALSO
+
+L<EVP_MD_fetch(3)>, L<OPENSSL_CTX(3)>
+
+=head1 HISTORY
+
+The functions described here were 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/man3/EVP_PKEY_ASN1_METHOD.pod b/doc/man3/EVP_PKEY_ASN1_METHOD.pod
index 1d89c38..ed44749 100644
--- a/doc/man3/EVP_PKEY_ASN1_METHOD.pod
+++ b/doc/man3/EVP_PKEY_ASN1_METHOD.pod
@@ -361,6 +361,16 @@ public key data for an EVP_PKEY. They MUST return 0 on error, or 1 on success.
 They are called by L<EVP_PKEY_new_raw_private_key(3)>, and
 L<EVP_PKEY_new_raw_public_key(3)> respectively.
 
+ size_t (*dirty) (const EVP_PKEY *pk);
+ void *(*export_to) (const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt);
+
+dirty_cnt() returns the internal key's dirty count.
+This can be used to synchronise different copies of the same keys.
+
+The export_to() method exports the key material from the given key to
+a provider, through the L<EVP_KEYMGMT(3)> interface, if that provider
+supports importing key material.
+
 =head2 Functions
 
 EVP_PKEY_asn1_new() creates and returns a new B<EVP_PKEY_ASN1_METHOD>
diff --git a/include/openssl/core_numbers.h b/include/openssl/core_numbers.h
index c589243..f45b8f1 100644
--- a/include/openssl/core_numbers.h
+++ b/include/openssl/core_numbers.h
@@ -229,9 +229,80 @@ OSSL_CORE_MAKE_FUNC(int, OP_cipher_ctx_get_params, (void *cctx,
 OSSL_CORE_MAKE_FUNC(int, OP_cipher_ctx_set_params, (void *cctx,
                                                     const OSSL_PARAM 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.
+ *
+ * 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.
+ */
+
+# define OSSL_OP_KEYMGMT                           10
+
+/* 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_PARAM params[]))
+
+/* Key domain parameter discovery */
+# 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 creation and destruction */
+# define OSSL_FUNC_KEYMGMT_IMPORTKEY               10
+# define OSSL_FUNC_KEYMGMT_GENKEY                  11
+# define OSSL_FUNC_KEYMGMT_LOADKEY                 12
+# define OSSL_FUNC_KEYMGMT_FREEKEY                 13
+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               14
+OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_exportkey,
+                    (void *key, OSSL_PARAM params[]))
+
+/* Key discovery */
+# define OSSL_FUNC_KEYMGMT_IMPORTKEY_TYPES         15
+# define OSSL_FUNC_KEYMGMT_EXPORTKEY_TYPES         16
+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 Exchange */
 
-# define OSSL_OP_KEYEXCH                               3
+# define OSSL_OP_KEYEXCH                              11
 
 # define OSSL_FUNC_KEYEXCH_NEWCTX                      1
 # define OSSL_FUNC_KEYEXCH_INIT                        2
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index 377b4b1..d014a2e 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -1411,6 +1411,12 @@ int EVP_PKEY_meth_remove(const EVP_PKEY_METHOD *pmeth);
 size_t EVP_PKEY_meth_get_count(void);
 const EVP_PKEY_METHOD *EVP_PKEY_meth_get0(size_t idx);
 
+EVP_KEYMGMT *EVP_KEYMGMT_fetch(OPENSSL_CTX *ctx, const char *algorithm,
+                               const char *properties);
+int EVP_KEYMGMT_up_ref(EVP_KEYMGMT *keymgmt);
+void EVP_KEYMGMT_free(EVP_KEYMGMT *keymgmt);
+const OSSL_PROVIDER *EVP_KEYMGMT_provider(const EVP_KEYMGMT *keymgmt);
+
 EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e);
 EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e);
 EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *ctx);
diff --git a/include/openssl/ossl_typ.h b/include/openssl/ossl_typ.h
index 76a9bee..7eec053 100644
--- a/include/openssl/ossl_typ.h
+++ b/include/openssl/ossl_typ.h
@@ -101,6 +101,8 @@ typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD;
 typedef struct evp_pkey_method_st EVP_PKEY_METHOD;
 typedef struct evp_pkey_ctx_st EVP_PKEY_CTX;
 
+typedef struct evp_keymgmt_st EVP_KEYMGMT;
+
 typedef struct evp_kdf_st EVP_KDF;
 typedef struct evp_kdf_ctx_st EVP_KDF_CTX;
 
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 648aed9..1992504 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4685,3 +4685,7 @@ EVP_KEYEXCH_up_ref                      4790	3_0_0	EXIST::FUNCTION:
 EVP_KEYEXCH_fetch                       4791	3_0_0	EXIST::FUNCTION:
 EVP_PKEY_CTX_set_dh_pad                 4792	3_0_0	EXIST::FUNCTION:DH
 EVP_PKEY_CTX_set_params                 4793	3_0_0	EXIST::FUNCTION:
+EVP_KEYMGMT_fetch                       4794	3_0_0	EXIST::FUNCTION:
+EVP_KEYMGMT_up_ref                      4795	3_0_0	EXIST::FUNCTION:
+EVP_KEYMGMT_free                        4796	3_0_0	EXIST::FUNCTION:
+EVP_KEYMGMT_provider                    4797	3_0_0	EXIST::FUNCTION:
diff --git a/util/private.num b/util/private.num
index f63319d..3307e3e 100644
--- a/util/private.num
+++ b/util/private.num
@@ -24,6 +24,7 @@ CRYPTO_EX_new                           datatype
 DTLS_timer_cb                           datatype
 EVP_KDF                                 datatype
 EVP_KDF_CTX                             datatype
+EVP_KEYMGMT                             datatype
 EVP_MAC                                 datatype
 EVP_MAC_CTX                             datatype
 EVP_PKEY_gen_cb                         datatype


More information about the openssl-commits mailing list