Fix error code
[openssl.git] / crypto / cms / cms_smime.c
1 /*
2  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project.
4  */
5 /* ====================================================================
6  * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  */
53
54 #include "internal/cryptlib.h"
55 #include <openssl/asn1t.h>
56 #include <openssl/x509.h>
57 #include <openssl/x509v3.h>
58 #include <openssl/err.h>
59 #include <openssl/cms.h>
60 #include "cms_lcl.h"
61 #include "internal/asn1_int.h"
62
63 static BIO *cms_get_text_bio(BIO *out, unsigned int flags)
64 {
65     BIO *rbio;
66     if (out == NULL)
67         rbio = BIO_new(BIO_s_null());
68     else if (flags & CMS_TEXT) {
69         rbio = BIO_new(BIO_s_mem());
70         BIO_set_mem_eof_return(rbio, 0);
71     } else
72         rbio = out;
73     return rbio;
74 }
75
76 static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
77 {
78     unsigned char buf[4096];
79     int r = 0, i;
80     BIO *tmpout;
81
82     tmpout = cms_get_text_bio(out, flags);
83
84     if (tmpout == NULL) {
85         CMSerr(CMS_F_CMS_COPY_CONTENT, ERR_R_MALLOC_FAILURE);
86         goto err;
87     }
88
89     /* Read all content through chain to process digest, decrypt etc */
90     for (;;) {
91         i = BIO_read(in, buf, sizeof(buf));
92         if (i <= 0) {
93             if (BIO_method_type(in) == BIO_TYPE_CIPHER) {
94                 if (!BIO_get_cipher_status(in))
95                     goto err;
96             }
97             if (i < 0)
98                 goto err;
99             break;
100         }
101
102         if (tmpout && (BIO_write(tmpout, buf, i) != i))
103             goto err;
104     }
105
106     if (flags & CMS_TEXT) {
107         if (!SMIME_text(tmpout, out)) {
108             CMSerr(CMS_F_CMS_COPY_CONTENT, CMS_R_SMIME_TEXT_ERROR);
109             goto err;
110         }
111     }
112
113     r = 1;
114
115  err:
116     if (tmpout != out)
117         BIO_free(tmpout);
118     return r;
119
120 }
121
122 static int check_content(CMS_ContentInfo *cms)
123 {
124     ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
125     if (!pos || !*pos) {
126         CMSerr(CMS_F_CHECK_CONTENT, CMS_R_NO_CONTENT);
127         return 0;
128     }
129     return 1;
130 }
131
132 static void do_free_upto(BIO *f, BIO *upto)
133 {
134     if (upto) {
135         BIO *tbio;
136         do {
137             tbio = BIO_pop(f);
138             BIO_free(f);
139             f = tbio;
140         }
141         while (f && f != upto);
142     } else
143         BIO_free_all(f);
144 }
145
146 int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags)
147 {
148     BIO *cont;
149     int r;
150     if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_data) {
151         CMSerr(CMS_F_CMS_DATA, CMS_R_TYPE_NOT_DATA);
152         return 0;
153     }
154     cont = CMS_dataInit(cms, NULL);
155     if (!cont)
156         return 0;
157     r = cms_copy_content(out, cont, flags);
158     BIO_free_all(cont);
159     return r;
160 }
161
162 CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags)
163 {
164     CMS_ContentInfo *cms;
165     cms = cms_Data_create();
166     if (!cms)
167         return NULL;
168
169     if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
170         return cms;
171
172     CMS_ContentInfo_free(cms);
173
174     return NULL;
175 }
176
177 int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
178                       unsigned int flags)
179 {
180     BIO *cont;
181     int r;
182     if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_digest) {
183         CMSerr(CMS_F_CMS_DIGEST_VERIFY, CMS_R_TYPE_NOT_DIGESTED_DATA);
184         return 0;
185     }
186
187     if (!dcont && !check_content(cms))
188         return 0;
189
190     cont = CMS_dataInit(cms, dcont);
191     if (!cont)
192         return 0;
193     r = cms_copy_content(out, cont, flags);
194     if (r)
195         r = cms_DigestedData_do_final(cms, cont, 1);
196     do_free_upto(cont, dcont);
197     return r;
198 }
199
200 CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
201                                    unsigned int flags)
202 {
203     CMS_ContentInfo *cms;
204     if (!md)
205         md = EVP_sha1();
206     cms = cms_DigestedData_create(md);
207     if (!cms)
208         return NULL;
209
210     if (!(flags & CMS_DETACHED))
211         CMS_set_detached(cms, 0);
212
213     if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
214         return cms;
215
216     CMS_ContentInfo_free(cms);
217     return NULL;
218 }
219
220 int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
221                               const unsigned char *key, size_t keylen,
222                               BIO *dcont, BIO *out, unsigned int flags)
223 {
224     BIO *cont;
225     int r;
226     if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_encrypted) {
227         CMSerr(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT,
228                CMS_R_TYPE_NOT_ENCRYPTED_DATA);
229         return 0;
230     }
231
232     if (!dcont && !check_content(cms))
233         return 0;
234
235     if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0)
236         return 0;
237     cont = CMS_dataInit(cms, dcont);
238     if (!cont)
239         return 0;
240     r = cms_copy_content(out, cont, flags);
241     do_free_upto(cont, dcont);
242     return r;
243 }
244
245 CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
246                                            const unsigned char *key,
247                                            size_t keylen, unsigned int flags)
248 {
249     CMS_ContentInfo *cms;
250     if (!cipher) {
251         CMSerr(CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT, CMS_R_NO_CIPHER);
252         return NULL;
253     }
254     cms = CMS_ContentInfo_new();
255     if (cms == NULL)
256         return NULL;
257     if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen))
258         return NULL;
259
260     if (!(flags & CMS_DETACHED))
261         CMS_set_detached(cms, 0);
262
263     if ((flags & (CMS_STREAM | CMS_PARTIAL))
264         || CMS_final(cms, in, NULL, flags))
265         return cms;
266
267     CMS_ContentInfo_free(cms);
268     return NULL;
269 }
270
271 static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
272                                       X509_STORE *store,
273                                       STACK_OF(X509) *certs,
274                                       STACK_OF(X509_CRL) *crls)
275 {
276     X509_STORE_CTX ctx;
277     X509 *signer;
278     int i, j, r = 0;
279     CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
280     if (!X509_STORE_CTX_init(&ctx, store, signer, certs)) {
281         CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT, CMS_R_STORE_INIT_ERROR);
282         goto err;
283     }
284     X509_STORE_CTX_set_default(&ctx, "smime_sign");
285     if (crls)
286         X509_STORE_CTX_set0_crls(&ctx, crls);
287
288     i = X509_verify_cert(&ctx);
289     if (i <= 0) {
290         j = X509_STORE_CTX_get_error(&ctx);
291         CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT,
292                CMS_R_CERTIFICATE_VERIFY_ERROR);
293         ERR_add_error_data(2, "Verify error:",
294                            X509_verify_cert_error_string(j));
295         goto err;
296     }
297     r = 1;
298  err:
299     X509_STORE_CTX_cleanup(&ctx);
300     return r;
301
302 }
303
304 int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
305                X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags)
306 {
307     CMS_SignerInfo *si;
308     STACK_OF(CMS_SignerInfo) *sinfos;
309     STACK_OF(X509) *cms_certs = NULL;
310     STACK_OF(X509_CRL) *crls = NULL;
311     X509 *signer;
312     int i, scount = 0, ret = 0;
313     BIO *cmsbio = NULL, *tmpin = NULL, *tmpout = NULL;
314
315     if (!dcont && !check_content(cms))
316         return 0;
317     if (dcont && !(flags & CMS_BINARY)) {
318         const ASN1_OBJECT *coid = CMS_get0_eContentType(cms);
319         if (OBJ_obj2nid(coid) == NID_id_ct_asciiTextWithCRLF)
320             flags |= CMS_ASCIICRLF;
321     }
322
323     /* Attempt to find all signer certificates */
324
325     sinfos = CMS_get0_SignerInfos(cms);
326
327     if (sk_CMS_SignerInfo_num(sinfos) <= 0) {
328         CMSerr(CMS_F_CMS_VERIFY, CMS_R_NO_SIGNERS);
329         goto err;
330     }
331
332     for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
333         si = sk_CMS_SignerInfo_value(sinfos, i);
334         CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
335         if (signer)
336             scount++;
337     }
338
339     if (scount != sk_CMS_SignerInfo_num(sinfos))
340         scount += CMS_set1_signers_certs(cms, certs, flags);
341
342     if (scount != sk_CMS_SignerInfo_num(sinfos)) {
343         CMSerr(CMS_F_CMS_VERIFY, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND);
344         goto err;
345     }
346
347     /* Attempt to verify all signers certs */
348
349     if (!(flags & CMS_NO_SIGNER_CERT_VERIFY)) {
350         cms_certs = CMS_get1_certs(cms);
351         if (!(flags & CMS_NOCRL))
352             crls = CMS_get1_crls(cms);
353         for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
354             si = sk_CMS_SignerInfo_value(sinfos, i);
355             if (!cms_signerinfo_verify_cert(si, store, cms_certs, crls))
356                 goto err;
357         }
358     }
359
360     /* Attempt to verify all SignerInfo signed attribute signatures */
361
362     if (!(flags & CMS_NO_ATTR_VERIFY)) {
363         for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
364             si = sk_CMS_SignerInfo_value(sinfos, i);
365             if (CMS_signed_get_attr_count(si) < 0)
366                 continue;
367             if (CMS_SignerInfo_verify(si) <= 0)
368                 goto err;
369         }
370     }
371
372     /*
373      * Performance optimization: if the content is a memory BIO then store
374      * its contents in a temporary read only memory BIO. This avoids
375      * potentially large numbers of slow copies of data which will occur when
376      * reading from a read write memory BIO when signatures are calculated.
377      */
378
379     if (dcont && (BIO_method_type(dcont) == BIO_TYPE_MEM)) {
380         char *ptr;
381         long len;
382         len = BIO_get_mem_data(dcont, &ptr);
383         tmpin = BIO_new_mem_buf(ptr, len);
384         if (tmpin == NULL) {
385             CMSerr(CMS_F_CMS_VERIFY, ERR_R_MALLOC_FAILURE);
386             goto err2;
387         }
388     } else
389         tmpin = dcont;
390     /*
391      * If not binary mode and detached generate digests by *writing* through
392      * the BIO. That makes it possible to canonicalise the input.
393      */
394     if (!(flags & SMIME_BINARY) && dcont) {
395         /*
396          * Create output BIO so we can either handle text or to ensure
397          * included content doesn't override detached content.
398          */
399         tmpout = cms_get_text_bio(out, flags);
400         if (!tmpout) {
401             CMSerr(CMS_F_CMS_VERIFY, ERR_R_MALLOC_FAILURE);
402             goto err;
403         }
404         cmsbio = CMS_dataInit(cms, tmpout);
405         if (!cmsbio)
406             goto err;
407         /*
408          * Don't use SMIME_TEXT for verify: it adds headers and we want to
409          * remove them.
410          */
411         SMIME_crlf_copy(dcont, cmsbio, flags & ~SMIME_TEXT);
412
413         if (flags & CMS_TEXT) {
414             if (!SMIME_text(tmpout, out)) {
415                 CMSerr(CMS_F_CMS_VERIFY, CMS_R_SMIME_TEXT_ERROR);
416                 goto err;
417             }
418         }
419     } else {
420         cmsbio = CMS_dataInit(cms, tmpin);
421         if (!cmsbio)
422             goto err;
423
424         if (!cms_copy_content(out, cmsbio, flags))
425             goto err;
426
427     }
428     if (!(flags & CMS_NO_CONTENT_VERIFY)) {
429         for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
430             si = sk_CMS_SignerInfo_value(sinfos, i);
431             if (CMS_SignerInfo_verify_content(si, cmsbio) <= 0) {
432                 CMSerr(CMS_F_CMS_VERIFY, CMS_R_CONTENT_VERIFY_ERROR);
433                 goto err;
434             }
435         }
436     }
437
438     ret = 1;
439
440  err:
441     if (!(flags & SMIME_BINARY) && dcont) {
442         do_free_upto(cmsbio, tmpout);
443         if (tmpin != dcont)
444             BIO_free(tmpin);
445     } else {
446         if (dcont && (tmpin == dcont))
447             do_free_upto(cmsbio, dcont);
448         else
449             BIO_free_all(cmsbio);
450     }
451
452     if (out != tmpout)
453         BIO_free_all(tmpout);
454
455  err2:
456     sk_X509_pop_free(cms_certs, X509_free);
457     sk_X509_CRL_pop_free(crls, X509_CRL_free);
458
459     return ret;
460 }
461
462 int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
463                        STACK_OF(X509) *certs,
464                        X509_STORE *store, unsigned int flags)
465 {
466     int r;
467     flags &= ~(CMS_DETACHED | CMS_TEXT);
468     r = CMS_verify(rcms, certs, store, NULL, NULL, flags);
469     if (r <= 0)
470         return r;
471     return cms_Receipt_verify(rcms, ocms);
472 }
473
474 CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey,
475                           STACK_OF(X509) *certs, BIO *data,
476                           unsigned int flags)
477 {
478     CMS_ContentInfo *cms;
479     int i;
480
481     cms = CMS_ContentInfo_new();
482     if (cms == NULL || !CMS_SignedData_init(cms))
483         goto merr;
484     if (flags & CMS_ASCIICRLF
485         && !CMS_set1_eContentType(cms,
486                                   OBJ_nid2obj(NID_id_ct_asciiTextWithCRLF)))
487         goto err;
488
489     if (pkey && !CMS_add1_signer(cms, signcert, pkey, NULL, flags)) {
490         CMSerr(CMS_F_CMS_SIGN, CMS_R_ADD_SIGNER_ERROR);
491         goto err;
492     }
493
494     for (i = 0; i < sk_X509_num(certs); i++) {
495         X509 *x = sk_X509_value(certs, i);
496         if (!CMS_add1_cert(cms, x))
497             goto merr;
498     }
499
500     if (!(flags & CMS_DETACHED))
501         CMS_set_detached(cms, 0);
502
503     if ((flags & (CMS_STREAM | CMS_PARTIAL))
504         || CMS_final(cms, data, NULL, flags))
505         return cms;
506     else
507         goto err;
508
509  merr:
510     CMSerr(CMS_F_CMS_SIGN, ERR_R_MALLOC_FAILURE);
511
512  err:
513     CMS_ContentInfo_free(cms);
514     return NULL;
515 }
516
517 CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
518                                   X509 *signcert, EVP_PKEY *pkey,
519                                   STACK_OF(X509) *certs, unsigned int flags)
520 {
521     CMS_SignerInfo *rct_si;
522     CMS_ContentInfo *cms = NULL;
523     ASN1_OCTET_STRING **pos, *os;
524     BIO *rct_cont = NULL;
525     int r = 0;
526
527     flags &= ~(CMS_STREAM | CMS_TEXT);
528     /* Not really detached but avoids content being allocated */
529     flags |= CMS_PARTIAL | CMS_BINARY | CMS_DETACHED;
530     if (!pkey || !signcert) {
531         CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_NO_KEY_OR_CERT);
532         return NULL;
533     }
534
535     /* Initialize signed data */
536
537     cms = CMS_sign(NULL, NULL, certs, NULL, flags);
538     if (!cms)
539         goto err;
540
541     /* Set inner content type to signed receipt */
542     if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt)))
543         goto err;
544
545     rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags);
546     if (!rct_si) {
547         CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_ADD_SIGNER_ERROR);
548         goto err;
549     }
550
551     os = cms_encode_Receipt(si);
552
553     if (!os)
554         goto err;
555
556     /* Set content to digest */
557     rct_cont = BIO_new_mem_buf(os->data, os->length);
558     if (!rct_cont)
559         goto err;
560
561     /* Add msgSigDigest attribute */
562
563     if (!cms_msgSigDigest_add1(rct_si, si))
564         goto err;
565
566     /* Finalize structure */
567     if (!CMS_final(cms, rct_cont, NULL, flags))
568         goto err;
569
570     /* Set embedded content */
571     pos = CMS_get0_content(cms);
572     *pos = os;
573
574     r = 1;
575
576  err:
577     BIO_free(rct_cont);
578     if (r)
579         return cms;
580     CMS_ContentInfo_free(cms);
581     return NULL;
582
583 }
584
585 CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
586                              const EVP_CIPHER *cipher, unsigned int flags)
587 {
588     CMS_ContentInfo *cms;
589     int i;
590     X509 *recip;
591     cms = CMS_EnvelopedData_create(cipher);
592     if (!cms)
593         goto merr;
594     for (i = 0; i < sk_X509_num(certs); i++) {
595         recip = sk_X509_value(certs, i);
596         if (!CMS_add1_recipient_cert(cms, recip, flags)) {
597             CMSerr(CMS_F_CMS_ENCRYPT, CMS_R_RECIPIENT_ERROR);
598             goto err;
599         }
600     }
601
602     if (!(flags & CMS_DETACHED))
603         CMS_set_detached(cms, 0);
604
605     if ((flags & (CMS_STREAM | CMS_PARTIAL))
606         || CMS_final(cms, data, NULL, flags))
607         return cms;
608     else
609         goto err;
610
611  merr:
612     CMSerr(CMS_F_CMS_ENCRYPT, ERR_R_MALLOC_FAILURE);
613  err:
614     CMS_ContentInfo_free(cms);
615     return NULL;
616 }
617
618 static int cms_kari_set1_pkey(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
619                               EVP_PKEY *pk, X509 *cert)
620 {
621     int i;
622     STACK_OF(CMS_RecipientEncryptedKey) *reks;
623     CMS_RecipientEncryptedKey *rek;
624     reks = CMS_RecipientInfo_kari_get0_reks(ri);
625     if (!cert)
626         return 0;
627     for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) {
628         int rv;
629         rek = sk_CMS_RecipientEncryptedKey_value(reks, i);
630         if (CMS_RecipientEncryptedKey_cert_cmp(rek, cert))
631             continue;
632         CMS_RecipientInfo_kari_set0_pkey(ri, pk);
633         rv = CMS_RecipientInfo_kari_decrypt(cms, ri, rek);
634         CMS_RecipientInfo_kari_set0_pkey(ri, NULL);
635         if (rv > 0)
636             return 1;
637         return -1;
638     }
639     return 0;
640 }
641
642 int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
643 {
644     STACK_OF(CMS_RecipientInfo) *ris;
645     CMS_RecipientInfo *ri;
646     int i, r, ri_type;
647     int debug = 0, match_ri = 0;
648     ris = CMS_get0_RecipientInfos(cms);
649     if (ris)
650         debug = cms->d.envelopedData->encryptedContentInfo->debug;
651     ri_type = cms_pkey_get_ri_type(pk);
652     if (ri_type == CMS_RECIPINFO_NONE) {
653         CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY,
654                CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
655         return 0;
656     }
657
658     for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
659         ri = sk_CMS_RecipientInfo_value(ris, i);
660         if (CMS_RecipientInfo_type(ri) != ri_type)
661             continue;
662         match_ri = 1;
663         if (ri_type == CMS_RECIPINFO_AGREE) {
664             r = cms_kari_set1_pkey(cms, ri, pk, cert);
665             if (r > 0)
666                 return 1;
667             if (r < 0)
668                 return 0;
669         }
670         /*
671          * If we have a cert try matching RecipientInfo otherwise try them
672          * all.
673          */
674         else if (!cert || !CMS_RecipientInfo_ktri_cert_cmp(ri, cert)) {
675             CMS_RecipientInfo_set0_pkey(ri, pk);
676             r = CMS_RecipientInfo_decrypt(cms, ri);
677             CMS_RecipientInfo_set0_pkey(ri, NULL);
678             if (cert) {
679                 /*
680                  * If not debugging clear any error and return success to
681                  * avoid leaking of information useful to MMA
682                  */
683                 if (!debug) {
684                     ERR_clear_error();
685                     return 1;
686                 }
687                 if (r > 0)
688                     return 1;
689                 CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_DECRYPT_ERROR);
690                 return 0;
691             }
692             /*
693              * If no cert and not debugging don't leave loop after first
694              * successful decrypt. Always attempt to decrypt all recipients
695              * to avoid leaking timing of a successful decrypt.
696              */
697             else if (r > 0 && debug)
698                 return 1;
699         }
700     }
701     /* If no cert and not debugging always return success */
702     if (match_ri && !cert && !debug) {
703         ERR_clear_error();
704         return 1;
705     }
706
707     CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT);
708     return 0;
709
710 }
711
712 int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
713                          unsigned char *key, size_t keylen,
714                          unsigned char *id, size_t idlen)
715 {
716     STACK_OF(CMS_RecipientInfo) *ris;
717     CMS_RecipientInfo *ri;
718     int i, r;
719     ris = CMS_get0_RecipientInfos(cms);
720     for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
721         ri = sk_CMS_RecipientInfo_value(ris, i);
722         if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK)
723             continue;
724
725         /*
726          * If we have an id try matching RecipientInfo otherwise try them
727          * all.
728          */
729         if (!id || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) {
730             CMS_RecipientInfo_set0_key(ri, key, keylen);
731             r = CMS_RecipientInfo_decrypt(cms, ri);
732             CMS_RecipientInfo_set0_key(ri, NULL, 0);
733             if (r > 0)
734                 return 1;
735             if (id) {
736                 CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_DECRYPT_ERROR);
737                 return 0;
738             }
739             ERR_clear_error();
740         }
741     }
742
743     CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_NO_MATCHING_RECIPIENT);
744     return 0;
745
746 }
747
748 int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
749                               unsigned char *pass, ossl_ssize_t passlen)
750 {
751     STACK_OF(CMS_RecipientInfo) *ris;
752     CMS_RecipientInfo *ri;
753     int i, r;
754     ris = CMS_get0_RecipientInfos(cms);
755     for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
756         ri = sk_CMS_RecipientInfo_value(ris, i);
757         if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_PASS)
758             continue;
759         CMS_RecipientInfo_set0_password(ri, pass, passlen);
760         r = CMS_RecipientInfo_decrypt(cms, ri);
761         CMS_RecipientInfo_set0_password(ri, NULL, 0);
762         if (r > 0)
763             return 1;
764     }
765
766     CMSerr(CMS_F_CMS_DECRYPT_SET1_PASSWORD, CMS_R_NO_MATCHING_RECIPIENT);
767     return 0;
768
769 }
770
771 int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
772                 BIO *dcont, BIO *out, unsigned int flags)
773 {
774     int r;
775     BIO *cont;
776     if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped) {
777         CMSerr(CMS_F_CMS_DECRYPT, CMS_R_TYPE_NOT_ENVELOPED_DATA);
778         return 0;
779     }
780     if (!dcont && !check_content(cms))
781         return 0;
782     if (flags & CMS_DEBUG_DECRYPT)
783         cms->d.envelopedData->encryptedContentInfo->debug = 1;
784     else
785         cms->d.envelopedData->encryptedContentInfo->debug = 0;
786     if (!pk && !cert && !dcont && !out)
787         return 1;
788     if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert))
789         return 0;
790     cont = CMS_dataInit(cms, dcont);
791     if (!cont)
792         return 0;
793     r = cms_copy_content(out, cont, flags);
794     do_free_upto(cont, dcont);
795     return r;
796 }
797
798 int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags)
799 {
800     BIO *cmsbio;
801     int ret = 0;
802
803     if ((cmsbio = CMS_dataInit(cms, dcont)) == NULL) {
804         CMSerr(CMS_F_CMS_FINAL, CMS_R_CMS_LIB);
805         return 0;
806     }
807
808     SMIME_crlf_copy(data, cmsbio, flags);
809
810     (void)BIO_flush(cmsbio);
811
812     if (!CMS_dataFinal(cms, cmsbio)) {
813         CMSerr(CMS_F_CMS_FINAL, CMS_R_CMS_DATAFINAL_ERROR);
814         goto err;
815     }
816
817     ret = 1;
818
819  err:
820     do_free_upto(cmsbio, dcont);
821
822     return ret;
823
824 }
825
826 #ifdef ZLIB
827
828 int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
829                    unsigned int flags)
830 {
831     BIO *cont;
832     int r;
833     if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_id_smime_ct_compressedData) {
834         CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_TYPE_NOT_COMPRESSED_DATA);
835         return 0;
836     }
837
838     if (!dcont && !check_content(cms))
839         return 0;
840
841     cont = CMS_dataInit(cms, dcont);
842     if (!cont)
843         return 0;
844     r = cms_copy_content(out, cont, flags);
845     do_free_upto(cont, dcont);
846     return r;
847 }
848
849 CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
850 {
851     CMS_ContentInfo *cms;
852     if (comp_nid <= 0)
853         comp_nid = NID_zlib_compression;
854     cms = cms_CompressedData_create(comp_nid);
855     if (!cms)
856         return NULL;
857
858     if (!(flags & CMS_DETACHED))
859         CMS_set_detached(cms, 0);
860
861     if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
862         return cms;
863
864     CMS_ContentInfo_free(cms);
865     return NULL;
866 }
867
868 #else
869
870 int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
871                    unsigned int flags)
872 {
873     CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
874     return 0;
875 }
876
877 CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
878 {
879     CMSerr(CMS_F_CMS_COMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
880     return NULL;
881 }
882
883 #endif