From 761ffa729f396dc4b8607a64ad522f6104eaa7bd Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Mon, 17 Mar 2008 13:38:51 +0000 Subject: [PATCH] Preliminary support for enveloped data content type creation. Fix signed data creation so versions are only corrected if structure is being created. --- crypto/cms/cms.h | 10 +++ crypto/cms/cms_enc.c | 23 ++++--- crypto/cms/cms_env.c | 151 ++++++++++++++++++++++++++++++++++++++--- crypto/cms/cms_err.c | 9 ++- crypto/cms/cms_lcl.h | 5 ++ crypto/cms/cms_sd.c | 5 +- crypto/cms/cms_smime.c | 49 ++++++++++--- 7 files changed, 221 insertions(+), 31 deletions(-) diff --git a/crypto/cms/cms.h b/crypto/cms/cms.h index c3ab3eb171..d316db5743 100644 --- a/crypto/cms/cms.h +++ b/crypto/cms/cms.h @@ -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 diff --git a/crypto/cms/cms_enc.c b/crypto/cms/cms_enc.c index fad756e37a..21d86f986e 100644 --- a/crypto/cms/cms_enc.c +++ b/crypto/cms/cms_enc.c @@ -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); } diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c index 796b0d3756..c2cf669718 100644 --- a/crypto/cms/cms_env.c +++ b/crypto/cms/cms_env.c @@ -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; + } diff --git a/crypto/cms/cms_err.c b/crypto/cms/cms_err.c index 047a3d0fab..0e13f39ff1 100644 --- a/crypto/cms/cms_err.c +++ b/crypto/cms/cms_err.c @@ -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} diff --git a/crypto/cms/cms_lcl.h b/crypto/cms/cms_lcl.h index 774ec103f7..f23d096607 100644 --- a/crypto/cms/cms_lcl.h +++ b/crypto/cms/cms_lcl.h @@ -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); diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c index 4483593f86..302b93f805 100644 --- a/crypto/cms/cms_sd.c +++ b/crypto/cms/cms_sd.c @@ -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; diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c index 7a2498d735..3a813de246 100644 --- a/crypto/cms/cms_smime.c +++ b/crypto/cms/cms_smime.c @@ -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; } } -- 2.34.1