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