The branch master has been updated
       via  348900774c14dd79c9cf762d59554f38d8c77120 (commit)
       via  71434aed0de274abe8f10768c4dd11a5b3b387e4 (commit)
      from  88398d2a358fe41e33c61ac02f23ffaeacddcff0 (commit)


- Log -----------------------------------------------------------------
commit 348900774c14dd79c9cf762d59554f38d8c77120
Author: Dmitry Belyavskiy <beld...@gmail.com>
Date:   Tue Jan 21 15:04:42 2020 +0300

    Documenting newly added CMS modification
    
    Documented CMS-related API functions.
    Documented flags added to openssl-cms command
    
    Reviewed-by: Shane Lontis <shane.lon...@oracle.com>
    Reviewed-by: Paul Dale <paul.d...@oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/10904)

commit 71434aed0de274abe8f10768c4dd11a5b3b387e4
Author: Dmitry Belyavskiy <beld...@gmail.com>
Date:   Mon Jan 20 18:17:44 2020 +0300

    Implementation of Russian GOST CMS
    
    Reviewed-by: Shane Lontis <shane.lon...@oracle.com>
    Reviewed-by: Paul Dale <paul.d...@oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/10904)

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

Summary of changes:
 apps/cms.c                           |  49 ++++++++++---
 crypto/cms/cms_env.c                 | 137 ++++++++++++++++++++++++++++++-----
 crypto/cms/cms_kari.c                |  93 +++++++++++++++++++++---
 crypto/cms/cms_lib.c                 |   4 +-
 crypto/cms/cms_local.h               |   7 +-
 crypto/cms/cms_smime.c               |  40 ++++++----
 crypto/err/openssl.txt               |   4 +
 crypto/evp/pmeth_lib.c               |   7 ++
 doc/man1/openssl-cms.pod.in          |  13 ++++
 doc/man3/CMS_add1_recipient_cert.pod |  18 ++++-
 doc/man3/CMS_decrypt.pod             |  19 ++++-
 doc/man3/CMS_get0_RecipientInfos.pod |  20 ++++-
 include/openssl/cms.h                |   5 ++
 include/openssl/cmserr.h             |   6 +-
 include/openssl/evp.h                |   9 +++
 util/libcrypto.num                   |   3 +
 util/missingcrypto.txt               |   2 -
 17 files changed, 371 insertions(+), 65 deletions(-)

diff --git a/apps/cms.c b/apps/cms.c
index d67116d3fc..9c92e79658 100644
--- a/apps/cms.c
+++ b/apps/cms.c
@@ -81,10 +81,11 @@ typedef enum OPTION_choice {
     OPT_PASSIN, OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP,
     OPT_CERTSOUT, OPT_MD, OPT_INKEY, OPT_KEYFORM, OPT_KEYOPT, OPT_RR_FROM,
     OPT_RR_TO, OPT_AES128_WRAP, OPT_AES192_WRAP, OPT_AES256_WRAP,
-    OPT_3DES_WRAP, OPT_ENGINE,
+    OPT_3DES_WRAP, OPT_WRAP, OPT_ENGINE,
     OPT_R_ENUM,
     OPT_V_ENUM,
-    OPT_CIPHER
+    OPT_CIPHER,
+    OPT_ORIGINATOR
 } OPTION_CHOICE;
 
 const OPTIONS cms_options[] = {
@@ -197,6 +198,7 @@ const OPTIONS cms_options[] = {
     {"from", OPT_FROM, 's', "From address"},
     {"subject", OPT_SUBJECT, 's', "Subject"},
     {"signer", OPT_SIGNER, 's', "Signer certificate file"},
+    {"originator", OPT_ORIGINATOR, 's', "Originator certificate file"},
     {"recip", OPT_RECIP, '<', "Recipient cert file for decryption"},
     {"receipt_request_from", OPT_RR_FROM, 's',
         "Create signed receipt request with specified email address"},
@@ -214,6 +216,7 @@ const OPTIONS cms_options[] = {
 # ifndef OPENSSL_NO_DES
     {"des3-wrap", OPT_3DES_WRAP, '-', "Use 3DES-EDE to wrap key"},
 # endif
+    {"wrap", OPT_WRAP, 's', "Any wrap cipher to wrap key"},
 
     OPT_R_OPTIONS,
     OPT_V_OPTIONS,
@@ -236,7 +239,7 @@ int cms_main(int argc, char **argv)
     STACK_OF(OPENSSL_STRING) *rr_to = NULL, *rr_from = NULL;
     STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL;
     STACK_OF(X509) *encerts = NULL, *other = NULL;
-    X509 *cert = NULL, *recip = NULL, *signer = NULL;
+    X509 *cert = NULL, *recip = NULL, *signer = NULL, *originator = NULL;
     X509_STORE *store = NULL;
     X509_VERIFY_PARAM *vpm = NULL;
     char *certfile = NULL, *keyfile = NULL, *contfile = NULL;
@@ -244,7 +247,7 @@ int cms_main(int argc, char **argv)
     char *certsoutfile = NULL;
     int noCAfile = 0, noCApath = 0, noCAstore = 0;
     char *infile = NULL, *outfile = NULL, *rctfile = NULL;
-    char *passinarg = NULL, *passin = NULL, *signerfile = NULL, *recipfile = 
NULL;
+    char *passinarg = NULL, *passin = NULL, *signerfile = NULL, 
*originatorfile = NULL, *recipfile = NULL;
     char *to = NULL, *from = NULL, *subject = NULL, *prog;
     cms_key_param *key_first = NULL, *key_param = NULL;
     int flags = CMS_DETACHED, noout = 0, print = 0, keyidx = -1, vpmtouched = 
0;
@@ -535,6 +538,9 @@ int cms_main(int argc, char **argv)
             }
             signerfile = opt_arg();
             break;
+        case OPT_ORIGINATOR:
+             originatorfile = opt_arg();
+             break;
         case OPT_INKEY:
             /* If previous -inkey argument add signer to list */
             if (keyfile != NULL) {
@@ -629,6 +635,10 @@ int cms_main(int argc, char **argv)
         case OPT_AES256_WRAP:
             wrap_cipher = EVP_aes_256_wrap();
             break;
+        case OPT_WRAP:
+            if (!opt_cipher(opt_unknown(), &wrap_cipher))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
@@ -759,6 +769,14 @@ int cms_main(int argc, char **argv)
         }
     }
 
+    if (originatorfile != NULL) {
+        if ((originator = load_cert(originatorfile, FORMAT_PEM,
+                                    "originator certificate file")) == NULL) {
+             ERR_print_errors(bio_err);
+             goto end;
+        }
+    }
+
     if (operation == SMIME_SIGN_RECEIPT) {
         if ((signer = load_cert(signerfile, FORMAT_PEM,
                                 "receipt signer certificate file")) == NULL) {
@@ -767,7 +785,7 @@ int cms_main(int argc, char **argv)
         }
     }
 
-    if (operation == SMIME_DECRYPT) {
+    if ((operation == SMIME_DECRYPT) || (operation == SMIME_ENCRYPT)) {
         if (keyfile == NULL)
             keyfile = recipfile;
     } else if ((operation == SMIME_SIGN) || (operation == SMIME_SIGN_RECEIPT)) 
{
@@ -877,23 +895,32 @@ int cms_main(int argc, char **argv)
         for (i = 0; i < sk_X509_num(encerts); i++) {
             CMS_RecipientInfo *ri;
             cms_key_param *kparam;
-            int tflags = flags;
+            int tflags = flags | CMS_KEY_PARAM; /* This flag enforces 
allocating the EVP_PKEY_CTX for the recipient here */
+            EVP_PKEY_CTX *pctx;
             X509 *x = sk_X509_value(encerts, i);
+            int res;
+
             for (kparam = key_first; kparam; kparam = kparam->next) {
                 if (kparam->idx == i) {
-                    tflags |= CMS_KEY_PARAM;
                     break;
                 }
             }
-            ri = CMS_add1_recipient_cert(cms, x, tflags);
+            ri = CMS_add1_recipient(cms, x, key, originator, tflags);
             if (ri == NULL)
                 goto end;
+
+            pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
             if (kparam != NULL) {
-                EVP_PKEY_CTX *pctx;
-                pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
                 if (!cms_set_pkey_param(pctx, kparam->param))
                     goto end;
             }
+
+            res = EVP_PKEY_CTX_ctrl(pctx, -1, -1,
+                                    EVP_PKEY_CTRL_CIPHER,
+                                    EVP_CIPHER_nid(cipher), NULL);
+            if (res <= 0 && res != -2)
+                goto end;
+
             if (CMS_RecipientInfo_type(ri) == CMS_RECIPINFO_AGREE
                 && wrap_cipher) {
                 EVP_CIPHER_CTX *wctx;
@@ -1039,7 +1066,7 @@ int cms_main(int argc, char **argv)
         }
 
         if (key != NULL) {
-            if (!CMS_decrypt_set1_pkey(cms, key, recip)) {
+            if (!CMS_decrypt_set1_pkey_and_peer(cms, key, recip, originator)) {
                 BIO_puts(bio_err, "Error decrypting CMS using private key\n");
                 goto end;
             }
diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c
index ac34f3efd6..003a406c68 100644
--- a/crypto/cms/cms_env.c
+++ b/crypto/cms/cms_env.c
@@ -20,6 +20,8 @@
 
 /* CMS EnvelopedData Utilities */
 
+static void cms_env_set_version(CMS_EnvelopedData *env);
+
 CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms)
 {
     if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped) {
@@ -122,6 +124,47 @@ CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER 
*cipher)
     return NULL;
 }
 
+int cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain)
+{
+    CMS_EnvelopedData *env = NULL;
+    EVP_CIPHER_CTX *ctx = NULL;
+    BIO *mbio = BIO_find_type(chain, BIO_TYPE_CIPHER);
+
+    env = cms_get0_enveloped(cms);
+    if (env == NULL)
+        return 0;
+
+    if (mbio == NULL) {
+        CMSerr(CMS_F_CMS_ENVELOPEDDATA_FINAL, CMS_R_CONTENT_NOT_FOUND);
+        return 0;
+    }
+
+    BIO_get_cipher_ctx(mbio, &ctx);
+
+    /*
+     * If the selected cipher supports unprotected attributes,
+     * deal with it using special ctrl function
+     */
+    if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & 
EVP_CIPH_FLAG_CIPHER_WITH_MAC) {
+        if (cms->d.envelopedData->unprotectedAttrs == NULL)
+            cms->d.envelopedData->unprotectedAttrs = 
sk_X509_ATTRIBUTE_new_null();
+
+        if (cms->d.envelopedData->unprotectedAttrs == NULL) {
+            CMSerr(CMS_F_CMS_ENVELOPEDDATA_FINAL, ERR_R_MALLOC_FAILURE);
+            return 0;
+        }
+
+        if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_PROCESS_UNPROTECTED,
+                                1, env->unprotectedAttrs) <= 0) {
+            CMSerr(CMS_F_CMS_ENVELOPEDDATA_FINAL, CMS_R_CTRL_FAILURE);
+            return 0;
+        }
+    }
+
+    cms_env_set_version(cms->d.envelopedData);
+    return 1;
+}
+
 /* Key Transport Recipient Info (KTRI) routines */
 
 /* Initialise a ktri based on passed certificate and key */
@@ -176,8 +219,9 @@ static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo 
*ri, X509 *recip,
  * Add a recipient certificate using appropriate type of RecipientInfo
  */
 
-CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
-                                           X509 *recip, unsigned int flags)
+CMS_RecipientInfo *CMS_add1_recipient(CMS_ContentInfo *cms, X509 *recip,
+                                      EVP_PKEY *originatorPrivKey,
+                                      X509 *originator, unsigned int flags)
 {
     CMS_RecipientInfo *ri = NULL;
     CMS_EnvelopedData *env;
@@ -193,7 +237,7 @@ CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo 
*cms,
 
     pk = X509_get0_pubkey(recip);
     if (pk == NULL) {
-        CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, CMS_R_ERROR_GETTING_PUBLIC_KEY);
+        CMSerr(CMS_F_CMS_ADD1_RECIPIENT, CMS_R_ERROR_GETTING_PUBLIC_KEY);
         goto err;
     }
 
@@ -205,12 +249,12 @@ CMS_RecipientInfo 
*CMS_add1_recipient_cert(CMS_ContentInfo *cms,
         break;
 
     case CMS_RECIPINFO_AGREE:
-        if (!cms_RecipientInfo_kari_init(ri, recip, pk, flags))
+        if (!cms_RecipientInfo_kari_init(ri, recip, pk, originator, 
originatorPrivKey, flags))
             goto err;
         break;
 
     default:
-        CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,
+        CMSerr(CMS_F_CMS_ADD1_RECIPIENT,
                CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
         goto err;
 
@@ -222,13 +266,19 @@ CMS_RecipientInfo 
*CMS_add1_recipient_cert(CMS_ContentInfo *cms,
     return ri;
 
  merr:
-    CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ERR_R_MALLOC_FAILURE);
+    CMSerr(CMS_F_CMS_ADD1_RECIPIENT, ERR_R_MALLOC_FAILURE);
  err:
     M_ASN1_free_of(ri, CMS_RecipientInfo);
     return NULL;
 
 }
 
+CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
+     X509 *recip, unsigned int flags)
+{
+     return CMS_add1_recipient(cms, recip, NULL, NULL, flags);
+}
+
 int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri,
                                      EVP_PKEY **pk, X509 **recip,
                                      X509_ALGOR **palg)
@@ -894,7 +944,34 @@ static void cms_env_set_version(CMS_EnvelopedData *env)
     env->version = 0;
 }
 
-BIO *cms_EnvelopedData_init_bio(const CMS_ContentInfo *cms)
+static BIO *cms_EnvelopedData_Decryption_init_bio(CMS_ContentInfo *cms)
+{
+    CMS_EncryptedContentInfo *ec = cms->d.envelopedData->encryptedContentInfo;
+    BIO *contentBio = cms_EncryptedContent_init_bio(ec);
+    EVP_CIPHER_CTX *ctx = NULL;
+
+    if (contentBio == NULL)
+        return NULL;
+
+    BIO_get_cipher_ctx(contentBio, &ctx);
+    if (ctx == NULL) {
+        BIO_free(contentBio);
+        return NULL;
+    }
+/*
+ * If the selected cipher supports unprotected attributes,
+ * deal with it using special ctrl function
+ */
+    if ((EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & 
EVP_CIPH_FLAG_CIPHER_WITH_MAC)
+         && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_PROCESS_UNPROTECTED, 0,
+                                cms->d.envelopedData->unprotectedAttrs) <= 0) {
+        BIO_free(contentBio);
+        return NULL;
+    }
+    return contentBio;
+}
+
+static BIO *cms_EnvelopedData_Encryption_init_bio(CMS_ContentInfo *cms)
 {
     CMS_EncryptedContentInfo *ec;
     STACK_OF(CMS_RecipientInfo) *rinfos;
@@ -907,22 +984,19 @@ BIO *cms_EnvelopedData_init_bio(const CMS_ContentInfo 
*cms)
     ec = cms->d.envelopedData->encryptedContentInfo;
     ret = cms_EncryptedContent_init_bio(ec);
 
-    /* If error or no cipher end of processing */
-
-    if (!ret || !ec->cipher)
+    /* If error end of processing */
+    if (!ret)
         return ret;
 
     /* Now encrypt content key according to each RecipientInfo type */
-
     rinfos = cms->d.envelopedData->recipientInfos;
 
     for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++) {
-        ri = sk_CMS_RecipientInfo_value(rinfos, i);
-        if (CMS_RecipientInfo_encrypt(cms, ri) <= 0) {
-            CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO,
-                   CMS_R_ERROR_SETTING_RECIPIENTINFO);
-            goto err;
-        }
+         ri = sk_CMS_RecipientInfo_value(rinfos, i);
+         if (CMS_RecipientInfo_encrypt(cms, ri) <= 0) {
+             CMSerr(0, CMS_R_ERROR_SETTING_RECIPIENTINFO);
+             goto err;
+         }
     }
     cms_env_set_version(cms->d.envelopedData);
 
@@ -937,7 +1011,17 @@ BIO *cms_EnvelopedData_init_bio(const CMS_ContentInfo 
*cms)
         return ret;
     BIO_free(ret);
     return NULL;
+}
+
+BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms)
+{
+    if (cms->d.envelopedData->encryptedContentInfo->cipher != NULL) {
+         /* If cipher is set it's encryption */
+         return cms_EnvelopedData_Encryption_init_bio(cms);
+    }
 
+    /* If cipher is not set it's decryption */
+    return cms_EnvelopedData_Decryption_init_bio(cms);
 }
 
 /*
@@ -955,3 +1039,22 @@ int cms_pkey_get_ri_type(EVP_PKEY *pk)
     }
     return CMS_RECIPINFO_TRANS;
 }
+
+int cms_pkey_is_ri_type_supported(EVP_PKEY *pk, int ri_type)
+{
+    int supportedRiType;
+
+    if (pk->ameth != NULL && pk->ameth->pkey_ctrl != NULL) {
+        int i, r;
+
+        i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_IS_RI_TYPE_SUPPORTED, 
ri_type, &r);
+        if (i > 0)
+            return r;
+    }
+
+    supportedRiType = cms_pkey_get_ri_type(pk);
+    if (supportedRiType < 0)
+        return 0;
+
+    return (supportedRiType == ri_type);
+}
diff --git a/crypto/cms/cms_kari.c b/crypto/cms/cms_kari.c
index 6b0a59ebde..3299e9b5f5 100644
--- a/crypto/cms/cms_kari.c
+++ b/crypto/cms/cms_kari.c
@@ -152,7 +152,7 @@ int 
CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek,
         return -1;
 }
 
-int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk)
+int CMS_RecipientInfo_kari_set0_pkey_and_peer(CMS_RecipientInfo *ri, EVP_PKEY 
*pk, X509 *peer)
 {
     EVP_PKEY_CTX *pctx;
     CMS_KeyAgreeRecipientInfo *kari = ri->d.kari;
@@ -161,9 +161,18 @@ int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo 
*ri, EVP_PKEY *pk)
     kari->pctx = NULL;
     if (pk == NULL)
         return 1;
+
     pctx = EVP_PKEY_CTX_new(pk, NULL);
     if (pctx == NULL || EVP_PKEY_derive_init(pctx) <= 0)
         goto err;
+
+    if (peer != NULL) {
+        EVP_PKEY *pub_pkey = X509_get0_pubkey(peer);
+
+        if (EVP_PKEY_derive_set_peer(pctx, pub_pkey) <= 0)
+            goto err;
+    }
+
     kari->pctx = pctx;
     return 1;
  err:
@@ -171,6 +180,11 @@ int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo 
*ri, EVP_PKEY *pk)
     return 0;
 }
 
+int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk)
+{
+    return CMS_RecipientInfo_kari_set0_pkey_and_peer(ri, pk, NULL);
+}
+
 EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri)
 {
     if (ri->type == CMS_RECIPINFO_AGREE)
@@ -283,10 +297,29 @@ static int 
cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari,
     return rv;
 }
 
+/* Set originator private key and initialise context based on it */
+static int cms_kari_set_originator_private_key(CMS_KeyAgreeRecipientInfo 
*kari, EVP_PKEY *originatorPrivKey )
+{
+    EVP_PKEY_CTX *pctx = NULL;
+    int rv = 0;
+
+    pctx = EVP_PKEY_CTX_new(originatorPrivKey, NULL);
+    if (pctx == NULL)
+        goto err;
+    if (EVP_PKEY_derive_init(pctx) <= 0)
+         goto err;
+
+    kari->pctx = pctx;
+    rv = 1;
+ err:
+    if (rv == 0)
+        EVP_PKEY_CTX_free(pctx);
+    return rv;
+}
+
 /* Initialise a kari based on passed certificate and key */
 
-int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip,
-                                EVP_PKEY *pk, unsigned int flags)
+int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri,  X509 *recip, EVP_PKEY 
*recipPubKey, X509 * originator, EVP_PKEY *originatorPrivKey, unsigned int 
flags)
 {
     CMS_KeyAgreeRecipientInfo *kari;
     CMS_RecipientEncryptedKey *rek = NULL;
@@ -321,12 +354,36 @@ int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, 
X509 *recip,
             return 0;
     }
 
-    /* Create ephemeral key */
-    if (!cms_kari_create_ephemeral_key(kari, pk))
-        return 0;
+    if (originatorPrivKey == NULL && originator == NULL) {
+        /* Create ephemeral key */
+        if (!cms_kari_create_ephemeral_key(kari, recipPubKey))
+            return 0;
+    } else {
+         /* Use originator key */
+         CMS_OriginatorIdentifierOrKey *oik = ri->d.kari->originator;
+
+         if (originatorPrivKey == NULL && originator == NULL)
+            return 0;
+
+         if (flags & CMS_USE_ORIGINATOR_KEYID) {
+              oik->type = CMS_OIK_KEYIDENTIFIER;
+              oik->d.subjectKeyIdentifier = ASN1_OCTET_STRING_new();
+              if (oik->d.subjectKeyIdentifier == NULL)
+                   return 0;
+              if (!cms_set1_keyid(&oik->d.subjectKeyIdentifier, originator))
+                   return 0;
+         } else {
+              oik->type = CMS_REK_ISSUER_SERIAL;
+              if (!cms_set1_ias(&oik->d.issuerAndSerialNumber, originator))
+                   return 0;
+         }
+
+         if (!cms_kari_set_originator_private_key(kari, originatorPrivKey))
+             return 0;
+    }
 
-    EVP_PKEY_up_ref(pk);
-    rek->pkey = pk;
+    EVP_PKEY_up_ref(recipPubKey);
+    rek->pkey = recipPubKey;
     return 1;
 }
 
@@ -336,14 +393,30 @@ static int cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari,
     EVP_CIPHER_CTX *ctx = kari->ctx;
     const EVP_CIPHER *kekcipher;
     int keylen = EVP_CIPHER_key_length(cipher);
+    int ret;
+
     /* If a suitable wrap algorithm is already set nothing to do */
     kekcipher = EVP_CIPHER_CTX_cipher(ctx);
-
-    if (kekcipher) {
+    if (kekcipher != NULL) {
         if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_WRAP_MODE)
             return 0;
         return 1;
     }
+    else if (cipher != NULL
+         && (EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_GET_WRAP_CIPHER)) {
+        ret = EVP_CIPHER_meth_get_ctrl(cipher)(NULL, EVP_CTRL_GET_WRAP_CIPHER,
+                                               0, &kekcipher);
+        if (ret <= 0)
+             return 0;
+
+        if (kekcipher != NULL) {
+             if (EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
+                 return 0;
+
+             return EVP_EncryptInit_ex(ctx, kekcipher, NULL, NULL, NULL);
+        }
+    }
+
     /*
      * Pick a cipher based on content encryption cipher. If it is DES3 use
      * DES3 wrap otherwise use AES wrap similar to key size.
diff --git a/crypto/cms/cms_lib.c b/crypto/cms/cms_lib.c
index 245544e3e9..15aba4af52 100644
--- a/crypto/cms/cms_lib.c
+++ b/crypto/cms/cms_lib.c
@@ -133,12 +133,14 @@ int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
     switch (OBJ_obj2nid(cms->contentType)) {
 
     case NID_pkcs7_data:
-    case NID_pkcs7_enveloped:
     case NID_pkcs7_encrypted:
     case NID_id_smime_ct_compressedData:
         /* Nothing to do */
         return 1;
 
+    case NID_pkcs7_enveloped:
+        return cms_EnvelopedData_final(cms, cmsbio);
+
     case NID_pkcs7_signed:
         return cms_SignedData_final(cms, cmsbio);
 
diff --git a/crypto/cms/cms_local.h b/crypto/cms/cms_local.h
index 6cb31955eb..46956a0947 100644
--- a/crypto/cms/cms_local.h
+++ b/crypto/cms/cms_local.h
@@ -402,13 +402,16 @@ int cms_Receipt_verify(CMS_ContentInfo *cms, 
CMS_ContentInfo *req_cms);
 int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src);
 ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si);
 
-BIO *cms_EnvelopedData_init_bio(const CMS_ContentInfo *cms);
+BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms);
+int cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain);
 CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms);
 int cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd);
 int cms_pkey_get_ri_type(EVP_PKEY *pk);
+int cms_pkey_is_ri_type_supported(EVP_PKEY *pk, int ri_type);
 /* KARI routines */
 int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip,
-                                EVP_PKEY *pk, unsigned int flags);
+                                EVP_PKEY *recipPubKey, X509 *originator,
+                                EVP_PKEY *originatorPrivKey, unsigned int 
flags);
 int cms_RecipientInfo_kari_encrypt(const CMS_ContentInfo *cms,
                                    CMS_RecipientInfo *ri);
 
diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c
index 4ae85c0335..d5112a83ea 100644
--- a/crypto/cms/cms_smime.c
+++ b/crypto/cms/cms_smime.c
@@ -576,19 +576,20 @@ CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO 
*data,
     return NULL;
 }
 
-static int cms_kari_set1_pkey(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
-                              EVP_PKEY *pk, X509 *cert)
+static int cms_kari_set1_pkey_and_peer(CMS_ContentInfo *cms, CMS_RecipientInfo 
*ri,
+                                       EVP_PKEY *pk, X509 *cert, X509 *peer)
 {
     int i;
     STACK_OF(CMS_RecipientEncryptedKey) *reks;
     CMS_RecipientEncryptedKey *rek;
+
     reks = CMS_RecipientInfo_kari_get0_reks(ri);
     for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) {
         int rv;
         rek = sk_CMS_RecipientEncryptedKey_value(reks, i);
         if (cert != NULL && CMS_RecipientEncryptedKey_cert_cmp(rek, cert))
             continue;
-        CMS_RecipientInfo_kari_set0_pkey(ri, pk);
+        CMS_RecipientInfo_kari_set0_pkey_and_peer(ri, pk, peer);
         rv = CMS_RecipientInfo_kari_decrypt(cms, ri, rek);
         CMS_RecipientInfo_kari_set0_pkey(ri, NULL);
         if (rv > 0)
@@ -599,28 +600,37 @@ static int cms_kari_set1_pkey(CMS_ContentInfo *cms, 
CMS_RecipientInfo *ri,
 }
 
 int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
+{
+     return CMS_decrypt_set1_pkey_and_peer(cms, pk, cert, NULL);
+}
+
+int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 
*cert, X509 *peer)
 {
     STACK_OF(CMS_RecipientInfo) *ris;
     CMS_RecipientInfo *ri;
-    int i, r, ri_type;
+    int i, r, cms_pkey_ri_type;
     int debug = 0, match_ri = 0;
     ris = CMS_get0_RecipientInfos(cms);
     if (ris)
         debug = cms->d.envelopedData->encryptedContentInfo->debug;
-    ri_type = cms_pkey_get_ri_type(pk);
-    if (ri_type == CMS_RECIPINFO_NONE) {
-        CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY,
-               CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
-        return 0;
+
+    cms_pkey_ri_type = cms_pkey_get_ri_type(pk);
+    if (cms_pkey_ri_type == CMS_RECIPINFO_NONE) {
+         CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY_AND_PEER,
+              CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+         return 0;
     }
 
     for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
+        int ri_type;
+
         ri = sk_CMS_RecipientInfo_value(ris, i);
-        if (CMS_RecipientInfo_type(ri) != ri_type)
+        ri_type = CMS_RecipientInfo_type(ri);
+        if (!cms_pkey_is_ri_type_supported(pk, ri_type))
             continue;
         match_ri = 1;
         if (ri_type == CMS_RECIPINFO_AGREE) {
-            r = cms_kari_set1_pkey(cms, ri, pk, cert);
+            r = cms_kari_set1_pkey_and_peer(cms, ri, pk, cert, peer);
             if (r > 0)
                 return 1;
             if (r < 0)
@@ -646,7 +656,7 @@ int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY 
*pk, X509 *cert)
                 }
                 if (r > 0)
                     return 1;
-                CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_DECRYPT_ERROR);
+                CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY_AND_PEER, 
CMS_R_DECRYPT_ERROR);
                 return 0;
             }
             /*
@@ -654,17 +664,17 @@ int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY 
*pk, X509 *cert)
              * successful decrypt. Always attempt to decrypt all recipients
              * to avoid leaking timing of a successful decrypt.
              */
-            else if (r > 0 && debug)
+            else if (r > 0 && (debug || cms_pkey_ri_type != 
CMS_RECIPINFO_TRANS))
                 return 1;
         }
     }
     /* If no cert, key transport and not debugging always return success */
-    if (cert == NULL && ri_type == CMS_RECIPINFO_TRANS && match_ri && !debug) {
+    if (cert == NULL && cms_pkey_ri_type == CMS_RECIPINFO_TRANS && match_ri && 
!debug) {
         ERR_clear_error();
         return 1;
     }
 
-    CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT);
+    CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY_AND_PEER, CMS_R_NO_MATCHING_RECIPIENT);
     return 0;
 
 }
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 0a37d5af23..f14acc65b6 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -243,6 +243,7 @@ CMS_F_CMS_ADD0_CERT:164:CMS_add0_cert
 CMS_F_CMS_ADD0_RECIPIENT_KEY:100:CMS_add0_recipient_key
 CMS_F_CMS_ADD0_RECIPIENT_PASSWORD:165:CMS_add0_recipient_password
 CMS_F_CMS_ADD1_RECEIPTREQUEST:158:CMS_add1_ReceiptRequest
+CMS_F_CMS_ADD1_RECIPIENT:184:
 CMS_F_CMS_ADD1_RECIPIENT_CERT:101:CMS_add1_recipient_cert
 CMS_F_CMS_ADD1_SIGNER:102:CMS_add1_signer
 CMS_F_CMS_ADD1_SIGNINGTIME:103:cms_add1_signingTime
@@ -260,6 +261,7 @@ CMS_F_CMS_DECRYPT:112:CMS_decrypt
 CMS_F_CMS_DECRYPT_SET1_KEY:113:CMS_decrypt_set1_key
 CMS_F_CMS_DECRYPT_SET1_PASSWORD:166:CMS_decrypt_set1_password
 CMS_F_CMS_DECRYPT_SET1_PKEY:114:CMS_decrypt_set1_pkey
+CMS_F_CMS_DECRYPT_SET1_PKEY_AND_PEER:185:
 CMS_F_CMS_DIGESTALGORITHM_FIND_CTX:115:cms_DigestAlgorithm_find_ctx
 CMS_F_CMS_DIGESTALGORITHM_INIT_BIO:116:cms_DigestAlgorithm_init_bio
 CMS_F_CMS_DIGESTEDDATA_DO_FINAL:117:cms_DigestedData_do_final
@@ -272,6 +274,8 @@ 
CMS_F_CMS_ENCRYPTEDDATA_DECRYPT:121:CMS_EncryptedData_decrypt
 CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT:122:CMS_EncryptedData_encrypt
 CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY:123:CMS_EncryptedData_set1_key
 CMS_F_CMS_ENVELOPEDDATA_CREATE:124:CMS_EnvelopedData_create
+CMS_F_CMS_ENVELOPEDDATA_ENCRYPTION_INIT_BIO:186:
+CMS_F_CMS_ENVELOPEDDATA_FINAL:187:
 CMS_F_CMS_ENVELOPEDDATA_INIT_BIO:125:cms_EnvelopedData_init_bio
 CMS_F_CMS_ENVELOPED_DATA_INIT:126:cms_enveloped_data_init
 CMS_F_CMS_ENV_ASN1_CTRL:171:cms_env_asn1_ctrl
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index c82a543857..c42897c87d 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -774,6 +774,13 @@ int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const 
EVP_MD *md)
 static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype,
                                 int cmd, int p1, void *p2)
 {
+    /*
+     * GOST CMS format is different for different cipher algorithms.
+     * Most of other algorithms don't have such a difference
+     * so this ctrl is just ignored.
+     */
+    if (cmd == EVP_PKEY_CTRL_CIPHER)
+        return -2;
 # ifndef OPENSSL_NO_DH
     if (keytype == EVP_PKEY_DH) {
         switch (cmd) {
diff --git a/doc/man1/openssl-cms.pod.in b/doc/man1/openssl-cms.pod.in
index 1965a952be..161408fdcb 100644
--- a/doc/man1/openssl-cms.pod.in
+++ b/doc/man1/openssl-cms.pod.in
@@ -46,6 +46,7 @@ B<openssl> B<cms>
 [B<-print>]
 [B<-md> I<digest>]
 [B<-I<cipher>>]
+[B<-wrap> I<cipher>]
 [B<-nointern>]
 [B<-noverify>]
 [B<-nocerts>]
@@ -58,6 +59,7 @@ B<openssl> B<cms>
 [B<-certfile> I<file>]
 [B<-certsout> I<file>]
 [B<-signer> I<file>]
+[B<-originator> I<file>]
 [B<-recip> I<file>]
 [B<-keyid>]
 [B<-receipt_request_all>]
@@ -300,6 +302,12 @@ supported by your version of OpenSSL.
 If not specified triple DES is used. Only used with B<-encrypt> and
 B<-EncryptedData_create> commands.
 
+=item B<-wrap> I<cipher>
+
+Cipher algorithm to use for key wrap when encrypting the message using Key
+Agreement for key transport. The algorithm specified should be suitable for key
+wrap.
+
 =item B<-nointern>
 
 When verifying a message normally certificates (if any) included in
@@ -374,6 +382,11 @@ used multiple times if more than one signer is required. 
If a message is being
 verified then the signers certificates will be written to this file if the
 verification was successful.
 
+=item B<-originator> I<file>
+
+A certificate of the originator of the encrypted message. Necessary for
+decryption when Key Agreement is in use for a shared key.
+
 =item B<-recip> I<file>
 
 When decrypting a message this specifies the recipients certificate. The
diff --git a/doc/man3/CMS_add1_recipient_cert.pod 
b/doc/man3/CMS_add1_recipient_cert.pod
index b68183d109..34d1e0ee36 100644
--- a/doc/man3/CMS_add1_recipient_cert.pod
+++ b/doc/man3/CMS_add1_recipient_cert.pod
@@ -2,12 +2,16 @@
 
 =head1 NAME
 
-CMS_add1_recipient_cert, CMS_add0_recipient_key - add recipients to a CMS 
enveloped data structure
+CMS_add1_recipient, CMS_add1_recipient_cert, CMS_add0_recipient_key - add 
recipients to a CMS enveloped data structure
 
 =head1 SYNOPSIS
 
  #include <openssl/cms.h>
 
+ CMS_RecipientInfo *CMS_add1_recipient(CMS_ContentInfo *cms, X509 *recip,
+                                       EVP_PKEY *originatorPrivKey, 
+                                       X509 *originator, unsigned int flags);
+
  CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
                                             X509 *recip, unsigned int flags);
 
@@ -20,6 +24,11 @@ CMS_add1_recipient_cert, CMS_add0_recipient_key - add 
recipients to a CMS envelo
 
 =head1 DESCRIPTION
 
+CMS_add1_recipient() adds recipient B<recip> and provides the originator pkey
+B<originatorPrivKey> and originator certificate B<originator> to 
CMS_ContentInfo.
+The originator-related fields are relevant only in case when the keyAgreement
+method of providing of the shared key is in use.
+
 CMS_add1_recipient_cert() adds recipient B<recip> to CMS_ContentInfo enveloped
 data structure B<cms> as a KeyTransRecipientInfo structure.
 
@@ -60,9 +69,14 @@ occurs.
 L<ERR_get_error(3)>, L<CMS_decrypt(3)>,
 L<CMS_final(3)>,
 
+=head1 HISTORY
+
+B<CMS_add1_recipient_cert> and B<CMS_add0_recipient_key> were added in
+OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
-Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2008-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
diff --git a/doc/man3/CMS_decrypt.pod b/doc/man3/CMS_decrypt.pod
index 0c5834c549..3124fa8394 100644
--- a/doc/man3/CMS_decrypt.pod
+++ b/doc/man3/CMS_decrypt.pod
@@ -2,7 +2,8 @@
 
 =head1 NAME
 
-CMS_decrypt - decrypt content from a CMS envelopedData structure
+CMS_decrypt, CMS_decrypt_set1_pkey_and_peer, CMS_decrypt_set1_pkey - decrypt
+content from a CMS envelopedData structure
 
 =head1 SYNOPSIS
 
@@ -10,6 +11,9 @@ CMS_decrypt - decrypt content from a CMS envelopedData 
structure
 
  int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert,
                  BIO *dcont, BIO *out, unsigned int flags);
+ int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms,
+                 EVP_PKEY *pk, X509 *cert, X509 *peer);
+ int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert);
 
 =head1 DESCRIPTION
 
@@ -21,6 +25,13 @@ B<flags> is an optional set of flags.
 The B<dcont> parameter is used in the rare case where the encrypted content
 is detached. It will normally be set to NULL.
 
+CMS_decrypt_set1_pkey_and_peer() associates the private key B<pkey>, the
+corresponding certificate B<cert> and the originator certificate B<peer> with
+the CMS_ContentInfo structure B<cms>.
+
+CMS_decrypt_set1_pkey() associates the private key B<pkey>, corresponding
+certificate B<cert> with the CMS_ContentInfo structure B<cms>.
+
 =head1 NOTES
 
 Although the recipients certificate is not needed to decrypt the data it is
@@ -70,9 +81,13 @@ mentioned in CMS_verify() also applies to CMS_decrypt().
 
 L<ERR_get_error(3)>, L<CMS_encrypt(3)>
 
+=head1 HISTORY
+
+B<CMS_decrypt_set1_pkey_and_peer> was added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
-Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2008-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
diff --git a/doc/man3/CMS_get0_RecipientInfos.pod 
b/doc/man3/CMS_get0_RecipientInfos.pod
index 5d19e3d178..c6354381fc 100644
--- a/doc/man3/CMS_get0_RecipientInfos.pod
+++ b/doc/man3/CMS_get0_RecipientInfos.pod
@@ -5,6 +5,8 @@
 CMS_get0_RecipientInfos, CMS_RecipientInfo_type,
 CMS_RecipientInfo_ktri_get0_signer_id, CMS_RecipientInfo_ktri_cert_cmp,
 CMS_RecipientInfo_set0_pkey, CMS_RecipientInfo_kekri_get0_id,
+CMS_RecipientInfo_kari_set0_pkey_and_peer,
+CMS_RecipientInfo_kari_set0_pkey,
 CMS_RecipientInfo_kekri_id_cmp, CMS_RecipientInfo_set0_key,
 CMS_RecipientInfo_decrypt, CMS_RecipientInfo_encrypt
 - CMS envelopedData RecipientInfo routines
@@ -22,7 +24,9 @@ CMS_RecipientInfo_decrypt, CMS_RecipientInfo_encrypt
                                            ASN1_INTEGER **sno);
  int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert);
  int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey);
-
+ int CMS_RecipientInfo_kari_set0_pkey_and_peer(CMS_RecipientInfo *ri,
+                                               EVP_PKEY *pk, X509 *peer);
+ int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk);
  int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri, X509_ALGOR **palg,
                                      ASN1_OCTET_STRING **pid,
                                      ASN1_GENERALIZEDTIME **pdate,
@@ -58,6 +62,13 @@ CMS_RecipientInfo_set0_pkey() associates the private key 
B<pkey> with
 the CMS_RecipientInfo structure B<ri>, which must be of type
 CMS_RECIPINFO_TRANS.
 
+CMS_RecipientInfo_kari_set0_pkey_and_peer() associates the private key B<pkey>
+and peer certificate B<peer> with the CMS_RecipientInfo structure B<ri>, which
+must be of type CMS_RECIPINFO_AGREE.
+
+CMS_RecipientInfo_kari_set0_pkey() associates the private key B<pkey> with the
+CMS_RecipientInfo structure B<ri>, which must be of type CMS_RECIPINFO_AGREE.
+
 CMS_RecipientInfo_kekri_get0_id() retrieves the key information from the
 CMS_RecipientInfo structure B<ri> which must be of type CMS_RECIPINFO_KEK.  Any
 of the remaining parameters can be NULL if the application is not interested in
@@ -127,9 +138,14 @@ Any error can be obtained from L<ERR_get_error(3)>.
 
 L<ERR_get_error(3)>, L<CMS_decrypt(3)>
 
+=head1 HISTORY
+
+B<CMS_RecipientInfo_kari_set0_pkey_and_peer> and 
B<CMS_RecipientInfo_kari_set0_pkey> 
+were added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
-Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2008-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
diff --git a/include/openssl/cms.h b/include/openssl/cms.h
index 1d502fa457..5f66e6df4b 100644
--- a/include/openssl/cms.h
+++ b/include/openssl/cms.h
@@ -80,6 +80,7 @@ DECLARE_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
 # define CMS_KEY_PARAM                   0x40000
 # define CMS_ASCIICRLF                   0x80000
 # define CMS_CADES                       0x100000
+# define CMS_USE_ORIGINATOR_KEYID        0x200000
 
 const ASN1_OBJECT *CMS_get0_type(const CMS_ContentInfo *cms);
 
@@ -150,6 +151,7 @@ int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 
*cert,
                 BIO *dcont, BIO *out, unsigned int flags);
 
 int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert);
+int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 
*cert, X509 *peer);
 int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
                          unsigned char *key, size_t keylen,
                          const unsigned char *id, size_t idlen);
@@ -162,6 +164,8 @@ EVP_PKEY_CTX 
*CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri);
 CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher);
 CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
                                            X509 *recip, unsigned int flags);
+CMS_RecipientInfo *CMS_add1_recipient(CMS_ContentInfo *cms, X509 *recip,
+     EVP_PKEY *originatorPrivKey, X509 * originator, unsigned int flags);
 int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey);
 int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert);
 int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri,
@@ -326,6 +330,7 @@ int 
CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek,
 int CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek,
                                        X509 *cert);
 int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk);
+int CMS_RecipientInfo_kari_set0_pkey_and_peer(CMS_RecipientInfo *ri, EVP_PKEY 
*pk, X509 *peer);
 EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri);
 int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms,
                                    CMS_RecipientInfo *ri,
diff --git a/include/openssl/cmserr.h b/include/openssl/cmserr.h
index 10e0fd6ae8..494ae6191a 100644
--- a/include/openssl/cmserr.h
+++ b/include/openssl/cmserr.h
@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-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
@@ -39,6 +39,7 @@ int ERR_load_CMS_strings(void);
 #   define CMS_F_CMS_ADD0_RECIPIENT_KEY                     0
 #   define CMS_F_CMS_ADD0_RECIPIENT_PASSWORD                0
 #   define CMS_F_CMS_ADD1_RECEIPTREQUEST                    0
+#   define CMS_F_CMS_ADD1_RECIPIENT                         0
 #   define CMS_F_CMS_ADD1_RECIPIENT_CERT                    0
 #   define CMS_F_CMS_ADD1_SIGNER                            0
 #   define CMS_F_CMS_ADD1_SIGNINGTIME                       0
@@ -56,6 +57,7 @@ int ERR_load_CMS_strings(void);
 #   define CMS_F_CMS_DECRYPT_SET1_KEY                       0
 #   define CMS_F_CMS_DECRYPT_SET1_PASSWORD                  0
 #   define CMS_F_CMS_DECRYPT_SET1_PKEY                      0
+#   define CMS_F_CMS_DECRYPT_SET1_PKEY_AND_PEER             0
 #   define CMS_F_CMS_DIGESTALGORITHM_FIND_CTX               0
 #   define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO               0
 #   define CMS_F_CMS_DIGESTEDDATA_DO_FINAL                  0
@@ -68,6 +70,8 @@ int ERR_load_CMS_strings(void);
 #   define CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT                  0
 #   define CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY                 0
 #   define CMS_F_CMS_ENVELOPEDDATA_CREATE                   0
+#   define CMS_F_CMS_ENVELOPEDDATA_ENCRYPTION_INIT_BIO      0
+#   define CMS_F_CMS_ENVELOPEDDATA_FINAL                    0
 #   define CMS_F_CMS_ENVELOPEDDATA_INIT_BIO                 0
 #   define CMS_F_CMS_ENVELOPED_DATA_INIT                    0
 #   define CMS_F_CMS_ENV_ASN1_CTRL                          0
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index 7aa56b3e93..202675cc70 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -294,6 +294,10 @@ int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER 
*cipher))(EVP_CIPHER_CTX *,
 # define         EVP_CIPH_FLAG_PIPELINE          0X800000
 /* For provider implementations that handle  ASN1 get/set param themselves */
 # define         EVP_CIPH_FLAG_CUSTOM_ASN1       0x1000000
+/* For ciphers generating unprotected CMS attributes */
+# define         EVP_CIPH_FLAG_CIPHER_WITH_MAC   0x2000000
+/* For supplementary wrap cipher support */
+# define         EVP_CIPH_FLAG_GET_WRAP_CIPHER   0x4000000
 
 /*
  * Cipher context flag to indicate we can handle wrap mode: if allowed in
@@ -372,6 +376,10 @@ int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER 
*cipher))(EVP_CIPHER_CTX *,
 # define         EVP_CTRL_GET_IV                         0x26
 /* Tell the cipher it's doing a speed test (SIV disallows multiple ops) */
 # define         EVP_CTRL_SET_SPEED                      0x27
+/* Get the unprotectedAttrs from cipher ctx */
+# define         EVP_CTRL_PROCESS_UNPROTECTED            0x28
+/* Get the supplementary wrap cipher */
+#define          EVP_CTRL_GET_WRAP_CIPHER                0x29
 
 /* Padding modes */
 #define EVP_PADDING_PKCS7       1
@@ -1259,6 +1267,7 @@ int EVP_PBE_get(int *ptype, int *ppbe_nid, size_t num);
 # define ASN1_PKEY_CTRL_SET1_TLS_ENCPT   0x9
 # define ASN1_PKEY_CTRL_GET1_TLS_ENCPT   0xa
 # define ASN1_PKEY_CTRL_SUPPORTS_MD_NID  0xb
+# define ASN1_PKEY_CTRL_CMS_IS_RI_TYPE_SUPPORTED 0xc
 
 int EVP_PKEY_asn1_get_count(void);
 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx);
diff --git a/util/libcrypto.num b/util/libcrypto.num
index fa220d873f..8334b99361 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4912,6 +4912,9 @@ ASN1_GENERALIZEDTIME_dup                ? 3_0_0   
EXIST::FUNCTION:
 RAND_priv_bytes_ex                      ?      3_0_0   EXIST::FUNCTION:
 RAND_bytes_ex                           ?      3_0_0   EXIST::FUNCTION:
 EVP_PKEY_get_default_digest_name        ?      3_0_0   EXIST::FUNCTION:
+CMS_decrypt_set1_pkey_and_peer          ?      3_0_0   EXIST::FUNCTION:CMS
+CMS_add1_recipient                      ?      3_0_0   EXIST::FUNCTION:CMS
+CMS_RecipientInfo_kari_set0_pkey_and_peer ?    3_0_0   EXIST::FUNCTION:CMS
 PKCS8_pkey_add1_attr                    ?      3_0_0   EXIST::FUNCTION:
 PKCS8_pkey_add1_attr_by_OBJ             ?      3_0_0   EXIST::FUNCTION:
 EVP_PKEY_private_check                  ?      3_0_0   EXIST::FUNCTION:
diff --git a/util/missingcrypto.txt b/util/missingcrypto.txt
index be5535b87d..99c2883bd0 100644
--- a/util/missingcrypto.txt
+++ b/util/missingcrypto.txt
@@ -325,7 +325,6 @@ CMS_RecipientInfo_kari_get0_ctx(3)
 CMS_RecipientInfo_kari_get0_orig_id(3)
 CMS_RecipientInfo_kari_get0_reks(3)
 CMS_RecipientInfo_kari_orig_id_cmp(3)
-CMS_RecipientInfo_kari_set0_pkey(3)
 CMS_RecipientInfo_ktri_get0_algs(3)
 CMS_RecipientInfo_set0_password(3)
 CMS_SharedInfo_encode(3)
@@ -347,7 +346,6 @@ CMS_dataInit(3)
 CMS_data_create(3)
 CMS_decrypt_set1_key(3)
 CMS_decrypt_set1_password(3)
-CMS_decrypt_set1_pkey(3)
 CMS_digest_create(3)
 CMS_digest_verify(3)
 CMS_is_detached(3)

Reply via email to