[openssl] master update

Matt Caswell matt at openssl.org
Thu Oct 15 09:09:34 UTC 2020


The branch master has been updated
       via  29000e43ea257bf54f6ccb2064b3744853b821b2 (commit)
       via  0d30e15a57fdd9c27a9148c17289a1005345f0c7 (commit)
       via  7022d9b9032794330cd2d753f077670db95d33d4 (commit)
       via  9ab7fe483629704b09dc43c1998e0e489615390f (commit)
       via  0b3a4ef27a6c2a427dc2d4a87c52677d57c90f4c (commit)
       via  99b3b762c33fad9383cb2d1791be9c9f7d44710a (commit)
      from  5b70206cb316024c6dc30ce54f585ce5cf001a56 (commit)


- Log -----------------------------------------------------------------
commit 29000e43ea257bf54f6ccb2064b3744853b821b2
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Oct 12 17:12:03 2020 +0100

    Make evp_pkey_ctx_get0_libctx/propq public API
    
    These were previously added as an internal API. But since the CMS code
    needs them, other code might do too.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/13088)

commit 0d30e15a57fdd9c27a9148c17289a1005345f0c7
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Oct 6 17:02:45 2020 +0100

    Remove some more CMS key downgrades
    
    Fixes #12983
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/13088)

commit 7022d9b9032794330cd2d753f077670db95d33d4
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Oct 7 15:59:28 2020 +0100

    Remove CMS recipient info information out of the algorithm implementations
    
    Low level algorithm implementations have no business knowing about details
    of the higher level CMS concept. This knowledge is therefore moved into the
    CMS layer.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/13088)

commit 9ab7fe483629704b09dc43c1998e0e489615390f
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Oct 7 14:45:22 2020 +0100

    Move CMS signing code out of the algorithms and into CMS
    
    There is a large amount of CMS sepcific code in the algorithms. This is in
    the wrong place and breaks layering. This code should be in the CMS layer.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/13088)

commit 0b3a4ef27a6c2a427dc2d4a87c52677d57c90f4c
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Oct 6 16:02:43 2020 +0100

    Move CMS enveloping code out of the algorithms and into CMS
    
    There is quite a large amount of algorithm specific CMS code sitting in
    the algorithm directories. However, this seems to break layering.
    Algorithms really have no business knowing anything about CMS. Really it
    should be the other way around. Where there is algorithm specific CMS code
    it is the CMS layer that should know how to handle different algorithms.
    
    Therefore we move this code into the CMS layer.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/13088)

commit 99b3b762c33fad9383cb2d1791be9c9f7d44710a
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Oct 2 11:25:25 2020 +0100

    Remove a CMS key downgrade
    
    We were downgrading a key in the CMS code. This is no longer necessary.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/13088)

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

Summary of changes:
 apps/cms.c                            |  14 --
 crypto/asn1/asn1_err.c                |   1 +
 crypto/asn1/x_algor.c                 |  63 +++++
 crypto/cms/build.info                 |   9 +-
 crypto/cms/cms_dh.c                   | 320 ++++++++++++++++++++++++++
 crypto/cms/cms_ec.c                   | 419 ++++++++++++++++++++++++++++++++++
 crypto/cms/cms_env.c                  |  29 +++
 crypto/cms/cms_err.c                  |  12 +
 crypto/cms/cms_kari.c                 |  46 ----
 crypto/cms/cms_local.h                |   6 +
 crypto/cms/cms_rsa.c                  | 253 ++++++++++++++++++++
 crypto/cms/cms_sd.c                   |   9 +
 crypto/dh/dh_ameth.c                  | 334 +--------------------------
 crypto/dsa/dsa_ameth.c                |  22 --
 crypto/ec/ec_ameth.c                  | 358 -----------------------------
 crypto/err/openssl.txt                |   9 +
 crypto/evp/pmeth_lib.c                |  10 +
 crypto/rsa/rsa_ameth.c                | 338 ++-------------------------
 doc/man3/EVP_PKEY_CTX_get0_libctx.pod |  45 ++++
 include/crypto/asn1.h                 |   5 +
 include/crypto/rsa.h                  |   4 +
 include/openssl/asn1err.h             |   1 +
 include/openssl/cmserr.h              |   8 +
 include/openssl/evp.h                 |   3 +
 util/libcrypto.num                    |   2 +
 25 files changed, 1228 insertions(+), 1092 deletions(-)
 create mode 100644 crypto/cms/cms_dh.c
 create mode 100644 crypto/cms/cms_ec.c
 create mode 100644 crypto/cms/cms_rsa.c
 create mode 100644 doc/man3/EVP_PKEY_CTX_get0_libctx.pod

diff --git a/apps/cms.c b/apps/cms.c
index 91d951980d..37b1e96a14 100644
--- a/apps/cms.c
+++ b/apps/cms.c
@@ -862,13 +862,6 @@ int cms_main(int argc, char **argv)
         key = load_key(keyfile, keyform, 0, passin, e, "signing key");
         if (key == NULL)
             goto end;
-
-        /*
-         * TODO: Remove this when CMS has full support for provider-native
-         * EVP_PKEYs
-         */
-        if (EVP_PKEY_get0(key) == NULL)
-            goto end;
     }
 
     in = bio_open_default(infile, 'r', informat);
@@ -1067,13 +1060,6 @@ int cms_main(int argc, char **argv)
                 goto end;
             }
 
-            /*
-             * TODO: Remove this when CMS has full support for provider-native
-             * EVP_PKEYs
-             */
-            if (EVP_PKEY_get0(key) == NULL)
-                goto end;
-
             for (kparam = key_first; kparam; kparam = kparam->next) {
                 if (kparam->idx == i) {
                     tflags |= CMS_KEY_PARAM;
diff --git a/crypto/asn1/asn1_err.c b/crypto/asn1/asn1_err.c
index 6a599bc067..814cd91373 100644
--- a/crypto/asn1/asn1_err.c
+++ b/crypto/asn1/asn1_err.c
@@ -171,6 +171,7 @@ static const ERR_STRING_DATA ASN1_str_reasons[] = {
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNEXPECTED_EOC), "unexpected eoc"},
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH),
     "universalstring is wrong length"},
+    {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_DIGEST), "unknown digest"},
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_FORMAT), "unknown format"},
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM),
     "unknown message digest algorithm"},
diff --git a/crypto/asn1/x_algor.c b/crypto/asn1/x_algor.c
index f29d26d91c..7e198a558c 100644
--- a/crypto/asn1/x_algor.c
+++ b/crypto/asn1/x_algor.c
@@ -11,6 +11,8 @@
 #include <openssl/x509.h>
 #include <openssl/asn1.h>
 #include <openssl/asn1t.h>
+#include <openssl/err.h>
+#include "crypto/asn1.h"
 #include "crypto/evp.h"
 
 ASN1_SEQUENCE(X509_ALGOR) = {
@@ -125,3 +127,64 @@ int X509_ALGOR_copy(X509_ALGOR *dest, const X509_ALGOR *src)
 
     return 1;
 }
+
+/* allocate and set algorithm ID from EVP_MD, default SHA1 */
+int x509_algor_new_from_md(X509_ALGOR **palg, const EVP_MD *md)
+{
+    /* Default is SHA1 so no need to create it - still success */
+    if (md == NULL || EVP_MD_is_a(md, "SHA1"))
+        return 1;
+    *palg = X509_ALGOR_new();
+    if (*palg == NULL)
+        return 0;
+    X509_ALGOR_set_md(*palg, md);
+    return 1;
+}
+
+/* convert algorithm ID to EVP_MD, default SHA1 */
+const EVP_MD *x509_algor_get_md(X509_ALGOR *alg)
+{
+    const EVP_MD *md;
+
+    if (alg == NULL)
+        return EVP_sha1();
+    md = EVP_get_digestbyobj(alg->algorithm);
+    if (md == NULL)
+        ASN1err(0, ASN1_R_UNKNOWN_DIGEST);
+    return md;
+}
+
+X509_ALGOR *x509_algor_mgf1_decode(X509_ALGOR *alg)
+{
+    if (OBJ_obj2nid(alg->algorithm) != NID_mgf1)
+        return NULL;
+    return ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(X509_ALGOR),
+                                     alg->parameter);
+}
+
+/* Allocate and set MGF1 algorithm ID from EVP_MD */
+int x509_algor_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md)
+{
+    X509_ALGOR *algtmp = NULL;
+    ASN1_STRING *stmp = NULL;
+
+    *palg = NULL;
+    if (mgf1md == NULL || EVP_MD_is_a(mgf1md, "SHA1"))
+        return 1;
+    /* need to embed algorithm ID inside another */
+    if (!x509_algor_new_from_md(&algtmp, mgf1md))
+        goto err;
+    if (ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp) == NULL)
+         goto err;
+    *palg = X509_ALGOR_new();
+    if (*palg == NULL)
+        goto err;
+    X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp);
+    stmp = NULL;
+ err:
+    ASN1_STRING_free(stmp);
+    X509_ALGOR_free(algtmp);
+    if (*palg != NULL)
+        return 1;
+    return 0;
+}
diff --git a/crypto/cms/build.info b/crypto/cms/build.info
index cb675436ef..c7579f78c1 100644
--- a/crypto/cms/build.info
+++ b/crypto/cms/build.info
@@ -2,4 +2,11 @@ LIBS=../../libcrypto
 SOURCE[../../libcrypto]= \
         cms_lib.c cms_asn1.c cms_att.c cms_io.c cms_smime.c cms_err.c \
         cms_sd.c cms_dd.c cms_cd.c cms_env.c cms_enc.c cms_ess.c \
-        cms_pwri.c cms_kari.c
+        cms_pwri.c cms_kari.c cms_rsa.c
+
+IF[{- !$disabled{dh} -}]
+  SOURCE[../../libcrypto]=cms_dh.c
+ENDIF
+IF[{- !$disabled{ec} || !$disabled{dsa}-}]
+  SOURCE[../../libcrypto]=cms_ec.c
+ENDIF
diff --git a/crypto/cms/cms_dh.c b/crypto/cms/cms_dh.c
new file mode 100644
index 0000000000..0d9eac50b3
--- /dev/null
+++ b/crypto/cms/cms_dh.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright 2006-2020 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 <assert.h>
+#include <openssl/cms.h>
+#include <openssl/dh.h>
+#include <openssl/err.h>
+#include <openssl/core_names.h>
+#include "cms_local.h"
+
+static int dh_cms_set_peerkey(EVP_PKEY_CTX *pctx,
+                              X509_ALGOR *alg, ASN1_BIT_STRING *pubkey)
+{
+    const ASN1_OBJECT *aoid;
+    int atype;
+    const void *aval;
+    ASN1_INTEGER *public_key = NULL;
+    int rv = 0;
+    EVP_PKEY *pkpeer = NULL, *pk = NULL;
+    const unsigned char *p;
+    int plen;
+
+    X509_ALGOR_get0(&aoid, &atype, &aval, alg);
+    if (OBJ_obj2nid(aoid) != NID_dhpublicnumber)
+        goto err;
+    /* Only absent parameters allowed in RFC XXXX */
+    if (atype != V_ASN1_UNDEF && atype == V_ASN1_NULL)
+        goto err;
+
+    pk = EVP_PKEY_CTX_get0_pkey(pctx);
+    if (pk == NULL || !EVP_PKEY_is_a(pk, "DHX"))
+        goto err;
+
+    /* Get public key */
+    plen = ASN1_STRING_length(pubkey);
+    p = ASN1_STRING_get0_data(pubkey);
+    if (p == NULL || plen == 0)
+        goto err;
+
+    pkpeer = EVP_PKEY_new();
+    if (pkpeer == NULL
+            || !EVP_PKEY_copy_parameters(pkpeer, pk)
+               /*
+                * TODO(3.0): This is badly named!! Can we make this more
+                * generic and not TLS specific?
+                */
+            || !EVP_PKEY_set1_tls_encodedpoint(pkpeer, p, plen))
+        goto err;
+
+    if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0)
+        rv = 1;
+ err:
+    ASN1_INTEGER_free(public_key);
+    EVP_PKEY_free(pkpeer);
+    return rv;
+}
+
+static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
+{
+    int rv = 0;
+    X509_ALGOR *alg, *kekalg = NULL;
+    ASN1_OCTET_STRING *ukm;
+    const unsigned char *p;
+    unsigned char *dukm = NULL;
+    size_t dukmlen = 0;
+    int keylen, plen;
+    const EVP_CIPHER *kekcipher;
+    EVP_CIPHER_CTX *kekctx;
+
+    if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
+        goto err;
+
+    /*
+     * For DH we only have one OID permissible. If ever any more get defined
+     * we will need something cleverer.
+     */
+    if (OBJ_obj2nid(alg->algorithm) != NID_id_smime_alg_ESDH) {
+        CMSerr(0, CMS_R_KDF_PARAMETER_ERROR);
+        goto err;
+    }
+
+    if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, EVP_PKEY_DH_KDF_X9_42) <= 0
+            || EVP_PKEY_CTX_set_dh_kdf_md(pctx, EVP_sha1()) <= 0)
+        goto err;
+
+    if (alg->parameter->type != V_ASN1_SEQUENCE)
+        goto err;
+
+    p = alg->parameter->value.sequence->data;
+    plen = alg->parameter->value.sequence->length;
+    kekalg = d2i_X509_ALGOR(NULL, &p, plen);
+    if (kekalg == NULL)
+        goto err;
+    kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
+    if (kekctx == NULL)
+        goto err;
+    kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
+    if (kekcipher == NULL || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
+        goto err;
+    if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
+        goto err;
+    if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0)
+        goto err;
+
+    keylen = EVP_CIPHER_CTX_key_length(kekctx);
+    if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0)
+        goto err;
+    /* Use OBJ_nid2obj to ensure we use built in OID that isn't freed */
+    if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx,
+                                     OBJ_nid2obj(EVP_CIPHER_type(kekcipher)))
+        <= 0)
+        goto err;
+
+    if (ukm != NULL) {
+        dukmlen = ASN1_STRING_length(ukm);
+        dukm = OPENSSL_memdup(ASN1_STRING_get0_data(ukm), dukmlen);
+        if (dukm == NULL)
+            goto err;
+    }
+
+    if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0)
+        goto err;
+    dukm = NULL;
+
+    rv = 1;
+ err:
+    X509_ALGOR_free(kekalg);
+    OPENSSL_free(dukm);
+    return rv;
+}
+
+static int dh_cms_decrypt(CMS_RecipientInfo *ri)
+{
+    EVP_PKEY_CTX *pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
+
+    if (pctx == NULL)
+        return 0;
+    /* See if we need to set peer key */
+    if (!EVP_PKEY_CTX_get0_peerkey(pctx)) {
+        X509_ALGOR *alg;
+        ASN1_BIT_STRING *pubkey;
+
+        if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey,
+                                                 NULL, NULL, NULL))
+            return 0;
+        if (alg ==  NULL || pubkey == NULL)
+            return 0;
+        if (!dh_cms_set_peerkey(pctx, alg, pubkey)) {
+            DHerr(DH_F_DH_CMS_DECRYPT, DH_R_PEER_KEY_ERROR);
+            return 0;
+        }
+    }
+    /* Set DH derivation parameters and initialise unwrap context */
+    if (!dh_cms_set_shared_info(pctx, ri)) {
+        DHerr(DH_F_DH_CMS_DECRYPT, DH_R_SHARED_INFO_ERROR);
+        return 0;
+    }
+    return 1;
+}
+
+static int dh_cms_encrypt(CMS_RecipientInfo *ri)
+{
+    EVP_PKEY_CTX *pctx;
+    EVP_PKEY *pkey;
+    EVP_CIPHER_CTX *ctx;
+    int keylen;
+    X509_ALGOR *talg, *wrap_alg = NULL;
+    const ASN1_OBJECT *aoid;
+    ASN1_BIT_STRING *pubkey;
+    ASN1_STRING *wrap_str;
+    ASN1_OCTET_STRING *ukm;
+    unsigned char *penc = NULL, *dukm = NULL;
+    int penclen;
+    size_t dukmlen = 0;
+    int rv = 0;
+    int kdf_type, wrap_nid;
+    const EVP_MD *kdf_md;
+
+    pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
+    if (pctx == NULL)
+        return 0;
+    /* Get ephemeral key */
+    pkey = EVP_PKEY_CTX_get0_pkey(pctx);
+    if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
+                                             NULL, NULL, NULL))
+        goto err;
+
+    /* Is everything uninitialised? */
+    X509_ALGOR_get0(&aoid, NULL, NULL, talg);
+    if (aoid == OBJ_nid2obj(NID_undef)) {
+        BIGNUM *bn_pub_key = NULL;
+        ASN1_INTEGER *pubk;
+
+        if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, &bn_pub_key))
+            goto err;
+
+        pubk = BN_to_ASN1_INTEGER(bn_pub_key, NULL);
+        BN_free(bn_pub_key);
+        if (pubk == NULL)
+            goto err;
+
+        /* Set the key */
+        penclen = i2d_ASN1_INTEGER(pubk, &penc);
+        ASN1_INTEGER_free(pubk);
+        if (penclen <= 0)
+            goto err;
+        ASN1_STRING_set0(pubkey, penc, penclen);
+        pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
+        pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+
+        penc = NULL;
+        X509_ALGOR_set0(talg, OBJ_nid2obj(NID_dhpublicnumber),
+                        V_ASN1_UNDEF, NULL);
+    }
+
+    /* See if custom parameters set */
+    kdf_type = EVP_PKEY_CTX_get_dh_kdf_type(pctx);
+    if (kdf_type <= 0 || !EVP_PKEY_CTX_get_dh_kdf_md(pctx, &kdf_md))
+        goto err;
+
+    if (kdf_type == EVP_PKEY_DH_KDF_NONE) {
+        kdf_type = EVP_PKEY_DH_KDF_X9_42;
+        if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, kdf_type) <= 0)
+            goto err;
+    } else if (kdf_type != EVP_PKEY_DH_KDF_X9_42)
+        /* Unknown KDF */
+        goto err;
+    if (kdf_md == NULL) {
+        /* Only SHA1 supported */
+        kdf_md = EVP_sha1();
+        if (EVP_PKEY_CTX_set_dh_kdf_md(pctx, kdf_md) <= 0)
+            goto err;
+    } else if (EVP_MD_type(kdf_md) != NID_sha1)
+        /* Unsupported digest */
+        goto err;
+
+    if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
+        goto err;
+
+    /* Get wrap NID */
+    ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
+    wrap_nid = EVP_CIPHER_CTX_type(ctx);
+    if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx, OBJ_nid2obj(wrap_nid)) <= 0)
+        goto err;
+    keylen = EVP_CIPHER_CTX_key_length(ctx);
+
+    /* Package wrap algorithm in an AlgorithmIdentifier */
+
+    wrap_alg = X509_ALGOR_new();
+    if (wrap_alg == NULL)
+        goto err;
+    wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
+    wrap_alg->parameter = ASN1_TYPE_new();
+    if (wrap_alg->parameter == NULL)
+        goto err;
+    if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
+        goto err;
+    if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) {
+        ASN1_TYPE_free(wrap_alg->parameter);
+        wrap_alg->parameter = NULL;
+    }
+
+    if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0)
+        goto err;
+
+    if (ukm != NULL) {
+        dukmlen = ASN1_STRING_length(ukm);
+        dukm = OPENSSL_memdup(ASN1_STRING_get0_data(ukm), dukmlen);
+        if (dukm == NULL)
+            goto err;
+    }
+
+    if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0)
+        goto err;
+    dukm = NULL;
+
+    /*
+     * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter
+     * of another AlgorithmIdentifier.
+     */
+    penc = NULL;
+    penclen = i2d_X509_ALGOR(wrap_alg, &penc);
+    if (penc == NULL || penclen == 0)
+        goto err;
+    wrap_str = ASN1_STRING_new();
+    if (wrap_str == NULL)
+        goto err;
+    ASN1_STRING_set0(wrap_str, penc, penclen);
+    penc = NULL;
+    X509_ALGOR_set0(talg, OBJ_nid2obj(NID_id_smime_alg_ESDH),
+                    V_ASN1_SEQUENCE, wrap_str);
+
+    rv = 1;
+
+ err:
+    OPENSSL_free(penc);
+    X509_ALGOR_free(wrap_alg);
+    OPENSSL_free(dukm);
+    return rv;
+}
+
+int cms_dh_envelope(CMS_RecipientInfo *ri, int decrypt)
+{
+    assert(decrypt == 0 || decrypt == 1);
+
+    if (decrypt == 1)
+        return dh_cms_decrypt(ri);
+
+    if (decrypt == 0)
+        return dh_cms_encrypt(ri);
+
+    CMSerr(0, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+    return 0;
+}
diff --git a/crypto/cms/cms_ec.c b/crypto/cms/cms_ec.c
new file mode 100644
index 0000000000..ca2294ebc3
--- /dev/null
+++ b/crypto/cms/cms_ec.c
@@ -0,0 +1,419 @@
+/*
+ * Copyright 2006-2020 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 <assert.h>
+#include <openssl/cms.h>
+#include <openssl/err.h>
+#include <openssl/decoder.h>
+#include "cms_local.h"
+#include "crypto/evp.h"
+
+#ifndef OPENSSL_NO_EC
+static EVP_PKEY *pkey_type2param(int ptype, const void *pval,
+                                 OPENSSL_CTX *libctx, const char *propq)
+{
+    EVP_PKEY *pkey = NULL;
+    EVP_PKEY_CTX *pctx = NULL;
+
+    if (ptype == V_ASN1_SEQUENCE) {
+        const ASN1_STRING *pstr = pval;
+        const unsigned char *pm = pstr->data;
+        int pmlen = pstr->length;
+        OSSL_DECODER_CTX *ctx = NULL;
+        BIO *membio = NULL;
+
+        /* TODO(3.0): Need to be able to specify here that only params will do */
+        ctx = OSSL_DECODER_CTX_new_by_EVP_PKEY(&pkey, "DER", "EC", libctx,
+                                               propq);
+        if (ctx == NULL)
+            goto err;
+
+        membio = BIO_new_mem_buf(pm, pmlen);
+        if (membio == NULL) {
+            OSSL_DECODER_CTX_free(ctx);
+            goto err;
+        }
+        OSSL_DECODER_from_bio(ctx, membio);
+        BIO_free(membio);
+        OSSL_DECODER_CTX_free(ctx);
+    } else if (ptype == V_ASN1_OBJECT) {
+        const ASN1_OBJECT *poid = pval;
+        const char *groupname;
+
+        /* type == V_ASN1_OBJECT => the parameters are given by an asn1 OID */
+        pctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", propq);
+        if (pctx == NULL || EVP_PKEY_paramgen_init(pctx) <= 0)
+            goto err;
+        groupname = OBJ_nid2sn(OBJ_obj2nid(poid));
+        if (groupname == NULL
+                || !EVP_PKEY_CTX_set_group_name(pctx, groupname)) {
+            CMSerr(0, CMS_R_DECODE_ERROR);
+            goto err;
+        }
+        if (EVP_PKEY_paramgen(pctx, &pkey) <= 0)
+            goto err;
+    } else {
+        CMSerr(0, CMS_R_DECODE_ERROR);
+        goto err;
+    }
+
+    return pkey;
+
+ err:
+    EVP_PKEY_free(pkey);
+    EVP_PKEY_CTX_free(pctx);
+    return NULL;
+}
+
+static int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx,
+                                X509_ALGOR *alg, ASN1_BIT_STRING *pubkey)
+{
+    const ASN1_OBJECT *aoid;
+    int atype;
+    const void *aval;
+    int rv = 0;
+    EVP_PKEY *pkpeer = NULL;
+    const unsigned char *p;
+    int plen;
+
+    X509_ALGOR_get0(&aoid, &atype, &aval, alg);
+    if (OBJ_obj2nid(aoid) != NID_X9_62_id_ecPublicKey)
+        goto err;
+
+    /* If absent parameters get group from main key */
+    if (atype == V_ASN1_UNDEF || atype == V_ASN1_NULL) {
+        EVP_PKEY *pk;
+
+        pk = EVP_PKEY_CTX_get0_pkey(pctx);
+        if (pk == NULL)
+            goto err;
+
+        pkpeer = EVP_PKEY_new();
+        if (pkpeer == NULL)
+            goto err;
+        if (!EVP_PKEY_copy_parameters(pkpeer, pk))
+            goto err;
+    } else {
+        pkpeer = pkey_type2param(atype, aval,
+                                 EVP_PKEY_CTX_get0_libctx(pctx),
+                                 EVP_PKEY_CTX_get0_propq(pctx));
+        if (pkpeer == NULL)
+            goto err;
+    }
+    /* We have parameters now set public key */
+    plen = ASN1_STRING_length(pubkey);
+    p = ASN1_STRING_get0_data(pubkey);
+    if (p == NULL || plen == 0)
+        goto err;
+
+    /* TODO(3.0): Terrible name. We need a non-tls specific name */
+    if (!EVP_PKEY_set1_tls_encodedpoint(pkpeer, p, plen))
+        goto err;
+
+    if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0)
+        rv = 1;
+ err:
+    EVP_PKEY_free(pkpeer);
+    return rv;
+}
+
+/* Set KDF parameters based on KDF NID */
+static int ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid)
+{
+    int kdf_nid, kdfmd_nid, cofactor;
+    const EVP_MD *kdf_md;
+
+    if (eckdf_nid == NID_undef)
+        return 0;
+
+    /* Lookup KDF type, cofactor mode and digest */
+    if (!OBJ_find_sigid_algs(eckdf_nid, &kdfmd_nid, &kdf_nid))
+        return 0;
+
+    if (kdf_nid == NID_dh_std_kdf)
+        cofactor = 0;
+    else if (kdf_nid == NID_dh_cofactor_kdf)
+        cofactor = 1;
+    else
+        return 0;
+
+    if (EVP_PKEY_CTX_set_ecdh_cofactor_mode(pctx, cofactor) <= 0)
+        return 0;
+
+    if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_63) <= 0)
+        return 0;
+
+    kdf_md = EVP_get_digestbynid(kdfmd_nid);
+    if (!kdf_md)
+        return 0;
+
+    if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
+        return 0;
+    return 1;
+}
+
+static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
+{
+    int rv = 0;
+    X509_ALGOR *alg, *kekalg = NULL;
+    ASN1_OCTET_STRING *ukm;
+    const unsigned char *p;
+    unsigned char *der = NULL;
+    int plen, keylen;
+    EVP_CIPHER *kekcipher = NULL;
+    EVP_CIPHER_CTX *kekctx;
+    const char *name;
+
+    if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
+        return 0;
+
+    if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(alg->algorithm))) {
+        CMSerr(0, CMS_R_KDF_PARAMETER_ERROR);
+        return 0;
+    }
+
+    if (alg->parameter->type != V_ASN1_SEQUENCE)
+        return 0;
+
+    p = alg->parameter->value.sequence->data;
+    plen = alg->parameter->value.sequence->length;
+    kekalg = d2i_X509_ALGOR(NULL, &p, plen);
+    if (kekalg == NULL)
+        goto err;
+    kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
+    if (kekctx == NULL)
+        goto err;
+    name = OBJ_nid2sn(OBJ_obj2nid(kekalg->algorithm));
+    kekcipher = EVP_CIPHER_fetch(pctx->libctx, name, pctx->propquery);
+    if (kekcipher == NULL || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
+        goto err;
+    if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
+        goto err;
+    if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0)
+        goto err;
+
+    keylen = EVP_CIPHER_CTX_key_length(kekctx);
+    if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
+        goto err;
+
+    plen = CMS_SharedInfo_encode(&der, kekalg, ukm, keylen);
+
+    if (plen <= 0)
+        goto err;
+
+    if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen) <= 0)
+        goto err;
+    der = NULL;
+
+    rv = 1;
+ err:
+    EVP_CIPHER_free(kekcipher);
+    X509_ALGOR_free(kekalg);
+    OPENSSL_free(der);
+    return rv;
+}
+
+static int ecdh_cms_decrypt(CMS_RecipientInfo *ri)
+{
+    EVP_PKEY_CTX *pctx;
+
+    pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
+    if (pctx == NULL)
+        return 0;
+    /* See if we need to set peer key */
+    if (!EVP_PKEY_CTX_get0_peerkey(pctx)) {
+        X509_ALGOR *alg;
+        ASN1_BIT_STRING *pubkey;
+
+        if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey,
+                                                 NULL, NULL, NULL))
+            return 0;
+        if (alg == NULL || pubkey == NULL)
+            return 0;
+        if (!ecdh_cms_set_peerkey(pctx, alg, pubkey)) {
+            CMSerr(0, CMS_R_PEER_KEY_ERROR);
+            return 0;
+        }
+    }
+    /* Set ECDH derivation parameters and initialise unwrap context */
+    if (!ecdh_cms_set_shared_info(pctx, ri)) {
+        CMSerr(0, CMS_R_SHARED_INFO_ERROR);
+        return 0;
+    }
+    return 1;
+}
+
+static int ecdh_cms_encrypt(CMS_RecipientInfo *ri)
+{
+    EVP_PKEY_CTX *pctx;
+    EVP_PKEY *pkey;
+    EVP_CIPHER_CTX *ctx;
+    int keylen;
+    X509_ALGOR *talg, *wrap_alg = NULL;
+    const ASN1_OBJECT *aoid;
+    ASN1_BIT_STRING *pubkey;
+    ASN1_STRING *wrap_str;
+    ASN1_OCTET_STRING *ukm;
+    unsigned char *penc = NULL;
+    size_t penclen;
+    int rv = 0;
+    int ecdh_nid, kdf_type, kdf_nid, wrap_nid;
+    const EVP_MD *kdf_md;
+
+    pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
+    if (pctx == NULL)
+        return 0;
+    /* Get ephemeral key */
+    pkey = EVP_PKEY_CTX_get0_pkey(pctx);
+    if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
+                                             NULL, NULL, NULL))
+        goto err;
+    X509_ALGOR_get0(&aoid, NULL, NULL, talg);
+    /* Is everything uninitialised? */
+    if (aoid == OBJ_nid2obj(NID_undef)) {
+        /* Set the key */
+
+        /* TODO(3.0): Terrible name. Needs a non TLS specific name */
+        penclen = EVP_PKEY_get1_tls_encodedpoint(pkey, &penc);
+        ASN1_STRING_set0(pubkey, penc, penclen);
+        pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
+        pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+
+        penc = NULL;
+        X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
+                        V_ASN1_UNDEF, NULL);
+    }
+
+    /* See if custom parameters set */
+    kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx);
+    if (kdf_type <= 0)
+        goto err;
+    if (!EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md))
+        goto err;
+    ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx);
+    if (ecdh_nid < 0)
+        goto err;
+    else if (ecdh_nid == 0)
+        ecdh_nid = NID_dh_std_kdf;
+    else if (ecdh_nid == 1)
+        ecdh_nid = NID_dh_cofactor_kdf;
+
+    if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) {
+        kdf_type = EVP_PKEY_ECDH_KDF_X9_63;
+        if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0)
+            goto err;
+    } else
+        /* Unknown KDF */
+        goto err;
+    if (kdf_md == NULL) {
+        /* Fixme later for better MD */
+        kdf_md = EVP_sha1();
+        if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
+            goto err;
+    }
+
+    if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
+        goto err;
+
+    /* Lookup NID for KDF+cofactor+digest */
+
+    if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_type(kdf_md), ecdh_nid))
+        goto err;
+    /* Get wrap NID */
+    ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
+    wrap_nid = EVP_CIPHER_CTX_type(ctx);
+    keylen = EVP_CIPHER_CTX_key_length(ctx);
+
+    /* Package wrap algorithm in an AlgorithmIdentifier */
+
+    wrap_alg = X509_ALGOR_new();
+    if (wrap_alg == NULL)
+        goto err;
+    wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
+    wrap_alg->parameter = ASN1_TYPE_new();
+    if (wrap_alg->parameter == NULL)
+        goto err;
+    if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
+        goto err;
+    if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) {
+        ASN1_TYPE_free(wrap_alg->parameter);
+        wrap_alg->parameter = NULL;
+    }
+
+    if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
+        goto err;
+
+    penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen);
+
+    if (penclen == 0)
+        goto err;
+
+    if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0)
+        goto err;
+    penc = NULL;
+
+    /*
+     * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter
+     * of another AlgorithmIdentifier.
+     */
+    penclen = i2d_X509_ALGOR(wrap_alg, &penc);
+    if (penc == NULL || penclen == 0)
+        goto err;
+    wrap_str = ASN1_STRING_new();
+    if (wrap_str == NULL)
+        goto err;
+    ASN1_STRING_set0(wrap_str, penc, penclen);
+    penc = NULL;
+    X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str);
+
+    rv = 1;
+
+ err:
+    OPENSSL_free(penc);
+    X509_ALGOR_free(wrap_alg);
+    return rv;
+}
+
+int cms_ecdh_envelope(CMS_RecipientInfo *ri, int decrypt)
+{
+    assert(decrypt == 0 || decrypt == 1);
+
+    if (decrypt == 1)
+        return ecdh_cms_decrypt(ri);
+
+    if (decrypt == 0)
+        return ecdh_cms_encrypt(ri);
+
+    CMSerr(0, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+    return 0;
+}
+#endif
+
+/* ECDSA and DSA implementation is the same */
+int cms_ecdsa_dsa_sign(CMS_SignerInfo *si, int verify)
+{
+    assert(verify == 0 || verify == 1);
+
+    if (verify == 0) {
+        int snid, hnid;
+        X509_ALGOR *alg1, *alg2;
+        EVP_PKEY *pkey = si->pkey;
+
+        CMS_SignerInfo_get0_algs(si, NULL, NULL, &alg1, &alg2);
+        if (alg1 == NULL || alg1->algorithm == NULL)
+            return -1;
+        hnid = OBJ_obj2nid(alg1->algorithm);
+        if (hnid == NID_undef)
+            return -1;
+        if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
+            return -1;
+        X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
+    }
+    return 1;
+}
diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c
index b1bba4c2d6..8f3e2db339 100644
--- a/crypto/cms/cms_env.c
+++ b/crypto/cms/cms_env.c
@@ -115,6 +115,21 @@ int cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd)
             return 0;
     } else
         return 0;
+
+#ifndef OPENSSL_NO_DH
+    if (EVP_PKEY_is_a(pkey, "DHX"))
+        return cms_dh_envelope(ri, cmd);
+    else
+#endif
+#ifndef OPENSSL_NO_EC
+    if (EVP_PKEY_is_a(pkey, "EC"))
+        return cms_ecdh_envelope(ri, cmd);
+    else
+#endif
+    if (EVP_PKEY_is_a(pkey, "RSA"))
+        return cms_rsa_envelope(ri, cmd);
+
+    /* Something else? We'll give engines etc a chance to handle this */
     if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL)
         return 1;
     i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_ENVELOPE, cmd, ri);
@@ -1288,6 +1303,20 @@ err:
  */
 int cms_pkey_get_ri_type(EVP_PKEY *pk)
 {
+    /* Check types that we know about */
+    if (EVP_PKEY_is_a(pk, "DH"))
+        return CMS_RECIPINFO_AGREE;
+    else if (EVP_PKEY_is_a(pk, "DSA"))
+        return CMS_RECIPINFO_NONE;
+    else if (EVP_PKEY_is_a(pk, "EC"))
+        return CMS_RECIPINFO_AGREE;
+    else if (EVP_PKEY_is_a(pk, "RSA"))
+        return CMS_RECIPINFO_TRANS;
+
+    /*
+     * Otherwise this might ben an engine implementation, so see if we can get
+     * the type from the ameth.
+     */
     if (pk->ameth && pk->ameth->pkey_ctrl) {
         int i, r;
         i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_RI_TYPE, 0, &r);
diff --git a/crypto/cms/cms_err.c b/crypto/cms/cms_err.c
index da14c726c4..fdb2b7f5c8 100644
--- a/crypto/cms/cms_err.c
+++ b/crypto/cms/cms_err.c
@@ -47,6 +47,7 @@ static const ERR_STRING_DATA CMS_str_reasons[] = {
     "content verify error"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CTRL_ERROR), "ctrl error"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CTRL_FAILURE), "ctrl failure"},
+    {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_DECODE_ERROR), "decode error"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_DECRYPT_ERROR), "decrypt error"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ERROR_GETTING_PUBLIC_KEY),
     "error getting public key"},
@@ -64,6 +65,11 @@ static const ERR_STRING_DATA CMS_str_reasons[] = {
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER),
     "invalid key encryption parameter"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_KEY_LENGTH), "invalid key length"},
+    {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_LABEL), "invalid label"},
+    {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_OAEP_PARAMETERS),
+    "invalid oaep parameters"},
+    {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_KDF_PARAMETER_ERROR),
+    "kdf parameter error"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MD_BIO_INIT_ERROR), "md bio init error"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH),
     "messagedigest attribute wrong length"},
@@ -102,11 +108,13 @@ static const ERR_STRING_DATA CMS_str_reasons[] = {
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_PUBLIC_KEY), "no public key"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_RECEIPT_REQUEST), "no receipt request"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_SIGNERS), "no signers"},
+    {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_PEER_KEY_ERROR), "peer key error"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE),
     "private key does not match certificate"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_RECEIPT_DECODE_ERROR),
     "receipt decode error"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_RECIPIENT_ERROR), "recipient error"},
+    {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_SHARED_INFO_ERROR), "shared info error"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND),
     "signer certificate not found"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_SIGNFINAL_ERROR), "signfinal error"},
@@ -131,10 +139,14 @@ static const ERR_STRING_DATA CMS_str_reasons[] = {
     "unsupported compression algorithm"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_CONTENT_TYPE),
     "unsupported content type"},
+    {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_ENCRYPTION_TYPE),
+    "unsupported encryption type"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_KEK_ALGORITHM),
     "unsupported kek algorithm"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM),
     "unsupported key encryption algorithm"},
+    {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_LABEL_SOURCE),
+    "unsupported label source"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE),
     "unsupported recipientinfo type"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_RECIPIENT_TYPE),
diff --git a/crypto/cms/cms_kari.c b/crypto/cms/cms_kari.c
index 82a03e6c6b..13f7e78d37 100644
--- a/crypto/cms/cms_kari.c
+++ b/crypto/cms/cms_kari.c
@@ -261,26 +261,6 @@ int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms,
     size_t ceklen;
     CMS_EncryptedContentInfo *ec;
 
-    {
-        /*
-         * TODO(3.0) Remove this when we have functionality to deserialize
-         * parameters in EVP_PKEY form from an X509_ALGOR.
-         * This is needed to be able to replace the EC_KEY specific decoding
-         * that happens in ecdh_cms_set_peerkey() (crypto/ec/ec_ameth.c)
-         *
-         * THIS IS TEMPORARY
-         */
-        EVP_PKEY_CTX *pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
-        EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
-
-        EVP_PKEY_get0(pkey);
-        if (EVP_PKEY_id(pkey) == EVP_PKEY_NONE) {
-            CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_DECRYPT,
-                   CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
-            goto err;
-        }
-    }
-
     enckeylen = rek->encryptedKey->length;
     enckey = rek->encryptedKey->data;
     /* Setup all parameters to derive KEK */
@@ -499,32 +479,6 @@ int cms_RecipientInfo_kari_encrypt(const CMS_ContentInfo *cms,
     STACK_OF(CMS_RecipientEncryptedKey) *reks;
     int i;
 
-    {
-        /*
-         * TODO(3.0) Remove this when we have figured out all the details
-         * need to set up encryption right.  With legacy keys, a *lot* is
-         * happening in the CMS specific EVP_PKEY_ASN1_METHOD functions,
-         * such as automatically setting a default KDF type, KDF digest,
-         * all that kind of stuff.
-         * With EVP_SIGNATURE, setting a default digest is done by getting
-         * the default MD for the key, and then inject that back into the
-         * signature implementation...  we could do something similar with
-         * CMS, possibly using CMS specific OSSL_PARAM keys, just like we
-         * have for certain AlgorithmIdentifier retrievals.
-         *
-         * THIS IS TEMPORARY
-         */
-        EVP_PKEY_CTX *pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
-        EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
-
-        EVP_PKEY_get0(pkey);
-        if (EVP_PKEY_id(pkey) == EVP_PKEY_NONE) {
-            CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT,
-                   CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
-            return 0;
-        }
-    }
-
     if (ri->type != CMS_RECIPINFO_AGREE) {
         CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT, CMS_R_NOT_KEY_AGREEMENT);
         return 0;
diff --git a/crypto/cms/cms_local.h b/crypto/cms/cms_local.h
index 336c354655..0b663a9e88 100644
--- a/crypto/cms/cms_local.h
+++ b/crypto/cms/cms_local.h
@@ -471,6 +471,12 @@ void cms_SignerInfos_set_cmsctx(CMS_ContentInfo *cms);
 /* ESS routines */
 int ess_check_signing_certs(CMS_SignerInfo *si, STACK_OF(X509) *chain);
 
+int cms_dh_envelope(CMS_RecipientInfo *ri, int decrypt);
+int cms_ecdh_envelope(CMS_RecipientInfo *ri, int decrypt);
+int cms_rsa_envelope(CMS_RecipientInfo *ri, int decrypt);
+int cms_ecdsa_dsa_sign(CMS_SignerInfo *si, int verify);
+int cms_rsa_sign(CMS_SignerInfo *si, int verify);
+
 DECLARE_ASN1_ITEM(CMS_CertificateChoices)
 DECLARE_ASN1_ITEM(CMS_DigestedData)
 DECLARE_ASN1_ITEM(CMS_EncryptedData)
diff --git a/crypto/cms/cms_rsa.c b/crypto/cms/cms_rsa.c
new file mode 100644
index 0000000000..88201d7b44
--- /dev/null
+++ b/crypto/cms/cms_rsa.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2006-2020 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 <assert.h>
+#include <openssl/cms.h>
+#include <openssl/err.h>
+#include "crypto/asn1.h"
+#include "crypto/rsa.h"
+#include "cms_local.h"
+
+static RSA_OAEP_PARAMS *rsa_oaep_decode(const X509_ALGOR *alg)
+{
+    RSA_OAEP_PARAMS *oaep;
+
+    oaep = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_OAEP_PARAMS),
+                                     alg->parameter);
+
+    if (oaep == NULL)
+        return NULL;
+
+    if (oaep->maskGenFunc != NULL) {
+        oaep->maskHash = x509_algor_mgf1_decode(oaep->maskGenFunc);
+        if (oaep->maskHash == NULL) {
+            RSA_OAEP_PARAMS_free(oaep);
+            return NULL;
+        }
+    }
+    return oaep;
+}
+
+static int rsa_cms_decrypt(CMS_RecipientInfo *ri)
+{
+    EVP_PKEY_CTX *pkctx;
+    X509_ALGOR *cmsalg;
+    int nid;
+    int rv = -1;
+    unsigned char *label = NULL;
+    int labellen = 0;
+    const EVP_MD *mgf1md = NULL, *md = NULL;
+    RSA_OAEP_PARAMS *oaep;
+
+    pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
+    if (pkctx == NULL)
+        return 0;
+    if (!CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &cmsalg))
+        return -1;
+    nid = OBJ_obj2nid(cmsalg->algorithm);
+    if (nid == NID_rsaEncryption)
+        return 1;
+    if (nid != NID_rsaesOaep) {
+        CMSerr(0, CMS_R_UNSUPPORTED_ENCRYPTION_TYPE);
+        return -1;
+    }
+    /* Decode OAEP parameters */
+    oaep = rsa_oaep_decode(cmsalg);
+
+    if (oaep == NULL) {
+        CMSerr(0, CMS_R_INVALID_OAEP_PARAMETERS);
+        goto err;
+    }
+
+    mgf1md = x509_algor_get_md(oaep->maskHash);
+    if (mgf1md == NULL)
+        goto err;
+    md = x509_algor_get_md(oaep->hashFunc);
+    if (md == NULL)
+        goto err;
+
+    if (oaep->pSourceFunc != NULL) {
+        X509_ALGOR *plab = oaep->pSourceFunc;
+
+        if (OBJ_obj2nid(plab->algorithm) != NID_pSpecified) {
+            CMSerr(0, CMS_R_UNSUPPORTED_LABEL_SOURCE);
+            goto err;
+        }
+        if (plab->parameter->type != V_ASN1_OCTET_STRING) {
+            CMSerr(0, CMS_R_INVALID_LABEL);
+            goto err;
+        }
+
+        label = plab->parameter->value.octet_string->data;
+        /* Stop label being freed when OAEP parameters are freed */
+        plab->parameter->value.octet_string->data = NULL;
+        labellen = plab->parameter->value.octet_string->length;
+    }
+
+    if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0)
+        goto err;
+    if (EVP_PKEY_CTX_set_rsa_oaep_md(pkctx, md) <= 0)
+        goto err;
+    if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0)
+        goto err;
+    if (label != NULL
+            && EVP_PKEY_CTX_set0_rsa_oaep_label(pkctx, label, labellen) <= 0)
+        goto err;
+    /* Carry on */
+    rv = 1;
+
+ err:
+    RSA_OAEP_PARAMS_free(oaep);
+    return rv;
+}
+
+static int rsa_cms_encrypt(CMS_RecipientInfo *ri)
+{
+    const EVP_MD *md, *mgf1md;
+    RSA_OAEP_PARAMS *oaep = NULL;
+    ASN1_STRING *os = NULL;
+    X509_ALGOR *alg;
+    EVP_PKEY_CTX *pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
+    int pad_mode = RSA_PKCS1_PADDING, rv = 0, labellen;
+    unsigned char *label;
+
+    if (CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &alg) <= 0)
+        return 0;
+    if (pkctx != NULL) {
+        if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
+            return 0;
+    }
+    if (pad_mode == RSA_PKCS1_PADDING) {
+        X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
+        return 1;
+    }
+    /* Not supported */
+    if (pad_mode != RSA_PKCS1_OAEP_PADDING)
+        return 0;
+    if (EVP_PKEY_CTX_get_rsa_oaep_md(pkctx, &md) <= 0)
+        goto err;
+    if (EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) <= 0)
+        goto err;
+    labellen = EVP_PKEY_CTX_get0_rsa_oaep_label(pkctx, &label);
+    if (labellen < 0)
+        goto err;
+    oaep = RSA_OAEP_PARAMS_new();
+    if (oaep == NULL)
+        goto err;
+    if (!x509_algor_new_from_md(&oaep->hashFunc, md))
+        goto err;
+    if (!x509_algor_md_to_mgf1(&oaep->maskGenFunc, mgf1md))
+        goto err;
+    if (labellen > 0) {
+        ASN1_OCTET_STRING *los;
+
+        oaep->pSourceFunc = X509_ALGOR_new();
+        if (oaep->pSourceFunc == NULL)
+            goto err;
+        los = ASN1_OCTET_STRING_new();
+        if (los == NULL)
+            goto err;
+        if (!ASN1_OCTET_STRING_set(los, label, labellen)) {
+            ASN1_OCTET_STRING_free(los);
+            goto err;
+        }
+        X509_ALGOR_set0(oaep->pSourceFunc, OBJ_nid2obj(NID_pSpecified),
+                        V_ASN1_OCTET_STRING, los);
+    }
+    /* create string with pss parameter encoding. */
+    if (!ASN1_item_pack(oaep, ASN1_ITEM_rptr(RSA_OAEP_PARAMS), &os))
+         goto err;
+    X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaesOaep), V_ASN1_SEQUENCE, os);
+    os = NULL;
+    rv = 1;
+ err:
+    RSA_OAEP_PARAMS_free(oaep);
+    ASN1_STRING_free(os);
+    return rv;
+}
+
+int cms_rsa_envelope(CMS_RecipientInfo *ri, int decrypt)
+{
+    assert(decrypt == 0 || decrypt == 1);
+
+    if (decrypt == 1)
+        return rsa_cms_decrypt(ri);
+
+    if (decrypt == 0)
+        return rsa_cms_encrypt(ri);
+
+    CMSerr(0, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+    return 0;
+}
+
+static int rsa_cms_sign(CMS_SignerInfo *si)
+{
+    int pad_mode = RSA_PKCS1_PADDING;
+    X509_ALGOR *alg;
+    EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si);
+    ASN1_STRING *os = NULL;
+
+    CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg);
+    if (pkctx != NULL) {
+        if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
+            return 0;
+    }
+    if (pad_mode == RSA_PKCS1_PADDING) {
+        X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
+        return 1;
+    }
+    /* We don't support it */
+    if (pad_mode != RSA_PKCS1_PSS_PADDING)
+        return 0;
+    os = ossl_rsa_ctx_to_pss_string(pkctx);
+    if (os == NULL)
+        return 0;
+    X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_PKEY_RSA_PSS), V_ASN1_SEQUENCE, os);
+    return 1;
+}
+
+static int rsa_cms_verify(CMS_SignerInfo *si)
+{
+    int nid, nid2;
+    X509_ALGOR *alg;
+    EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si);
+    EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pkctx);
+
+    CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg);
+    nid = OBJ_obj2nid(alg->algorithm);
+    if (nid == EVP_PKEY_RSA_PSS)
+        return ossl_rsa_pss_to_ctx(NULL, pkctx, alg, NULL);
+    /* Only PSS allowed for PSS keys */
+    if (EVP_PKEY_is_a(pkey, "RSA-PSS")) {
+        RSAerr(RSA_F_RSA_CMS_VERIFY, RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
+        return 0;
+    }
+    if (nid == NID_rsaEncryption)
+        return 1;
+    /* Workaround for some implementation that use a signature OID */
+    if (OBJ_find_sigid_algs(nid, NULL, &nid2)) {
+        if (nid2 == NID_rsaEncryption)
+            return 1;
+    }
+    return 0;
+}
+
+int cms_rsa_sign(CMS_SignerInfo *si, int verify)
+{
+    assert(verify == 0 || verify == 1);
+
+    if (verify == 1)
+        return rsa_cms_verify(si);
+
+    if (verify == 0)
+        return rsa_cms_sign(si);
+
+    CMSerr(0, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+    return 0;
+}
diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c
index 1338211072..377fac5917 100644
--- a/crypto/cms/cms_sd.c
+++ b/crypto/cms/cms_sd.c
@@ -233,6 +233,15 @@ static int cms_sd_asn1_ctrl(CMS_SignerInfo *si, int cmd)
     EVP_PKEY *pkey = si->pkey;
     int i;
 
+#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC)
+    if (EVP_PKEY_is_a(pkey, "DSA") || EVP_PKEY_is_a(pkey, "EC"))
+        return cms_ecdsa_dsa_sign(si, cmd);
+    else
+#endif
+    if (EVP_PKEY_is_a(pkey, "RSA") || EVP_PKEY_is_a(pkey, "RSA-PSS"))
+        return cms_rsa_sign(si, cmd);
+
+    /* Something else? We'll give engines etc a chance to handle this */
     if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL)
         return 1;
     i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_SIGN, cmd, si);
diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c
index e32de78638..9ad75d2092 100644
--- a/crypto/dh/dh_ameth.c
+++ b/crypto/dh/dh_ameth.c
@@ -14,18 +14,17 @@
 #include "internal/deprecated.h"
 
 #include <stdio.h>
-#include "internal/cryptlib.h"
 #include <openssl/x509.h>
 #include <openssl/asn1.h>
-#include "dh_local.h"
 #include <openssl/bn.h>
-#include "crypto/asn1.h"
-#include "crypto/dh.h"
-#include "crypto/evp.h"
-#include <openssl/cms.h>
 #include <openssl/core_names.h>
 #include <openssl/param_build.h>
 #include "internal/ffc.h"
+#include "internal/cryptlib.h"
+#include "crypto/asn1.h"
+#include "crypto/dh.h"
+#include "crypto/evp.h"
+#include "dh_local.h"
 
 /*
  * i2d/d2i like DH parameter functions which use the appropriate routine for
@@ -434,11 +433,6 @@ int DHparams_print(BIO *bp, const DH *x)
     return do_dh_print(bp, x, 4, 0);
 }
 
-#ifndef OPENSSL_NO_CMS
-static int dh_cms_decrypt(CMS_RecipientInfo *ri);
-static int dh_cms_encrypt(CMS_RecipientInfo *ri);
-#endif
-
 static int dh_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
 {
     switch (op) {
@@ -454,19 +448,6 @@ static int dh_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
 static int dhx_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
 {
     switch (op) {
-#ifndef OPENSSL_NO_CMS
-
-    case ASN1_PKEY_CTRL_CMS_ENVELOPE:
-        if (arg1 == 1)
-            return dh_cms_decrypt(arg2);
-        else if (arg1 == 0)
-            return dh_cms_encrypt(arg2);
-        return -2;
-
-    case ASN1_PKEY_CTRL_CMS_RI_TYPE:
-        *(int *)arg2 = CMS_RECIPINFO_AGREE;
-        return 1;
-#endif
     default:
         return -2;
     }
@@ -675,308 +656,3 @@ const EVP_PKEY_ASN1_METHOD dhx_asn1_meth = {
     dh_pkey_export_to,
     dhx_pkey_import_from,
 };
-
-#ifndef OPENSSL_NO_CMS
-
-static int dh_cms_set_peerkey(EVP_PKEY_CTX *pctx,
-                              X509_ALGOR *alg, ASN1_BIT_STRING *pubkey)
-{
-    const ASN1_OBJECT *aoid;
-    int atype;
-    const void *aval;
-    ASN1_INTEGER *public_key = NULL;
-    int rv = 0;
-    EVP_PKEY *pkpeer = NULL, *pk = NULL;
-    DH *dhpeer = NULL;
-    const unsigned char *p;
-    int plen;
-
-    X509_ALGOR_get0(&aoid, &atype, &aval, alg);
-    if (OBJ_obj2nid(aoid) != NID_dhpublicnumber)
-        goto err;
-    /* Only absent parameters allowed in RFC XXXX */
-    if (atype != V_ASN1_UNDEF && atype == V_ASN1_NULL)
-        goto err;
-
-    pk = EVP_PKEY_CTX_get0_pkey(pctx);
-    if (pk == NULL)
-        goto err;
-    if (pk->type != EVP_PKEY_DHX)
-        goto err;
-    /* Get parameters from parent key */
-    dhpeer = DHparams_dup(pk->pkey.dh);
-    /* We have parameters now set public key */
-    plen = ASN1_STRING_length(pubkey);
-    p = ASN1_STRING_get0_data(pubkey);
-    if (p == NULL || plen == 0)
-        goto err;
-
-    if ((public_key = d2i_ASN1_INTEGER(NULL, &p, plen)) == NULL) {
-        DHerr(DH_F_DH_CMS_SET_PEERKEY, DH_R_DECODE_ERROR);
-        goto err;
-    }
-
-    /* We have parameters now set public key */
-    if ((dhpeer->pub_key = ASN1_INTEGER_to_BN(public_key, NULL)) == NULL) {
-        DHerr(DH_F_DH_CMS_SET_PEERKEY, DH_R_BN_DECODE_ERROR);
-        goto err;
-    }
-
-    pkpeer = EVP_PKEY_new();
-    if (pkpeer == NULL)
-        goto err;
-    EVP_PKEY_assign(pkpeer, pk->ameth->pkey_id, dhpeer);
-    dhpeer = NULL;
-    if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0)
-        rv = 1;
- err:
-    ASN1_INTEGER_free(public_key);
-    EVP_PKEY_free(pkpeer);
-    DH_free(dhpeer);
-    return rv;
-}
-
-static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
-{
-    int rv = 0;
-
-    X509_ALGOR *alg, *kekalg = NULL;
-    ASN1_OCTET_STRING *ukm;
-    const unsigned char *p;
-    unsigned char *dukm = NULL;
-    size_t dukmlen = 0;
-    int keylen, plen;
-    const EVP_CIPHER *kekcipher;
-    EVP_CIPHER_CTX *kekctx;
-
-    if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
-        goto err;
-
-    /*
-     * For DH we only have one OID permissible. If ever any more get defined
-     * we will need something cleverer.
-     */
-    if (OBJ_obj2nid(alg->algorithm) != NID_id_smime_alg_ESDH) {
-        DHerr(DH_F_DH_CMS_SET_SHARED_INFO, DH_R_KDF_PARAMETER_ERROR);
-        goto err;
-    }
-
-    if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, EVP_PKEY_DH_KDF_X9_42) <= 0)
-        goto err;
-
-    if (EVP_PKEY_CTX_set_dh_kdf_md(pctx, EVP_sha1()) <= 0)
-        goto err;
-
-    if (alg->parameter->type != V_ASN1_SEQUENCE)
-        goto err;
-
-    p = alg->parameter->value.sequence->data;
-    plen = alg->parameter->value.sequence->length;
-    kekalg = d2i_X509_ALGOR(NULL, &p, plen);
-    if (!kekalg)
-        goto err;
-    kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
-    if (!kekctx)
-        goto err;
-    kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
-    if (!kekcipher || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
-        goto err;
-    if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
-        goto err;
-    if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0)
-        goto err;
-
-    keylen = EVP_CIPHER_CTX_key_length(kekctx);
-    if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0)
-        goto err;
-    /* Use OBJ_nid2obj to ensure we use built in OID that isn't freed */
-    if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx,
-                                     OBJ_nid2obj(EVP_CIPHER_type(kekcipher)))
-        <= 0)
-        goto err;
-
-    if (ukm) {
-        dukmlen = ASN1_STRING_length(ukm);
-        dukm = OPENSSL_memdup(ASN1_STRING_get0_data(ukm), dukmlen);
-        if (!dukm)
-            goto err;
-    }
-
-    if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0)
-        goto err;
-    dukm = NULL;
-
-    rv = 1;
- err:
-    X509_ALGOR_free(kekalg);
-    OPENSSL_free(dukm);
-    return rv;
-}
-
-static int dh_cms_decrypt(CMS_RecipientInfo *ri)
-{
-    EVP_PKEY_CTX *pctx;
-
-    pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
-
-    if (pctx == NULL)
-        return 0;
-    /* See if we need to set peer key */
-    if (!EVP_PKEY_CTX_get0_peerkey(pctx)) {
-        X509_ALGOR *alg;
-        ASN1_BIT_STRING *pubkey;
-        if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey,
-                                                 NULL, NULL, NULL))
-            return 0;
-        if (!alg || !pubkey)
-            return 0;
-        if (!dh_cms_set_peerkey(pctx, alg, pubkey)) {
-            DHerr(DH_F_DH_CMS_DECRYPT, DH_R_PEER_KEY_ERROR);
-            return 0;
-        }
-    }
-    /* Set DH derivation parameters and initialise unwrap context */
-    if (!dh_cms_set_shared_info(pctx, ri)) {
-        DHerr(DH_F_DH_CMS_DECRYPT, DH_R_SHARED_INFO_ERROR);
-        return 0;
-    }
-    return 1;
-}
-
-static int dh_cms_encrypt(CMS_RecipientInfo *ri)
-{
-    EVP_PKEY_CTX *pctx;
-    EVP_PKEY *pkey;
-    EVP_CIPHER_CTX *ctx;
-    int keylen;
-    X509_ALGOR *talg, *wrap_alg = NULL;
-    const ASN1_OBJECT *aoid;
-    ASN1_BIT_STRING *pubkey;
-    ASN1_STRING *wrap_str;
-    ASN1_OCTET_STRING *ukm;
-    unsigned char *penc = NULL, *dukm = NULL;
-    int penclen;
-    size_t dukmlen = 0;
-    int rv = 0;
-    int kdf_type, wrap_nid;
-    const EVP_MD *kdf_md;
-
-    pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
-    if (pctx == NULL)
-        return 0;
-    /* Get ephemeral key */
-    pkey = EVP_PKEY_CTX_get0_pkey(pctx);
-    if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
-                                             NULL, NULL, NULL))
-        goto err;
-    X509_ALGOR_get0(&aoid, NULL, NULL, talg);
-    /* Is everything uninitialised? */
-    if (aoid == OBJ_nid2obj(NID_undef)) {
-        ASN1_INTEGER *pubk = BN_to_ASN1_INTEGER(pkey->pkey.dh->pub_key, NULL);
-
-        if (pubk == NULL)
-            goto err;
-        /* Set the key */
-
-        penclen = i2d_ASN1_INTEGER(pubk, &penc);
-        ASN1_INTEGER_free(pubk);
-        if (penclen <= 0)
-            goto err;
-        ASN1_STRING_set0(pubkey, penc, penclen);
-        pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
-        pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
-
-        penc = NULL;
-        X509_ALGOR_set0(talg, OBJ_nid2obj(NID_dhpublicnumber),
-                        V_ASN1_UNDEF, NULL);
-    }
-
-    /* See if custom parameters set */
-    kdf_type = EVP_PKEY_CTX_get_dh_kdf_type(pctx);
-    if (kdf_type <= 0)
-        goto err;
-    if (!EVP_PKEY_CTX_get_dh_kdf_md(pctx, &kdf_md))
-        goto err;
-
-    if (kdf_type == EVP_PKEY_DH_KDF_NONE) {
-        kdf_type = EVP_PKEY_DH_KDF_X9_42;
-        if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, kdf_type) <= 0)
-            goto err;
-    } else if (kdf_type != EVP_PKEY_DH_KDF_X9_42)
-        /* Unknown KDF */
-        goto err;
-    if (kdf_md == NULL) {
-        /* Only SHA1 supported */
-        kdf_md = EVP_sha1();
-        if (EVP_PKEY_CTX_set_dh_kdf_md(pctx, kdf_md) <= 0)
-            goto err;
-    } else if (EVP_MD_type(kdf_md) != NID_sha1)
-        /* Unsupported digest */
-        goto err;
-
-    if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
-        goto err;
-
-    /* Get wrap NID */
-    ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
-    wrap_nid = EVP_CIPHER_CTX_type(ctx);
-    if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx, OBJ_nid2obj(wrap_nid)) <= 0)
-        goto err;
-    keylen = EVP_CIPHER_CTX_key_length(ctx);
-
-    /* Package wrap algorithm in an AlgorithmIdentifier */
-
-    wrap_alg = X509_ALGOR_new();
-    if (wrap_alg == NULL)
-        goto err;
-    wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
-    wrap_alg->parameter = ASN1_TYPE_new();
-    if (wrap_alg->parameter == NULL)
-        goto err;
-    if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
-        goto err;
-    if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) {
-        ASN1_TYPE_free(wrap_alg->parameter);
-        wrap_alg->parameter = NULL;
-    }
-
-    if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0)
-        goto err;
-
-    if (ukm) {
-        dukmlen = ASN1_STRING_length(ukm);
-        dukm = OPENSSL_memdup(ASN1_STRING_get0_data(ukm), dukmlen);
-        if (!dukm)
-            goto err;
-    }
-
-    if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0)
-        goto err;
-    dukm = NULL;
-
-    /*
-     * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter
-     * of another AlgorithmIdentifier.
-     */
-    penc = NULL;
-    penclen = i2d_X509_ALGOR(wrap_alg, &penc);
-    if (penc == NULL || penclen == 0)
-        goto err;
-    wrap_str = ASN1_STRING_new();
-    if (wrap_str == NULL)
-        goto err;
-    ASN1_STRING_set0(wrap_str, penc, penclen);
-    penc = NULL;
-    X509_ALGOR_set0(talg, OBJ_nid2obj(NID_id_smime_alg_ESDH),
-                    V_ASN1_SEQUENCE, wrap_str);
-
-    rv = 1;
-
- err:
-    OPENSSL_free(penc);
-    X509_ALGOR_free(wrap_alg);
-    OPENSSL_free(dukm);
-    return rv;
-}
-
-#endif
diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c
index 7619c05b5e..98b531ea24 100644
--- a/crypto/dsa/dsa_ameth.c
+++ b/crypto/dsa/dsa_ameth.c
@@ -17,7 +17,6 @@
 #include <openssl/x509.h>
 #include <openssl/asn1.h>
 #include <openssl/bn.h>
-#include <openssl/cms.h>
 #include <openssl/core_names.h>
 #include <openssl/param_build.h>
 #include "internal/cryptlib.h"
@@ -481,27 +480,6 @@ static int dsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
             X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
         }
         return 1;
-#ifndef OPENSSL_NO_CMS
-    case ASN1_PKEY_CTRL_CMS_SIGN:
-        if (arg1 == 0) {
-            int snid, hnid;
-            X509_ALGOR *alg1, *alg2;
-            CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2);
-            if (alg1 == NULL || alg1->algorithm == NULL)
-                return -1;
-            hnid = OBJ_obj2nid(alg1->algorithm);
-            if (hnid == NID_undef)
-                return -1;
-            if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
-                return -1;
-            X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
-        }
-        return 1;
-
-    case ASN1_PKEY_CTRL_CMS_RI_TYPE:
-        *(int *)arg2 = CMS_RECIPINFO_NONE;
-        return 1;
-#endif
 
     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
         *(int *)arg2 = NID_sha256;
diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c
index 4bbbabff07..caeb7f70cc 100644
--- a/crypto/ec/ec_ameth.c
+++ b/crypto/ec/ec_ameth.c
@@ -18,7 +18,6 @@
 #include <openssl/x509.h>
 #include <openssl/ec.h>
 #include <openssl/bn.h>
-#include <openssl/cms.h>
 #include <openssl/asn1t.h>
 #include "crypto/asn1.h"
 #include "crypto/evp.h"
@@ -27,11 +26,6 @@
 #include "openssl/param_build.h"
 #include "ec_local.h"
 
-#ifndef OPENSSL_NO_CMS
-static int ecdh_cms_decrypt(CMS_RecipientInfo *ri);
-static int ecdh_cms_encrypt(CMS_RecipientInfo *ri);
-#endif
-
 static int eckey_param2type(int *pptype, void **ppval, const EC_KEY *ec_key)
 {
     const EC_GROUP *group;
@@ -494,34 +488,6 @@ static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
             X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
         }
         return 1;
-#ifndef OPENSSL_NO_CMS
-    case ASN1_PKEY_CTRL_CMS_SIGN:
-        if (arg1 == 0) {
-            int snid, hnid;
-            X509_ALGOR *alg1, *alg2;
-            CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2);
-            if (alg1 == NULL || alg1->algorithm == NULL)
-                return -1;
-            hnid = OBJ_obj2nid(alg1->algorithm);
-            if (hnid == NID_undef)
-                return -1;
-            if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
-                return -1;
-            X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
-        }
-        return 1;
-
-    case ASN1_PKEY_CTRL_CMS_ENVELOPE:
-        if (arg1 == 1)
-            return ecdh_cms_decrypt(arg2);
-        else if (arg1 == 0)
-            return ecdh_cms_encrypt(arg2);
-        return -2;
-
-    case ASN1_PKEY_CTRL_CMS_RI_TYPE:
-        *(int *)arg2 = CMS_RECIPINFO_AGREE;
-        return 1;
-#endif
 
     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
         if (EVP_PKEY_id(pkey) == EVP_PKEY_SM2) {
@@ -828,327 +794,3 @@ int ECParameters_print(BIO *bp, const EC_KEY *x)
 {
     return do_EC_KEY_print(bp, x, 4, EC_KEY_PRINT_PARAM);
 }
-
-#ifndef OPENSSL_NO_CMS
-
-static int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx,
-                                X509_ALGOR *alg, ASN1_BIT_STRING *pubkey)
-{
-    const ASN1_OBJECT *aoid;
-    int atype;
-    const void *aval;
-    int rv = 0;
-    EVP_PKEY *pkpeer = NULL;
-    EC_KEY *ecpeer = NULL;
-    const unsigned char *p;
-    int plen;
-
-    X509_ALGOR_get0(&aoid, &atype, &aval, alg);
-    if (OBJ_obj2nid(aoid) != NID_X9_62_id_ecPublicKey)
-        goto err;
-    /* If absent parameters get group from main key */
-    if (atype == V_ASN1_UNDEF || atype == V_ASN1_NULL) {
-        const EC_GROUP *grp;
-        EVP_PKEY *pk;
-        pk = EVP_PKEY_CTX_get0_pkey(pctx);
-        if (pk == NULL)
-            goto err;
-        grp = EC_KEY_get0_group(pk->pkey.ec);
-        ecpeer = EC_KEY_new();
-        if (ecpeer == NULL)
-            goto err;
-        if (!EC_KEY_set_group(ecpeer, grp))
-            goto err;
-    } else {
-        ecpeer = eckey_type2param(atype, aval, pctx->libctx, pctx->propquery);
-        if (!ecpeer)
-            goto err;
-    }
-    /* We have parameters now set public key */
-    plen = ASN1_STRING_length(pubkey);
-    p = ASN1_STRING_get0_data(pubkey);
-    if (p == NULL || plen == 0)
-        goto err;
-    if (!o2i_ECPublicKey(&ecpeer, &p, plen))
-        goto err;
-    pkpeer = EVP_PKEY_new();
-    if (pkpeer == NULL)
-        goto err;
-    EVP_PKEY_set1_EC_KEY(pkpeer, ecpeer);
-    if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0)
-        rv = 1;
- err:
-    EC_KEY_free(ecpeer);
-    EVP_PKEY_free(pkpeer);
-    return rv;
-}
-
-/* Set KDF parameters based on KDF NID */
-static int ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid)
-{
-    int kdf_nid, kdfmd_nid, cofactor;
-    const EVP_MD *kdf_md;
-    if (eckdf_nid == NID_undef)
-        return 0;
-
-    /* Lookup KDF type, cofactor mode and digest */
-    if (!OBJ_find_sigid_algs(eckdf_nid, &kdfmd_nid, &kdf_nid))
-        return 0;
-
-    if (kdf_nid == NID_dh_std_kdf)
-        cofactor = 0;
-    else if (kdf_nid == NID_dh_cofactor_kdf)
-        cofactor = 1;
-    else
-        return 0;
-
-    if (EVP_PKEY_CTX_set_ecdh_cofactor_mode(pctx, cofactor) <= 0)
-        return 0;
-
-    if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_63) <= 0)
-        return 0;
-
-    kdf_md = EVP_get_digestbynid(kdfmd_nid);
-    if (!kdf_md)
-        return 0;
-
-    if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
-        return 0;
-    return 1;
-}
-
-static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
-{
-    int rv = 0;
-
-    X509_ALGOR *alg, *kekalg = NULL;
-    ASN1_OCTET_STRING *ukm;
-    const unsigned char *p;
-    unsigned char *der = NULL;
-    int plen, keylen;
-    EVP_CIPHER *kekcipher = NULL;
-    EVP_CIPHER_CTX *kekctx;
-    const char *name;
-
-    if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
-        return 0;
-
-    if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(alg->algorithm))) {
-        ECerr(EC_F_ECDH_CMS_SET_SHARED_INFO, EC_R_KDF_PARAMETER_ERROR);
-        return 0;
-    }
-
-    if (alg->parameter->type != V_ASN1_SEQUENCE)
-        return 0;
-
-    p = alg->parameter->value.sequence->data;
-    plen = alg->parameter->value.sequence->length;
-    kekalg = d2i_X509_ALGOR(NULL, &p, plen);
-    if (kekalg == NULL)
-        goto err;
-    kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
-    if (kekctx == NULL)
-        goto err;
-    name = OBJ_nid2sn(OBJ_obj2nid(kekalg->algorithm));
-    kekcipher = EVP_CIPHER_fetch(pctx->libctx, name, pctx->propquery);
-    if (kekcipher == NULL || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
-        goto err;
-    if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
-        goto err;
-    if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0)
-        goto err;
-
-    keylen = EVP_CIPHER_CTX_key_length(kekctx);
-    if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
-        goto err;
-
-    plen = CMS_SharedInfo_encode(&der, kekalg, ukm, keylen);
-
-    if (plen <= 0)
-        goto err;
-
-    if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen) <= 0)
-        goto err;
-    der = NULL;
-
-    rv = 1;
- err:
-    EVP_CIPHER_free(kekcipher);
-    X509_ALGOR_free(kekalg);
-    OPENSSL_free(der);
-    return rv;
-}
-
-static int ecdh_cms_decrypt(CMS_RecipientInfo *ri)
-{
-    EVP_PKEY_CTX *pctx;
-
-    pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
-    if (pctx == NULL)
-        return 0;
-    /* See if we need to set peer key */
-    if (!EVP_PKEY_CTX_get0_peerkey(pctx)) {
-        X509_ALGOR *alg;
-        ASN1_BIT_STRING *pubkey;
-
-        if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey,
-                                                 NULL, NULL, NULL))
-            return 0;
-        if (!alg || !pubkey)
-            return 0;
-        if (!ecdh_cms_set_peerkey(pctx, alg, pubkey)) {
-            ECerr(EC_F_ECDH_CMS_DECRYPT, EC_R_PEER_KEY_ERROR);
-            return 0;
-        }
-    }
-    /* Set ECDH derivation parameters and initialise unwrap context */
-    if (!ecdh_cms_set_shared_info(pctx, ri)) {
-        ECerr(EC_F_ECDH_CMS_DECRYPT, EC_R_SHARED_INFO_ERROR);
-        return 0;
-    }
-    return 1;
-}
-
-static int ecdh_cms_encrypt(CMS_RecipientInfo *ri)
-{
-    EVP_PKEY_CTX *pctx;
-    EVP_PKEY *pkey;
-    EVP_CIPHER_CTX *ctx;
-    int keylen;
-    X509_ALGOR *talg, *wrap_alg = NULL;
-    const ASN1_OBJECT *aoid;
-    ASN1_BIT_STRING *pubkey;
-    ASN1_STRING *wrap_str;
-    ASN1_OCTET_STRING *ukm;
-    unsigned char *penc = NULL;
-    int penclen;
-    int rv = 0;
-    int ecdh_nid, kdf_type, kdf_nid, wrap_nid;
-    const EVP_MD *kdf_md;
-
-    pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
-    if (pctx == NULL)
-        return 0;
-    /* Get ephemeral key */
-    pkey = EVP_PKEY_CTX_get0_pkey(pctx);
-    if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
-                                             NULL, NULL, NULL))
-        goto err;
-    X509_ALGOR_get0(&aoid, NULL, NULL, talg);
-    /* Is everything uninitialised? */
-    if (aoid == OBJ_nid2obj(NID_undef)) {
-
-        EC_KEY *eckey = pkey->pkey.ec;
-        /* Set the key */
-        unsigned char *p;
-
-        penclen = i2o_ECPublicKey(eckey, NULL);
-        if (penclen <= 0)
-            goto err;
-        penc = OPENSSL_malloc(penclen);
-        if (penc == NULL)
-            goto err;
-        p = penc;
-        penclen = i2o_ECPublicKey(eckey, &p);
-        if (penclen <= 0)
-            goto err;
-        ASN1_STRING_set0(pubkey, penc, penclen);
-        pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
-        pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
-
-        penc = NULL;
-        X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
-                        V_ASN1_UNDEF, NULL);
-    }
-
-    /* See if custom parameters set */
-    kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx);
-    if (kdf_type <= 0)
-        goto err;
-    if (!EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md))
-        goto err;
-    ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx);
-    if (ecdh_nid < 0)
-        goto err;
-    else if (ecdh_nid == 0)
-        ecdh_nid = NID_dh_std_kdf;
-    else if (ecdh_nid == 1)
-        ecdh_nid = NID_dh_cofactor_kdf;
-
-    if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) {
-        kdf_type = EVP_PKEY_ECDH_KDF_X9_63;
-        if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0)
-            goto err;
-    } else
-        /* Unknown KDF */
-        goto err;
-    if (kdf_md == NULL) {
-        /* Fixme later for better MD */
-        kdf_md = EVP_sha1();
-        if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
-            goto err;
-    }
-
-    if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
-        goto err;
-
-    /* Lookup NID for KDF+cofactor+digest */
-
-    if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_type(kdf_md), ecdh_nid))
-        goto err;
-    /* Get wrap NID */
-    ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
-    wrap_nid = EVP_CIPHER_CTX_type(ctx);
-    keylen = EVP_CIPHER_CTX_key_length(ctx);
-
-    /* Package wrap algorithm in an AlgorithmIdentifier */
-
-    wrap_alg = X509_ALGOR_new();
-    if (wrap_alg == NULL)
-        goto err;
-    wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
-    wrap_alg->parameter = ASN1_TYPE_new();
-    if (wrap_alg->parameter == NULL)
-        goto err;
-    if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
-        goto err;
-    if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) {
-        ASN1_TYPE_free(wrap_alg->parameter);
-        wrap_alg->parameter = NULL;
-    }
-
-    if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
-        goto err;
-
-    penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen);
-
-    if (!penclen)
-        goto err;
-
-    if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0)
-        goto err;
-    penc = NULL;
-
-    /*
-     * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter
-     * of another AlgorithmIdentifier.
-     */
-    penclen = i2d_X509_ALGOR(wrap_alg, &penc);
-    if (!penc || !penclen)
-        goto err;
-    wrap_str = ASN1_STRING_new();
-    if (wrap_str == NULL)
-        goto err;
-    ASN1_STRING_set0(wrap_str, penc, penclen);
-    penc = NULL;
-    X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str);
-
-    rv = 1;
-
- err:
-    OPENSSL_free(penc);
-    X509_ALGOR_free(wrap_alg);
-    return rv;
-}
-
-#endif
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 2aca84f838..7bb83593a6 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -1996,6 +1996,7 @@ ASN1_R_TYPE_NOT_CONSTRUCTED:156:type not constructed
 ASN1_R_TYPE_NOT_PRIMITIVE:195:type not primitive
 ASN1_R_UNEXPECTED_EOC:159:unexpected eoc
 ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH:215:universalstring is wrong length
+ASN1_R_UNKNOWN_DIGEST:229:unknown digest
 ASN1_R_UNKNOWN_FORMAT:160:unknown format
 ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM:161:unknown message digest algorithm
 ASN1_R_UNKNOWN_OBJECT_TYPE:162:unknown object type
@@ -2181,6 +2182,7 @@ CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA:108:content type not signed data
 CMS_R_CONTENT_VERIFY_ERROR:109:content verify error
 CMS_R_CTRL_ERROR:110:ctrl error
 CMS_R_CTRL_FAILURE:111:ctrl failure
+CMS_R_DECODE_ERROR:187:decode error
 CMS_R_DECRYPT_ERROR:112:decrypt error
 CMS_R_ERROR_GETTING_PUBLIC_KEY:113:error getting public key
 CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE:114:\
@@ -2192,6 +2194,9 @@ CMS_R_ESS_SIGNING_CERTID_MISMATCH_ERROR:183:ess signing certid mismatch error
 CMS_R_INVALID_ENCRYPTED_KEY_LENGTH:117:invalid encrypted key length
 CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER:176:invalid key encryption parameter
 CMS_R_INVALID_KEY_LENGTH:118:invalid key length
+CMS_R_INVALID_LABEL:190:invalid label
+CMS_R_INVALID_OAEP_PARAMETERS:191:invalid oaep parameters
+CMS_R_KDF_PARAMETER_ERROR:186:kdf parameter error
 CMS_R_MD_BIO_INIT_ERROR:119:md bio init error
 CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH:120:\
 	messagedigest attribute wrong length
@@ -2223,10 +2228,12 @@ CMS_R_NO_PRIVATE_KEY:133:no private key
 CMS_R_NO_PUBLIC_KEY:134:no public key
 CMS_R_NO_RECEIPT_REQUEST:168:no receipt request
 CMS_R_NO_SIGNERS:135:no signers
+CMS_R_PEER_KEY_ERROR:188:peer key error
 CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:136:\
 	private key does not match certificate
 CMS_R_RECEIPT_DECODE_ERROR:169:receipt decode error
 CMS_R_RECIPIENT_ERROR:137:recipient error
+CMS_R_SHARED_INFO_ERROR:189:shared info error
 CMS_R_SIGNER_CERTIFICATE_NOT_FOUND:138:signer certificate not found
 CMS_R_SIGNFINAL_ERROR:139:signfinal error
 CMS_R_SMIME_TEXT_ERROR:140:smime text error
@@ -2242,9 +2249,11 @@ CMS_R_UNKNOWN_DIGEST_ALGORITHM:149:unknown digest algorithm
 CMS_R_UNKNOWN_ID:150:unknown id
 CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM:151:unsupported compression algorithm
 CMS_R_UNSUPPORTED_CONTENT_TYPE:152:unsupported content type
+CMS_R_UNSUPPORTED_ENCRYPTION_TYPE:192:unsupported encryption type
 CMS_R_UNSUPPORTED_KEK_ALGORITHM:153:unsupported kek algorithm
 CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM:179:\
 	unsupported key encryption algorithm
+CMS_R_UNSUPPORTED_LABEL_SOURCE:193:unsupported label source
 CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE:155:unsupported recipientinfo type
 CMS_R_UNSUPPORTED_RECIPIENT_TYPE:154:unsupported recipient type
 CMS_R_UNSUPPORTED_TYPE:156:unsupported type
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index fc06a101c8..042035a75a 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -1762,6 +1762,16 @@ int evp_pkey_ctx_use_cached_data(EVP_PKEY_CTX *ctx)
     return ret;
 }
 
+OPENSSL_CTX *EVP_PKEY_CTX_get0_libctx(EVP_PKEY_CTX *ctx)
+{
+    return ctx->libctx;
+}
+
+const char *EVP_PKEY_CTX_get0_propq(EVP_PKEY_CTX *ctx)
+{
+    return ctx->propquery;
+}
+
 /* Utility functions to send a string of hex string to a ctrl */
 
 int EVP_PKEY_CTX_str2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *str)
diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c
index 6105b7849a..c693ca7e21 100644
--- a/crypto/rsa/rsa_ameth.c
+++ b/crypto/rsa/rsa_ameth.c
@@ -18,7 +18,6 @@
 #include <openssl/asn1t.h>
 #include <openssl/x509.h>
 #include <openssl/bn.h>
-#include <openssl/cms.h>
 #include <openssl/core_names.h>
 #include <openssl/param_build.h>
 #include "crypto/asn1.h"
@@ -26,13 +25,6 @@
 #include "crypto/rsa.h"
 #include "rsa_local.h"
 
-#ifndef OPENSSL_NO_CMS
-static int rsa_cms_sign(CMS_SignerInfo *si);
-static int rsa_cms_verify(CMS_SignerInfo *si);
-static int rsa_cms_decrypt(CMS_RecipientInfo *ri);
-static int rsa_cms_encrypt(CMS_RecipientInfo *ri);
-#endif
-
 static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg);
 static int rsa_sync_to_pss_params_30(RSA *rsa);
 
@@ -256,14 +248,6 @@ static void int_rsa_free(EVP_PKEY *pkey)
     RSA_free(pkey->pkey.rsa);
 }
 
-static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg)
-{
-    if (OBJ_obj2nid(alg->algorithm) != NID_mgf1)
-        return NULL;
-    return ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(X509_ALGOR),
-                                     alg->parameter);
-}
-
 static int rsa_pss_param_print(BIO *bp, int pss_key, RSA_PSS_PARAMS *pss,
                                int indent)
 {
@@ -315,7 +299,7 @@ static int rsa_pss_param_print(BIO *bp, int pss_key, RSA_PSS_PARAMS *pss,
             goto err;
         if (BIO_puts(bp, " with ") <= 0)
             goto err;
-        maskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
+        maskHash = x509_algor_mgf1_decode(pss->maskGenAlgorithm);
         if (maskHash != NULL) {
             if (i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0)
                 goto err;
@@ -471,7 +455,7 @@ static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg)
         return NULL;
 
     if (pss->maskGenAlgorithm != NULL) {
-        pss->maskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
+        pss->maskHash = x509_algor_mgf1_decode(pss->maskGenAlgorithm);
         if (pss->maskHash == NULL) {
             RSA_PSS_PARAMS_free(pss);
             return NULL;
@@ -520,29 +504,6 @@ static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
         if (arg1 == 0)
             PKCS7_RECIP_INFO_get0_alg(arg2, &alg);
         break;
-#ifndef OPENSSL_NO_CMS
-    case ASN1_PKEY_CTRL_CMS_SIGN:
-        if (arg1 == 0)
-            return rsa_cms_sign(arg2);
-        else if (arg1 == 1)
-            return rsa_cms_verify(arg2);
-        break;
-
-    case ASN1_PKEY_CTRL_CMS_ENVELOPE:
-        if (pkey_is_pss(pkey))
-            return -2;
-        if (arg1 == 0)
-            return rsa_cms_encrypt(arg2);
-        else if (arg1 == 1)
-            return rsa_cms_decrypt(arg2);
-        break;
-
-    case ASN1_PKEY_CTRL_CMS_RI_TYPE:
-        if (pkey_is_pss(pkey))
-            return -2;
-        *(int *)arg2 = CMS_RECIPINFO_TRANS;
-        return 1;
-#endif
 
     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
         if (pkey->pkey.rsa->pss != NULL) {
@@ -570,58 +531,6 @@ static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
 
 }
 
-/* allocate and set algorithm ID from EVP_MD, default SHA1 */
-static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md)
-{
-    if (md == NULL || EVP_MD_type(md) == NID_sha1)
-        return 1;
-    *palg = X509_ALGOR_new();
-    if (*palg == NULL)
-        return 0;
-    X509_ALGOR_set_md(*palg, md);
-    return 1;
-}
-
-/* Allocate and set MGF1 algorithm ID from EVP_MD */
-static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md)
-{
-    X509_ALGOR *algtmp = NULL;
-    ASN1_STRING *stmp = NULL;
-
-    *palg = NULL;
-    if (mgf1md == NULL || EVP_MD_type(mgf1md) == NID_sha1)
-        return 1;
-    /* need to embed algorithm ID inside another */
-    if (!rsa_md_to_algor(&algtmp, mgf1md))
-        goto err;
-    if (ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp) == NULL)
-         goto err;
-    *palg = X509_ALGOR_new();
-    if (*palg == NULL)
-        goto err;
-    X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp);
-    stmp = NULL;
- err:
-    ASN1_STRING_free(stmp);
-    X509_ALGOR_free(algtmp);
-    if (*palg)
-        return 1;
-    return 0;
-}
-
-/* convert algorithm ID to EVP_MD, default SHA1 */
-static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg)
-{
-    const EVP_MD *md;
-
-    if (!alg)
-        return EVP_sha1();
-    md = EVP_get_digestbyobj(alg->algorithm);
-    if (md == NULL)
-        RSAerr(RSA_F_RSA_ALGOR_TO_MD, RSA_R_UNKNOWN_DIGEST);
-    return md;
-}
-
 /*
  * Convert EVP_PKEY_CTX in PSS mode into corresponding algorithm parameter,
  * suitable for setting an AlgorithmIdentifier.
@@ -631,7 +540,6 @@ static RSA_PSS_PARAMS *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx)
 {
     const EVP_MD *sigmd, *mgf1md;
     EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx);
-    RSA *rsa = EVP_PKEY_get0_RSA(pk);
     int saltlen;
 
     if (EVP_PKEY_CTX_get_signature_md(pkctx, &sigmd) <= 0)
@@ -643,7 +551,7 @@ static RSA_PSS_PARAMS *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx)
     if (saltlen == -1) {
         saltlen = EVP_MD_size(sigmd);
     } else if (saltlen == -2 || saltlen == -3) {
-        saltlen = RSA_size(rsa) - EVP_MD_size(sigmd) - 2;
+        saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2;
         if ((EVP_PKEY_bits(pk) & 0x7) == 1)
             saltlen--;
         if (saltlen < 0)
@@ -667,13 +575,13 @@ RSA_PSS_PARAMS *rsa_pss_params_create(const EVP_MD *sigmd,
         if (!ASN1_INTEGER_set(pss->saltLength, saltlen))
             goto err;
     }
-    if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd))
+    if (!x509_algor_new_from_md(&pss->hashAlgorithm, sigmd))
         goto err;
     if (mgf1md == NULL)
         mgf1md = sigmd;
-    if (!rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md))
+    if (!x509_algor_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md))
         goto err;
-    if (!rsa_md_to_algor(&pss->maskHash, mgf1md))
+    if (!x509_algor_new_from_md(&pss->maskHash, mgf1md))
         goto err;
     return pss;
  err:
@@ -681,7 +589,7 @@ RSA_PSS_PARAMS *rsa_pss_params_create(const EVP_MD *sigmd,
     return NULL;
 }
 
-static ASN1_STRING *rsa_ctx_to_pss_string(EVP_PKEY_CTX *pkctx)
+ASN1_STRING *ossl_rsa_ctx_to_pss_string(EVP_PKEY_CTX *pkctx)
 {
     RSA_PSS_PARAMS *pss = rsa_ctx_to_pss(pkctx);
     ASN1_STRING *os;
@@ -700,8 +608,8 @@ static ASN1_STRING *rsa_ctx_to_pss_string(EVP_PKEY_CTX *pkctx)
  * passed to pkctx instead.
  */
 
-static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx,
-                          const X509_ALGOR *sigalg, EVP_PKEY *pkey)
+int ossl_rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx,
+                        const X509_ALGOR *sigalg, EVP_PKEY *pkey)
 {
     int rv = -1;
     int saltlen;
@@ -710,14 +618,14 @@ static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx,
 
     /* Sanity check: make sure it is PSS */
     if (OBJ_obj2nid(sigalg->algorithm) != EVP_PKEY_RSA_PSS) {
-        RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_UNSUPPORTED_SIGNATURE_TYPE);
+        RSAerr(0, RSA_R_UNSUPPORTED_SIGNATURE_TYPE);
         return -1;
     }
     /* Decode PSS parameters */
     pss = rsa_pss_decode(sigalg);
 
     if (!rsa_pss_get_param(pss, &md, &mgf1md, &saltlen)) {
-        RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_PSS_PARAMETERS);
+        RSAerr(0, RSA_R_INVALID_PSS_PARAMETERS);
         goto err;
     }
 
@@ -730,7 +638,7 @@ static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx,
         if (EVP_PKEY_CTX_get_signature_md(pkctx, &checkmd) <= 0)
             goto err;
         if (EVP_MD_type(md) != EVP_MD_type(checkmd)) {
-            RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_DIGEST_DOES_NOT_MATCH);
+            RSAerr(0, RSA_R_DIGEST_DOES_NOT_MATCH);
             goto err;
         }
     }
@@ -781,10 +689,10 @@ static int rsa_pss_get_param_unverified(const RSA_PSS_PARAMS *pss,
 
     if (pss == NULL)
         return 0;
-    *pmd = rsa_algor_to_md(pss->hashAlgorithm);
+    *pmd = x509_algor_get_md(pss->hashAlgorithm);
     if (*pmd == NULL)
         return 0;
-    *pmgf1md = rsa_algor_to_md(pss->maskHash);
+    *pmgf1md = x509_algor_get_md(pss->maskHash);
     if (*pmgf1md == NULL)
         return 0;
     if (pss->saltLength)
@@ -851,33 +759,6 @@ static int rsa_sync_to_pss_params_30(RSA *rsa)
     return 1;
 }
 
-#ifndef OPENSSL_NO_CMS
-static int rsa_cms_verify(CMS_SignerInfo *si)
-{
-    int nid, nid2;
-    X509_ALGOR *alg;
-    EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si);
-
-    CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg);
-    nid = OBJ_obj2nid(alg->algorithm);
-    if (nid == EVP_PKEY_RSA_PSS)
-        return rsa_pss_to_ctx(NULL, pkctx, alg, NULL);
-    /* Only PSS allowed for PSS keys */
-    if (pkey_ctx_is_pss(pkctx)) {
-        RSAerr(RSA_F_RSA_CMS_VERIFY, RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
-        return 0;
-    }
-    if (nid == NID_rsaEncryption)
-        return 1;
-    /* Workaround for some implementation that use a signature OID */
-    if (OBJ_find_sigid_algs(nid, NULL, &nid2)) {
-        if (nid2 == NID_rsaEncryption)
-            return 1;
-    }
-    return 0;
-}
-#endif
-
 /*
  * Customised RSA item verification routine. This is called when a signature
  * is encountered requiring special handling. We currently only handle PSS.
@@ -892,41 +773,13 @@ static int rsa_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
         RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_SIGNATURE_TYPE);
         return -1;
     }
-    if (rsa_pss_to_ctx(ctx, NULL, sigalg, pkey) > 0) {
+    if (ossl_rsa_pss_to_ctx(ctx, NULL, sigalg, pkey) > 0) {
         /* Carry on */
         return 2;
     }
     return -1;
 }
 
-#ifndef OPENSSL_NO_CMS
-static int rsa_cms_sign(CMS_SignerInfo *si)
-{
-    int pad_mode = RSA_PKCS1_PADDING;
-    X509_ALGOR *alg;
-    EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si);
-    ASN1_STRING *os = NULL;
-
-    CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg);
-    if (pkctx) {
-        if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
-            return 0;
-    }
-    if (pad_mode == RSA_PKCS1_PADDING) {
-        X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
-        return 1;
-    }
-    /* We don't support it */
-    if (pad_mode != RSA_PKCS1_PSS_PADDING)
-        return 0;
-    os = rsa_ctx_to_pss_string(pkctx);
-    if (!os)
-        return 0;
-    X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_PKEY_RSA_PSS), V_ASN1_SEQUENCE, os);
-    return 1;
-}
-#endif
-
 static int rsa_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, const void *asn,
                          X509_ALGOR *alg1, X509_ALGOR *alg2,
                          ASN1_BIT_STRING *sig)
@@ -940,7 +793,7 @@ static int rsa_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, const void *asn,
         return 2;
     if (pad_mode == RSA_PKCS1_PSS_PADDING) {
         ASN1_STRING *os1 = NULL;
-        os1 = rsa_ctx_to_pss_string(pkctx);
+        os1 = ossl_rsa_ctx_to_pss_string(pkctx);
         if (!os1)
             return 0;
         /* Duplicate parameters if we have to */
@@ -1013,165 +866,6 @@ static int rsa_sig_info_set(X509_SIG_INFO *siginf, const X509_ALGOR *sigalg,
     return rv;
 }
 
-#ifndef OPENSSL_NO_CMS
-static RSA_OAEP_PARAMS *rsa_oaep_decode(const X509_ALGOR *alg)
-{
-    RSA_OAEP_PARAMS *oaep;
-
-    oaep = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_OAEP_PARAMS),
-                                     alg->parameter);
-
-    if (oaep == NULL)
-        return NULL;
-
-    if (oaep->maskGenFunc != NULL) {
-        oaep->maskHash = rsa_mgf1_decode(oaep->maskGenFunc);
-        if (oaep->maskHash == NULL) {
-            RSA_OAEP_PARAMS_free(oaep);
-            return NULL;
-        }
-    }
-    return oaep;
-}
-
-static int rsa_cms_decrypt(CMS_RecipientInfo *ri)
-{
-    EVP_PKEY_CTX *pkctx;
-    X509_ALGOR *cmsalg;
-    int nid;
-    int rv = -1;
-    unsigned char *label = NULL;
-    int labellen = 0;
-    const EVP_MD *mgf1md = NULL, *md = NULL;
-    RSA_OAEP_PARAMS *oaep;
-
-    pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
-    if (pkctx == NULL)
-        return 0;
-    if (!CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &cmsalg))
-        return -1;
-    nid = OBJ_obj2nid(cmsalg->algorithm);
-    if (nid == NID_rsaEncryption)
-        return 1;
-    if (nid != NID_rsaesOaep) {
-        RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_UNSUPPORTED_ENCRYPTION_TYPE);
-        return -1;
-    }
-    /* Decode OAEP parameters */
-    oaep = rsa_oaep_decode(cmsalg);
-
-    if (oaep == NULL) {
-        RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_INVALID_OAEP_PARAMETERS);
-        goto err;
-    }
-
-    mgf1md = rsa_algor_to_md(oaep->maskHash);
-    if (mgf1md == NULL)
-        goto err;
-    md = rsa_algor_to_md(oaep->hashFunc);
-    if (md == NULL)
-        goto err;
-
-    if (oaep->pSourceFunc != NULL) {
-        X509_ALGOR *plab = oaep->pSourceFunc;
-
-        if (OBJ_obj2nid(plab->algorithm) != NID_pSpecified) {
-            RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_UNSUPPORTED_LABEL_SOURCE);
-            goto err;
-        }
-        if (plab->parameter->type != V_ASN1_OCTET_STRING) {
-            RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_INVALID_LABEL);
-            goto err;
-        }
-
-        label = plab->parameter->value.octet_string->data;
-        /* Stop label being freed when OAEP parameters are freed */
-        plab->parameter->value.octet_string->data = NULL;
-        labellen = plab->parameter->value.octet_string->length;
-    }
-
-    if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0)
-        goto err;
-    if (EVP_PKEY_CTX_set_rsa_oaep_md(pkctx, md) <= 0)
-        goto err;
-    if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0)
-        goto err;
-    if (label != NULL
-            && EVP_PKEY_CTX_set0_rsa_oaep_label(pkctx, label, labellen) <= 0)
-        goto err;
-    /* Carry on */
-    rv = 1;
-
- err:
-    RSA_OAEP_PARAMS_free(oaep);
-    return rv;
-}
-
-static int rsa_cms_encrypt(CMS_RecipientInfo *ri)
-{
-    const EVP_MD *md, *mgf1md;
-    RSA_OAEP_PARAMS *oaep = NULL;
-    ASN1_STRING *os = NULL;
-    X509_ALGOR *alg;
-    EVP_PKEY_CTX *pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
-    int pad_mode = RSA_PKCS1_PADDING, rv = 0, labellen;
-    unsigned char *label;
-
-    if (CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &alg) <= 0)
-        return 0;
-    if (pkctx) {
-        if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
-            return 0;
-    }
-    if (pad_mode == RSA_PKCS1_PADDING) {
-        X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
-        return 1;
-    }
-    /* Not supported */
-    if (pad_mode != RSA_PKCS1_OAEP_PADDING)
-        return 0;
-    if (EVP_PKEY_CTX_get_rsa_oaep_md(pkctx, &md) <= 0)
-        goto err;
-    if (EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) <= 0)
-        goto err;
-    labellen = EVP_PKEY_CTX_get0_rsa_oaep_label(pkctx, &label);
-    if (labellen < 0)
-        goto err;
-    oaep = RSA_OAEP_PARAMS_new();
-    if (oaep == NULL)
-        goto err;
-    if (!rsa_md_to_algor(&oaep->hashFunc, md))
-        goto err;
-    if (!rsa_md_to_mgf1(&oaep->maskGenFunc, mgf1md))
-        goto err;
-    if (labellen > 0) {
-        ASN1_OCTET_STRING *los;
-        oaep->pSourceFunc = X509_ALGOR_new();
-        if (oaep->pSourceFunc == NULL)
-            goto err;
-        los = ASN1_OCTET_STRING_new();
-        if (los == NULL)
-            goto err;
-        if (!ASN1_OCTET_STRING_set(los, label, labellen)) {
-            ASN1_OCTET_STRING_free(los);
-            goto err;
-        }
-        X509_ALGOR_set0(oaep->pSourceFunc, OBJ_nid2obj(NID_pSpecified),
-                        V_ASN1_OCTET_STRING, los);
-    }
-    /* create string with pss parameter encoding. */
-    if (!ASN1_item_pack(oaep, ASN1_ITEM_rptr(RSA_OAEP_PARAMS), &os))
-         goto err;
-    X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaesOaep), V_ASN1_SEQUENCE, os);
-    os = NULL;
-    rv = 1;
- err:
-    RSA_OAEP_PARAMS_free(oaep);
-    ASN1_STRING_free(os);
-    return rv;
-}
-#endif
-
 static int rsa_pkey_check(const EVP_PKEY *pkey)
 {
     return RSA_check_key_ex(pkey->pkey.rsa, NULL);
diff --git a/doc/man3/EVP_PKEY_CTX_get0_libctx.pod b/doc/man3/EVP_PKEY_CTX_get0_libctx.pod
new file mode 100644
index 0000000000..2536ae820e
--- /dev/null
+++ b/doc/man3/EVP_PKEY_CTX_get0_libctx.pod
@@ -0,0 +1,45 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_CTX_get0_libctx,
+EVP_PKEY_CTX_get0_propq
+- functions for getting OPENSSL_CTX and property query data from an EVP_PKEY_CTX
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ OPENSSL_CTX *EVP_PKEY_CTX_get0_libctx(EVP_PKEY_CTX *ctx);
+ const char *EVP_PKEY_CTX_get0_propq(EVP_PKEY_CTX *ctx);
+
+=head1 DESCRIPTION
+
+The EVP_PKEY_CTX_get0_libctx() and EVP_PKEY_CTX_get0_propq() functions obtain
+the OPENSSL_CTX and property query string values respectively that were
+associated with the EVP_PKEY_CTX when it was constructed.
+
+=head1 RETURN VALUES
+
+EVP_PKEY_CTX_get0_libctx() and EVP_PKEY_CTX_get0_propq() functions return the
+OPENSSL_CTX and property query string associated with the EVP_PKEY_CTX or NULL
+if they are not set. The returned values should not be freed by the caller.
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_CTX_new(3)>
+
+=head1 HISTORY
+
+All functions were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020 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/include/crypto/asn1.h b/include/crypto/asn1.h
index 5f6987e066..08018e4cf1 100644
--- a/include/crypto/asn1.h
+++ b/include/crypto/asn1.h
@@ -133,3 +133,8 @@ int asn1_type_set_octetstring_int(ASN1_TYPE *a, long num,
                                   unsigned char *data, int len);
 int asn1_type_get_octetstring_int(const ASN1_TYPE *a, long *num,
                                   unsigned char *data, int max_len);
+
+int x509_algor_new_from_md(X509_ALGOR **palg, const EVP_MD *md);
+const EVP_MD *x509_algor_get_md(X509_ALGOR *alg);
+X509_ALGOR *x509_algor_mgf1_decode(X509_ALGOR *alg);
+int x509_algor_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md);
diff --git a/include/crypto/rsa.h b/include/crypto/rsa.h
index 85682aa55d..7ec745766f 100644
--- a/include/crypto/rsa.h
+++ b/include/crypto/rsa.h
@@ -93,6 +93,10 @@ extern const char *ossl_rsa_mp_factor_names[];
 extern const char *ossl_rsa_mp_exp_names[];
 extern const char *ossl_rsa_mp_coeff_names[];
 
+ASN1_STRING *ossl_rsa_ctx_to_pss_string(EVP_PKEY_CTX *pkctx);
+int ossl_rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx,
+                        const X509_ALGOR *sigalg, EVP_PKEY *pkey);
+
 # if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
 int rsa_acvp_test_gen_params_new(OSSL_PARAM **dst, const OSSL_PARAM src[]);
 void rsa_acvp_test_gen_params_free(OSSL_PARAM *dst);
diff --git a/include/openssl/asn1err.h b/include/openssl/asn1err.h
index b58339ba47..a29722e868 100644
--- a/include/openssl/asn1err.h
+++ b/include/openssl/asn1err.h
@@ -244,6 +244,7 @@ int ERR_load_ASN1_strings(void);
 # define ASN1_R_TYPE_NOT_PRIMITIVE                        195
 # define ASN1_R_UNEXPECTED_EOC                            159
 # define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH           215
+# define ASN1_R_UNKNOWN_DIGEST                            229
 # define ASN1_R_UNKNOWN_FORMAT                            160
 # define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM          161
 # define ASN1_R_UNKNOWN_OBJECT_TYPE                       162
diff --git a/include/openssl/cmserr.h b/include/openssl/cmserr.h
index 1e7daf044b..e234ad0126 100644
--- a/include/openssl/cmserr.h
+++ b/include/openssl/cmserr.h
@@ -146,6 +146,7 @@ int ERR_load_CMS_strings(void);
 #  define CMS_R_CONTENT_VERIFY_ERROR                       109
 #  define CMS_R_CTRL_ERROR                                 110
 #  define CMS_R_CTRL_FAILURE                               111
+#  define CMS_R_DECODE_ERROR                               187
 #  define CMS_R_DECRYPT_ERROR                              112
 #  define CMS_R_ERROR_GETTING_PUBLIC_KEY                   113
 #  define CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE      114
@@ -156,6 +157,9 @@ int ERR_load_CMS_strings(void);
 #  define CMS_R_INVALID_ENCRYPTED_KEY_LENGTH               117
 #  define CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER           176
 #  define CMS_R_INVALID_KEY_LENGTH                         118
+#  define CMS_R_INVALID_LABEL                              190
+#  define CMS_R_INVALID_OAEP_PARAMETERS                    191
+#  define CMS_R_KDF_PARAMETER_ERROR                        186
 #  define CMS_R_MD_BIO_INIT_ERROR                          119
 #  define CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH       120
 #  define CMS_R_MESSAGEDIGEST_WRONG_LENGTH                 121
@@ -186,9 +190,11 @@ int ERR_load_CMS_strings(void);
 #  define CMS_R_NO_PUBLIC_KEY                              134
 #  define CMS_R_NO_RECEIPT_REQUEST                         168
 #  define CMS_R_NO_SIGNERS                                 135
+#  define CMS_R_PEER_KEY_ERROR                             188
 #  define CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE     136
 #  define CMS_R_RECEIPT_DECODE_ERROR                       169
 #  define CMS_R_RECIPIENT_ERROR                            137
+#  define CMS_R_SHARED_INFO_ERROR                          189
 #  define CMS_R_SIGNER_CERTIFICATE_NOT_FOUND               138
 #  define CMS_R_SIGNFINAL_ERROR                            139
 #  define CMS_R_SMIME_TEXT_ERROR                           140
@@ -204,8 +210,10 @@ int ERR_load_CMS_strings(void);
 #  define CMS_R_UNKNOWN_ID                                 150
 #  define CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM          151
 #  define CMS_R_UNSUPPORTED_CONTENT_TYPE                   152
+#  define CMS_R_UNSUPPORTED_ENCRYPTION_TYPE                192
 #  define CMS_R_UNSUPPORTED_KEK_ALGORITHM                  153
 #  define CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM       179
+#  define CMS_R_UNSUPPORTED_LABEL_SOURCE                   193
 #  define CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE             155
 #  define CMS_R_UNSUPPORTED_RECIPIENT_TYPE                 154
 #  define CMS_R_UNSUPPORTED_TYPE                           156
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index 8c2d00813c..5527709be0 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -1966,6 +1966,9 @@ int EVP_hex2ctrl(int (*cb)(void *ctx, int cmd, void *buf, size_t buflen),
 int EVP_PKEY_CTX_set_group_name(EVP_PKEY_CTX *ctx, const char *name);
 int EVP_PKEY_CTX_get_group_name(EVP_PKEY_CTX *ctx, char *name, size_t namelen);
 
+OPENSSL_CTX *EVP_PKEY_CTX_get0_libctx(EVP_PKEY_CTX *ctx);
+const char *EVP_PKEY_CTX_get0_propq(EVP_PKEY_CTX *ctx);
+
 # ifdef  __cplusplus
 }
 # endif
diff --git a/util/libcrypto.num b/util/libcrypto.num
index fb0069c9e8..12ba103689 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -5288,3 +5288,5 @@ PKCS7_type_is_other                     ?	3_0_0	EXIST::FUNCTION:
 PKCS7_get_octet_string                  ?	3_0_0	EXIST::FUNCTION:
 OSSL_DECODER_from_data                  ?	3_0_0	EXIST::FUNCTION:
 OSSL_ENCODER_to_data                    ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_CTX_get0_libctx                ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_CTX_get0_propq                 ?	3_0_0	EXIST::FUNCTION:


More information about the openssl-commits mailing list