Annotation of src/usr.bin/openssl/smime.c, Revision 1.9
1.9 ! jsing 1: /* $OpenBSD: smime.c,v 1.8 2017/01/20 08:57:12 deraadt Exp $ */
1.1 jsing 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:
72: static int save_certs(char *signerfile, STACK_OF(X509) * signers);
73: static 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:
85: int
86: smime_main(int argc, char **argv)
87: {
88: int operation = 0;
89: int ret = 0;
90: char **args;
91: const char *inmode = "r", *outmode = "w";
92: char *infile = NULL, *outfile = NULL;
93: char *signerfile = NULL, *recipfile = NULL;
94: STACK_OF(OPENSSL_STRING) * sksigners = NULL, *skkeys = NULL;
95: char *certfile = NULL, *keyfile = NULL, *contfile = NULL;
96: const EVP_CIPHER *cipher = NULL;
97: PKCS7 *p7 = NULL;
98: X509_STORE *store = NULL;
99: X509 *cert = NULL, *recip = NULL, *signer = NULL;
100: EVP_PKEY *key = NULL;
101: STACK_OF(X509) * encerts = NULL, *other = NULL;
102: BIO *in = NULL, *out = NULL, *indata = NULL;
103: int badarg = 0;
104: int flags = PKCS7_DETACHED;
105: char *to = NULL, *from = NULL, *subject = NULL;
106: char *CAfile = NULL, *CApath = NULL;
107: char *passargin = NULL, *passin = NULL;
108: int indef = 0;
109: const EVP_MD *sign_md = NULL;
110: int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
111: int keyform = FORMAT_PEM;
112:
113: X509_VERIFY_PARAM *vpm = NULL;
1.5 doug 114:
115: if (single_execution) {
1.8 deraadt 116: if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
1.5 doug 117: perror("pledge");
1.7 doug 118: exit(1);
119: }
1.5 doug 120: }
1.1 jsing 121:
122: args = argv + 1;
123: ret = 1;
124:
125: while (!badarg && *args && *args[0] == '-') {
126: if (!strcmp(*args, "-encrypt"))
127: operation = SMIME_ENCRYPT;
128: else if (!strcmp(*args, "-decrypt"))
129: operation = SMIME_DECRYPT;
130: else if (!strcmp(*args, "-sign"))
131: operation = SMIME_SIGN;
132: else if (!strcmp(*args, "-resign"))
133: operation = SMIME_RESIGN;
134: else if (!strcmp(*args, "-verify"))
135: operation = SMIME_VERIFY;
136: else if (!strcmp(*args, "-pk7out"))
137: operation = SMIME_PK7OUT;
138: #ifndef OPENSSL_NO_DES
139: else if (!strcmp(*args, "-des3"))
140: cipher = EVP_des_ede3_cbc();
141: else if (!strcmp(*args, "-des"))
142: cipher = EVP_des_cbc();
143: #endif
144: #ifndef OPENSSL_NO_RC2
145: else if (!strcmp(*args, "-rc2-40"))
146: cipher = EVP_rc2_40_cbc();
147: else if (!strcmp(*args, "-rc2-128"))
148: cipher = EVP_rc2_cbc();
149: else if (!strcmp(*args, "-rc2-64"))
150: cipher = EVP_rc2_64_cbc();
151: #endif
152: #ifndef OPENSSL_NO_AES
153: else if (!strcmp(*args, "-aes128"))
154: cipher = EVP_aes_128_cbc();
155: else if (!strcmp(*args, "-aes192"))
156: cipher = EVP_aes_192_cbc();
157: else if (!strcmp(*args, "-aes256"))
158: cipher = EVP_aes_256_cbc();
159: #endif
160: #ifndef OPENSSL_NO_CAMELLIA
161: else if (!strcmp(*args, "-camellia128"))
162: cipher = EVP_camellia_128_cbc();
163: else if (!strcmp(*args, "-camellia192"))
164: cipher = EVP_camellia_192_cbc();
165: else if (!strcmp(*args, "-camellia256"))
166: cipher = EVP_camellia_256_cbc();
167: #endif
168: else if (!strcmp(*args, "-text"))
169: flags |= PKCS7_TEXT;
170: else if (!strcmp(*args, "-nointern"))
171: flags |= PKCS7_NOINTERN;
172: else if (!strcmp(*args, "-noverify"))
173: flags |= PKCS7_NOVERIFY;
174: else if (!strcmp(*args, "-nochain"))
175: flags |= PKCS7_NOCHAIN;
176: else if (!strcmp(*args, "-nocerts"))
177: flags |= PKCS7_NOCERTS;
178: else if (!strcmp(*args, "-noattr"))
179: flags |= PKCS7_NOATTR;
180: else if (!strcmp(*args, "-nodetach"))
181: flags &= ~PKCS7_DETACHED;
182: else if (!strcmp(*args, "-nosmimecap"))
183: flags |= PKCS7_NOSMIMECAP;
184: else if (!strcmp(*args, "-binary"))
185: flags |= PKCS7_BINARY;
186: else if (!strcmp(*args, "-nosigs"))
187: flags |= PKCS7_NOSIGS;
188: else if (!strcmp(*args, "-stream"))
189: indef = 1;
190: else if (!strcmp(*args, "-indef"))
191: indef = 1;
192: else if (!strcmp(*args, "-noindef"))
193: indef = 0;
194: else if (!strcmp(*args, "-nooldmime"))
195: flags |= PKCS7_NOOLDMIMETYPE;
196: else if (!strcmp(*args, "-crlfeol"))
197: flags |= PKCS7_CRLFEOL;
198: else if (!strcmp(*args, "-passin")) {
199: if (!args[1])
200: goto argerr;
201: passargin = *++args;
202: } else if (!strcmp(*args, "-to")) {
203: if (!args[1])
204: goto argerr;
205: to = *++args;
206: } else if (!strcmp(*args, "-from")) {
207: if (!args[1])
208: goto argerr;
209: from = *++args;
210: } else if (!strcmp(*args, "-subject")) {
211: if (!args[1])
212: goto argerr;
213: subject = *++args;
214: } else if (!strcmp(*args, "-signer")) {
215: if (!args[1])
216: goto argerr;
217: /* If previous -signer argument add signer to list */
218:
219: if (signerfile) {
220: if (!sksigners)
221: sksigners = sk_OPENSSL_STRING_new_null();
222: sk_OPENSSL_STRING_push(sksigners, signerfile);
223: if (!keyfile)
224: keyfile = signerfile;
225: if (!skkeys)
226: skkeys = sk_OPENSSL_STRING_new_null();
227: sk_OPENSSL_STRING_push(skkeys, keyfile);
228: keyfile = NULL;
229: }
230: signerfile = *++args;
231: } else if (!strcmp(*args, "-recip")) {
232: if (!args[1])
233: goto argerr;
234: recipfile = *++args;
235: } else if (!strcmp(*args, "-md")) {
236: if (!args[1])
237: goto argerr;
238: sign_md = EVP_get_digestbyname(*++args);
239: if (sign_md == NULL) {
240: BIO_printf(bio_err, "Unknown digest %s\n",
241: *args);
242: goto argerr;
243: }
244: } else if (!strcmp(*args, "-inkey")) {
245: if (!args[1])
246: goto argerr;
247: /* If previous -inkey arument add signer to list */
248: if (keyfile) {
249: if (!signerfile) {
250: BIO_puts(bio_err, "Illegal -inkey without -signer\n");
251: goto argerr;
252: }
253: if (!sksigners)
254: sksigners = sk_OPENSSL_STRING_new_null();
255: sk_OPENSSL_STRING_push(sksigners, signerfile);
256: signerfile = NULL;
257: if (!skkeys)
258: skkeys = sk_OPENSSL_STRING_new_null();
259: sk_OPENSSL_STRING_push(skkeys, keyfile);
260: }
261: keyfile = *++args;
262: } else if (!strcmp(*args, "-keyform")) {
263: if (!args[1])
264: goto argerr;
265: keyform = str2fmt(*++args);
266: } else if (!strcmp(*args, "-certfile")) {
267: if (!args[1])
268: goto argerr;
269: certfile = *++args;
270: } else if (!strcmp(*args, "-CAfile")) {
271: if (!args[1])
272: goto argerr;
273: CAfile = *++args;
274: } else if (!strcmp(*args, "-CApath")) {
275: if (!args[1])
276: goto argerr;
277: CApath = *++args;
278: } else if (!strcmp(*args, "-in")) {
279: if (!args[1])
280: goto argerr;
281: infile = *++args;
282: } else if (!strcmp(*args, "-inform")) {
283: if (!args[1])
284: goto argerr;
285: informat = str2fmt(*++args);
286: } else if (!strcmp(*args, "-outform")) {
287: if (!args[1])
288: goto argerr;
289: outformat = str2fmt(*++args);
290: } else if (!strcmp(*args, "-out")) {
291: if (!args[1])
292: goto argerr;
293: outfile = *++args;
294: } else if (!strcmp(*args, "-content")) {
295: if (!args[1])
296: goto argerr;
297: contfile = *++args;
298: } else if (args_verify(&args, NULL, &badarg, bio_err, &vpm))
299: continue;
300: else if ((cipher = EVP_get_cipherbyname(*args + 1)) == NULL)
301: badarg = 1;
302: args++;
303: }
304:
305: if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners)) {
306: BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
307: goto argerr;
308: }
309: if (operation & SMIME_SIGNERS) {
310: /* Check to see if any final signer needs to be appended */
311: if (keyfile && !signerfile) {
312: BIO_puts(bio_err, "Illegal -inkey without -signer\n");
313: goto argerr;
314: }
315: if (signerfile) {
316: if (!sksigners)
317: sksigners = sk_OPENSSL_STRING_new_null();
318: sk_OPENSSL_STRING_push(sksigners, signerfile);
319: if (!skkeys)
320: skkeys = sk_OPENSSL_STRING_new_null();
321: if (!keyfile)
322: keyfile = signerfile;
323: sk_OPENSSL_STRING_push(skkeys, keyfile);
324: }
325: if (!sksigners) {
326: BIO_printf(bio_err, "No signer certificate specified\n");
327: badarg = 1;
328: }
329: signerfile = NULL;
330: keyfile = NULL;
331: } else if (operation == SMIME_DECRYPT) {
332: if (!recipfile && !keyfile) {
333: BIO_printf(bio_err, "No recipient certificate or key specified\n");
334: badarg = 1;
335: }
336: } else if (operation == SMIME_ENCRYPT) {
337: if (!*args) {
338: BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
339: badarg = 1;
340: }
341: } else if (!operation)
342: badarg = 1;
343:
344: if (badarg) {
345: argerr:
346: BIO_printf(bio_err, "Usage smime [options] cert.pem ...\n");
347: BIO_printf(bio_err, "where options are\n");
348: BIO_printf(bio_err, "-encrypt encrypt message\n");
349: BIO_printf(bio_err, "-decrypt decrypt encrypted message\n");
350: BIO_printf(bio_err, "-sign sign message\n");
351: BIO_printf(bio_err, "-verify verify signed message\n");
352: BIO_printf(bio_err, "-pk7out output PKCS#7 structure\n");
353: #ifndef OPENSSL_NO_DES
354: BIO_printf(bio_err, "-des3 encrypt with triple DES\n");
355: BIO_printf(bio_err, "-des encrypt with DES\n");
356: #endif
357: #ifndef OPENSSL_NO_RC2
358: BIO_printf(bio_err, "-rc2-40 encrypt with RC2-40 (default)\n");
359: BIO_printf(bio_err, "-rc2-64 encrypt with RC2-64\n");
360: BIO_printf(bio_err, "-rc2-128 encrypt with RC2-128\n");
361: #endif
362: #ifndef OPENSSL_NO_AES
363: BIO_printf(bio_err, "-aes128, -aes192, -aes256\n");
364: BIO_printf(bio_err, " encrypt PEM output with cbc aes\n");
365: #endif
366: #ifndef OPENSSL_NO_CAMELLIA
367: BIO_printf(bio_err, "-camellia128, -camellia192, -camellia256\n");
368: BIO_printf(bio_err, " encrypt PEM output with cbc camellia\n");
369: #endif
370: BIO_printf(bio_err, "-nointern don't search certificates in message for signer\n");
371: BIO_printf(bio_err, "-nosigs don't verify message signature\n");
372: BIO_printf(bio_err, "-noverify don't verify signers certificate\n");
373: BIO_printf(bio_err, "-nocerts don't include signers certificate when signing\n");
374: BIO_printf(bio_err, "-nodetach use opaque signing\n");
375: BIO_printf(bio_err, "-noattr don't include any signed attributes\n");
376: BIO_printf(bio_err, "-binary don't translate message to text\n");
377: BIO_printf(bio_err, "-certfile file other certificates file\n");
378: BIO_printf(bio_err, "-signer file signer certificate file\n");
379: BIO_printf(bio_err, "-recip file recipient certificate file for decryption\n");
380: BIO_printf(bio_err, "-in file input file\n");
381: BIO_printf(bio_err, "-inform arg input format SMIME (default), PEM or DER\n");
382: BIO_printf(bio_err, "-inkey file input private key (if not signer or recipient)\n");
1.4 bcook 383: BIO_printf(bio_err, "-keyform arg input private key format (PEM)\n");
1.1 jsing 384: BIO_printf(bio_err, "-out file output file\n");
385: BIO_printf(bio_err, "-outform arg output format SMIME (default), PEM or DER\n");
386: BIO_printf(bio_err, "-content file supply or override content for detached signature\n");
387: BIO_printf(bio_err, "-to addr to address\n");
388: BIO_printf(bio_err, "-from ad from address\n");
389: BIO_printf(bio_err, "-subject s subject\n");
390: BIO_printf(bio_err, "-text include or delete text MIME headers\n");
391: BIO_printf(bio_err, "-CApath dir trusted certificates directory\n");
392: BIO_printf(bio_err, "-CAfile file trusted certificates file\n");
393: BIO_printf(bio_err, "-crl_check check revocation status of signer's certificate using CRLs\n");
394: BIO_printf(bio_err, "-crl_check_all check revocation status of signer's certificate chain using CRLs\n");
395: BIO_printf(bio_err, "-passin arg input file pass phrase source\n");
396: BIO_printf(bio_err, "cert.pem recipient certificate(s) for encryption\n");
397: goto end;
398: }
399:
400: if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
401: BIO_printf(bio_err, "Error getting password\n");
402: goto end;
403: }
404: ret = 2;
405:
406: if (!(operation & SMIME_SIGNERS))
407: flags &= ~PKCS7_DETACHED;
408:
409: if (operation & SMIME_OP) {
410: if (outformat == FORMAT_ASN1)
411: outmode = "wb";
412: } else {
413: if (flags & PKCS7_BINARY)
414: outmode = "wb";
415: }
416:
417: if (operation & SMIME_IP) {
418: if (informat == FORMAT_ASN1)
419: inmode = "rb";
420: } else {
421: if (flags & PKCS7_BINARY)
422: inmode = "rb";
423: }
424:
425: if (operation == SMIME_ENCRYPT) {
426: if (!cipher) {
427: #ifndef OPENSSL_NO_RC2
428: cipher = EVP_rc2_40_cbc();
429: #else
430: BIO_printf(bio_err, "No cipher selected\n");
431: goto end;
432: #endif
433: }
434: encerts = sk_X509_new_null();
435: while (*args) {
436: if (!(cert = load_cert(bio_err, *args, FORMAT_PEM,
1.4 bcook 437: NULL, "recipient certificate file"))) {
1.1 jsing 438: goto end;
439: }
440: sk_X509_push(encerts, cert);
441: cert = NULL;
442: args++;
443: }
444: }
445: if (certfile) {
446: if (!(other = load_certs(bio_err, certfile, FORMAT_PEM, NULL,
1.4 bcook 447: "certificate file"))) {
1.1 jsing 448: ERR_print_errors(bio_err);
449: goto end;
450: }
451: }
452: if (recipfile && (operation == SMIME_DECRYPT)) {
453: if (!(recip = load_cert(bio_err, recipfile, FORMAT_PEM, NULL,
1.4 bcook 454: "recipient certificate file"))) {
1.1 jsing 455: ERR_print_errors(bio_err);
456: goto end;
457: }
458: }
459: if (operation == SMIME_DECRYPT) {
460: if (!keyfile)
461: keyfile = recipfile;
462: } else if (operation == SMIME_SIGN) {
463: if (!keyfile)
464: keyfile = signerfile;
465: } else
466: keyfile = NULL;
467:
468: if (keyfile) {
1.4 bcook 469: key = load_key(bio_err, keyfile, keyform, 0, passin,
1.1 jsing 470: "signing key file");
471: if (!key)
472: goto end;
473: }
474: if (infile) {
475: if (!(in = BIO_new_file(infile, inmode))) {
476: BIO_printf(bio_err,
477: "Can't open input file %s\n", infile);
478: goto end;
479: }
480: } else
481: in = BIO_new_fp(stdin, BIO_NOCLOSE);
482:
483: if (operation & SMIME_IP) {
484: if (informat == FORMAT_SMIME)
485: p7 = SMIME_read_PKCS7(in, &indata);
486: else if (informat == FORMAT_PEM)
487: p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
488: else if (informat == FORMAT_ASN1)
489: p7 = d2i_PKCS7_bio(in, NULL);
490: else {
491: BIO_printf(bio_err, "Bad input format for PKCS#7 file\n");
492: goto end;
493: }
494:
495: if (!p7) {
496: BIO_printf(bio_err, "Error reading S/MIME message\n");
497: goto end;
498: }
499: if (contfile) {
500: BIO_free(indata);
501: if (!(indata = BIO_new_file(contfile, "rb"))) {
502: BIO_printf(bio_err, "Can't read content file %s\n", contfile);
503: goto end;
504: }
505: }
506: }
507: if (outfile) {
508: if (!(out = BIO_new_file(outfile, outmode))) {
509: BIO_printf(bio_err,
510: "Can't open output file %s\n", outfile);
511: goto end;
512: }
513: } else {
514: out = BIO_new_fp(stdout, BIO_NOCLOSE);
515: }
516:
517: if (operation == SMIME_VERIFY) {
518: if (!(store = setup_verify(bio_err, CAfile, CApath)))
519: goto end;
520: X509_STORE_set_verify_cb(store, smime_cb);
521: if (vpm)
522: X509_STORE_set1_param(store, vpm);
523: }
524: ret = 3;
525:
526: if (operation == SMIME_ENCRYPT) {
527: if (indef)
528: flags |= PKCS7_STREAM;
529: p7 = PKCS7_encrypt(encerts, in, cipher, flags);
530: } else if (operation & SMIME_SIGNERS) {
531: int i;
532: /*
533: * If detached data content we only enable streaming if
534: * S/MIME output format.
535: */
536: if (operation == SMIME_SIGN) {
537: if (flags & PKCS7_DETACHED) {
538: if (outformat == FORMAT_SMIME)
539: flags |= PKCS7_STREAM;
540: } else if (indef)
541: flags |= PKCS7_STREAM;
542: flags |= PKCS7_PARTIAL;
543: p7 = PKCS7_sign(NULL, NULL, other, in, flags);
544: if (!p7)
545: goto end;
546: } else
547: flags |= PKCS7_REUSE_DIGEST;
548: for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) {
549: signerfile = sk_OPENSSL_STRING_value(sksigners, i);
550: keyfile = sk_OPENSSL_STRING_value(skkeys, i);
551: signer = load_cert(bio_err, signerfile, FORMAT_PEM, NULL,
1.4 bcook 552: "signer certificate");
1.1 jsing 553: if (!signer)
554: goto end;
1.4 bcook 555: key = load_key(bio_err, keyfile, keyform, 0, passin,
1.1 jsing 556: "signing key file");
557: if (!key)
558: goto end;
559: if (!PKCS7_sign_add_signer(p7, signer, key,
560: sign_md, flags))
561: goto end;
562: X509_free(signer);
563: signer = NULL;
564: EVP_PKEY_free(key);
565: key = NULL;
566: }
567: /* If not streaming or resigning finalize structure */
568: if ((operation == SMIME_SIGN) && !(flags & PKCS7_STREAM)) {
569: if (!PKCS7_final(p7, in, flags))
570: goto end;
571: }
572: }
573: if (!p7) {
574: BIO_printf(bio_err, "Error creating PKCS#7 structure\n");
575: goto end;
576: }
577: ret = 4;
578: if (operation == SMIME_DECRYPT) {
579: if (!PKCS7_decrypt(p7, key, recip, out, flags)) {
580: BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n");
581: goto end;
582: }
583: } else if (operation == SMIME_VERIFY) {
584: STACK_OF(X509) * signers;
585: if (PKCS7_verify(p7, other, store, indata, out, flags))
586: BIO_printf(bio_err, "Verification successful\n");
587: else {
588: BIO_printf(bio_err, "Verification failure\n");
589: goto end;
590: }
591: signers = PKCS7_get0_signers(p7, other, flags);
592: if (!save_certs(signerfile, signers)) {
593: BIO_printf(bio_err, "Error writing signers to %s\n",
594: signerfile);
595: ret = 5;
596: goto end;
597: }
598: sk_X509_free(signers);
599: } else if (operation == SMIME_PK7OUT)
600: PEM_write_bio_PKCS7(out, p7);
601: else {
602: if (to)
603: BIO_printf(out, "To: %s\n", to);
604: if (from)
605: BIO_printf(out, "From: %s\n", from);
606: if (subject)
607: BIO_printf(out, "Subject: %s\n", subject);
608: if (outformat == FORMAT_SMIME) {
609: if (operation == SMIME_RESIGN)
610: SMIME_write_PKCS7(out, p7, indata, flags);
611: else
612: SMIME_write_PKCS7(out, p7, in, flags);
613: } else if (outformat == FORMAT_PEM)
614: PEM_write_bio_PKCS7_stream(out, p7, in, flags);
615: else if (outformat == FORMAT_ASN1)
616: i2d_PKCS7_bio_stream(out, p7, in, flags);
617: else {
618: BIO_printf(bio_err, "Bad output format for PKCS#7 file\n");
619: goto end;
620: }
621: }
622: ret = 0;
623: end:
624: if (ret)
625: ERR_print_errors(bio_err);
626: sk_X509_pop_free(encerts, X509_free);
627: sk_X509_pop_free(other, X509_free);
1.9 ! jsing 628: X509_VERIFY_PARAM_free(vpm);
! 629: sk_OPENSSL_STRING_free(sksigners);
! 630: sk_OPENSSL_STRING_free(skkeys);
1.1 jsing 631: X509_STORE_free(store);
632: X509_free(cert);
633: X509_free(recip);
634: X509_free(signer);
635: EVP_PKEY_free(key);
636: PKCS7_free(p7);
637: BIO_free(in);
638: BIO_free(indata);
639: BIO_free_all(out);
640: free(passin);
641:
642: return (ret);
643: }
644:
645: static int
646: save_certs(char *signerfile, STACK_OF(X509) * signers)
647: {
648: int i;
649: BIO *tmp;
650: if (!signerfile)
651: return 1;
652: tmp = BIO_new_file(signerfile, "w");
653: if (!tmp)
654: return 0;
655: for (i = 0; i < sk_X509_num(signers); i++)
656: PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
657: BIO_free(tmp);
658: return 1;
659: }
660:
661:
662: /* Minimal callback just to output policy info (if any) */
663:
664: static int
665: smime_cb(int ok, X509_STORE_CTX * ctx)
666: {
667: int error;
668:
669: error = X509_STORE_CTX_get_error(ctx);
670:
671: if ((error != X509_V_ERR_NO_EXPLICIT_POLICY)
672: && ((error != X509_V_OK) || (ok != 2)))
673: return ok;
674:
675: policies_print(NULL, ctx);
676:
677: return ok;
678:
679: }