159191Skris/* smime.c */ 2280304Sjkim/* 3280304Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 4160814Ssimon * project. 559191Skris */ 659191Skris/* ==================================================================== 7160814Ssimon * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. 859191Skris * 959191Skris * Redistribution and use in source and binary forms, with or without 1059191Skris * modification, are permitted provided that the following conditions 1159191Skris * are met: 1259191Skris * 1359191Skris * 1. Redistributions of source code must retain the above copyright 14280304Sjkim * notice, this list of conditions and the following disclaimer. 1559191Skris * 1659191Skris * 2. Redistributions in binary form must reproduce the above copyright 1759191Skris * notice, this list of conditions and the following disclaimer in 1859191Skris * the documentation and/or other materials provided with the 1959191Skris * distribution. 2059191Skris * 2159191Skris * 3. All advertising materials mentioning features or use of this 2259191Skris * software must display the following acknowledgment: 2359191Skris * "This product includes software developed by the OpenSSL Project 2459191Skris * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2559191Skris * 2659191Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2759191Skris * endorse or promote products derived from this software without 2859191Skris * prior written permission. For written permission, please contact 2959191Skris * licensing@OpenSSL.org. 3059191Skris * 3159191Skris * 5. Products derived from this software may not be called "OpenSSL" 3259191Skris * nor may "OpenSSL" appear in their names without prior written 3359191Skris * permission of the OpenSSL Project. 3459191Skris * 3559191Skris * 6. Redistributions of any form whatsoever must retain the following 3659191Skris * acknowledgment: 3759191Skris * "This product includes software developed by the OpenSSL Project 3859191Skris * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3959191Skris * 4059191Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 4159191Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4259191Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4359191Skris * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4459191Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4559191Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4659191Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4759191Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4859191Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4959191Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 5059191Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 5159191Skris * OF THE POSSIBILITY OF SUCH DAMAGE. 5259191Skris * ==================================================================== 5359191Skris * 5459191Skris * This product includes cryptographic software written by Eric Young 5559191Skris * (eay@cryptsoft.com). This product includes software written by Tim 5659191Skris * Hudson (tjh@cryptsoft.com). 5759191Skris * 5859191Skris */ 5959191Skris 6059191Skris/* S/MIME utility function */ 6159191Skris 6259191Skris#include <stdio.h> 6359191Skris#include <string.h> 6459191Skris#include "apps.h" 6559191Skris#include <openssl/crypto.h> 6659191Skris#include <openssl/pem.h> 6759191Skris#include <openssl/err.h> 68160814Ssimon#include <openssl/x509_vfy.h> 69160814Ssimon#include <openssl/x509v3.h> 7059191Skris 7159191Skris#undef PROG 7259191Skris#define PROG smime_main 7359191Skrisstatic int save_certs(char *signerfile, STACK_OF(X509) *signers); 74160814Ssimonstatic int smime_cb(int ok, X509_STORE_CTX *ctx); 7559191Skris 76280304Sjkim#define SMIME_OP 0x10 77280304Sjkim#define SMIME_IP 0x20 78280304Sjkim#define SMIME_SIGNERS 0x40 79280304Sjkim#define SMIME_ENCRYPT (1 | SMIME_OP) 80280304Sjkim#define SMIME_DECRYPT (2 | SMIME_IP) 81280304Sjkim#define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS) 82280304Sjkim#define SMIME_VERIFY (4 | SMIME_IP) 83280304Sjkim#define SMIME_PK7OUT (5 | SMIME_IP | SMIME_OP) 84280304Sjkim#define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS) 8559191Skris 8659191Skrisint MAIN(int, char **); 8759191Skris 8859191Skrisint MAIN(int argc, char **argv) 89280304Sjkim{ 90280304Sjkim ENGINE *e = NULL; 91280304Sjkim int operation = 0; 92280304Sjkim int ret = 0; 93280304Sjkim char **args; 94280304Sjkim const char *inmode = "r", *outmode = "w"; 95280304Sjkim char *infile = NULL, *outfile = NULL; 96280304Sjkim char *signerfile = NULL, *recipfile = NULL; 97280304Sjkim STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL; 98280304Sjkim char *certfile = NULL, *keyfile = NULL, *contfile = NULL; 99280304Sjkim const EVP_CIPHER *cipher = NULL; 100280304Sjkim PKCS7 *p7 = NULL; 101280304Sjkim X509_STORE *store = NULL; 102280304Sjkim X509 *cert = NULL, *recip = NULL, *signer = NULL; 103280304Sjkim EVP_PKEY *key = NULL; 104280304Sjkim STACK_OF(X509) *encerts = NULL, *other = NULL; 105280304Sjkim BIO *in = NULL, *out = NULL, *indata = NULL; 106280304Sjkim int badarg = 0; 107280304Sjkim int flags = PKCS7_DETACHED; 108280304Sjkim char *to = NULL, *from = NULL, *subject = NULL; 109280304Sjkim char *CAfile = NULL, *CApath = NULL; 110280304Sjkim char *passargin = NULL, *passin = NULL; 111280304Sjkim char *inrand = NULL; 112280304Sjkim int need_rand = 0; 113280304Sjkim int indef = 0; 114280304Sjkim const EVP_MD *sign_md = NULL; 115280304Sjkim int informat = FORMAT_SMIME, outformat = FORMAT_SMIME; 116280304Sjkim int keyform = FORMAT_PEM; 117111147Snectar#ifndef OPENSSL_NO_ENGINE 118280304Sjkim char *engine = NULL; 119111147Snectar#endif 120109998Smarkm 121280304Sjkim X509_VERIFY_PARAM *vpm = NULL; 122160814Ssimon 123280304Sjkim args = argv + 1; 124280304Sjkim ret = 1; 12559191Skris 126280304Sjkim apps_startup(); 127109998Smarkm 128280304Sjkim if (bio_err == NULL) { 129280304Sjkim if ((bio_err = BIO_new(BIO_s_file())) != NULL) 130280304Sjkim BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); 131280304Sjkim } 132109998Smarkm 133280304Sjkim if (!load_config(bio_err, NULL)) 134280304Sjkim goto end; 135109998Smarkm 136280304Sjkim while (!badarg && *args && *args[0] == '-') { 137280304Sjkim if (!strcmp(*args, "-encrypt")) 138280304Sjkim operation = SMIME_ENCRYPT; 139280304Sjkim else if (!strcmp(*args, "-decrypt")) 140280304Sjkim operation = SMIME_DECRYPT; 141280304Sjkim else if (!strcmp(*args, "-sign")) 142280304Sjkim operation = SMIME_SIGN; 143280304Sjkim else if (!strcmp(*args, "-resign")) 144280304Sjkim operation = SMIME_RESIGN; 145280304Sjkim else if (!strcmp(*args, "-verify")) 146280304Sjkim operation = SMIME_VERIFY; 147280304Sjkim else if (!strcmp(*args, "-pk7out")) 148280304Sjkim operation = SMIME_PK7OUT; 149109998Smarkm#ifndef OPENSSL_NO_DES 150280304Sjkim else if (!strcmp(*args, "-des3")) 151280304Sjkim cipher = EVP_des_ede3_cbc(); 152280304Sjkim else if (!strcmp(*args, "-des")) 153280304Sjkim cipher = EVP_des_cbc(); 15459191Skris#endif 155194206Ssimon#ifndef OPENSSL_NO_SEED 156280304Sjkim else if (!strcmp(*args, "-seed")) 157280304Sjkim cipher = EVP_seed_cbc(); 158194206Ssimon#endif 159109998Smarkm#ifndef OPENSSL_NO_RC2 160280304Sjkim else if (!strcmp(*args, "-rc2-40")) 161280304Sjkim cipher = EVP_rc2_40_cbc(); 162280304Sjkim else if (!strcmp(*args, "-rc2-128")) 163280304Sjkim cipher = EVP_rc2_cbc(); 164280304Sjkim else if (!strcmp(*args, "-rc2-64")) 165280304Sjkim cipher = EVP_rc2_64_cbc(); 16659191Skris#endif 167109998Smarkm#ifndef OPENSSL_NO_AES 168280304Sjkim else if (!strcmp(*args, "-aes128")) 169280304Sjkim cipher = EVP_aes_128_cbc(); 170280304Sjkim else if (!strcmp(*args, "-aes192")) 171280304Sjkim cipher = EVP_aes_192_cbc(); 172280304Sjkim else if (!strcmp(*args, "-aes256")) 173280304Sjkim cipher = EVP_aes_256_cbc(); 174109998Smarkm#endif 175162911Ssimon#ifndef OPENSSL_NO_CAMELLIA 176280304Sjkim else if (!strcmp(*args, "-camellia128")) 177280304Sjkim cipher = EVP_camellia_128_cbc(); 178280304Sjkim else if (!strcmp(*args, "-camellia192")) 179280304Sjkim cipher = EVP_camellia_192_cbc(); 180280304Sjkim else if (!strcmp(*args, "-camellia256")) 181280304Sjkim cipher = EVP_camellia_256_cbc(); 182162911Ssimon#endif 183280304Sjkim else if (!strcmp(*args, "-text")) 184280304Sjkim flags |= PKCS7_TEXT; 185280304Sjkim else if (!strcmp(*args, "-nointern")) 186280304Sjkim flags |= PKCS7_NOINTERN; 187280304Sjkim else if (!strcmp(*args, "-noverify")) 188280304Sjkim flags |= PKCS7_NOVERIFY; 189280304Sjkim else if (!strcmp(*args, "-nochain")) 190280304Sjkim flags |= PKCS7_NOCHAIN; 191280304Sjkim else if (!strcmp(*args, "-nocerts")) 192280304Sjkim flags |= PKCS7_NOCERTS; 193280304Sjkim else if (!strcmp(*args, "-noattr")) 194280304Sjkim flags |= PKCS7_NOATTR; 195280304Sjkim else if (!strcmp(*args, "-nodetach")) 196280304Sjkim flags &= ~PKCS7_DETACHED; 197280304Sjkim else if (!strcmp(*args, "-nosmimecap")) 198280304Sjkim flags |= PKCS7_NOSMIMECAP; 199280304Sjkim else if (!strcmp(*args, "-binary")) 200280304Sjkim flags |= PKCS7_BINARY; 201280304Sjkim else if (!strcmp(*args, "-nosigs")) 202280304Sjkim flags |= PKCS7_NOSIGS; 203280304Sjkim else if (!strcmp(*args, "-stream")) 204280304Sjkim indef = 1; 205280304Sjkim else if (!strcmp(*args, "-indef")) 206280304Sjkim indef = 1; 207280304Sjkim else if (!strcmp(*args, "-noindef")) 208280304Sjkim indef = 0; 209280304Sjkim else if (!strcmp(*args, "-nooldmime")) 210280304Sjkim flags |= PKCS7_NOOLDMIMETYPE; 211280304Sjkim else if (!strcmp(*args, "-crlfeol")) 212280304Sjkim flags |= PKCS7_CRLFEOL; 213280304Sjkim else if (!strcmp(*args, "-rand")) { 214280304Sjkim if (!args[1]) 215280304Sjkim goto argerr; 216280304Sjkim args++; 217280304Sjkim inrand = *args; 218280304Sjkim need_rand = 1; 219280304Sjkim } 220111147Snectar#ifndef OPENSSL_NO_ENGINE 221280304Sjkim else if (!strcmp(*args, "-engine")) { 222280304Sjkim if (!args[1]) 223280304Sjkim goto argerr; 224280304Sjkim engine = *++args; 225280304Sjkim } 226111147Snectar#endif 227280304Sjkim else if (!strcmp(*args, "-passin")) { 228280304Sjkim if (!args[1]) 229280304Sjkim goto argerr; 230280304Sjkim passargin = *++args; 231280304Sjkim } else if (!strcmp(*args, "-to")) { 232280304Sjkim if (!args[1]) 233280304Sjkim goto argerr; 234280304Sjkim to = *++args; 235280304Sjkim } else if (!strcmp(*args, "-from")) { 236280304Sjkim if (!args[1]) 237280304Sjkim goto argerr; 238280304Sjkim from = *++args; 239280304Sjkim } else if (!strcmp(*args, "-subject")) { 240280304Sjkim if (!args[1]) 241280304Sjkim goto argerr; 242280304Sjkim subject = *++args; 243280304Sjkim } else if (!strcmp(*args, "-signer")) { 244280304Sjkim if (!args[1]) 245280304Sjkim goto argerr; 246280304Sjkim /* If previous -signer argument add signer to list */ 247238405Sjkim 248280304Sjkim if (signerfile) { 249280304Sjkim if (!sksigners) 250280304Sjkim sksigners = sk_OPENSSL_STRING_new_null(); 251280304Sjkim sk_OPENSSL_STRING_push(sksigners, signerfile); 252280304Sjkim if (!keyfile) 253280304Sjkim keyfile = signerfile; 254280304Sjkim if (!skkeys) 255280304Sjkim skkeys = sk_OPENSSL_STRING_new_null(); 256280304Sjkim sk_OPENSSL_STRING_push(skkeys, keyfile); 257280304Sjkim keyfile = NULL; 258280304Sjkim } 259280304Sjkim signerfile = *++args; 260280304Sjkim } else if (!strcmp(*args, "-recip")) { 261280304Sjkim if (!args[1]) 262280304Sjkim goto argerr; 263280304Sjkim recipfile = *++args; 264280304Sjkim } else if (!strcmp(*args, "-md")) { 265280304Sjkim if (!args[1]) 266280304Sjkim goto argerr; 267280304Sjkim sign_md = EVP_get_digestbyname(*++args); 268280304Sjkim if (sign_md == NULL) { 269280304Sjkim BIO_printf(bio_err, "Unknown digest %s\n", *args); 270280304Sjkim goto argerr; 271280304Sjkim } 272280304Sjkim } else if (!strcmp(*args, "-inkey")) { 273280304Sjkim if (!args[1]) 274280304Sjkim goto argerr; 275280304Sjkim /* If previous -inkey arument add signer to list */ 276280304Sjkim if (keyfile) { 277280304Sjkim if (!signerfile) { 278280304Sjkim BIO_puts(bio_err, "Illegal -inkey without -signer\n"); 279280304Sjkim goto argerr; 280280304Sjkim } 281280304Sjkim if (!sksigners) 282280304Sjkim sksigners = sk_OPENSSL_STRING_new_null(); 283280304Sjkim sk_OPENSSL_STRING_push(sksigners, signerfile); 284280304Sjkim signerfile = NULL; 285280304Sjkim if (!skkeys) 286280304Sjkim skkeys = sk_OPENSSL_STRING_new_null(); 287280304Sjkim sk_OPENSSL_STRING_push(skkeys, keyfile); 288280304Sjkim } 289280304Sjkim keyfile = *++args; 290280304Sjkim } else if (!strcmp(*args, "-keyform")) { 291280304Sjkim if (!args[1]) 292280304Sjkim goto argerr; 293280304Sjkim keyform = str2fmt(*++args); 294280304Sjkim } else if (!strcmp(*args, "-certfile")) { 295280304Sjkim if (!args[1]) 296280304Sjkim goto argerr; 297280304Sjkim certfile = *++args; 298280304Sjkim } else if (!strcmp(*args, "-CAfile")) { 299280304Sjkim if (!args[1]) 300280304Sjkim goto argerr; 301280304Sjkim CAfile = *++args; 302280304Sjkim } else if (!strcmp(*args, "-CApath")) { 303280304Sjkim if (!args[1]) 304280304Sjkim goto argerr; 305280304Sjkim CApath = *++args; 306280304Sjkim } else if (!strcmp(*args, "-in")) { 307280304Sjkim if (!args[1]) 308280304Sjkim goto argerr; 309280304Sjkim infile = *++args; 310280304Sjkim } else if (!strcmp(*args, "-inform")) { 311280304Sjkim if (!args[1]) 312280304Sjkim goto argerr; 313280304Sjkim informat = str2fmt(*++args); 314280304Sjkim } else if (!strcmp(*args, "-outform")) { 315280304Sjkim if (!args[1]) 316280304Sjkim goto argerr; 317280304Sjkim outformat = str2fmt(*++args); 318280304Sjkim } else if (!strcmp(*args, "-out")) { 319280304Sjkim if (!args[1]) 320280304Sjkim goto argerr; 321280304Sjkim outfile = *++args; 322280304Sjkim } else if (!strcmp(*args, "-content")) { 323280304Sjkim if (!args[1]) 324280304Sjkim goto argerr; 325280304Sjkim contfile = *++args; 326280304Sjkim } else if (args_verify(&args, NULL, &badarg, bio_err, &vpm)) 327280304Sjkim continue; 328280304Sjkim else if ((cipher = EVP_get_cipherbyname(*args + 1)) == NULL) 329280304Sjkim badarg = 1; 330280304Sjkim args++; 331280304Sjkim } 33259191Skris 333280304Sjkim if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners)) { 334280304Sjkim BIO_puts(bio_err, "Multiple signers or keys not allowed\n"); 335280304Sjkim goto argerr; 336280304Sjkim } 337160814Ssimon 338280304Sjkim if (operation & SMIME_SIGNERS) { 339280304Sjkim /* Check to see if any final signer needs to be appended */ 340280304Sjkim if (keyfile && !signerfile) { 341280304Sjkim BIO_puts(bio_err, "Illegal -inkey without -signer\n"); 342280304Sjkim goto argerr; 343280304Sjkim } 344280304Sjkim if (signerfile) { 345280304Sjkim if (!sksigners) 346280304Sjkim sksigners = sk_OPENSSL_STRING_new_null(); 347280304Sjkim sk_OPENSSL_STRING_push(sksigners, signerfile); 348280304Sjkim if (!skkeys) 349280304Sjkim skkeys = sk_OPENSSL_STRING_new_null(); 350280304Sjkim if (!keyfile) 351280304Sjkim keyfile = signerfile; 352280304Sjkim sk_OPENSSL_STRING_push(skkeys, keyfile); 353280304Sjkim } 354280304Sjkim if (!sksigners) { 355280304Sjkim BIO_printf(bio_err, "No signer certificate specified\n"); 356280304Sjkim badarg = 1; 357280304Sjkim } 358280304Sjkim signerfile = NULL; 359280304Sjkim keyfile = NULL; 360280304Sjkim need_rand = 1; 361280304Sjkim } else if (operation == SMIME_DECRYPT) { 362280304Sjkim if (!recipfile && !keyfile) { 363280304Sjkim BIO_printf(bio_err, 364280304Sjkim "No recipient certificate or key specified\n"); 365280304Sjkim badarg = 1; 366280304Sjkim } 367280304Sjkim } else if (operation == SMIME_ENCRYPT) { 368280304Sjkim if (!*args) { 369280304Sjkim BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); 370280304Sjkim badarg = 1; 371280304Sjkim } 372280304Sjkim need_rand = 1; 373280304Sjkim } else if (!operation) 374280304Sjkim badarg = 1; 37559191Skris 376280304Sjkim if (badarg) { 377280304Sjkim argerr: 378280304Sjkim BIO_printf(bio_err, "Usage smime [options] cert.pem ...\n"); 379280304Sjkim BIO_printf(bio_err, "where options are\n"); 380280304Sjkim BIO_printf(bio_err, "-encrypt encrypt message\n"); 381280304Sjkim BIO_printf(bio_err, "-decrypt decrypt encrypted message\n"); 382280304Sjkim BIO_printf(bio_err, "-sign sign message\n"); 383280304Sjkim BIO_printf(bio_err, "-verify verify signed message\n"); 384280304Sjkim BIO_printf(bio_err, "-pk7out output PKCS#7 structure\n"); 385109998Smarkm#ifndef OPENSSL_NO_DES 386280304Sjkim BIO_printf(bio_err, "-des3 encrypt with triple DES\n"); 387280304Sjkim BIO_printf(bio_err, "-des encrypt with DES\n"); 38859191Skris#endif 389194206Ssimon#ifndef OPENSSL_NO_SEED 390280304Sjkim BIO_printf(bio_err, "-seed encrypt with SEED\n"); 391194206Ssimon#endif 392109998Smarkm#ifndef OPENSSL_NO_RC2 393280304Sjkim BIO_printf(bio_err, "-rc2-40 encrypt with RC2-40 (default)\n"); 394280304Sjkim BIO_printf(bio_err, "-rc2-64 encrypt with RC2-64\n"); 395280304Sjkim BIO_printf(bio_err, "-rc2-128 encrypt with RC2-128\n"); 39659191Skris#endif 397109998Smarkm#ifndef OPENSSL_NO_AES 398280304Sjkim BIO_printf(bio_err, "-aes128, -aes192, -aes256\n"); 399280304Sjkim BIO_printf(bio_err, 400280304Sjkim " encrypt PEM output with cbc aes\n"); 401109998Smarkm#endif 402162911Ssimon#ifndef OPENSSL_NO_CAMELLIA 403280304Sjkim BIO_printf(bio_err, "-camellia128, -camellia192, -camellia256\n"); 404280304Sjkim BIO_printf(bio_err, 405280304Sjkim " encrypt PEM output with cbc camellia\n"); 406162911Ssimon#endif 407280304Sjkim BIO_printf(bio_err, 408280304Sjkim "-nointern don't search certificates in message for signer\n"); 409280304Sjkim BIO_printf(bio_err, 410280304Sjkim "-nosigs don't verify message signature\n"); 411280304Sjkim BIO_printf(bio_err, 412280304Sjkim "-noverify don't verify signers certificate\n"); 413280304Sjkim BIO_printf(bio_err, 414280304Sjkim "-nocerts don't include signers certificate when signing\n"); 415280304Sjkim BIO_printf(bio_err, "-nodetach use opaque signing\n"); 416280304Sjkim BIO_printf(bio_err, 417280304Sjkim "-noattr don't include any signed attributes\n"); 418280304Sjkim BIO_printf(bio_err, 419280304Sjkim "-binary don't translate message to text\n"); 420280304Sjkim BIO_printf(bio_err, "-certfile file other certificates file\n"); 421280304Sjkim BIO_printf(bio_err, "-signer file signer certificate file\n"); 422280304Sjkim BIO_printf(bio_err, 423280304Sjkim "-recip file recipient certificate file for decryption\n"); 424280304Sjkim BIO_printf(bio_err, "-in file input file\n"); 425280304Sjkim BIO_printf(bio_err, 426280304Sjkim "-inform arg input format SMIME (default), PEM or DER\n"); 427280304Sjkim BIO_printf(bio_err, 428280304Sjkim "-inkey file input private key (if not signer or recipient)\n"); 429280304Sjkim BIO_printf(bio_err, 430280304Sjkim "-keyform arg input private key format (PEM or ENGINE)\n"); 431280304Sjkim BIO_printf(bio_err, "-out file output file\n"); 432280304Sjkim BIO_printf(bio_err, 433280304Sjkim "-outform arg output format SMIME (default), PEM or DER\n"); 434280304Sjkim BIO_printf(bio_err, 435280304Sjkim "-content file supply or override content for detached signature\n"); 436280304Sjkim BIO_printf(bio_err, "-to addr to address\n"); 437280304Sjkim BIO_printf(bio_err, "-from ad from address\n"); 438280304Sjkim BIO_printf(bio_err, "-subject s subject\n"); 439280304Sjkim BIO_printf(bio_err, 440280304Sjkim "-text include or delete text MIME headers\n"); 441280304Sjkim BIO_printf(bio_err, 442280304Sjkim "-CApath dir trusted certificates directory\n"); 443280304Sjkim BIO_printf(bio_err, "-CAfile file trusted certificates file\n"); 444280304Sjkim BIO_printf(bio_err, 445284285Sjkim "-no_alt_chains only ever use the first certificate chain found\n"); 446284285Sjkim BIO_printf(bio_err, 447280304Sjkim "-crl_check check revocation status of signer's certificate using CRLs\n"); 448280304Sjkim BIO_printf(bio_err, 449280304Sjkim "-crl_check_all check revocation status of signer's certificate chain using CRLs\n"); 450111147Snectar#ifndef OPENSSL_NO_ENGINE 451280304Sjkim BIO_printf(bio_err, 452280304Sjkim "-engine e use engine e, possibly a hardware device.\n"); 453111147Snectar#endif 454280304Sjkim BIO_printf(bio_err, "-passin arg input file pass phrase source\n"); 455280304Sjkim BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, 456280304Sjkim LIST_SEPARATOR_CHAR); 457280304Sjkim BIO_printf(bio_err, 458280304Sjkim " load the file (or the files in the directory) into\n"); 459280304Sjkim BIO_printf(bio_err, " the random number generator\n"); 460280304Sjkim BIO_printf(bio_err, 461280304Sjkim "cert.pem recipient certificate(s) for encryption\n"); 462280304Sjkim goto end; 463280304Sjkim } 464111147Snectar#ifndef OPENSSL_NO_ENGINE 465280304Sjkim e = setup_engine(bio_err, engine, 0); 466111147Snectar#endif 467109998Smarkm 468280304Sjkim if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { 469280304Sjkim BIO_printf(bio_err, "Error getting password\n"); 470280304Sjkim goto end; 471280304Sjkim } 47259191Skris 473280304Sjkim if (need_rand) { 474280304Sjkim app_RAND_load_file(NULL, bio_err, (inrand != NULL)); 475280304Sjkim if (inrand != NULL) 476280304Sjkim BIO_printf(bio_err, "%ld semi-random bytes loaded\n", 477280304Sjkim app_RAND_load_files(inrand)); 478280304Sjkim } 47959191Skris 480280304Sjkim ret = 2; 48159191Skris 482280304Sjkim if (!(operation & SMIME_SIGNERS)) 483280304Sjkim flags &= ~PKCS7_DETACHED; 48459191Skris 485280304Sjkim if (operation & SMIME_OP) { 486280304Sjkim if (outformat == FORMAT_ASN1) 487280304Sjkim outmode = "wb"; 488280304Sjkim } else { 489280304Sjkim if (flags & PKCS7_BINARY) 490280304Sjkim outmode = "wb"; 491280304Sjkim } 492238405Sjkim 493280304Sjkim if (operation & SMIME_IP) { 494280304Sjkim if (informat == FORMAT_ASN1) 495280304Sjkim inmode = "rb"; 496280304Sjkim } else { 497280304Sjkim if (flags & PKCS7_BINARY) 498280304Sjkim inmode = "rb"; 499280304Sjkim } 50059191Skris 501280304Sjkim if (operation == SMIME_ENCRYPT) { 502280304Sjkim if (!cipher) { 503280304Sjkim#ifndef OPENSSL_NO_DES 504280304Sjkim cipher = EVP_des_ede3_cbc(); 50559191Skris#else 506280304Sjkim BIO_printf(bio_err, "No cipher selected\n"); 507280304Sjkim goto end; 50859191Skris#endif 509280304Sjkim } 510280304Sjkim encerts = sk_X509_new_null(); 511280304Sjkim while (*args) { 512280304Sjkim if (!(cert = load_cert(bio_err, *args, FORMAT_PEM, 513280304Sjkim NULL, e, "recipient certificate file"))) { 514280304Sjkim#if 0 /* An appropriate message is already printed */ 515280304Sjkim BIO_printf(bio_err, 516280304Sjkim "Can't read recipient certificate file %s\n", 517280304Sjkim *args); 518109998Smarkm#endif 519280304Sjkim goto end; 520280304Sjkim } 521280304Sjkim sk_X509_push(encerts, cert); 522280304Sjkim cert = NULL; 523280304Sjkim args++; 524280304Sjkim } 525280304Sjkim } 52659191Skris 527280304Sjkim if (certfile) { 528280304Sjkim if (!(other = load_certs(bio_err, certfile, FORMAT_PEM, NULL, 529280304Sjkim e, "certificate file"))) { 530280304Sjkim ERR_print_errors(bio_err); 531280304Sjkim goto end; 532280304Sjkim } 533280304Sjkim } 53459191Skris 535280304Sjkim if (recipfile && (operation == SMIME_DECRYPT)) { 536280304Sjkim if (!(recip = load_cert(bio_err, recipfile, FORMAT_PEM, NULL, 537280304Sjkim e, "recipient certificate file"))) { 538280304Sjkim ERR_print_errors(bio_err); 539280304Sjkim goto end; 540280304Sjkim } 541280304Sjkim } 54259191Skris 543280304Sjkim if (operation == SMIME_DECRYPT) { 544280304Sjkim if (!keyfile) 545280304Sjkim keyfile = recipfile; 546280304Sjkim } else if (operation == SMIME_SIGN) { 547280304Sjkim if (!keyfile) 548280304Sjkim keyfile = signerfile; 549280304Sjkim } else 550280304Sjkim keyfile = NULL; 55159191Skris 552280304Sjkim if (keyfile) { 553280304Sjkim key = load_key(bio_err, keyfile, keyform, 0, passin, e, 554280304Sjkim "signing key file"); 555280304Sjkim if (!key) 556280304Sjkim goto end; 557280304Sjkim } 55859191Skris 559280304Sjkim if (infile) { 560280304Sjkim if (!(in = BIO_new_file(infile, inmode))) { 561280304Sjkim BIO_printf(bio_err, "Can't open input file %s\n", infile); 562280304Sjkim goto end; 563280304Sjkim } 564280304Sjkim } else 565280304Sjkim in = BIO_new_fp(stdin, BIO_NOCLOSE); 56659191Skris 567280304Sjkim if (operation & SMIME_IP) { 568280304Sjkim if (informat == FORMAT_SMIME) 569280304Sjkim p7 = SMIME_read_PKCS7(in, &indata); 570280304Sjkim else if (informat == FORMAT_PEM) 571280304Sjkim p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); 572280304Sjkim else if (informat == FORMAT_ASN1) 573280304Sjkim p7 = d2i_PKCS7_bio(in, NULL); 574280304Sjkim else { 575280304Sjkim BIO_printf(bio_err, "Bad input format for PKCS#7 file\n"); 576280304Sjkim goto end; 577280304Sjkim } 578238405Sjkim 579280304Sjkim if (!p7) { 580280304Sjkim BIO_printf(bio_err, "Error reading S/MIME message\n"); 581280304Sjkim goto end; 582280304Sjkim } 583280304Sjkim if (contfile) { 584280304Sjkim BIO_free(indata); 585280304Sjkim if (!(indata = BIO_new_file(contfile, "rb"))) { 586280304Sjkim BIO_printf(bio_err, "Can't read content file %s\n", contfile); 587280304Sjkim goto end; 588280304Sjkim } 589280304Sjkim } 590280304Sjkim } 591238405Sjkim 592280304Sjkim if (outfile) { 593280304Sjkim if (!(out = BIO_new_file(outfile, outmode))) { 594280304Sjkim BIO_printf(bio_err, "Can't open output file %s\n", outfile); 595280304Sjkim goto end; 596280304Sjkim } 597280304Sjkim } else { 598280304Sjkim out = BIO_new_fp(stdout, BIO_NOCLOSE); 599109998Smarkm#ifdef OPENSSL_SYS_VMS 600280304Sjkim { 601280304Sjkim BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 602280304Sjkim out = BIO_push(tmpbio, out); 603280304Sjkim } 60468651Skris#endif 605280304Sjkim } 60659191Skris 607280304Sjkim if (operation == SMIME_VERIFY) { 608280304Sjkim if (!(store = setup_verify(bio_err, CAfile, CApath))) 609280304Sjkim goto end; 610280304Sjkim X509_STORE_set_verify_cb(store, smime_cb); 611280304Sjkim if (vpm) 612280304Sjkim X509_STORE_set1_param(store, vpm); 613280304Sjkim } 61459191Skris 615280304Sjkim ret = 3; 616109998Smarkm 617280304Sjkim if (operation == SMIME_ENCRYPT) { 618280304Sjkim if (indef) 619280304Sjkim flags |= PKCS7_STREAM; 620280304Sjkim p7 = PKCS7_encrypt(encerts, in, cipher, flags); 621280304Sjkim } else if (operation & SMIME_SIGNERS) { 622280304Sjkim int i; 623280304Sjkim /* 624280304Sjkim * If detached data content we only enable streaming if S/MIME output 625280304Sjkim * format. 626280304Sjkim */ 627280304Sjkim if (operation == SMIME_SIGN) { 628280304Sjkim if (flags & PKCS7_DETACHED) { 629280304Sjkim if (outformat == FORMAT_SMIME) 630280304Sjkim flags |= PKCS7_STREAM; 631280304Sjkim } else if (indef) 632280304Sjkim flags |= PKCS7_STREAM; 633280304Sjkim flags |= PKCS7_PARTIAL; 634280304Sjkim p7 = PKCS7_sign(NULL, NULL, other, in, flags); 635280304Sjkim if (!p7) 636280304Sjkim goto end; 637280304Sjkim } else 638280304Sjkim flags |= PKCS7_REUSE_DIGEST; 639280304Sjkim for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) { 640280304Sjkim signerfile = sk_OPENSSL_STRING_value(sksigners, i); 641280304Sjkim keyfile = sk_OPENSSL_STRING_value(skkeys, i); 642280304Sjkim signer = load_cert(bio_err, signerfile, FORMAT_PEM, NULL, 643280304Sjkim e, "signer certificate"); 644280304Sjkim if (!signer) 645280304Sjkim goto end; 646280304Sjkim key = load_key(bio_err, keyfile, keyform, 0, passin, e, 647280304Sjkim "signing key file"); 648280304Sjkim if (!key) 649280304Sjkim goto end; 650280304Sjkim if (!PKCS7_sign_add_signer(p7, signer, key, sign_md, flags)) 651280304Sjkim goto end; 652280304Sjkim X509_free(signer); 653280304Sjkim signer = NULL; 654280304Sjkim EVP_PKEY_free(key); 655280304Sjkim key = NULL; 656280304Sjkim } 657280304Sjkim /* If not streaming or resigning finalize structure */ 658280304Sjkim if ((operation == SMIME_SIGN) && !(flags & PKCS7_STREAM)) { 659280304Sjkim if (!PKCS7_final(p7, in, flags)) 660280304Sjkim goto end; 661280304Sjkim } 662280304Sjkim } 66359191Skris 664280304Sjkim if (!p7) { 665280304Sjkim BIO_printf(bio_err, "Error creating PKCS#7 structure\n"); 666280304Sjkim goto end; 667280304Sjkim } 66859191Skris 669280304Sjkim ret = 4; 670280304Sjkim if (operation == SMIME_DECRYPT) { 671280304Sjkim if (!PKCS7_decrypt(p7, key, recip, out, flags)) { 672280304Sjkim BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n"); 673280304Sjkim goto end; 674280304Sjkim } 675280304Sjkim } else if (operation == SMIME_VERIFY) { 676280304Sjkim STACK_OF(X509) *signers; 677280304Sjkim if (PKCS7_verify(p7, other, store, indata, out, flags)) 678280304Sjkim BIO_printf(bio_err, "Verification successful\n"); 679280304Sjkim else { 680280304Sjkim BIO_printf(bio_err, "Verification failure\n"); 681280304Sjkim goto end; 682280304Sjkim } 683280304Sjkim signers = PKCS7_get0_signers(p7, other, flags); 684280304Sjkim if (!save_certs(signerfile, signers)) { 685280304Sjkim BIO_printf(bio_err, "Error writing signers to %s\n", signerfile); 686280304Sjkim ret = 5; 687280304Sjkim goto end; 688280304Sjkim } 689280304Sjkim sk_X509_free(signers); 690280304Sjkim } else if (operation == SMIME_PK7OUT) 691280304Sjkim PEM_write_bio_PKCS7(out, p7); 692280304Sjkim else { 693280304Sjkim if (to) 694280304Sjkim BIO_printf(out, "To: %s\n", to); 695280304Sjkim if (from) 696280304Sjkim BIO_printf(out, "From: %s\n", from); 697280304Sjkim if (subject) 698280304Sjkim BIO_printf(out, "Subject: %s\n", subject); 699280304Sjkim if (outformat == FORMAT_SMIME) { 700280304Sjkim if (operation == SMIME_RESIGN) 701280304Sjkim SMIME_write_PKCS7(out, p7, indata, flags); 702280304Sjkim else 703280304Sjkim SMIME_write_PKCS7(out, p7, in, flags); 704280304Sjkim } else if (outformat == FORMAT_PEM) 705280304Sjkim PEM_write_bio_PKCS7_stream(out, p7, in, flags); 706280304Sjkim else if (outformat == FORMAT_ASN1) 707280304Sjkim i2d_PKCS7_bio_stream(out, p7, in, flags); 708280304Sjkim else { 709280304Sjkim BIO_printf(bio_err, "Bad output format for PKCS#7 file\n"); 710280304Sjkim goto end; 711280304Sjkim } 712280304Sjkim } 713280304Sjkim ret = 0; 714280304Sjkim end: 715280304Sjkim if (need_rand) 716280304Sjkim app_RAND_write_file(NULL, bio_err); 717280304Sjkim if (ret) 718280304Sjkim ERR_print_errors(bio_err); 719280304Sjkim sk_X509_pop_free(encerts, X509_free); 720280304Sjkim sk_X509_pop_free(other, X509_free); 721280304Sjkim if (vpm) 722280304Sjkim X509_VERIFY_PARAM_free(vpm); 723280304Sjkim if (sksigners) 724280304Sjkim sk_OPENSSL_STRING_free(sksigners); 725280304Sjkim if (skkeys) 726280304Sjkim sk_OPENSSL_STRING_free(skkeys); 727280304Sjkim X509_STORE_free(store); 728280304Sjkim X509_free(cert); 729280304Sjkim X509_free(recip); 730280304Sjkim X509_free(signer); 731280304Sjkim EVP_PKEY_free(key); 732280304Sjkim PKCS7_free(p7); 733280304Sjkim BIO_free(in); 734280304Sjkim BIO_free(indata); 735280304Sjkim BIO_free_all(out); 736280304Sjkim if (passin) 737280304Sjkim OPENSSL_free(passin); 738280304Sjkim return (ret); 73959191Skris} 74059191Skris 74159191Skrisstatic int save_certs(char *signerfile, STACK_OF(X509) *signers) 742280304Sjkim{ 743280304Sjkim int i; 744280304Sjkim BIO *tmp; 745280304Sjkim if (!signerfile) 746280304Sjkim return 1; 747280304Sjkim tmp = BIO_new_file(signerfile, "w"); 748280304Sjkim if (!tmp) 749280304Sjkim return 0; 750280304Sjkim for (i = 0; i < sk_X509_num(signers); i++) 751280304Sjkim PEM_write_bio_X509(tmp, sk_X509_value(signers, i)); 752280304Sjkim BIO_free(tmp); 753280304Sjkim return 1; 754280304Sjkim} 755160814Ssimon 756160814Ssimon/* Minimal callback just to output policy info (if any) */ 757160814Ssimon 758160814Ssimonstatic int smime_cb(int ok, X509_STORE_CTX *ctx) 759280304Sjkim{ 760280304Sjkim int error; 761160814Ssimon 762280304Sjkim error = X509_STORE_CTX_get_error(ctx); 763160814Ssimon 764280304Sjkim if ((error != X509_V_ERR_NO_EXPLICIT_POLICY) 765280304Sjkim && ((error != X509_V_OK) || (ok != 2))) 766280304Sjkim return ok; 767160814Ssimon 768280304Sjkim policies_print(NULL, ctx); 769160814Ssimon 770280304Sjkim return ok; 771160814Ssimon 772280304Sjkim} 773