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