int r = 0, i;
BIO *tmpout = NULL;
- if(flags & CMS_TEXT)
- {
+ if (out == NULL)
+ tmpout = BIO_new(BIO_s_null());
+ else if (flags & CMS_TEXT)
tmpout = BIO_new(BIO_s_mem());
- if(!tmpout)
- {
- CMSerr(CMS_F_CMS_COPY_CONTENT,ERR_R_MALLOC_FAILURE);
- goto err;
- }
- }
else
tmpout = out;
+ if(!tmpout)
+ {
+ CMSerr(CMS_F_CMS_COPY_CONTENT,ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
/* Read all content through chain to process digest, decrypt etc */
for (;;)
{
if (!cms)
return NULL;
- if ((flags & CMS_STREAM) || CMS_final(cms, in, flags))
+ if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
return cms;
CMS_ContentInfo_free(cms);
if(!(flags & CMS_DETACHED))
CMS_set_detached(cms, 0);
- if ((flags & CMS_STREAM) || CMS_final(cms, in, flags))
+ if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
return cms;
CMS_ContentInfo_free(cms);
if(!(flags & CMS_DETACHED))
CMS_set_detached(cms, 0);
- if ((flags & (CMS_STREAM|CMS_PARTIAL)) || CMS_final(cms, in, flags))
+ if ((flags & (CMS_STREAM|CMS_PARTIAL))
+ || CMS_final(cms, in, NULL, flags))
return cms;
CMS_ContentInfo_free(cms);
if (!(flags & CMS_NO_SIGNER_CERT_VERIFY))
{
cms_certs = CMS_get1_certs(cms);
- crls = CMS_get1_crls(cms);
+ if (!(flags & CMS_NOCRL))
+ crls = CMS_get1_crls(cms);
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
{
si = sk_CMS_SignerInfo_value(sinfos, i);
return ret;
}
+int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
+ STACK_OF(X509) *certs,
+ X509_STORE *store, unsigned int flags)
+ {
+ int r;
+ flags &= ~(CMS_DETACHED|CMS_TEXT);
+ r = CMS_verify(rcms, certs, store, NULL, NULL, flags);
+ if (r <= 0)
+ return r;
+ return cms_Receipt_verify(rcms, ocms);
+ }
+
CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
BIO *data, unsigned int flags)
{
if(!(flags & CMS_DETACHED))
CMS_set_detached(cms, 0);
- if ((flags & (CMS_STREAM|CMS_PARTIAL)) || CMS_final(cms, data, flags))
+ if ((flags & (CMS_STREAM|CMS_PARTIAL))
+ || CMS_final(cms, data, NULL, flags))
return cms;
-
- return cms;
+ else
+ goto err;
merr:
CMSerr(CMS_F_CMS_SIGN, ERR_R_MALLOC_FAILURE);
return NULL;
}
-/* Placeholder for now... */
+CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
+ X509 *signcert, EVP_PKEY *pkey,
+ STACK_OF(X509) *certs,
+ unsigned int flags)
+ {
+ CMS_SignerInfo *rct_si;
+ CMS_ContentInfo *cms = NULL;
+ ASN1_OCTET_STRING **pos, *os;
+ BIO *rct_cont = NULL;
+ int r = 0;
+
+ flags &= ~(CMS_STREAM|CMS_TEXT);
+ /* Not really detached but avoids content being allocated */
+ flags |= CMS_PARTIAL|CMS_BINARY|CMS_DETACHED;
+ if (!pkey || !signcert)
+ {
+ CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_NO_KEY_OR_CERT);
+ return NULL;
+ }
+
+ /* Initialize signed data */
-CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in,
+ cms = CMS_sign(NULL, NULL, certs, NULL, flags);
+ if (!cms)
+ goto err;
+
+ /* Set inner content type to signed receipt */
+ if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt)))
+ goto err;
+
+ rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags);
+ if (!rct_si)
+ {
+ CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_ADD_SIGNER_ERROR);
+ goto err;
+ }
+
+ os = cms_encode_Receipt(si);
+
+ if (!os)
+ goto err;
+
+ /* Set content to digest */
+ rct_cont = BIO_new_mem_buf(os->data, os->length);
+ if (!rct_cont)
+ goto err;
+
+ /* Add msgSigDigest attribute */
+
+ if (!cms_msgSigDigest_add1(rct_si, si))
+ goto err;
+
+ /* Finalize structure */
+ if (!CMS_final(cms, rct_cont, NULL, flags))
+ goto err;
+
+ /* Set embedded content */
+ pos = CMS_get0_content(cms);
+ *pos = os;
+
+ r = 1;
+
+ err:
+ if (rct_cont)
+ BIO_free(rct_cont);
+ if (r)
+ return cms;
+ CMS_ContentInfo_free(cms);
+ return NULL;
+
+ }
+
+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, NULL, flags))
+ return cms;
+ else
+ goto err;
+
+ merr:
+ CMSerr(CMS_F_CMS_ENCRYPT, ERR_R_MALLOC_FAILURE);
+ err:
+ if (cms)
+ CMS_ContentInfo_free(cms);
return NULL;
}
-
-int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
- BIO *dcont, BIO *out,
- unsigned int flags)
+
+int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
{
STACK_OF(CMS_RecipientInfo) *ris;
CMS_RecipientInfo *ri;
int i, r;
- BIO *cont;
- if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped)
+ ris = CMS_get0_RecipientInfos(cms);
+ for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
{
- CMSerr(CMS_F_CMS_DECRYPT, CMS_R_TYPE_NOT_ENVELOPED_DATA);
- return 0;
+ ri = sk_CMS_RecipientInfo_value(ris, i);
+ if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_TRANS)
+ continue;
+ /* If we have a cert try matching RecipientInfo
+ * otherwise try them all.
+ */
+ if (!cert || (CMS_RecipientInfo_ktri_cert_cmp(ri, cert) == 0))
+ {
+ CMS_RecipientInfo_set0_pkey(ri, pk);
+ r = CMS_RecipientInfo_decrypt(cms, ri);
+ CMS_RecipientInfo_set0_pkey(ri, NULL);
+ if (r > 0)
+ return 1;
+ if (cert)
+ {
+ CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY,
+ CMS_R_DECRYPT_ERROR);
+ return 0;
+ }
+ ERR_clear_error();
+ }
}
- if (!dcont && !check_content(cms))
- return 0;
+
+ CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT);
+ return 0;
+
+ }
+
+int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
+ unsigned char *key, size_t keylen,
+ unsigned char *id, size_t idlen)
+ {
+ STACK_OF(CMS_RecipientInfo) *ris;
+ CMS_RecipientInfo *ri;
+ int i, r;
ris = CMS_get0_RecipientInfos(cms);
for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
{
ri = sk_CMS_RecipientInfo_value(ris, i);
- if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_TRANS)
- continue;
- if (cert)
+ if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK)
+ continue;
+
+ /* If we have an id try matching RecipientInfo
+ * otherwise try them all.
+ */
+ if (!id || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0))
{
- if (CMS_RecipientInfo_ktri_cert_cmp(ri, cert) == 0)
+ CMS_RecipientInfo_set0_key(ri, key, keylen);
+ r = CMS_RecipientInfo_decrypt(cms, ri);
+ CMS_RecipientInfo_set0_key(ri, NULL, 0);
+ if (r > 0)
+ return 1;
+ if (id)
{
- if (CMS_RecipientInfo_decrypt(cms, ri, pk) <=0)
- return 0;
- else
- break;
+ CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY,
+ CMS_R_DECRYPT_ERROR);
+ return 0;
}
+ ERR_clear_error();
}
}
- if (i == sk_CMS_RecipientInfo_num(ris))
+ CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_NO_MATCHING_RECIPIENT);
+ return 0;
+
+ }
+
+int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
+ BIO *dcont, BIO *out,
+ unsigned int flags)
+ {
+ int r;
+ BIO *cont;
+ if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped)
{
- CMSerr(CMS_F_CMS_DECRYPT, CMS_R_NO_MATCHING_RECIPIENT);
+ CMSerr(CMS_F_CMS_DECRYPT, CMS_R_TYPE_NOT_ENVELOPED_DATA);
return 0;
}
+ if (!dcont && !check_content(cms))
+ return 0;
+ if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert))
+ return 0;
+
cont = CMS_dataInit(cms, dcont);
if (!cont)
return 0;
return r;
}
-int CMS_final(CMS_ContentInfo *cms, BIO *data, int flags)
+int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags)
{
BIO *cmsbio;
int ret = 0;
- if (!(cmsbio = CMS_dataInit(cms, NULL)))
+ if (!(cmsbio = CMS_dataInit(cms, dcont)))
{
CMSerr(CMS_F_CMS_FINAL,ERR_R_MALLOC_FAILURE);
return 0;
#ifdef ZLIB
-int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
+int CMS_uncompress(CMS_ContentInfo *cms, BIO *out, BIO *dcont,
unsigned int flags)
{
BIO *cont;
if(!(flags & CMS_DETACHED))
CMS_set_detached(cms, 0);
- if ((flags & CMS_STREAM) || CMS_final(cms, in, flags))
+ if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
return cms;
CMS_ContentInfo_free(cms);