5e0fbe5899e6d50a730b302fd2dd74a9f5ead954
[openssl.git] / apps / crl.c
1 /*
2  * Copyright 1995-2016 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 "apps.h"
14 #include <openssl/bio.h>
15 #include <openssl/err.h>
16 #include <openssl/x509.h>
17 #include <openssl/x509v3.h>
18 #include <openssl/pem.h>
19
20 typedef enum OPTION_choice {
21     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
22     OPT_INFORM, OPT_IN, OPT_OUTFORM, OPT_OUT, OPT_KEYFORM, OPT_KEY,
23     OPT_ISSUER, OPT_LASTUPDATE, OPT_NEXTUPDATE, OPT_FINGERPRINT,
24     OPT_CRLNUMBER, OPT_BADSIG, OPT_GENDELTA, OPT_CAPATH, OPT_CAFILE,
25     OPT_NOCAPATH, OPT_NOCAFILE, OPT_VERIFY, OPT_TEXT, OPT_HASH, OPT_HASH_OLD,
26     OPT_NOOUT, OPT_NAMEOPT, OPT_MD
27 } OPTION_CHOICE;
28
29 OPTIONS crl_options[] = {
30     {"help", OPT_HELP, '-', "Display this summary"},
31     {"inform", OPT_INFORM, 'F', "Input format; default PEM"},
32     {"in", OPT_IN, '<', "Input file - default stdin"},
33     {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"},
34     {"out", OPT_OUT, '>', "output file - default stdout"},
35     {"keyform", OPT_KEYFORM, 'F', "Private key file format (PEM or ENGINE)"},
36     {"key", OPT_KEY, '<', "CRL signing Private key to use"},
37     {"issuer", OPT_ISSUER, '-', "Print issuer DN"},
38     {"lastupdate", OPT_LASTUPDATE, '-', "Set lastUpdate field"},
39     {"nextupdate", OPT_NEXTUPDATE, '-', "Set nextUpdate field"},
40     {"noout", OPT_NOOUT, '-', "No CRL output"},
41     {"fingerprint", OPT_FINGERPRINT, '-', "Print the crl fingerprint"},
42     {"crlnumber", OPT_CRLNUMBER, '-', "Print CRL number"},
43     {"badsig", OPT_BADSIG, '-', "Corrupt last byte of loaded CRL signature (for test)" },
44     {"gendelta", OPT_GENDELTA, '<'},
45     {"CApath", OPT_CAPATH, '/', "Verify CRL using certificates in dir"},
46     {"CAfile", OPT_CAFILE, '<', "Verify CRL using certificates in file name"},
47     {"no-CAfile", OPT_NOCAFILE, '-',
48      "Do not load the default certificates file"},
49     {"no-CApath", OPT_NOCAPATH, '-',
50      "Do not load certificates from the default certificates directory"},
51     {"verify", OPT_VERIFY, '-', "Verify CRL signature"},
52     {"text", OPT_TEXT, '-', "Print out a text format version"},
53     {"hash", OPT_HASH, '-', "Print hash value"},
54     {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
55     {"", OPT_MD, '-', "Any supported digest"},
56 #ifndef OPENSSL_NO_MD5
57     {"hash_old", OPT_HASH_OLD, '-', "Print old-style (MD5) hash value"},
58 #endif
59     {NULL}
60 };
61
62 int crl_main(int argc, char **argv)
63 {
64     X509_CRL *x = NULL;
65     BIO *out = NULL;
66     X509_STORE *store = NULL;
67     X509_STORE_CTX *ctx = NULL;
68     X509_LOOKUP *lookup = NULL;
69     X509_OBJECT *xobj = NULL;
70     EVP_PKEY *pkey;
71     const EVP_MD *digest = EVP_sha1();
72     unsigned long nmflag = 0;
73     char nmflag_set = 0;
74     char *infile = NULL, *outfile = NULL, *crldiff = NULL, *keyfile = NULL;
75     const char *CAfile = NULL, *CApath = NULL, *prog;
76     OPTION_CHOICE o;
77     int hash = 0, issuer = 0, lastupdate = 0, nextupdate = 0, noout = 0;
78     int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM;
79     int ret = 1, num = 0, badsig = 0, fingerprint = 0, crlnumber = 0;
80     int text = 0, do_ver = 0, noCAfile = 0, noCApath = 0;
81     int i;
82 #ifndef OPENSSL_NO_MD5
83     int hash_old = 0;
84 #endif
85
86     prog = opt_init(argc, argv, crl_options);
87     while ((o = opt_next()) != OPT_EOF) {
88         switch (o) {
89         case OPT_EOF:
90         case OPT_ERR:
91  opthelp:
92             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
93             goto end;
94         case OPT_HELP:
95             opt_help(crl_options);
96             ret = 0;
97             goto end;
98         case OPT_INFORM:
99             if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
100                 goto opthelp;
101             break;
102         case OPT_IN:
103             infile = opt_arg();
104             break;
105         case OPT_OUTFORM:
106             if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
107                 goto opthelp;
108             break;
109         case OPT_OUT:
110             outfile = opt_arg();
111             break;
112         case OPT_KEYFORM:
113             if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat))
114                 goto opthelp;
115             break;
116         case OPT_KEY:
117             keyfile = opt_arg();
118             break;
119         case OPT_GENDELTA:
120             crldiff = opt_arg();
121             break;
122         case OPT_CAPATH:
123             CApath = opt_arg();
124             do_ver = 1;
125             break;
126         case OPT_CAFILE:
127             CAfile = opt_arg();
128             do_ver = 1;
129             break;
130         case OPT_NOCAPATH:
131             noCApath =  1;
132             break;
133         case OPT_NOCAFILE:
134             noCAfile =  1;
135             break;
136         case OPT_HASH_OLD:
137 #ifndef OPENSSL_NO_MD5
138             hash_old = ++num;
139 #endif
140             break;
141         case OPT_VERIFY:
142             do_ver = 1;
143             break;
144         case OPT_TEXT:
145             text = 1;
146             break;
147         case OPT_HASH:
148             hash = ++num;
149             break;
150         case OPT_ISSUER:
151             issuer = ++num;
152             break;
153         case OPT_LASTUPDATE:
154             lastupdate = ++num;
155             break;
156         case OPT_NEXTUPDATE:
157             nextupdate = ++num;
158             break;
159         case OPT_NOOUT:
160             noout = ++num;
161             break;
162         case OPT_FINGERPRINT:
163             fingerprint = ++num;
164             break;
165         case OPT_CRLNUMBER:
166             crlnumber = ++num;
167             break;
168         case OPT_BADSIG:
169             badsig = 1;
170             break;
171         case OPT_NAMEOPT:
172             nmflag_set = 1;
173             if (!set_name_ex(&nmflag, opt_arg()))
174                 goto opthelp;
175             break;
176         case OPT_MD:
177             if (!opt_md(opt_unknown(), &digest))
178                 goto opthelp;
179         }
180     }
181     argc = opt_num_rest();
182     if (argc != 0)
183         goto opthelp;
184
185     if (!nmflag_set)
186         nmflag = XN_FLAG_ONELINE;
187
188     x = load_crl(infile, informat);
189     if (x == NULL)
190         goto end;
191
192     if (do_ver) {
193         if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
194             goto end;
195         lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
196         if (lookup == NULL)
197             goto end;
198         ctx = X509_STORE_CTX_new();
199         if (ctx == NULL || !X509_STORE_CTX_init(ctx, store, NULL, NULL)) {
200             BIO_printf(bio_err, "Error initialising X509 store\n");
201             goto end;
202         }
203
204         xobj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_X509,
205                                                  X509_CRL_get_issuer(x));
206         if (xobj == NULL) {
207             BIO_printf(bio_err, "Error getting CRL issuer certificate\n");
208             goto end;
209         }
210         pkey = X509_get_pubkey(X509_OBJECT_get0_X509(xobj));
211         X509_OBJECT_free(xobj);
212         if (!pkey) {
213             BIO_printf(bio_err, "Error getting CRL issuer public key\n");
214             goto end;
215         }
216         i = X509_CRL_verify(x, pkey);
217         EVP_PKEY_free(pkey);
218         if (i < 0)
219             goto end;
220         if (i == 0)
221             BIO_printf(bio_err, "verify failure\n");
222         else
223             BIO_printf(bio_err, "verify OK\n");
224     }
225
226     if (crldiff) {
227         X509_CRL *newcrl, *delta;
228         if (!keyfile) {
229             BIO_puts(bio_err, "Missing CRL signing key\n");
230             goto end;
231         }
232         newcrl = load_crl(crldiff, informat);
233         if (!newcrl)
234             goto end;
235         pkey = load_key(keyfile, keyformat, 0, NULL, NULL, "CRL signing key");
236         if (!pkey) {
237             X509_CRL_free(newcrl);
238             goto end;
239         }
240         delta = X509_CRL_diff(x, newcrl, pkey, digest, 0);
241         X509_CRL_free(newcrl);
242         EVP_PKEY_free(pkey);
243         if (delta) {
244             X509_CRL_free(x);
245             x = delta;
246         } else {
247             BIO_puts(bio_err, "Error creating delta CRL\n");
248             goto end;
249         }
250     }
251
252     if (badsig) {
253         const ASN1_BIT_STRING *sig;
254
255         X509_CRL_get0_signature(x, &sig, NULL);
256         corrupt_signature(sig);
257     }
258
259     if (num) {
260         for (i = 1; i <= num; i++) {
261             if (issuer == i) {
262                 print_name(bio_out, "issuer=", X509_CRL_get_issuer(x),
263                            nmflag);
264             }
265             if (crlnumber == i) {
266                 ASN1_INTEGER *crlnum;
267                 crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL);
268                 BIO_printf(bio_out, "crlNumber=");
269                 if (crlnum) {
270                     i2a_ASN1_INTEGER(bio_out, crlnum);
271                     ASN1_INTEGER_free(crlnum);
272                 } else
273                     BIO_puts(bio_out, "<NONE>");
274                 BIO_printf(bio_out, "\n");
275             }
276             if (hash == i) {
277                 BIO_printf(bio_out, "%08lx\n",
278                            X509_NAME_hash(X509_CRL_get_issuer(x)));
279             }
280 #ifndef OPENSSL_NO_MD5
281             if (hash_old == i) {
282                 BIO_printf(bio_out, "%08lx\n",
283                            X509_NAME_hash_old(X509_CRL_get_issuer(x)));
284             }
285 #endif
286             if (lastupdate == i) {
287                 BIO_printf(bio_out, "lastUpdate=");
288                 ASN1_TIME_print(bio_out, X509_CRL_get0_lastUpdate(x));
289                 BIO_printf(bio_out, "\n");
290             }
291             if (nextupdate == i) {
292                 BIO_printf(bio_out, "nextUpdate=");
293                 if (X509_CRL_get0_nextUpdate(x))
294                     ASN1_TIME_print(bio_out, X509_CRL_get0_nextUpdate(x));
295                 else
296                     BIO_printf(bio_out, "NONE");
297                 BIO_printf(bio_out, "\n");
298             }
299             if (fingerprint == i) {
300                 int j;
301                 unsigned int n;
302                 unsigned char md[EVP_MAX_MD_SIZE];
303
304                 if (!X509_CRL_digest(x, digest, md, &n)) {
305                     BIO_printf(bio_err, "out of memory\n");
306                     goto end;
307                 }
308                 BIO_printf(bio_out, "%s Fingerprint=",
309                            OBJ_nid2sn(EVP_MD_type(digest)));
310                 for (j = 0; j < (int)n; j++) {
311                     BIO_printf(bio_out, "%02X%c", md[j], (j + 1 == (int)n)
312                                ? '\n' : ':');
313                 }
314             }
315         }
316     }
317     out = bio_open_default(outfile, 'w', outformat);
318     if (out == NULL)
319         goto end;
320
321     if (text)
322         X509_CRL_print(out, x);
323
324     if (noout) {
325         ret = 0;
326         goto end;
327     }
328
329     if (outformat == FORMAT_ASN1)
330         i = (int)i2d_X509_CRL_bio(out, x);
331     else
332         i = PEM_write_bio_X509_CRL(out, x);
333     if (!i) {
334         BIO_printf(bio_err, "unable to write CRL\n");
335         goto end;
336     }
337     ret = 0;
338
339  end:
340     if (ret != 0)
341         ERR_print_errors(bio_err);
342     BIO_free_all(out);
343     X509_CRL_free(x);
344     X509_STORE_CTX_free(ctx);
345     X509_STORE_free(store);
346     return (ret);
347 }