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