cms_smime.c revision 296465
1/* crypto/cms/cms_smime.c */ 2/* 3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 4 * project. 5 */ 6/* ==================================================================== 7 * Copyright (c) 2008 The OpenSSL Project. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. All advertising materials mentioning features or use of this 22 * software must display the following acknowledgment: 23 * "This product includes software developed by the OpenSSL Project 24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25 * 26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27 * endorse or promote products derived from this software without 28 * prior written permission. For written permission, please contact 29 * licensing@OpenSSL.org. 30 * 31 * 5. Products derived from this software may not be called "OpenSSL" 32 * nor may "OpenSSL" appear in their names without prior written 33 * permission of the OpenSSL Project. 34 * 35 * 6. Redistributions of any form whatsoever must retain the following 36 * acknowledgment: 37 * "This product includes software developed by the OpenSSL Project 38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51 * OF THE POSSIBILITY OF SUCH DAMAGE. 52 * ==================================================================== 53 */ 54 55#include "cryptlib.h" 56#include <openssl/asn1t.h> 57#include <openssl/x509.h> 58#include <openssl/x509v3.h> 59#include <openssl/err.h> 60#include <openssl/cms.h> 61#include "cms_lcl.h" 62 63static int cms_copy_content(BIO *out, BIO *in, unsigned int flags) 64{ 65 unsigned char buf[4096]; 66 int r = 0, i; 67 BIO *tmpout = NULL; 68 69 if (out == NULL) 70 tmpout = BIO_new(BIO_s_null()); 71 else if (flags & CMS_TEXT) { 72 tmpout = BIO_new(BIO_s_mem()); 73 BIO_set_mem_eof_return(tmpout, 0); 74 } else 75 tmpout = out; 76 77 if (!tmpout) { 78 CMSerr(CMS_F_CMS_COPY_CONTENT, ERR_R_MALLOC_FAILURE); 79 goto err; 80 } 81 82 /* Read all content through chain to process digest, decrypt etc */ 83 for (;;) { 84 i = BIO_read(in, buf, sizeof(buf)); 85 if (i <= 0) { 86 if (BIO_method_type(in) == BIO_TYPE_CIPHER) { 87 if (!BIO_get_cipher_status(in)) 88 goto err; 89 } 90 if (i < 0) 91 goto err; 92 break; 93 } 94 95 if (tmpout && (BIO_write(tmpout, buf, i) != i)) 96 goto err; 97 } 98 99 if (flags & CMS_TEXT) { 100 if (!SMIME_text(tmpout, out)) { 101 CMSerr(CMS_F_CMS_COPY_CONTENT, CMS_R_SMIME_TEXT_ERROR); 102 goto err; 103 } 104 } 105 106 r = 1; 107 108 err: 109 if (tmpout && (tmpout != out)) 110 BIO_free(tmpout); 111 return r; 112 113} 114 115static int check_content(CMS_ContentInfo *cms) 116{ 117 ASN1_OCTET_STRING **pos = CMS_get0_content(cms); 118 if (!pos || !*pos) { 119 CMSerr(CMS_F_CHECK_CONTENT, CMS_R_NO_CONTENT); 120 return 0; 121 } 122 return 1; 123} 124 125static void do_free_upto(BIO *f, BIO *upto) 126{ 127 if (upto) { 128 BIO *tbio; 129 do { 130 tbio = BIO_pop(f); 131 BIO_free(f); 132 f = tbio; 133 } 134 while (f && f != upto); 135 } else 136 BIO_free_all(f); 137} 138 139int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags) 140{ 141 BIO *cont; 142 int r; 143 if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_data) { 144 CMSerr(CMS_F_CMS_DATA, CMS_R_TYPE_NOT_DATA); 145 return 0; 146 } 147 cont = CMS_dataInit(cms, NULL); 148 if (!cont) 149 return 0; 150 r = cms_copy_content(out, cont, flags); 151 BIO_free_all(cont); 152 return r; 153} 154 155CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags) 156{ 157 CMS_ContentInfo *cms; 158 cms = cms_Data_create(); 159 if (!cms) 160 return NULL; 161 162 if (CMS_final(cms, in, NULL, flags)) 163 return cms; 164 165 CMS_ContentInfo_free(cms); 166 167 return NULL; 168} 169 170int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out, 171 unsigned int flags) 172{ 173 BIO *cont; 174 int r; 175 if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_digest) { 176 CMSerr(CMS_F_CMS_DIGEST_VERIFY, CMS_R_TYPE_NOT_DIGESTED_DATA); 177 return 0; 178 } 179 180 if (!dcont && !check_content(cms)) 181 return 0; 182 183 cont = CMS_dataInit(cms, dcont); 184 if (!cont) 185 return 0; 186 r = cms_copy_content(out, cont, flags); 187 if (r) 188 r = cms_DigestedData_do_final(cms, cont, 1); 189 do_free_upto(cont, dcont); 190 return r; 191} 192 193CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md, 194 unsigned int flags) 195{ 196 CMS_ContentInfo *cms; 197 if (!md) 198 md = EVP_sha1(); 199 cms = cms_DigestedData_create(md); 200 if (!cms) 201 return NULL; 202 203 if (!(flags & CMS_DETACHED)) { 204 flags &= ~CMS_STREAM; 205 CMS_set_detached(cms, 0); 206 } 207 208 if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags)) 209 return cms; 210 211 CMS_ContentInfo_free(cms); 212 return NULL; 213} 214 215int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms, 216 const unsigned char *key, size_t keylen, 217 BIO *dcont, BIO *out, unsigned int flags) 218{ 219 BIO *cont; 220 int r; 221 if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_encrypted) { 222 CMSerr(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT, 223 CMS_R_TYPE_NOT_ENCRYPTED_DATA); 224 return 0; 225 } 226 227 if (!dcont && !check_content(cms)) 228 return 0; 229 230 if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0) 231 return 0; 232 cont = CMS_dataInit(cms, dcont); 233 if (!cont) 234 return 0; 235 r = cms_copy_content(out, cont, flags); 236 do_free_upto(cont, dcont); 237 return r; 238} 239 240CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher, 241 const unsigned char *key, 242 size_t keylen, unsigned int flags) 243{ 244 CMS_ContentInfo *cms; 245 if (!cipher) { 246 CMSerr(CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT, CMS_R_NO_CIPHER); 247 return NULL; 248 } 249 cms = CMS_ContentInfo_new(); 250 if (!cms) 251 return NULL; 252 if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen)) 253 return NULL; 254 255 if (!(flags & CMS_DETACHED)) { 256 flags &= ~CMS_STREAM; 257 CMS_set_detached(cms, 0); 258 } 259 260 if ((flags & (CMS_STREAM | CMS_PARTIAL)) 261 || CMS_final(cms, in, NULL, flags)) 262 return cms; 263 264 CMS_ContentInfo_free(cms); 265 return NULL; 266} 267 268static int cms_signerinfo_verify_cert(CMS_SignerInfo *si, 269 X509_STORE *store, 270 STACK_OF(X509) *certs, 271 STACK_OF(X509_CRL) *crls, 272 unsigned int flags) 273{ 274 X509_STORE_CTX ctx; 275 X509 *signer; 276 int i, j, r = 0; 277 CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL); 278 if (!X509_STORE_CTX_init(&ctx, store, signer, certs)) { 279 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT, CMS_R_STORE_INIT_ERROR); 280 goto err; 281 } 282 X509_STORE_CTX_set_default(&ctx, "smime_sign"); 283 if (crls) 284 X509_STORE_CTX_set0_crls(&ctx, crls); 285 286 i = X509_verify_cert(&ctx); 287 if (i <= 0) { 288 j = X509_STORE_CTX_get_error(&ctx); 289 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT, 290 CMS_R_CERTIFICATE_VERIFY_ERROR); 291 ERR_add_error_data(2, "Verify error:", 292 X509_verify_cert_error_string(j)); 293 goto err; 294 } 295 r = 1; 296 err: 297 X509_STORE_CTX_cleanup(&ctx); 298 return r; 299 300} 301 302int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, 303 X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags) 304{ 305 CMS_SignerInfo *si; 306 STACK_OF(CMS_SignerInfo) *sinfos; 307 STACK_OF(X509) *cms_certs = NULL; 308 STACK_OF(X509_CRL) *crls = NULL; 309 X509 *signer; 310 int i, scount = 0, ret = 0; 311 BIO *cmsbio = NULL, *tmpin = NULL; 312 313 if (!dcont && !check_content(cms)) 314 return 0; 315 316 /* Attempt to find all signer certificates */ 317 318 sinfos = CMS_get0_SignerInfos(cms); 319 320 if (sk_CMS_SignerInfo_num(sinfos) <= 0) { 321 CMSerr(CMS_F_CMS_VERIFY, CMS_R_NO_SIGNERS); 322 goto err; 323 } 324 325 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { 326 si = sk_CMS_SignerInfo_value(sinfos, i); 327 CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL); 328 if (signer) 329 scount++; 330 } 331 332 if (scount != sk_CMS_SignerInfo_num(sinfos)) 333 scount += CMS_set1_signers_certs(cms, certs, flags); 334 335 if (scount != sk_CMS_SignerInfo_num(sinfos)) { 336 CMSerr(CMS_F_CMS_VERIFY, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND); 337 goto err; 338 } 339 340 /* Attempt to verify all signers certs */ 341 342 if (!(flags & CMS_NO_SIGNER_CERT_VERIFY)) { 343 cms_certs = CMS_get1_certs(cms); 344 if (!(flags & CMS_NOCRL)) 345 crls = CMS_get1_crls(cms); 346 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { 347 si = sk_CMS_SignerInfo_value(sinfos, i); 348 if (!cms_signerinfo_verify_cert(si, store, 349 cms_certs, crls, flags)) 350 goto err; 351 } 352 } 353 354 /* Attempt to verify all SignerInfo signed attribute signatures */ 355 356 if (!(flags & CMS_NO_ATTR_VERIFY)) { 357 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { 358 si = sk_CMS_SignerInfo_value(sinfos, i); 359 if (CMS_signed_get_attr_count(si) < 0) 360 continue; 361 if (CMS_SignerInfo_verify(si) <= 0) 362 goto err; 363 } 364 } 365 366 /* 367 * Performance optimization: if the content is a memory BIO then store 368 * its contents in a temporary read only memory BIO. This avoids 369 * potentially large numbers of slow copies of data which will occur when 370 * reading from a read write memory BIO when signatures are calculated. 371 */ 372 373 if (dcont && (BIO_method_type(dcont) == BIO_TYPE_MEM)) { 374 char *ptr; 375 long len; 376 len = BIO_get_mem_data(dcont, &ptr); 377 tmpin = BIO_new_mem_buf(ptr, len); 378 if (tmpin == NULL) { 379 CMSerr(CMS_F_CMS_VERIFY, ERR_R_MALLOC_FAILURE); 380 return 0; 381 } 382 } else 383 tmpin = dcont; 384 385 cmsbio = CMS_dataInit(cms, tmpin); 386 if (!cmsbio) 387 goto err; 388 389 if (!cms_copy_content(out, cmsbio, flags)) 390 goto err; 391 392 if (!(flags & CMS_NO_CONTENT_VERIFY)) { 393 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { 394 si = sk_CMS_SignerInfo_value(sinfos, i); 395 if (CMS_SignerInfo_verify_content(si, cmsbio) <= 0) { 396 CMSerr(CMS_F_CMS_VERIFY, CMS_R_CONTENT_VERIFY_ERROR); 397 goto err; 398 } 399 } 400 } 401 402 ret = 1; 403 404 err: 405 406 if (dcont && (tmpin == dcont)) 407 do_free_upto(cmsbio, dcont); 408 else 409 BIO_free_all(cmsbio); 410 411 if (cms_certs) 412 sk_X509_pop_free(cms_certs, X509_free); 413 if (crls) 414 sk_X509_CRL_pop_free(crls, X509_CRL_free); 415 416 return ret; 417} 418 419int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms, 420 STACK_OF(X509) *certs, 421 X509_STORE *store, unsigned int flags) 422{ 423 int r; 424 r = CMS_verify(rcms, certs, store, NULL, NULL, flags); 425 if (r <= 0) 426 return r; 427 return cms_Receipt_verify(rcms, ocms); 428} 429 430CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, 431 STACK_OF(X509) *certs, BIO *data, 432 unsigned int flags) 433{ 434 CMS_ContentInfo *cms; 435 int i; 436 437 cms = CMS_ContentInfo_new(); 438 if (!cms || !CMS_SignedData_init(cms)) 439 goto merr; 440 441 if (pkey && !CMS_add1_signer(cms, signcert, pkey, NULL, flags)) { 442 CMSerr(CMS_F_CMS_SIGN, CMS_R_ADD_SIGNER_ERROR); 443 goto err; 444 } 445 446 for (i = 0; i < sk_X509_num(certs); i++) { 447 X509 *x = sk_X509_value(certs, i); 448 if (!CMS_add1_cert(cms, x)) 449 goto merr; 450 } 451 452 if (!(flags & CMS_DETACHED)) { 453 flags &= ~CMS_STREAM; 454 CMS_set_detached(cms, 0); 455 } 456 457 if ((flags & (CMS_STREAM | CMS_PARTIAL)) 458 || CMS_final(cms, data, NULL, flags)) 459 return cms; 460 else 461 goto err; 462 463 merr: 464 CMSerr(CMS_F_CMS_SIGN, ERR_R_MALLOC_FAILURE); 465 466 err: 467 if (cms) 468 CMS_ContentInfo_free(cms); 469 return NULL; 470} 471 472CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si, 473 X509 *signcert, EVP_PKEY *pkey, 474 STACK_OF(X509) *certs, unsigned int flags) 475{ 476 CMS_SignerInfo *rct_si; 477 CMS_ContentInfo *cms = NULL; 478 ASN1_OCTET_STRING **pos, *os; 479 BIO *rct_cont = NULL; 480 int r = 0; 481 482 flags &= ~CMS_STREAM; 483 /* Not really detached but avoids content being allocated */ 484 flags |= CMS_PARTIAL | CMS_BINARY | CMS_DETACHED; 485 if (!pkey || !signcert) { 486 CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_NO_KEY_OR_CERT); 487 return NULL; 488 } 489 490 /* Initialize signed data */ 491 492 cms = CMS_sign(NULL, NULL, certs, NULL, flags); 493 if (!cms) 494 goto err; 495 496 /* Set inner content type to signed receipt */ 497 if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt))) 498 goto err; 499 500 rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags); 501 if (!rct_si) { 502 CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_ADD_SIGNER_ERROR); 503 goto err; 504 } 505 506 os = cms_encode_Receipt(si); 507 508 if (!os) 509 goto err; 510 511 /* Set content to digest */ 512 rct_cont = BIO_new_mem_buf(os->data, os->length); 513 if (!rct_cont) 514 goto err; 515 516 /* Add msgSigDigest attribute */ 517 518 if (!cms_msgSigDigest_add1(rct_si, si)) 519 goto err; 520 521 /* Finalize structure */ 522 if (!CMS_final(cms, rct_cont, NULL, flags)) 523 goto err; 524 525 /* Set embedded content */ 526 pos = CMS_get0_content(cms); 527 *pos = os; 528 529 r = 1; 530 531 err: 532 if (rct_cont) 533 BIO_free(rct_cont); 534 if (r) 535 return cms; 536 CMS_ContentInfo_free(cms); 537 return NULL; 538 539} 540 541CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data, 542 const EVP_CIPHER *cipher, unsigned int flags) 543{ 544 CMS_ContentInfo *cms; 545 int i; 546 X509 *recip; 547 cms = CMS_EnvelopedData_create(cipher); 548 if (!cms) 549 goto merr; 550 for (i = 0; i < sk_X509_num(certs); i++) { 551 recip = sk_X509_value(certs, i); 552 if (!CMS_add1_recipient_cert(cms, recip, flags)) { 553 CMSerr(CMS_F_CMS_ENCRYPT, CMS_R_RECIPIENT_ERROR); 554 goto err; 555 } 556 } 557 558 if (!(flags & CMS_DETACHED)) { 559 flags &= ~CMS_STREAM; 560 CMS_set_detached(cms, 0); 561 } 562 563 if ((flags & (CMS_STREAM | CMS_PARTIAL)) 564 || CMS_final(cms, data, NULL, flags)) 565 return cms; 566 else 567 goto err; 568 569 merr: 570 CMSerr(CMS_F_CMS_ENCRYPT, ERR_R_MALLOC_FAILURE); 571 err: 572 if (cms) 573 CMS_ContentInfo_free(cms); 574 return NULL; 575} 576 577int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert) 578{ 579 STACK_OF(CMS_RecipientInfo) *ris; 580 CMS_RecipientInfo *ri; 581 int i, r; 582 int debug = 0, ri_match = 0; 583 ris = CMS_get0_RecipientInfos(cms); 584 if (ris) 585 debug = cms->d.envelopedData->encryptedContentInfo->debug; 586 for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) { 587 ri = sk_CMS_RecipientInfo_value(ris, i); 588 if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_TRANS) 589 continue; 590 ri_match = 1; 591 /* 592 * If we have a cert try matching RecipientInfo otherwise try them 593 * all. 594 */ 595 if (!cert || (CMS_RecipientInfo_ktri_cert_cmp(ri, cert) == 0)) { 596 CMS_RecipientInfo_set0_pkey(ri, pk); 597 r = CMS_RecipientInfo_decrypt(cms, ri); 598 CMS_RecipientInfo_set0_pkey(ri, NULL); 599 if (cert) { 600 /* 601 * If not debugging clear any error and return success to 602 * avoid leaking of information useful to MMA 603 */ 604 if (!debug) { 605 ERR_clear_error(); 606 return 1; 607 } 608 if (r > 0) 609 return 1; 610 CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_DECRYPT_ERROR); 611 return 0; 612 } 613 /* 614 * If no cert and not debugging don't leave loop after first 615 * successful decrypt. Always attempt to decrypt all recipients 616 * to avoid leaking timing of a successful decrypt. 617 */ 618 else if (r > 0 && debug) 619 return 1; 620 } 621 } 622 /* If no cert and not debugging always return success */ 623 if (ri_match && !cert && !debug) { 624 ERR_clear_error(); 625 return 1; 626 } 627 628 CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT); 629 return 0; 630 631} 632 633int CMS_decrypt_set1_key(CMS_ContentInfo *cms, 634 unsigned char *key, size_t keylen, 635 unsigned char *id, size_t idlen) 636{ 637 STACK_OF(CMS_RecipientInfo) *ris; 638 CMS_RecipientInfo *ri; 639 int i, r; 640 ris = CMS_get0_RecipientInfos(cms); 641 for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) { 642 ri = sk_CMS_RecipientInfo_value(ris, i); 643 if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK) 644 continue; 645 646 /* 647 * If we have an id try matching RecipientInfo otherwise try them 648 * all. 649 */ 650 if (!id || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) { 651 CMS_RecipientInfo_set0_key(ri, key, keylen); 652 r = CMS_RecipientInfo_decrypt(cms, ri); 653 CMS_RecipientInfo_set0_key(ri, NULL, 0); 654 if (r > 0) 655 return 1; 656 if (id) { 657 CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_DECRYPT_ERROR); 658 return 0; 659 } 660 ERR_clear_error(); 661 } 662 } 663 664 CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_NO_MATCHING_RECIPIENT); 665 return 0; 666 667} 668 669int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert, 670 BIO *dcont, BIO *out, unsigned int flags) 671{ 672 int r; 673 BIO *cont; 674 if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped) { 675 CMSerr(CMS_F_CMS_DECRYPT, CMS_R_TYPE_NOT_ENVELOPED_DATA); 676 return 0; 677 } 678 if (!dcont && !check_content(cms)) 679 return 0; 680 if (flags & CMS_DEBUG_DECRYPT) 681 cms->d.envelopedData->encryptedContentInfo->debug = 1; 682 else 683 cms->d.envelopedData->encryptedContentInfo->debug = 0; 684 if (!pk && !cert && !dcont && !out) 685 return 1; 686 if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert)) 687 return 0; 688 cont = CMS_dataInit(cms, dcont); 689 if (!cont) 690 return 0; 691 r = cms_copy_content(out, cont, flags); 692 do_free_upto(cont, dcont); 693 return r; 694} 695 696int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags) 697{ 698 BIO *cmsbio; 699 int ret = 0; 700 if (!(cmsbio = CMS_dataInit(cms, dcont))) { 701 CMSerr(CMS_F_CMS_FINAL, ERR_R_MALLOC_FAILURE); 702 return 0; 703 } 704 705 SMIME_crlf_copy(data, cmsbio, flags); 706 707 (void)BIO_flush(cmsbio); 708 709 if (!CMS_dataFinal(cms, cmsbio)) { 710 CMSerr(CMS_F_CMS_FINAL, CMS_R_CMS_DATAFINAL_ERROR); 711 goto err; 712 } 713 714 ret = 1; 715 716 err: 717 do_free_upto(cmsbio, dcont); 718 719 return ret; 720 721} 722 723#ifdef ZLIB 724 725int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, 726 unsigned int flags) 727{ 728 BIO *cont; 729 int r; 730 if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_id_smime_ct_compressedData) { 731 CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_TYPE_NOT_COMPRESSED_DATA); 732 return 0; 733 } 734 735 if (!dcont && !check_content(cms)) 736 return 0; 737 738 cont = CMS_dataInit(cms, dcont); 739 if (!cont) 740 return 0; 741 r = cms_copy_content(out, cont, flags); 742 do_free_upto(cont, dcont); 743 return r; 744} 745 746CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags) 747{ 748 CMS_ContentInfo *cms; 749 if (comp_nid <= 0) 750 comp_nid = NID_zlib_compression; 751 cms = cms_CompressedData_create(comp_nid); 752 if (!cms) 753 return NULL; 754 755 if (!(flags & CMS_DETACHED)) { 756 flags &= ~CMS_STREAM; 757 CMS_set_detached(cms, 0); 758 } 759 760 if (CMS_final(cms, in, NULL, flags)) 761 return cms; 762 763 CMS_ContentInfo_free(cms); 764 return NULL; 765} 766 767#else 768 769int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, 770 unsigned int flags) 771{ 772 CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM); 773 return 0; 774} 775 776CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags) 777{ 778 CMSerr(CMS_F_CMS_COMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM); 779 return NULL; 780} 781 782#endif 783