1*0Sstevel@tonic-gate /* smime.c */ 2*0Sstevel@tonic-gate /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL 3*0Sstevel@tonic-gate * project 1999. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate /* ==================================================================== 6*0Sstevel@tonic-gate * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 7*0Sstevel@tonic-gate * 8*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 9*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 10*0Sstevel@tonic-gate * are met: 11*0Sstevel@tonic-gate * 12*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 13*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 14*0Sstevel@tonic-gate * 15*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 16*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in 17*0Sstevel@tonic-gate * the documentation and/or other materials provided with the 18*0Sstevel@tonic-gate * distribution. 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this 21*0Sstevel@tonic-gate * software must display the following acknowledgment: 22*0Sstevel@tonic-gate * "This product includes software developed by the OpenSSL Project 23*0Sstevel@tonic-gate * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24*0Sstevel@tonic-gate * 25*0Sstevel@tonic-gate * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26*0Sstevel@tonic-gate * endorse or promote products derived from this software without 27*0Sstevel@tonic-gate * prior written permission. For written permission, please contact 28*0Sstevel@tonic-gate * licensing@OpenSSL.org. 29*0Sstevel@tonic-gate * 30*0Sstevel@tonic-gate * 5. Products derived from this software may not be called "OpenSSL" 31*0Sstevel@tonic-gate * nor may "OpenSSL" appear in their names without prior written 32*0Sstevel@tonic-gate * permission of the OpenSSL Project. 33*0Sstevel@tonic-gate * 34*0Sstevel@tonic-gate * 6. Redistributions of any form whatsoever must retain the following 35*0Sstevel@tonic-gate * acknowledgment: 36*0Sstevel@tonic-gate * "This product includes software developed by the OpenSSL Project 37*0Sstevel@tonic-gate * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38*0Sstevel@tonic-gate * 39*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40*0Sstevel@tonic-gate * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41*0Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42*0Sstevel@tonic-gate * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43*0Sstevel@tonic-gate * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44*0Sstevel@tonic-gate * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45*0Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46*0Sstevel@tonic-gate * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47*0Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48*0Sstevel@tonic-gate * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49*0Sstevel@tonic-gate * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50*0Sstevel@tonic-gate * OF THE POSSIBILITY OF SUCH DAMAGE. 51*0Sstevel@tonic-gate * ==================================================================== 52*0Sstevel@tonic-gate * 53*0Sstevel@tonic-gate * This product includes cryptographic software written by Eric Young 54*0Sstevel@tonic-gate * (eay@cryptsoft.com). This product includes software written by Tim 55*0Sstevel@tonic-gate * Hudson (tjh@cryptsoft.com). 56*0Sstevel@tonic-gate * 57*0Sstevel@tonic-gate */ 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate /* 60*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 61*0Sstevel@tonic-gate * Use is subject to license terms. 62*0Sstevel@tonic-gate */ 63*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 64*0Sstevel@tonic-gate #ifdef SOLARIS_OPENSSL 65*0Sstevel@tonic-gate #include <dlfcn.h> 66*0Sstevel@tonic-gate #endif /* SOLARIS_OPENSSL */ 67*0Sstevel@tonic-gate 68*0Sstevel@tonic-gate /* S/MIME utility function */ 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate #include <stdio.h> 71*0Sstevel@tonic-gate #include <string.h> 72*0Sstevel@tonic-gate #include "apps.h" 73*0Sstevel@tonic-gate #include <openssl/crypto.h> 74*0Sstevel@tonic-gate #include <openssl/pem.h> 75*0Sstevel@tonic-gate #include <openssl/err.h> 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate #undef PROG 78*0Sstevel@tonic-gate #define PROG smime_main 79*0Sstevel@tonic-gate static int save_certs(char *signerfile, STACK_OF(X509) *signers); 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate #define SMIME_OP 0x10 82*0Sstevel@tonic-gate #define SMIME_ENCRYPT (1 | SMIME_OP) 83*0Sstevel@tonic-gate #define SMIME_DECRYPT 2 84*0Sstevel@tonic-gate #define SMIME_SIGN (3 | SMIME_OP) 85*0Sstevel@tonic-gate #define SMIME_VERIFY 4 86*0Sstevel@tonic-gate #define SMIME_PK7OUT 5 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate int MAIN(int, char **); 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate int MAIN(int argc, char **argv) 91*0Sstevel@tonic-gate { 92*0Sstevel@tonic-gate ENGINE *e = NULL; 93*0Sstevel@tonic-gate int operation = 0; 94*0Sstevel@tonic-gate int ret = 0; 95*0Sstevel@tonic-gate char **args; 96*0Sstevel@tonic-gate char *inmode = "r", *outmode = "w"; 97*0Sstevel@tonic-gate char *infile = NULL, *outfile = NULL; 98*0Sstevel@tonic-gate char *signerfile = NULL, *recipfile = NULL; 99*0Sstevel@tonic-gate char *certfile = NULL, *keyfile = NULL, *contfile=NULL; 100*0Sstevel@tonic-gate const EVP_CIPHER *cipher = NULL; 101*0Sstevel@tonic-gate PKCS7 *p7 = NULL; 102*0Sstevel@tonic-gate X509_STORE *store = NULL; 103*0Sstevel@tonic-gate X509 *cert = NULL, *recip = NULL, *signer = NULL; 104*0Sstevel@tonic-gate EVP_PKEY *key = NULL; 105*0Sstevel@tonic-gate STACK_OF(X509) *encerts = NULL, *other = NULL; 106*0Sstevel@tonic-gate BIO *in = NULL, *out = NULL, *indata = NULL; 107*0Sstevel@tonic-gate int badarg = 0; 108*0Sstevel@tonic-gate int flags = PKCS7_DETACHED, store_flags = 0; 109*0Sstevel@tonic-gate char *to = NULL, *from = NULL, *subject = NULL; 110*0Sstevel@tonic-gate char *CAfile = NULL, *CApath = NULL; 111*0Sstevel@tonic-gate char *passargin = NULL, *passin = NULL; 112*0Sstevel@tonic-gate char *inrand = NULL; 113*0Sstevel@tonic-gate int need_rand = 0; 114*0Sstevel@tonic-gate int informat = FORMAT_SMIME, outformat = FORMAT_SMIME; 115*0Sstevel@tonic-gate int keyform = FORMAT_PEM; 116*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE 117*0Sstevel@tonic-gate char *engine=NULL; 118*0Sstevel@tonic-gate #endif 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate args = argv + 1; 121*0Sstevel@tonic-gate ret = 1; 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate apps_startup(); 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate if (bio_err == NULL) 126*0Sstevel@tonic-gate if ((bio_err = BIO_new(BIO_s_file())) != NULL) 127*0Sstevel@tonic-gate BIO_set_fp(bio_err, stderr, BIO_NOCLOSE|BIO_FP_TEXT); 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate if (!load_config(bio_err, NULL)) 130*0Sstevel@tonic-gate goto end; 131*0Sstevel@tonic-gate 132*0Sstevel@tonic-gate while (!badarg && *args && *args[0] == '-') { 133*0Sstevel@tonic-gate if (!strcmp (*args, "-encrypt")) operation = SMIME_ENCRYPT; 134*0Sstevel@tonic-gate else if (!strcmp (*args, "-decrypt")) operation = SMIME_DECRYPT; 135*0Sstevel@tonic-gate else if (!strcmp (*args, "-sign")) operation = SMIME_SIGN; 136*0Sstevel@tonic-gate else if (!strcmp (*args, "-verify")) operation = SMIME_VERIFY; 137*0Sstevel@tonic-gate else if (!strcmp (*args, "-pk7out")) operation = SMIME_PK7OUT; 138*0Sstevel@tonic-gate #ifndef OPENSSL_NO_DES 139*0Sstevel@tonic-gate else if (!strcmp (*args, "-des3")) 140*0Sstevel@tonic-gate cipher = EVP_des_ede3_cbc(); 141*0Sstevel@tonic-gate else if (!strcmp (*args, "-des")) 142*0Sstevel@tonic-gate cipher = EVP_des_cbc(); 143*0Sstevel@tonic-gate #endif 144*0Sstevel@tonic-gate #ifndef OPENSSL_NO_RC2 145*0Sstevel@tonic-gate else if (!strcmp (*args, "-rc2-40")) 146*0Sstevel@tonic-gate cipher = EVP_rc2_40_cbc(); 147*0Sstevel@tonic-gate else if (!strcmp (*args, "-rc2-128")) 148*0Sstevel@tonic-gate cipher = EVP_rc2_cbc(); 149*0Sstevel@tonic-gate else if (!strcmp (*args, "-rc2-64")) 150*0Sstevel@tonic-gate cipher = EVP_rc2_64_cbc(); 151*0Sstevel@tonic-gate #endif 152*0Sstevel@tonic-gate #ifndef OPENSSL_NO_AES 153*0Sstevel@tonic-gate else if (!strcmp(*args,"-aes128")) 154*0Sstevel@tonic-gate cipher = EVP_aes_128_cbc(); 155*0Sstevel@tonic-gate #ifdef SOLARIS_OPENSSL 156*0Sstevel@tonic-gate else if (strcmp(*argv,"-aes192") == 0) 157*0Sstevel@tonic-gate { 158*0Sstevel@tonic-gate cipher = dlsym(RTLD_DEFAULT, "EVP_aes_192_cbc"); 159*0Sstevel@tonic-gate if (cipher == NULL) 160*0Sstevel@tonic-gate { 161*0Sstevel@tonic-gate BIO_printf(bio_err,"SUNWcry not installed.\n"); 162*0Sstevel@tonic-gate goto end; 163*0Sstevel@tonic-gate } 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate else if (strcmp(*argv,"-aes256") == 0) 166*0Sstevel@tonic-gate { 167*0Sstevel@tonic-gate cipher = dlsym(RTLD_DEFAULT, "EVP_aes_256_cbc"); 168*0Sstevel@tonic-gate if (cipher == NULL) 169*0Sstevel@tonic-gate { 170*0Sstevel@tonic-gate BIO_printf(bio_err,"SUNWcry not installed.\n"); 171*0Sstevel@tonic-gate goto end; 172*0Sstevel@tonic-gate } 173*0Sstevel@tonic-gate } 174*0Sstevel@tonic-gate #else 175*0Sstevel@tonic-gate else if (!strcmp(*args,"-aes192")) 176*0Sstevel@tonic-gate cipher = EVP_aes_192_cbc(); 177*0Sstevel@tonic-gate else if (!strcmp(*args,"-aes256")) 178*0Sstevel@tonic-gate cipher = EVP_aes_256_cbc(); 179*0Sstevel@tonic-gate #endif /* SOLARIS_OPENSSL */ 180*0Sstevel@tonic-gate #endif 181*0Sstevel@tonic-gate else if (!strcmp (*args, "-text")) 182*0Sstevel@tonic-gate flags |= PKCS7_TEXT; 183*0Sstevel@tonic-gate else if (!strcmp (*args, "-nointern")) 184*0Sstevel@tonic-gate flags |= PKCS7_NOINTERN; 185*0Sstevel@tonic-gate else if (!strcmp (*args, "-noverify")) 186*0Sstevel@tonic-gate flags |= PKCS7_NOVERIFY; 187*0Sstevel@tonic-gate else if (!strcmp (*args, "-nochain")) 188*0Sstevel@tonic-gate flags |= PKCS7_NOCHAIN; 189*0Sstevel@tonic-gate else if (!strcmp (*args, "-nocerts")) 190*0Sstevel@tonic-gate flags |= PKCS7_NOCERTS; 191*0Sstevel@tonic-gate else if (!strcmp (*args, "-noattr")) 192*0Sstevel@tonic-gate flags |= PKCS7_NOATTR; 193*0Sstevel@tonic-gate else if (!strcmp (*args, "-nodetach")) 194*0Sstevel@tonic-gate flags &= ~PKCS7_DETACHED; 195*0Sstevel@tonic-gate else if (!strcmp (*args, "-nosmimecap")) 196*0Sstevel@tonic-gate flags |= PKCS7_NOSMIMECAP; 197*0Sstevel@tonic-gate else if (!strcmp (*args, "-binary")) 198*0Sstevel@tonic-gate flags |= PKCS7_BINARY; 199*0Sstevel@tonic-gate else if (!strcmp (*args, "-nosigs")) 200*0Sstevel@tonic-gate flags |= PKCS7_NOSIGS; 201*0Sstevel@tonic-gate else if (!strcmp (*args, "-nooldmime")) 202*0Sstevel@tonic-gate flags |= PKCS7_NOOLDMIMETYPE; 203*0Sstevel@tonic-gate else if (!strcmp (*args, "-crlfeol")) 204*0Sstevel@tonic-gate flags |= PKCS7_CRLFEOL; 205*0Sstevel@tonic-gate else if (!strcmp (*args, "-crl_check")) 206*0Sstevel@tonic-gate store_flags |= X509_V_FLAG_CRL_CHECK; 207*0Sstevel@tonic-gate else if (!strcmp (*args, "-crl_check_all")) 208*0Sstevel@tonic-gate store_flags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL; 209*0Sstevel@tonic-gate else if (!strcmp(*args,"-rand")) { 210*0Sstevel@tonic-gate if (args[1]) { 211*0Sstevel@tonic-gate args++; 212*0Sstevel@tonic-gate inrand = *args; 213*0Sstevel@tonic-gate } else badarg = 1; 214*0Sstevel@tonic-gate need_rand = 1; 215*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE 216*0Sstevel@tonic-gate } else if (!strcmp(*args,"-engine")) { 217*0Sstevel@tonic-gate if (args[1]) { 218*0Sstevel@tonic-gate args++; 219*0Sstevel@tonic-gate engine = *args; 220*0Sstevel@tonic-gate } else badarg = 1; 221*0Sstevel@tonic-gate #endif 222*0Sstevel@tonic-gate } else if (!strcmp(*args,"-passin")) { 223*0Sstevel@tonic-gate if (args[1]) { 224*0Sstevel@tonic-gate args++; 225*0Sstevel@tonic-gate passargin = *args; 226*0Sstevel@tonic-gate } else badarg = 1; 227*0Sstevel@tonic-gate } else if (!strcmp (*args, "-to")) { 228*0Sstevel@tonic-gate if (args[1]) { 229*0Sstevel@tonic-gate args++; 230*0Sstevel@tonic-gate to = *args; 231*0Sstevel@tonic-gate } else badarg = 1; 232*0Sstevel@tonic-gate } else if (!strcmp (*args, "-from")) { 233*0Sstevel@tonic-gate if (args[1]) { 234*0Sstevel@tonic-gate args++; 235*0Sstevel@tonic-gate from = *args; 236*0Sstevel@tonic-gate } else badarg = 1; 237*0Sstevel@tonic-gate } else if (!strcmp (*args, "-subject")) { 238*0Sstevel@tonic-gate if (args[1]) { 239*0Sstevel@tonic-gate args++; 240*0Sstevel@tonic-gate subject = *args; 241*0Sstevel@tonic-gate } else badarg = 1; 242*0Sstevel@tonic-gate } else if (!strcmp (*args, "-signer")) { 243*0Sstevel@tonic-gate if (args[1]) { 244*0Sstevel@tonic-gate args++; 245*0Sstevel@tonic-gate signerfile = *args; 246*0Sstevel@tonic-gate } else badarg = 1; 247*0Sstevel@tonic-gate } else if (!strcmp (*args, "-recip")) { 248*0Sstevel@tonic-gate if (args[1]) { 249*0Sstevel@tonic-gate args++; 250*0Sstevel@tonic-gate recipfile = *args; 251*0Sstevel@tonic-gate } else badarg = 1; 252*0Sstevel@tonic-gate } else if (!strcmp (*args, "-inkey")) { 253*0Sstevel@tonic-gate if (args[1]) { 254*0Sstevel@tonic-gate args++; 255*0Sstevel@tonic-gate keyfile = *args; 256*0Sstevel@tonic-gate } else badarg = 1; 257*0Sstevel@tonic-gate } else if (!strcmp (*args, "-keyform")) { 258*0Sstevel@tonic-gate if (args[1]) { 259*0Sstevel@tonic-gate args++; 260*0Sstevel@tonic-gate keyform = str2fmt(*args); 261*0Sstevel@tonic-gate } else badarg = 1; 262*0Sstevel@tonic-gate } else if (!strcmp (*args, "-certfile")) { 263*0Sstevel@tonic-gate if (args[1]) { 264*0Sstevel@tonic-gate args++; 265*0Sstevel@tonic-gate certfile = *args; 266*0Sstevel@tonic-gate } else badarg = 1; 267*0Sstevel@tonic-gate } else if (!strcmp (*args, "-CAfile")) { 268*0Sstevel@tonic-gate if (args[1]) { 269*0Sstevel@tonic-gate args++; 270*0Sstevel@tonic-gate CAfile = *args; 271*0Sstevel@tonic-gate } else badarg = 1; 272*0Sstevel@tonic-gate } else if (!strcmp (*args, "-CApath")) { 273*0Sstevel@tonic-gate if (args[1]) { 274*0Sstevel@tonic-gate args++; 275*0Sstevel@tonic-gate CApath = *args; 276*0Sstevel@tonic-gate } else badarg = 1; 277*0Sstevel@tonic-gate } else if (!strcmp (*args, "-in")) { 278*0Sstevel@tonic-gate if (args[1]) { 279*0Sstevel@tonic-gate args++; 280*0Sstevel@tonic-gate infile = *args; 281*0Sstevel@tonic-gate } else badarg = 1; 282*0Sstevel@tonic-gate } else if (!strcmp (*args, "-inform")) { 283*0Sstevel@tonic-gate if (args[1]) { 284*0Sstevel@tonic-gate args++; 285*0Sstevel@tonic-gate informat = str2fmt(*args); 286*0Sstevel@tonic-gate } else badarg = 1; 287*0Sstevel@tonic-gate } else if (!strcmp (*args, "-outform")) { 288*0Sstevel@tonic-gate if (args[1]) { 289*0Sstevel@tonic-gate args++; 290*0Sstevel@tonic-gate outformat = str2fmt(*args); 291*0Sstevel@tonic-gate } else badarg = 1; 292*0Sstevel@tonic-gate } else if (!strcmp (*args, "-out")) { 293*0Sstevel@tonic-gate if (args[1]) { 294*0Sstevel@tonic-gate args++; 295*0Sstevel@tonic-gate outfile = *args; 296*0Sstevel@tonic-gate } else badarg = 1; 297*0Sstevel@tonic-gate } else if (!strcmp (*args, "-content")) { 298*0Sstevel@tonic-gate if (args[1]) { 299*0Sstevel@tonic-gate args++; 300*0Sstevel@tonic-gate contfile = *args; 301*0Sstevel@tonic-gate } else badarg = 1; 302*0Sstevel@tonic-gate } else badarg = 1; 303*0Sstevel@tonic-gate args++; 304*0Sstevel@tonic-gate } 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gate if(operation == SMIME_SIGN) { 307*0Sstevel@tonic-gate if(!signerfile) { 308*0Sstevel@tonic-gate BIO_printf(bio_err, "No signer certificate specified\n"); 309*0Sstevel@tonic-gate badarg = 1; 310*0Sstevel@tonic-gate } 311*0Sstevel@tonic-gate need_rand = 1; 312*0Sstevel@tonic-gate } else if(operation == SMIME_DECRYPT) { 313*0Sstevel@tonic-gate if(!recipfile) { 314*0Sstevel@tonic-gate BIO_printf(bio_err, "No recipient certificate and key specified\n"); 315*0Sstevel@tonic-gate badarg = 1; 316*0Sstevel@tonic-gate } 317*0Sstevel@tonic-gate } else if(operation == SMIME_ENCRYPT) { 318*0Sstevel@tonic-gate if(!*args) { 319*0Sstevel@tonic-gate BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); 320*0Sstevel@tonic-gate badarg = 1; 321*0Sstevel@tonic-gate } 322*0Sstevel@tonic-gate need_rand = 1; 323*0Sstevel@tonic-gate } else if(!operation) badarg = 1; 324*0Sstevel@tonic-gate 325*0Sstevel@tonic-gate if (badarg) { 326*0Sstevel@tonic-gate BIO_printf (bio_err, "Usage smime [options] cert.pem ...\n"); 327*0Sstevel@tonic-gate BIO_printf (bio_err, "where options are\n"); 328*0Sstevel@tonic-gate BIO_printf (bio_err, "-encrypt encrypt message\n"); 329*0Sstevel@tonic-gate BIO_printf (bio_err, "-decrypt decrypt encrypted message\n"); 330*0Sstevel@tonic-gate BIO_printf (bio_err, "-sign sign message\n"); 331*0Sstevel@tonic-gate BIO_printf (bio_err, "-verify verify signed message\n"); 332*0Sstevel@tonic-gate BIO_printf (bio_err, "-pk7out output PKCS#7 structure\n"); 333*0Sstevel@tonic-gate #ifndef OPENSSL_NO_DES 334*0Sstevel@tonic-gate BIO_printf (bio_err, "-des3 encrypt with triple DES\n"); 335*0Sstevel@tonic-gate BIO_printf (bio_err, "-des encrypt with DES\n"); 336*0Sstevel@tonic-gate #endif 337*0Sstevel@tonic-gate #ifndef OPENSSL_NO_RC2 338*0Sstevel@tonic-gate BIO_printf (bio_err, "-rc2-40 encrypt with RC2-40 (default)\n"); 339*0Sstevel@tonic-gate BIO_printf (bio_err, "-rc2-64 encrypt with RC2-64\n"); 340*0Sstevel@tonic-gate BIO_printf (bio_err, "-rc2-128 encrypt with RC2-128\n"); 341*0Sstevel@tonic-gate #endif 342*0Sstevel@tonic-gate #ifndef OPENSSL_NO_AES 343*0Sstevel@tonic-gate BIO_printf (bio_err, "-aes128, -aes192, -aes256\n"); 344*0Sstevel@tonic-gate BIO_printf (bio_err, " encrypt PEM output with cbc aes\n"); 345*0Sstevel@tonic-gate #endif 346*0Sstevel@tonic-gate BIO_printf (bio_err, "-nointern don't search certificates in message for signer\n"); 347*0Sstevel@tonic-gate BIO_printf (bio_err, "-nosigs don't verify message signature\n"); 348*0Sstevel@tonic-gate BIO_printf (bio_err, "-noverify don't verify signers certificate\n"); 349*0Sstevel@tonic-gate BIO_printf (bio_err, "-nocerts don't include signers certificate when signing\n"); 350*0Sstevel@tonic-gate BIO_printf (bio_err, "-nodetach use opaque signing\n"); 351*0Sstevel@tonic-gate BIO_printf (bio_err, "-noattr don't include any signed attributes\n"); 352*0Sstevel@tonic-gate BIO_printf (bio_err, "-binary don't translate message to text\n"); 353*0Sstevel@tonic-gate BIO_printf (bio_err, "-certfile file other certificates file\n"); 354*0Sstevel@tonic-gate BIO_printf (bio_err, "-signer file signer certificate file\n"); 355*0Sstevel@tonic-gate BIO_printf (bio_err, "-recip file recipient certificate file for decryption\n"); 356*0Sstevel@tonic-gate BIO_printf (bio_err, "-in file input file\n"); 357*0Sstevel@tonic-gate BIO_printf (bio_err, "-inform arg input format SMIME (default), PEM or DER\n"); 358*0Sstevel@tonic-gate BIO_printf (bio_err, "-inkey file input private key (if not signer or recipient)\n"); 359*0Sstevel@tonic-gate BIO_printf (bio_err, "-keyform arg input private key format (PEM or ENGINE)\n"); 360*0Sstevel@tonic-gate BIO_printf (bio_err, "-out file output file\n"); 361*0Sstevel@tonic-gate BIO_printf (bio_err, "-outform arg output format SMIME (default), PEM or DER\n"); 362*0Sstevel@tonic-gate BIO_printf (bio_err, "-content file supply or override content for detached signature\n"); 363*0Sstevel@tonic-gate BIO_printf (bio_err, "-to addr to address\n"); 364*0Sstevel@tonic-gate BIO_printf (bio_err, "-from ad from address\n"); 365*0Sstevel@tonic-gate BIO_printf (bio_err, "-subject s subject\n"); 366*0Sstevel@tonic-gate BIO_printf (bio_err, "-text include or delete text MIME headers\n"); 367*0Sstevel@tonic-gate BIO_printf (bio_err, "-CApath dir trusted certificates directory\n"); 368*0Sstevel@tonic-gate BIO_printf (bio_err, "-CAfile file trusted certificates file\n"); 369*0Sstevel@tonic-gate BIO_printf (bio_err, "-crl_check check revocation status of signer's certificate using CRLs\n"); 370*0Sstevel@tonic-gate BIO_printf (bio_err, "-crl_check_all check revocation status of signer's certificate chain using CRLs\n"); 371*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE 372*0Sstevel@tonic-gate BIO_printf (bio_err, "-engine e use engine e, possibly a hardware device.\n"); 373*0Sstevel@tonic-gate #endif 374*0Sstevel@tonic-gate BIO_printf (bio_err, "-passin arg input file pass phrase source\n"); 375*0Sstevel@tonic-gate BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); 376*0Sstevel@tonic-gate BIO_printf(bio_err, " load the file (or the files in the directory) into\n"); 377*0Sstevel@tonic-gate BIO_printf(bio_err, " the random number generator\n"); 378*0Sstevel@tonic-gate BIO_printf (bio_err, "cert.pem recipient certificate(s) for encryption\n"); 379*0Sstevel@tonic-gate goto end; 380*0Sstevel@tonic-gate } 381*0Sstevel@tonic-gate 382*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE 383*0Sstevel@tonic-gate e = setup_engine(bio_err, engine, 0); 384*0Sstevel@tonic-gate #endif 385*0Sstevel@tonic-gate 386*0Sstevel@tonic-gate if(!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { 387*0Sstevel@tonic-gate BIO_printf(bio_err, "Error getting password\n"); 388*0Sstevel@tonic-gate goto end; 389*0Sstevel@tonic-gate } 390*0Sstevel@tonic-gate 391*0Sstevel@tonic-gate if (need_rand) { 392*0Sstevel@tonic-gate app_RAND_load_file(NULL, bio_err, (inrand != NULL)); 393*0Sstevel@tonic-gate if (inrand != NULL) 394*0Sstevel@tonic-gate BIO_printf(bio_err,"%ld semi-random bytes loaded\n", 395*0Sstevel@tonic-gate app_RAND_load_files(inrand)); 396*0Sstevel@tonic-gate } 397*0Sstevel@tonic-gate 398*0Sstevel@tonic-gate ret = 2; 399*0Sstevel@tonic-gate 400*0Sstevel@tonic-gate if(operation != SMIME_SIGN) flags &= ~PKCS7_DETACHED; 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate if(operation & SMIME_OP) { 403*0Sstevel@tonic-gate if(flags & PKCS7_BINARY) inmode = "rb"; 404*0Sstevel@tonic-gate if(outformat == FORMAT_ASN1) outmode = "wb"; 405*0Sstevel@tonic-gate } else { 406*0Sstevel@tonic-gate if(flags & PKCS7_BINARY) outmode = "wb"; 407*0Sstevel@tonic-gate if(informat == FORMAT_ASN1) inmode = "rb"; 408*0Sstevel@tonic-gate } 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate if(operation == SMIME_ENCRYPT) { 411*0Sstevel@tonic-gate if (!cipher) { 412*0Sstevel@tonic-gate #ifndef OPENSSL_NO_RC2 413*0Sstevel@tonic-gate cipher = EVP_rc2_40_cbc(); 414*0Sstevel@tonic-gate #else 415*0Sstevel@tonic-gate BIO_printf(bio_err, "No cipher selected\n"); 416*0Sstevel@tonic-gate goto end; 417*0Sstevel@tonic-gate #endif 418*0Sstevel@tonic-gate } 419*0Sstevel@tonic-gate encerts = sk_X509_new_null(); 420*0Sstevel@tonic-gate while (*args) { 421*0Sstevel@tonic-gate if(!(cert = load_cert(bio_err,*args,FORMAT_PEM, 422*0Sstevel@tonic-gate NULL, e, "recipient certificate file"))) { 423*0Sstevel@tonic-gate #if 0 /* An appropriate message is already printed */ 424*0Sstevel@tonic-gate BIO_printf(bio_err, "Can't read recipient certificate file %s\n", *args); 425*0Sstevel@tonic-gate #endif 426*0Sstevel@tonic-gate goto end; 427*0Sstevel@tonic-gate } 428*0Sstevel@tonic-gate sk_X509_push(encerts, cert); 429*0Sstevel@tonic-gate cert = NULL; 430*0Sstevel@tonic-gate args++; 431*0Sstevel@tonic-gate } 432*0Sstevel@tonic-gate } 433*0Sstevel@tonic-gate 434*0Sstevel@tonic-gate if(signerfile && (operation == SMIME_SIGN)) { 435*0Sstevel@tonic-gate if(!(signer = load_cert(bio_err,signerfile,FORMAT_PEM, NULL, 436*0Sstevel@tonic-gate e, "signer certificate"))) { 437*0Sstevel@tonic-gate #if 0 /* An appropri message has already been printed */ 438*0Sstevel@tonic-gate BIO_printf(bio_err, "Can't read signer certificate file %s\n", signerfile); 439*0Sstevel@tonic-gate #endif 440*0Sstevel@tonic-gate goto end; 441*0Sstevel@tonic-gate } 442*0Sstevel@tonic-gate } 443*0Sstevel@tonic-gate 444*0Sstevel@tonic-gate if(certfile) { 445*0Sstevel@tonic-gate if(!(other = load_certs(bio_err,certfile,FORMAT_PEM, NULL, 446*0Sstevel@tonic-gate e, "certificate file"))) { 447*0Sstevel@tonic-gate #if 0 /* An appropriate message has already been printed */ 448*0Sstevel@tonic-gate BIO_printf(bio_err, "Can't read certificate file %s\n", certfile); 449*0Sstevel@tonic-gate #endif 450*0Sstevel@tonic-gate ERR_print_errors(bio_err); 451*0Sstevel@tonic-gate goto end; 452*0Sstevel@tonic-gate } 453*0Sstevel@tonic-gate } 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate if(recipfile && (operation == SMIME_DECRYPT)) { 456*0Sstevel@tonic-gate if(!(recip = load_cert(bio_err,recipfile,FORMAT_PEM,NULL, 457*0Sstevel@tonic-gate e, "recipient certificate file"))) { 458*0Sstevel@tonic-gate #if 0 /* An appropriate message has alrady been printed */ 459*0Sstevel@tonic-gate BIO_printf(bio_err, "Can't read recipient certificate file %s\n", recipfile); 460*0Sstevel@tonic-gate #endif 461*0Sstevel@tonic-gate ERR_print_errors(bio_err); 462*0Sstevel@tonic-gate goto end; 463*0Sstevel@tonic-gate } 464*0Sstevel@tonic-gate } 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate if(operation == SMIME_DECRYPT) { 467*0Sstevel@tonic-gate if(!keyfile) keyfile = recipfile; 468*0Sstevel@tonic-gate } else if(operation == SMIME_SIGN) { 469*0Sstevel@tonic-gate if(!keyfile) keyfile = signerfile; 470*0Sstevel@tonic-gate } else keyfile = NULL; 471*0Sstevel@tonic-gate 472*0Sstevel@tonic-gate if(keyfile) { 473*0Sstevel@tonic-gate key = load_key(bio_err, keyfile, keyform, 0, passin, e, 474*0Sstevel@tonic-gate "signing key file"); 475*0Sstevel@tonic-gate if (!key) { 476*0Sstevel@tonic-gate goto end; 477*0Sstevel@tonic-gate } 478*0Sstevel@tonic-gate } 479*0Sstevel@tonic-gate 480*0Sstevel@tonic-gate if (infile) { 481*0Sstevel@tonic-gate if (!(in = BIO_new_file(infile, inmode))) { 482*0Sstevel@tonic-gate BIO_printf (bio_err, 483*0Sstevel@tonic-gate "Can't open input file %s\n", infile); 484*0Sstevel@tonic-gate goto end; 485*0Sstevel@tonic-gate } 486*0Sstevel@tonic-gate } else in = BIO_new_fp(stdin, BIO_NOCLOSE); 487*0Sstevel@tonic-gate 488*0Sstevel@tonic-gate if (outfile) { 489*0Sstevel@tonic-gate if (!(out = BIO_new_file(outfile, outmode))) { 490*0Sstevel@tonic-gate BIO_printf (bio_err, 491*0Sstevel@tonic-gate "Can't open output file %s\n", outfile); 492*0Sstevel@tonic-gate goto end; 493*0Sstevel@tonic-gate } 494*0Sstevel@tonic-gate } else { 495*0Sstevel@tonic-gate out = BIO_new_fp(stdout, BIO_NOCLOSE); 496*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS 497*0Sstevel@tonic-gate { 498*0Sstevel@tonic-gate BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 499*0Sstevel@tonic-gate out = BIO_push(tmpbio, out); 500*0Sstevel@tonic-gate } 501*0Sstevel@tonic-gate #endif 502*0Sstevel@tonic-gate } 503*0Sstevel@tonic-gate 504*0Sstevel@tonic-gate if(operation == SMIME_VERIFY) { 505*0Sstevel@tonic-gate if(!(store = setup_verify(bio_err, CAfile, CApath))) goto end; 506*0Sstevel@tonic-gate X509_STORE_set_flags(store, store_flags); 507*0Sstevel@tonic-gate } 508*0Sstevel@tonic-gate 509*0Sstevel@tonic-gate 510*0Sstevel@tonic-gate ret = 3; 511*0Sstevel@tonic-gate 512*0Sstevel@tonic-gate if(operation == SMIME_ENCRYPT) { 513*0Sstevel@tonic-gate p7 = PKCS7_encrypt(encerts, in, cipher, flags); 514*0Sstevel@tonic-gate } else if(operation == SMIME_SIGN) { 515*0Sstevel@tonic-gate p7 = PKCS7_sign(signer, key, other, in, flags); 516*0Sstevel@tonic-gate if (BIO_reset(in) != 0 && (flags & PKCS7_DETACHED)) { 517*0Sstevel@tonic-gate BIO_printf(bio_err, "Can't rewind input file\n"); 518*0Sstevel@tonic-gate goto end; 519*0Sstevel@tonic-gate } 520*0Sstevel@tonic-gate } else { 521*0Sstevel@tonic-gate if(informat == FORMAT_SMIME) 522*0Sstevel@tonic-gate p7 = SMIME_read_PKCS7(in, &indata); 523*0Sstevel@tonic-gate else if(informat == FORMAT_PEM) 524*0Sstevel@tonic-gate p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); 525*0Sstevel@tonic-gate else if(informat == FORMAT_ASN1) 526*0Sstevel@tonic-gate p7 = d2i_PKCS7_bio(in, NULL); 527*0Sstevel@tonic-gate else { 528*0Sstevel@tonic-gate BIO_printf(bio_err, "Bad input format for PKCS#7 file\n"); 529*0Sstevel@tonic-gate goto end; 530*0Sstevel@tonic-gate } 531*0Sstevel@tonic-gate 532*0Sstevel@tonic-gate if(!p7) { 533*0Sstevel@tonic-gate BIO_printf(bio_err, "Error reading S/MIME message\n"); 534*0Sstevel@tonic-gate goto end; 535*0Sstevel@tonic-gate } 536*0Sstevel@tonic-gate if(contfile) { 537*0Sstevel@tonic-gate BIO_free(indata); 538*0Sstevel@tonic-gate if(!(indata = BIO_new_file(contfile, "rb"))) { 539*0Sstevel@tonic-gate BIO_printf(bio_err, "Can't read content file %s\n", contfile); 540*0Sstevel@tonic-gate goto end; 541*0Sstevel@tonic-gate } 542*0Sstevel@tonic-gate } 543*0Sstevel@tonic-gate } 544*0Sstevel@tonic-gate 545*0Sstevel@tonic-gate if(!p7) { 546*0Sstevel@tonic-gate BIO_printf(bio_err, "Error creating PKCS#7 structure\n"); 547*0Sstevel@tonic-gate goto end; 548*0Sstevel@tonic-gate } 549*0Sstevel@tonic-gate 550*0Sstevel@tonic-gate ret = 4; 551*0Sstevel@tonic-gate if(operation == SMIME_DECRYPT) { 552*0Sstevel@tonic-gate if(!PKCS7_decrypt(p7, key, recip, out, flags)) { 553*0Sstevel@tonic-gate BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n"); 554*0Sstevel@tonic-gate goto end; 555*0Sstevel@tonic-gate } 556*0Sstevel@tonic-gate } else if(operation == SMIME_VERIFY) { 557*0Sstevel@tonic-gate STACK_OF(X509) *signers; 558*0Sstevel@tonic-gate if(PKCS7_verify(p7, other, store, indata, out, flags)) { 559*0Sstevel@tonic-gate BIO_printf(bio_err, "Verification successful\n"); 560*0Sstevel@tonic-gate } else { 561*0Sstevel@tonic-gate BIO_printf(bio_err, "Verification failure\n"); 562*0Sstevel@tonic-gate goto end; 563*0Sstevel@tonic-gate } 564*0Sstevel@tonic-gate signers = PKCS7_get0_signers(p7, other, flags); 565*0Sstevel@tonic-gate if(!save_certs(signerfile, signers)) { 566*0Sstevel@tonic-gate BIO_printf(bio_err, "Error writing signers to %s\n", 567*0Sstevel@tonic-gate signerfile); 568*0Sstevel@tonic-gate ret = 5; 569*0Sstevel@tonic-gate goto end; 570*0Sstevel@tonic-gate } 571*0Sstevel@tonic-gate sk_X509_free(signers); 572*0Sstevel@tonic-gate } else if(operation == SMIME_PK7OUT) { 573*0Sstevel@tonic-gate PEM_write_bio_PKCS7(out, p7); 574*0Sstevel@tonic-gate } else { 575*0Sstevel@tonic-gate if(to) BIO_printf(out, "To: %s\n", to); 576*0Sstevel@tonic-gate if(from) BIO_printf(out, "From: %s\n", from); 577*0Sstevel@tonic-gate if(subject) BIO_printf(out, "Subject: %s\n", subject); 578*0Sstevel@tonic-gate if(outformat == FORMAT_SMIME) 579*0Sstevel@tonic-gate SMIME_write_PKCS7(out, p7, in, flags); 580*0Sstevel@tonic-gate else if(outformat == FORMAT_PEM) 581*0Sstevel@tonic-gate PEM_write_bio_PKCS7(out,p7); 582*0Sstevel@tonic-gate else if(outformat == FORMAT_ASN1) 583*0Sstevel@tonic-gate i2d_PKCS7_bio(out,p7); 584*0Sstevel@tonic-gate else { 585*0Sstevel@tonic-gate BIO_printf(bio_err, "Bad output format for PKCS#7 file\n"); 586*0Sstevel@tonic-gate goto end; 587*0Sstevel@tonic-gate } 588*0Sstevel@tonic-gate } 589*0Sstevel@tonic-gate ret = 0; 590*0Sstevel@tonic-gate end: 591*0Sstevel@tonic-gate if (need_rand) 592*0Sstevel@tonic-gate app_RAND_write_file(NULL, bio_err); 593*0Sstevel@tonic-gate if(ret) ERR_print_errors(bio_err); 594*0Sstevel@tonic-gate sk_X509_pop_free(encerts, X509_free); 595*0Sstevel@tonic-gate sk_X509_pop_free(other, X509_free); 596*0Sstevel@tonic-gate X509_STORE_free(store); 597*0Sstevel@tonic-gate X509_free(cert); 598*0Sstevel@tonic-gate X509_free(recip); 599*0Sstevel@tonic-gate X509_free(signer); 600*0Sstevel@tonic-gate EVP_PKEY_free(key); 601*0Sstevel@tonic-gate PKCS7_free(p7); 602*0Sstevel@tonic-gate BIO_free(in); 603*0Sstevel@tonic-gate BIO_free(indata); 604*0Sstevel@tonic-gate BIO_free_all(out); 605*0Sstevel@tonic-gate if(passin) OPENSSL_free(passin); 606*0Sstevel@tonic-gate return (ret); 607*0Sstevel@tonic-gate } 608*0Sstevel@tonic-gate 609*0Sstevel@tonic-gate static int save_certs(char *signerfile, STACK_OF(X509) *signers) 610*0Sstevel@tonic-gate { 611*0Sstevel@tonic-gate int i; 612*0Sstevel@tonic-gate BIO *tmp; 613*0Sstevel@tonic-gate if(!signerfile) return 1; 614*0Sstevel@tonic-gate tmp = BIO_new_file(signerfile, "w"); 615*0Sstevel@tonic-gate if(!tmp) return 0; 616*0Sstevel@tonic-gate for(i = 0; i < sk_X509_num(signers); i++) 617*0Sstevel@tonic-gate PEM_write_bio_X509(tmp, sk_X509_value(signers, i)); 618*0Sstevel@tonic-gate BIO_free(tmp); 619*0Sstevel@tonic-gate return 1; 620*0Sstevel@tonic-gate } 621*0Sstevel@tonic-gate 622