xref: /dragonfly/crypto/libressl/apps/openssl/smime.c (revision de0e0e4d)
1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: smime.c,v 1.17 2022/01/16 07:12:28 inoguchi Exp $ */
2f5b1c8a1SJohn Marino /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3f5b1c8a1SJohn Marino  * project.
4f5b1c8a1SJohn Marino  */
5f5b1c8a1SJohn Marino /* ====================================================================
6f5b1c8a1SJohn Marino  * Copyright (c) 1999-2004 The OpenSSL Project.  All rights reserved.
7f5b1c8a1SJohn Marino  *
8f5b1c8a1SJohn Marino  * Redistribution and use in source and binary forms, with or without
9f5b1c8a1SJohn Marino  * modification, are permitted provided that the following conditions
10f5b1c8a1SJohn Marino  * are met:
11f5b1c8a1SJohn Marino  *
12f5b1c8a1SJohn Marino  * 1. Redistributions of source code must retain the above copyright
13f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer.
14f5b1c8a1SJohn Marino  *
15f5b1c8a1SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
16f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer in
17f5b1c8a1SJohn Marino  *    the documentation and/or other materials provided with the
18f5b1c8a1SJohn Marino  *    distribution.
19f5b1c8a1SJohn Marino  *
20f5b1c8a1SJohn Marino  * 3. All advertising materials mentioning features or use of this
21f5b1c8a1SJohn Marino  *    software must display the following acknowledgment:
22f5b1c8a1SJohn Marino  *    "This product includes software developed by the OpenSSL Project
23f5b1c8a1SJohn Marino  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24f5b1c8a1SJohn Marino  *
25f5b1c8a1SJohn Marino  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26f5b1c8a1SJohn Marino  *    endorse or promote products derived from this software without
27f5b1c8a1SJohn Marino  *    prior written permission. For written permission, please contact
28f5b1c8a1SJohn Marino  *    licensing@OpenSSL.org.
29f5b1c8a1SJohn Marino  *
30f5b1c8a1SJohn Marino  * 5. Products derived from this software may not be called "OpenSSL"
31f5b1c8a1SJohn Marino  *    nor may "OpenSSL" appear in their names without prior written
32f5b1c8a1SJohn Marino  *    permission of the OpenSSL Project.
33f5b1c8a1SJohn Marino  *
34f5b1c8a1SJohn Marino  * 6. Redistributions of any form whatsoever must retain the following
35f5b1c8a1SJohn Marino  *    acknowledgment:
36f5b1c8a1SJohn Marino  *    "This product includes software developed by the OpenSSL Project
37f5b1c8a1SJohn Marino  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38f5b1c8a1SJohn Marino  *
39f5b1c8a1SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40f5b1c8a1SJohn Marino  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41f5b1c8a1SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42f5b1c8a1SJohn Marino  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43f5b1c8a1SJohn Marino  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44f5b1c8a1SJohn Marino  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45f5b1c8a1SJohn Marino  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46f5b1c8a1SJohn Marino  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47f5b1c8a1SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48f5b1c8a1SJohn Marino  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49f5b1c8a1SJohn Marino  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50f5b1c8a1SJohn Marino  * OF THE POSSIBILITY OF SUCH DAMAGE.
51f5b1c8a1SJohn Marino  * ====================================================================
52f5b1c8a1SJohn Marino  *
53f5b1c8a1SJohn Marino  * This product includes cryptographic software written by Eric Young
54f5b1c8a1SJohn Marino  * (eay@cryptsoft.com).  This product includes software written by Tim
55f5b1c8a1SJohn Marino  * Hudson (tjh@cryptsoft.com).
56f5b1c8a1SJohn Marino  *
57f5b1c8a1SJohn Marino  */
58f5b1c8a1SJohn Marino 
59f5b1c8a1SJohn Marino /* S/MIME utility function */
60f5b1c8a1SJohn Marino 
61f5b1c8a1SJohn Marino #include <stdio.h>
62f5b1c8a1SJohn Marino #include <string.h>
63f5b1c8a1SJohn Marino 
64f5b1c8a1SJohn Marino #include "apps.h"
65f5b1c8a1SJohn Marino 
66f5b1c8a1SJohn Marino #include <openssl/crypto.h>
67f5b1c8a1SJohn Marino #include <openssl/err.h>
68f5b1c8a1SJohn Marino #include <openssl/pem.h>
69f5b1c8a1SJohn Marino #include <openssl/x509_vfy.h>
70f5b1c8a1SJohn Marino #include <openssl/x509v3.h>
71f5b1c8a1SJohn Marino 
72f5b1c8a1SJohn Marino static int save_certs(char *signerfile, STACK_OF(X509) *signers);
73f5b1c8a1SJohn Marino static int smime_cb(int ok, X509_STORE_CTX *ctx);
74f5b1c8a1SJohn Marino 
75f5b1c8a1SJohn Marino #define SMIME_OP	0x10
76f5b1c8a1SJohn Marino #define SMIME_IP	0x20
77f5b1c8a1SJohn Marino #define SMIME_SIGNERS	0x40
78f5b1c8a1SJohn Marino #define SMIME_ENCRYPT	(1 | SMIME_OP)
79f5b1c8a1SJohn Marino #define SMIME_DECRYPT	(2 | SMIME_IP)
80f5b1c8a1SJohn Marino #define SMIME_SIGN	(3 | SMIME_OP | SMIME_SIGNERS)
81f5b1c8a1SJohn Marino #define SMIME_VERIFY	(4 | SMIME_IP)
82f5b1c8a1SJohn Marino #define SMIME_PK7OUT	(5 | SMIME_IP | SMIME_OP)
83f5b1c8a1SJohn Marino #define SMIME_RESIGN	(6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
84f5b1c8a1SJohn Marino 
85*de0e0e4dSAntonio Huete Jimenez static struct {
86*de0e0e4dSAntonio Huete Jimenez 	char *CAfile;
87*de0e0e4dSAntonio Huete Jimenez 	char *CApath;
88*de0e0e4dSAntonio Huete Jimenez 	char *certfile;
89*de0e0e4dSAntonio Huete Jimenez 	const EVP_CIPHER *cipher;
90*de0e0e4dSAntonio Huete Jimenez 	char *contfile;
91*de0e0e4dSAntonio Huete Jimenez 	int flags;
92*de0e0e4dSAntonio Huete Jimenez 	char *from;
93*de0e0e4dSAntonio Huete Jimenez 	int indef;
94*de0e0e4dSAntonio Huete Jimenez 	char *infile;
95*de0e0e4dSAntonio Huete Jimenez 	int informat;
96*de0e0e4dSAntonio Huete Jimenez 	char *keyfile;
97*de0e0e4dSAntonio Huete Jimenez 	int keyform;
98*de0e0e4dSAntonio Huete Jimenez 	int operation;
99*de0e0e4dSAntonio Huete Jimenez 	char *outfile;
100*de0e0e4dSAntonio Huete Jimenez 	int outformat;
101*de0e0e4dSAntonio Huete Jimenez 	char *passargin;
102*de0e0e4dSAntonio Huete Jimenez 	char *recipfile;
103*de0e0e4dSAntonio Huete Jimenez 	const EVP_MD *sign_md;
104*de0e0e4dSAntonio Huete Jimenez 	char *signerfile;
105*de0e0e4dSAntonio Huete Jimenez 	STACK_OF(OPENSSL_STRING) *skkeys;
106*de0e0e4dSAntonio Huete Jimenez 	STACK_OF(OPENSSL_STRING) *sksigners;
107*de0e0e4dSAntonio Huete Jimenez 	char *subject;
108*de0e0e4dSAntonio Huete Jimenez 	char *to;
109*de0e0e4dSAntonio Huete Jimenez 	X509_VERIFY_PARAM *vpm;
110*de0e0e4dSAntonio Huete Jimenez } smime_config;
111*de0e0e4dSAntonio Huete Jimenez 
112*de0e0e4dSAntonio Huete Jimenez static const EVP_CIPHER *
get_cipher_by_name(char * name)113*de0e0e4dSAntonio Huete Jimenez get_cipher_by_name(char *name)
114*de0e0e4dSAntonio Huete Jimenez {
115*de0e0e4dSAntonio Huete Jimenez 	if (name == NULL || strcmp(name, "") == 0)
116*de0e0e4dSAntonio Huete Jimenez 		return (NULL);
117*de0e0e4dSAntonio Huete Jimenez #ifndef OPENSSL_NO_AES
118*de0e0e4dSAntonio Huete Jimenez 	else if (strcmp(name, "aes128") == 0)
119*de0e0e4dSAntonio Huete Jimenez 		return EVP_aes_128_cbc();
120*de0e0e4dSAntonio Huete Jimenez 	else if (strcmp(name, "aes192") == 0)
121*de0e0e4dSAntonio Huete Jimenez 		return EVP_aes_192_cbc();
122*de0e0e4dSAntonio Huete Jimenez 	else if (strcmp(name, "aes256") == 0)
123*de0e0e4dSAntonio Huete Jimenez 		return EVP_aes_256_cbc();
124*de0e0e4dSAntonio Huete Jimenez #endif
125*de0e0e4dSAntonio Huete Jimenez #ifndef OPENSSL_NO_CAMELLIA
126*de0e0e4dSAntonio Huete Jimenez 	else if (strcmp(name, "camellia128") == 0)
127*de0e0e4dSAntonio Huete Jimenez 		return EVP_camellia_128_cbc();
128*de0e0e4dSAntonio Huete Jimenez 	else if (strcmp(name, "camellia192") == 0)
129*de0e0e4dSAntonio Huete Jimenez 		return EVP_camellia_192_cbc();
130*de0e0e4dSAntonio Huete Jimenez 	else if (strcmp(name, "camellia256") == 0)
131*de0e0e4dSAntonio Huete Jimenez 		return EVP_camellia_256_cbc();
132*de0e0e4dSAntonio Huete Jimenez #endif
133*de0e0e4dSAntonio Huete Jimenez #ifndef OPENSSL_NO_DES
134*de0e0e4dSAntonio Huete Jimenez 	else if (strcmp(name, "des") == 0)
135*de0e0e4dSAntonio Huete Jimenez 		return EVP_des_cbc();
136*de0e0e4dSAntonio Huete Jimenez 	else if (strcmp(name, "des3") == 0)
137*de0e0e4dSAntonio Huete Jimenez 		return EVP_des_ede3_cbc();
138*de0e0e4dSAntonio Huete Jimenez #endif
139*de0e0e4dSAntonio Huete Jimenez #ifndef OPENSSL_NO_RC2
140*de0e0e4dSAntonio Huete Jimenez 	else if (!strcmp(name, "rc2-40"))
141*de0e0e4dSAntonio Huete Jimenez 		return EVP_rc2_40_cbc();
142*de0e0e4dSAntonio Huete Jimenez 	else if (!strcmp(name, "rc2-64"))
143*de0e0e4dSAntonio Huete Jimenez 		return EVP_rc2_64_cbc();
144*de0e0e4dSAntonio Huete Jimenez 	else if (!strcmp(name, "rc2-128"))
145*de0e0e4dSAntonio Huete Jimenez 		return EVP_rc2_cbc();
146*de0e0e4dSAntonio Huete Jimenez #endif
147*de0e0e4dSAntonio Huete Jimenez 	else
148*de0e0e4dSAntonio Huete Jimenez 		return NULL;
149*de0e0e4dSAntonio Huete Jimenez }
150*de0e0e4dSAntonio Huete Jimenez 
151*de0e0e4dSAntonio Huete Jimenez static int
smime_opt_cipher(int argc,char ** argv,int * argsused)152*de0e0e4dSAntonio Huete Jimenez smime_opt_cipher(int argc, char **argv, int *argsused)
153*de0e0e4dSAntonio Huete Jimenez {
154*de0e0e4dSAntonio Huete Jimenez 	char *name = argv[0];
155*de0e0e4dSAntonio Huete Jimenez 
156*de0e0e4dSAntonio Huete Jimenez 	if (*name++ != '-')
157*de0e0e4dSAntonio Huete Jimenez 		return (1);
158*de0e0e4dSAntonio Huete Jimenez 
159*de0e0e4dSAntonio Huete Jimenez 	if ((smime_config.cipher = get_cipher_by_name(name)) == NULL)
160*de0e0e4dSAntonio Huete Jimenez 		if ((smime_config.cipher = EVP_get_cipherbyname(name)) == NULL)
161*de0e0e4dSAntonio Huete Jimenez 			return (1);
162*de0e0e4dSAntonio Huete Jimenez 
163*de0e0e4dSAntonio Huete Jimenez 	*argsused = 1;
164*de0e0e4dSAntonio Huete Jimenez 	return (0);
165*de0e0e4dSAntonio Huete Jimenez }
166*de0e0e4dSAntonio Huete Jimenez 
167*de0e0e4dSAntonio Huete Jimenez static int
smime_opt_inkey(char * arg)168*de0e0e4dSAntonio Huete Jimenez smime_opt_inkey(char *arg)
169*de0e0e4dSAntonio Huete Jimenez {
170*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.keyfile == NULL) {
171*de0e0e4dSAntonio Huete Jimenez 		smime_config.keyfile = arg;
172*de0e0e4dSAntonio Huete Jimenez 		return (0);
173*de0e0e4dSAntonio Huete Jimenez 	}
174*de0e0e4dSAntonio Huete Jimenez 
175*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.signerfile == NULL) {
176*de0e0e4dSAntonio Huete Jimenez 		BIO_puts(bio_err, "Illegal -inkey without -signer\n");
177*de0e0e4dSAntonio Huete Jimenez 		return (1);
178*de0e0e4dSAntonio Huete Jimenez 	}
179*de0e0e4dSAntonio Huete Jimenez 
180*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.sksigners == NULL) {
181*de0e0e4dSAntonio Huete Jimenez 		if ((smime_config.sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
182*de0e0e4dSAntonio Huete Jimenez 			return (1);
183*de0e0e4dSAntonio Huete Jimenez 	}
184*de0e0e4dSAntonio Huete Jimenez 	if (!sk_OPENSSL_STRING_push(smime_config.sksigners,
185*de0e0e4dSAntonio Huete Jimenez 	    smime_config.signerfile))
186*de0e0e4dSAntonio Huete Jimenez 		return (1);
187*de0e0e4dSAntonio Huete Jimenez 
188*de0e0e4dSAntonio Huete Jimenez 	smime_config.signerfile = NULL;
189*de0e0e4dSAntonio Huete Jimenez 
190*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.skkeys == NULL) {
191*de0e0e4dSAntonio Huete Jimenez 		if ((smime_config.skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
192*de0e0e4dSAntonio Huete Jimenez 			return (1);
193*de0e0e4dSAntonio Huete Jimenez 	}
194*de0e0e4dSAntonio Huete Jimenez 	if (!sk_OPENSSL_STRING_push(smime_config.skkeys, smime_config.keyfile))
195*de0e0e4dSAntonio Huete Jimenez 		return (1);
196*de0e0e4dSAntonio Huete Jimenez 
197*de0e0e4dSAntonio Huete Jimenez 	smime_config.keyfile = arg;
198*de0e0e4dSAntonio Huete Jimenez 	return (0);
199*de0e0e4dSAntonio Huete Jimenez }
200*de0e0e4dSAntonio Huete Jimenez 
201*de0e0e4dSAntonio Huete Jimenez static int
smime_opt_md(char * arg)202*de0e0e4dSAntonio Huete Jimenez smime_opt_md(char *arg)
203*de0e0e4dSAntonio Huete Jimenez {
204*de0e0e4dSAntonio Huete Jimenez 	if ((smime_config.sign_md = EVP_get_digestbyname(arg)) == NULL) {
205*de0e0e4dSAntonio Huete Jimenez 		BIO_printf(bio_err, "Unknown digest %s\n", arg);
206*de0e0e4dSAntonio Huete Jimenez 		return (1);
207*de0e0e4dSAntonio Huete Jimenez 	}
208*de0e0e4dSAntonio Huete Jimenez 	return (0);
209*de0e0e4dSAntonio Huete Jimenez }
210*de0e0e4dSAntonio Huete Jimenez 
211*de0e0e4dSAntonio Huete Jimenez static int
smime_opt_signer(char * arg)212*de0e0e4dSAntonio Huete Jimenez smime_opt_signer(char *arg)
213*de0e0e4dSAntonio Huete Jimenez {
214*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.signerfile == NULL) {
215*de0e0e4dSAntonio Huete Jimenez 		smime_config.signerfile = arg;
216*de0e0e4dSAntonio Huete Jimenez 		return (0);
217*de0e0e4dSAntonio Huete Jimenez 	}
218*de0e0e4dSAntonio Huete Jimenez 
219*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.sksigners == NULL) {
220*de0e0e4dSAntonio Huete Jimenez 		if ((smime_config.sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
221*de0e0e4dSAntonio Huete Jimenez 			return (1);
222*de0e0e4dSAntonio Huete Jimenez 	}
223*de0e0e4dSAntonio Huete Jimenez 	if (!sk_OPENSSL_STRING_push(smime_config.sksigners,
224*de0e0e4dSAntonio Huete Jimenez 	    smime_config.signerfile))
225*de0e0e4dSAntonio Huete Jimenez 		return (1);
226*de0e0e4dSAntonio Huete Jimenez 
227*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.keyfile == NULL)
228*de0e0e4dSAntonio Huete Jimenez 		smime_config.keyfile = smime_config.signerfile;
229*de0e0e4dSAntonio Huete Jimenez 
230*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.skkeys == NULL) {
231*de0e0e4dSAntonio Huete Jimenez 		if ((smime_config.skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
232*de0e0e4dSAntonio Huete Jimenez 			return (1);
233*de0e0e4dSAntonio Huete Jimenez 	}
234*de0e0e4dSAntonio Huete Jimenez 	if (!sk_OPENSSL_STRING_push(smime_config.skkeys, smime_config.keyfile))
235*de0e0e4dSAntonio Huete Jimenez 		return (1);
236*de0e0e4dSAntonio Huete Jimenez 
237*de0e0e4dSAntonio Huete Jimenez 	smime_config.keyfile = NULL;
238*de0e0e4dSAntonio Huete Jimenez 
239*de0e0e4dSAntonio Huete Jimenez 	smime_config.signerfile = arg;
240*de0e0e4dSAntonio Huete Jimenez 	return (0);
241*de0e0e4dSAntonio Huete Jimenez }
242*de0e0e4dSAntonio Huete Jimenez 
243*de0e0e4dSAntonio Huete Jimenez static int
smime_opt_verify_param(int argc,char ** argv,int * argsused)244*de0e0e4dSAntonio Huete Jimenez smime_opt_verify_param(int argc, char **argv, int *argsused)
245*de0e0e4dSAntonio Huete Jimenez {
246*de0e0e4dSAntonio Huete Jimenez 	int oargc = argc;
247*de0e0e4dSAntonio Huete Jimenez 	int badarg = 0;
248*de0e0e4dSAntonio Huete Jimenez 
249*de0e0e4dSAntonio Huete Jimenez 	if (!args_verify(&argv, &argc, &badarg, bio_err, &smime_config.vpm))
250*de0e0e4dSAntonio Huete Jimenez 		return (1);
251*de0e0e4dSAntonio Huete Jimenez 	if (badarg)
252*de0e0e4dSAntonio Huete Jimenez 		return (1);
253*de0e0e4dSAntonio Huete Jimenez 
254*de0e0e4dSAntonio Huete Jimenez 	*argsused = oargc - argc;
255*de0e0e4dSAntonio Huete Jimenez 
256*de0e0e4dSAntonio Huete Jimenez 	return (0);
257*de0e0e4dSAntonio Huete Jimenez }
258*de0e0e4dSAntonio Huete Jimenez 
259*de0e0e4dSAntonio Huete Jimenez static const struct option smime_options[] = {
260*de0e0e4dSAntonio Huete Jimenez #ifndef OPENSSL_NO_AES
261*de0e0e4dSAntonio Huete Jimenez 	{
262*de0e0e4dSAntonio Huete Jimenez 		.name = "aes128",
263*de0e0e4dSAntonio Huete Jimenez 		.desc = "Encrypt PEM output with CBC AES",
264*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARGV_FUNC,
265*de0e0e4dSAntonio Huete Jimenez 		.opt.argvfunc = smime_opt_cipher,
266*de0e0e4dSAntonio Huete Jimenez 	},
267*de0e0e4dSAntonio Huete Jimenez 	{
268*de0e0e4dSAntonio Huete Jimenez 		.name = "aes192",
269*de0e0e4dSAntonio Huete Jimenez 		.desc = "Encrypt PEM output with CBC AES",
270*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARGV_FUNC,
271*de0e0e4dSAntonio Huete Jimenez 		.opt.argvfunc = smime_opt_cipher,
272*de0e0e4dSAntonio Huete Jimenez 	},
273*de0e0e4dSAntonio Huete Jimenez 	{
274*de0e0e4dSAntonio Huete Jimenez 		.name = "aes256",
275*de0e0e4dSAntonio Huete Jimenez 		.desc = "Encrypt PEM output with CBC AES",
276*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARGV_FUNC,
277*de0e0e4dSAntonio Huete Jimenez 		.opt.argvfunc = smime_opt_cipher,
278*de0e0e4dSAntonio Huete Jimenez 	},
279*de0e0e4dSAntonio Huete Jimenez #endif
280*de0e0e4dSAntonio Huete Jimenez #ifndef OPENSSL_NO_CAMELLIA
281*de0e0e4dSAntonio Huete Jimenez 	{
282*de0e0e4dSAntonio Huete Jimenez 		.name = "camellia128",
283*de0e0e4dSAntonio Huete Jimenez 		.desc = "Encrypt PEM output with CBC Camellia",
284*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARGV_FUNC,
285*de0e0e4dSAntonio Huete Jimenez 		.opt.argvfunc = smime_opt_cipher,
286*de0e0e4dSAntonio Huete Jimenez 	},
287*de0e0e4dSAntonio Huete Jimenez 	{
288*de0e0e4dSAntonio Huete Jimenez 		.name = "camellia192",
289*de0e0e4dSAntonio Huete Jimenez 		.desc = "Encrypt PEM output with CBC Camellia",
290*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARGV_FUNC,
291*de0e0e4dSAntonio Huete Jimenez 		.opt.argvfunc = smime_opt_cipher,
292*de0e0e4dSAntonio Huete Jimenez 	},
293*de0e0e4dSAntonio Huete Jimenez 	{
294*de0e0e4dSAntonio Huete Jimenez 		.name = "camellia256",
295*de0e0e4dSAntonio Huete Jimenez 		.desc = "Encrypt PEM output with CBC Camellia",
296*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARGV_FUNC,
297*de0e0e4dSAntonio Huete Jimenez 		.opt.argvfunc = smime_opt_cipher,
298*de0e0e4dSAntonio Huete Jimenez 	},
299*de0e0e4dSAntonio Huete Jimenez #endif
300*de0e0e4dSAntonio Huete Jimenez #ifndef OPENSSL_NO_DES
301*de0e0e4dSAntonio Huete Jimenez 	{
302*de0e0e4dSAntonio Huete Jimenez 		.name = "des",
303*de0e0e4dSAntonio Huete Jimenez 		.desc = "Encrypt with DES",
304*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARGV_FUNC,
305*de0e0e4dSAntonio Huete Jimenez 		.opt.argvfunc = smime_opt_cipher,
306*de0e0e4dSAntonio Huete Jimenez 	},
307*de0e0e4dSAntonio Huete Jimenez 	{
308*de0e0e4dSAntonio Huete Jimenez 		.name = "des3",
309*de0e0e4dSAntonio Huete Jimenez 		.desc = "Encrypt with triple DES",
310*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARGV_FUNC,
311*de0e0e4dSAntonio Huete Jimenez 		.opt.argvfunc = smime_opt_cipher,
312*de0e0e4dSAntonio Huete Jimenez 	},
313*de0e0e4dSAntonio Huete Jimenez #endif
314*de0e0e4dSAntonio Huete Jimenez #ifndef OPENSSL_NO_RC2
315*de0e0e4dSAntonio Huete Jimenez 	{
316*de0e0e4dSAntonio Huete Jimenez 		.name = "rc2-40",
317*de0e0e4dSAntonio Huete Jimenez 		.desc = "Encrypt with RC2-40 (default)",
318*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARGV_FUNC,
319*de0e0e4dSAntonio Huete Jimenez 		.opt.argvfunc = smime_opt_cipher,
320*de0e0e4dSAntonio Huete Jimenez 	},
321*de0e0e4dSAntonio Huete Jimenez 	{
322*de0e0e4dSAntonio Huete Jimenez 		.name = "rc2-64",
323*de0e0e4dSAntonio Huete Jimenez 		.desc = "Encrypt with RC2-64",
324*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARGV_FUNC,
325*de0e0e4dSAntonio Huete Jimenez 		.opt.argvfunc = smime_opt_cipher,
326*de0e0e4dSAntonio Huete Jimenez 	},
327*de0e0e4dSAntonio Huete Jimenez 	{
328*de0e0e4dSAntonio Huete Jimenez 		.name = "rc2-128",
329*de0e0e4dSAntonio Huete Jimenez 		.desc = "Encrypt with RC2-128",
330*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARGV_FUNC,
331*de0e0e4dSAntonio Huete Jimenez 		.opt.argvfunc = smime_opt_cipher,
332*de0e0e4dSAntonio Huete Jimenez 	},
333*de0e0e4dSAntonio Huete Jimenez #endif
334*de0e0e4dSAntonio Huete Jimenez 	{
335*de0e0e4dSAntonio Huete Jimenez 		.name = "CAfile",
336*de0e0e4dSAntonio Huete Jimenez 		.argname = "file",
337*de0e0e4dSAntonio Huete Jimenez 		.desc = "Certificate Authority file",
338*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARG,
339*de0e0e4dSAntonio Huete Jimenez 		.opt.arg = &smime_config.CAfile,
340*de0e0e4dSAntonio Huete Jimenez 	},
341*de0e0e4dSAntonio Huete Jimenez 	{
342*de0e0e4dSAntonio Huete Jimenez 		.name = "CApath",
343*de0e0e4dSAntonio Huete Jimenez 		.argname = "path",
344*de0e0e4dSAntonio Huete Jimenez 		.desc = "Certificate Authority path",
345*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARG,
346*de0e0e4dSAntonio Huete Jimenez 		.opt.arg = &smime_config.CApath,
347*de0e0e4dSAntonio Huete Jimenez 	},
348*de0e0e4dSAntonio Huete Jimenez 	{
349*de0e0e4dSAntonio Huete Jimenez 		.name = "binary",
350*de0e0e4dSAntonio Huete Jimenez 		.desc = "Do not translate message to text",
351*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE_OR,
352*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.flags,
353*de0e0e4dSAntonio Huete Jimenez 		.value = PKCS7_BINARY,
354*de0e0e4dSAntonio Huete Jimenez 	},
355*de0e0e4dSAntonio Huete Jimenez 	{
356*de0e0e4dSAntonio Huete Jimenez 		.name = "certfile",
357*de0e0e4dSAntonio Huete Jimenez 		.argname = "file",
358*de0e0e4dSAntonio Huete Jimenez 		.desc = "Other certificates file",
359*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARG,
360*de0e0e4dSAntonio Huete Jimenez 		.opt.arg = &smime_config.certfile,
361*de0e0e4dSAntonio Huete Jimenez 	},
362*de0e0e4dSAntonio Huete Jimenez 	{
363*de0e0e4dSAntonio Huete Jimenez 		.name = "content",
364*de0e0e4dSAntonio Huete Jimenez 		.argname = "file",
365*de0e0e4dSAntonio Huete Jimenez 		.desc = "Supply or override content for detached signature",
366*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARG,
367*de0e0e4dSAntonio Huete Jimenez 		.opt.arg = &smime_config.contfile,
368*de0e0e4dSAntonio Huete Jimenez 	},
369*de0e0e4dSAntonio Huete Jimenez 	{
370*de0e0e4dSAntonio Huete Jimenez 		.name = "crlfeol",
371*de0e0e4dSAntonio Huete Jimenez 		.desc = "Use CRLF as EOL termination instead of CR only",
372*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE_OR,
373*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.flags,
374*de0e0e4dSAntonio Huete Jimenez 		.value = PKCS7_CRLFEOL,
375*de0e0e4dSAntonio Huete Jimenez 	},
376*de0e0e4dSAntonio Huete Jimenez 	{
377*de0e0e4dSAntonio Huete Jimenez 		.name = "decrypt",
378*de0e0e4dSAntonio Huete Jimenez 		.desc = "Decrypt encrypted message",
379*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE,
380*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.operation,
381*de0e0e4dSAntonio Huete Jimenez 		.value = SMIME_DECRYPT,
382*de0e0e4dSAntonio Huete Jimenez 	},
383*de0e0e4dSAntonio Huete Jimenez 	{
384*de0e0e4dSAntonio Huete Jimenez 		.name = "encrypt",
385*de0e0e4dSAntonio Huete Jimenez 		.desc = "Encrypt message",
386*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE,
387*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.operation,
388*de0e0e4dSAntonio Huete Jimenez 		.value = SMIME_ENCRYPT,
389*de0e0e4dSAntonio Huete Jimenez 	},
390*de0e0e4dSAntonio Huete Jimenez 	{
391*de0e0e4dSAntonio Huete Jimenez 		.name = "from",
392*de0e0e4dSAntonio Huete Jimenez 		.argname = "addr",
393*de0e0e4dSAntonio Huete Jimenez 		.desc = "From address",
394*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARG,
395*de0e0e4dSAntonio Huete Jimenez 		.opt.arg = &smime_config.from,
396*de0e0e4dSAntonio Huete Jimenez 	},
397*de0e0e4dSAntonio Huete Jimenez 	{
398*de0e0e4dSAntonio Huete Jimenez 		.name = "in",
399*de0e0e4dSAntonio Huete Jimenez 		.argname = "file",
400*de0e0e4dSAntonio Huete Jimenez 		.desc = "Input file",
401*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARG,
402*de0e0e4dSAntonio Huete Jimenez 		.opt.arg = &smime_config.infile,
403*de0e0e4dSAntonio Huete Jimenez 	},
404*de0e0e4dSAntonio Huete Jimenez 	{
405*de0e0e4dSAntonio Huete Jimenez 		.name = "indef",
406*de0e0e4dSAntonio Huete Jimenez 		.desc = "Same as -stream",
407*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE,
408*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.indef,
409*de0e0e4dSAntonio Huete Jimenez 		.value = 1,
410*de0e0e4dSAntonio Huete Jimenez 	},
411*de0e0e4dSAntonio Huete Jimenez 	{
412*de0e0e4dSAntonio Huete Jimenez 		.name = "inform",
413*de0e0e4dSAntonio Huete Jimenez 		.argname = "fmt",
414*de0e0e4dSAntonio Huete Jimenez 		.desc = "Input format (DER, PEM or SMIME (default))",
415*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARG_FORMAT,
416*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.informat,
417*de0e0e4dSAntonio Huete Jimenez 	},
418*de0e0e4dSAntonio Huete Jimenez 	{
419*de0e0e4dSAntonio Huete Jimenez 		.name = "inkey",
420*de0e0e4dSAntonio Huete Jimenez 		.argname = "file",
421*de0e0e4dSAntonio Huete Jimenez 		.desc = "Input key file",
422*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARG_FUNC,
423*de0e0e4dSAntonio Huete Jimenez 		.opt.argfunc = smime_opt_inkey,
424*de0e0e4dSAntonio Huete Jimenez 	},
425*de0e0e4dSAntonio Huete Jimenez 	{
426*de0e0e4dSAntonio Huete Jimenez 		.name = "keyform",
427*de0e0e4dSAntonio Huete Jimenez 		.argname = "fmt",
428*de0e0e4dSAntonio Huete Jimenez 		.desc = "Input key format (DER or PEM (default))",
429*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARG_FORMAT,
430*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.keyform,
431*de0e0e4dSAntonio Huete Jimenez 	},
432*de0e0e4dSAntonio Huete Jimenez 	{
433*de0e0e4dSAntonio Huete Jimenez 		.name = "md",
434*de0e0e4dSAntonio Huete Jimenez 		.argname = "digest",
435*de0e0e4dSAntonio Huete Jimenez 		.desc = "Digest to use when signing or resigning",
436*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARG_FUNC,
437*de0e0e4dSAntonio Huete Jimenez 		.opt.argfunc = smime_opt_md,
438*de0e0e4dSAntonio Huete Jimenez 	},
439*de0e0e4dSAntonio Huete Jimenez 	{
440*de0e0e4dSAntonio Huete Jimenez 		.name = "noattr",
441*de0e0e4dSAntonio Huete Jimenez 		.desc = "Do not include any signed attributes",
442*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE_OR,
443*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.flags,
444*de0e0e4dSAntonio Huete Jimenez 		.value = PKCS7_NOATTR,
445*de0e0e4dSAntonio Huete Jimenez 	},
446*de0e0e4dSAntonio Huete Jimenez 	{
447*de0e0e4dSAntonio Huete Jimenez 		.name = "nocerts",
448*de0e0e4dSAntonio Huete Jimenez 		.desc = "Do not include signer's certificate when signing",
449*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE_OR,
450*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.flags,
451*de0e0e4dSAntonio Huete Jimenez 		.value = PKCS7_NOCERTS,
452*de0e0e4dSAntonio Huete Jimenez 	},
453*de0e0e4dSAntonio Huete Jimenez 	{
454*de0e0e4dSAntonio Huete Jimenez 		.name = "nochain",
455*de0e0e4dSAntonio Huete Jimenez 		.desc = "Do not chain verification of signer's certificates",
456*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE_OR,
457*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.flags,
458*de0e0e4dSAntonio Huete Jimenez 		.value = PKCS7_NOCHAIN,
459*de0e0e4dSAntonio Huete Jimenez 	},
460*de0e0e4dSAntonio Huete Jimenez 	{
461*de0e0e4dSAntonio Huete Jimenez 		.name = "nodetach",
462*de0e0e4dSAntonio Huete Jimenez 		.desc = "Use opaque signing",
463*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE_AND,
464*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.flags,
465*de0e0e4dSAntonio Huete Jimenez 		.value = ~PKCS7_DETACHED,
466*de0e0e4dSAntonio Huete Jimenez 	},
467*de0e0e4dSAntonio Huete Jimenez 	{
468*de0e0e4dSAntonio Huete Jimenez 		.name = "noindef",
469*de0e0e4dSAntonio Huete Jimenez 		.desc = "Disable streaming I/O",
470*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE,
471*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.indef,
472*de0e0e4dSAntonio Huete Jimenez 		.value = 0,
473*de0e0e4dSAntonio Huete Jimenez 	},
474*de0e0e4dSAntonio Huete Jimenez 	{
475*de0e0e4dSAntonio Huete Jimenez 		.name = "nointern",
476*de0e0e4dSAntonio Huete Jimenez 		.desc = "Do not search certificates in message for signer",
477*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE_OR,
478*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.flags,
479*de0e0e4dSAntonio Huete Jimenez 		.value = PKCS7_NOINTERN,
480*de0e0e4dSAntonio Huete Jimenez 	},
481*de0e0e4dSAntonio Huete Jimenez 	{
482*de0e0e4dSAntonio Huete Jimenez 		.name = "nooldmime",
483*de0e0e4dSAntonio Huete Jimenez 		.desc = "Output old S/MIME content type",
484*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE_OR,
485*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.flags,
486*de0e0e4dSAntonio Huete Jimenez 		.value = PKCS7_NOOLDMIMETYPE,
487*de0e0e4dSAntonio Huete Jimenez 	},
488*de0e0e4dSAntonio Huete Jimenez 	{
489*de0e0e4dSAntonio Huete Jimenez 		.name = "nosigs",
490*de0e0e4dSAntonio Huete Jimenez 		.desc = "Do not verify message signature",
491*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE_OR,
492*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.flags,
493*de0e0e4dSAntonio Huete Jimenez 		.value = PKCS7_NOSIGS,
494*de0e0e4dSAntonio Huete Jimenez 	},
495*de0e0e4dSAntonio Huete Jimenez 	{
496*de0e0e4dSAntonio Huete Jimenez 		.name = "nosmimecap",
497*de0e0e4dSAntonio Huete Jimenez 		.desc = "Omit the SMIMECapabilities attribute",
498*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE_OR,
499*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.flags,
500*de0e0e4dSAntonio Huete Jimenez 		.value = PKCS7_NOSMIMECAP,
501*de0e0e4dSAntonio Huete Jimenez 	},
502*de0e0e4dSAntonio Huete Jimenez 	{
503*de0e0e4dSAntonio Huete Jimenez 		.name = "noverify",
504*de0e0e4dSAntonio Huete Jimenez 		.desc = "Do not verify signer's certificate",
505*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE_OR,
506*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.flags,
507*de0e0e4dSAntonio Huete Jimenez 		.value = PKCS7_NOVERIFY,
508*de0e0e4dSAntonio Huete Jimenez 	},
509*de0e0e4dSAntonio Huete Jimenez 	{
510*de0e0e4dSAntonio Huete Jimenez 		.name = "out",
511*de0e0e4dSAntonio Huete Jimenez 		.argname = "file",
512*de0e0e4dSAntonio Huete Jimenez 		.desc = "Output file",
513*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARG,
514*de0e0e4dSAntonio Huete Jimenez 		.opt.arg = &smime_config.outfile,
515*de0e0e4dSAntonio Huete Jimenez 	},
516*de0e0e4dSAntonio Huete Jimenez 	{
517*de0e0e4dSAntonio Huete Jimenez 		.name = "outform",
518*de0e0e4dSAntonio Huete Jimenez 		.argname = "fmt",
519*de0e0e4dSAntonio Huete Jimenez 		.desc = "Output format (DER, PEM or SMIME (default))",
520*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARG_FORMAT,
521*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.outformat,
522*de0e0e4dSAntonio Huete Jimenez 	},
523*de0e0e4dSAntonio Huete Jimenez 	{
524*de0e0e4dSAntonio Huete Jimenez 		.name = "passin",
525*de0e0e4dSAntonio Huete Jimenez 		.argname = "src",
526*de0e0e4dSAntonio Huete Jimenez 		.desc = "Private key password source",
527*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARG,
528*de0e0e4dSAntonio Huete Jimenez 		.opt.arg = &smime_config.passargin,
529*de0e0e4dSAntonio Huete Jimenez 	},
530*de0e0e4dSAntonio Huete Jimenez 	{
531*de0e0e4dSAntonio Huete Jimenez 		.name = "pk7out",
532*de0e0e4dSAntonio Huete Jimenez 		.desc = "Output PKCS#7 structure",
533*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE,
534*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.operation,
535*de0e0e4dSAntonio Huete Jimenez 		.value = SMIME_PK7OUT,
536*de0e0e4dSAntonio Huete Jimenez 	},
537*de0e0e4dSAntonio Huete Jimenez 	{
538*de0e0e4dSAntonio Huete Jimenez 		.name = "recip",
539*de0e0e4dSAntonio Huete Jimenez 		.argname = "file",
540*de0e0e4dSAntonio Huete Jimenez 		.desc = "Recipient certificate file for decryption",
541*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARG,
542*de0e0e4dSAntonio Huete Jimenez 		.opt.arg = &smime_config.recipfile,
543*de0e0e4dSAntonio Huete Jimenez 	},
544*de0e0e4dSAntonio Huete Jimenez 	{
545*de0e0e4dSAntonio Huete Jimenez 		.name = "resign",
546*de0e0e4dSAntonio Huete Jimenez 		.desc = "Resign a signed message",
547*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE,
548*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.operation,
549*de0e0e4dSAntonio Huete Jimenez 		.value = SMIME_RESIGN,
550*de0e0e4dSAntonio Huete Jimenez 	},
551*de0e0e4dSAntonio Huete Jimenez 	{
552*de0e0e4dSAntonio Huete Jimenez 		.name = "sign",
553*de0e0e4dSAntonio Huete Jimenez 		.desc = "Sign message",
554*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE,
555*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.operation,
556*de0e0e4dSAntonio Huete Jimenez 		.value = SMIME_SIGN,
557*de0e0e4dSAntonio Huete Jimenez 	},
558*de0e0e4dSAntonio Huete Jimenez 	{
559*de0e0e4dSAntonio Huete Jimenez 		.name = "signer",
560*de0e0e4dSAntonio Huete Jimenez 		.argname = "file",
561*de0e0e4dSAntonio Huete Jimenez 		.desc = "Signer certificate file",
562*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARG_FUNC,
563*de0e0e4dSAntonio Huete Jimenez 		.opt.argfunc = smime_opt_signer,
564*de0e0e4dSAntonio Huete Jimenez 	},
565*de0e0e4dSAntonio Huete Jimenez 	{
566*de0e0e4dSAntonio Huete Jimenez 		.name = "stream",
567*de0e0e4dSAntonio Huete Jimenez 		.desc = "Enable streaming I/O",
568*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE,
569*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.indef,
570*de0e0e4dSAntonio Huete Jimenez 		.value = 1,
571*de0e0e4dSAntonio Huete Jimenez 	},
572*de0e0e4dSAntonio Huete Jimenez 	{
573*de0e0e4dSAntonio Huete Jimenez 		.name = "subject",
574*de0e0e4dSAntonio Huete Jimenez 		.argname = "s",
575*de0e0e4dSAntonio Huete Jimenez 		.desc = "Subject",
576*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARG,
577*de0e0e4dSAntonio Huete Jimenez 		.opt.arg = &smime_config.subject,
578*de0e0e4dSAntonio Huete Jimenez 	},
579*de0e0e4dSAntonio Huete Jimenez 	{
580*de0e0e4dSAntonio Huete Jimenez 		.name = "text",
581*de0e0e4dSAntonio Huete Jimenez 		.desc = "Include or delete text MIME headers",
582*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE_OR,
583*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.flags,
584*de0e0e4dSAntonio Huete Jimenez 		.value = PKCS7_TEXT,
585*de0e0e4dSAntonio Huete Jimenez 	},
586*de0e0e4dSAntonio Huete Jimenez 	{
587*de0e0e4dSAntonio Huete Jimenez 		.name = "to",
588*de0e0e4dSAntonio Huete Jimenez 		.argname = "addr",
589*de0e0e4dSAntonio Huete Jimenez 		.desc = "To address",
590*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARG,
591*de0e0e4dSAntonio Huete Jimenez 		.opt.arg = &smime_config.to,
592*de0e0e4dSAntonio Huete Jimenez 	},
593*de0e0e4dSAntonio Huete Jimenez 	{
594*de0e0e4dSAntonio Huete Jimenez 		.name = "verify",
595*de0e0e4dSAntonio Huete Jimenez 		.desc = "Verify signed message",
596*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_VALUE,
597*de0e0e4dSAntonio Huete Jimenez 		.opt.value = &smime_config.operation,
598*de0e0e4dSAntonio Huete Jimenez 		.value = SMIME_VERIFY,
599*de0e0e4dSAntonio Huete Jimenez 	},
600*de0e0e4dSAntonio Huete Jimenez 	{
601*de0e0e4dSAntonio Huete Jimenez 		.name = "check_ss_sig",
602*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARGV_FUNC,
603*de0e0e4dSAntonio Huete Jimenez 		.opt.argvfunc = smime_opt_verify_param,
604*de0e0e4dSAntonio Huete Jimenez 	},
605*de0e0e4dSAntonio Huete Jimenez 	{
606*de0e0e4dSAntonio Huete Jimenez 		.name = "crl_check",
607*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARGV_FUNC,
608*de0e0e4dSAntonio Huete Jimenez 		.opt.argvfunc = smime_opt_verify_param,
609*de0e0e4dSAntonio Huete Jimenez 	},
610*de0e0e4dSAntonio Huete Jimenez 	{
611*de0e0e4dSAntonio Huete Jimenez 		.name = "crl_check_all",
612*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARGV_FUNC,
613*de0e0e4dSAntonio Huete Jimenez 		.opt.argvfunc = smime_opt_verify_param,
614*de0e0e4dSAntonio Huete Jimenez 	},
615*de0e0e4dSAntonio Huete Jimenez 	{
616*de0e0e4dSAntonio Huete Jimenez 		.name = "extended_crl",
617*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARGV_FUNC,
618*de0e0e4dSAntonio Huete Jimenez 		.opt.argvfunc = smime_opt_verify_param,
619*de0e0e4dSAntonio Huete Jimenez 	},
620*de0e0e4dSAntonio Huete Jimenez 	{
621*de0e0e4dSAntonio Huete Jimenez 		.name = "ignore_critical",
622*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARGV_FUNC,
623*de0e0e4dSAntonio Huete Jimenez 		.opt.argvfunc = smime_opt_verify_param,
624*de0e0e4dSAntonio Huete Jimenez 	},
625*de0e0e4dSAntonio Huete Jimenez 	{
626*de0e0e4dSAntonio Huete Jimenez 		.name = "issuer_checks",
627*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARGV_FUNC,
628*de0e0e4dSAntonio Huete Jimenez 		.opt.argvfunc = smime_opt_verify_param,
629*de0e0e4dSAntonio Huete Jimenez 	},
630*de0e0e4dSAntonio Huete Jimenez 	{
631*de0e0e4dSAntonio Huete Jimenez 		.name = "policy_check",
632*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARGV_FUNC,
633*de0e0e4dSAntonio Huete Jimenez 		.opt.argvfunc = smime_opt_verify_param,
634*de0e0e4dSAntonio Huete Jimenez 	},
635*de0e0e4dSAntonio Huete Jimenez 	{
636*de0e0e4dSAntonio Huete Jimenez 		.name = "x509_strict",
637*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARGV_FUNC,
638*de0e0e4dSAntonio Huete Jimenez 		.opt.argvfunc = smime_opt_verify_param,
639*de0e0e4dSAntonio Huete Jimenez 	},
640*de0e0e4dSAntonio Huete Jimenez 	{
641*de0e0e4dSAntonio Huete Jimenez 		.name = NULL,
642*de0e0e4dSAntonio Huete Jimenez 		.type = OPTION_ARGV_FUNC,
643*de0e0e4dSAntonio Huete Jimenez 		.opt.argvfunc = smime_opt_cipher,
644*de0e0e4dSAntonio Huete Jimenez 	},
645*de0e0e4dSAntonio Huete Jimenez 	{ NULL },
646*de0e0e4dSAntonio Huete Jimenez };
647*de0e0e4dSAntonio Huete Jimenez 
648*de0e0e4dSAntonio Huete Jimenez static const struct option verify_shared_options[] = {
649*de0e0e4dSAntonio Huete Jimenez 	{
650*de0e0e4dSAntonio Huete Jimenez 		.name = "check_ss_sig",
651*de0e0e4dSAntonio Huete Jimenez 		.desc = "Check the root CA self-signed certificate signature",
652*de0e0e4dSAntonio Huete Jimenez 	},
653*de0e0e4dSAntonio Huete Jimenez 	{
654*de0e0e4dSAntonio Huete Jimenez 		.name = "crl_check",
655*de0e0e4dSAntonio Huete Jimenez 		.desc = "Enable CRL checking for the leaf certificate",
656*de0e0e4dSAntonio Huete Jimenez 	},
657*de0e0e4dSAntonio Huete Jimenez 	{
658*de0e0e4dSAntonio Huete Jimenez 		.name = "crl_check_all",
659*de0e0e4dSAntonio Huete Jimenez 		.desc = "Enable CRL checking for the entire certificate chain",
660*de0e0e4dSAntonio Huete Jimenez 	},
661*de0e0e4dSAntonio Huete Jimenez 	{
662*de0e0e4dSAntonio Huete Jimenez 		.name = "extended_crl",
663*de0e0e4dSAntonio Huete Jimenez 		.desc = "Enable extended CRL support",
664*de0e0e4dSAntonio Huete Jimenez 	},
665*de0e0e4dSAntonio Huete Jimenez 	{
666*de0e0e4dSAntonio Huete Jimenez 		.name = "ignore_critical",
667*de0e0e4dSAntonio Huete Jimenez 		.desc = "Disable critical extension checking",
668*de0e0e4dSAntonio Huete Jimenez 	},
669*de0e0e4dSAntonio Huete Jimenez 	{
670*de0e0e4dSAntonio Huete Jimenez 		.name = "issuer_checks",
671*de0e0e4dSAntonio Huete Jimenez 		.desc = "Enable debugging of certificate issuer checks",
672*de0e0e4dSAntonio Huete Jimenez 	},
673*de0e0e4dSAntonio Huete Jimenez 	{
674*de0e0e4dSAntonio Huete Jimenez 		.name = "policy_check",
675*de0e0e4dSAntonio Huete Jimenez 		.desc = "Enable certificate policy checking",
676*de0e0e4dSAntonio Huete Jimenez 	},
677*de0e0e4dSAntonio Huete Jimenez 	{
678*de0e0e4dSAntonio Huete Jimenez 		.name = "x509_strict",
679*de0e0e4dSAntonio Huete Jimenez 		.desc = "Use strict X.509 rules (disables workarounds)",
680*de0e0e4dSAntonio Huete Jimenez 	},
681*de0e0e4dSAntonio Huete Jimenez 	{ NULL },
682*de0e0e4dSAntonio Huete Jimenez };
683*de0e0e4dSAntonio Huete Jimenez 
684*de0e0e4dSAntonio Huete Jimenez static void
smime_usage(void)685*de0e0e4dSAntonio Huete Jimenez smime_usage(void)
686*de0e0e4dSAntonio Huete Jimenez {
687*de0e0e4dSAntonio Huete Jimenez 	fprintf(stderr, "usage: smime "
688*de0e0e4dSAntonio Huete Jimenez 	    "[-aes128 | -aes192 | -aes256 | -des |\n"
689*de0e0e4dSAntonio Huete Jimenez 	    "    -des3 | -rc2-40 | -rc2-64 | -rc2-128] [-binary]\n"
690*de0e0e4dSAntonio Huete Jimenez 	    "    [-CAfile file] [-CApath directory] [-certfile file]\n"
691*de0e0e4dSAntonio Huete Jimenez 	    "    [-content file]\n"
692*de0e0e4dSAntonio Huete Jimenez 	    "    [-decrypt] [-encrypt]\n"
693*de0e0e4dSAntonio Huete Jimenez 	    "    [-from addr] [-in file] [-indef]\n"
694*de0e0e4dSAntonio Huete Jimenez 	    "    [-inform der | pem | smime] [-inkey file]\n"
695*de0e0e4dSAntonio Huete Jimenez 	    "    [-keyform der | pem] [-md digest] [-noattr] [-nocerts]\n"
696*de0e0e4dSAntonio Huete Jimenez 	    "    [-nochain] [-nodetach] [-noindef] [-nointern] [-nosigs]\n"
697*de0e0e4dSAntonio Huete Jimenez 	    "    [-nosmimecap] [-noverify] [-out file]\n"
698*de0e0e4dSAntonio Huete Jimenez 	    "    [-outform der | pem | smime] [-passin arg] [-pk7out]\n"
699*de0e0e4dSAntonio Huete Jimenez 	    "    [-recip file] [-resign] [-sign]\n"
700*de0e0e4dSAntonio Huete Jimenez 	    "    [-signer file] [-stream] [-subject s] [-text] [-to addr]\n"
701*de0e0e4dSAntonio Huete Jimenez 	    "    [-verify] [cert.pem ...]\n\n");
702*de0e0e4dSAntonio Huete Jimenez 
703*de0e0e4dSAntonio Huete Jimenez 	options_usage(smime_options);
704*de0e0e4dSAntonio Huete Jimenez 
705*de0e0e4dSAntonio Huete Jimenez 	fprintf(stderr, "\nVerification options:\n\n");
706*de0e0e4dSAntonio Huete Jimenez 	options_usage(verify_shared_options);
707*de0e0e4dSAntonio Huete Jimenez }
708*de0e0e4dSAntonio Huete Jimenez 
709f5b1c8a1SJohn Marino int
smime_main(int argc,char ** argv)710f5b1c8a1SJohn Marino smime_main(int argc, char **argv)
711f5b1c8a1SJohn Marino {
712f5b1c8a1SJohn Marino 	int ret = 0;
713f5b1c8a1SJohn Marino 	char **args;
714*de0e0e4dSAntonio Huete Jimenez 	int argsused = 0;
715f5b1c8a1SJohn Marino 	const char *inmode = "r", *outmode = "w";
716f5b1c8a1SJohn Marino 	PKCS7 *p7 = NULL;
717f5b1c8a1SJohn Marino 	X509_STORE *store = NULL;
718f5b1c8a1SJohn Marino 	X509 *cert = NULL, *recip = NULL, *signer = NULL;
719f5b1c8a1SJohn Marino 	EVP_PKEY *key = NULL;
720f5b1c8a1SJohn Marino 	STACK_OF(X509) *encerts = NULL, *other = NULL;
721f5b1c8a1SJohn Marino 	BIO *in = NULL, *out = NULL, *indata = NULL;
722f5b1c8a1SJohn Marino 	int badarg = 0;
723*de0e0e4dSAntonio Huete Jimenez 	char *passin = NULL;
724f5b1c8a1SJohn Marino 
725f5b1c8a1SJohn Marino 	if (single_execution) {
72672c33676SMaxim Ag 		if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
727f5b1c8a1SJohn Marino 			perror("pledge");
728f5b1c8a1SJohn Marino 			exit(1);
729f5b1c8a1SJohn Marino 		}
730f5b1c8a1SJohn Marino 	}
731f5b1c8a1SJohn Marino 
732*de0e0e4dSAntonio Huete Jimenez 	memset(&smime_config, 0, sizeof(smime_config));
733*de0e0e4dSAntonio Huete Jimenez 	smime_config.flags = PKCS7_DETACHED;
734*de0e0e4dSAntonio Huete Jimenez 	smime_config.informat = FORMAT_SMIME;
735*de0e0e4dSAntonio Huete Jimenez 	smime_config.outformat = FORMAT_SMIME;
736*de0e0e4dSAntonio Huete Jimenez 	smime_config.keyform = FORMAT_PEM;
737*de0e0e4dSAntonio Huete Jimenez 	if (options_parse(argc, argv, smime_options, NULL, &argsused) != 0) {
738*de0e0e4dSAntonio Huete Jimenez 		goto argerr;
739*de0e0e4dSAntonio Huete Jimenez 	}
740*de0e0e4dSAntonio Huete Jimenez 	args = argv + argsused;
741f5b1c8a1SJohn Marino 	ret = 1;
742f5b1c8a1SJohn Marino 
743*de0e0e4dSAntonio Huete Jimenez 	if (!(smime_config.operation & SMIME_SIGNERS) &&
744*de0e0e4dSAntonio Huete Jimenez 	    (smime_config.skkeys != NULL || smime_config.sksigners != NULL)) {
745f5b1c8a1SJohn Marino 		BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
746f5b1c8a1SJohn Marino 		goto argerr;
747f5b1c8a1SJohn Marino 	}
748*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.operation & SMIME_SIGNERS) {
749f5b1c8a1SJohn Marino 		/* Check to see if any final signer needs to be appended */
750*de0e0e4dSAntonio Huete Jimenez 		if (smime_config.keyfile != NULL &&
751*de0e0e4dSAntonio Huete Jimenez 		    smime_config.signerfile == NULL) {
752f5b1c8a1SJohn Marino 			BIO_puts(bio_err, "Illegal -inkey without -signer\n");
753f5b1c8a1SJohn Marino 			goto argerr;
754f5b1c8a1SJohn Marino 		}
755*de0e0e4dSAntonio Huete Jimenez 		if (smime_config.signerfile != NULL) {
756*de0e0e4dSAntonio Huete Jimenez 			if (smime_config.sksigners == NULL) {
757*de0e0e4dSAntonio Huete Jimenez 				if ((smime_config.sksigners =
758*de0e0e4dSAntonio Huete Jimenez 				    sk_OPENSSL_STRING_new_null()) == NULL)
759*de0e0e4dSAntonio Huete Jimenez 					goto end;
760f5b1c8a1SJohn Marino 			}
761*de0e0e4dSAntonio Huete Jimenez 			if (!sk_OPENSSL_STRING_push(smime_config.sksigners,
762*de0e0e4dSAntonio Huete Jimenez 			    smime_config.signerfile))
763*de0e0e4dSAntonio Huete Jimenez 				goto end;
764*de0e0e4dSAntonio Huete Jimenez 			if (smime_config.skkeys == NULL) {
765*de0e0e4dSAntonio Huete Jimenez 				if ((smime_config.skkeys =
766*de0e0e4dSAntonio Huete Jimenez 				    sk_OPENSSL_STRING_new_null()) == NULL)
767*de0e0e4dSAntonio Huete Jimenez 					goto end;
768*de0e0e4dSAntonio Huete Jimenez 			}
769*de0e0e4dSAntonio Huete Jimenez 			if (smime_config.keyfile == NULL)
770*de0e0e4dSAntonio Huete Jimenez 				smime_config.keyfile = smime_config.signerfile;
771*de0e0e4dSAntonio Huete Jimenez 			if (!sk_OPENSSL_STRING_push(smime_config.skkeys,
772*de0e0e4dSAntonio Huete Jimenez 			    smime_config.keyfile))
773*de0e0e4dSAntonio Huete Jimenez 				goto end;
774*de0e0e4dSAntonio Huete Jimenez 		}
775*de0e0e4dSAntonio Huete Jimenez 		if (smime_config.sksigners == NULL) {
776*de0e0e4dSAntonio Huete Jimenez 			BIO_printf(bio_err,
777*de0e0e4dSAntonio Huete Jimenez 			    "No signer certificate specified\n");
778f5b1c8a1SJohn Marino 			badarg = 1;
779f5b1c8a1SJohn Marino 		}
780*de0e0e4dSAntonio Huete Jimenez 		smime_config.signerfile = NULL;
781*de0e0e4dSAntonio Huete Jimenez 		smime_config.keyfile = NULL;
782*de0e0e4dSAntonio Huete Jimenez 	} else if (smime_config.operation == SMIME_DECRYPT) {
783*de0e0e4dSAntonio Huete Jimenez 		if (smime_config.recipfile == NULL &&
784*de0e0e4dSAntonio Huete Jimenez 		    smime_config.keyfile == NULL) {
785*de0e0e4dSAntonio Huete Jimenez 			BIO_printf(bio_err,
786*de0e0e4dSAntonio Huete Jimenez 			    "No recipient certificate or key specified\n");
787f5b1c8a1SJohn Marino 			badarg = 1;
788f5b1c8a1SJohn Marino 		}
789*de0e0e4dSAntonio Huete Jimenez 	} else if (smime_config.operation == SMIME_ENCRYPT) {
790*de0e0e4dSAntonio Huete Jimenez 		if (*args == NULL) {
791*de0e0e4dSAntonio Huete Jimenez 			BIO_printf(bio_err,
792*de0e0e4dSAntonio Huete Jimenez 			    "No recipient(s) certificate(s) specified\n");
793f5b1c8a1SJohn Marino 			badarg = 1;
794f5b1c8a1SJohn Marino 		}
795*de0e0e4dSAntonio Huete Jimenez 	} else if (!smime_config.operation) {
796f5b1c8a1SJohn Marino 		badarg = 1;
797*de0e0e4dSAntonio Huete Jimenez 	}
798f5b1c8a1SJohn Marino 
799f5b1c8a1SJohn Marino 	if (badarg) {
800f5b1c8a1SJohn Marino  argerr:
801*de0e0e4dSAntonio Huete Jimenez 		smime_usage();
802f5b1c8a1SJohn Marino 		goto end;
803f5b1c8a1SJohn Marino 	}
804f5b1c8a1SJohn Marino 
805*de0e0e4dSAntonio Huete Jimenez 	if (!app_passwd(bio_err, smime_config.passargin, NULL, &passin, NULL)) {
806f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "Error getting password\n");
807f5b1c8a1SJohn Marino 		goto end;
808f5b1c8a1SJohn Marino 	}
809f5b1c8a1SJohn Marino 	ret = 2;
810f5b1c8a1SJohn Marino 
811*de0e0e4dSAntonio Huete Jimenez 	if (!(smime_config.operation & SMIME_SIGNERS))
812*de0e0e4dSAntonio Huete Jimenez 		smime_config.flags &= ~PKCS7_DETACHED;
813f5b1c8a1SJohn Marino 
814*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.operation & SMIME_OP) {
815*de0e0e4dSAntonio Huete Jimenez 		if (smime_config.outformat == FORMAT_ASN1)
816f5b1c8a1SJohn Marino 			outmode = "wb";
817f5b1c8a1SJohn Marino 	} else {
818*de0e0e4dSAntonio Huete Jimenez 		if (smime_config.flags & PKCS7_BINARY)
819f5b1c8a1SJohn Marino 			outmode = "wb";
820f5b1c8a1SJohn Marino 	}
821f5b1c8a1SJohn Marino 
822*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.operation & SMIME_IP) {
823*de0e0e4dSAntonio Huete Jimenez 		if (smime_config.informat == FORMAT_ASN1)
824f5b1c8a1SJohn Marino 			inmode = "rb";
825f5b1c8a1SJohn Marino 	} else {
826*de0e0e4dSAntonio Huete Jimenez 		if (smime_config.flags & PKCS7_BINARY)
827f5b1c8a1SJohn Marino 			inmode = "rb";
828f5b1c8a1SJohn Marino 	}
829f5b1c8a1SJohn Marino 
830*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.operation == SMIME_ENCRYPT) {
831*de0e0e4dSAntonio Huete Jimenez 		if (smime_config.cipher == NULL) {
832f5b1c8a1SJohn Marino #ifndef OPENSSL_NO_RC2
833*de0e0e4dSAntonio Huete Jimenez 			smime_config.cipher = EVP_rc2_40_cbc();
834f5b1c8a1SJohn Marino #else
835f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "No cipher selected\n");
836f5b1c8a1SJohn Marino 			goto end;
837f5b1c8a1SJohn Marino #endif
838f5b1c8a1SJohn Marino 		}
839*de0e0e4dSAntonio Huete Jimenez 		if ((encerts = sk_X509_new_null()) == NULL)
840*de0e0e4dSAntonio Huete Jimenez 			goto end;
841*de0e0e4dSAntonio Huete Jimenez 		while (*args != NULL) {
842*de0e0e4dSAntonio Huete Jimenez 			if ((cert = load_cert(bio_err, *args, FORMAT_PEM,
843*de0e0e4dSAntonio Huete Jimenez 			    NULL, "recipient certificate file")) == NULL) {
844f5b1c8a1SJohn Marino 				goto end;
845f5b1c8a1SJohn Marino 			}
846*de0e0e4dSAntonio Huete Jimenez 			if (!sk_X509_push(encerts, cert))
847*de0e0e4dSAntonio Huete Jimenez 				goto end;
848f5b1c8a1SJohn Marino 			cert = NULL;
849f5b1c8a1SJohn Marino 			args++;
850f5b1c8a1SJohn Marino 		}
851f5b1c8a1SJohn Marino 	}
852*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.certfile != NULL) {
853*de0e0e4dSAntonio Huete Jimenez 		if ((other = load_certs(bio_err, smime_config.certfile,
854*de0e0e4dSAntonio Huete Jimenez 		    FORMAT_PEM, NULL, "certificate file")) == NULL) {
855f5b1c8a1SJohn Marino 			ERR_print_errors(bio_err);
856f5b1c8a1SJohn Marino 			goto end;
857f5b1c8a1SJohn Marino 		}
858f5b1c8a1SJohn Marino 	}
859*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.recipfile != NULL &&
860*de0e0e4dSAntonio Huete Jimenez 	    (smime_config.operation == SMIME_DECRYPT)) {
861*de0e0e4dSAntonio Huete Jimenez 		if ((recip = load_cert(bio_err, smime_config.recipfile,
862*de0e0e4dSAntonio Huete Jimenez 		    FORMAT_PEM, NULL, "recipient certificate file")) == NULL) {
863f5b1c8a1SJohn Marino 			ERR_print_errors(bio_err);
864f5b1c8a1SJohn Marino 			goto end;
865f5b1c8a1SJohn Marino 		}
866f5b1c8a1SJohn Marino 	}
867*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.operation == SMIME_DECRYPT) {
868*de0e0e4dSAntonio Huete Jimenez 		if (smime_config.keyfile == NULL)
869*de0e0e4dSAntonio Huete Jimenez 			smime_config.keyfile = smime_config.recipfile;
870*de0e0e4dSAntonio Huete Jimenez 	} else if (smime_config.operation == SMIME_SIGN) {
871*de0e0e4dSAntonio Huete Jimenez 		if (smime_config.keyfile == NULL)
872*de0e0e4dSAntonio Huete Jimenez 			smime_config.keyfile = smime_config.signerfile;
873*de0e0e4dSAntonio Huete Jimenez 	} else {
874*de0e0e4dSAntonio Huete Jimenez 		smime_config.keyfile = NULL;
875*de0e0e4dSAntonio Huete Jimenez 	}
876f5b1c8a1SJohn Marino 
877*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.keyfile != NULL) {
878*de0e0e4dSAntonio Huete Jimenez 		key = load_key(bio_err, smime_config.keyfile,
879*de0e0e4dSAntonio Huete Jimenez 		    smime_config.keyform, 0, passin, "signing key file");
880*de0e0e4dSAntonio Huete Jimenez 		if (key == NULL)
881f5b1c8a1SJohn Marino 			goto end;
882f5b1c8a1SJohn Marino 	}
883*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.infile != NULL) {
884*de0e0e4dSAntonio Huete Jimenez 		if ((in = BIO_new_file(smime_config.infile, inmode)) == NULL) {
885f5b1c8a1SJohn Marino 			BIO_printf(bio_err,
886*de0e0e4dSAntonio Huete Jimenez 			    "Can't open input file %s\n", smime_config.infile);
887f5b1c8a1SJohn Marino 			goto end;
888f5b1c8a1SJohn Marino 		}
889f5b1c8a1SJohn Marino 	} else {
890*de0e0e4dSAntonio Huete Jimenez 		if ((in = BIO_new_fp(stdin, BIO_NOCLOSE)) == NULL)
891*de0e0e4dSAntonio Huete Jimenez 			goto end;
892f5b1c8a1SJohn Marino 	}
893f5b1c8a1SJohn Marino 
894*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.operation & SMIME_IP) {
895*de0e0e4dSAntonio Huete Jimenez 		if (smime_config.informat == FORMAT_SMIME)
896*de0e0e4dSAntonio Huete Jimenez 			p7 = SMIME_read_PKCS7(in, &indata);
897*de0e0e4dSAntonio Huete Jimenez 		else if (smime_config.informat == FORMAT_PEM)
898*de0e0e4dSAntonio Huete Jimenez 			p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
899*de0e0e4dSAntonio Huete Jimenez 		else if (smime_config.informat == FORMAT_ASN1)
900*de0e0e4dSAntonio Huete Jimenez 			p7 = d2i_PKCS7_bio(in, NULL);
901*de0e0e4dSAntonio Huete Jimenez 		else {
902*de0e0e4dSAntonio Huete Jimenez 			BIO_printf(bio_err,
903*de0e0e4dSAntonio Huete Jimenez 			    "Bad input format for PKCS#7 file\n");
904*de0e0e4dSAntonio Huete Jimenez 			goto end;
905*de0e0e4dSAntonio Huete Jimenez 		}
906*de0e0e4dSAntonio Huete Jimenez 
907*de0e0e4dSAntonio Huete Jimenez 		if (p7 == NULL) {
908*de0e0e4dSAntonio Huete Jimenez 			BIO_printf(bio_err, "Error reading S/MIME message\n");
909*de0e0e4dSAntonio Huete Jimenez 			goto end;
910*de0e0e4dSAntonio Huete Jimenez 		}
911*de0e0e4dSAntonio Huete Jimenez 		if (smime_config.contfile != NULL) {
912*de0e0e4dSAntonio Huete Jimenez 			BIO_free(indata);
913*de0e0e4dSAntonio Huete Jimenez 			if ((indata = BIO_new_file(smime_config.contfile,
914*de0e0e4dSAntonio Huete Jimenez 			    "rb")) == NULL) {
915*de0e0e4dSAntonio Huete Jimenez 				BIO_printf(bio_err,
916*de0e0e4dSAntonio Huete Jimenez 				    "Can't read content file %s\n",
917*de0e0e4dSAntonio Huete Jimenez 				    smime_config.contfile);
918*de0e0e4dSAntonio Huete Jimenez 				goto end;
919*de0e0e4dSAntonio Huete Jimenez 			}
920*de0e0e4dSAntonio Huete Jimenez 		}
921*de0e0e4dSAntonio Huete Jimenez 	}
922*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.outfile != NULL) {
923*de0e0e4dSAntonio Huete Jimenez 		if ((out = BIO_new_file(smime_config.outfile, outmode)) == NULL) {
924*de0e0e4dSAntonio Huete Jimenez 			BIO_printf(bio_err,
925*de0e0e4dSAntonio Huete Jimenez 			    "Can't open output file %s\n",
926*de0e0e4dSAntonio Huete Jimenez 			    smime_config.outfile);
927*de0e0e4dSAntonio Huete Jimenez 			goto end;
928*de0e0e4dSAntonio Huete Jimenez 		}
929*de0e0e4dSAntonio Huete Jimenez 	} else {
930*de0e0e4dSAntonio Huete Jimenez 		if ((out = BIO_new_fp(stdout, BIO_NOCLOSE)) == NULL)
931*de0e0e4dSAntonio Huete Jimenez 			goto end;
932*de0e0e4dSAntonio Huete Jimenez 	}
933*de0e0e4dSAntonio Huete Jimenez 
934*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.operation == SMIME_VERIFY) {
935*de0e0e4dSAntonio Huete Jimenez 		if ((store = setup_verify(bio_err, smime_config.CAfile,
936*de0e0e4dSAntonio Huete Jimenez 		    smime_config.CApath)) == NULL)
937f5b1c8a1SJohn Marino 			goto end;
938f5b1c8a1SJohn Marino 		X509_STORE_set_verify_cb(store, smime_cb);
939*de0e0e4dSAntonio Huete Jimenez 		if (smime_config.vpm != NULL) {
940*de0e0e4dSAntonio Huete Jimenez 			if (!X509_STORE_set1_param(store, smime_config.vpm))
941*de0e0e4dSAntonio Huete Jimenez 				goto end;
942*de0e0e4dSAntonio Huete Jimenez 		}
943f5b1c8a1SJohn Marino 	}
944f5b1c8a1SJohn Marino 	ret = 3;
945f5b1c8a1SJohn Marino 
946*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.operation == SMIME_ENCRYPT) {
947*de0e0e4dSAntonio Huete Jimenez 		if (smime_config.indef)
948*de0e0e4dSAntonio Huete Jimenez 			smime_config.flags |= PKCS7_STREAM;
949*de0e0e4dSAntonio Huete Jimenez 		p7 = PKCS7_encrypt(encerts, in, smime_config.cipher,
950*de0e0e4dSAntonio Huete Jimenez 		    smime_config.flags);
951*de0e0e4dSAntonio Huete Jimenez 	} else if (smime_config.operation & SMIME_SIGNERS) {
952f5b1c8a1SJohn Marino 		int i;
953f5b1c8a1SJohn Marino 		/*
954f5b1c8a1SJohn Marino 		 * If detached data content we only enable streaming if
955f5b1c8a1SJohn Marino 		 * S/MIME output format.
956f5b1c8a1SJohn Marino 		 */
957*de0e0e4dSAntonio Huete Jimenez 		if (smime_config.operation == SMIME_SIGN) {
958*de0e0e4dSAntonio Huete Jimenez 			if (smime_config.flags & PKCS7_DETACHED) {
959*de0e0e4dSAntonio Huete Jimenez 				if (smime_config.outformat == FORMAT_SMIME)
960*de0e0e4dSAntonio Huete Jimenez 					smime_config.flags |= PKCS7_STREAM;
961*de0e0e4dSAntonio Huete Jimenez 			} else if (smime_config.indef) {
962*de0e0e4dSAntonio Huete Jimenez 				smime_config.flags |= PKCS7_STREAM;
963*de0e0e4dSAntonio Huete Jimenez 			}
964*de0e0e4dSAntonio Huete Jimenez 			smime_config.flags |= PKCS7_PARTIAL;
965*de0e0e4dSAntonio Huete Jimenez 			p7 = PKCS7_sign(NULL, NULL, other, in,
966*de0e0e4dSAntonio Huete Jimenez 			    smime_config.flags);
967*de0e0e4dSAntonio Huete Jimenez 			if (p7 == NULL)
968f5b1c8a1SJohn Marino 				goto end;
969*de0e0e4dSAntonio Huete Jimenez 		} else {
970*de0e0e4dSAntonio Huete Jimenez 			smime_config.flags |= PKCS7_REUSE_DIGEST;
971*de0e0e4dSAntonio Huete Jimenez 		}
972*de0e0e4dSAntonio Huete Jimenez 		for (i = 0; i < sk_OPENSSL_STRING_num(smime_config.sksigners); i++) {
973*de0e0e4dSAntonio Huete Jimenez 			smime_config.signerfile =
974*de0e0e4dSAntonio Huete Jimenez 			    sk_OPENSSL_STRING_value(smime_config.sksigners, i);
975*de0e0e4dSAntonio Huete Jimenez 			smime_config.keyfile =
976*de0e0e4dSAntonio Huete Jimenez 			    sk_OPENSSL_STRING_value(smime_config.skkeys, i);
977*de0e0e4dSAntonio Huete Jimenez 			signer = load_cert(bio_err, smime_config.signerfile,
978*de0e0e4dSAntonio Huete Jimenez 			    FORMAT_PEM, NULL, "signer certificate");
979*de0e0e4dSAntonio Huete Jimenez 			if (signer == NULL)
980f5b1c8a1SJohn Marino 				goto end;
981*de0e0e4dSAntonio Huete Jimenez 			key = load_key(bio_err, smime_config.keyfile,
982*de0e0e4dSAntonio Huete Jimenez 			    smime_config.keyform, 0, passin,
983f5b1c8a1SJohn Marino 			    "signing key file");
984*de0e0e4dSAntonio Huete Jimenez 			if (key == NULL)
985f5b1c8a1SJohn Marino 				goto end;
986*de0e0e4dSAntonio Huete Jimenez 			if (PKCS7_sign_add_signer(p7, signer, key,
987*de0e0e4dSAntonio Huete Jimenez 			    smime_config.sign_md, smime_config.flags) == NULL)
988f5b1c8a1SJohn Marino 				goto end;
989f5b1c8a1SJohn Marino 			X509_free(signer);
990f5b1c8a1SJohn Marino 			signer = NULL;
991f5b1c8a1SJohn Marino 			EVP_PKEY_free(key);
992f5b1c8a1SJohn Marino 			key = NULL;
993f5b1c8a1SJohn Marino 		}
994f5b1c8a1SJohn Marino 		/* If not streaming or resigning finalize structure */
995*de0e0e4dSAntonio Huete Jimenez 		if ((smime_config.operation == SMIME_SIGN) &&
996*de0e0e4dSAntonio Huete Jimenez 		    !(smime_config.flags & PKCS7_STREAM)) {
997*de0e0e4dSAntonio Huete Jimenez 			if (!PKCS7_final(p7, in, smime_config.flags))
998f5b1c8a1SJohn Marino 				goto end;
999f5b1c8a1SJohn Marino 		}
1000f5b1c8a1SJohn Marino 	}
1001*de0e0e4dSAntonio Huete Jimenez 	if (p7 == NULL) {
1002f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "Error creating PKCS#7 structure\n");
1003f5b1c8a1SJohn Marino 		goto end;
1004f5b1c8a1SJohn Marino 	}
1005f5b1c8a1SJohn Marino 	ret = 4;
1006*de0e0e4dSAntonio Huete Jimenez 
1007*de0e0e4dSAntonio Huete Jimenez 	if (smime_config.operation == SMIME_DECRYPT) {
1008*de0e0e4dSAntonio Huete Jimenez 		if (!PKCS7_decrypt(p7, key, recip, out, smime_config.flags)) {
1009*de0e0e4dSAntonio Huete Jimenez 			BIO_printf(bio_err,
1010*de0e0e4dSAntonio Huete Jimenez 			    "Error decrypting PKCS#7 structure\n");
1011f5b1c8a1SJohn Marino 			goto end;
1012f5b1c8a1SJohn Marino 		}
1013*de0e0e4dSAntonio Huete Jimenez 	} else if (smime_config.operation == SMIME_VERIFY) {
1014f5b1c8a1SJohn Marino 		STACK_OF(X509) *signers;
1015*de0e0e4dSAntonio Huete Jimenez 		if (PKCS7_verify(p7, other, store, indata, out,
1016*de0e0e4dSAntonio Huete Jimenez 		    smime_config.flags)) {
1017f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "Verification successful\n");
1018*de0e0e4dSAntonio Huete Jimenez 		} else {
1019f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "Verification failure\n");
1020f5b1c8a1SJohn Marino 			goto end;
1021f5b1c8a1SJohn Marino 		}
1022*de0e0e4dSAntonio Huete Jimenez 		if ((signers = PKCS7_get0_signers(p7, other,
1023*de0e0e4dSAntonio Huete Jimenez 		    smime_config.flags)) == NULL)
1024*de0e0e4dSAntonio Huete Jimenez 			goto end;
1025*de0e0e4dSAntonio Huete Jimenez 		if (!save_certs(smime_config.signerfile, signers)) {
1026f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "Error writing signers to %s\n",
1027*de0e0e4dSAntonio Huete Jimenez 			    smime_config.signerfile);
1028*de0e0e4dSAntonio Huete Jimenez 			sk_X509_free(signers);
1029f5b1c8a1SJohn Marino 			ret = 5;
1030f5b1c8a1SJohn Marino 			goto end;
1031f5b1c8a1SJohn Marino 		}
1032f5b1c8a1SJohn Marino 		sk_X509_free(signers);
1033*de0e0e4dSAntonio Huete Jimenez 	} else if (smime_config.operation == SMIME_PK7OUT) {
1034f5b1c8a1SJohn Marino 		PEM_write_bio_PKCS7(out, p7);
1035*de0e0e4dSAntonio Huete Jimenez 	} else {
1036*de0e0e4dSAntonio Huete Jimenez 		if (smime_config.to != NULL)
1037*de0e0e4dSAntonio Huete Jimenez 			BIO_printf(out, "To: %s\n", smime_config.to);
1038*de0e0e4dSAntonio Huete Jimenez 		if (smime_config.from != NULL)
1039*de0e0e4dSAntonio Huete Jimenez 			BIO_printf(out, "From: %s\n", smime_config.from);
1040*de0e0e4dSAntonio Huete Jimenez 		if (smime_config.subject != NULL)
1041*de0e0e4dSAntonio Huete Jimenez 			BIO_printf(out, "Subject: %s\n", smime_config.subject);
1042*de0e0e4dSAntonio Huete Jimenez 		if (smime_config.outformat == FORMAT_SMIME) {
1043*de0e0e4dSAntonio Huete Jimenez 			if (smime_config.operation == SMIME_RESIGN) {
1044*de0e0e4dSAntonio Huete Jimenez 				if (!SMIME_write_PKCS7(out, p7, indata,
1045*de0e0e4dSAntonio Huete Jimenez 				    smime_config.flags))
1046*de0e0e4dSAntonio Huete Jimenez 					goto end;
1047*de0e0e4dSAntonio Huete Jimenez 			} else {
1048*de0e0e4dSAntonio Huete Jimenez 				if (!SMIME_write_PKCS7(out, p7, in,
1049*de0e0e4dSAntonio Huete Jimenez 				    smime_config.flags))
1050*de0e0e4dSAntonio Huete Jimenez 					goto end;
1051*de0e0e4dSAntonio Huete Jimenez 			}
1052*de0e0e4dSAntonio Huete Jimenez 		} else if (smime_config.outformat == FORMAT_PEM) {
1053*de0e0e4dSAntonio Huete Jimenez 			if (!PEM_write_bio_PKCS7_stream(out, p7, in,
1054*de0e0e4dSAntonio Huete Jimenez 			    smime_config.flags))
1055*de0e0e4dSAntonio Huete Jimenez 				goto end;
1056*de0e0e4dSAntonio Huete Jimenez 		} else if (smime_config.outformat == FORMAT_ASN1) {
1057*de0e0e4dSAntonio Huete Jimenez 			if (!i2d_PKCS7_bio_stream(out, p7, in,
1058*de0e0e4dSAntonio Huete Jimenez 			    smime_config.flags))
1059*de0e0e4dSAntonio Huete Jimenez 				goto end;
1060*de0e0e4dSAntonio Huete Jimenez 		} else {
1061*de0e0e4dSAntonio Huete Jimenez 			BIO_printf(bio_err,
1062*de0e0e4dSAntonio Huete Jimenez 			    "Bad output format for PKCS#7 file\n");
1063f5b1c8a1SJohn Marino 			goto end;
1064f5b1c8a1SJohn Marino 		}
1065f5b1c8a1SJohn Marino 	}
1066*de0e0e4dSAntonio Huete Jimenez 
1067f5b1c8a1SJohn Marino 	ret = 0;
1068*de0e0e4dSAntonio Huete Jimenez 
1069f5b1c8a1SJohn Marino  end:
1070f5b1c8a1SJohn Marino 	if (ret)
1071f5b1c8a1SJohn Marino 		ERR_print_errors(bio_err);
1072f5b1c8a1SJohn Marino 	sk_X509_pop_free(encerts, X509_free);
1073f5b1c8a1SJohn Marino 	sk_X509_pop_free(other, X509_free);
1074*de0e0e4dSAntonio Huete Jimenez 	X509_VERIFY_PARAM_free(smime_config.vpm);
1075*de0e0e4dSAntonio Huete Jimenez 	sk_OPENSSL_STRING_free(smime_config.sksigners);
1076*de0e0e4dSAntonio Huete Jimenez 	sk_OPENSSL_STRING_free(smime_config.skkeys);
1077f5b1c8a1SJohn Marino 	X509_STORE_free(store);
1078f5b1c8a1SJohn Marino 	X509_free(cert);
1079f5b1c8a1SJohn Marino 	X509_free(recip);
1080f5b1c8a1SJohn Marino 	X509_free(signer);
1081f5b1c8a1SJohn Marino 	EVP_PKEY_free(key);
1082f5b1c8a1SJohn Marino 	PKCS7_free(p7);
1083f5b1c8a1SJohn Marino 	BIO_free(in);
1084f5b1c8a1SJohn Marino 	BIO_free(indata);
1085f5b1c8a1SJohn Marino 	BIO_free_all(out);
1086f5b1c8a1SJohn Marino 	free(passin);
1087f5b1c8a1SJohn Marino 
1088f5b1c8a1SJohn Marino 	return (ret);
1089f5b1c8a1SJohn Marino }
1090f5b1c8a1SJohn Marino 
1091f5b1c8a1SJohn Marino static int
save_certs(char * signerfile,STACK_OF (X509)* signers)1092f5b1c8a1SJohn Marino save_certs(char *signerfile, STACK_OF(X509) *signers)
1093f5b1c8a1SJohn Marino {
1094f5b1c8a1SJohn Marino 	int i;
1095f5b1c8a1SJohn Marino 	BIO *tmp;
1096*de0e0e4dSAntonio Huete Jimenez 
1097*de0e0e4dSAntonio Huete Jimenez 	if (signerfile == NULL)
1098f5b1c8a1SJohn Marino 		return 1;
1099f5b1c8a1SJohn Marino 	tmp = BIO_new_file(signerfile, "w");
1100*de0e0e4dSAntonio Huete Jimenez 	if (tmp == NULL)
1101f5b1c8a1SJohn Marino 		return 0;
1102f5b1c8a1SJohn Marino 	for (i = 0; i < sk_X509_num(signers); i++)
1103f5b1c8a1SJohn Marino 		PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
1104f5b1c8a1SJohn Marino 	BIO_free(tmp);
1105*de0e0e4dSAntonio Huete Jimenez 
1106f5b1c8a1SJohn Marino 	return 1;
1107f5b1c8a1SJohn Marino }
1108f5b1c8a1SJohn Marino 
1109f5b1c8a1SJohn Marino /* Minimal callback just to output policy info (if any) */
1110f5b1c8a1SJohn Marino static int
smime_cb(int ok,X509_STORE_CTX * ctx)1111f5b1c8a1SJohn Marino smime_cb(int ok, X509_STORE_CTX *ctx)
1112f5b1c8a1SJohn Marino {
1113f5b1c8a1SJohn Marino 	int error;
1114f5b1c8a1SJohn Marino 
1115f5b1c8a1SJohn Marino 	error = X509_STORE_CTX_get_error(ctx);
1116f5b1c8a1SJohn Marino 
1117*de0e0e4dSAntonio Huete Jimenez 	if ((error != X509_V_ERR_NO_EXPLICIT_POLICY) &&
1118*de0e0e4dSAntonio Huete Jimenez 	    ((error != X509_V_OK) || (ok != 2)))
1119f5b1c8a1SJohn Marino 		return ok;
1120f5b1c8a1SJohn Marino 
1121f5b1c8a1SJohn Marino 	policies_print(NULL, ctx);
1122f5b1c8a1SJohn Marino 
1123f5b1c8a1SJohn Marino 	return ok;
1124f5b1c8a1SJohn Marino }
1125