smime.c revision 160814
1/* smime.c */ 2/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL 3 * project. 4 */ 5/* ==================================================================== 6 * Copyright (c) 1999-2004 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 * This product includes cryptographic software written by Eric Young 54 * (eay@cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh@cryptsoft.com). 56 * 57 */ 58 59/* S/MIME utility function */ 60 61#include <stdio.h> 62#include <string.h> 63#include "apps.h" 64#include <openssl/crypto.h> 65#include <openssl/pem.h> 66#include <openssl/err.h> 67#include <openssl/x509_vfy.h> 68#include <openssl/x509v3.h> 69 70#undef PROG 71#define PROG smime_main 72static int save_certs(char *signerfile, STACK_OF(X509) *signers); 73static int smime_cb(int ok, X509_STORE_CTX *ctx); 74 75#define SMIME_OP 0x10 76#define SMIME_ENCRYPT (1 | SMIME_OP) 77#define SMIME_DECRYPT 2 78#define SMIME_SIGN (3 | SMIME_OP) 79#define SMIME_VERIFY 4 80#define SMIME_PK7OUT 5 81 82int MAIN(int, char **); 83 84int MAIN(int argc, char **argv) 85 { 86 ENGINE *e = NULL; 87 int operation = 0; 88 int ret = 0; 89 char **args; 90 const char *inmode = "r", *outmode = "w"; 91 char *infile = NULL, *outfile = NULL; 92 char *signerfile = NULL, *recipfile = NULL; 93 char *certfile = NULL, *keyfile = NULL, *contfile=NULL; 94 const EVP_CIPHER *cipher = NULL; 95 PKCS7 *p7 = NULL; 96 X509_STORE *store = NULL; 97 X509 *cert = NULL, *recip = NULL, *signer = NULL; 98 EVP_PKEY *key = NULL; 99 STACK_OF(X509) *encerts = NULL, *other = NULL; 100 BIO *in = NULL, *out = NULL, *indata = NULL; 101 int badarg = 0; 102 int flags = PKCS7_DETACHED; 103 char *to = NULL, *from = NULL, *subject = NULL; 104 char *CAfile = NULL, *CApath = NULL; 105 char *passargin = NULL, *passin = NULL; 106 char *inrand = NULL; 107 int need_rand = 0; 108 int informat = FORMAT_SMIME, outformat = FORMAT_SMIME; 109 int keyform = FORMAT_PEM; 110#ifndef OPENSSL_NO_ENGINE 111 char *engine=NULL; 112#endif 113 114 X509_VERIFY_PARAM *vpm = NULL; 115 116 args = argv + 1; 117 ret = 1; 118 119 apps_startup(); 120 121 if (bio_err == NULL) 122 { 123 if ((bio_err = BIO_new(BIO_s_file())) != NULL) 124 BIO_set_fp(bio_err, stderr, BIO_NOCLOSE|BIO_FP_TEXT); 125 } 126 127 if (!load_config(bio_err, NULL)) 128 goto end; 129 130 while (!badarg && *args && *args[0] == '-') 131 { 132 if (!strcmp (*args, "-encrypt")) 133 operation = SMIME_ENCRYPT; 134 else if (!strcmp (*args, "-decrypt")) 135 operation = SMIME_DECRYPT; 136 else if (!strcmp (*args, "-sign")) 137 operation = SMIME_SIGN; 138 else if (!strcmp (*args, "-verify")) 139 operation = SMIME_VERIFY; 140 else if (!strcmp (*args, "-pk7out")) 141 operation = SMIME_PK7OUT; 142#ifndef OPENSSL_NO_DES 143 else if (!strcmp (*args, "-des3")) 144 cipher = EVP_des_ede3_cbc(); 145 else if (!strcmp (*args, "-des")) 146 cipher = EVP_des_cbc(); 147#endif 148#ifndef OPENSSL_NO_RC2 149 else if (!strcmp (*args, "-rc2-40")) 150 cipher = EVP_rc2_40_cbc(); 151 else if (!strcmp (*args, "-rc2-128")) 152 cipher = EVP_rc2_cbc(); 153 else if (!strcmp (*args, "-rc2-64")) 154 cipher = EVP_rc2_64_cbc(); 155#endif 156#ifndef OPENSSL_NO_AES 157 else if (!strcmp(*args,"-aes128")) 158 cipher = EVP_aes_128_cbc(); 159 else if (!strcmp(*args,"-aes192")) 160 cipher = EVP_aes_192_cbc(); 161 else if (!strcmp(*args,"-aes256")) 162 cipher = EVP_aes_256_cbc(); 163#endif 164 else if (!strcmp (*args, "-text")) 165 flags |= PKCS7_TEXT; 166 else if (!strcmp (*args, "-nointern")) 167 flags |= PKCS7_NOINTERN; 168 else if (!strcmp (*args, "-noverify")) 169 flags |= PKCS7_NOVERIFY; 170 else if (!strcmp (*args, "-nochain")) 171 flags |= PKCS7_NOCHAIN; 172 else if (!strcmp (*args, "-nocerts")) 173 flags |= PKCS7_NOCERTS; 174 else if (!strcmp (*args, "-noattr")) 175 flags |= PKCS7_NOATTR; 176 else if (!strcmp (*args, "-nodetach")) 177 flags &= ~PKCS7_DETACHED; 178 else if (!strcmp (*args, "-nosmimecap")) 179 flags |= PKCS7_NOSMIMECAP; 180 else if (!strcmp (*args, "-binary")) 181 flags |= PKCS7_BINARY; 182 else if (!strcmp (*args, "-nosigs")) 183 flags |= PKCS7_NOSIGS; 184 else if (!strcmp (*args, "-nooldmime")) 185 flags |= PKCS7_NOOLDMIMETYPE; 186 else if (!strcmp (*args, "-crlfeol")) 187 flags |= PKCS7_CRLFEOL; 188 else if (!strcmp(*args,"-rand")) 189 { 190 if (args[1]) 191 { 192 args++; 193 inrand = *args; 194 } 195 else 196 badarg = 1; 197 need_rand = 1; 198 } 199#ifndef OPENSSL_NO_ENGINE 200 else if (!strcmp(*args,"-engine")) 201 { 202 if (args[1]) 203 { 204 args++; 205 engine = *args; 206 } 207 else badarg = 1; 208 } 209#endif 210 else if (!strcmp(*args,"-passin")) 211 { 212 if (args[1]) 213 { 214 args++; 215 passargin = *args; 216 } 217 else 218 badarg = 1; 219 } 220 else if (!strcmp (*args, "-to")) 221 { 222 if (args[1]) 223 { 224 args++; 225 to = *args; 226 } 227 else 228 badarg = 1; 229 } 230 else if (!strcmp (*args, "-from")) 231 { 232 if (args[1]) 233 { 234 args++; 235 from = *args; 236 } 237 else badarg = 1; 238 } 239 else if (!strcmp (*args, "-subject")) 240 { 241 if (args[1]) 242 { 243 args++; 244 subject = *args; 245 } 246 else 247 badarg = 1; 248 } 249 else if (!strcmp (*args, "-signer")) 250 { 251 if (args[1]) 252 { 253 args++; 254 signerfile = *args; 255 } 256 else 257 badarg = 1; 258 } 259 else if (!strcmp (*args, "-recip")) 260 { 261 if (args[1]) 262 { 263 args++; 264 recipfile = *args; 265 } 266 else badarg = 1; 267 } 268 else if (!strcmp (*args, "-inkey")) 269 { 270 if (args[1]) 271 { 272 args++; 273 keyfile = *args; 274 } 275 else 276 badarg = 1; 277 } 278 else if (!strcmp (*args, "-keyform")) 279 { 280 if (args[1]) 281 { 282 args++; 283 keyform = str2fmt(*args); 284 } 285 else 286 badarg = 1; 287 } 288 else if (!strcmp (*args, "-certfile")) 289 { 290 if (args[1]) 291 { 292 args++; 293 certfile = *args; 294 } 295 else 296 badarg = 1; 297 } 298 else if (!strcmp (*args, "-CAfile")) 299 { 300 if (args[1]) 301 { 302 args++; 303 CAfile = *args; 304 } 305 else 306 badarg = 1; 307 } 308 else if (!strcmp (*args, "-CApath")) 309 { 310 if (args[1]) 311 { 312 args++; 313 CApath = *args; 314 } 315 else 316 badarg = 1; 317 } 318 else if (!strcmp (*args, "-in")) 319 { 320 if (args[1]) 321 { 322 args++; 323 infile = *args; 324 } 325 else 326 badarg = 1; 327 } 328 else if (!strcmp (*args, "-inform")) 329 { 330 if (args[1]) 331 { 332 args++; 333 informat = str2fmt(*args); 334 } 335 else 336 badarg = 1; 337 } 338 else if (!strcmp (*args, "-outform")) 339 { 340 if (args[1]) 341 { 342 args++; 343 outformat = str2fmt(*args); 344 } 345 else 346 badarg = 1; 347 } 348 else if (!strcmp (*args, "-out")) 349 { 350 if (args[1]) 351 { 352 args++; 353 outfile = *args; 354 } 355 else 356 badarg = 1; 357 } 358 else if (!strcmp (*args, "-content")) 359 { 360 if (args[1]) 361 { 362 args++; 363 contfile = *args; 364 } 365 else 366 badarg = 1; 367 } 368 else if (args_verify(&args, NULL, &badarg, bio_err, &vpm)) 369 continue; 370 else 371 badarg = 1; 372 args++; 373 } 374 375 376 if (operation == SMIME_SIGN) 377 { 378 if (!signerfile) 379 { 380 BIO_printf(bio_err, "No signer certificate specified\n"); 381 badarg = 1; 382 } 383 need_rand = 1; 384 } 385 else if (operation == SMIME_DECRYPT) 386 { 387 if (!recipfile && !keyfile) 388 { 389 BIO_printf(bio_err, "No recipient certificate or key specified\n"); 390 badarg = 1; 391 } 392 } 393 else if (operation == SMIME_ENCRYPT) 394 { 395 if (!*args) 396 { 397 BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); 398 badarg = 1; 399 } 400 need_rand = 1; 401 } 402 else if (!operation) 403 badarg = 1; 404 405 if (badarg) 406 { 407 BIO_printf (bio_err, "Usage smime [options] cert.pem ...\n"); 408 BIO_printf (bio_err, "where options are\n"); 409 BIO_printf (bio_err, "-encrypt encrypt message\n"); 410 BIO_printf (bio_err, "-decrypt decrypt encrypted message\n"); 411 BIO_printf (bio_err, "-sign sign message\n"); 412 BIO_printf (bio_err, "-verify verify signed message\n"); 413 BIO_printf (bio_err, "-pk7out output PKCS#7 structure\n"); 414#ifndef OPENSSL_NO_DES 415 BIO_printf (bio_err, "-des3 encrypt with triple DES\n"); 416 BIO_printf (bio_err, "-des encrypt with DES\n"); 417#endif 418#ifndef OPENSSL_NO_RC2 419 BIO_printf (bio_err, "-rc2-40 encrypt with RC2-40 (default)\n"); 420 BIO_printf (bio_err, "-rc2-64 encrypt with RC2-64\n"); 421 BIO_printf (bio_err, "-rc2-128 encrypt with RC2-128\n"); 422#endif 423#ifndef OPENSSL_NO_AES 424 BIO_printf (bio_err, "-aes128, -aes192, -aes256\n"); 425 BIO_printf (bio_err, " encrypt PEM output with cbc aes\n"); 426#endif 427 BIO_printf (bio_err, "-nointern don't search certificates in message for signer\n"); 428 BIO_printf (bio_err, "-nosigs don't verify message signature\n"); 429 BIO_printf (bio_err, "-noverify don't verify signers certificate\n"); 430 BIO_printf (bio_err, "-nocerts don't include signers certificate when signing\n"); 431 BIO_printf (bio_err, "-nodetach use opaque signing\n"); 432 BIO_printf (bio_err, "-noattr don't include any signed attributes\n"); 433 BIO_printf (bio_err, "-binary don't translate message to text\n"); 434 BIO_printf (bio_err, "-certfile file other certificates file\n"); 435 BIO_printf (bio_err, "-signer file signer certificate file\n"); 436 BIO_printf (bio_err, "-recip file recipient certificate file for decryption\n"); 437 BIO_printf (bio_err, "-in file input file\n"); 438 BIO_printf (bio_err, "-inform arg input format SMIME (default), PEM or DER\n"); 439 BIO_printf (bio_err, "-inkey file input private key (if not signer or recipient)\n"); 440 BIO_printf (bio_err, "-keyform arg input private key format (PEM or ENGINE)\n"); 441 BIO_printf (bio_err, "-out file output file\n"); 442 BIO_printf (bio_err, "-outform arg output format SMIME (default), PEM or DER\n"); 443 BIO_printf (bio_err, "-content file supply or override content for detached signature\n"); 444 BIO_printf (bio_err, "-to addr to address\n"); 445 BIO_printf (bio_err, "-from ad from address\n"); 446 BIO_printf (bio_err, "-subject s subject\n"); 447 BIO_printf (bio_err, "-text include or delete text MIME headers\n"); 448 BIO_printf (bio_err, "-CApath dir trusted certificates directory\n"); 449 BIO_printf (bio_err, "-CAfile file trusted certificates file\n"); 450 BIO_printf (bio_err, "-crl_check check revocation status of signer's certificate using CRLs\n"); 451 BIO_printf (bio_err, "-crl_check_all check revocation status of signer's certificate chain using CRLs\n"); 452#ifndef OPENSSL_NO_ENGINE 453 BIO_printf (bio_err, "-engine e use engine e, possibly a hardware device.\n"); 454#endif 455 BIO_printf (bio_err, "-passin arg input file pass phrase source\n"); 456 BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); 457 BIO_printf(bio_err, " load the file (or the files in the directory) into\n"); 458 BIO_printf(bio_err, " the random number generator\n"); 459 BIO_printf (bio_err, "cert.pem recipient certificate(s) for encryption\n"); 460 goto end; 461 } 462 463#ifndef OPENSSL_NO_ENGINE 464 e = setup_engine(bio_err, engine, 0); 465#endif 466 467 if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) 468 { 469 BIO_printf(bio_err, "Error getting password\n"); 470 goto end; 471 } 472 473 if (need_rand) 474 { 475 app_RAND_load_file(NULL, bio_err, (inrand != NULL)); 476 if (inrand != NULL) 477 BIO_printf(bio_err,"%ld semi-random bytes loaded\n", 478 app_RAND_load_files(inrand)); 479 } 480 481 ret = 2; 482 483 if (operation != SMIME_SIGN) 484 flags &= ~PKCS7_DETACHED; 485 486 if (operation & SMIME_OP) 487 { 488 if (flags & PKCS7_BINARY) 489 inmode = "rb"; 490 if (outformat == FORMAT_ASN1) 491 outmode = "wb"; 492 } 493 else 494 { 495 if (flags & PKCS7_BINARY) 496 outmode = "wb"; 497 if (informat == FORMAT_ASN1) 498 inmode = "rb"; 499 } 500 501 if (operation == SMIME_ENCRYPT) 502 { 503 if (!cipher) 504 { 505#ifndef OPENSSL_NO_RC2 506 cipher = EVP_rc2_40_cbc(); 507#else 508 BIO_printf(bio_err, "No cipher selected\n"); 509 goto end; 510#endif 511 } 512 encerts = sk_X509_new_null(); 513 while (*args) 514 { 515 if (!(cert = load_cert(bio_err,*args,FORMAT_PEM, 516 NULL, e, "recipient certificate file"))) 517 { 518#if 0 /* An appropriate message is already printed */ 519 BIO_printf(bio_err, "Can't read recipient certificate file %s\n", *args); 520#endif 521 goto end; 522 } 523 sk_X509_push(encerts, cert); 524 cert = NULL; 525 args++; 526 } 527 } 528 529 if (signerfile && (operation == SMIME_SIGN)) 530 { 531 if (!(signer = load_cert(bio_err,signerfile,FORMAT_PEM, NULL, 532 e, "signer certificate"))) 533 { 534#if 0 /* An appropri message has already been printed */ 535 BIO_printf(bio_err, "Can't read signer certificate file %s\n", signerfile); 536#endif 537 goto end; 538 } 539 } 540 541 if (certfile) 542 { 543 if (!(other = load_certs(bio_err,certfile,FORMAT_PEM, NULL, 544 e, "certificate file"))) 545 { 546#if 0 /* An appropriate message has already been printed */ 547 BIO_printf(bio_err, "Can't read certificate file %s\n", certfile); 548#endif 549 ERR_print_errors(bio_err); 550 goto end; 551 } 552 } 553 554 if (recipfile && (operation == SMIME_DECRYPT)) 555 { 556 if (!(recip = load_cert(bio_err,recipfile,FORMAT_PEM,NULL, 557 e, "recipient certificate file"))) 558 { 559#if 0 /* An appropriate message has alrady been printed */ 560 BIO_printf(bio_err, "Can't read recipient certificate file %s\n", recipfile); 561#endif 562 ERR_print_errors(bio_err); 563 goto end; 564 } 565 } 566 567 if (operation == SMIME_DECRYPT) 568 { 569 if (!keyfile) 570 keyfile = recipfile; 571 } 572 else if (operation == SMIME_SIGN) 573 { 574 if (!keyfile) 575 keyfile = signerfile; 576 } 577 else keyfile = NULL; 578 579 if (keyfile) 580 { 581 key = load_key(bio_err, keyfile, keyform, 0, passin, e, 582 "signing key file"); 583 if (!key) 584 goto end; 585 } 586 587 if (infile) 588 { 589 if (!(in = BIO_new_file(infile, inmode))) 590 { 591 BIO_printf (bio_err, 592 "Can't open input file %s\n", infile); 593 goto end; 594 } 595 } 596 else 597 in = BIO_new_fp(stdin, BIO_NOCLOSE); 598 599 if (outfile) 600 { 601 if (!(out = BIO_new_file(outfile, outmode))) 602 { 603 BIO_printf (bio_err, 604 "Can't open output file %s\n", outfile); 605 goto end; 606 } 607 } 608 else 609 { 610 out = BIO_new_fp(stdout, BIO_NOCLOSE); 611#ifdef OPENSSL_SYS_VMS 612 { 613 BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 614 out = BIO_push(tmpbio, out); 615 } 616#endif 617 } 618 619 if (operation == SMIME_VERIFY) 620 { 621 if (!(store = setup_verify(bio_err, CAfile, CApath))) 622 goto end; 623 X509_STORE_set_verify_cb_func(store, smime_cb); 624 if (vpm) 625 X509_STORE_set1_param(store, vpm); 626 } 627 628 629 ret = 3; 630 631 if (operation == SMIME_ENCRYPT) 632 p7 = PKCS7_encrypt(encerts, in, cipher, flags); 633 else if (operation == SMIME_SIGN) 634 { 635 /* If detached data and SMIME output enable partial 636 * signing. 637 */ 638 if ((flags & PKCS7_DETACHED) && (outformat == FORMAT_SMIME)) 639 flags |= PKCS7_STREAM; 640 p7 = PKCS7_sign(signer, key, other, in, flags); 641 /* Don't need to rewind for partial signing */ 642 if (!(flags & PKCS7_STREAM) && (BIO_reset(in) != 0)) 643 { 644 BIO_printf(bio_err, "Can't rewind input file\n"); 645 goto end; 646 } 647 } 648 else 649 { 650 if (informat == FORMAT_SMIME) 651 p7 = SMIME_read_PKCS7(in, &indata); 652 else if (informat == FORMAT_PEM) 653 p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); 654 else if (informat == FORMAT_ASN1) 655 p7 = d2i_PKCS7_bio(in, NULL); 656 else 657 { 658 BIO_printf(bio_err, "Bad input format for PKCS#7 file\n"); 659 goto end; 660 } 661 662 if (!p7) 663 { 664 BIO_printf(bio_err, "Error reading S/MIME message\n"); 665 goto end; 666 } 667 if (contfile) 668 { 669 BIO_free(indata); 670 if (!(indata = BIO_new_file(contfile, "rb"))) 671 { 672 BIO_printf(bio_err, "Can't read content file %s\n", contfile); 673 goto end; 674 } 675 } 676 } 677 678 if (!p7) 679 { 680 BIO_printf(bio_err, "Error creating PKCS#7 structure\n"); 681 goto end; 682 } 683 684 ret = 4; 685 if (operation == SMIME_DECRYPT) 686 { 687 if (!PKCS7_decrypt(p7, key, recip, out, flags)) 688 { 689 BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n"); 690 goto end; 691 } 692 } 693 else if (operation == SMIME_VERIFY) 694 { 695 STACK_OF(X509) *signers; 696 if (PKCS7_verify(p7, other, store, indata, out, flags)) 697 BIO_printf(bio_err, "Verification successful\n"); 698 else 699 { 700 BIO_printf(bio_err, "Verification failure\n"); 701 goto end; 702 } 703 signers = PKCS7_get0_signers(p7, other, flags); 704 if (!save_certs(signerfile, signers)) 705 { 706 BIO_printf(bio_err, "Error writing signers to %s\n", 707 signerfile); 708 ret = 5; 709 goto end; 710 } 711 sk_X509_free(signers); 712 } 713 else if (operation == SMIME_PK7OUT) 714 PEM_write_bio_PKCS7(out, p7); 715 else 716 { 717 if (to) 718 BIO_printf(out, "To: %s\n", to); 719 if (from) 720 BIO_printf(out, "From: %s\n", from); 721 if (subject) 722 BIO_printf(out, "Subject: %s\n", subject); 723 if (outformat == FORMAT_SMIME) 724 SMIME_write_PKCS7(out, p7, in, flags); 725 else if (outformat == FORMAT_PEM) 726 PEM_write_bio_PKCS7(out,p7); 727 else if (outformat == FORMAT_ASN1) 728 i2d_PKCS7_bio(out,p7); 729 else 730 { 731 BIO_printf(bio_err, "Bad output format for PKCS#7 file\n"); 732 goto end; 733 } 734 } 735 ret = 0; 736end: 737 if (need_rand) 738 app_RAND_write_file(NULL, bio_err); 739 if (ret) ERR_print_errors(bio_err); 740 sk_X509_pop_free(encerts, X509_free); 741 sk_X509_pop_free(other, X509_free); 742 if (vpm) 743 X509_VERIFY_PARAM_free(vpm); 744 X509_STORE_free(store); 745 X509_free(cert); 746 X509_free(recip); 747 X509_free(signer); 748 EVP_PKEY_free(key); 749 PKCS7_free(p7); 750 BIO_free(in); 751 BIO_free(indata); 752 BIO_free_all(out); 753 if (passin) OPENSSL_free(passin); 754 return (ret); 755} 756 757static int save_certs(char *signerfile, STACK_OF(X509) *signers) 758 { 759 int i; 760 BIO *tmp; 761 if (!signerfile) 762 return 1; 763 tmp = BIO_new_file(signerfile, "w"); 764 if (!tmp) return 0; 765 for(i = 0; i < sk_X509_num(signers); i++) 766 PEM_write_bio_X509(tmp, sk_X509_value(signers, i)); 767 BIO_free(tmp); 768 return 1; 769 } 770 771 772/* Minimal callback just to output policy info (if any) */ 773 774static int smime_cb(int ok, X509_STORE_CTX *ctx) 775 { 776 int error; 777 778 error = X509_STORE_CTX_get_error(ctx); 779 780 if ((error != X509_V_ERR_NO_EXPLICIT_POLICY) 781 && ((error != X509_V_OK) || (ok != 2))) 782 return ok; 783 784 policies_print(NULL, ctx); 785 786 return ok; 787 788 } 789