xref: /freebsd/crypto/openssl/apps/pkcs7.c (revision e6bfd18d21b225af6a0ed67ceeaf1293b7b9eba5)
1 /*
2  * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <time.h>
14 #include "apps.h"
15 #include "progs.h"
16 #include <openssl/err.h>
17 #include <openssl/objects.h>
18 #include <openssl/evp.h>
19 #include <openssl/x509.h>
20 #include <openssl/pkcs7.h>
21 #include <openssl/pem.h>
22 
23 typedef enum OPTION_choice {
24     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
25     OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOOUT,
26     OPT_TEXT, OPT_PRINT, OPT_PRINT_CERTS, OPT_ENGINE
27 } OPTION_CHOICE;
28 
29 const OPTIONS pkcs7_options[] = {
30     {"help", OPT_HELP, '-', "Display this summary"},
31     {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"},
32     {"in", OPT_IN, '<', "Input file"},
33     {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
34     {"out", OPT_OUT, '>', "Output file"},
35     {"noout", OPT_NOOUT, '-', "Don't output encoded data"},
36     {"text", OPT_TEXT, '-', "Print full details of certificates"},
37     {"print", OPT_PRINT, '-', "Print out all fields of the PKCS7 structure"},
38     {"print_certs", OPT_PRINT_CERTS, '-',
39      "Print_certs  print any certs or crl in the input"},
40 #ifndef OPENSSL_NO_ENGINE
41     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
42 #endif
43     {NULL}
44 };
45 
46 int pkcs7_main(int argc, char **argv)
47 {
48     ENGINE *e = NULL;
49     PKCS7 *p7 = NULL;
50     BIO *in = NULL, *out = NULL;
51     int informat = FORMAT_PEM, outformat = FORMAT_PEM;
52     char *infile = NULL, *outfile = NULL, *prog;
53     int i, print_certs = 0, text = 0, noout = 0, p7_print = 0, ret = 1;
54     OPTION_CHOICE o;
55 
56     prog = opt_init(argc, argv, pkcs7_options);
57     while ((o = opt_next()) != OPT_EOF) {
58         switch (o) {
59         case OPT_EOF:
60         case OPT_ERR:
61  opthelp:
62             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
63             goto end;
64         case OPT_HELP:
65             opt_help(pkcs7_options);
66             ret = 0;
67             goto end;
68         case OPT_INFORM:
69             if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
70                 goto opthelp;
71             break;
72         case OPT_OUTFORM:
73             if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
74                 goto opthelp;
75             break;
76         case OPT_IN:
77             infile = opt_arg();
78             break;
79         case OPT_OUT:
80             outfile = opt_arg();
81             break;
82         case OPT_NOOUT:
83             noout = 1;
84             break;
85         case OPT_TEXT:
86             text = 1;
87             break;
88         case OPT_PRINT:
89             p7_print = 1;
90             break;
91         case OPT_PRINT_CERTS:
92             print_certs = 1;
93             break;
94         case OPT_ENGINE:
95             e = setup_engine(opt_arg(), 0);
96             break;
97         }
98     }
99     argc = opt_num_rest();
100     if (argc != 0)
101         goto opthelp;
102 
103     in = bio_open_default(infile, 'r', informat);
104     if (in == NULL)
105         goto end;
106 
107     if (informat == FORMAT_ASN1)
108         p7 = d2i_PKCS7_bio(in, NULL);
109     else
110         p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
111     if (p7 == NULL) {
112         BIO_printf(bio_err, "unable to load PKCS7 object\n");
113         ERR_print_errors(bio_err);
114         goto end;
115     }
116 
117     out = bio_open_default(outfile, 'w', outformat);
118     if (out == NULL)
119         goto end;
120 
121     if (p7_print)
122         PKCS7_print_ctx(out, p7, 0, NULL);
123 
124     if (print_certs) {
125         STACK_OF(X509) *certs = NULL;
126         STACK_OF(X509_CRL) *crls = NULL;
127 
128         i = OBJ_obj2nid(p7->type);
129         switch (i) {
130         case NID_pkcs7_signed:
131             if (p7->d.sign != NULL) {
132                 certs = p7->d.sign->cert;
133                 crls = p7->d.sign->crl;
134             }
135             break;
136         case NID_pkcs7_signedAndEnveloped:
137             if (p7->d.signed_and_enveloped != NULL) {
138                 certs = p7->d.signed_and_enveloped->cert;
139                 crls = p7->d.signed_and_enveloped->crl;
140             }
141             break;
142         default:
143             break;
144         }
145 
146         if (certs != NULL) {
147             X509 *x;
148 
149             for (i = 0; i < sk_X509_num(certs); i++) {
150                 x = sk_X509_value(certs, i);
151                 if (text)
152                     X509_print(out, x);
153                 else
154                     dump_cert_text(out, x);
155 
156                 if (!noout)
157                     PEM_write_bio_X509(out, x);
158                 BIO_puts(out, "\n");
159             }
160         }
161         if (crls != NULL) {
162             X509_CRL *crl;
163 
164             for (i = 0; i < sk_X509_CRL_num(crls); i++) {
165                 crl = sk_X509_CRL_value(crls, i);
166 
167                 X509_CRL_print_ex(out, crl, get_nameopt());
168 
169                 if (!noout)
170                     PEM_write_bio_X509_CRL(out, crl);
171                 BIO_puts(out, "\n");
172             }
173         }
174 
175         ret = 0;
176         goto end;
177     }
178 
179     if (!noout) {
180         if (outformat == FORMAT_ASN1)
181             i = i2d_PKCS7_bio(out, p7);
182         else
183             i = PEM_write_bio_PKCS7(out, p7);
184 
185         if (!i) {
186             BIO_printf(bio_err, "unable to write pkcs7 object\n");
187             ERR_print_errors(bio_err);
188             goto end;
189         }
190     }
191     ret = 0;
192  end:
193     PKCS7_free(p7);
194     release_engine(e);
195     BIO_free(in);
196     BIO_free_all(out);
197     return ret;
198 }
199