xref: /onnv-gate/usr/src/common/openssl/apps/smime.c (revision 0:68f95e015346)
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