cms_smime.c revision 284295
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 62static 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 122static 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 133static 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 && f != upto); 145 } 146 else 147 BIO_free_all(f); 148 } 149 150int 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 167CMS_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 182int 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 206CMS_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 229int 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 255CMS_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 285static 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 322int 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 454int 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 465CMS_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 509CMS_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 581CMS_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 620int 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 int debug = 0, ri_match = 0; 626 ris = CMS_get0_RecipientInfos(cms); 627 if (ris) 628 debug = cms->d.envelopedData->encryptedContentInfo->debug; 629 for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) 630 { 631 ri = sk_CMS_RecipientInfo_value(ris, i); 632 if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_TRANS) 633 continue; 634 ri_match = 1; 635 /* If we have a cert try matching RecipientInfo 636 * otherwise try them all. 637 */ 638 if (!cert || (CMS_RecipientInfo_ktri_cert_cmp(ri, cert) == 0)) 639 { 640 CMS_RecipientInfo_set0_pkey(ri, pk); 641 r = CMS_RecipientInfo_decrypt(cms, ri); 642 CMS_RecipientInfo_set0_pkey(ri, NULL); 643 if (cert) 644 { 645 /* If not debugging clear any error and 646 * return success to avoid leaking of 647 * information useful to MMA 648 */ 649 if (!debug) 650 { 651 ERR_clear_error(); 652 return 1; 653 } 654 if (r > 0) 655 return 1; 656 CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, 657 CMS_R_DECRYPT_ERROR); 658 return 0; 659 } 660 /* If no cert and not debugging don't leave loop 661 * after first successful decrypt. Always attempt 662 * to decrypt all recipients to avoid leaking timing 663 * of a successful decrypt. 664 */ 665 else if (r > 0 && debug) 666 return 1; 667 } 668 } 669 /* If no cert and not debugging always return success */ 670 if (ri_match && !cert && !debug) 671 { 672 ERR_clear_error(); 673 return 1; 674 } 675 676 CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT); 677 return 0; 678 679 } 680 681int CMS_decrypt_set1_key(CMS_ContentInfo *cms, 682 unsigned char *key, size_t keylen, 683 unsigned char *id, size_t idlen) 684 { 685 STACK_OF(CMS_RecipientInfo) *ris; 686 CMS_RecipientInfo *ri; 687 int i, r; 688 ris = CMS_get0_RecipientInfos(cms); 689 for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) 690 { 691 ri = sk_CMS_RecipientInfo_value(ris, i); 692 if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK) 693 continue; 694 695 /* If we have an id try matching RecipientInfo 696 * otherwise try them all. 697 */ 698 if (!id || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) 699 { 700 CMS_RecipientInfo_set0_key(ri, key, keylen); 701 r = CMS_RecipientInfo_decrypt(cms, ri); 702 CMS_RecipientInfo_set0_key(ri, NULL, 0); 703 if (r > 0) 704 return 1; 705 if (id) 706 { 707 CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, 708 CMS_R_DECRYPT_ERROR); 709 return 0; 710 } 711 ERR_clear_error(); 712 } 713 } 714 715 CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_NO_MATCHING_RECIPIENT); 716 return 0; 717 718 } 719 720int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert, 721 BIO *dcont, BIO *out, 722 unsigned int flags) 723 { 724 int r; 725 BIO *cont; 726 if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped) 727 { 728 CMSerr(CMS_F_CMS_DECRYPT, CMS_R_TYPE_NOT_ENVELOPED_DATA); 729 return 0; 730 } 731 if (!dcont && !check_content(cms)) 732 return 0; 733 if (flags & CMS_DEBUG_DECRYPT) 734 cms->d.envelopedData->encryptedContentInfo->debug = 1; 735 else 736 cms->d.envelopedData->encryptedContentInfo->debug = 0; 737 if (!pk && !cert && !dcont && !out) 738 return 1; 739 if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert)) 740 return 0; 741 cont = CMS_dataInit(cms, dcont); 742 if (!cont) 743 return 0; 744 r = cms_copy_content(out, cont, flags); 745 do_free_upto(cont, dcont); 746 return r; 747 } 748 749int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags) 750 { 751 BIO *cmsbio; 752 int ret = 0; 753 if (!(cmsbio = CMS_dataInit(cms, dcont))) 754 { 755 CMSerr(CMS_F_CMS_FINAL,ERR_R_MALLOC_FAILURE); 756 return 0; 757 } 758 759 SMIME_crlf_copy(data, cmsbio, flags); 760 761 (void)BIO_flush(cmsbio); 762 763 764 if (!CMS_dataFinal(cms, cmsbio)) 765 { 766 CMSerr(CMS_F_CMS_FINAL,CMS_R_CMS_DATAFINAL_ERROR); 767 goto err; 768 } 769 770 ret = 1; 771 772 err: 773 do_free_upto(cmsbio, dcont); 774 775 return ret; 776 777 } 778 779#ifdef ZLIB 780 781int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, 782 unsigned int flags) 783 { 784 BIO *cont; 785 int r; 786 if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_id_smime_ct_compressedData) 787 { 788 CMSerr(CMS_F_CMS_UNCOMPRESS, 789 CMS_R_TYPE_NOT_COMPRESSED_DATA); 790 return 0; 791 } 792 793 if (!dcont && !check_content(cms)) 794 return 0; 795 796 cont = CMS_dataInit(cms, dcont); 797 if (!cont) 798 return 0; 799 r = cms_copy_content(out, cont, flags); 800 do_free_upto(cont, dcont); 801 return r; 802 } 803 804CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags) 805 { 806 CMS_ContentInfo *cms; 807 if (comp_nid <= 0) 808 comp_nid = NID_zlib_compression; 809 cms = cms_CompressedData_create(comp_nid); 810 if (!cms) 811 return NULL; 812 813 if(!(flags & CMS_DETACHED)) 814 { 815 flags &= ~CMS_STREAM; 816 CMS_set_detached(cms, 0); 817 } 818 819 if (CMS_final(cms, in, NULL, flags)) 820 return cms; 821 822 CMS_ContentInfo_free(cms); 823 return NULL; 824 } 825 826#else 827 828int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, 829 unsigned int flags) 830 { 831 CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM); 832 return 0; 833 } 834 835CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags) 836 { 837 CMSerr(CMS_F_CMS_COMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM); 838 return NULL; 839 } 840 841#endif 842