159191Skris/* smime.c */ 2194206Ssimon/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3160814Ssimon * project. 459191Skris */ 559191Skris/* ==================================================================== 6160814Ssimon * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. 759191Skris * 859191Skris * Redistribution and use in source and binary forms, with or without 959191Skris * modification, are permitted provided that the following conditions 1059191Skris * are met: 1159191Skris * 1259191Skris * 1. Redistributions of source code must retain the above copyright 1359191Skris * notice, this list of conditions and the following disclaimer. 1459191Skris * 1559191Skris * 2. Redistributions in binary form must reproduce the above copyright 1659191Skris * notice, this list of conditions and the following disclaimer in 1759191Skris * the documentation and/or other materials provided with the 1859191Skris * distribution. 1959191Skris * 2059191Skris * 3. All advertising materials mentioning features or use of this 2159191Skris * software must display the following acknowledgment: 2259191Skris * "This product includes software developed by the OpenSSL Project 2359191Skris * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2459191Skris * 2559191Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2659191Skris * endorse or promote products derived from this software without 2759191Skris * prior written permission. For written permission, please contact 2859191Skris * licensing@OpenSSL.org. 2959191Skris * 3059191Skris * 5. Products derived from this software may not be called "OpenSSL" 3159191Skris * nor may "OpenSSL" appear in their names without prior written 3259191Skris * permission of the OpenSSL Project. 3359191Skris * 3459191Skris * 6. Redistributions of any form whatsoever must retain the following 3559191Skris * acknowledgment: 3659191Skris * "This product includes software developed by the OpenSSL Project 3759191Skris * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3859191Skris * 3959191Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 4059191Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4159191Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4259191Skris * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4359191Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4459191Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4559191Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4659191Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4759191Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4859191Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 4959191Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 5059191Skris * OF THE POSSIBILITY OF SUCH DAMAGE. 5159191Skris * ==================================================================== 5259191Skris * 5359191Skris * This product includes cryptographic software written by Eric Young 5459191Skris * (eay@cryptsoft.com). This product includes software written by Tim 5559191Skris * Hudson (tjh@cryptsoft.com). 5659191Skris * 5759191Skris */ 5859191Skris 5959191Skris/* S/MIME utility function */ 6059191Skris 6159191Skris#include <stdio.h> 6259191Skris#include <string.h> 6359191Skris#include "apps.h" 6459191Skris#include <openssl/crypto.h> 6559191Skris#include <openssl/pem.h> 6659191Skris#include <openssl/err.h> 67160814Ssimon#include <openssl/x509_vfy.h> 68160814Ssimon#include <openssl/x509v3.h> 6959191Skris 7059191Skris#undef PROG 7159191Skris#define PROG smime_main 7259191Skrisstatic int save_certs(char *signerfile, STACK_OF(X509) *signers); 73160814Ssimonstatic int smime_cb(int ok, X509_STORE_CTX *ctx); 7459191Skris 7559191Skris#define SMIME_OP 0x10 76238405Sjkim#define SMIME_IP 0x20 77238405Sjkim#define SMIME_SIGNERS 0x40 7859191Skris#define SMIME_ENCRYPT (1 | SMIME_OP) 79238405Sjkim#define SMIME_DECRYPT (2 | SMIME_IP) 80238405Sjkim#define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS) 81238405Sjkim#define SMIME_VERIFY (4 | SMIME_IP) 82238405Sjkim#define SMIME_PK7OUT (5 | SMIME_IP | SMIME_OP) 83238405Sjkim#define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS) 8459191Skris 8559191Skrisint MAIN(int, char **); 8659191Skris 8759191Skrisint MAIN(int argc, char **argv) 88160814Ssimon { 89109998Smarkm ENGINE *e = NULL; 9059191Skris int operation = 0; 9159191Skris int ret = 0; 9259191Skris char **args; 93160814Ssimon const char *inmode = "r", *outmode = "w"; 9459191Skris char *infile = NULL, *outfile = NULL; 9559191Skris char *signerfile = NULL, *recipfile = NULL; 96238405Sjkim STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL; 9768651Skris char *certfile = NULL, *keyfile = NULL, *contfile=NULL; 98109998Smarkm const EVP_CIPHER *cipher = NULL; 9959191Skris PKCS7 *p7 = NULL; 10059191Skris X509_STORE *store = NULL; 10159191Skris X509 *cert = NULL, *recip = NULL, *signer = NULL; 10259191Skris EVP_PKEY *key = NULL; 10359191Skris STACK_OF(X509) *encerts = NULL, *other = NULL; 10459191Skris BIO *in = NULL, *out = NULL, *indata = NULL; 10559191Skris int badarg = 0; 106160814Ssimon int flags = PKCS7_DETACHED; 10759191Skris char *to = NULL, *from = NULL, *subject = NULL; 10859191Skris char *CAfile = NULL, *CApath = NULL; 10959191Skris char *passargin = NULL, *passin = NULL; 11059191Skris char *inrand = NULL; 11159191Skris int need_rand = 0; 112238405Sjkim int indef = 0; 113238405Sjkim const EVP_MD *sign_md = NULL; 11468651Skris int informat = FORMAT_SMIME, outformat = FORMAT_SMIME; 115109998Smarkm int keyform = FORMAT_PEM; 116111147Snectar#ifndef OPENSSL_NO_ENGINE 117109998Smarkm char *engine=NULL; 118111147Snectar#endif 119109998Smarkm 120160814Ssimon X509_VERIFY_PARAM *vpm = NULL; 121160814Ssimon 12259191Skris args = argv + 1; 12359191Skris ret = 1; 12459191Skris 125109998Smarkm apps_startup(); 126109998Smarkm 127109998Smarkm if (bio_err == NULL) 128160814Ssimon { 129109998Smarkm if ((bio_err = BIO_new(BIO_s_file())) != NULL) 130109998Smarkm BIO_set_fp(bio_err, stderr, BIO_NOCLOSE|BIO_FP_TEXT); 131160814Ssimon } 132109998Smarkm 133109998Smarkm if (!load_config(bio_err, NULL)) 134109998Smarkm goto end; 135109998Smarkm 136160814Ssimon while (!badarg && *args && *args[0] == '-') 137160814Ssimon { 138160814Ssimon if (!strcmp (*args, "-encrypt")) 139160814Ssimon operation = SMIME_ENCRYPT; 140160814Ssimon else if (!strcmp (*args, "-decrypt")) 141160814Ssimon operation = SMIME_DECRYPT; 142160814Ssimon else if (!strcmp (*args, "-sign")) 143160814Ssimon operation = SMIME_SIGN; 144238405Sjkim else if (!strcmp (*args, "-resign")) 145238405Sjkim operation = SMIME_RESIGN; 146160814Ssimon else if (!strcmp (*args, "-verify")) 147160814Ssimon operation = SMIME_VERIFY; 148160814Ssimon else if (!strcmp (*args, "-pk7out")) 149160814Ssimon operation = SMIME_PK7OUT; 150109998Smarkm#ifndef OPENSSL_NO_DES 15159191Skris else if (!strcmp (*args, "-des3")) 15259191Skris cipher = EVP_des_ede3_cbc(); 15359191Skris else if (!strcmp (*args, "-des")) 15459191Skris cipher = EVP_des_cbc(); 15559191Skris#endif 156194206Ssimon#ifndef OPENSSL_NO_SEED 157194206Ssimon else if (!strcmp (*args, "-seed")) 158194206Ssimon cipher = EVP_seed_cbc(); 159194206Ssimon#endif 160109998Smarkm#ifndef OPENSSL_NO_RC2 16159191Skris else if (!strcmp (*args, "-rc2-40")) 16259191Skris cipher = EVP_rc2_40_cbc(); 16359191Skris else if (!strcmp (*args, "-rc2-128")) 16459191Skris cipher = EVP_rc2_cbc(); 16559191Skris else if (!strcmp (*args, "-rc2-64")) 16659191Skris cipher = EVP_rc2_64_cbc(); 16759191Skris#endif 168109998Smarkm#ifndef OPENSSL_NO_AES 169109998Smarkm else if (!strcmp(*args,"-aes128")) 170109998Smarkm cipher = EVP_aes_128_cbc(); 171109998Smarkm else if (!strcmp(*args,"-aes192")) 172109998Smarkm cipher = EVP_aes_192_cbc(); 173109998Smarkm else if (!strcmp(*args,"-aes256")) 174109998Smarkm cipher = EVP_aes_256_cbc(); 175109998Smarkm#endif 176162911Ssimon#ifndef OPENSSL_NO_CAMELLIA 177162911Ssimon else if (!strcmp(*args,"-camellia128")) 178162911Ssimon cipher = EVP_camellia_128_cbc(); 179162911Ssimon else if (!strcmp(*args,"-camellia192")) 180162911Ssimon cipher = EVP_camellia_192_cbc(); 181162911Ssimon else if (!strcmp(*args,"-camellia256")) 182162911Ssimon cipher = EVP_camellia_256_cbc(); 183162911Ssimon#endif 18459191Skris else if (!strcmp (*args, "-text")) 18559191Skris flags |= PKCS7_TEXT; 18659191Skris else if (!strcmp (*args, "-nointern")) 18759191Skris flags |= PKCS7_NOINTERN; 18859191Skris else if (!strcmp (*args, "-noverify")) 18959191Skris flags |= PKCS7_NOVERIFY; 19059191Skris else if (!strcmp (*args, "-nochain")) 19159191Skris flags |= PKCS7_NOCHAIN; 19259191Skris else if (!strcmp (*args, "-nocerts")) 19359191Skris flags |= PKCS7_NOCERTS; 19459191Skris else if (!strcmp (*args, "-noattr")) 19559191Skris flags |= PKCS7_NOATTR; 19659191Skris else if (!strcmp (*args, "-nodetach")) 19759191Skris flags &= ~PKCS7_DETACHED; 19868651Skris else if (!strcmp (*args, "-nosmimecap")) 19968651Skris flags |= PKCS7_NOSMIMECAP; 20059191Skris else if (!strcmp (*args, "-binary")) 20159191Skris flags |= PKCS7_BINARY; 20259191Skris else if (!strcmp (*args, "-nosigs")) 20359191Skris flags |= PKCS7_NOSIGS; 204238405Sjkim else if (!strcmp (*args, "-stream")) 205238405Sjkim indef = 1; 206238405Sjkim else if (!strcmp (*args, "-indef")) 207238405Sjkim indef = 1; 208238405Sjkim else if (!strcmp (*args, "-noindef")) 209238405Sjkim indef = 0; 210120631Snectar else if (!strcmp (*args, "-nooldmime")) 211120631Snectar flags |= PKCS7_NOOLDMIMETYPE; 212120631Snectar else if (!strcmp (*args, "-crlfeol")) 213120631Snectar flags |= PKCS7_CRLFEOL; 214160814Ssimon else if (!strcmp(*args,"-rand")) 215160814Ssimon { 216238405Sjkim if (!args[1]) 217238405Sjkim goto argerr; 218238405Sjkim args++; 219238405Sjkim inrand = *args; 22059191Skris need_rand = 1; 221160814Ssimon } 222111147Snectar#ifndef OPENSSL_NO_ENGINE 223160814Ssimon else if (!strcmp(*args,"-engine")) 224160814Ssimon { 225238405Sjkim if (!args[1]) 226238405Sjkim goto argerr; 227238405Sjkim engine = *++args; 228160814Ssimon } 229111147Snectar#endif 230160814Ssimon else if (!strcmp(*args,"-passin")) 231160814Ssimon { 232238405Sjkim if (!args[1]) 233238405Sjkim goto argerr; 234238405Sjkim passargin = *++args; 235160814Ssimon } 236160814Ssimon else if (!strcmp (*args, "-to")) 237160814Ssimon { 238238405Sjkim if (!args[1]) 239238405Sjkim goto argerr; 240238405Sjkim to = *++args; 241160814Ssimon } 242160814Ssimon else if (!strcmp (*args, "-from")) 243160814Ssimon { 244238405Sjkim if (!args[1]) 245238405Sjkim goto argerr; 246238405Sjkim from = *++args; 247160814Ssimon } 248160814Ssimon else if (!strcmp (*args, "-subject")) 249160814Ssimon { 250238405Sjkim if (!args[1]) 251238405Sjkim goto argerr; 252238405Sjkim subject = *++args; 253160814Ssimon } 254160814Ssimon else if (!strcmp (*args, "-signer")) 255160814Ssimon { 256238405Sjkim if (!args[1]) 257238405Sjkim goto argerr; 258238405Sjkim /* If previous -signer argument add signer to list */ 259238405Sjkim 260238405Sjkim if (signerfile) 261160814Ssimon { 262238405Sjkim if (!sksigners) 263238405Sjkim sksigners = sk_OPENSSL_STRING_new_null(); 264238405Sjkim sk_OPENSSL_STRING_push(sksigners, signerfile); 265238405Sjkim if (!keyfile) 266238405Sjkim keyfile = signerfile; 267238405Sjkim if (!skkeys) 268238405Sjkim skkeys = sk_OPENSSL_STRING_new_null(); 269238405Sjkim sk_OPENSSL_STRING_push(skkeys, keyfile); 270238405Sjkim keyfile = NULL; 271160814Ssimon } 272238405Sjkim signerfile = *++args; 273160814Ssimon } 274160814Ssimon else if (!strcmp (*args, "-recip")) 275160814Ssimon { 276238405Sjkim if (!args[1]) 277238405Sjkim goto argerr; 278238405Sjkim recipfile = *++args; 279238405Sjkim } 280238405Sjkim else if (!strcmp (*args, "-md")) 281238405Sjkim { 282238405Sjkim if (!args[1]) 283238405Sjkim goto argerr; 284238405Sjkim sign_md = EVP_get_digestbyname(*++args); 285238405Sjkim if (sign_md == NULL) 286160814Ssimon { 287238405Sjkim BIO_printf(bio_err, "Unknown digest %s\n", 288238405Sjkim *args); 289238405Sjkim goto argerr; 290160814Ssimon } 291160814Ssimon } 292160814Ssimon else if (!strcmp (*args, "-inkey")) 293160814Ssimon { 294238405Sjkim if (!args[1]) 295238405Sjkim goto argerr; 296238405Sjkim /* If previous -inkey arument add signer to list */ 297238405Sjkim if (keyfile) 298160814Ssimon { 299238405Sjkim if (!signerfile) 300238405Sjkim { 301238405Sjkim BIO_puts(bio_err, "Illegal -inkey without -signer\n"); 302238405Sjkim goto argerr; 303238405Sjkim } 304238405Sjkim if (!sksigners) 305238405Sjkim sksigners = sk_OPENSSL_STRING_new_null(); 306238405Sjkim sk_OPENSSL_STRING_push(sksigners, signerfile); 307238405Sjkim signerfile = NULL; 308238405Sjkim if (!skkeys) 309238405Sjkim skkeys = sk_OPENSSL_STRING_new_null(); 310238405Sjkim sk_OPENSSL_STRING_push(skkeys, keyfile); 311160814Ssimon } 312238405Sjkim keyfile = *++args; 313238405Sjkim } 314160814Ssimon else if (!strcmp (*args, "-keyform")) 315160814Ssimon { 316238405Sjkim if (!args[1]) 317238405Sjkim goto argerr; 318238405Sjkim keyform = str2fmt(*++args); 319160814Ssimon } 320160814Ssimon else if (!strcmp (*args, "-certfile")) 321160814Ssimon { 322238405Sjkim if (!args[1]) 323238405Sjkim goto argerr; 324238405Sjkim certfile = *++args; 325160814Ssimon } 326160814Ssimon else if (!strcmp (*args, "-CAfile")) 327160814Ssimon { 328238405Sjkim if (!args[1]) 329238405Sjkim goto argerr; 330238405Sjkim CAfile = *++args; 331160814Ssimon } 332160814Ssimon else if (!strcmp (*args, "-CApath")) 333160814Ssimon { 334238405Sjkim if (!args[1]) 335238405Sjkim goto argerr; 336238405Sjkim CApath = *++args; 337160814Ssimon } 338160814Ssimon else if (!strcmp (*args, "-in")) 339160814Ssimon { 340238405Sjkim if (!args[1]) 341238405Sjkim goto argerr; 342238405Sjkim infile = *++args; 343160814Ssimon } 344160814Ssimon else if (!strcmp (*args, "-inform")) 345160814Ssimon { 346238405Sjkim if (!args[1]) 347238405Sjkim goto argerr; 348238405Sjkim informat = str2fmt(*++args); 349160814Ssimon } 350160814Ssimon else if (!strcmp (*args, "-outform")) 351160814Ssimon { 352238405Sjkim if (!args[1]) 353238405Sjkim goto argerr; 354238405Sjkim outformat = str2fmt(*++args); 355160814Ssimon } 356160814Ssimon else if (!strcmp (*args, "-out")) 357160814Ssimon { 358238405Sjkim if (!args[1]) 359238405Sjkim goto argerr; 360238405Sjkim outfile = *++args; 361160814Ssimon } 362160814Ssimon else if (!strcmp (*args, "-content")) 363160814Ssimon { 364238405Sjkim if (!args[1]) 365238405Sjkim goto argerr; 366238405Sjkim contfile = *++args; 367160814Ssimon } 368160814Ssimon else if (args_verify(&args, NULL, &badarg, bio_err, &vpm)) 369160814Ssimon continue; 370238405Sjkim else if ((cipher = EVP_get_cipherbyname(*args + 1)) == NULL) 371160814Ssimon badarg = 1; 37259191Skris args++; 373160814Ssimon } 37459191Skris 375238405Sjkim if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners)) 376238405Sjkim { 377238405Sjkim BIO_puts(bio_err, "Multiple signers or keys not allowed\n"); 378238405Sjkim goto argerr; 379238405Sjkim } 380160814Ssimon 381238405Sjkim if (operation & SMIME_SIGNERS) 382160814Ssimon { 383238405Sjkim /* Check to see if any final signer needs to be appended */ 384238405Sjkim if (keyfile && !signerfile) 385160814Ssimon { 386238405Sjkim BIO_puts(bio_err, "Illegal -inkey without -signer\n"); 387238405Sjkim goto argerr; 388238405Sjkim } 389238405Sjkim if (signerfile) 390238405Sjkim { 391238405Sjkim if (!sksigners) 392238405Sjkim sksigners = sk_OPENSSL_STRING_new_null(); 393238405Sjkim sk_OPENSSL_STRING_push(sksigners, signerfile); 394238405Sjkim if (!skkeys) 395238405Sjkim skkeys = sk_OPENSSL_STRING_new_null(); 396238405Sjkim if (!keyfile) 397238405Sjkim keyfile = signerfile; 398238405Sjkim sk_OPENSSL_STRING_push(skkeys, keyfile); 399238405Sjkim } 400238405Sjkim if (!sksigners) 401238405Sjkim { 40259191Skris BIO_printf(bio_err, "No signer certificate specified\n"); 40359191Skris badarg = 1; 404160814Ssimon } 405238405Sjkim signerfile = NULL; 406238405Sjkim keyfile = NULL; 407160814Ssimon need_rand = 1; 40859191Skris } 409160814Ssimon else if (operation == SMIME_DECRYPT) 410160814Ssimon { 411160814Ssimon if (!recipfile && !keyfile) 412160814Ssimon { 413160814Ssimon BIO_printf(bio_err, "No recipient certificate or key specified\n"); 41459191Skris badarg = 1; 415160814Ssimon } 41659191Skris } 417160814Ssimon else if (operation == SMIME_ENCRYPT) 418160814Ssimon { 419160814Ssimon if (!*args) 420160814Ssimon { 42159191Skris BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); 42259191Skris badarg = 1; 423160814Ssimon } 424160814Ssimon need_rand = 1; 42559191Skris } 426160814Ssimon else if (!operation) 427160814Ssimon badarg = 1; 42859191Skris 429160814Ssimon if (badarg) 430160814Ssimon { 431238405Sjkim argerr: 43259191Skris BIO_printf (bio_err, "Usage smime [options] cert.pem ...\n"); 43359191Skris BIO_printf (bio_err, "where options are\n"); 43459191Skris BIO_printf (bio_err, "-encrypt encrypt message\n"); 43559191Skris BIO_printf (bio_err, "-decrypt decrypt encrypted message\n"); 43659191Skris BIO_printf (bio_err, "-sign sign message\n"); 43759191Skris BIO_printf (bio_err, "-verify verify signed message\n"); 43859191Skris BIO_printf (bio_err, "-pk7out output PKCS#7 structure\n"); 439109998Smarkm#ifndef OPENSSL_NO_DES 44059191Skris BIO_printf (bio_err, "-des3 encrypt with triple DES\n"); 44159191Skris BIO_printf (bio_err, "-des encrypt with DES\n"); 44259191Skris#endif 443194206Ssimon#ifndef OPENSSL_NO_SEED 444194206Ssimon BIO_printf (bio_err, "-seed encrypt with SEED\n"); 445194206Ssimon#endif 446109998Smarkm#ifndef OPENSSL_NO_RC2 44759191Skris BIO_printf (bio_err, "-rc2-40 encrypt with RC2-40 (default)\n"); 44859191Skris BIO_printf (bio_err, "-rc2-64 encrypt with RC2-64\n"); 44959191Skris BIO_printf (bio_err, "-rc2-128 encrypt with RC2-128\n"); 45059191Skris#endif 451109998Smarkm#ifndef OPENSSL_NO_AES 452109998Smarkm BIO_printf (bio_err, "-aes128, -aes192, -aes256\n"); 453109998Smarkm BIO_printf (bio_err, " encrypt PEM output with cbc aes\n"); 454109998Smarkm#endif 455162911Ssimon#ifndef OPENSSL_NO_CAMELLIA 456162911Ssimon BIO_printf (bio_err, "-camellia128, -camellia192, -camellia256\n"); 457162911Ssimon BIO_printf (bio_err, " encrypt PEM output with cbc camellia\n"); 458162911Ssimon#endif 45959191Skris BIO_printf (bio_err, "-nointern don't search certificates in message for signer\n"); 46059191Skris BIO_printf (bio_err, "-nosigs don't verify message signature\n"); 46159191Skris BIO_printf (bio_err, "-noverify don't verify signers certificate\n"); 46259191Skris BIO_printf (bio_err, "-nocerts don't include signers certificate when signing\n"); 46359191Skris BIO_printf (bio_err, "-nodetach use opaque signing\n"); 46459191Skris BIO_printf (bio_err, "-noattr don't include any signed attributes\n"); 46559191Skris BIO_printf (bio_err, "-binary don't translate message to text\n"); 46659191Skris BIO_printf (bio_err, "-certfile file other certificates file\n"); 46759191Skris BIO_printf (bio_err, "-signer file signer certificate file\n"); 46859191Skris BIO_printf (bio_err, "-recip file recipient certificate file for decryption\n"); 46959191Skris BIO_printf (bio_err, "-in file input file\n"); 47068651Skris BIO_printf (bio_err, "-inform arg input format SMIME (default), PEM or DER\n"); 47159191Skris BIO_printf (bio_err, "-inkey file input private key (if not signer or recipient)\n"); 472109998Smarkm BIO_printf (bio_err, "-keyform arg input private key format (PEM or ENGINE)\n"); 47359191Skris BIO_printf (bio_err, "-out file output file\n"); 47468651Skris BIO_printf (bio_err, "-outform arg output format SMIME (default), PEM or DER\n"); 47568651Skris BIO_printf (bio_err, "-content file supply or override content for detached signature\n"); 47659191Skris BIO_printf (bio_err, "-to addr to address\n"); 47759191Skris BIO_printf (bio_err, "-from ad from address\n"); 47859191Skris BIO_printf (bio_err, "-subject s subject\n"); 47959191Skris BIO_printf (bio_err, "-text include or delete text MIME headers\n"); 48059191Skris BIO_printf (bio_err, "-CApath dir trusted certificates directory\n"); 48159191Skris BIO_printf (bio_err, "-CAfile file trusted certificates file\n"); 482109998Smarkm BIO_printf (bio_err, "-crl_check check revocation status of signer's certificate using CRLs\n"); 483109998Smarkm BIO_printf (bio_err, "-crl_check_all check revocation status of signer's certificate chain using CRLs\n"); 484111147Snectar#ifndef OPENSSL_NO_ENGINE 485109998Smarkm BIO_printf (bio_err, "-engine e use engine e, possibly a hardware device.\n"); 486111147Snectar#endif 48779998Skris BIO_printf (bio_err, "-passin arg input file pass phrase source\n"); 48859191Skris BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); 48959191Skris BIO_printf(bio_err, " load the file (or the files in the directory) into\n"); 49059191Skris BIO_printf(bio_err, " the random number generator\n"); 49159191Skris BIO_printf (bio_err, "cert.pem recipient certificate(s) for encryption\n"); 49259191Skris goto end; 493160814Ssimon } 49459191Skris 495111147Snectar#ifndef OPENSSL_NO_ENGINE 496109998Smarkm e = setup_engine(bio_err, engine, 0); 497111147Snectar#endif 498109998Smarkm 499160814Ssimon if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) 500160814Ssimon { 50159191Skris BIO_printf(bio_err, "Error getting password\n"); 50259191Skris goto end; 503160814Ssimon } 50459191Skris 505160814Ssimon if (need_rand) 506160814Ssimon { 50759191Skris app_RAND_load_file(NULL, bio_err, (inrand != NULL)); 50859191Skris if (inrand != NULL) 50959191Skris BIO_printf(bio_err,"%ld semi-random bytes loaded\n", 51059191Skris app_RAND_load_files(inrand)); 511160814Ssimon } 51259191Skris 51359191Skris ret = 2; 51459191Skris 515238405Sjkim if (!(operation & SMIME_SIGNERS)) 516160814Ssimon flags &= ~PKCS7_DETACHED; 51759191Skris 518160814Ssimon if (operation & SMIME_OP) 519160814Ssimon { 520160814Ssimon if (outformat == FORMAT_ASN1) 521160814Ssimon outmode = "wb"; 522160814Ssimon } 523160814Ssimon else 524160814Ssimon { 525160814Ssimon if (flags & PKCS7_BINARY) 526160814Ssimon outmode = "wb"; 527238405Sjkim } 528238405Sjkim 529238405Sjkim if (operation & SMIME_IP) 530238405Sjkim { 531160814Ssimon if (informat == FORMAT_ASN1) 532160814Ssimon inmode = "rb"; 533160814Ssimon } 534238405Sjkim else 535238405Sjkim { 536238405Sjkim if (flags & PKCS7_BINARY) 537238405Sjkim inmode = "rb"; 538238405Sjkim } 53959191Skris 540160814Ssimon if (operation == SMIME_ENCRYPT) 541160814Ssimon { 542160814Ssimon if (!cipher) 543160814Ssimon { 544279264Sdelphij#ifndef OPENSSL_NO_DES 545279264Sdelphij cipher = EVP_des_ede3_cbc(); 54659191Skris#else 54759191Skris BIO_printf(bio_err, "No cipher selected\n"); 54859191Skris goto end; 54959191Skris#endif 550160814Ssimon } 55159191Skris encerts = sk_X509_new_null(); 552160814Ssimon while (*args) 553160814Ssimon { 554160814Ssimon if (!(cert = load_cert(bio_err,*args,FORMAT_PEM, 555160814Ssimon NULL, e, "recipient certificate file"))) 556160814Ssimon { 557109998Smarkm#if 0 /* An appropriate message is already printed */ 55859191Skris BIO_printf(bio_err, "Can't read recipient certificate file %s\n", *args); 559109998Smarkm#endif 56059191Skris goto end; 561160814Ssimon } 56259191Skris sk_X509_push(encerts, cert); 56359191Skris cert = NULL; 56459191Skris args++; 565160814Ssimon } 56659191Skris } 56759191Skris 568160814Ssimon if (certfile) 569160814Ssimon { 570160814Ssimon if (!(other = load_certs(bio_err,certfile,FORMAT_PEM, NULL, 571160814Ssimon e, "certificate file"))) 572160814Ssimon { 57359191Skris ERR_print_errors(bio_err); 57459191Skris goto end; 575160814Ssimon } 57659191Skris } 57759191Skris 578160814Ssimon if (recipfile && (operation == SMIME_DECRYPT)) 579160814Ssimon { 580160814Ssimon if (!(recip = load_cert(bio_err,recipfile,FORMAT_PEM,NULL, 581160814Ssimon e, "recipient certificate file"))) 582160814Ssimon { 58359191Skris ERR_print_errors(bio_err); 58459191Skris goto end; 585160814Ssimon } 58659191Skris } 58759191Skris 588160814Ssimon if (operation == SMIME_DECRYPT) 589160814Ssimon { 590160814Ssimon if (!keyfile) 591160814Ssimon keyfile = recipfile; 592160814Ssimon } 593160814Ssimon else if (operation == SMIME_SIGN) 594160814Ssimon { 595160814Ssimon if (!keyfile) 596160814Ssimon keyfile = signerfile; 597160814Ssimon } 598160814Ssimon else keyfile = NULL; 59959191Skris 600160814Ssimon if (keyfile) 601160814Ssimon { 602109998Smarkm key = load_key(bio_err, keyfile, keyform, 0, passin, e, 603109998Smarkm "signing key file"); 604160814Ssimon if (!key) 60559191Skris goto end; 606160814Ssimon } 60759191Skris 608160814Ssimon if (infile) 609160814Ssimon { 610160814Ssimon if (!(in = BIO_new_file(infile, inmode))) 611160814Ssimon { 61259191Skris BIO_printf (bio_err, 61359191Skris "Can't open input file %s\n", infile); 61459191Skris goto end; 615160814Ssimon } 61659191Skris } 617160814Ssimon else 618160814Ssimon in = BIO_new_fp(stdin, BIO_NOCLOSE); 61959191Skris 620238405Sjkim if (operation & SMIME_IP) 621238405Sjkim { 622238405Sjkim if (informat == FORMAT_SMIME) 623238405Sjkim p7 = SMIME_read_PKCS7(in, &indata); 624238405Sjkim else if (informat == FORMAT_PEM) 625238405Sjkim p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); 626238405Sjkim else if (informat == FORMAT_ASN1) 627238405Sjkim p7 = d2i_PKCS7_bio(in, NULL); 628238405Sjkim else 629238405Sjkim { 630238405Sjkim BIO_printf(bio_err, "Bad input format for PKCS#7 file\n"); 631238405Sjkim goto end; 632238405Sjkim } 633238405Sjkim 634238405Sjkim if (!p7) 635238405Sjkim { 636238405Sjkim BIO_printf(bio_err, "Error reading S/MIME message\n"); 637238405Sjkim goto end; 638238405Sjkim } 639238405Sjkim if (contfile) 640238405Sjkim { 641238405Sjkim BIO_free(indata); 642238405Sjkim if (!(indata = BIO_new_file(contfile, "rb"))) 643238405Sjkim { 644238405Sjkim BIO_printf(bio_err, "Can't read content file %s\n", contfile); 645238405Sjkim goto end; 646238405Sjkim } 647238405Sjkim } 648238405Sjkim } 649238405Sjkim 650160814Ssimon if (outfile) 651160814Ssimon { 652160814Ssimon if (!(out = BIO_new_file(outfile, outmode))) 653160814Ssimon { 65459191Skris BIO_printf (bio_err, 65559191Skris "Can't open output file %s\n", outfile); 65659191Skris goto end; 657160814Ssimon } 65859191Skris } 659160814Ssimon else 660160814Ssimon { 66168651Skris out = BIO_new_fp(stdout, BIO_NOCLOSE); 662109998Smarkm#ifdef OPENSSL_SYS_VMS 66368651Skris { 66468651Skris BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 66568651Skris out = BIO_push(tmpbio, out); 66668651Skris } 66768651Skris#endif 668160814Ssimon } 66959191Skris 670160814Ssimon if (operation == SMIME_VERIFY) 671160814Ssimon { 672160814Ssimon if (!(store = setup_verify(bio_err, CAfile, CApath))) 673160814Ssimon goto end; 674238405Sjkim X509_STORE_set_verify_cb(store, smime_cb); 675160814Ssimon if (vpm) 676160814Ssimon X509_STORE_set1_param(store, vpm); 677160814Ssimon } 67859191Skris 679109998Smarkm 68059191Skris ret = 3; 68159191Skris 682160814Ssimon if (operation == SMIME_ENCRYPT) 683160814Ssimon { 684238405Sjkim if (indef) 685160814Ssimon flags |= PKCS7_STREAM; 686238405Sjkim p7 = PKCS7_encrypt(encerts, in, cipher, flags); 687100928Snectar } 688238405Sjkim else if (operation & SMIME_SIGNERS) 689160814Ssimon { 690238405Sjkim int i; 691238405Sjkim /* If detached data content we only enable streaming if 692238405Sjkim * S/MIME output format. 693238405Sjkim */ 694238405Sjkim if (operation == SMIME_SIGN) 695160814Ssimon { 696238405Sjkim if (flags & PKCS7_DETACHED) 697238405Sjkim { 698238405Sjkim if (outformat == FORMAT_SMIME) 699238405Sjkim flags |= PKCS7_STREAM; 700238405Sjkim } 701238405Sjkim else if (indef) 702238405Sjkim flags |= PKCS7_STREAM; 703238405Sjkim flags |= PKCS7_PARTIAL; 704238405Sjkim p7 = PKCS7_sign(NULL, NULL, other, in, flags); 705238405Sjkim if (!p7) 706238405Sjkim goto end; 707160814Ssimon } 708238405Sjkim else 709238405Sjkim flags |= PKCS7_REUSE_DIGEST; 710238405Sjkim for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) 711160814Ssimon { 712238405Sjkim signerfile = sk_OPENSSL_STRING_value(sksigners, i); 713238405Sjkim keyfile = sk_OPENSSL_STRING_value(skkeys, i); 714238405Sjkim signer = load_cert(bio_err, signerfile,FORMAT_PEM, NULL, 715238405Sjkim e, "signer certificate"); 716238405Sjkim if (!signer) 717238405Sjkim goto end; 718238405Sjkim key = load_key(bio_err, keyfile, keyform, 0, passin, e, 719238405Sjkim "signing key file"); 720238405Sjkim if (!key) 721238405Sjkim goto end; 722238405Sjkim if (!PKCS7_sign_add_signer(p7, signer, key, 723238405Sjkim sign_md, flags)) 724238405Sjkim goto end; 725238405Sjkim X509_free(signer); 726238405Sjkim signer = NULL; 727238405Sjkim EVP_PKEY_free(key); 728238405Sjkim key = NULL; 729160814Ssimon } 730238405Sjkim /* If not streaming or resigning finalize structure */ 731238405Sjkim if ((operation == SMIME_SIGN) && !(flags & PKCS7_STREAM)) 732160814Ssimon { 733238405Sjkim if (!PKCS7_final(p7, in, flags)) 73468651Skris goto end; 73568651Skris } 73668651Skris } 73759191Skris 738160814Ssimon if (!p7) 739160814Ssimon { 74059191Skris BIO_printf(bio_err, "Error creating PKCS#7 structure\n"); 74159191Skris goto end; 742160814Ssimon } 74359191Skris 74459191Skris ret = 4; 745160814Ssimon if (operation == SMIME_DECRYPT) 746160814Ssimon { 747160814Ssimon if (!PKCS7_decrypt(p7, key, recip, out, flags)) 748160814Ssimon { 74959191Skris BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n"); 75059191Skris goto end; 751160814Ssimon } 75259191Skris } 753160814Ssimon else if (operation == SMIME_VERIFY) 754160814Ssimon { 75559191Skris STACK_OF(X509) *signers; 756160814Ssimon if (PKCS7_verify(p7, other, store, indata, out, flags)) 757100928Snectar BIO_printf(bio_err, "Verification successful\n"); 758160814Ssimon else 759160814Ssimon { 760100928Snectar BIO_printf(bio_err, "Verification failure\n"); 76159191Skris goto end; 762160814Ssimon } 76359191Skris signers = PKCS7_get0_signers(p7, other, flags); 764160814Ssimon if (!save_certs(signerfile, signers)) 765160814Ssimon { 76659191Skris BIO_printf(bio_err, "Error writing signers to %s\n", 76759191Skris signerfile); 76859191Skris ret = 5; 76959191Skris goto end; 770160814Ssimon } 771160814Ssimon sk_X509_free(signers); 77259191Skris } 773160814Ssimon else if (operation == SMIME_PK7OUT) 77459191Skris PEM_write_bio_PKCS7(out, p7); 775160814Ssimon else 776160814Ssimon { 777160814Ssimon if (to) 778160814Ssimon BIO_printf(out, "To: %s\n", to); 779160814Ssimon if (from) 780160814Ssimon BIO_printf(out, "From: %s\n", from); 781160814Ssimon if (subject) 782160814Ssimon BIO_printf(out, "Subject: %s\n", subject); 783160814Ssimon if (outformat == FORMAT_SMIME) 784238405Sjkim { 785238405Sjkim if (operation == SMIME_RESIGN) 786238405Sjkim SMIME_write_PKCS7(out, p7, indata, flags); 787238405Sjkim else 788238405Sjkim SMIME_write_PKCS7(out, p7, in, flags); 789238405Sjkim } 790160814Ssimon else if (outformat == FORMAT_PEM) 791238405Sjkim PEM_write_bio_PKCS7_stream(out, p7, in, flags); 792160814Ssimon else if (outformat == FORMAT_ASN1) 793238405Sjkim i2d_PKCS7_bio_stream(out,p7, in, flags); 794160814Ssimon else 795160814Ssimon { 79668651Skris BIO_printf(bio_err, "Bad output format for PKCS#7 file\n"); 79768651Skris goto end; 798160814Ssimon } 79968651Skris } 80059191Skris ret = 0; 80159191Skrisend: 80259191Skris if (need_rand) 80359191Skris app_RAND_write_file(NULL, bio_err); 804160814Ssimon if (ret) ERR_print_errors(bio_err); 80559191Skris sk_X509_pop_free(encerts, X509_free); 80659191Skris sk_X509_pop_free(other, X509_free); 807160814Ssimon if (vpm) 808160814Ssimon X509_VERIFY_PARAM_free(vpm); 809238405Sjkim if (sksigners) 810238405Sjkim sk_OPENSSL_STRING_free(sksigners); 811238405Sjkim if (skkeys) 812238405Sjkim sk_OPENSSL_STRING_free(skkeys); 81359191Skris X509_STORE_free(store); 81459191Skris X509_free(cert); 81559191Skris X509_free(recip); 81659191Skris X509_free(signer); 81759191Skris EVP_PKEY_free(key); 81859191Skris PKCS7_free(p7); 81959191Skris BIO_free(in); 82059191Skris BIO_free(indata); 82168651Skris BIO_free_all(out); 822160814Ssimon if (passin) OPENSSL_free(passin); 82359191Skris return (ret); 82459191Skris} 82559191Skris 82659191Skrisstatic int save_certs(char *signerfile, STACK_OF(X509) *signers) 827160814Ssimon { 82859191Skris int i; 82959191Skris BIO *tmp; 830160814Ssimon if (!signerfile) 831160814Ssimon return 1; 83259191Skris tmp = BIO_new_file(signerfile, "w"); 833160814Ssimon if (!tmp) return 0; 83459191Skris for(i = 0; i < sk_X509_num(signers); i++) 83559191Skris PEM_write_bio_X509(tmp, sk_X509_value(signers, i)); 83659191Skris BIO_free(tmp); 83759191Skris return 1; 838160814Ssimon } 83959191Skris 840160814Ssimon 841160814Ssimon/* Minimal callback just to output policy info (if any) */ 842160814Ssimon 843160814Ssimonstatic int smime_cb(int ok, X509_STORE_CTX *ctx) 844160814Ssimon { 845160814Ssimon int error; 846160814Ssimon 847160814Ssimon error = X509_STORE_CTX_get_error(ctx); 848160814Ssimon 849160814Ssimon if ((error != X509_V_ERR_NO_EXPLICIT_POLICY) 850160814Ssimon && ((error != X509_V_OK) || (ok != 2))) 851160814Ssimon return ok; 852160814Ssimon 853160814Ssimon policies_print(NULL, ctx); 854160814Ssimon 855160814Ssimon return ok; 856160814Ssimon 857160814Ssimon } 858