1 /* $OpenBSD: smime.c,v 1.10 2018/02/07 05:47:55 jsing Exp $ */ 2 /* Written by Dr Stephen N Henson (steve@openssl.org) 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 64 #include "apps.h" 65 66 #include <openssl/crypto.h> 67 #include <openssl/err.h> 68 #include <openssl/pem.h> 69 #include <openssl/x509_vfy.h> 70 #include <openssl/x509v3.h> 71 72 static int save_certs(char *signerfile, STACK_OF(X509) * signers); 73 static int smime_cb(int ok, X509_STORE_CTX * ctx); 74 75 #define SMIME_OP 0x10 76 #define SMIME_IP 0x20 77 #define SMIME_SIGNERS 0x40 78 #define SMIME_ENCRYPT (1 | SMIME_OP) 79 #define SMIME_DECRYPT (2 | SMIME_IP) 80 #define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS) 81 #define SMIME_VERIFY (4 | SMIME_IP) 82 #define SMIME_PK7OUT (5 | SMIME_IP | SMIME_OP) 83 #define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS) 84 85 int 86 smime_main(int argc, char **argv) 87 { 88 int operation = 0; 89 int ret = 0; 90 char **args; 91 const char *inmode = "r", *outmode = "w"; 92 char *infile = NULL, *outfile = NULL; 93 char *signerfile = NULL, *recipfile = NULL; 94 STACK_OF(OPENSSL_STRING) * sksigners = NULL, *skkeys = NULL; 95 char *certfile = NULL, *keyfile = NULL, *contfile = NULL; 96 const EVP_CIPHER *cipher = NULL; 97 PKCS7 *p7 = NULL; 98 X509_STORE *store = NULL; 99 X509 *cert = NULL, *recip = NULL, *signer = NULL; 100 EVP_PKEY *key = NULL; 101 STACK_OF(X509) * encerts = NULL, *other = NULL; 102 BIO *in = NULL, *out = NULL, *indata = NULL; 103 int badarg = 0; 104 int flags = PKCS7_DETACHED; 105 char *to = NULL, *from = NULL, *subject = NULL; 106 char *CAfile = NULL, *CApath = NULL; 107 char *passargin = NULL, *passin = NULL; 108 int indef = 0; 109 const EVP_MD *sign_md = NULL; 110 int informat = FORMAT_SMIME, outformat = FORMAT_SMIME; 111 int keyform = FORMAT_PEM; 112 113 X509_VERIFY_PARAM *vpm = NULL; 114 115 if (single_execution) { 116 if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { 117 perror("pledge"); 118 exit(1); 119 } 120 } 121 122 args = argv + 1; 123 ret = 1; 124 125 while (!badarg && *args && *args[0] == '-') { 126 if (!strcmp(*args, "-encrypt")) 127 operation = SMIME_ENCRYPT; 128 else if (!strcmp(*args, "-decrypt")) 129 operation = SMIME_DECRYPT; 130 else if (!strcmp(*args, "-sign")) 131 operation = SMIME_SIGN; 132 else if (!strcmp(*args, "-resign")) 133 operation = SMIME_RESIGN; 134 else if (!strcmp(*args, "-verify")) 135 operation = SMIME_VERIFY; 136 else if (!strcmp(*args, "-pk7out")) 137 operation = SMIME_PK7OUT; 138 #ifndef OPENSSL_NO_DES 139 else if (!strcmp(*args, "-des3")) 140 cipher = EVP_des_ede3_cbc(); 141 else if (!strcmp(*args, "-des")) 142 cipher = EVP_des_cbc(); 143 #endif 144 #ifndef OPENSSL_NO_RC2 145 else if (!strcmp(*args, "-rc2-40")) 146 cipher = EVP_rc2_40_cbc(); 147 else if (!strcmp(*args, "-rc2-128")) 148 cipher = EVP_rc2_cbc(); 149 else if (!strcmp(*args, "-rc2-64")) 150 cipher = EVP_rc2_64_cbc(); 151 #endif 152 #ifndef OPENSSL_NO_AES 153 else if (!strcmp(*args, "-aes128")) 154 cipher = EVP_aes_128_cbc(); 155 else if (!strcmp(*args, "-aes192")) 156 cipher = EVP_aes_192_cbc(); 157 else if (!strcmp(*args, "-aes256")) 158 cipher = EVP_aes_256_cbc(); 159 #endif 160 #ifndef OPENSSL_NO_CAMELLIA 161 else if (!strcmp(*args, "-camellia128")) 162 cipher = EVP_camellia_128_cbc(); 163 else if (!strcmp(*args, "-camellia192")) 164 cipher = EVP_camellia_192_cbc(); 165 else if (!strcmp(*args, "-camellia256")) 166 cipher = EVP_camellia_256_cbc(); 167 #endif 168 else if (!strcmp(*args, "-text")) 169 flags |= PKCS7_TEXT; 170 else if (!strcmp(*args, "-nointern")) 171 flags |= PKCS7_NOINTERN; 172 else if (!strcmp(*args, "-noverify")) 173 flags |= PKCS7_NOVERIFY; 174 else if (!strcmp(*args, "-nochain")) 175 flags |= PKCS7_NOCHAIN; 176 else if (!strcmp(*args, "-nocerts")) 177 flags |= PKCS7_NOCERTS; 178 else if (!strcmp(*args, "-noattr")) 179 flags |= PKCS7_NOATTR; 180 else if (!strcmp(*args, "-nodetach")) 181 flags &= ~PKCS7_DETACHED; 182 else if (!strcmp(*args, "-nosmimecap")) 183 flags |= PKCS7_NOSMIMECAP; 184 else if (!strcmp(*args, "-binary")) 185 flags |= PKCS7_BINARY; 186 else if (!strcmp(*args, "-nosigs")) 187 flags |= PKCS7_NOSIGS; 188 else if (!strcmp(*args, "-stream")) 189 indef = 1; 190 else if (!strcmp(*args, "-indef")) 191 indef = 1; 192 else if (!strcmp(*args, "-noindef")) 193 indef = 0; 194 else if (!strcmp(*args, "-nooldmime")) 195 flags |= PKCS7_NOOLDMIMETYPE; 196 else if (!strcmp(*args, "-crlfeol")) 197 flags |= PKCS7_CRLFEOL; 198 else if (!strcmp(*args, "-passin")) { 199 if (!args[1]) 200 goto argerr; 201 passargin = *++args; 202 } else if (!strcmp(*args, "-to")) { 203 if (!args[1]) 204 goto argerr; 205 to = *++args; 206 } else if (!strcmp(*args, "-from")) { 207 if (!args[1]) 208 goto argerr; 209 from = *++args; 210 } else if (!strcmp(*args, "-subject")) { 211 if (!args[1]) 212 goto argerr; 213 subject = *++args; 214 } else if (!strcmp(*args, "-signer")) { 215 if (!args[1]) 216 goto argerr; 217 /* If previous -signer argument add signer to list */ 218 219 if (signerfile) { 220 if (!sksigners) 221 sksigners = sk_OPENSSL_STRING_new_null(); 222 sk_OPENSSL_STRING_push(sksigners, signerfile); 223 if (!keyfile) 224 keyfile = signerfile; 225 if (!skkeys) 226 skkeys = sk_OPENSSL_STRING_new_null(); 227 sk_OPENSSL_STRING_push(skkeys, keyfile); 228 keyfile = NULL; 229 } 230 signerfile = *++args; 231 } else if (!strcmp(*args, "-recip")) { 232 if (!args[1]) 233 goto argerr; 234 recipfile = *++args; 235 } else if (!strcmp(*args, "-md")) { 236 if (!args[1]) 237 goto argerr; 238 sign_md = EVP_get_digestbyname(*++args); 239 if (sign_md == NULL) { 240 BIO_printf(bio_err, "Unknown digest %s\n", 241 *args); 242 goto argerr; 243 } 244 } else if (!strcmp(*args, "-inkey")) { 245 if (!args[1]) 246 goto argerr; 247 /* If previous -inkey arument add signer to list */ 248 if (keyfile) { 249 if (!signerfile) { 250 BIO_puts(bio_err, "Illegal -inkey without -signer\n"); 251 goto argerr; 252 } 253 if (!sksigners) 254 sksigners = sk_OPENSSL_STRING_new_null(); 255 sk_OPENSSL_STRING_push(sksigners, signerfile); 256 signerfile = NULL; 257 if (!skkeys) 258 skkeys = sk_OPENSSL_STRING_new_null(); 259 sk_OPENSSL_STRING_push(skkeys, keyfile); 260 } 261 keyfile = *++args; 262 } else if (!strcmp(*args, "-keyform")) { 263 if (!args[1]) 264 goto argerr; 265 keyform = str2fmt(*++args); 266 } else if (!strcmp(*args, "-certfile")) { 267 if (!args[1]) 268 goto argerr; 269 certfile = *++args; 270 } else if (!strcmp(*args, "-CAfile")) { 271 if (!args[1]) 272 goto argerr; 273 CAfile = *++args; 274 } else if (!strcmp(*args, "-CApath")) { 275 if (!args[1]) 276 goto argerr; 277 CApath = *++args; 278 } else if (!strcmp(*args, "-in")) { 279 if (!args[1]) 280 goto argerr; 281 infile = *++args; 282 } else if (!strcmp(*args, "-inform")) { 283 if (!args[1]) 284 goto argerr; 285 informat = str2fmt(*++args); 286 } else if (!strcmp(*args, "-outform")) { 287 if (!args[1]) 288 goto argerr; 289 outformat = str2fmt(*++args); 290 } else if (!strcmp(*args, "-out")) { 291 if (!args[1]) 292 goto argerr; 293 outfile = *++args; 294 } else if (!strcmp(*args, "-content")) { 295 if (!args[1]) 296 goto argerr; 297 contfile = *++args; 298 } else if (args_verify(&args, NULL, &badarg, bio_err, &vpm)) 299 continue; 300 else if ((cipher = EVP_get_cipherbyname(*args + 1)) == NULL) 301 badarg = 1; 302 args++; 303 } 304 305 if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners)) { 306 BIO_puts(bio_err, "Multiple signers or keys not allowed\n"); 307 goto argerr; 308 } 309 if (operation & SMIME_SIGNERS) { 310 /* Check to see if any final signer needs to be appended */ 311 if (keyfile && !signerfile) { 312 BIO_puts(bio_err, "Illegal -inkey without -signer\n"); 313 goto argerr; 314 } 315 if (signerfile) { 316 if (!sksigners) 317 sksigners = sk_OPENSSL_STRING_new_null(); 318 sk_OPENSSL_STRING_push(sksigners, signerfile); 319 if (!skkeys) 320 skkeys = sk_OPENSSL_STRING_new_null(); 321 if (!keyfile) 322 keyfile = signerfile; 323 sk_OPENSSL_STRING_push(skkeys, keyfile); 324 } 325 if (!sksigners) { 326 BIO_printf(bio_err, "No signer certificate specified\n"); 327 badarg = 1; 328 } 329 signerfile = NULL; 330 keyfile = NULL; 331 } else if (operation == SMIME_DECRYPT) { 332 if (!recipfile && !keyfile) { 333 BIO_printf(bio_err, "No recipient certificate or key specified\n"); 334 badarg = 1; 335 } 336 } else if (operation == SMIME_ENCRYPT) { 337 if (!*args) { 338 BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); 339 badarg = 1; 340 } 341 } else if (!operation) 342 badarg = 1; 343 344 if (badarg) { 345 argerr: 346 BIO_printf(bio_err, "Usage smime [options] cert.pem ...\n"); 347 BIO_printf(bio_err, "where options are\n"); 348 BIO_printf(bio_err, "-encrypt encrypt message\n"); 349 BIO_printf(bio_err, "-decrypt decrypt encrypted message\n"); 350 BIO_printf(bio_err, "-sign sign message\n"); 351 BIO_printf(bio_err, "-verify verify signed message\n"); 352 BIO_printf(bio_err, "-pk7out output PKCS#7 structure\n"); 353 #ifndef OPENSSL_NO_DES 354 BIO_printf(bio_err, "-des3 encrypt with triple DES\n"); 355 BIO_printf(bio_err, "-des encrypt with DES\n"); 356 #endif 357 #ifndef OPENSSL_NO_RC2 358 BIO_printf(bio_err, "-rc2-40 encrypt with RC2-40 (default)\n"); 359 BIO_printf(bio_err, "-rc2-64 encrypt with RC2-64\n"); 360 BIO_printf(bio_err, "-rc2-128 encrypt with RC2-128\n"); 361 #endif 362 #ifndef OPENSSL_NO_AES 363 BIO_printf(bio_err, "-aes128, -aes192, -aes256\n"); 364 BIO_printf(bio_err, " encrypt PEM output with cbc aes\n"); 365 #endif 366 #ifndef OPENSSL_NO_CAMELLIA 367 BIO_printf(bio_err, "-camellia128, -camellia192, -camellia256\n"); 368 BIO_printf(bio_err, " encrypt PEM output with cbc camellia\n"); 369 #endif 370 BIO_printf(bio_err, "-nointern don't search certificates in message for signer\n"); 371 BIO_printf(bio_err, "-nosigs don't verify message signature\n"); 372 BIO_printf(bio_err, "-noverify don't verify signers certificate\n"); 373 BIO_printf(bio_err, "-nocerts don't include signers certificate when signing\n"); 374 BIO_printf(bio_err, "-nodetach use opaque signing\n"); 375 BIO_printf(bio_err, "-noattr don't include any signed attributes\n"); 376 BIO_printf(bio_err, "-binary don't translate message to text\n"); 377 BIO_printf(bio_err, "-certfile file other certificates file\n"); 378 BIO_printf(bio_err, "-signer file signer certificate file\n"); 379 BIO_printf(bio_err, "-recip file recipient certificate file for decryption\n"); 380 BIO_printf(bio_err, "-in file input file\n"); 381 BIO_printf(bio_err, "-inform arg input format SMIME (default), PEM or DER\n"); 382 BIO_printf(bio_err, "-inkey file input private key (if not signer or recipient)\n"); 383 BIO_printf(bio_err, "-keyform arg input private key format (PEM)\n"); 384 BIO_printf(bio_err, "-out file output file\n"); 385 BIO_printf(bio_err, "-outform arg output format SMIME (default), PEM or DER\n"); 386 BIO_printf(bio_err, "-content file supply or override content for detached signature\n"); 387 BIO_printf(bio_err, "-to addr to address\n"); 388 BIO_printf(bio_err, "-from ad from address\n"); 389 BIO_printf(bio_err, "-subject s subject\n"); 390 BIO_printf(bio_err, "-text include or delete text MIME headers\n"); 391 BIO_printf(bio_err, "-CApath dir trusted certificates directory\n"); 392 BIO_printf(bio_err, "-CAfile file trusted certificates file\n"); 393 BIO_printf(bio_err, "-crl_check check revocation status of signer's certificate using CRLs\n"); 394 BIO_printf(bio_err, "-crl_check_all check revocation status of signer's certificate chain using CRLs\n"); 395 BIO_printf(bio_err, "-passin arg input file pass phrase source\n"); 396 BIO_printf(bio_err, "cert.pem recipient certificate(s) for encryption\n"); 397 goto end; 398 } 399 400 if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { 401 BIO_printf(bio_err, "Error getting password\n"); 402 goto end; 403 } 404 ret = 2; 405 406 if (!(operation & SMIME_SIGNERS)) 407 flags &= ~PKCS7_DETACHED; 408 409 if (operation & SMIME_OP) { 410 if (outformat == FORMAT_ASN1) 411 outmode = "wb"; 412 } else { 413 if (flags & PKCS7_BINARY) 414 outmode = "wb"; 415 } 416 417 if (operation & SMIME_IP) { 418 if (informat == FORMAT_ASN1) 419 inmode = "rb"; 420 } else { 421 if (flags & PKCS7_BINARY) 422 inmode = "rb"; 423 } 424 425 if (operation == SMIME_ENCRYPT) { 426 if (!cipher) { 427 #ifndef OPENSSL_NO_RC2 428 cipher = EVP_rc2_40_cbc(); 429 #else 430 BIO_printf(bio_err, "No cipher selected\n"); 431 goto end; 432 #endif 433 } 434 encerts = sk_X509_new_null(); 435 while (*args) { 436 if (!(cert = load_cert(bio_err, *args, FORMAT_PEM, 437 NULL, "recipient certificate file"))) { 438 goto end; 439 } 440 sk_X509_push(encerts, cert); 441 cert = NULL; 442 args++; 443 } 444 } 445 if (certfile) { 446 if (!(other = load_certs(bio_err, certfile, FORMAT_PEM, NULL, 447 "certificate file"))) { 448 ERR_print_errors(bio_err); 449 goto end; 450 } 451 } 452 if (recipfile && (operation == SMIME_DECRYPT)) { 453 if (!(recip = load_cert(bio_err, recipfile, FORMAT_PEM, NULL, 454 "recipient certificate file"))) { 455 ERR_print_errors(bio_err); 456 goto end; 457 } 458 } 459 if (operation == SMIME_DECRYPT) { 460 if (!keyfile) 461 keyfile = recipfile; 462 } else if (operation == SMIME_SIGN) { 463 if (!keyfile) 464 keyfile = signerfile; 465 } else 466 keyfile = NULL; 467 468 if (keyfile) { 469 key = load_key(bio_err, keyfile, keyform, 0, passin, 470 "signing key file"); 471 if (!key) 472 goto end; 473 } 474 if (infile) { 475 if (!(in = BIO_new_file(infile, inmode))) { 476 BIO_printf(bio_err, 477 "Can't open input file %s\n", infile); 478 goto end; 479 } 480 } else 481 in = BIO_new_fp(stdin, BIO_NOCLOSE); 482 483 if (operation & SMIME_IP) { 484 if (informat == FORMAT_SMIME) 485 p7 = SMIME_read_PKCS7(in, &indata); 486 else if (informat == FORMAT_PEM) 487 p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); 488 else if (informat == FORMAT_ASN1) 489 p7 = d2i_PKCS7_bio(in, NULL); 490 else { 491 BIO_printf(bio_err, "Bad input format for PKCS#7 file\n"); 492 goto end; 493 } 494 495 if (!p7) { 496 BIO_printf(bio_err, "Error reading S/MIME message\n"); 497 goto end; 498 } 499 if (contfile) { 500 BIO_free(indata); 501 if (!(indata = BIO_new_file(contfile, "rb"))) { 502 BIO_printf(bio_err, "Can't read content file %s\n", contfile); 503 goto end; 504 } 505 } 506 } 507 if (outfile) { 508 if (!(out = BIO_new_file(outfile, outmode))) { 509 BIO_printf(bio_err, 510 "Can't open output file %s\n", outfile); 511 goto end; 512 } 513 } else { 514 out = BIO_new_fp(stdout, BIO_NOCLOSE); 515 } 516 517 if (operation == SMIME_VERIFY) { 518 if (!(store = setup_verify(bio_err, CAfile, CApath))) 519 goto end; 520 X509_STORE_set_verify_cb(store, smime_cb); 521 if (vpm) 522 X509_STORE_set1_param(store, vpm); 523 } 524 ret = 3; 525 526 if (operation == SMIME_ENCRYPT) { 527 if (indef) 528 flags |= PKCS7_STREAM; 529 p7 = PKCS7_encrypt(encerts, in, cipher, flags); 530 } else if (operation & SMIME_SIGNERS) { 531 int i; 532 /* 533 * If detached data content we only enable streaming if 534 * S/MIME output format. 535 */ 536 if (operation == SMIME_SIGN) { 537 if (flags & PKCS7_DETACHED) { 538 if (outformat == FORMAT_SMIME) 539 flags |= PKCS7_STREAM; 540 } else if (indef) 541 flags |= PKCS7_STREAM; 542 flags |= PKCS7_PARTIAL; 543 p7 = PKCS7_sign(NULL, NULL, other, in, flags); 544 if (!p7) 545 goto end; 546 } else 547 flags |= PKCS7_REUSE_DIGEST; 548 for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) { 549 signerfile = sk_OPENSSL_STRING_value(sksigners, i); 550 keyfile = sk_OPENSSL_STRING_value(skkeys, i); 551 signer = load_cert(bio_err, signerfile, FORMAT_PEM, NULL, 552 "signer certificate"); 553 if (!signer) 554 goto end; 555 key = load_key(bio_err, keyfile, keyform, 0, passin, 556 "signing key file"); 557 if (!key) 558 goto end; 559 if (!PKCS7_sign_add_signer(p7, signer, key, 560 sign_md, flags)) 561 goto end; 562 X509_free(signer); 563 signer = NULL; 564 EVP_PKEY_free(key); 565 key = NULL; 566 } 567 /* If not streaming or resigning finalize structure */ 568 if ((operation == SMIME_SIGN) && !(flags & PKCS7_STREAM)) { 569 if (!PKCS7_final(p7, in, flags)) 570 goto end; 571 } 572 } 573 if (!p7) { 574 BIO_printf(bio_err, "Error creating PKCS#7 structure\n"); 575 goto end; 576 } 577 ret = 4; 578 if (operation == SMIME_DECRYPT) { 579 if (!PKCS7_decrypt(p7, key, recip, out, flags)) { 580 BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n"); 581 goto end; 582 } 583 } else if (operation == SMIME_VERIFY) { 584 STACK_OF(X509) * signers; 585 if (PKCS7_verify(p7, other, store, indata, out, flags)) 586 BIO_printf(bio_err, "Verification successful\n"); 587 else { 588 BIO_printf(bio_err, "Verification failure\n"); 589 goto end; 590 } 591 signers = PKCS7_get0_signers(p7, other, flags); 592 if (!save_certs(signerfile, signers)) { 593 BIO_printf(bio_err, "Error writing signers to %s\n", 594 signerfile); 595 ret = 5; 596 goto end; 597 } 598 sk_X509_free(signers); 599 } else if (operation == SMIME_PK7OUT) 600 PEM_write_bio_PKCS7(out, p7); 601 else { 602 if (to) 603 BIO_printf(out, "To: %s\n", to); 604 if (from) 605 BIO_printf(out, "From: %s\n", from); 606 if (subject) 607 BIO_printf(out, "Subject: %s\n", subject); 608 if (outformat == FORMAT_SMIME) { 609 if (operation == SMIME_RESIGN) 610 SMIME_write_PKCS7(out, p7, indata, flags); 611 else 612 SMIME_write_PKCS7(out, p7, in, flags); 613 } else if (outformat == FORMAT_PEM) 614 PEM_write_bio_PKCS7_stream(out, p7, in, flags); 615 else if (outformat == FORMAT_ASN1) 616 i2d_PKCS7_bio_stream(out, p7, in, flags); 617 else { 618 BIO_printf(bio_err, "Bad output format for PKCS#7 file\n"); 619 goto end; 620 } 621 } 622 ret = 0; 623 end: 624 if (ret) 625 ERR_print_errors(bio_err); 626 sk_X509_pop_free(encerts, X509_free); 627 sk_X509_pop_free(other, X509_free); 628 X509_VERIFY_PARAM_free(vpm); 629 sk_OPENSSL_STRING_free(sksigners); 630 sk_OPENSSL_STRING_free(skkeys); 631 X509_STORE_free(store); 632 X509_free(cert); 633 X509_free(recip); 634 X509_free(signer); 635 EVP_PKEY_free(key); 636 PKCS7_free(p7); 637 BIO_free(in); 638 BIO_free(indata); 639 BIO_free_all(out); 640 free(passin); 641 642 return (ret); 643 } 644 645 static int 646 save_certs(char *signerfile, STACK_OF(X509) * signers) 647 { 648 int i; 649 BIO *tmp; 650 if (!signerfile) 651 return 1; 652 tmp = BIO_new_file(signerfile, "w"); 653 if (!tmp) 654 return 0; 655 for (i = 0; i < sk_X509_num(signers); i++) 656 PEM_write_bio_X509(tmp, sk_X509_value(signers, i)); 657 BIO_free(tmp); 658 return 1; 659 } 660 661 662 /* Minimal callback just to output policy info (if any) */ 663 664 static int 665 smime_cb(int ok, X509_STORE_CTX * ctx) 666 { 667 int error; 668 669 error = X509_STORE_CTX_get_error(ctx); 670 671 if ((error != X509_V_ERR_NO_EXPLICIT_POLICY) 672 && ((error != X509_V_OK) || (ok != 2))) 673 return ok; 674 675 policies_print(NULL, ctx); 676 677 return ok; 678 679 } 680