Preliminary support for enveloped data content type creation.
authorDr. Stephen Henson <steve@openssl.org>
Mon, 17 Mar 2008 13:38:51 +0000 (13:38 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Mon, 17 Mar 2008 13:38:51 +0000 (13:38 +0000)
Fix signed data creation so versions are only corrected if structure is
being created.

crypto/cms/cms.h
crypto/cms/cms_enc.c
crypto/cms/cms_env.c
crypto/cms/cms_err.c
crypto/cms/cms_lcl.h
crypto/cms/cms_sd.c
crypto/cms/cms_smime.c

index c3ab3eb..d316db5 100644 (file)
@@ -169,6 +169,9 @@ int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert,
 
 STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms);
 int CMS_RecipientInfo_type(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);
 int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert);
 int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri,
                                        EVP_PKEY **pk, X509 **recip,
@@ -290,6 +293,7 @@ void ERR_load_CMS_strings(void);
 #define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO              111
 #define CMS_F_CMS_DIGESTEDDATA_DO_FINAL                         112
 #define CMS_F_CMS_DIGEST_VERIFY                                 113
+#define CMS_F_CMS_ENCRYPT                               154
 #define CMS_F_CMS_ENCRYPTEDCONTENT_DECRYPT_BIO          146
 #define CMS_F_CMS_ENCRYPTEDCONTENT_ENCRYPT_BIO          144
 #define CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO             148
@@ -299,6 +303,8 @@ void ERR_load_CMS_strings(void);
 #define CMS_F_CMS_ENCRYPTEDDATA_INIT_BIO                147
 #define CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY                141
 #define CMS_F_CMS_ENCRYPTED_DATA_DECRYPT                139
+#define CMS_F_CMS_ENVELOPEDDATA_CREATE                  153
+#define CMS_F_CMS_ENVELOPEDDATA_INIT_BIO                156
 #define CMS_F_CMS_ENVELOPED_DATA_INIT                   114
 #define CMS_F_CMS_FINAL                                         115
 #define CMS_F_CMS_GET0_CERTIFICATE_CHOICES              116
@@ -309,6 +315,7 @@ void ERR_load_CMS_strings(void);
 #define CMS_F_CMS_GET0_SIGNED                           121
 #define CMS_F_CMS_RECIPIENTINFO_DECRYPT                         150
 #define CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP           122
+#define CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT            155
 #define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS          123
 #define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID     124
 #define CMS_F_CMS_SET1_SIGNERIDENTIFIER                         125
@@ -340,6 +347,7 @@ void ERR_load_CMS_strings(void);
 #define CMS_R_CTRL_FAILURE                              108
 #define CMS_R_ERROR_GETTING_PUBLIC_KEY                  109
 #define CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE     110
+#define CMS_R_ERROR_SETTING_RECIPIENTINFO               150
 #define CMS_R_INVALID_KEY_LENGTH                        140
 #define CMS_R_MD_BIO_INIT_ERROR                                 111
 #define CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH      112
@@ -358,6 +366,7 @@ void ERR_load_CMS_strings(void);
 #define CMS_R_NO_PUBLIC_KEY                             121
 #define CMS_R_NO_SIGNERS                                122
 #define CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE    123
+#define CMS_R_RECIPIENT_ERROR                           149
 #define CMS_R_SIGNER_CERTIFICATE_NOT_FOUND              124
 #define CMS_R_SIGNFINAL_ERROR                           125
 #define CMS_R_SMIME_TEXT_ERROR                          126
@@ -373,6 +382,7 @@ void ERR_load_CMS_strings(void);
 #define CMS_R_UNKNOWN_ID                                133
 #define CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM                 134
 #define CMS_R_UNSUPPORTED_CONTENT_TYPE                  135
+#define CMS_R_UNSUPPORTED_RECIPIENT_TYPE                151
 #define CMS_R_UNSUPPORTED_TYPE                          136
 #define CMS_R_VERIFICATION_FAILURE                      137
 
index fad756e..21d86f9 100644 (file)
@@ -92,7 +92,14 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
        BIO_get_cipher_ctx(b, &ctx);
 
        if (enc)
+               {
                ciph = ec->cipher;
+               /* If not keeping key set cipher to NULL so subsequent calls
+                * decrypt.
+                */
+               if (ec->key)
+                       ec->cipher = NULL;
+               }
        else
                {
                ciph = EVP_get_cipherbyobj(calg->algorithm);
@@ -112,12 +119,10 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
                goto err;
                }
 
-       if (enc)
-               calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx));
-
        if (enc)
                {
                int ivlen;
+               calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx));
                /* Generate a random IV if we need one */
                ivlen = EVP_CIPHER_CTX_iv_length(ctx);
                if (ivlen > 0)
@@ -128,11 +133,11 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
                        }
                }
        else if (EVP_CIPHER_asn1_to_param(ctx, calg->parameter) <= 0)
-                       {
-                       CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
+               {
+               CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
                                CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
-                       goto err;
-                       }
+               goto err;
+               }
 
 
        if (enc && !ec->key)
@@ -200,7 +205,7 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
        return NULL;
        }
 
-static int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec, 
+int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec, 
                                const EVP_CIPHER *cipher,
                                const unsigned char *key, size_t keylen)
        {
@@ -252,7 +257,7 @@ int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
 BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms)
        {
        CMS_EncryptedData *enc = cms->d.encryptedData;
-       if (enc->unprotectedAttrs)
+       if (enc->encryptedContentInfo->cipher && enc->unprotectedAttrs)
                enc->version = 2;
        return cms_EncryptedContent_init_bio(enc->encryptedContentInfo);
        }
index 796b0d3..c2cf669 100644 (file)
@@ -104,7 +104,7 @@ static CMS_EnvelopedData *cms_enveloped_data_init(CMS_ContentInfo *cms)
 STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms)
        {
        CMS_EnvelopedData *env;
-       env = cms_enveloped_data_init(cms);
+       env = cms_get0_enveloped(cms);
        if (!env)
                return NULL;
        return env->recipientInfos;
@@ -115,10 +115,30 @@ int CMS_RecipientInfo_type(CMS_RecipientInfo *ri)
        return ri->type;
        }
 
+CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher)
+       {
+       CMS_ContentInfo *cms;
+       CMS_EnvelopedData *env;
+       cms = CMS_ContentInfo_new();
+       if (!cms)
+               goto merr;
+       env = cms_enveloped_data_init(cms);
+       if (!env)
+               goto merr;
+       if (!cms_EncryptedContent_init(env->encryptedContentInfo,
+                                       cipher, NULL, 0))
+               goto merr;
+       return cms;
+       merr:
+       if (cms)
+               CMS_ContentInfo_free(cms);
+       CMSerr(CMS_F_CMS_ENVELOPEDDATA_CREATE, ERR_R_MALLOC_FAILURE);
+       return NULL;
+       }
+
 /* Add a recipient certificate. For now only handle key transport.
  * If we ever handle key agreement will need updating.
  */
-#if 0 /* currently unused/undeclared */
 CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
                                        X509 *recip, unsigned int flags)
        {
@@ -127,17 +147,16 @@ CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
        CMS_EnvelopedData *env;
        EVP_PKEY *pk = NULL;
        int i, type;
-       /* Init enveloped data */
-       env = cms_enveloped_data_init(cms);
+       env = cms_get0_enveloped(cms);
        if (!env)
                goto err;
 
-       /* Initialized recipient info */
+       /* Initialize recipient info */
        ri = M_ASN1_new_of(CMS_RecipientInfo);
        if (!ri)
                goto merr;
 
-       /* Initialize and add key transrport recipient info */
+       /* Initialize and add key transport recipient info */
 
        ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo);
        if (!ri->d.ktri)
@@ -155,7 +174,6 @@ CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
                goto err;
                }
        CRYPTO_add(&recip->references, 1, CRYPTO_LOCK_X509);
-       CRYPTO_add(&pk->references, 1, CRYPTO_LOCK_EVP_PKEY);
        ktri->pkey = pk;
        ktri->recip = recip;
 
@@ -208,7 +226,6 @@ CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
        return NULL;
 
        }
-#endif
 
 int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri,
                                        EVP_PKEY **pk, X509 **recip,
@@ -262,6 +279,71 @@ int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert)
        return cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert);
        }
 
+/* Encrypt content key in key transport recipient info */
+
+static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms,
+                                       CMS_RecipientInfo *ri)
+       {
+       CMS_KeyTransRecipientInfo *ktri;
+       CMS_EncryptedContentInfo *ec;
+       EVP_PKEY_CTX *pctx = NULL;
+       unsigned char *ek = NULL;
+       size_t eklen;
+
+       int ret = 0;
+
+       if (ri->type != CMS_RECIPINFO_TRANS)
+               {
+               CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT,
+                       CMS_R_NOT_KEY_TRANSPORT);
+               return 0;
+               }
+       ktri = ri->d.ktri;
+       ec = cms->d.envelopedData->encryptedContentInfo;
+
+       pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL);
+       if (!pctx)
+               return 0;
+
+       if (EVP_PKEY_encrypt_init(pctx) <= 0)
+               goto err;
+
+       if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT,
+                               EVP_PKEY_CTRL_CMS_ENCRYPT, 0, ri) <= 0)
+               {
+               CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, CMS_R_CTRL_ERROR);
+               goto err;
+               }
+
+       if (EVP_PKEY_encrypt(pctx, NULL, &eklen, ec->key, ec->keylen) <= 0)
+               goto err;
+
+       ek = OPENSSL_malloc(eklen);
+
+       if (ek == NULL)
+               {
+               CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT,
+                                                       ERR_R_MALLOC_FAILURE);
+               goto err;
+               }
+
+       if (EVP_PKEY_encrypt(pctx, ek, &eklen, ec->key, ec->keylen) <= 0)
+               goto err;
+
+       ASN1_STRING_set0(ktri->encryptedKey, ek, eklen);
+       ek = NULL;
+
+       ret = 1;
+
+       err:
+       if (pctx)
+               EVP_PKEY_CTX_free(pctx);
+       if (ek)
+               OPENSSL_free(ek);
+       return ret;
+
+       }
+
 int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
                               EVP_PKEY *pkey)
        {
@@ -332,6 +414,57 @@ int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
 BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms)
        {
        CMS_EncryptedContentInfo *ec;
+       STACK_OF(CMS_RecipientInfo) *rinfos;
+       CMS_RecipientInfo *ri;
+       int i, r, ok = 0;
+       BIO *ret;
+
+       /* Get BIO first to set up key */
+
        ec = cms->d.envelopedData->encryptedContentInfo;
-       return cms_EncryptedContent_init_bio(ec);
+       ret = cms_EncryptedContent_init_bio(ec);
+
+       /* If error or no cipher end of processing */
+
+       if (!ret || !ec->cipher)
+               return ret;
+
+
+       rinfos = cms->d.envelopedData->recipientInfos;
+
+       for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++)
+               {
+               ri = sk_CMS_RecipientInfo_value(rinfos, i);
+               if (ri->type == CMS_RECIPINFO_TRANS)
+                       r = cms_RecipientInfo_ktri_encrypt(cms, ri);
+               else
+                       {
+                       CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO,
+                               CMS_R_UNSUPPORTED_RECIPIENT_TYPE);
+                       goto err;
+                       }
+               if (r <= 0)
+                       {
+                       CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO,
+                               CMS_R_ERROR_SETTING_RECIPIENTINFO);
+                       goto err;
+                       }
+               }
+
+       ok = 1;
+
+       err:
+       ec->cipher = NULL;
+       if (ec->key)
+               {
+               OPENSSL_cleanse(ec->key, ec->keylen);
+               OPENSSL_free(ec->key);
+               ec->key = NULL;
+               ec->keylen = 0;
+               }
+       if (ok)
+               return ret;
+       BIO_free(ret);
+       return NULL;
+
        }
index 047a3d0..0e13f39 100644 (file)
@@ -71,7 +71,7 @@
 static ERR_STRING_DATA CMS_str_functs[]=
        {
 {ERR_FUNC(CMS_F_CHECK_CONTENT),        "CHECK_CONTENT"},
-{ERR_FUNC(CMS_F_CMS_ADD1_RECIPIENT_CERT),      "CMS_ADD1_RECIPIENT_CERT"},
+{ERR_FUNC(CMS_F_CMS_ADD1_RECIPIENT_CERT),      "CMS_add1_recipient_cert"},
 {ERR_FUNC(CMS_F_CMS_ADD1_SIGNER),      "CMS_add1_signer"},
 {ERR_FUNC(CMS_F_CMS_ADD1_SIGNINGTIME), "CMS_ADD1_SIGNINGTIME"},
 {ERR_FUNC(CMS_F_CMS_BIO_TO_ENCRYPTEDCONTENT),  "CMS_BIO_TO_ENCRYPTEDCONTENT"},
@@ -91,6 +91,7 @@ static ERR_STRING_DATA CMS_str_functs[]=
 {ERR_FUNC(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO), "CMS_DIGESTALGORITHM_INIT_BIO"},
 {ERR_FUNC(CMS_F_CMS_DIGESTEDDATA_DO_FINAL),    "CMS_DIGESTEDDATA_DO_FINAL"},
 {ERR_FUNC(CMS_F_CMS_DIGEST_VERIFY),    "CMS_digest_verify"},
+{ERR_FUNC(CMS_F_CMS_ENCRYPT),  "CMS_encrypt"},
 {ERR_FUNC(CMS_F_CMS_ENCRYPTEDCONTENT_DECRYPT_BIO),     "CMS_ENCRYPTEDCONTENT_DECRYPT_BIO"},
 {ERR_FUNC(CMS_F_CMS_ENCRYPTEDCONTENT_ENCRYPT_BIO),     "CMS_ENCRYPTEDCONTENT_ENCRYPT_BIO"},
 {ERR_FUNC(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO),        "CMS_ENCRYPTEDCONTENT_INIT_BIO"},
@@ -100,6 +101,8 @@ static ERR_STRING_DATA CMS_str_functs[]=
 {ERR_FUNC(CMS_F_CMS_ENCRYPTEDDATA_INIT_BIO),   "CMS_ENCRYPTEDDATA_INIT_BIO"},
 {ERR_FUNC(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY),   "CMS_EncryptedData_set1_key"},
 {ERR_FUNC(CMS_F_CMS_ENCRYPTED_DATA_DECRYPT),   "CMS_ENCRYPTED_DATA_DECRYPT"},
+{ERR_FUNC(CMS_F_CMS_ENVELOPEDDATA_CREATE),     "CMS_EnvelopedData_create"},
+{ERR_FUNC(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO),   "CMS_ENVELOPEDDATA_INIT_BIO"},
 {ERR_FUNC(CMS_F_CMS_ENVELOPED_DATA_INIT),      "CMS_ENVELOPED_DATA_INIT"},
 {ERR_FUNC(CMS_F_CMS_FINAL),    "CMS_final"},
 {ERR_FUNC(CMS_F_CMS_GET0_CERTIFICATE_CHOICES), "CMS_GET0_CERTIFICATE_CHOICES"},
@@ -110,6 +113,7 @@ static ERR_STRING_DATA CMS_str_functs[]=
 {ERR_FUNC(CMS_F_CMS_GET0_SIGNED),      "CMS_GET0_SIGNED"},
 {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_DECRYPT),    "CMS_RecipientInfo_decrypt"},
 {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP),      "CMS_RecipientInfo_ktri_cert_cmp"},
+{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT),       "CMS_RECIPIENTINFO_KTRI_ENCRYPT"},
 {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS),     "CMS_RecipientInfo_ktri_get0_algs"},
 {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID),        "CMS_RecipientInfo_ktri_get0_signer_id"},
 {ERR_FUNC(CMS_F_CMS_SET1_SIGNERIDENTIFIER),    "CMS_SET1_SIGNERIDENTIFIER"},
@@ -144,6 +148,7 @@ static ERR_STRING_DATA CMS_str_reasons[]=
 {ERR_REASON(CMS_R_CTRL_FAILURE)          ,"ctrl failure"},
 {ERR_REASON(CMS_R_ERROR_GETTING_PUBLIC_KEY),"error getting public key"},
 {ERR_REASON(CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE),"error reading messagedigest attribute"},
+{ERR_REASON(CMS_R_ERROR_SETTING_RECIPIENTINFO),"error setting recipientinfo"},
 {ERR_REASON(CMS_R_INVALID_KEY_LENGTH)    ,"invalid key length"},
 {ERR_REASON(CMS_R_MD_BIO_INIT_ERROR)     ,"md bio init error"},
 {ERR_REASON(CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH),"messagedigest attribute wrong length"},
@@ -162,6 +167,7 @@ static ERR_STRING_DATA CMS_str_reasons[]=
 {ERR_REASON(CMS_R_NO_PUBLIC_KEY)         ,"no public key"},
 {ERR_REASON(CMS_R_NO_SIGNERS)            ,"no signers"},
 {ERR_REASON(CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE),"private key does not match certificate"},
+{ERR_REASON(CMS_R_RECIPIENT_ERROR)       ,"recipient error"},
 {ERR_REASON(CMS_R_SIGNER_CERTIFICATE_NOT_FOUND),"signer certificate not found"},
 {ERR_REASON(CMS_R_SIGNFINAL_ERROR)       ,"signfinal error"},
 {ERR_REASON(CMS_R_SMIME_TEXT_ERROR)      ,"smime text error"},
@@ -177,6 +183,7 @@ static ERR_STRING_DATA CMS_str_reasons[]=
 {ERR_REASON(CMS_R_UNKNOWN_ID)            ,"unknown id"},
 {ERR_REASON(CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM),"unsupported compression algorithm"},
 {ERR_REASON(CMS_R_UNSUPPORTED_CONTENT_TYPE),"unsupported content type"},
+{ERR_REASON(CMS_R_UNSUPPORTED_RECIPIENT_TYPE),"unsupported recipient type"},
 {ERR_REASON(CMS_R_UNSUPPORTED_TYPE)      ,"unsupported type"},
 {ERR_REASON(CMS_R_VERIFICATION_FAILURE)  ,"verification failure"},
 {0,NULL}
index 774ec10..f23d096 100644 (file)
@@ -123,6 +123,8 @@ struct CMS_EncapsulatedContentInfo_st
        {
        ASN1_OBJECT *eContentType;
        ASN1_OCTET_STRING *eContent;
+       /* Set to 1 if incomplete structure only part set up */
+       int partial;
        };
 
 struct CMS_SignerInfo_st
@@ -411,6 +413,9 @@ int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
 
 BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec);
 BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms);
+int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec, 
+                               const EVP_CIPHER *cipher,
+                               const unsigned char *key, size_t keylen);
 
 BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms);
        
index 4483593..302b93f 100644 (file)
@@ -87,6 +87,7 @@ static CMS_SignedData *cms_signed_data_init(CMS_ContentInfo *cms)
                cms->d.signedData->version = 1;
                cms->d.signedData->encapContentInfo->eContentType =
                                                OBJ_nid2obj(NID_pkcs7_data);
+               cms->d.signedData->encapContentInfo->partial = 1;
                ASN1_OBJECT_free(cms->contentType);
                cms->contentType = OBJ_nid2obj(NID_pkcs7_signed);
                return cms->d.signedData;
@@ -679,6 +680,7 @@ int cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain)
                if (!cms_SignerInfo_content_sign(si, chain))
                        return 0;
                }
+       cms->d.signedData->encapContentInfo->partial = 0;
        return 1;
        }
 
@@ -800,7 +802,8 @@ BIO *cms_SignedData_init_bio(CMS_ContentInfo *cms)
        sd = cms_get0_signed(cms);
        if (!sd)
                return NULL;
-       cms_sd_set_version(sd);
+       if (cms->d.signedData->encapContentInfo->partial)
+               cms_sd_set_version(sd);
        for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++)
                {
                X509_ALGOR *digestAlgorithm;
index 7a2498d..3a813de 100644 (file)
@@ -459,11 +459,38 @@ CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
        return NULL;
        }
 
-/* Placeholder for now... */
-
-CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in,
+CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
                                const EVP_CIPHER *cipher, unsigned int flags)
        {
+       CMS_ContentInfo *cms;
+       int i;
+       X509 *recip;
+       cms = CMS_EnvelopedData_create(cipher);
+       if (!cms)
+               goto merr;
+       for (i = 0; i < sk_X509_num(certs); i++)
+               {
+               recip = sk_X509_value(certs, i);
+               if (!CMS_add1_recipient_cert(cms, recip, flags))
+                       {
+                       CMSerr(CMS_F_CMS_ENCRYPT, CMS_R_RECIPIENT_ERROR);
+                       goto err;
+                       }
+               }
+
+       if(!(flags & CMS_DETACHED))
+               CMS_set_detached(cms, 0);
+
+       if ((flags & (CMS_STREAM|CMS_PARTIAL)) || CMS_final(cms, data, flags))
+               return cms;
+
+       return cms;
+
+       merr:
+       CMSerr(CMS_F_CMS_ENCRYPT, ERR_R_MALLOC_FAILURE);
+       err:
+       if (cms)
+               CMS_ContentInfo_free(cms);
        return NULL;
        }
        
@@ -488,15 +515,15 @@ int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
                ri = sk_CMS_RecipientInfo_value(ris, i);
                if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_TRANS)
                        continue;
-               if (cert)
+               /* If we have a cert try matching RecipientInfo otherwise
+                * try them all.
+                */
+               if (!cert || (CMS_RecipientInfo_ktri_cert_cmp(ri, cert) == 0))
                        {
-                       if (CMS_RecipientInfo_ktri_cert_cmp(ri, cert) == 0)
-                               {
-                               if (CMS_RecipientInfo_decrypt(cms, ri, pk) <=0)
-                                       return 0;
-                               else
-                                       break;
-                               }
+                       if (CMS_RecipientInfo_decrypt(cms, ri, pk) > 0)
+                               break;
+                       else if (cert)
+                               return 0;
                        }
                }