pkcs7.c revision 296341
1194206Ssimon/* apps/pkcs7.c */
2160814Ssimon/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3160814Ssimon * All rights reserved.
4194206Ssimon *
5194206Ssimon * This package is an SSL implementation written
6194206Ssimon * by Eric Young (eay@cryptsoft.com).
7194206Ssimon * The implementation was written so as to conform with Netscapes SSL.
8194206Ssimon *
9194206Ssimon * This library is free for commercial and non-commercial use as long as
10194206Ssimon * the following conditions are aheared to.  The following conditions
11194206Ssimon * apply to all code found in this distribution, be it the RC4, RSA,
12194206Ssimon * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13194206Ssimon * included with this distribution is covered by the same copyright terms
14194206Ssimon * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15194206Ssimon *
16194206Ssimon * Copyright remains Eric Young's, and as such any Copyright notices in
17194206Ssimon * the code are not to be removed.
18194206Ssimon * If this package is used in a product, Eric Young should be given attribution
19194206Ssimon * as the author of the parts of the library used.
20194206Ssimon * This can be in the form of a textual message at program startup or
21194206Ssimon * in documentation (online or textual) provided with the package.
22194206Ssimon *
23194206Ssimon * Redistribution and use in source and binary forms, with or without
24194206Ssimon * modification, are permitted provided that the following conditions
25194206Ssimon * are met:
26194206Ssimon * 1. Redistributions of source code must retain the copyright
27194206Ssimon *    notice, this list of conditions and the following disclaimer.
28194206Ssimon * 2. Redistributions in binary form must reproduce the above copyright
29194206Ssimon *    notice, this list of conditions and the following disclaimer in the
30194206Ssimon *    documentation and/or other materials provided with the distribution.
31194206Ssimon * 3. All advertising materials mentioning features or use of this software
32194206Ssimon *    must display the following acknowledgement:
33194206Ssimon *    "This product includes cryptographic software written by
34194206Ssimon *     Eric Young (eay@cryptsoft.com)"
35194206Ssimon *    The word 'cryptographic' can be left out if the rouines from the library
36194206Ssimon *    being used are not cryptographic related :-).
37194206Ssimon * 4. If you include any Windows specific code (or a derivative thereof) from
38194206Ssimon *    the apps directory (application code) you must include an acknowledgement:
39194206Ssimon *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40194206Ssimon *
41194206Ssimon * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42194206Ssimon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43194206Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44194206Ssimon * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45160814Ssimon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46194206Ssimon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47160814Ssimon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49160814Ssimon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50160814Ssimon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51160814Ssimon * SUCH DAMAGE.
52194206Ssimon *
53160814Ssimon * The licence and distribution terms for any publically available version or
54160814Ssimon * derivative of this code cannot be changed.  i.e. this code cannot simply be
55160814Ssimon * copied and put under another distribution licence
56160814Ssimon * [including the GNU Public Licence.]
57160814Ssimon */
58194206Ssimon
59160814Ssimon#include <stdio.h>
60194206Ssimon#include <stdlib.h>
61194206Ssimon#include <string.h>
62160814Ssimon#include <time.h>
63194206Ssimon#include "apps.h"
64160814Ssimon#include <openssl/err.h>
65194206Ssimon#include <openssl/objects.h>
66194206Ssimon#include <openssl/evp.h>
67194206Ssimon#include <openssl/x509.h>
68194206Ssimon#include <openssl/pkcs7.h>
69194206Ssimon#include <openssl/pem.h>
70160814Ssimon
71160814Ssimon#undef PROG
72160814Ssimon#define PROG    pkcs7_main
73160814Ssimon
74160814Ssimon/*-
75160814Ssimon * -inform arg  - input format - default PEM (DER or PEM)
76160814Ssimon * -outform arg - output format - default PEM
77160814Ssimon * -in arg      - input file - default stdin
78160814Ssimon * -out arg     - output file - default stdout
79160814Ssimon * -print_certs
80160814Ssimon */
81160814Ssimon
82160814Ssimonint MAIN(int, char **);
83160814Ssimon
84194206Ssimonint MAIN(int argc, char **argv)
85194206Ssimon{
86194206Ssimon    PKCS7 *p7 = NULL;
87194206Ssimon    int i, badops = 0;
88194206Ssimon    BIO *in = NULL, *out = NULL;
89194206Ssimon    int informat, outformat;
90194206Ssimon    char *infile, *outfile, *prog;
91194206Ssimon    int print_certs = 0, text = 0, noout = 0, p7_print = 0;
92194206Ssimon    int ret = 1;
93160814Ssimon#ifndef OPENSSL_NO_ENGINE
94160814Ssimon    char *engine = NULL;
95160814Ssimon#endif
96194206Ssimon
97194206Ssimon    apps_startup();
98194206Ssimon
99194206Ssimon    if (bio_err == NULL)
100194206Ssimon        if ((bio_err = BIO_new(BIO_s_file())) != NULL)
101194206Ssimon            BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
102194206Ssimon
103194206Ssimon    if (!load_config(bio_err, NULL))
104194206Ssimon        goto end;
105194206Ssimon
106194206Ssimon    infile = NULL;
107194206Ssimon    outfile = NULL;
108194206Ssimon    informat = FORMAT_PEM;
109194206Ssimon    outformat = FORMAT_PEM;
110194206Ssimon
111194206Ssimon    prog = argv[0];
112194206Ssimon    argc--;
113194206Ssimon    argv++;
114194206Ssimon    while (argc >= 1) {
115194206Ssimon        if (strcmp(*argv, "-inform") == 0) {
116194206Ssimon            if (--argc < 1)
117194206Ssimon                goto bad;
118194206Ssimon            informat = str2fmt(*(++argv));
119194206Ssimon        } else if (strcmp(*argv, "-outform") == 0) {
120194206Ssimon            if (--argc < 1)
121194206Ssimon                goto bad;
122194206Ssimon            outformat = str2fmt(*(++argv));
123194206Ssimon        } else if (strcmp(*argv, "-in") == 0) {
124194206Ssimon            if (--argc < 1)
125194206Ssimon                goto bad;
126194206Ssimon            infile = *(++argv);
127194206Ssimon        } else if (strcmp(*argv, "-out") == 0) {
128194206Ssimon            if (--argc < 1)
129194206Ssimon                goto bad;
130160814Ssimon            outfile = *(++argv);
131194206Ssimon        } else if (strcmp(*argv, "-noout") == 0)
132194206Ssimon            noout = 1;
133160814Ssimon        else if (strcmp(*argv, "-text") == 0)
134238405Sjkim            text = 1;
135194206Ssimon        else if (strcmp(*argv, "-print") == 0)
136194206Ssimon            p7_print = 1;
137238405Sjkim        else if (strcmp(*argv, "-print_certs") == 0)
138194206Ssimon            print_certs = 1;
139194206Ssimon#ifndef OPENSSL_NO_ENGINE
140194206Ssimon        else if (strcmp(*argv, "-engine") == 0) {
141238405Sjkim            if (--argc < 1)
142194206Ssimon                goto bad;
143160814Ssimon            engine = *(++argv);
144160814Ssimon        }
145160814Ssimon#endif
146194206Ssimon        else {
147160814Ssimon            BIO_printf(bio_err, "unknown option %s\n", *argv);
148160814Ssimon            badops = 1;
149160814Ssimon            break;
150160814Ssimon        }
151160814Ssimon        argc--;
152160814Ssimon        argv++;
153160814Ssimon    }
154194206Ssimon
155160814Ssimon    if (badops) {
156160814Ssimon bad:
157160814Ssimon        BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog);
158160814Ssimon        BIO_printf(bio_err, "where options are\n");
159160814Ssimon        BIO_printf(bio_err, " -inform arg   input format - DER or PEM\n");
160160814Ssimon        BIO_printf(bio_err, " -outform arg  output format - DER or PEM\n");
161194206Ssimon        BIO_printf(bio_err, " -in arg       input file\n");
162160814Ssimon        BIO_printf(bio_err, " -out arg      output file\n");
163160814Ssimon        BIO_printf(bio_err,
164160814Ssimon                   " -print_certs  print any certs or crl in the input\n");
165160814Ssimon        BIO_printf(bio_err,
166160814Ssimon                   " -text         print full details of certificates\n");
167160814Ssimon        BIO_printf(bio_err, " -noout        don't output encoded data\n");
168160814Ssimon#ifndef OPENSSL_NO_ENGINE
169194206Ssimon        BIO_printf(bio_err,
170194206Ssimon                   " -engine e     use engine e, possibly a hardware device.\n");
171194206Ssimon#endif
172194206Ssimon        ret = 1;
173194206Ssimon        goto end;
174194206Ssimon    }
175194206Ssimon
176194206Ssimon    ERR_load_crypto_strings();
177194206Ssimon
178194206Ssimon#ifndef OPENSSL_NO_ENGINE
179194206Ssimon    setup_engine(bio_err, engine, 0);
180194206Ssimon#endif
181194206Ssimon
182194206Ssimon    in = BIO_new(BIO_s_file());
183194206Ssimon    out = BIO_new(BIO_s_file());
184160814Ssimon    if ((in == NULL) || (out == NULL)) {
185194206Ssimon        ERR_print_errors(bio_err);
186194206Ssimon        goto end;
187160814Ssimon    }
188160814Ssimon
189160814Ssimon    if (infile == NULL)
190194206Ssimon        BIO_set_fp(in, stdin, BIO_NOCLOSE);
191194206Ssimon    else {
192194206Ssimon        if (BIO_read_filename(in, infile) <= 0) {
193194206Ssimon            BIO_printf(bio_err, "unable to load input file\n");
194194206Ssimon            ERR_print_errors(bio_err);
195194206Ssimon            goto end;
196194206Ssimon        }
197194206Ssimon    }
198194206Ssimon
199194206Ssimon    if (informat == FORMAT_ASN1)
200194206Ssimon        p7 = d2i_PKCS7_bio(in, NULL);
201194206Ssimon    else if (informat == FORMAT_PEM)
202194206Ssimon        p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
203194206Ssimon    else {
204194206Ssimon        BIO_printf(bio_err, "bad input format specified for pkcs7 object\n");
205194206Ssimon        goto end;
206194206Ssimon    }
207194206Ssimon    if (p7 == NULL) {
208194206Ssimon        BIO_printf(bio_err, "unable to load PKCS7 object\n");
209194206Ssimon        ERR_print_errors(bio_err);
210194206Ssimon        goto end;
211194206Ssimon    }
212194206Ssimon
213194206Ssimon    if (outfile == NULL) {
214194206Ssimon        BIO_set_fp(out, stdout, BIO_NOCLOSE);
215276861Sjkim#ifdef OPENSSL_SYS_VMS
216194206Ssimon        {
217194206Ssimon            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
218194206Ssimon            out = BIO_push(tmpbio, out);
219194206Ssimon        }
220194206Ssimon#endif
221194206Ssimon    } else {
222160814Ssimon        if (BIO_write_filename(out, outfile) <= 0) {
223160814Ssimon            perror(outfile);
224194206Ssimon            goto end;
225194206Ssimon        }
226194206Ssimon    }
227160814Ssimon
228160814Ssimon    if (p7_print)
229160814Ssimon        PKCS7_print_ctx(out, p7, 0, NULL);
230160814Ssimon
231160814Ssimon    if (print_certs) {
232160814Ssimon        STACK_OF(X509) *certs = NULL;
233194206Ssimon        STACK_OF(X509_CRL) *crls = NULL;
234194206Ssimon
235194206Ssimon        i = OBJ_obj2nid(p7->type);
236160814Ssimon        switch (i) {
237160814Ssimon        case NID_pkcs7_signed:
238160814Ssimon            certs = p7->d.sign->cert;
239160814Ssimon            crls = p7->d.sign->crl;
240194206Ssimon            break;
241194206Ssimon        case NID_pkcs7_signedAndEnveloped:
242160814Ssimon            certs = p7->d.signed_and_enveloped->cert;
243160814Ssimon            crls = p7->d.signed_and_enveloped->crl;
244160814Ssimon            break;
245160814Ssimon        default:
246160814Ssimon            break;
247160814Ssimon        }
248194206Ssimon
249194206Ssimon        if (certs != NULL) {
250194206Ssimon            X509 *x;
251194206Ssimon
252160814Ssimon            for (i = 0; i < sk_X509_num(certs); i++) {
253160814Ssimon                x = sk_X509_value(certs, i);
254160814Ssimon                if (text)
255160814Ssimon                    X509_print(out, x);
256160814Ssimon                else
257160814Ssimon                    dump_cert_text(out, x);
258160814Ssimon
259160814Ssimon                if (!noout)
260160814Ssimon                    PEM_write_bio_X509(out, x);
261160814Ssimon                BIO_puts(out, "\n");
262160814Ssimon            }
263160814Ssimon        }
264160814Ssimon        if (crls != NULL) {
265160814Ssimon            X509_CRL *crl;
266160814Ssimon
267160814Ssimon            for (i = 0; i < sk_X509_CRL_num(crls); i++) {
268160814Ssimon                crl = sk_X509_CRL_value(crls, i);
269160814Ssimon
270160814Ssimon                X509_CRL_print(out, crl);
271160814Ssimon
272160814Ssimon                if (!noout)
273160814Ssimon                    PEM_write_bio_X509_CRL(out, crl);
274194206Ssimon                BIO_puts(out, "\n");
275194206Ssimon            }
276194206Ssimon        }
277194206Ssimon
278194206Ssimon        ret = 0;
279194206Ssimon        goto end;
280194206Ssimon    }
281194206Ssimon
282194206Ssimon    if (!noout) {
283194206Ssimon        if (outformat == FORMAT_ASN1)
284194206Ssimon            i = i2d_PKCS7_bio(out, p7);
285194206Ssimon        else if (outformat == FORMAT_PEM)
286160814Ssimon            i = PEM_write_bio_PKCS7(out, p7);
287160814Ssimon        else {
288160814Ssimon            BIO_printf(bio_err, "bad output format specified for outfile\n");
289160814Ssimon            goto end;
290160814Ssimon        }
291160814Ssimon
292194206Ssimon        if (!i) {
293160814Ssimon            BIO_printf(bio_err, "unable to write pkcs7 object\n");
294160814Ssimon            ERR_print_errors(bio_err);
295160814Ssimon            goto end;
296160814Ssimon        }
297160814Ssimon    }
298160814Ssimon    ret = 0;
299160814Ssimon end:
300160814Ssimon    if (p7 != NULL)
301194206Ssimon        PKCS7_free(p7);
302160814Ssimon    if (in != NULL)
303160814Ssimon        BIO_free(in);
304160814Ssimon    if (out != NULL)
305160814Ssimon        BIO_free_all(out);
306160814Ssimon    apps_shutdown();
307160814Ssimon    OPENSSL_EXIT(ret);
308160814Ssimon}
309194206Ssimon