1 /* 2 * Copyright 1999-2025 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 /* S/MIME utility function */ 11 12 #include <stdio.h> 13 #include <string.h> 14 #include "apps.h" 15 #include "progs.h" 16 #include <openssl/crypto.h> 17 #include <openssl/pem.h> 18 #include <openssl/err.h> 19 #include <openssl/x509_vfy.h> 20 #include <openssl/x509v3.h> 21 22 static int save_certs(char *signerfile, STACK_OF(X509) *signers); 23 static int smime_cb(int ok, X509_STORE_CTX *ctx); 24 25 #define SMIME_OP 0x10 26 #define SMIME_IP 0x20 27 #define SMIME_SIGNERS 0x40 28 #define SMIME_ENCRYPT (1 | SMIME_OP) 29 #define SMIME_DECRYPT (2 | SMIME_IP) 30 #define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS) 31 #define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS) 32 #define SMIME_VERIFY (4 | SMIME_IP) 33 #define SMIME_PK7OUT (5 | SMIME_IP | SMIME_OP) 34 35 typedef enum OPTION_choice { 36 OPT_COMMON, 37 OPT_ENCRYPT, OPT_DECRYPT, OPT_SIGN, OPT_RESIGN, OPT_VERIFY, 38 OPT_PK7OUT, OPT_TEXT, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCHAIN, 39 OPT_NOCERTS, OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP, 40 OPT_BINARY, OPT_NOSIGS, OPT_STREAM, OPT_INDEF, OPT_NOINDEF, 41 OPT_CRLFEOL, OPT_ENGINE, OPT_PASSIN, 42 OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP, OPT_MD, 43 OPT_CIPHER, OPT_INKEY, OPT_KEYFORM, OPT_CERTFILE, OPT_CAFILE, 44 OPT_CAPATH, OPT_CASTORE, OPT_NOCAFILE, OPT_NOCAPATH, OPT_NOCASTORE, 45 OPT_R_ENUM, OPT_PROV_ENUM, OPT_CONFIG, 46 OPT_V_ENUM, 47 OPT_IN, OPT_INFORM, OPT_OUT, 48 OPT_OUTFORM, OPT_CONTENT 49 } OPTION_CHOICE; 50 51 const OPTIONS smime_options[] = { 52 {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert...]\n"}, 53 54 OPT_SECTION("General"), 55 {"help", OPT_HELP, '-', "Display this summary"}, 56 {"in", OPT_IN, '<', "Input file"}, 57 {"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"}, 58 {"out", OPT_OUT, '>', "Output file"}, 59 {"outform", OPT_OUTFORM, 'c', 60 "Output format SMIME (default), PEM or DER"}, 61 {"inkey", OPT_INKEY, 's', 62 "Input private key (if not signer or recipient)"}, 63 {"keyform", OPT_KEYFORM, 'f', "Input private key format (ENGINE, other values ignored)"}, 64 #ifndef OPENSSL_NO_ENGINE 65 {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 66 #endif 67 {"stream", OPT_STREAM, '-', "Enable CMS streaming" }, 68 {"indef", OPT_INDEF, '-', "Same as -stream" }, 69 {"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"}, 70 OPT_CONFIG_OPTION, 71 72 OPT_SECTION("Action"), 73 {"encrypt", OPT_ENCRYPT, '-', "Encrypt message"}, 74 {"decrypt", OPT_DECRYPT, '-', "Decrypt encrypted message"}, 75 {"sign", OPT_SIGN, '-', "Sign message"}, 76 {"resign", OPT_RESIGN, '-', "Resign a signed message"}, 77 {"verify", OPT_VERIFY, '-', "Verify signed message"}, 78 {"pk7out", OPT_PK7OUT, '-', "Output PKCS#7 structure"}, 79 80 OPT_SECTION("Signing/Encryption"), 81 {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, 82 {"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"}, 83 {"", OPT_CIPHER, '-', "Any supported cipher"}, 84 {"nointern", OPT_NOINTERN, '-', 85 "Don't search certificates in message for signer"}, 86 {"nodetach", OPT_NODETACH, '-', "Use opaque signing"}, 87 {"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"}, 88 {"binary", OPT_BINARY, '-', "Don't translate message to text"}, 89 {"signer", OPT_SIGNER, 's', "Signer certificate file"}, 90 {"content", OPT_CONTENT, '<', 91 "Supply or override content for detached signature"}, 92 {"nocerts", OPT_NOCERTS, '-', 93 "Don't include signers certificate when signing"}, 94 95 OPT_SECTION("Verification/Decryption"), 96 {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"}, 97 {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"}, 98 99 {"certfile", OPT_CERTFILE, '<', 100 "Extra signer and intermediate CA certificates to include when signing"}, 101 {OPT_MORE_STR, 0, 0, 102 "or to use as preferred signer certs and for chain building when verifying"}, 103 {"recip", OPT_RECIP, '<', "Recipient certificate file for decryption"}, 104 105 OPT_SECTION("Email"), 106 {"to", OPT_TO, 's', "To address"}, 107 {"from", OPT_FROM, 's', "From address"}, 108 {"subject", OPT_SUBJECT, 's', "Subject"}, 109 {"text", OPT_TEXT, '-', "Include or delete text MIME headers"}, 110 {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"}, 111 112 OPT_SECTION("Certificate chain"), 113 {"CApath", OPT_CAPATH, '/', "Trusted certificates directory"}, 114 {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"}, 115 {"CAstore", OPT_CASTORE, ':', "Trusted certificates store URI"}, 116 {"no-CAfile", OPT_NOCAFILE, '-', 117 "Do not load the default certificates file"}, 118 {"no-CApath", OPT_NOCAPATH, '-', 119 "Do not load certificates from the default certificates directory"}, 120 {"no-CAstore", OPT_NOCASTORE, '-', 121 "Do not load certificates from the default certificates store"}, 122 {"nochain", OPT_NOCHAIN, '-', 123 "set PKCS7_NOCHAIN so certificates contained in the message are not used as untrusted CAs" }, 124 {"crlfeol", OPT_CRLFEOL, '-', "Use CRLF as EOL termination instead of LF only"}, 125 126 OPT_R_OPTIONS, 127 OPT_V_OPTIONS, 128 OPT_PROV_OPTIONS, 129 130 OPT_PARAMETERS(), 131 {"cert", 0, 0, "Recipient certs, used when encrypting"}, 132 {NULL} 133 }; 134 135 static const char *operation_name(int operation) 136 { 137 switch (operation) { 138 case SMIME_ENCRYPT: 139 return "encrypt"; 140 case SMIME_DECRYPT: 141 return "decrypt"; 142 case SMIME_SIGN: 143 return "sign"; 144 case SMIME_RESIGN: 145 return "resign"; 146 case SMIME_VERIFY: 147 return "verify"; 148 case SMIME_PK7OUT: 149 return "pk7out"; 150 default: 151 return "(invalid operation)"; 152 } 153 } 154 155 #define SET_OPERATION(op) \ 156 ((operation != 0 && (operation != (op))) \ 157 ? 0 * BIO_printf(bio_err, "%s: Cannot use -%s together with -%s\n", \ 158 prog, operation_name(op), operation_name(operation)) \ 159 : (operation = (op))) 160 161 int smime_main(int argc, char **argv) 162 { 163 CONF *conf = NULL; 164 BIO *in = NULL, *out = NULL, *indata = NULL; 165 EVP_PKEY *key = NULL; 166 PKCS7 *p7 = NULL; 167 STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL; 168 STACK_OF(X509) *encerts = NULL, *other = NULL; 169 X509 *cert = NULL, *recip = NULL, *signer = NULL; 170 X509_STORE *store = NULL; 171 X509_VERIFY_PARAM *vpm = NULL; 172 EVP_CIPHER *cipher = NULL; 173 EVP_MD *sign_md = NULL; 174 const char *CAfile = NULL, *CApath = NULL, *CAstore = NULL, *prog = NULL; 175 char *certfile = NULL, *keyfile = NULL, *contfile = NULL; 176 char *infile = NULL, *outfile = NULL, *signerfile = NULL, *recipfile = NULL; 177 char *passinarg = NULL, *passin = NULL, *to = NULL, *from = NULL; 178 char *subject = NULL, *digestname = NULL, *ciphername = NULL; 179 OPTION_CHOICE o; 180 int noCApath = 0, noCAfile = 0, noCAstore = 0; 181 int flags = PKCS7_DETACHED, operation = 0, ret = 0, indef = 0; 182 int informat = FORMAT_SMIME, outformat = FORMAT_SMIME, keyform = 183 FORMAT_UNDEF; 184 int vpmtouched = 0, rv = 0; 185 ENGINE *e = NULL; 186 const char *mime_eol = "\n"; 187 OSSL_LIB_CTX *libctx = app_get0_libctx(); 188 189 if ((vpm = X509_VERIFY_PARAM_new()) == NULL) 190 return 1; 191 192 opt_set_unknown_name("cipher"); 193 prog = opt_init(argc, argv, smime_options); 194 while ((o = opt_next()) != OPT_EOF) { 195 switch (o) { 196 case OPT_EOF: 197 case OPT_ERR: 198 opthelp: 199 BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 200 goto end; 201 case OPT_HELP: 202 opt_help(smime_options); 203 ret = 0; 204 goto end; 205 case OPT_INFORM: 206 if (!opt_format(opt_arg(), OPT_FMT_PDS, &informat)) 207 goto opthelp; 208 break; 209 case OPT_IN: 210 infile = opt_arg(); 211 break; 212 case OPT_OUTFORM: 213 if (!opt_format(opt_arg(), OPT_FMT_PDS, &outformat)) 214 goto opthelp; 215 break; 216 case OPT_OUT: 217 outfile = opt_arg(); 218 break; 219 case OPT_ENCRYPT: 220 if (!SET_OPERATION(SMIME_ENCRYPT)) 221 goto end; 222 break; 223 case OPT_DECRYPT: 224 if (!SET_OPERATION(SMIME_DECRYPT)) 225 goto end; 226 break; 227 case OPT_SIGN: 228 if (!SET_OPERATION(SMIME_SIGN)) 229 goto end; 230 break; 231 case OPT_RESIGN: 232 if (!SET_OPERATION(SMIME_RESIGN)) 233 goto end; 234 break; 235 case OPT_VERIFY: 236 if (!SET_OPERATION(SMIME_VERIFY)) 237 goto end; 238 break; 239 case OPT_PK7OUT: 240 if (!SET_OPERATION(SMIME_PK7OUT)) 241 goto end; 242 break; 243 case OPT_TEXT: 244 flags |= PKCS7_TEXT; 245 break; 246 case OPT_NOINTERN: 247 flags |= PKCS7_NOINTERN; 248 break; 249 case OPT_NOVERIFY: 250 flags |= PKCS7_NOVERIFY; 251 break; 252 case OPT_NOCHAIN: 253 flags |= PKCS7_NOCHAIN; 254 break; 255 case OPT_NOCERTS: 256 flags |= PKCS7_NOCERTS; 257 break; 258 case OPT_NOATTR: 259 flags |= PKCS7_NOATTR; 260 break; 261 case OPT_NODETACH: 262 flags &= ~PKCS7_DETACHED; 263 break; 264 case OPT_NOSMIMECAP: 265 flags |= PKCS7_NOSMIMECAP; 266 break; 267 case OPT_BINARY: 268 flags |= PKCS7_BINARY; 269 break; 270 case OPT_NOSIGS: 271 flags |= PKCS7_NOSIGS; 272 break; 273 case OPT_STREAM: 274 case OPT_INDEF: 275 indef = 1; 276 break; 277 case OPT_NOINDEF: 278 indef = 0; 279 break; 280 case OPT_CRLFEOL: 281 flags |= PKCS7_CRLFEOL; 282 mime_eol = "\r\n"; 283 break; 284 case OPT_R_CASES: 285 if (!opt_rand(o)) 286 goto end; 287 break; 288 case OPT_PROV_CASES: 289 if (!opt_provider(o)) 290 goto end; 291 break; 292 case OPT_CONFIG: 293 conf = app_load_config_modules(opt_arg()); 294 if (conf == NULL) 295 goto end; 296 break; 297 case OPT_ENGINE: 298 e = setup_engine(opt_arg(), 0); 299 break; 300 case OPT_PASSIN: 301 passinarg = opt_arg(); 302 break; 303 case OPT_TO: 304 to = opt_arg(); 305 break; 306 case OPT_FROM: 307 from = opt_arg(); 308 break; 309 case OPT_SUBJECT: 310 subject = opt_arg(); 311 break; 312 case OPT_SIGNER: 313 /* If previous -signer argument add signer to list */ 314 if (signerfile != NULL) { 315 if (sksigners == NULL 316 && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) 317 goto end; 318 if (sk_OPENSSL_STRING_push(sksigners, signerfile) <= 0) 319 goto end; 320 if (keyfile == NULL) 321 keyfile = signerfile; 322 if (skkeys == NULL 323 && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) 324 goto end; 325 if (sk_OPENSSL_STRING_push(skkeys, keyfile) <= 0) 326 goto end; 327 keyfile = NULL; 328 } 329 signerfile = opt_arg(); 330 break; 331 case OPT_RECIP: 332 recipfile = opt_arg(); 333 break; 334 case OPT_MD: 335 digestname = opt_arg(); 336 break; 337 case OPT_CIPHER: 338 ciphername = opt_unknown(); 339 break; 340 case OPT_INKEY: 341 /* If previous -inkey argument add signer to list */ 342 if (keyfile != NULL) { 343 if (signerfile == NULL) { 344 BIO_printf(bio_err, 345 "%s: Must have -signer before -inkey\n", prog); 346 goto opthelp; 347 } 348 if (sksigners == NULL 349 && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) 350 goto end; 351 if (sk_OPENSSL_STRING_push(sksigners, signerfile) <= 0) 352 goto end; 353 signerfile = NULL; 354 if (skkeys == NULL 355 && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) 356 goto end; 357 if (sk_OPENSSL_STRING_push(skkeys, keyfile) <= 0) 358 goto end; 359 } 360 keyfile = opt_arg(); 361 break; 362 case OPT_KEYFORM: 363 if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform)) 364 goto opthelp; 365 break; 366 case OPT_CERTFILE: 367 certfile = opt_arg(); 368 break; 369 case OPT_CAFILE: 370 CAfile = opt_arg(); 371 break; 372 case OPT_CAPATH: 373 CApath = opt_arg(); 374 break; 375 case OPT_CASTORE: 376 CAstore = opt_arg(); 377 break; 378 case OPT_NOCAFILE: 379 noCAfile = 1; 380 break; 381 case OPT_NOCAPATH: 382 noCApath = 1; 383 break; 384 case OPT_NOCASTORE: 385 noCAstore = 1; 386 break; 387 case OPT_CONTENT: 388 contfile = opt_arg(); 389 break; 390 case OPT_V_CASES: 391 if (!opt_verify(o, vpm)) 392 goto opthelp; 393 vpmtouched++; 394 break; 395 } 396 } 397 398 /* Extra arguments are files with recipient keys. */ 399 argc = opt_num_rest(); 400 argv = opt_rest(); 401 402 if (!app_RAND_load()) 403 goto end; 404 405 if (digestname != NULL) { 406 if (!opt_md(digestname, &sign_md)) 407 goto opthelp; 408 } 409 if (!opt_cipher_any(ciphername, &cipher)) 410 goto opthelp; 411 if (!(operation & SMIME_SIGNERS) && (skkeys != NULL || sksigners != NULL)) { 412 BIO_puts(bio_err, "Multiple signers or keys not allowed\n"); 413 goto opthelp; 414 } 415 if (!operation) { 416 BIO_puts(bio_err, 417 "No operation (-encrypt|-sign|...) specified\n"); 418 goto opthelp; 419 } 420 421 if (operation & SMIME_SIGNERS) { 422 /* Check to see if any final signer needs to be appended */ 423 if (keyfile && !signerfile) { 424 BIO_puts(bio_err, "Illegal -inkey without -signer\n"); 425 goto opthelp; 426 } 427 if (signerfile != NULL) { 428 if (sksigners == NULL 429 && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) 430 goto end; 431 if (sk_OPENSSL_STRING_push(sksigners, signerfile) <= 0) 432 goto end; 433 if (!skkeys && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) 434 goto end; 435 if (!keyfile) 436 keyfile = signerfile; 437 if (sk_OPENSSL_STRING_push(skkeys, keyfile) <= 0) 438 goto end; 439 } 440 if (sksigners == NULL) { 441 BIO_printf(bio_err, "No signer certificate specified\n"); 442 goto opthelp; 443 } 444 signerfile = NULL; 445 keyfile = NULL; 446 } else if (operation == SMIME_DECRYPT) { 447 if (recipfile == NULL && keyfile == NULL) { 448 BIO_printf(bio_err, 449 "No recipient certificate or key specified\n"); 450 goto opthelp; 451 } 452 } else if (operation == SMIME_ENCRYPT) { 453 if (argc == 0) { 454 BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); 455 goto opthelp; 456 } 457 } 458 459 if (!app_passwd(passinarg, NULL, &passin, NULL)) { 460 BIO_printf(bio_err, "Error getting password\n"); 461 goto end; 462 } 463 464 ret = 2; 465 466 if (!(operation & SMIME_SIGNERS)) 467 flags &= ~PKCS7_DETACHED; 468 469 if (!(operation & SMIME_OP)) { 470 if (flags & PKCS7_BINARY) 471 outformat = FORMAT_BINARY; 472 } 473 474 if (!(operation & SMIME_IP)) { 475 if (flags & PKCS7_BINARY) 476 informat = FORMAT_BINARY; 477 } 478 479 if (operation == SMIME_ENCRYPT) { 480 if (cipher == NULL) 481 cipher = (EVP_CIPHER *)EVP_aes_256_cbc(); 482 encerts = sk_X509_new_null(); 483 if (encerts == NULL) 484 goto end; 485 while (*argv != NULL) { 486 cert = load_cert(*argv, FORMAT_UNDEF, 487 "recipient certificate file"); 488 if (cert == NULL) 489 goto end; 490 if (!sk_X509_push(encerts, cert)) 491 goto end; 492 cert = NULL; 493 argv++; 494 } 495 } 496 497 if (certfile != NULL) { 498 if (!load_certs(certfile, 0, &other, NULL, "certificates")) { 499 ERR_print_errors(bio_err); 500 goto end; 501 } 502 } 503 504 if (recipfile != NULL && (operation == SMIME_DECRYPT)) { 505 if ((recip = load_cert(recipfile, FORMAT_UNDEF, 506 "recipient certificate file")) == NULL) { 507 ERR_print_errors(bio_err); 508 goto end; 509 } 510 } 511 512 if (operation == SMIME_DECRYPT) { 513 if (keyfile == NULL) 514 keyfile = recipfile; 515 } else if (operation == SMIME_SIGN) { 516 if (keyfile == NULL) 517 keyfile = signerfile; 518 } else { 519 keyfile = NULL; 520 } 521 522 if (keyfile != NULL) { 523 key = load_key(keyfile, keyform, 0, passin, e, "signing key"); 524 if (key == NULL) 525 goto end; 526 } 527 528 in = bio_open_default(infile, 'r', informat); 529 if (in == NULL) 530 goto end; 531 532 if (operation & SMIME_IP) { 533 PKCS7 *p7_in = NULL; 534 535 p7 = PKCS7_new_ex(libctx, app_get0_propq()); 536 if (p7 == NULL) { 537 BIO_printf(bio_err, "Error allocating PKCS7 object\n"); 538 goto end; 539 } 540 if (informat == FORMAT_SMIME) { 541 p7_in = SMIME_read_PKCS7_ex(in, &indata, &p7); 542 } else if (informat == FORMAT_PEM) { 543 p7_in = PEM_read_bio_PKCS7(in, &p7, NULL, NULL); 544 } else if (informat == FORMAT_ASN1) { 545 p7_in = d2i_PKCS7_bio(in, &p7); 546 } else { 547 BIO_printf(bio_err, "Bad input format for PKCS#7 file\n"); 548 goto end; 549 } 550 551 if (p7_in == NULL) { 552 BIO_printf(bio_err, "Error reading S/MIME message\n"); 553 goto end; 554 } 555 if (contfile != NULL) { 556 BIO_free(indata); 557 if ((indata = BIO_new_file(contfile, "rb")) == NULL) { 558 BIO_printf(bio_err, "Can't read content file %s\n", contfile); 559 goto end; 560 } 561 } 562 } 563 564 out = bio_open_default(outfile, 'w', outformat); 565 if (out == NULL) 566 goto end; 567 568 if (operation == SMIME_VERIFY) { 569 if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath, 570 CAstore, noCAstore)) == NULL) 571 goto end; 572 X509_STORE_set_verify_cb(store, smime_cb); 573 if (vpmtouched) 574 X509_STORE_set1_param(store, vpm); 575 } 576 577 ret = 3; 578 579 if (operation == SMIME_ENCRYPT) { 580 if (indef) 581 flags |= PKCS7_STREAM; 582 p7 = PKCS7_encrypt_ex(encerts, in, cipher, flags, libctx, app_get0_propq()); 583 } else if (operation & SMIME_SIGNERS) { 584 int i; 585 /* 586 * If detached data content we only enable streaming if S/MIME output 587 * format. 588 */ 589 if (operation == SMIME_SIGN) { 590 if (flags & PKCS7_DETACHED) { 591 if (outformat == FORMAT_SMIME) 592 flags |= PKCS7_STREAM; 593 } else if (indef) { 594 flags |= PKCS7_STREAM; 595 } 596 flags |= PKCS7_PARTIAL; 597 p7 = PKCS7_sign_ex(NULL, NULL, other, in, flags, libctx, app_get0_propq()); 598 if (p7 == NULL) 599 goto end; 600 if (flags & PKCS7_NOCERTS) { 601 for (i = 0; i < sk_X509_num(other); i++) { 602 X509 *x = sk_X509_value(other, i); 603 PKCS7_add_certificate(p7, x); 604 } 605 } 606 } else { 607 flags |= PKCS7_REUSE_DIGEST; 608 } 609 for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) { 610 signerfile = sk_OPENSSL_STRING_value(sksigners, i); 611 keyfile = sk_OPENSSL_STRING_value(skkeys, i); 612 signer = load_cert(signerfile, FORMAT_UNDEF, "signer certificate"); 613 if (signer == NULL) 614 goto end; 615 key = load_key(keyfile, keyform, 0, passin, e, "signing key"); 616 if (key == NULL) 617 goto end; 618 619 if (!PKCS7_sign_add_signer(p7, signer, key, sign_md, flags)) 620 goto end; 621 X509_free(signer); 622 signer = NULL; 623 EVP_PKEY_free(key); 624 key = NULL; 625 } 626 /* If not streaming or resigning finalize structure */ 627 if ((operation == SMIME_SIGN) && !(flags & PKCS7_STREAM)) { 628 if (!PKCS7_final(p7, in, flags)) 629 goto end; 630 } 631 } 632 633 if (p7 == NULL) { 634 BIO_printf(bio_err, "Error creating PKCS#7 structure\n"); 635 goto end; 636 } 637 638 ret = 4; 639 if (operation == SMIME_DECRYPT) { 640 if (!PKCS7_decrypt(p7, key, recip, out, flags)) { 641 BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n"); 642 goto end; 643 } 644 } else if (operation == SMIME_VERIFY) { 645 STACK_OF(X509) *signers; 646 if (PKCS7_verify(p7, other, store, indata, out, flags)) 647 BIO_printf(bio_err, "Verification successful\n"); 648 else { 649 BIO_printf(bio_err, "Verification failure\n"); 650 goto end; 651 } 652 signers = PKCS7_get0_signers(p7, other, flags); 653 if (!save_certs(signerfile, signers)) { 654 BIO_printf(bio_err, "Error writing signers to %s\n", signerfile); 655 ret = 5; 656 goto end; 657 } 658 sk_X509_free(signers); 659 } else if (operation == SMIME_PK7OUT) { 660 PEM_write_bio_PKCS7(out, p7); 661 } else { 662 if (to) 663 BIO_printf(out, "To: %s%s", to, mime_eol); 664 if (from) 665 BIO_printf(out, "From: %s%s", from, mime_eol); 666 if (subject) 667 BIO_printf(out, "Subject: %s%s", subject, mime_eol); 668 if (outformat == FORMAT_SMIME) { 669 if (operation == SMIME_RESIGN) 670 rv = SMIME_write_PKCS7(out, p7, indata, flags); 671 else 672 rv = SMIME_write_PKCS7(out, p7, in, flags); 673 } else if (outformat == FORMAT_PEM) { 674 rv = PEM_write_bio_PKCS7_stream(out, p7, in, flags); 675 } else if (outformat == FORMAT_ASN1) { 676 rv = i2d_PKCS7_bio_stream(out, p7, in, flags); 677 } else { 678 BIO_printf(bio_err, "Bad output format for PKCS#7 file\n"); 679 goto end; 680 } 681 if (rv == 0) { 682 BIO_printf(bio_err, "Error writing output\n"); 683 ret = 3; 684 goto end; 685 } 686 } 687 ret = 0; 688 end: 689 if (ret) 690 ERR_print_errors(bio_err); 691 OSSL_STACK_OF_X509_free(encerts); 692 OSSL_STACK_OF_X509_free(other); 693 X509_VERIFY_PARAM_free(vpm); 694 sk_OPENSSL_STRING_free(sksigners); 695 sk_OPENSSL_STRING_free(skkeys); 696 X509_STORE_free(store); 697 X509_free(cert); 698 X509_free(recip); 699 X509_free(signer); 700 EVP_PKEY_free(key); 701 EVP_MD_free(sign_md); 702 EVP_CIPHER_free(cipher); 703 PKCS7_free(p7); 704 release_engine(e); 705 BIO_free(in); 706 BIO_free(indata); 707 BIO_free_all(out); 708 OPENSSL_free(passin); 709 NCONF_free(conf); 710 return ret; 711 } 712 713 static int save_certs(char *signerfile, STACK_OF(X509) *signers) 714 { 715 int i; 716 BIO *tmp; 717 718 if (signerfile == NULL) 719 return 1; 720 tmp = BIO_new_file(signerfile, "w"); 721 if (tmp == NULL) 722 return 0; 723 for (i = 0; i < sk_X509_num(signers); i++) 724 PEM_write_bio_X509(tmp, sk_X509_value(signers, i)); 725 BIO_free(tmp); 726 return 1; 727 } 728 729 /* Minimal callback just to output policy info (if any) */ 730 731 static int smime_cb(int ok, X509_STORE_CTX *ctx) 732 { 733 int error; 734 735 error = X509_STORE_CTX_get_error(ctx); 736 737 if ((error != X509_V_ERR_NO_EXPLICIT_POLICY) 738 && ((error != X509_V_OK) || (ok != 2))) 739 return ok; 740 741 policies_print(ctx); 742 743 return ok; 744 } 745