xref: /minix3/crypto/external/bsd/openssl/dist/apps/smime.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1ebfedea0SLionel Sambuc /* smime.c */
2*0a6a1f1dSLionel Sambuc /*
3*0a6a1f1dSLionel Sambuc  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4ebfedea0SLionel Sambuc  * project.
5ebfedea0SLionel Sambuc  */
6ebfedea0SLionel Sambuc /* ====================================================================
7ebfedea0SLionel Sambuc  * Copyright (c) 1999-2004 The OpenSSL Project.  All rights reserved.
8ebfedea0SLionel Sambuc  *
9ebfedea0SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
10ebfedea0SLionel Sambuc  * modification, are permitted provided that the following conditions
11ebfedea0SLionel Sambuc  * are met:
12ebfedea0SLionel Sambuc  *
13ebfedea0SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
14ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
15ebfedea0SLionel Sambuc  *
16ebfedea0SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
17ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in
18ebfedea0SLionel Sambuc  *    the documentation and/or other materials provided with the
19ebfedea0SLionel Sambuc  *    distribution.
20ebfedea0SLionel Sambuc  *
21ebfedea0SLionel Sambuc  * 3. All advertising materials mentioning features or use of this
22ebfedea0SLionel Sambuc  *    software must display the following acknowledgment:
23ebfedea0SLionel Sambuc  *    "This product includes software developed by the OpenSSL Project
24ebfedea0SLionel Sambuc  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25ebfedea0SLionel Sambuc  *
26ebfedea0SLionel Sambuc  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27ebfedea0SLionel Sambuc  *    endorse or promote products derived from this software without
28ebfedea0SLionel Sambuc  *    prior written permission. For written permission, please contact
29ebfedea0SLionel Sambuc  *    licensing@OpenSSL.org.
30ebfedea0SLionel Sambuc  *
31ebfedea0SLionel Sambuc  * 5. Products derived from this software may not be called "OpenSSL"
32ebfedea0SLionel Sambuc  *    nor may "OpenSSL" appear in their names without prior written
33ebfedea0SLionel Sambuc  *    permission of the OpenSSL Project.
34ebfedea0SLionel Sambuc  *
35ebfedea0SLionel Sambuc  * 6. Redistributions of any form whatsoever must retain the following
36ebfedea0SLionel Sambuc  *    acknowledgment:
37ebfedea0SLionel Sambuc  *    "This product includes software developed by the OpenSSL Project
38ebfedea0SLionel Sambuc  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39ebfedea0SLionel Sambuc  *
40ebfedea0SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41ebfedea0SLionel Sambuc  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42ebfedea0SLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43ebfedea0SLionel Sambuc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44ebfedea0SLionel Sambuc  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45ebfedea0SLionel Sambuc  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46ebfedea0SLionel Sambuc  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47ebfedea0SLionel Sambuc  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48ebfedea0SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49ebfedea0SLionel Sambuc  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50ebfedea0SLionel Sambuc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51ebfedea0SLionel Sambuc  * OF THE POSSIBILITY OF SUCH DAMAGE.
52ebfedea0SLionel Sambuc  * ====================================================================
53ebfedea0SLionel Sambuc  *
54ebfedea0SLionel Sambuc  * This product includes cryptographic software written by Eric Young
55ebfedea0SLionel Sambuc  * (eay@cryptsoft.com).  This product includes software written by Tim
56ebfedea0SLionel Sambuc  * Hudson (tjh@cryptsoft.com).
57ebfedea0SLionel Sambuc  *
58ebfedea0SLionel Sambuc  */
59ebfedea0SLionel Sambuc 
60ebfedea0SLionel Sambuc /* S/MIME utility function */
61ebfedea0SLionel Sambuc 
62ebfedea0SLionel Sambuc #include <stdio.h>
63ebfedea0SLionel Sambuc #include <string.h>
64ebfedea0SLionel Sambuc #include "apps.h"
65ebfedea0SLionel Sambuc #include <openssl/crypto.h>
66ebfedea0SLionel Sambuc #include <openssl/pem.h>
67ebfedea0SLionel Sambuc #include <openssl/err.h>
68ebfedea0SLionel Sambuc #include <openssl/x509_vfy.h>
69ebfedea0SLionel Sambuc #include <openssl/x509v3.h>
70ebfedea0SLionel Sambuc 
71ebfedea0SLionel Sambuc #undef PROG
72ebfedea0SLionel Sambuc #define PROG smime_main
73ebfedea0SLionel Sambuc static int save_certs(char *signerfile, STACK_OF(X509) *signers);
74ebfedea0SLionel Sambuc static int smime_cb(int ok, X509_STORE_CTX *ctx);
75ebfedea0SLionel Sambuc 
76ebfedea0SLionel Sambuc #define SMIME_OP        0x10
77ebfedea0SLionel Sambuc #define SMIME_IP        0x20
78ebfedea0SLionel Sambuc #define SMIME_SIGNERS   0x40
79ebfedea0SLionel Sambuc #define SMIME_ENCRYPT   (1 | SMIME_OP)
80ebfedea0SLionel Sambuc #define SMIME_DECRYPT   (2 | SMIME_IP)
81ebfedea0SLionel Sambuc #define SMIME_SIGN      (3 | SMIME_OP | SMIME_SIGNERS)
82ebfedea0SLionel Sambuc #define SMIME_VERIFY    (4 | SMIME_IP)
83ebfedea0SLionel Sambuc #define SMIME_PK7OUT    (5 | SMIME_IP | SMIME_OP)
84ebfedea0SLionel Sambuc #define SMIME_RESIGN    (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
85ebfedea0SLionel Sambuc 
86ebfedea0SLionel Sambuc int MAIN(int, char **);
87ebfedea0SLionel Sambuc 
MAIN(int argc,char ** argv)88ebfedea0SLionel Sambuc int MAIN(int argc, char **argv)
89ebfedea0SLionel Sambuc {
90ebfedea0SLionel Sambuc     ENGINE *e = NULL;
91ebfedea0SLionel Sambuc     int operation = 0;
92ebfedea0SLionel Sambuc     int ret = 0;
93ebfedea0SLionel Sambuc     char **args;
94ebfedea0SLionel Sambuc     const char *inmode = "r", *outmode = "w";
95ebfedea0SLionel Sambuc     char *infile = NULL, *outfile = NULL;
96ebfedea0SLionel Sambuc     char *signerfile = NULL, *recipfile = NULL;
97ebfedea0SLionel Sambuc     STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL;
98ebfedea0SLionel Sambuc     char *certfile = NULL, *keyfile = NULL, *contfile = NULL;
99ebfedea0SLionel Sambuc     const EVP_CIPHER *cipher = NULL;
100ebfedea0SLionel Sambuc     PKCS7 *p7 = NULL;
101ebfedea0SLionel Sambuc     X509_STORE *store = NULL;
102ebfedea0SLionel Sambuc     X509 *cert = NULL, *recip = NULL, *signer = NULL;
103ebfedea0SLionel Sambuc     EVP_PKEY *key = NULL;
104ebfedea0SLionel Sambuc     STACK_OF(X509) *encerts = NULL, *other = NULL;
105ebfedea0SLionel Sambuc     BIO *in = NULL, *out = NULL, *indata = NULL;
106ebfedea0SLionel Sambuc     int badarg = 0;
107ebfedea0SLionel Sambuc     int flags = PKCS7_DETACHED;
108ebfedea0SLionel Sambuc     char *to = NULL, *from = NULL, *subject = NULL;
109ebfedea0SLionel Sambuc     char *CAfile = NULL, *CApath = NULL;
110ebfedea0SLionel Sambuc     char *passargin = NULL, *passin = NULL;
111ebfedea0SLionel Sambuc     char *inrand = NULL;
112ebfedea0SLionel Sambuc     int need_rand = 0;
113ebfedea0SLionel Sambuc     int indef = 0;
114ebfedea0SLionel Sambuc     const EVP_MD *sign_md = NULL;
115ebfedea0SLionel Sambuc     int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
116ebfedea0SLionel Sambuc     int keyform = FORMAT_PEM;
117ebfedea0SLionel Sambuc #ifndef OPENSSL_NO_ENGINE
118ebfedea0SLionel Sambuc     char *engine = NULL;
119ebfedea0SLionel Sambuc #endif
120ebfedea0SLionel Sambuc 
121ebfedea0SLionel Sambuc     X509_VERIFY_PARAM *vpm = NULL;
122ebfedea0SLionel Sambuc 
123ebfedea0SLionel Sambuc     args = argv + 1;
124ebfedea0SLionel Sambuc     ret = 1;
125ebfedea0SLionel Sambuc 
126ebfedea0SLionel Sambuc     apps_startup();
127ebfedea0SLionel Sambuc 
128*0a6a1f1dSLionel Sambuc     if (bio_err == NULL) {
129ebfedea0SLionel Sambuc         if ((bio_err = BIO_new(BIO_s_file())) != NULL)
130ebfedea0SLionel Sambuc             BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
131ebfedea0SLionel Sambuc     }
132ebfedea0SLionel Sambuc 
133ebfedea0SLionel Sambuc     if (!load_config(bio_err, NULL))
134ebfedea0SLionel Sambuc         goto end;
135ebfedea0SLionel Sambuc 
136*0a6a1f1dSLionel Sambuc     while (!badarg && *args && *args[0] == '-') {
137ebfedea0SLionel Sambuc         if (!strcmp(*args, "-encrypt"))
138ebfedea0SLionel Sambuc             operation = SMIME_ENCRYPT;
139ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-decrypt"))
140ebfedea0SLionel Sambuc             operation = SMIME_DECRYPT;
141ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-sign"))
142ebfedea0SLionel Sambuc             operation = SMIME_SIGN;
143ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-resign"))
144ebfedea0SLionel Sambuc             operation = SMIME_RESIGN;
145ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-verify"))
146ebfedea0SLionel Sambuc             operation = SMIME_VERIFY;
147ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-pk7out"))
148ebfedea0SLionel Sambuc             operation = SMIME_PK7OUT;
149ebfedea0SLionel Sambuc #ifndef OPENSSL_NO_DES
150ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-des3"))
151ebfedea0SLionel Sambuc             cipher = EVP_des_ede3_cbc();
152ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-des"))
153ebfedea0SLionel Sambuc             cipher = EVP_des_cbc();
154ebfedea0SLionel Sambuc #endif
155ebfedea0SLionel Sambuc #ifndef OPENSSL_NO_SEED
156ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-seed"))
157ebfedea0SLionel Sambuc             cipher = EVP_seed_cbc();
158ebfedea0SLionel Sambuc #endif
159ebfedea0SLionel Sambuc #ifndef OPENSSL_NO_RC2
160ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-rc2-40"))
161ebfedea0SLionel Sambuc             cipher = EVP_rc2_40_cbc();
162ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-rc2-128"))
163ebfedea0SLionel Sambuc             cipher = EVP_rc2_cbc();
164ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-rc2-64"))
165ebfedea0SLionel Sambuc             cipher = EVP_rc2_64_cbc();
166ebfedea0SLionel Sambuc #endif
167ebfedea0SLionel Sambuc #ifndef OPENSSL_NO_AES
168ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-aes128"))
169ebfedea0SLionel Sambuc             cipher = EVP_aes_128_cbc();
170ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-aes192"))
171ebfedea0SLionel Sambuc             cipher = EVP_aes_192_cbc();
172ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-aes256"))
173ebfedea0SLionel Sambuc             cipher = EVP_aes_256_cbc();
174ebfedea0SLionel Sambuc #endif
175ebfedea0SLionel Sambuc #ifndef OPENSSL_NO_CAMELLIA
176ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-camellia128"))
177ebfedea0SLionel Sambuc             cipher = EVP_camellia_128_cbc();
178ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-camellia192"))
179ebfedea0SLionel Sambuc             cipher = EVP_camellia_192_cbc();
180ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-camellia256"))
181ebfedea0SLionel Sambuc             cipher = EVP_camellia_256_cbc();
182ebfedea0SLionel Sambuc #endif
183ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-text"))
184ebfedea0SLionel Sambuc             flags |= PKCS7_TEXT;
185ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-nointern"))
186ebfedea0SLionel Sambuc             flags |= PKCS7_NOINTERN;
187ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-noverify"))
188ebfedea0SLionel Sambuc             flags |= PKCS7_NOVERIFY;
189ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-nochain"))
190ebfedea0SLionel Sambuc             flags |= PKCS7_NOCHAIN;
191ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-nocerts"))
192ebfedea0SLionel Sambuc             flags |= PKCS7_NOCERTS;
193ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-noattr"))
194ebfedea0SLionel Sambuc             flags |= PKCS7_NOATTR;
195ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-nodetach"))
196ebfedea0SLionel Sambuc             flags &= ~PKCS7_DETACHED;
197ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-nosmimecap"))
198ebfedea0SLionel Sambuc             flags |= PKCS7_NOSMIMECAP;
199ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-binary"))
200ebfedea0SLionel Sambuc             flags |= PKCS7_BINARY;
201ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-nosigs"))
202ebfedea0SLionel Sambuc             flags |= PKCS7_NOSIGS;
203ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-stream"))
204ebfedea0SLionel Sambuc             indef = 1;
205ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-indef"))
206ebfedea0SLionel Sambuc             indef = 1;
207ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-noindef"))
208ebfedea0SLionel Sambuc             indef = 0;
209ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-nooldmime"))
210ebfedea0SLionel Sambuc             flags |= PKCS7_NOOLDMIMETYPE;
211ebfedea0SLionel Sambuc         else if (!strcmp(*args, "-crlfeol"))
212ebfedea0SLionel Sambuc             flags |= PKCS7_CRLFEOL;
213*0a6a1f1dSLionel Sambuc         else if (!strcmp(*args, "-rand")) {
214ebfedea0SLionel Sambuc             if (!args[1])
215ebfedea0SLionel Sambuc                 goto argerr;
216ebfedea0SLionel Sambuc             args++;
217ebfedea0SLionel Sambuc             inrand = *args;
218ebfedea0SLionel Sambuc             need_rand = 1;
219ebfedea0SLionel Sambuc         }
220ebfedea0SLionel Sambuc #ifndef OPENSSL_NO_ENGINE
221*0a6a1f1dSLionel Sambuc         else if (!strcmp(*args, "-engine")) {
222ebfedea0SLionel Sambuc             if (!args[1])
223ebfedea0SLionel Sambuc                 goto argerr;
224ebfedea0SLionel Sambuc             engine = *++args;
225ebfedea0SLionel Sambuc         }
226ebfedea0SLionel Sambuc #endif
227*0a6a1f1dSLionel Sambuc         else if (!strcmp(*args, "-passin")) {
228ebfedea0SLionel Sambuc             if (!args[1])
229ebfedea0SLionel Sambuc                 goto argerr;
230ebfedea0SLionel Sambuc             passargin = *++args;
231*0a6a1f1dSLionel Sambuc         } else if (!strcmp(*args, "-to")) {
232ebfedea0SLionel Sambuc             if (!args[1])
233ebfedea0SLionel Sambuc                 goto argerr;
234ebfedea0SLionel Sambuc             to = *++args;
235*0a6a1f1dSLionel Sambuc         } else if (!strcmp(*args, "-from")) {
236ebfedea0SLionel Sambuc             if (!args[1])
237ebfedea0SLionel Sambuc                 goto argerr;
238ebfedea0SLionel Sambuc             from = *++args;
239*0a6a1f1dSLionel Sambuc         } else if (!strcmp(*args, "-subject")) {
240ebfedea0SLionel Sambuc             if (!args[1])
241ebfedea0SLionel Sambuc                 goto argerr;
242ebfedea0SLionel Sambuc             subject = *++args;
243*0a6a1f1dSLionel Sambuc         } else if (!strcmp(*args, "-signer")) {
244ebfedea0SLionel Sambuc             if (!args[1])
245ebfedea0SLionel Sambuc                 goto argerr;
246ebfedea0SLionel Sambuc             /* If previous -signer argument add signer to list */
247ebfedea0SLionel Sambuc 
248*0a6a1f1dSLionel Sambuc             if (signerfile) {
249ebfedea0SLionel Sambuc                 if (!sksigners)
250ebfedea0SLionel Sambuc                     sksigners = sk_OPENSSL_STRING_new_null();
251ebfedea0SLionel Sambuc                 sk_OPENSSL_STRING_push(sksigners, signerfile);
252ebfedea0SLionel Sambuc                 if (!keyfile)
253ebfedea0SLionel Sambuc                     keyfile = signerfile;
254ebfedea0SLionel Sambuc                 if (!skkeys)
255ebfedea0SLionel Sambuc                     skkeys = sk_OPENSSL_STRING_new_null();
256ebfedea0SLionel Sambuc                 sk_OPENSSL_STRING_push(skkeys, keyfile);
257ebfedea0SLionel Sambuc                 keyfile = NULL;
258ebfedea0SLionel Sambuc             }
259ebfedea0SLionel Sambuc             signerfile = *++args;
260*0a6a1f1dSLionel Sambuc         } else if (!strcmp(*args, "-recip")) {
261ebfedea0SLionel Sambuc             if (!args[1])
262ebfedea0SLionel Sambuc                 goto argerr;
263ebfedea0SLionel Sambuc             recipfile = *++args;
264*0a6a1f1dSLionel Sambuc         } else if (!strcmp(*args, "-md")) {
265ebfedea0SLionel Sambuc             if (!args[1])
266ebfedea0SLionel Sambuc                 goto argerr;
267ebfedea0SLionel Sambuc             sign_md = EVP_get_digestbyname(*++args);
268*0a6a1f1dSLionel Sambuc             if (sign_md == NULL) {
269*0a6a1f1dSLionel Sambuc                 BIO_printf(bio_err, "Unknown digest %s\n", *args);
270ebfedea0SLionel Sambuc                 goto argerr;
271ebfedea0SLionel Sambuc             }
272*0a6a1f1dSLionel Sambuc         } else if (!strcmp(*args, "-inkey")) {
273ebfedea0SLionel Sambuc             if (!args[1])
274ebfedea0SLionel Sambuc                 goto argerr;
275ebfedea0SLionel Sambuc             /* If previous -inkey arument add signer to list */
276*0a6a1f1dSLionel Sambuc             if (keyfile) {
277*0a6a1f1dSLionel Sambuc                 if (!signerfile) {
278ebfedea0SLionel Sambuc                     BIO_puts(bio_err, "Illegal -inkey without -signer\n");
279ebfedea0SLionel Sambuc                     goto argerr;
280ebfedea0SLionel Sambuc                 }
281ebfedea0SLionel Sambuc                 if (!sksigners)
282ebfedea0SLionel Sambuc                     sksigners = sk_OPENSSL_STRING_new_null();
283ebfedea0SLionel Sambuc                 sk_OPENSSL_STRING_push(sksigners, signerfile);
284ebfedea0SLionel Sambuc                 signerfile = NULL;
285ebfedea0SLionel Sambuc                 if (!skkeys)
286ebfedea0SLionel Sambuc                     skkeys = sk_OPENSSL_STRING_new_null();
287ebfedea0SLionel Sambuc                 sk_OPENSSL_STRING_push(skkeys, keyfile);
288ebfedea0SLionel Sambuc             }
289ebfedea0SLionel Sambuc             keyfile = *++args;
290*0a6a1f1dSLionel Sambuc         } else if (!strcmp(*args, "-keyform")) {
291ebfedea0SLionel Sambuc             if (!args[1])
292ebfedea0SLionel Sambuc                 goto argerr;
293ebfedea0SLionel Sambuc             keyform = str2fmt(*++args);
294*0a6a1f1dSLionel Sambuc         } else if (!strcmp(*args, "-certfile")) {
295ebfedea0SLionel Sambuc             if (!args[1])
296ebfedea0SLionel Sambuc                 goto argerr;
297ebfedea0SLionel Sambuc             certfile = *++args;
298*0a6a1f1dSLionel Sambuc         } else if (!strcmp(*args, "-CAfile")) {
299ebfedea0SLionel Sambuc             if (!args[1])
300ebfedea0SLionel Sambuc                 goto argerr;
301ebfedea0SLionel Sambuc             CAfile = *++args;
302*0a6a1f1dSLionel Sambuc         } else if (!strcmp(*args, "-CApath")) {
303ebfedea0SLionel Sambuc             if (!args[1])
304ebfedea0SLionel Sambuc                 goto argerr;
305ebfedea0SLionel Sambuc             CApath = *++args;
306*0a6a1f1dSLionel Sambuc         } else if (!strcmp(*args, "-in")) {
307ebfedea0SLionel Sambuc             if (!args[1])
308ebfedea0SLionel Sambuc                 goto argerr;
309ebfedea0SLionel Sambuc             infile = *++args;
310*0a6a1f1dSLionel Sambuc         } else if (!strcmp(*args, "-inform")) {
311ebfedea0SLionel Sambuc             if (!args[1])
312ebfedea0SLionel Sambuc                 goto argerr;
313ebfedea0SLionel Sambuc             informat = str2fmt(*++args);
314*0a6a1f1dSLionel Sambuc         } else if (!strcmp(*args, "-outform")) {
315ebfedea0SLionel Sambuc             if (!args[1])
316ebfedea0SLionel Sambuc                 goto argerr;
317ebfedea0SLionel Sambuc             outformat = str2fmt(*++args);
318*0a6a1f1dSLionel Sambuc         } else if (!strcmp(*args, "-out")) {
319ebfedea0SLionel Sambuc             if (!args[1])
320ebfedea0SLionel Sambuc                 goto argerr;
321ebfedea0SLionel Sambuc             outfile = *++args;
322*0a6a1f1dSLionel Sambuc         } else if (!strcmp(*args, "-content")) {
323ebfedea0SLionel Sambuc             if (!args[1])
324ebfedea0SLionel Sambuc                 goto argerr;
325ebfedea0SLionel Sambuc             contfile = *++args;
326*0a6a1f1dSLionel Sambuc         } else if (args_verify(&args, NULL, &badarg, bio_err, &vpm))
327ebfedea0SLionel Sambuc             continue;
328ebfedea0SLionel Sambuc         else if ((cipher = EVP_get_cipherbyname(*args + 1)) == NULL)
329ebfedea0SLionel Sambuc             badarg = 1;
330ebfedea0SLionel Sambuc         args++;
331ebfedea0SLionel Sambuc     }
332ebfedea0SLionel Sambuc 
333*0a6a1f1dSLionel Sambuc     if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners)) {
334ebfedea0SLionel Sambuc         BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
335ebfedea0SLionel Sambuc         goto argerr;
336ebfedea0SLionel Sambuc     }
337ebfedea0SLionel Sambuc 
338*0a6a1f1dSLionel Sambuc     if (operation & SMIME_SIGNERS) {
339ebfedea0SLionel Sambuc         /* Check to see if any final signer needs to be appended */
340*0a6a1f1dSLionel Sambuc         if (keyfile && !signerfile) {
341ebfedea0SLionel Sambuc             BIO_puts(bio_err, "Illegal -inkey without -signer\n");
342ebfedea0SLionel Sambuc             goto argerr;
343ebfedea0SLionel Sambuc         }
344*0a6a1f1dSLionel Sambuc         if (signerfile) {
345ebfedea0SLionel Sambuc             if (!sksigners)
346ebfedea0SLionel Sambuc                 sksigners = sk_OPENSSL_STRING_new_null();
347ebfedea0SLionel Sambuc             sk_OPENSSL_STRING_push(sksigners, signerfile);
348ebfedea0SLionel Sambuc             if (!skkeys)
349ebfedea0SLionel Sambuc                 skkeys = sk_OPENSSL_STRING_new_null();
350ebfedea0SLionel Sambuc             if (!keyfile)
351ebfedea0SLionel Sambuc                 keyfile = signerfile;
352ebfedea0SLionel Sambuc             sk_OPENSSL_STRING_push(skkeys, keyfile);
353ebfedea0SLionel Sambuc         }
354*0a6a1f1dSLionel Sambuc         if (!sksigners) {
355ebfedea0SLionel Sambuc             BIO_printf(bio_err, "No signer certificate specified\n");
356ebfedea0SLionel Sambuc             badarg = 1;
357ebfedea0SLionel Sambuc         }
358ebfedea0SLionel Sambuc         signerfile = NULL;
359ebfedea0SLionel Sambuc         keyfile = NULL;
360ebfedea0SLionel Sambuc         need_rand = 1;
361*0a6a1f1dSLionel Sambuc     } else if (operation == SMIME_DECRYPT) {
362*0a6a1f1dSLionel Sambuc         if (!recipfile && !keyfile) {
363*0a6a1f1dSLionel Sambuc             BIO_printf(bio_err,
364*0a6a1f1dSLionel Sambuc                        "No recipient certificate or key specified\n");
365ebfedea0SLionel Sambuc             badarg = 1;
366ebfedea0SLionel Sambuc         }
367*0a6a1f1dSLionel Sambuc     } else if (operation == SMIME_ENCRYPT) {
368*0a6a1f1dSLionel Sambuc         if (!*args) {
369ebfedea0SLionel Sambuc             BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
370ebfedea0SLionel Sambuc             badarg = 1;
371ebfedea0SLionel Sambuc         }
372ebfedea0SLionel Sambuc         need_rand = 1;
373*0a6a1f1dSLionel Sambuc     } else if (!operation)
374ebfedea0SLionel Sambuc         badarg = 1;
375ebfedea0SLionel Sambuc 
376*0a6a1f1dSLionel Sambuc     if (badarg) {
377ebfedea0SLionel Sambuc  argerr:
378ebfedea0SLionel Sambuc         BIO_printf(bio_err, "Usage smime [options] cert.pem ...\n");
379ebfedea0SLionel Sambuc         BIO_printf(bio_err, "where options are\n");
380ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-encrypt       encrypt message\n");
381ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-decrypt       decrypt encrypted message\n");
382ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-sign          sign message\n");
383ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-verify        verify signed message\n");
384ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-pk7out        output PKCS#7 structure\n");
385ebfedea0SLionel Sambuc #ifndef OPENSSL_NO_DES
386ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-des3          encrypt with triple DES\n");
387ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-des           encrypt with DES\n");
388ebfedea0SLionel Sambuc #endif
389ebfedea0SLionel Sambuc #ifndef OPENSSL_NO_SEED
390ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-seed          encrypt with SEED\n");
391ebfedea0SLionel Sambuc #endif
392ebfedea0SLionel Sambuc #ifndef OPENSSL_NO_RC2
393ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-rc2-40        encrypt with RC2-40 (default)\n");
394ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-rc2-64        encrypt with RC2-64\n");
395ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-rc2-128       encrypt with RC2-128\n");
396ebfedea0SLionel Sambuc #endif
397ebfedea0SLionel Sambuc #ifndef OPENSSL_NO_AES
398ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-aes128, -aes192, -aes256\n");
399*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
400*0a6a1f1dSLionel Sambuc                    "               encrypt PEM output with cbc aes\n");
401ebfedea0SLionel Sambuc #endif
402ebfedea0SLionel Sambuc #ifndef OPENSSL_NO_CAMELLIA
403ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-camellia128, -camellia192, -camellia256\n");
404*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
405*0a6a1f1dSLionel Sambuc                    "               encrypt PEM output with cbc camellia\n");
406ebfedea0SLionel Sambuc #endif
407*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
408*0a6a1f1dSLionel Sambuc                    "-nointern      don't search certificates in message for signer\n");
409*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
410*0a6a1f1dSLionel Sambuc                    "-nosigs        don't verify message signature\n");
411*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
412*0a6a1f1dSLionel Sambuc                    "-noverify      don't verify signers certificate\n");
413*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
414*0a6a1f1dSLionel Sambuc                    "-nocerts       don't include signers certificate when signing\n");
415ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-nodetach      use opaque signing\n");
416*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
417*0a6a1f1dSLionel Sambuc                    "-noattr        don't include any signed attributes\n");
418*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
419*0a6a1f1dSLionel Sambuc                    "-binary        don't translate message to text\n");
420ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-certfile file other certificates file\n");
421ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-signer file   signer certificate file\n");
422*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
423*0a6a1f1dSLionel Sambuc                    "-recip  file   recipient certificate file for decryption\n");
424ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-in file       input file\n");
425*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
426*0a6a1f1dSLionel Sambuc                    "-inform arg    input format SMIME (default), PEM or DER\n");
427*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
428*0a6a1f1dSLionel Sambuc                    "-inkey file    input private key (if not signer or recipient)\n");
429*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
430*0a6a1f1dSLionel Sambuc                    "-keyform arg   input private key format (PEM or ENGINE)\n");
431ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-out file      output file\n");
432*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
433*0a6a1f1dSLionel Sambuc                    "-outform arg   output format SMIME (default), PEM or DER\n");
434*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
435*0a6a1f1dSLionel Sambuc                    "-content file  supply or override content for detached signature\n");
436ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-to addr       to address\n");
437ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-from ad       from address\n");
438ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-subject s     subject\n");
439*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
440*0a6a1f1dSLionel Sambuc                    "-text          include or delete text MIME headers\n");
441*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
442*0a6a1f1dSLionel Sambuc                    "-CApath dir    trusted certificates directory\n");
443ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-CAfile file   trusted certificates file\n");
444*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
445*0a6a1f1dSLionel Sambuc                    "-no_alt_chains only ever use the first certificate chain found\n");
446*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
447*0a6a1f1dSLionel Sambuc                    "-crl_check     check revocation status of signer's certificate using CRLs\n");
448*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
449*0a6a1f1dSLionel Sambuc                    "-crl_check_all check revocation status of signer's certificate chain using CRLs\n");
450ebfedea0SLionel Sambuc #ifndef OPENSSL_NO_ENGINE
451*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
452*0a6a1f1dSLionel Sambuc                    "-engine e      use engine e, possibly a hardware device.\n");
453ebfedea0SLionel Sambuc #endif
454ebfedea0SLionel Sambuc         BIO_printf(bio_err, "-passin arg    input file pass phrase source\n");
455*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR,
456*0a6a1f1dSLionel Sambuc                    LIST_SEPARATOR_CHAR);
457*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
458*0a6a1f1dSLionel Sambuc                    "               load the file (or the files in the directory) into\n");
459ebfedea0SLionel Sambuc         BIO_printf(bio_err, "               the random number generator\n");
460*0a6a1f1dSLionel Sambuc         BIO_printf(bio_err,
461*0a6a1f1dSLionel Sambuc                    "cert.pem       recipient certificate(s) for encryption\n");
462ebfedea0SLionel Sambuc         goto end;
463ebfedea0SLionel Sambuc     }
464ebfedea0SLionel Sambuc #ifndef OPENSSL_NO_ENGINE
465ebfedea0SLionel Sambuc     e = setup_engine(bio_err, engine, 0);
466ebfedea0SLionel Sambuc #endif
467ebfedea0SLionel Sambuc 
468*0a6a1f1dSLionel Sambuc     if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
469ebfedea0SLionel Sambuc         BIO_printf(bio_err, "Error getting password\n");
470ebfedea0SLionel Sambuc         goto end;
471ebfedea0SLionel Sambuc     }
472ebfedea0SLionel Sambuc 
473*0a6a1f1dSLionel Sambuc     if (need_rand) {
474ebfedea0SLionel Sambuc         app_RAND_load_file(NULL, bio_err, (inrand != NULL));
475ebfedea0SLionel Sambuc         if (inrand != NULL)
476ebfedea0SLionel Sambuc             BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
477ebfedea0SLionel Sambuc                        app_RAND_load_files(inrand));
478ebfedea0SLionel Sambuc     }
479ebfedea0SLionel Sambuc 
480ebfedea0SLionel Sambuc     ret = 2;
481ebfedea0SLionel Sambuc 
482ebfedea0SLionel Sambuc     if (!(operation & SMIME_SIGNERS))
483ebfedea0SLionel Sambuc         flags &= ~PKCS7_DETACHED;
484ebfedea0SLionel Sambuc 
485*0a6a1f1dSLionel Sambuc     if (operation & SMIME_OP) {
486ebfedea0SLionel Sambuc         if (outformat == FORMAT_ASN1)
487ebfedea0SLionel Sambuc             outmode = "wb";
488*0a6a1f1dSLionel Sambuc     } else {
489ebfedea0SLionel Sambuc         if (flags & PKCS7_BINARY)
490ebfedea0SLionel Sambuc             outmode = "wb";
491ebfedea0SLionel Sambuc     }
492ebfedea0SLionel Sambuc 
493*0a6a1f1dSLionel Sambuc     if (operation & SMIME_IP) {
494ebfedea0SLionel Sambuc         if (informat == FORMAT_ASN1)
495ebfedea0SLionel Sambuc             inmode = "rb";
496*0a6a1f1dSLionel Sambuc     } else {
497ebfedea0SLionel Sambuc         if (flags & PKCS7_BINARY)
498ebfedea0SLionel Sambuc             inmode = "rb";
499ebfedea0SLionel Sambuc     }
500ebfedea0SLionel Sambuc 
501*0a6a1f1dSLionel Sambuc     if (operation == SMIME_ENCRYPT) {
502*0a6a1f1dSLionel Sambuc         if (!cipher) {
503*0a6a1f1dSLionel Sambuc #ifndef OPENSSL_NO_DES
504*0a6a1f1dSLionel Sambuc             cipher = EVP_des_ede3_cbc();
505ebfedea0SLionel Sambuc #else
506ebfedea0SLionel Sambuc             BIO_printf(bio_err, "No cipher selected\n");
507ebfedea0SLionel Sambuc             goto end;
508ebfedea0SLionel Sambuc #endif
509ebfedea0SLionel Sambuc         }
510ebfedea0SLionel Sambuc         encerts = sk_X509_new_null();
511*0a6a1f1dSLionel Sambuc         while (*args) {
512ebfedea0SLionel Sambuc             if (!(cert = load_cert(bio_err, *args, FORMAT_PEM,
513*0a6a1f1dSLionel Sambuc                                    NULL, e, "recipient certificate file"))) {
514ebfedea0SLionel Sambuc #if 0                           /* An appropriate message is already printed */
515*0a6a1f1dSLionel Sambuc                 BIO_printf(bio_err,
516*0a6a1f1dSLionel Sambuc                            "Can't read recipient certificate file %s\n",
517*0a6a1f1dSLionel Sambuc                            *args);
518ebfedea0SLionel Sambuc #endif
519ebfedea0SLionel Sambuc                 goto end;
520ebfedea0SLionel Sambuc             }
521ebfedea0SLionel Sambuc             sk_X509_push(encerts, cert);
522ebfedea0SLionel Sambuc             cert = NULL;
523ebfedea0SLionel Sambuc             args++;
524ebfedea0SLionel Sambuc         }
525ebfedea0SLionel Sambuc     }
526ebfedea0SLionel Sambuc 
527*0a6a1f1dSLionel Sambuc     if (certfile) {
528ebfedea0SLionel Sambuc         if (!(other = load_certs(bio_err, certfile, FORMAT_PEM, NULL,
529*0a6a1f1dSLionel Sambuc                                  e, "certificate file"))) {
530ebfedea0SLionel Sambuc             ERR_print_errors(bio_err);
531ebfedea0SLionel Sambuc             goto end;
532ebfedea0SLionel Sambuc         }
533ebfedea0SLionel Sambuc     }
534ebfedea0SLionel Sambuc 
535*0a6a1f1dSLionel Sambuc     if (recipfile && (operation == SMIME_DECRYPT)) {
536ebfedea0SLionel Sambuc         if (!(recip = load_cert(bio_err, recipfile, FORMAT_PEM, NULL,
537*0a6a1f1dSLionel Sambuc                                 e, "recipient certificate file"))) {
538ebfedea0SLionel Sambuc             ERR_print_errors(bio_err);
539ebfedea0SLionel Sambuc             goto end;
540ebfedea0SLionel Sambuc         }
541ebfedea0SLionel Sambuc     }
542ebfedea0SLionel Sambuc 
543*0a6a1f1dSLionel Sambuc     if (operation == SMIME_DECRYPT) {
544ebfedea0SLionel Sambuc         if (!keyfile)
545ebfedea0SLionel Sambuc             keyfile = recipfile;
546*0a6a1f1dSLionel Sambuc     } else if (operation == SMIME_SIGN) {
547ebfedea0SLionel Sambuc         if (!keyfile)
548ebfedea0SLionel Sambuc             keyfile = signerfile;
549*0a6a1f1dSLionel Sambuc     } else
550*0a6a1f1dSLionel Sambuc         keyfile = NULL;
551ebfedea0SLionel Sambuc 
552*0a6a1f1dSLionel Sambuc     if (keyfile) {
553ebfedea0SLionel Sambuc         key = load_key(bio_err, keyfile, keyform, 0, passin, e,
554ebfedea0SLionel Sambuc                        "signing key file");
555ebfedea0SLionel Sambuc         if (!key)
556ebfedea0SLionel Sambuc             goto end;
557ebfedea0SLionel Sambuc     }
558ebfedea0SLionel Sambuc 
559*0a6a1f1dSLionel Sambuc     if (infile) {
560*0a6a1f1dSLionel Sambuc         if (!(in = BIO_new_file(infile, inmode))) {
561*0a6a1f1dSLionel Sambuc             BIO_printf(bio_err, "Can't open input file %s\n", infile);
562ebfedea0SLionel Sambuc             goto end;
563ebfedea0SLionel Sambuc         }
564*0a6a1f1dSLionel Sambuc     } else
565ebfedea0SLionel Sambuc         in = BIO_new_fp(stdin, BIO_NOCLOSE);
566ebfedea0SLionel Sambuc 
567*0a6a1f1dSLionel Sambuc     if (operation & SMIME_IP) {
568ebfedea0SLionel Sambuc         if (informat == FORMAT_SMIME)
569ebfedea0SLionel Sambuc             p7 = SMIME_read_PKCS7(in, &indata);
570ebfedea0SLionel Sambuc         else if (informat == FORMAT_PEM)
571ebfedea0SLionel Sambuc             p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
572ebfedea0SLionel Sambuc         else if (informat == FORMAT_ASN1)
573ebfedea0SLionel Sambuc             p7 = d2i_PKCS7_bio(in, NULL);
574*0a6a1f1dSLionel Sambuc         else {
575ebfedea0SLionel Sambuc             BIO_printf(bio_err, "Bad input format for PKCS#7 file\n");
576ebfedea0SLionel Sambuc             goto end;
577ebfedea0SLionel Sambuc         }
578ebfedea0SLionel Sambuc 
579*0a6a1f1dSLionel Sambuc         if (!p7) {
580ebfedea0SLionel Sambuc             BIO_printf(bio_err, "Error reading S/MIME message\n");
581ebfedea0SLionel Sambuc             goto end;
582ebfedea0SLionel Sambuc         }
583*0a6a1f1dSLionel Sambuc         if (contfile) {
584ebfedea0SLionel Sambuc             BIO_free(indata);
585*0a6a1f1dSLionel Sambuc             if (!(indata = BIO_new_file(contfile, "rb"))) {
586ebfedea0SLionel Sambuc                 BIO_printf(bio_err, "Can't read content file %s\n", contfile);
587ebfedea0SLionel Sambuc                 goto end;
588ebfedea0SLionel Sambuc             }
589ebfedea0SLionel Sambuc         }
590ebfedea0SLionel Sambuc     }
591ebfedea0SLionel Sambuc 
592*0a6a1f1dSLionel Sambuc     if (outfile) {
593*0a6a1f1dSLionel Sambuc         if (!(out = BIO_new_file(outfile, outmode))) {
594*0a6a1f1dSLionel Sambuc             BIO_printf(bio_err, "Can't open output file %s\n", outfile);
595ebfedea0SLionel Sambuc             goto end;
596ebfedea0SLionel Sambuc         }
597*0a6a1f1dSLionel Sambuc     } else {
598ebfedea0SLionel Sambuc         out = BIO_new_fp(stdout, BIO_NOCLOSE);
599ebfedea0SLionel Sambuc #ifdef OPENSSL_SYS_VMS
600ebfedea0SLionel Sambuc         {
601ebfedea0SLionel Sambuc             BIO *tmpbio = BIO_new(BIO_f_linebuffer());
602ebfedea0SLionel Sambuc             out = BIO_push(tmpbio, out);
603ebfedea0SLionel Sambuc         }
604ebfedea0SLionel Sambuc #endif
605ebfedea0SLionel Sambuc     }
606ebfedea0SLionel Sambuc 
607*0a6a1f1dSLionel Sambuc     if (operation == SMIME_VERIFY) {
608ebfedea0SLionel Sambuc         if (!(store = setup_verify(bio_err, CAfile, CApath)))
609ebfedea0SLionel Sambuc             goto end;
610ebfedea0SLionel Sambuc         X509_STORE_set_verify_cb(store, smime_cb);
611ebfedea0SLionel Sambuc         if (vpm)
612ebfedea0SLionel Sambuc             X509_STORE_set1_param(store, vpm);
613ebfedea0SLionel Sambuc     }
614ebfedea0SLionel Sambuc 
615ebfedea0SLionel Sambuc     ret = 3;
616ebfedea0SLionel Sambuc 
617*0a6a1f1dSLionel Sambuc     if (operation == SMIME_ENCRYPT) {
618ebfedea0SLionel Sambuc         if (indef)
619ebfedea0SLionel Sambuc             flags |= PKCS7_STREAM;
620ebfedea0SLionel Sambuc         p7 = PKCS7_encrypt(encerts, in, cipher, flags);
621*0a6a1f1dSLionel Sambuc     } else if (operation & SMIME_SIGNERS) {
622ebfedea0SLionel Sambuc         int i;
623*0a6a1f1dSLionel Sambuc         /*
624*0a6a1f1dSLionel Sambuc          * If detached data content we only enable streaming if S/MIME output
625*0a6a1f1dSLionel Sambuc          * format.
626ebfedea0SLionel Sambuc          */
627*0a6a1f1dSLionel Sambuc         if (operation == SMIME_SIGN) {
628*0a6a1f1dSLionel Sambuc             if (flags & PKCS7_DETACHED) {
629ebfedea0SLionel Sambuc                 if (outformat == FORMAT_SMIME)
630ebfedea0SLionel Sambuc                     flags |= PKCS7_STREAM;
631*0a6a1f1dSLionel Sambuc             } else if (indef)
632ebfedea0SLionel Sambuc                 flags |= PKCS7_STREAM;
633ebfedea0SLionel Sambuc             flags |= PKCS7_PARTIAL;
634ebfedea0SLionel Sambuc             p7 = PKCS7_sign(NULL, NULL, other, in, flags);
635ebfedea0SLionel Sambuc             if (!p7)
636ebfedea0SLionel Sambuc                 goto end;
637*0a6a1f1dSLionel Sambuc         } else
638ebfedea0SLionel Sambuc             flags |= PKCS7_REUSE_DIGEST;
639*0a6a1f1dSLionel Sambuc         for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) {
640ebfedea0SLionel Sambuc             signerfile = sk_OPENSSL_STRING_value(sksigners, i);
641ebfedea0SLionel Sambuc             keyfile = sk_OPENSSL_STRING_value(skkeys, i);
642ebfedea0SLionel Sambuc             signer = load_cert(bio_err, signerfile, FORMAT_PEM, NULL,
643ebfedea0SLionel Sambuc                                e, "signer certificate");
644ebfedea0SLionel Sambuc             if (!signer)
645ebfedea0SLionel Sambuc                 goto end;
646ebfedea0SLionel Sambuc             key = load_key(bio_err, keyfile, keyform, 0, passin, e,
647ebfedea0SLionel Sambuc                            "signing key file");
648ebfedea0SLionel Sambuc             if (!key)
649ebfedea0SLionel Sambuc                 goto end;
650*0a6a1f1dSLionel Sambuc             if (!PKCS7_sign_add_signer(p7, signer, key, sign_md, flags))
651ebfedea0SLionel Sambuc                 goto end;
652ebfedea0SLionel Sambuc             X509_free(signer);
653ebfedea0SLionel Sambuc             signer = NULL;
654ebfedea0SLionel Sambuc             EVP_PKEY_free(key);
655ebfedea0SLionel Sambuc             key = NULL;
656ebfedea0SLionel Sambuc         }
657ebfedea0SLionel Sambuc         /* If not streaming or resigning finalize structure */
658*0a6a1f1dSLionel Sambuc         if ((operation == SMIME_SIGN) && !(flags & PKCS7_STREAM)) {
659ebfedea0SLionel Sambuc             if (!PKCS7_final(p7, in, flags))
660ebfedea0SLionel Sambuc                 goto end;
661ebfedea0SLionel Sambuc         }
662ebfedea0SLionel Sambuc     }
663ebfedea0SLionel Sambuc 
664*0a6a1f1dSLionel Sambuc     if (!p7) {
665ebfedea0SLionel Sambuc         BIO_printf(bio_err, "Error creating PKCS#7 structure\n");
666ebfedea0SLionel Sambuc         goto end;
667ebfedea0SLionel Sambuc     }
668ebfedea0SLionel Sambuc 
669ebfedea0SLionel Sambuc     ret = 4;
670*0a6a1f1dSLionel Sambuc     if (operation == SMIME_DECRYPT) {
671*0a6a1f1dSLionel Sambuc         if (!PKCS7_decrypt(p7, key, recip, out, flags)) {
672ebfedea0SLionel Sambuc             BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n");
673ebfedea0SLionel Sambuc             goto end;
674ebfedea0SLionel Sambuc         }
675*0a6a1f1dSLionel Sambuc     } else if (operation == SMIME_VERIFY) {
676ebfedea0SLionel Sambuc         STACK_OF(X509) *signers;
677ebfedea0SLionel Sambuc         if (PKCS7_verify(p7, other, store, indata, out, flags))
678ebfedea0SLionel Sambuc             BIO_printf(bio_err, "Verification successful\n");
679*0a6a1f1dSLionel Sambuc         else {
680ebfedea0SLionel Sambuc             BIO_printf(bio_err, "Verification failure\n");
681ebfedea0SLionel Sambuc             goto end;
682ebfedea0SLionel Sambuc         }
683ebfedea0SLionel Sambuc         signers = PKCS7_get0_signers(p7, other, flags);
684*0a6a1f1dSLionel Sambuc         if (!save_certs(signerfile, signers)) {
685*0a6a1f1dSLionel Sambuc             BIO_printf(bio_err, "Error writing signers to %s\n", signerfile);
686ebfedea0SLionel Sambuc             ret = 5;
687ebfedea0SLionel Sambuc             goto end;
688ebfedea0SLionel Sambuc         }
689ebfedea0SLionel Sambuc         sk_X509_free(signers);
690*0a6a1f1dSLionel Sambuc     } else if (operation == SMIME_PK7OUT)
691ebfedea0SLionel Sambuc         PEM_write_bio_PKCS7(out, p7);
692*0a6a1f1dSLionel Sambuc     else {
693ebfedea0SLionel Sambuc         if (to)
694ebfedea0SLionel Sambuc             BIO_printf(out, "To: %s\n", to);
695ebfedea0SLionel Sambuc         if (from)
696ebfedea0SLionel Sambuc             BIO_printf(out, "From: %s\n", from);
697ebfedea0SLionel Sambuc         if (subject)
698ebfedea0SLionel Sambuc             BIO_printf(out, "Subject: %s\n", subject);
699*0a6a1f1dSLionel Sambuc         if (outformat == FORMAT_SMIME) {
700ebfedea0SLionel Sambuc             if (operation == SMIME_RESIGN)
701ebfedea0SLionel Sambuc                 SMIME_write_PKCS7(out, p7, indata, flags);
702ebfedea0SLionel Sambuc             else
703ebfedea0SLionel Sambuc                 SMIME_write_PKCS7(out, p7, in, flags);
704*0a6a1f1dSLionel Sambuc         } else if (outformat == FORMAT_PEM)
705ebfedea0SLionel Sambuc             PEM_write_bio_PKCS7_stream(out, p7, in, flags);
706ebfedea0SLionel Sambuc         else if (outformat == FORMAT_ASN1)
707ebfedea0SLionel Sambuc             i2d_PKCS7_bio_stream(out, p7, in, flags);
708*0a6a1f1dSLionel Sambuc         else {
709ebfedea0SLionel Sambuc             BIO_printf(bio_err, "Bad output format for PKCS#7 file\n");
710ebfedea0SLionel Sambuc             goto end;
711ebfedea0SLionel Sambuc         }
712ebfedea0SLionel Sambuc     }
713ebfedea0SLionel Sambuc     ret = 0;
714ebfedea0SLionel Sambuc  end:
715ebfedea0SLionel Sambuc     if (need_rand)
716ebfedea0SLionel Sambuc         app_RAND_write_file(NULL, bio_err);
717*0a6a1f1dSLionel Sambuc     if (ret)
718*0a6a1f1dSLionel Sambuc         ERR_print_errors(bio_err);
719ebfedea0SLionel Sambuc     sk_X509_pop_free(encerts, X509_free);
720ebfedea0SLionel Sambuc     sk_X509_pop_free(other, X509_free);
721ebfedea0SLionel Sambuc     if (vpm)
722ebfedea0SLionel Sambuc         X509_VERIFY_PARAM_free(vpm);
723ebfedea0SLionel Sambuc     if (sksigners)
724ebfedea0SLionel Sambuc         sk_OPENSSL_STRING_free(sksigners);
725ebfedea0SLionel Sambuc     if (skkeys)
726ebfedea0SLionel Sambuc         sk_OPENSSL_STRING_free(skkeys);
727ebfedea0SLionel Sambuc     X509_STORE_free(store);
728ebfedea0SLionel Sambuc     X509_free(cert);
729ebfedea0SLionel Sambuc     X509_free(recip);
730ebfedea0SLionel Sambuc     X509_free(signer);
731ebfedea0SLionel Sambuc     EVP_PKEY_free(key);
732ebfedea0SLionel Sambuc     PKCS7_free(p7);
733ebfedea0SLionel Sambuc     BIO_free(in);
734ebfedea0SLionel Sambuc     BIO_free(indata);
735ebfedea0SLionel Sambuc     BIO_free_all(out);
736*0a6a1f1dSLionel Sambuc     if (passin)
737*0a6a1f1dSLionel Sambuc         OPENSSL_free(passin);
738ebfedea0SLionel Sambuc     return (ret);
739ebfedea0SLionel Sambuc }
740ebfedea0SLionel Sambuc 
save_certs(char * signerfile,STACK_OF (X509)* signers)741ebfedea0SLionel Sambuc static int save_certs(char *signerfile, STACK_OF(X509) *signers)
742ebfedea0SLionel Sambuc {
743ebfedea0SLionel Sambuc     int i;
744ebfedea0SLionel Sambuc     BIO *tmp;
745ebfedea0SLionel Sambuc     if (!signerfile)
746ebfedea0SLionel Sambuc         return 1;
747ebfedea0SLionel Sambuc     tmp = BIO_new_file(signerfile, "w");
748*0a6a1f1dSLionel Sambuc     if (!tmp)
749*0a6a1f1dSLionel Sambuc         return 0;
750ebfedea0SLionel Sambuc     for (i = 0; i < sk_X509_num(signers); i++)
751ebfedea0SLionel Sambuc         PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
752ebfedea0SLionel Sambuc     BIO_free(tmp);
753ebfedea0SLionel Sambuc     return 1;
754ebfedea0SLionel Sambuc }
755ebfedea0SLionel Sambuc 
756ebfedea0SLionel Sambuc /* Minimal callback just to output policy info (if any) */
757ebfedea0SLionel Sambuc 
smime_cb(int ok,X509_STORE_CTX * ctx)758ebfedea0SLionel Sambuc static int smime_cb(int ok, X509_STORE_CTX *ctx)
759ebfedea0SLionel Sambuc {
760ebfedea0SLionel Sambuc     int error;
761ebfedea0SLionel Sambuc 
762ebfedea0SLionel Sambuc     error = X509_STORE_CTX_get_error(ctx);
763ebfedea0SLionel Sambuc 
764ebfedea0SLionel Sambuc     if ((error != X509_V_ERR_NO_EXPLICIT_POLICY)
765ebfedea0SLionel Sambuc         && ((error != X509_V_OK) || (ok != 2)))
766ebfedea0SLionel Sambuc         return ok;
767ebfedea0SLionel Sambuc 
768ebfedea0SLionel Sambuc     policies_print(NULL, ctx);
769ebfedea0SLionel Sambuc 
770ebfedea0SLionel Sambuc     return ok;
771ebfedea0SLionel Sambuc 
772ebfedea0SLionel Sambuc }
773