8e3221b7269ed77427edee600bd8f9364abfaf34
[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
62 static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
63         {
64         unsigned char buf[4096];
65         int r = 0, i;
66         BIO *tmpout = NULL;
67
68         if (out == NULL)
69                 tmpout = BIO_new(BIO_s_null());
70         else if (flags & CMS_TEXT)
71                 tmpout = BIO_new(BIO_s_mem());
72         else
73                 tmpout = out;
74
75         if(!tmpout)
76                 {
77                 CMSerr(CMS_F_CMS_COPY_CONTENT,ERR_R_MALLOC_FAILURE);
78                 goto err;
79                 }
80
81         /* Read all content through chain to process digest, decrypt etc */
82         for (;;)
83         {
84                 i=BIO_read(in,buf,sizeof(buf));
85                 if (i <= 0)
86                         {
87                         if (BIO_method_type(in) == BIO_TYPE_CIPHER)
88                                 {
89                                 if (!BIO_get_cipher_status(in))
90                                         goto err;
91                                 }
92                         break;
93                         }
94                                 
95                 if (tmpout)
96                         BIO_write(tmpout, buf, i);
97         }
98
99         if(flags & CMS_TEXT)
100                 {
101                 if(!SMIME_text(tmpout, out))
102                         {
103                         CMSerr(CMS_F_CMS_COPY_CONTENT,CMS_R_SMIME_TEXT_ERROR);
104                         goto err;
105                         }
106                 }
107
108         r = 1;
109
110         err:
111         if (tmpout && (tmpout != out))
112                 BIO_free(tmpout);
113         return r;
114
115         }
116
117 static int check_content(CMS_ContentInfo *cms)
118         {
119         ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
120         if (!pos || !*pos)
121                 {
122                 CMSerr(CMS_F_CHECK_CONTENT, CMS_R_NO_CONTENT);
123                 return 0;
124                 }
125         return 1;
126         }
127
128 static void do_free_upto(BIO *f, BIO *upto)
129         {
130         if (upto)
131                 {
132                 BIO *tbio;
133                 do 
134                         {
135                         tbio = BIO_pop(f);
136                         BIO_free(f);
137                         f = tbio;
138                         }
139                 while (f != upto);
140                 }
141         else
142                 BIO_free_all(f);
143         }
144
145 int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags)
146         {
147         BIO *cont;
148         int r;
149         if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_data)
150                 {
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                 {
184                 CMSerr(CMS_F_CMS_DIGEST_VERIFY, CMS_R_TYPE_NOT_DIGESTED_DATA);
185                 return 0;
186                 }
187
188         if (!dcont && !check_content(cms))
189                 return 0;
190
191         cont = CMS_dataInit(cms, dcont);
192         if (!cont)
193                 return 0;
194         r = cms_copy_content(out, cont, flags);
195         if (r)
196                 r = cms_DigestedData_do_final(cms, cont, 1);
197         do_free_upto(cont, dcont);
198         return r;
199         }
200
201 CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
202                                         unsigned int flags)
203         {
204         CMS_ContentInfo *cms;
205         if (!md)
206                 md = EVP_sha1();
207         cms = cms_DigestedData_create(md);
208         if (!cms)
209                 return NULL;
210
211         if(!(flags & CMS_DETACHED))
212                 CMS_set_detached(cms, 0);
213
214         if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
215                 return cms;
216
217         CMS_ContentInfo_free(cms);
218         return NULL;
219         }
220
221 int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
222                                 const unsigned char *key, size_t keylen,
223                                 BIO *dcont, BIO *out, unsigned int flags)
224         {
225         BIO *cont;
226         int r;
227         if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_encrypted)
228                 {
229                 CMSerr(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT,
230                                         CMS_R_TYPE_NOT_ENCRYPTED_DATA);
231                 return 0;
232                 }
233
234         if (!dcont && !check_content(cms))
235                 return 0;
236
237         if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0)
238                 return 0;
239         cont = CMS_dataInit(cms, dcont);
240         if (!cont)
241                 return 0;
242         r = cms_copy_content(out, cont, flags);
243         do_free_upto(cont, dcont);
244         return r;
245         }
246
247 CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
248                                         const unsigned char *key, size_t keylen,
249                                         unsigned int flags)
250         {
251         CMS_ContentInfo *cms;
252         if (!cipher)
253                 {
254                 CMSerr(CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT, CMS_R_NO_CIPHER);
255                 return NULL;
256                 }
257         cms = CMS_ContentInfo_new();
258         if (!cms)
259                 return NULL;
260         if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen))
261                 return NULL;
262
263         if(!(flags & CMS_DETACHED))
264                 CMS_set_detached(cms, 0);
265
266         if ((flags & (CMS_STREAM|CMS_PARTIAL))
267                 || CMS_final(cms, in, NULL, flags))
268                 return cms;
269
270         CMS_ContentInfo_free(cms);
271         return NULL;
272         }
273
274 static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
275                                         X509_STORE *store,
276                                         STACK_OF(X509) *certs,
277                                         STACK_OF(X509_CRL) *crls,
278                                         unsigned int flags)
279         {
280         X509_STORE_CTX ctx;
281         X509 *signer;
282         int i, j, r = 0;
283         CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
284         if (!X509_STORE_CTX_init(&ctx, store, signer, certs))
285                 {
286                 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT,
287                                                 CMS_R_STORE_INIT_ERROR);
288                 goto err;
289                 }
290         X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_SMIME_SIGN);
291         if (crls)
292                 X509_STORE_CTX_set0_crls(&ctx, crls);
293
294         i = X509_verify_cert(&ctx);
295         if (i <= 0)
296                 {
297                 j = X509_STORE_CTX_get_error(&ctx);
298                 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT,
299                                                 CMS_R_CERTIFICATE_VERIFY_ERROR);
300                 ERR_add_error_data(2, "Verify error:",
301                                          X509_verify_cert_error_string(j));
302                 goto err;
303                 }
304         r = 1;
305         err:
306         X509_STORE_CTX_cleanup(&ctx);
307         return r;
308
309         }
310
311 int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
312                  X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags)
313         {
314         CMS_SignerInfo *si;
315         STACK_OF(CMS_SignerInfo) *sinfos;
316         STACK_OF(X509) *cms_certs = NULL;
317         STACK_OF(X509_CRL) *crls = NULL;
318         X509 *signer;
319         int i, scount = 0, ret = 0;
320         BIO *cmsbio = NULL, *tmpin = NULL;
321
322         if (!dcont && !check_content(cms))
323                 return 0;
324
325         /* Attempt to find all signer certificates */
326
327         sinfos = CMS_get0_SignerInfos(cms);
328
329         if (sk_CMS_SignerInfo_num(sinfos) <= 0)
330                 {
331                 CMSerr(CMS_F_CMS_VERIFY, CMS_R_NO_SIGNERS);
332                 goto err;
333                 }
334
335         for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
336                 {
337                 si = sk_CMS_SignerInfo_value(sinfos, i);
338                 CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
339                 if (signer)
340                         scount++;
341                 }
342
343         if (scount != sk_CMS_SignerInfo_num(sinfos))
344                 scount += CMS_set1_signers_certs(cms, certs, flags);
345
346         if (scount != sk_CMS_SignerInfo_num(sinfos))
347                 {
348                 CMSerr(CMS_F_CMS_VERIFY, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND);
349                 goto err;
350                 }
351
352         /* Attempt to verify all signers certs */
353
354         if (!(flags & CMS_NO_SIGNER_CERT_VERIFY))
355                 {
356                 cms_certs = CMS_get1_certs(cms);
357                 if (!(flags & CMS_NOCRL))
358                         crls = CMS_get1_crls(cms);
359                 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
360                         {
361                         si = sk_CMS_SignerInfo_value(sinfos, i);
362                         if (!cms_signerinfo_verify_cert(si, store,
363                                                         cms_certs, crls, flags))
364                                 goto err;
365                         }
366                 }
367
368         /* Attempt to verify all SignerInfo signed attribute signatures */
369
370         if (!(flags & CMS_NO_ATTR_VERIFY))
371                 {
372                 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
373                         {
374                         si = sk_CMS_SignerInfo_value(sinfos, i);
375                         if (CMS_signed_get_attr_count(si) < 0)
376                                 continue;
377                         if (CMS_SignerInfo_verify(si) <= 0)
378                                 goto err;
379                         }
380                 }
381
382         /* Performance optimization: if the content is a memory BIO then
383          * store its contents in a temporary read only memory BIO. This
384          * avoids potentially large numbers of slow copies of data which will
385          * occur when reading from a read write memory BIO when signatures
386          * are calculated.
387          */
388
389         if (dcont && (BIO_method_type(dcont) == BIO_TYPE_MEM))
390                 {
391                 char *ptr;
392                 long len;
393                 len = BIO_get_mem_data(dcont, &ptr);
394                 tmpin = BIO_new_mem_buf(ptr, len);
395                 if (tmpin == NULL)
396                         {
397                         CMSerr(CMS_F_CMS_VERIFY,ERR_R_MALLOC_FAILURE);
398                         return 0;
399                         }
400                 }
401         else
402                 tmpin = dcont;
403                 
404
405         cmsbio=CMS_dataInit(cms, tmpin);
406         if (!cmsbio)
407                 goto err;
408
409         if (!cms_copy_content(out, cmsbio, flags))
410                 goto err;
411
412         if (!(flags & CMS_NO_CONTENT_VERIFY))
413                 {
414                 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
415                         {
416                         si = sk_CMS_SignerInfo_value(sinfos, i);
417                         if (!CMS_SignerInfo_verify_content(si, cmsbio))
418                                 {
419                                 CMSerr(CMS_F_CMS_VERIFY,
420                                         CMS_R_CONTENT_VERIFY_ERROR);
421                                 goto err;
422                                 }
423                         }
424                 }
425
426         ret = 1;
427
428         err:
429         
430         if (dcont && (tmpin == dcont))
431                 do_free_upto(cmsbio, dcont);
432         else
433                 BIO_free_all(cmsbio);
434
435         if (cms_certs)
436                 sk_X509_pop_free(cms_certs, X509_free);
437         if (crls)
438                 sk_X509_CRL_pop_free(crls, X509_CRL_free);
439
440         return ret;
441         }
442
443 int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
444                         STACK_OF(X509) *certs,
445                         X509_STORE *store, unsigned int flags)
446         {
447         int r;
448         flags &= ~(CMS_DETACHED|CMS_TEXT);
449         r = CMS_verify(rcms, certs, store, NULL, NULL, flags);
450         if (r <= 0)
451                 return r;
452         return cms_Receipt_verify(rcms, ocms);
453         }
454
455 CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
456                                                 BIO *data, unsigned int flags)
457         {
458         CMS_ContentInfo *cms;
459         int i;
460
461         cms = CMS_ContentInfo_new();
462         if (!cms || !CMS_SignedData_init(cms))
463                 goto merr;
464
465         if (pkey && !CMS_add1_signer(cms, signcert, pkey, NULL, flags))
466                 {
467                 CMSerr(CMS_F_CMS_SIGN, CMS_R_ADD_SIGNER_ERROR);
468                 goto err;
469                 }
470
471         for (i = 0; i < sk_X509_num(certs); i++)
472                 {
473                 X509 *x = sk_X509_value(certs, i);
474                 if (!CMS_add1_cert(cms, x))
475                         goto merr;
476                 }
477
478         if(!(flags & CMS_DETACHED))
479                 CMS_set_detached(cms, 0);
480
481         if ((flags & (CMS_STREAM|CMS_PARTIAL))
482                 || CMS_final(cms, data, NULL, flags))
483                 return cms;
484         else
485                 goto err;
486
487         merr:
488         CMSerr(CMS_F_CMS_SIGN, ERR_R_MALLOC_FAILURE);
489
490         err:
491         if (cms)
492                 CMS_ContentInfo_free(cms);
493         return NULL;
494         }
495
496 CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
497                                         X509 *signcert, EVP_PKEY *pkey,
498                                         STACK_OF(X509) *certs,
499                                         unsigned int flags)
500         {
501         CMS_SignerInfo *rct_si;
502         CMS_ContentInfo *cms = NULL;
503         ASN1_OCTET_STRING **pos, *os;
504         BIO *rct_cont = NULL;
505         int r = 0;
506
507         flags &= ~(CMS_STREAM|CMS_TEXT);
508         /* Not really detached but avoids content being allocated */
509         flags |= CMS_PARTIAL|CMS_BINARY|CMS_DETACHED;
510         if (!pkey || !signcert)
511                 {
512                 CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_NO_KEY_OR_CERT);
513                 return NULL;
514                 }
515
516         /* Initialize signed data */
517
518         cms = CMS_sign(NULL, NULL, certs, NULL, flags);
519         if (!cms)
520                 goto err;
521
522         /* Set inner content type to signed receipt */
523         if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt)))
524                 goto err;
525
526         rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags);
527         if (!rct_si)
528                 {
529                 CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_ADD_SIGNER_ERROR);
530                 goto err;
531                 }
532
533         os = cms_encode_Receipt(si);
534
535         if (!os)
536                 goto err;
537
538         /* Set content to digest */
539         rct_cont = BIO_new_mem_buf(os->data, os->length);
540         if (!rct_cont)
541                 goto err;
542
543         /* Add msgSigDigest attribute */
544
545         if (!cms_msgSigDigest_add1(rct_si, si))
546                 goto err;
547
548         /* Finalize structure */
549         if (!CMS_final(cms, rct_cont, NULL, flags))
550                 goto err;
551
552         /* Set embedded content */
553         pos = CMS_get0_content(cms);
554         *pos = os;
555
556         r = 1;
557
558         err:
559         if (rct_cont)
560                 BIO_free(rct_cont);
561         if (r)
562                 return cms;
563         CMS_ContentInfo_free(cms);
564         return NULL;
565
566         }
567
568 CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
569                                 const EVP_CIPHER *cipher, unsigned int flags)
570         {
571         CMS_ContentInfo *cms;
572         int i;
573         X509 *recip;
574         cms = CMS_EnvelopedData_create(cipher);
575         if (!cms)
576                 goto merr;
577         for (i = 0; i < sk_X509_num(certs); i++)
578                 {
579                 recip = sk_X509_value(certs, i);
580                 if (!CMS_add1_recipient_cert(cms, recip, flags))
581                         {
582                         CMSerr(CMS_F_CMS_ENCRYPT, CMS_R_RECIPIENT_ERROR);
583                         goto err;
584                         }
585                 }
586
587         if(!(flags & CMS_DETACHED))
588                 CMS_set_detached(cms, 0);
589
590         if ((flags & (CMS_STREAM|CMS_PARTIAL))
591                 || CMS_final(cms, data, NULL, flags))
592                 return cms;
593         else
594                 goto err;
595
596         merr:
597         CMSerr(CMS_F_CMS_ENCRYPT, ERR_R_MALLOC_FAILURE);
598         err:
599         if (cms)
600                 CMS_ContentInfo_free(cms);
601         return NULL;
602         }
603
604 int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
605         {
606         STACK_OF(CMS_RecipientInfo) *ris;
607         CMS_RecipientInfo *ri;
608         int i, r;
609         ris = CMS_get0_RecipientInfos(cms);
610         for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
611                 {
612                 ri = sk_CMS_RecipientInfo_value(ris, i);
613                 if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_TRANS)
614                                 continue;
615                 /* If we have a cert try matching RecipientInfo
616                  * otherwise try them all.
617                  */
618                 if (!cert || (CMS_RecipientInfo_ktri_cert_cmp(ri, cert) == 0))
619                         {
620                         CMS_RecipientInfo_set0_pkey(ri, pk);
621                         r = CMS_RecipientInfo_decrypt(cms, ri);
622                         CMS_RecipientInfo_set0_pkey(ri, NULL);
623                         if (r > 0)
624                                 return 1;
625                         if (cert)
626                                 {
627                                 CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY,
628                                                 CMS_R_DECRYPT_ERROR);
629                                 return 0;
630                                 }
631                         ERR_clear_error();
632                         }
633                 }
634
635         CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT);
636         return 0;
637
638         }
639
640 int CMS_decrypt_set1_key(CMS_ContentInfo *cms, 
641                                 unsigned char *key, size_t keylen,
642                                 unsigned char *id, size_t idlen)
643         {
644         STACK_OF(CMS_RecipientInfo) *ris;
645         CMS_RecipientInfo *ri;
646         int i, r;
647         ris = CMS_get0_RecipientInfos(cms);
648         for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
649                 {
650                 ri = sk_CMS_RecipientInfo_value(ris, i);
651                 if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK)
652                                 continue;
653
654                 /* If we have an id try matching RecipientInfo
655                  * otherwise try them all.
656                  */
657                 if (!id || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0))
658                         {
659                         CMS_RecipientInfo_set0_key(ri, key, keylen);
660                         r = CMS_RecipientInfo_decrypt(cms, ri);
661                         CMS_RecipientInfo_set0_key(ri, NULL, 0);
662                         if (r > 0)
663                                 return 1;
664                         if (id)
665                                 {
666                                 CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY,
667                                                 CMS_R_DECRYPT_ERROR);
668                                 return 0;
669                                 }
670                         ERR_clear_error();
671                         }
672                 }
673
674         CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_NO_MATCHING_RECIPIENT);
675         return 0;
676
677         }
678         
679 int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
680                                 BIO *dcont, BIO *out,
681                                 unsigned int flags)
682         {
683         int r;
684         BIO *cont;
685         if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped)
686                 {
687                 CMSerr(CMS_F_CMS_DECRYPT, CMS_R_TYPE_NOT_ENVELOPED_DATA);
688                 return 0;
689                 }
690         if (!dcont && !check_content(cms))
691                 return 0;
692         if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert))
693                 return 0;
694
695         cont = CMS_dataInit(cms, dcont);
696         if (!cont)
697                 return 0;
698         r = cms_copy_content(out, cont, flags);
699         do_free_upto(cont, dcont);
700         return r;
701         }
702
703 int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags)
704         {
705         BIO *cmsbio;
706         int ret = 0;
707         if (!(cmsbio = CMS_dataInit(cms, dcont)))
708                 {
709                 CMSerr(CMS_F_CMS_FINAL,ERR_R_MALLOC_FAILURE);
710                 return 0;
711                 }
712
713         SMIME_crlf_copy(data, cmsbio, flags);
714
715         (void)BIO_flush(cmsbio);
716
717
718         if (!CMS_dataFinal(cms, cmsbio))
719                 {
720                 CMSerr(CMS_F_CMS_FINAL,CMS_R_CMS_DATAFINAL_ERROR);
721                 goto err;
722                 }
723
724         ret = 1;
725
726         err:
727         do_free_upto(cmsbio, dcont);
728
729         return ret;
730
731         }
732
733 #ifdef ZLIB
734
735 int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
736                                                         unsigned int flags)
737         {
738         BIO *cont;
739         int r;
740         if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_id_smime_ct_compressedData)
741                 {
742                 CMSerr(CMS_F_CMS_UNCOMPRESS,
743                                         CMS_R_TYPE_NOT_COMPRESSED_DATA);
744                 return 0;
745                 }
746
747         if (!dcont && !check_content(cms))
748                 return 0;
749
750         cont = CMS_dataInit(cms, dcont);
751         if (!cont)
752                 return 0;
753         r = cms_copy_content(out, cont, flags);
754         do_free_upto(cont, dcont);
755         return r;
756         }
757
758 CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
759         {
760         CMS_ContentInfo *cms;
761         if (comp_nid <= 0)
762                 comp_nid = NID_zlib_compression;
763         cms = cms_CompressedData_create(comp_nid);
764         if (!cms)
765                 return NULL;
766
767         if(!(flags & CMS_DETACHED))
768                 CMS_set_detached(cms, 0);
769
770         if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
771                 return cms;
772
773         CMS_ContentInfo_free(cms);
774         return NULL;
775         }
776
777 #else
778
779 int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
780                                                         unsigned int flags)
781         {
782         CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
783         return 0;
784         }
785
786 CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
787         {
788         CMSerr(CMS_F_CMS_COMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
789         return NULL;
790         }
791
792 #endif