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