159191Skris/* smime.c */ 2296465Sdelphij/* 3296465Sdelphij * 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 14296465Sdelphij * 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 76296465Sdelphij#define SMIME_OP 0x10 77296465Sdelphij#define SMIME_ENCRYPT (1 | SMIME_OP) 78296465Sdelphij#define SMIME_DECRYPT 2 79296465Sdelphij#define SMIME_SIGN (3 | SMIME_OP) 80296465Sdelphij#define SMIME_VERIFY 4 81296465Sdelphij#define SMIME_PK7OUT 5 8259191Skris 8359191Skrisint MAIN(int, char **); 8459191Skris 8559191Skrisint MAIN(int argc, char **argv) 86296465Sdelphij{ 87296465Sdelphij ENGINE *e = NULL; 88296465Sdelphij int operation = 0; 89296465Sdelphij int ret = 0; 90296465Sdelphij char **args; 91296465Sdelphij const char *inmode = "r", *outmode = "w"; 92296465Sdelphij char *infile = NULL, *outfile = NULL; 93296465Sdelphij char *signerfile = NULL, *recipfile = NULL; 94296465Sdelphij char *certfile = NULL, *keyfile = NULL, *contfile = NULL; 95296465Sdelphij const EVP_CIPHER *cipher = NULL; 96296465Sdelphij PKCS7 *p7 = NULL; 97296465Sdelphij X509_STORE *store = NULL; 98296465Sdelphij X509 *cert = NULL, *recip = NULL, *signer = NULL; 99296465Sdelphij EVP_PKEY *key = NULL; 100296465Sdelphij STACK_OF(X509) *encerts = NULL, *other = NULL; 101296465Sdelphij BIO *in = NULL, *out = NULL, *indata = NULL; 102296465Sdelphij int badarg = 0; 103296465Sdelphij int flags = PKCS7_DETACHED; 104296465Sdelphij char *to = NULL, *from = NULL, *subject = NULL; 105296465Sdelphij char *CAfile = NULL, *CApath = NULL; 106296465Sdelphij char *passargin = NULL, *passin = NULL; 107296465Sdelphij char *inrand = NULL; 108296465Sdelphij int need_rand = 0; 109296465Sdelphij int informat = FORMAT_SMIME, outformat = FORMAT_SMIME; 110296465Sdelphij int keyform = FORMAT_PEM; 111111147Snectar#ifndef OPENSSL_NO_ENGINE 112296465Sdelphij char *engine = NULL; 113111147Snectar#endif 114109998Smarkm 115296465Sdelphij X509_VERIFY_PARAM *vpm = NULL; 116160814Ssimon 117296465Sdelphij args = argv + 1; 118296465Sdelphij ret = 1; 11959191Skris 120296465Sdelphij apps_startup(); 121109998Smarkm 122296465Sdelphij if (bio_err == NULL) { 123296465Sdelphij if ((bio_err = BIO_new(BIO_s_file())) != NULL) 124296465Sdelphij BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); 125296465Sdelphij } 126109998Smarkm 127296465Sdelphij if (!load_config(bio_err, NULL)) 128296465Sdelphij goto end; 129109998Smarkm 130296465Sdelphij while (!badarg && *args && *args[0] == '-') { 131296465Sdelphij if (!strcmp(*args, "-encrypt")) 132296465Sdelphij operation = SMIME_ENCRYPT; 133296465Sdelphij else if (!strcmp(*args, "-decrypt")) 134296465Sdelphij operation = SMIME_DECRYPT; 135296465Sdelphij else if (!strcmp(*args, "-sign")) 136296465Sdelphij operation = SMIME_SIGN; 137296465Sdelphij else if (!strcmp(*args, "-verify")) 138296465Sdelphij operation = SMIME_VERIFY; 139296465Sdelphij else if (!strcmp(*args, "-pk7out")) 140296465Sdelphij operation = SMIME_PK7OUT; 141109998Smarkm#ifndef OPENSSL_NO_DES 142296465Sdelphij else if (!strcmp(*args, "-des3")) 143296465Sdelphij cipher = EVP_des_ede3_cbc(); 144296465Sdelphij else if (!strcmp(*args, "-des")) 145296465Sdelphij cipher = EVP_des_cbc(); 14659191Skris#endif 147194206Ssimon#ifndef OPENSSL_NO_SEED 148296465Sdelphij else if (!strcmp(*args, "-seed")) 149296465Sdelphij cipher = EVP_seed_cbc(); 150194206Ssimon#endif 151109998Smarkm#ifndef OPENSSL_NO_RC2 152296465Sdelphij else if (!strcmp(*args, "-rc2-40")) 153296465Sdelphij cipher = EVP_rc2_40_cbc(); 154296465Sdelphij else if (!strcmp(*args, "-rc2-128")) 155296465Sdelphij cipher = EVP_rc2_cbc(); 156296465Sdelphij else if (!strcmp(*args, "-rc2-64")) 157296465Sdelphij cipher = EVP_rc2_64_cbc(); 15859191Skris#endif 159109998Smarkm#ifndef OPENSSL_NO_AES 160296465Sdelphij else if (!strcmp(*args, "-aes128")) 161296465Sdelphij cipher = EVP_aes_128_cbc(); 162296465Sdelphij else if (!strcmp(*args, "-aes192")) 163296465Sdelphij cipher = EVP_aes_192_cbc(); 164296465Sdelphij else if (!strcmp(*args, "-aes256")) 165296465Sdelphij cipher = EVP_aes_256_cbc(); 166109998Smarkm#endif 167162911Ssimon#ifndef OPENSSL_NO_CAMELLIA 168296465Sdelphij else if (!strcmp(*args, "-camellia128")) 169296465Sdelphij cipher = EVP_camellia_128_cbc(); 170296465Sdelphij else if (!strcmp(*args, "-camellia192")) 171296465Sdelphij cipher = EVP_camellia_192_cbc(); 172296465Sdelphij else if (!strcmp(*args, "-camellia256")) 173296465Sdelphij cipher = EVP_camellia_256_cbc(); 174162911Ssimon#endif 175296465Sdelphij else if (!strcmp(*args, "-text")) 176296465Sdelphij flags |= PKCS7_TEXT; 177296465Sdelphij else if (!strcmp(*args, "-nointern")) 178296465Sdelphij flags |= PKCS7_NOINTERN; 179296465Sdelphij else if (!strcmp(*args, "-noverify")) 180296465Sdelphij flags |= PKCS7_NOVERIFY; 181296465Sdelphij else if (!strcmp(*args, "-nochain")) 182296465Sdelphij flags |= PKCS7_NOCHAIN; 183296465Sdelphij else if (!strcmp(*args, "-nocerts")) 184296465Sdelphij flags |= PKCS7_NOCERTS; 185296465Sdelphij else if (!strcmp(*args, "-noattr")) 186296465Sdelphij flags |= PKCS7_NOATTR; 187296465Sdelphij else if (!strcmp(*args, "-nodetach")) 188296465Sdelphij flags &= ~PKCS7_DETACHED; 189296465Sdelphij else if (!strcmp(*args, "-nosmimecap")) 190296465Sdelphij flags |= PKCS7_NOSMIMECAP; 191296465Sdelphij else if (!strcmp(*args, "-binary")) 192296465Sdelphij flags |= PKCS7_BINARY; 193296465Sdelphij else if (!strcmp(*args, "-nosigs")) 194296465Sdelphij flags |= PKCS7_NOSIGS; 195296465Sdelphij else if (!strcmp(*args, "-nooldmime")) 196296465Sdelphij flags |= PKCS7_NOOLDMIMETYPE; 197296465Sdelphij else if (!strcmp(*args, "-crlfeol")) 198296465Sdelphij flags |= PKCS7_CRLFEOL; 199296465Sdelphij else if (!strcmp(*args, "-rand")) { 200296465Sdelphij if (args[1]) { 201296465Sdelphij args++; 202296465Sdelphij inrand = *args; 203296465Sdelphij } else 204296465Sdelphij badarg = 1; 205296465Sdelphij need_rand = 1; 206296465Sdelphij } 207111147Snectar#ifndef OPENSSL_NO_ENGINE 208296465Sdelphij else if (!strcmp(*args, "-engine")) { 209296465Sdelphij if (args[1]) { 210296465Sdelphij args++; 211296465Sdelphij engine = *args; 212296465Sdelphij } else 213296465Sdelphij badarg = 1; 214296465Sdelphij } 215111147Snectar#endif 216296465Sdelphij else if (!strcmp(*args, "-passin")) { 217296465Sdelphij if (args[1]) { 218296465Sdelphij args++; 219296465Sdelphij passargin = *args; 220296465Sdelphij } else 221296465Sdelphij badarg = 1; 222296465Sdelphij } else if (!strcmp(*args, "-to")) { 223296465Sdelphij if (args[1]) { 224296465Sdelphij args++; 225296465Sdelphij to = *args; 226296465Sdelphij } else 227296465Sdelphij badarg = 1; 228296465Sdelphij } else if (!strcmp(*args, "-from")) { 229296465Sdelphij if (args[1]) { 230296465Sdelphij args++; 231296465Sdelphij from = *args; 232296465Sdelphij } else 233296465Sdelphij badarg = 1; 234296465Sdelphij } else if (!strcmp(*args, "-subject")) { 235296465Sdelphij if (args[1]) { 236296465Sdelphij args++; 237296465Sdelphij subject = *args; 238296465Sdelphij } else 239296465Sdelphij badarg = 1; 240296465Sdelphij } else if (!strcmp(*args, "-signer")) { 241296465Sdelphij if (args[1]) { 242296465Sdelphij args++; 243296465Sdelphij signerfile = *args; 244296465Sdelphij } else 245296465Sdelphij badarg = 1; 246296465Sdelphij } else if (!strcmp(*args, "-recip")) { 247296465Sdelphij if (args[1]) { 248296465Sdelphij args++; 249296465Sdelphij recipfile = *args; 250296465Sdelphij } else 251296465Sdelphij badarg = 1; 252296465Sdelphij } else if (!strcmp(*args, "-inkey")) { 253296465Sdelphij if (args[1]) { 254296465Sdelphij args++; 255296465Sdelphij keyfile = *args; 256296465Sdelphij } else 257296465Sdelphij badarg = 1; 258296465Sdelphij } else if (!strcmp(*args, "-keyform")) { 259296465Sdelphij if (args[1]) { 260296465Sdelphij args++; 261296465Sdelphij keyform = str2fmt(*args); 262296465Sdelphij } else 263296465Sdelphij badarg = 1; 264296465Sdelphij } else if (!strcmp(*args, "-certfile")) { 265296465Sdelphij if (args[1]) { 266296465Sdelphij args++; 267296465Sdelphij certfile = *args; 268296465Sdelphij } else 269296465Sdelphij badarg = 1; 270296465Sdelphij } else if (!strcmp(*args, "-CAfile")) { 271296465Sdelphij if (args[1]) { 272296465Sdelphij args++; 273296465Sdelphij CAfile = *args; 274296465Sdelphij } else 275296465Sdelphij badarg = 1; 276296465Sdelphij } else if (!strcmp(*args, "-CApath")) { 277296465Sdelphij if (args[1]) { 278296465Sdelphij args++; 279296465Sdelphij CApath = *args; 280296465Sdelphij } else 281296465Sdelphij badarg = 1; 282296465Sdelphij } else if (!strcmp(*args, "-in")) { 283296465Sdelphij if (args[1]) { 284296465Sdelphij args++; 285296465Sdelphij infile = *args; 286296465Sdelphij } else 287296465Sdelphij badarg = 1; 288296465Sdelphij } else if (!strcmp(*args, "-inform")) { 289296465Sdelphij if (args[1]) { 290296465Sdelphij args++; 291296465Sdelphij informat = str2fmt(*args); 292296465Sdelphij } else 293296465Sdelphij badarg = 1; 294296465Sdelphij } else if (!strcmp(*args, "-outform")) { 295296465Sdelphij if (args[1]) { 296296465Sdelphij args++; 297296465Sdelphij outformat = str2fmt(*args); 298296465Sdelphij } else 299296465Sdelphij badarg = 1; 300296465Sdelphij } else if (!strcmp(*args, "-out")) { 301296465Sdelphij if (args[1]) { 302296465Sdelphij args++; 303296465Sdelphij outfile = *args; 304296465Sdelphij } else 305296465Sdelphij badarg = 1; 306296465Sdelphij } else if (!strcmp(*args, "-content")) { 307296465Sdelphij if (args[1]) { 308296465Sdelphij args++; 309296465Sdelphij contfile = *args; 310296465Sdelphij } else 311296465Sdelphij badarg = 1; 312296465Sdelphij } else if (args_verify(&args, NULL, &badarg, bio_err, &vpm)) 313296465Sdelphij continue; 314296465Sdelphij else 315296465Sdelphij badarg = 1; 316296465Sdelphij args++; 317296465Sdelphij } 31859191Skris 319296465Sdelphij if (operation == SMIME_SIGN) { 320296465Sdelphij if (!signerfile) { 321296465Sdelphij BIO_printf(bio_err, "No signer certificate specified\n"); 322296465Sdelphij badarg = 1; 323296465Sdelphij } 324296465Sdelphij need_rand = 1; 325296465Sdelphij } else if (operation == SMIME_DECRYPT) { 326296465Sdelphij if (!recipfile && !keyfile) { 327296465Sdelphij BIO_printf(bio_err, 328296465Sdelphij "No recipient certificate or key specified\n"); 329296465Sdelphij badarg = 1; 330296465Sdelphij } 331296465Sdelphij } else if (operation == SMIME_ENCRYPT) { 332296465Sdelphij if (!*args) { 333296465Sdelphij BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); 334296465Sdelphij badarg = 1; 335296465Sdelphij } 336296465Sdelphij need_rand = 1; 337296465Sdelphij } else if (!operation) 338296465Sdelphij badarg = 1; 339160814Ssimon 340296465Sdelphij if (badarg) { 341296465Sdelphij BIO_printf(bio_err, "Usage smime [options] cert.pem ...\n"); 342296465Sdelphij BIO_printf(bio_err, "where options are\n"); 343296465Sdelphij BIO_printf(bio_err, "-encrypt encrypt message\n"); 344296465Sdelphij BIO_printf(bio_err, "-decrypt decrypt encrypted message\n"); 345296465Sdelphij BIO_printf(bio_err, "-sign sign message\n"); 346296465Sdelphij BIO_printf(bio_err, "-verify verify signed message\n"); 347296465Sdelphij BIO_printf(bio_err, "-pk7out output PKCS#7 structure\n"); 348109998Smarkm#ifndef OPENSSL_NO_DES 349296465Sdelphij BIO_printf(bio_err, "-des3 encrypt with triple DES\n"); 350296465Sdelphij BIO_printf(bio_err, "-des encrypt with DES\n"); 35159191Skris#endif 352194206Ssimon#ifndef OPENSSL_NO_SEED 353296465Sdelphij BIO_printf(bio_err, "-seed encrypt with SEED\n"); 354194206Ssimon#endif 355109998Smarkm#ifndef OPENSSL_NO_RC2 356296465Sdelphij BIO_printf(bio_err, "-rc2-40 encrypt with RC2-40 (default)\n"); 357296465Sdelphij BIO_printf(bio_err, "-rc2-64 encrypt with RC2-64\n"); 358296465Sdelphij BIO_printf(bio_err, "-rc2-128 encrypt with RC2-128\n"); 35959191Skris#endif 360109998Smarkm#ifndef OPENSSL_NO_AES 361296465Sdelphij BIO_printf(bio_err, "-aes128, -aes192, -aes256\n"); 362296465Sdelphij BIO_printf(bio_err, 363296465Sdelphij " encrypt PEM output with cbc aes\n"); 364109998Smarkm#endif 365162911Ssimon#ifndef OPENSSL_NO_CAMELLIA 366296465Sdelphij BIO_printf(bio_err, "-camellia128, -camellia192, -camellia256\n"); 367296465Sdelphij BIO_printf(bio_err, 368296465Sdelphij " encrypt PEM output with cbc camellia\n"); 369162911Ssimon#endif 370296465Sdelphij BIO_printf(bio_err, 371296465Sdelphij "-nointern don't search certificates in message for signer\n"); 372296465Sdelphij BIO_printf(bio_err, 373296465Sdelphij "-nosigs don't verify message signature\n"); 374296465Sdelphij BIO_printf(bio_err, 375296465Sdelphij "-noverify don't verify signers certificate\n"); 376296465Sdelphij BIO_printf(bio_err, 377296465Sdelphij "-nocerts don't include signers certificate when signing\n"); 378296465Sdelphij BIO_printf(bio_err, "-nodetach use opaque signing\n"); 379296465Sdelphij BIO_printf(bio_err, 380296465Sdelphij "-noattr don't include any signed attributes\n"); 381296465Sdelphij BIO_printf(bio_err, 382296465Sdelphij "-binary don't translate message to text\n"); 383296465Sdelphij BIO_printf(bio_err, "-certfile file other certificates file\n"); 384296465Sdelphij BIO_printf(bio_err, "-signer file signer certificate file\n"); 385296465Sdelphij BIO_printf(bio_err, 386296465Sdelphij "-recip file recipient certificate file for decryption\n"); 387296465Sdelphij BIO_printf(bio_err, "-in file input file\n"); 388296465Sdelphij BIO_printf(bio_err, 389296465Sdelphij "-inform arg input format SMIME (default), PEM or DER\n"); 390296465Sdelphij BIO_printf(bio_err, 391296465Sdelphij "-inkey file input private key (if not signer or recipient)\n"); 392296465Sdelphij BIO_printf(bio_err, 393296465Sdelphij "-keyform arg input private key format (PEM or ENGINE)\n"); 394296465Sdelphij BIO_printf(bio_err, "-out file output file\n"); 395296465Sdelphij BIO_printf(bio_err, 396296465Sdelphij "-outform arg output format SMIME (default), PEM or DER\n"); 397296465Sdelphij BIO_printf(bio_err, 398296465Sdelphij "-content file supply or override content for detached signature\n"); 399296465Sdelphij BIO_printf(bio_err, "-to addr to address\n"); 400296465Sdelphij BIO_printf(bio_err, "-from ad from address\n"); 401296465Sdelphij BIO_printf(bio_err, "-subject s subject\n"); 402296465Sdelphij BIO_printf(bio_err, 403296465Sdelphij "-text include or delete text MIME headers\n"); 404296465Sdelphij BIO_printf(bio_err, 405296465Sdelphij "-CApath dir trusted certificates directory\n"); 406296465Sdelphij BIO_printf(bio_err, "-CAfile file trusted certificates file\n"); 407296465Sdelphij BIO_printf(bio_err, 408296465Sdelphij "-crl_check check revocation status of signer's certificate using CRLs\n"); 409296465Sdelphij BIO_printf(bio_err, 410296465Sdelphij "-crl_check_all check revocation status of signer's certificate chain using CRLs\n"); 411111147Snectar#ifndef OPENSSL_NO_ENGINE 412296465Sdelphij BIO_printf(bio_err, 413296465Sdelphij "-engine e use engine e, possibly a hardware device.\n"); 414111147Snectar#endif 415296465Sdelphij BIO_printf(bio_err, "-passin arg input file pass phrase source\n"); 416296465Sdelphij BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, 417296465Sdelphij LIST_SEPARATOR_CHAR); 418296465Sdelphij BIO_printf(bio_err, 419296465Sdelphij " load the file (or the files in the directory) into\n"); 420296465Sdelphij BIO_printf(bio_err, " the random number generator\n"); 421296465Sdelphij BIO_printf(bio_err, 422296465Sdelphij "cert.pem recipient certificate(s) for encryption\n"); 423296465Sdelphij goto end; 424296465Sdelphij } 425111147Snectar#ifndef OPENSSL_NO_ENGINE 426296465Sdelphij e = setup_engine(bio_err, engine, 0); 427111147Snectar#endif 428109998Smarkm 429296465Sdelphij if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { 430296465Sdelphij BIO_printf(bio_err, "Error getting password\n"); 431296465Sdelphij goto end; 432296465Sdelphij } 43359191Skris 434296465Sdelphij if (need_rand) { 435296465Sdelphij app_RAND_load_file(NULL, bio_err, (inrand != NULL)); 436296465Sdelphij if (inrand != NULL) 437296465Sdelphij BIO_printf(bio_err, "%ld semi-random bytes loaded\n", 438296465Sdelphij app_RAND_load_files(inrand)); 439296465Sdelphij } 44059191Skris 441296465Sdelphij ret = 2; 44259191Skris 443296465Sdelphij if (operation != SMIME_SIGN) 444296465Sdelphij flags &= ~PKCS7_DETACHED; 44559191Skris 446296465Sdelphij if (operation & SMIME_OP) { 447296465Sdelphij if (flags & PKCS7_BINARY) 448296465Sdelphij inmode = "rb"; 449296465Sdelphij if (outformat == FORMAT_ASN1) 450296465Sdelphij outmode = "wb"; 451296465Sdelphij } else { 452296465Sdelphij if (flags & PKCS7_BINARY) 453296465Sdelphij outmode = "wb"; 454296465Sdelphij if (informat == FORMAT_ASN1) 455296465Sdelphij inmode = "rb"; 456296465Sdelphij } 45759191Skris 458296465Sdelphij if (operation == SMIME_ENCRYPT) { 459296465Sdelphij if (!cipher) { 460296465Sdelphij#ifndef OPENSSL_NO_DES 461296465Sdelphij cipher = EVP_des_ede3_cbc(); 46259191Skris#else 463296465Sdelphij BIO_printf(bio_err, "No cipher selected\n"); 464296465Sdelphij goto end; 46559191Skris#endif 466296465Sdelphij } 467296465Sdelphij encerts = sk_X509_new_null(); 468296465Sdelphij while (*args) { 469296465Sdelphij if (!(cert = load_cert(bio_err, *args, FORMAT_PEM, 470296465Sdelphij NULL, e, "recipient certificate file"))) { 471296465Sdelphij#if 0 /* An appropriate message is already printed */ 472296465Sdelphij BIO_printf(bio_err, 473296465Sdelphij "Can't read recipient certificate file %s\n", 474296465Sdelphij *args); 475109998Smarkm#endif 476296465Sdelphij goto end; 477296465Sdelphij } 478296465Sdelphij sk_X509_push(encerts, cert); 479296465Sdelphij cert = NULL; 480296465Sdelphij args++; 481296465Sdelphij } 482296465Sdelphij } 48359191Skris 484296465Sdelphij if (signerfile && (operation == SMIME_SIGN)) { 485296465Sdelphij if (!(signer = load_cert(bio_err, signerfile, FORMAT_PEM, NULL, 486296465Sdelphij e, "signer certificate"))) { 487296465Sdelphij#if 0 /* An appropri message has already been 488296465Sdelphij * printed */ 489296465Sdelphij BIO_printf(bio_err, "Can't read signer certificate file %s\n", 490296465Sdelphij signerfile); 491109998Smarkm#endif 492296465Sdelphij goto end; 493296465Sdelphij } 494296465Sdelphij } 49559191Skris 496296465Sdelphij if (certfile) { 497296465Sdelphij if (!(other = load_certs(bio_err, certfile, FORMAT_PEM, NULL, 498296465Sdelphij e, "certificate file"))) { 499296465Sdelphij#if 0 /* An appropriate message has already been 500296465Sdelphij * printed */ 501296465Sdelphij BIO_printf(bio_err, "Can't read certificate file %s\n", certfile); 502109998Smarkm#endif 503296465Sdelphij ERR_print_errors(bio_err); 504296465Sdelphij goto end; 505296465Sdelphij } 506296465Sdelphij } 50759191Skris 508296465Sdelphij if (recipfile && (operation == SMIME_DECRYPT)) { 509296465Sdelphij if (!(recip = load_cert(bio_err, recipfile, FORMAT_PEM, NULL, 510296465Sdelphij e, "recipient certificate file"))) { 511296465Sdelphij#if 0 /* An appropriate message has alrady been 512296465Sdelphij * printed */ 513296465Sdelphij BIO_printf(bio_err, "Can't read recipient certificate file %s\n", 514296465Sdelphij recipfile); 515109998Smarkm#endif 516296465Sdelphij ERR_print_errors(bio_err); 517296465Sdelphij goto end; 518296465Sdelphij } 519296465Sdelphij } 52059191Skris 521296465Sdelphij if (operation == SMIME_DECRYPT) { 522296465Sdelphij if (!keyfile) 523296465Sdelphij keyfile = recipfile; 524296465Sdelphij } else if (operation == SMIME_SIGN) { 525296465Sdelphij if (!keyfile) 526296465Sdelphij keyfile = signerfile; 527296465Sdelphij } else 528296465Sdelphij keyfile = NULL; 52959191Skris 530296465Sdelphij if (keyfile) { 531296465Sdelphij key = load_key(bio_err, keyfile, keyform, 0, passin, e, 532296465Sdelphij "signing key file"); 533296465Sdelphij if (!key) 534296465Sdelphij goto end; 535296465Sdelphij } 53659191Skris 537296465Sdelphij if (infile) { 538296465Sdelphij if (!(in = BIO_new_file(infile, inmode))) { 539296465Sdelphij BIO_printf(bio_err, "Can't open input file %s\n", infile); 540296465Sdelphij goto end; 541296465Sdelphij } 542296465Sdelphij } else 543296465Sdelphij in = BIO_new_fp(stdin, BIO_NOCLOSE); 54459191Skris 545296465Sdelphij if (outfile) { 546296465Sdelphij if (!(out = BIO_new_file(outfile, outmode))) { 547296465Sdelphij BIO_printf(bio_err, "Can't open output file %s\n", outfile); 548296465Sdelphij goto end; 549296465Sdelphij } 550296465Sdelphij } else { 551296465Sdelphij out = BIO_new_fp(stdout, BIO_NOCLOSE); 552109998Smarkm#ifdef OPENSSL_SYS_VMS 553296465Sdelphij { 554296465Sdelphij BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 555296465Sdelphij out = BIO_push(tmpbio, out); 556296465Sdelphij } 55768651Skris#endif 558296465Sdelphij } 55959191Skris 560296465Sdelphij if (operation == SMIME_VERIFY) { 561296465Sdelphij if (!(store = setup_verify(bio_err, CAfile, CApath))) 562296465Sdelphij goto end; 563296465Sdelphij X509_STORE_set_verify_cb_func(store, smime_cb); 564296465Sdelphij if (vpm) 565296465Sdelphij X509_STORE_set1_param(store, vpm); 566296465Sdelphij } 56759191Skris 568296465Sdelphij ret = 3; 569109998Smarkm 570296465Sdelphij if (operation == SMIME_ENCRYPT) 571296465Sdelphij p7 = PKCS7_encrypt(encerts, in, cipher, flags); 572296465Sdelphij else if (operation == SMIME_SIGN) { 573296465Sdelphij /* 574296465Sdelphij * If detached data and SMIME output enable partial signing. 575296465Sdelphij */ 576296465Sdelphij if ((flags & PKCS7_DETACHED) && (outformat == FORMAT_SMIME)) 577296465Sdelphij flags |= PKCS7_STREAM; 578296465Sdelphij p7 = PKCS7_sign(signer, key, other, in, flags); 579296465Sdelphij } else { 580296465Sdelphij if (informat == FORMAT_SMIME) 581296465Sdelphij p7 = SMIME_read_PKCS7(in, &indata); 582296465Sdelphij else if (informat == FORMAT_PEM) 583296465Sdelphij p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); 584296465Sdelphij else if (informat == FORMAT_ASN1) 585296465Sdelphij p7 = d2i_PKCS7_bio(in, NULL); 586296465Sdelphij else { 587296465Sdelphij BIO_printf(bio_err, "Bad input format for PKCS#7 file\n"); 588296465Sdelphij goto end; 589296465Sdelphij } 59059191Skris 591296465Sdelphij if (!p7) { 592296465Sdelphij BIO_printf(bio_err, "Error reading S/MIME message\n"); 593296465Sdelphij goto end; 594296465Sdelphij } 595296465Sdelphij if (contfile) { 596296465Sdelphij BIO_free(indata); 597296465Sdelphij if (!(indata = BIO_new_file(contfile, "rb"))) { 598296465Sdelphij BIO_printf(bio_err, "Can't read content file %s\n", contfile); 599296465Sdelphij goto end; 600296465Sdelphij } 601296465Sdelphij } 602296465Sdelphij } 60368651Skris 604296465Sdelphij if (!p7) { 605296465Sdelphij BIO_printf(bio_err, "Error creating PKCS#7 structure\n"); 606296465Sdelphij goto end; 607296465Sdelphij } 60859191Skris 609296465Sdelphij ret = 4; 610296465Sdelphij if (operation == SMIME_DECRYPT) { 611296465Sdelphij if (!PKCS7_decrypt(p7, key, recip, out, flags)) { 612296465Sdelphij BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n"); 613296465Sdelphij goto end; 614296465Sdelphij } 615296465Sdelphij } else if (operation == SMIME_VERIFY) { 616296465Sdelphij STACK_OF(X509) *signers; 617296465Sdelphij if (PKCS7_verify(p7, other, store, indata, out, flags)) 618296465Sdelphij BIO_printf(bio_err, "Verification successful\n"); 619296465Sdelphij else { 620296465Sdelphij BIO_printf(bio_err, "Verification failure\n"); 621296465Sdelphij goto end; 622296465Sdelphij } 623296465Sdelphij signers = PKCS7_get0_signers(p7, other, flags); 624296465Sdelphij if (!save_certs(signerfile, signers)) { 625296465Sdelphij BIO_printf(bio_err, "Error writing signers to %s\n", signerfile); 626296465Sdelphij ret = 5; 627296465Sdelphij goto end; 628296465Sdelphij } 629296465Sdelphij sk_X509_free(signers); 630296465Sdelphij } else if (operation == SMIME_PK7OUT) 631296465Sdelphij PEM_write_bio_PKCS7(out, p7); 632296465Sdelphij else { 633296465Sdelphij if (to) 634296465Sdelphij BIO_printf(out, "To: %s\n", to); 635296465Sdelphij if (from) 636296465Sdelphij BIO_printf(out, "From: %s\n", from); 637296465Sdelphij if (subject) 638296465Sdelphij BIO_printf(out, "Subject: %s\n", subject); 639296465Sdelphij if (outformat == FORMAT_SMIME) 640296465Sdelphij SMIME_write_PKCS7(out, p7, in, flags); 641296465Sdelphij else if (outformat == FORMAT_PEM) 642296465Sdelphij PEM_write_bio_PKCS7(out, p7); 643296465Sdelphij else if (outformat == FORMAT_ASN1) 644296465Sdelphij i2d_PKCS7_bio(out, p7); 645296465Sdelphij else { 646296465Sdelphij BIO_printf(bio_err, "Bad output format for PKCS#7 file\n"); 647296465Sdelphij goto end; 648296465Sdelphij } 649296465Sdelphij } 650296465Sdelphij ret = 0; 651296465Sdelphij end: 652296465Sdelphij if (need_rand) 653296465Sdelphij app_RAND_write_file(NULL, bio_err); 654296465Sdelphij if (ret) 655296465Sdelphij ERR_print_errors(bio_err); 656296465Sdelphij sk_X509_pop_free(encerts, X509_free); 657296465Sdelphij sk_X509_pop_free(other, X509_free); 658296465Sdelphij if (vpm) 659296465Sdelphij X509_VERIFY_PARAM_free(vpm); 660296465Sdelphij X509_STORE_free(store); 661296465Sdelphij X509_free(cert); 662296465Sdelphij X509_free(recip); 663296465Sdelphij X509_free(signer); 664296465Sdelphij EVP_PKEY_free(key); 665296465Sdelphij PKCS7_free(p7); 666296465Sdelphij BIO_free(in); 667296465Sdelphij BIO_free(indata); 668296465Sdelphij BIO_free_all(out); 669296465Sdelphij if (passin) 670296465Sdelphij OPENSSL_free(passin); 671296465Sdelphij return (ret); 67259191Skris} 67359191Skris 67459191Skrisstatic int save_certs(char *signerfile, STACK_OF(X509) *signers) 675296465Sdelphij{ 676296465Sdelphij int i; 677296465Sdelphij BIO *tmp; 678296465Sdelphij if (!signerfile) 679296465Sdelphij return 1; 680296465Sdelphij tmp = BIO_new_file(signerfile, "w"); 681296465Sdelphij if (!tmp) 682296465Sdelphij return 0; 683296465Sdelphij for (i = 0; i < sk_X509_num(signers); i++) 684296465Sdelphij PEM_write_bio_X509(tmp, sk_X509_value(signers, i)); 685296465Sdelphij BIO_free(tmp); 686296465Sdelphij return 1; 687296465Sdelphij} 688160814Ssimon 689160814Ssimon/* Minimal callback just to output policy info (if any) */ 690160814Ssimon 691160814Ssimonstatic int smime_cb(int ok, X509_STORE_CTX *ctx) 692296465Sdelphij{ 693296465Sdelphij int error; 694160814Ssimon 695296465Sdelphij error = X509_STORE_CTX_get_error(ctx); 696160814Ssimon 697296465Sdelphij if ((error != X509_V_ERR_NO_EXPLICIT_POLICY) 698296465Sdelphij && ((error != X509_V_OK) || (ok != 2))) 699296465Sdelphij return ok; 700160814Ssimon 701296465Sdelphij policies_print(NULL, ctx); 702160814Ssimon 703296465Sdelphij return ok; 704160814Ssimon 705296465Sdelphij} 706