xref: /openbsd-src/usr.bin/openssl/crl.c (revision e7718adaf9bdf5a32db0f291795197a85ccbb6ed)
1*e7718adaStb /* $OpenBSD: crl.c,v 1.17 2023/03/06 14:32:05 tb Exp $ */
2dab3f910Sjsing /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3dab3f910Sjsing  * All rights reserved.
4dab3f910Sjsing  *
5dab3f910Sjsing  * This package is an SSL implementation written
6dab3f910Sjsing  * by Eric Young (eay@cryptsoft.com).
7dab3f910Sjsing  * The implementation was written so as to conform with Netscapes SSL.
8dab3f910Sjsing  *
9dab3f910Sjsing  * This library is free for commercial and non-commercial use as long as
10dab3f910Sjsing  * the following conditions are aheared to.  The following conditions
11dab3f910Sjsing  * apply to all code found in this distribution, be it the RC4, RSA,
12dab3f910Sjsing  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13dab3f910Sjsing  * included with this distribution is covered by the same copyright terms
14dab3f910Sjsing  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15dab3f910Sjsing  *
16dab3f910Sjsing  * Copyright remains Eric Young's, and as such any Copyright notices in
17dab3f910Sjsing  * the code are not to be removed.
18dab3f910Sjsing  * If this package is used in a product, Eric Young should be given attribution
19dab3f910Sjsing  * as the author of the parts of the library used.
20dab3f910Sjsing  * This can be in the form of a textual message at program startup or
21dab3f910Sjsing  * in documentation (online or textual) provided with the package.
22dab3f910Sjsing  *
23dab3f910Sjsing  * Redistribution and use in source and binary forms, with or without
24dab3f910Sjsing  * modification, are permitted provided that the following conditions
25dab3f910Sjsing  * are met:
26dab3f910Sjsing  * 1. Redistributions of source code must retain the copyright
27dab3f910Sjsing  *    notice, this list of conditions and the following disclaimer.
28dab3f910Sjsing  * 2. Redistributions in binary form must reproduce the above copyright
29dab3f910Sjsing  *    notice, this list of conditions and the following disclaimer in the
30dab3f910Sjsing  *    documentation and/or other materials provided with the distribution.
31dab3f910Sjsing  * 3. All advertising materials mentioning features or use of this software
32dab3f910Sjsing  *    must display the following acknowledgement:
33dab3f910Sjsing  *    "This product includes cryptographic software written by
34dab3f910Sjsing  *     Eric Young (eay@cryptsoft.com)"
35dab3f910Sjsing  *    The word 'cryptographic' can be left out if the rouines from the library
36dab3f910Sjsing  *    being used are not cryptographic related :-).
37dab3f910Sjsing  * 4. If you include any Windows specific code (or a derivative thereof) from
38dab3f910Sjsing  *    the apps directory (application code) you must include an acknowledgement:
39dab3f910Sjsing  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40dab3f910Sjsing  *
41dab3f910Sjsing  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42dab3f910Sjsing  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43dab3f910Sjsing  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44dab3f910Sjsing  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45dab3f910Sjsing  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46dab3f910Sjsing  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47dab3f910Sjsing  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48dab3f910Sjsing  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49dab3f910Sjsing  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50dab3f910Sjsing  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51dab3f910Sjsing  * SUCH DAMAGE.
52dab3f910Sjsing  *
53dab3f910Sjsing  * The licence and distribution terms for any publically available version or
54dab3f910Sjsing  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55dab3f910Sjsing  * copied and put under another distribution licence
56dab3f910Sjsing  * [including the GNU Public Licence.]
57dab3f910Sjsing  */
58dab3f910Sjsing 
59dab3f910Sjsing #include <stdio.h>
60dab3f910Sjsing #include <stdlib.h>
61dab3f910Sjsing #include <string.h>
62dab3f910Sjsing 
63dab3f910Sjsing #include "apps.h"
64dab3f910Sjsing 
65dab3f910Sjsing #include <openssl/bio.h>
66dab3f910Sjsing #include <openssl/err.h>
67dab3f910Sjsing #include <openssl/pem.h>
68dab3f910Sjsing #include <openssl/x509.h>
69dab3f910Sjsing #include <openssl/x509v3.h>
70dab3f910Sjsing 
71017236d2Sjsing static struct {
72017236d2Sjsing 	char *cafile;
73017236d2Sjsing 	char *capath;
74017236d2Sjsing 	int crlnumber;
75017236d2Sjsing 	int fingerprint;
76017236d2Sjsing 	int hash;
77017236d2Sjsing 	int hash_old;
78017236d2Sjsing 	char *infile;
79017236d2Sjsing 	int informat;
80017236d2Sjsing 	int issuer;
81017236d2Sjsing 	int lastupdate;
82017236d2Sjsing 	char *nameopt;
83017236d2Sjsing 	int nextupdate;
84017236d2Sjsing 	int noout;
85017236d2Sjsing 	char *outfile;
86017236d2Sjsing 	int outformat;
87017236d2Sjsing 	int text;
88017236d2Sjsing 	int verify;
89*e7718adaStb } cfg;
90017236d2Sjsing 
91ea149709Sguenther static const struct option crl_options[] = {
92017236d2Sjsing 	{
93017236d2Sjsing 		.name = "CAfile",
94017236d2Sjsing 		.argname = "file",
95017236d2Sjsing 		.desc = "Verify the CRL using certificates in the given file",
96017236d2Sjsing 		.type = OPTION_ARG,
97*e7718adaStb 		.opt.arg = &cfg.cafile,
98017236d2Sjsing 	},
99017236d2Sjsing 	{
100017236d2Sjsing 		.name = "CApath",
101017236d2Sjsing 		.argname = "path",
102017236d2Sjsing 		.desc = "Verify the CRL using certificates in the given path",
103017236d2Sjsing 		.type = OPTION_ARG,
104*e7718adaStb 		.opt.arg = &cfg.capath,
105017236d2Sjsing 	},
106017236d2Sjsing 	{
107017236d2Sjsing 		.name = "crlnumber",
108017236d2Sjsing 		.desc = "Print the CRL number",
109017236d2Sjsing 		.type = OPTION_FLAG_ORD,
110*e7718adaStb 		.opt.flag = &cfg.crlnumber,
111017236d2Sjsing 	},
112017236d2Sjsing 	{
113017236d2Sjsing 		.name = "fingerprint",
114017236d2Sjsing 		.desc = "Print the CRL fingerprint",
115017236d2Sjsing 		.type = OPTION_FLAG_ORD,
116*e7718adaStb 		.opt.flag = &cfg.fingerprint,
117017236d2Sjsing 	},
118017236d2Sjsing 	{
119017236d2Sjsing 		.name = "hash",
120017236d2Sjsing 		.desc = "Print the hash of the issuer name",
121017236d2Sjsing 		.type = OPTION_FLAG_ORD,
122*e7718adaStb 		.opt.flag = &cfg.hash,
123017236d2Sjsing 	},
124017236d2Sjsing 	{
125017236d2Sjsing 		.name = "hash_old",
126017236d2Sjsing 		.desc = "Print an old-style (MD5) hash of the issuer name",
127017236d2Sjsing 		.type = OPTION_FLAG_ORD,
128*e7718adaStb 		.opt.flag = &cfg.hash_old,
129017236d2Sjsing 	},
130017236d2Sjsing 	{
131017236d2Sjsing 		.name = "in",
132017236d2Sjsing 		.argname = "file",
133017236d2Sjsing 		.desc = "Input file to read from (stdin if unspecified)",
134017236d2Sjsing 		.type = OPTION_ARG,
135*e7718adaStb 		.opt.arg = &cfg.infile,
136017236d2Sjsing 	},
137017236d2Sjsing 	{
138017236d2Sjsing 		.name = "inform",
139017236d2Sjsing 		.argname = "format",
140017236d2Sjsing 		.desc = "Input format (DER or PEM)",
141017236d2Sjsing 		.type = OPTION_ARG_FORMAT,
142*e7718adaStb 		.opt.value = &cfg.informat,
143017236d2Sjsing 	},
144017236d2Sjsing 	{
145017236d2Sjsing 		.name = "issuer",
146017236d2Sjsing 		.desc = "Print the issuer name",
147017236d2Sjsing 		.type = OPTION_FLAG_ORD,
148*e7718adaStb 		.opt.flag = &cfg.issuer,
149017236d2Sjsing 	},
150017236d2Sjsing 	{
151017236d2Sjsing 		.name = "lastupdate",
152017236d2Sjsing 		.desc = "Print the lastUpdate field",
153017236d2Sjsing 		.type = OPTION_FLAG_ORD,
154*e7718adaStb 		.opt.flag = &cfg.lastupdate,
155017236d2Sjsing 	},
156017236d2Sjsing 	{
157017236d2Sjsing 		.name = "nameopt",
158017236d2Sjsing 		.argname = "options",
159017236d2Sjsing 		.desc = "Specify certificate name options",
160017236d2Sjsing 		.type = OPTION_ARG,
161*e7718adaStb 		.opt.arg = &cfg.nameopt,
162017236d2Sjsing 	},
163017236d2Sjsing 	{
164017236d2Sjsing 		.name = "nextupdate",
165017236d2Sjsing 		.desc = "Print the nextUpdate field",
166017236d2Sjsing 		.type = OPTION_FLAG_ORD,
167*e7718adaStb 		.opt.flag = &cfg.nextupdate,
168017236d2Sjsing 	},
169017236d2Sjsing 	{
170017236d2Sjsing 		.name = "noout",
171017236d2Sjsing 		.desc = "Do not output the encoded version of the CRL",
172017236d2Sjsing 		.type = OPTION_FLAG,
173*e7718adaStb 		.opt.flag = &cfg.noout,
174017236d2Sjsing 	},
175017236d2Sjsing 	{
176017236d2Sjsing 		.name = "out",
177017236d2Sjsing 		.argname = "file",
178017236d2Sjsing 		.desc = "Output file to write to (stdout if unspecified)",
179017236d2Sjsing 		.type = OPTION_ARG,
180*e7718adaStb 		.opt.arg = &cfg.outfile,
181017236d2Sjsing 	},
182017236d2Sjsing 	{
183017236d2Sjsing 		.name = "outform",
184017236d2Sjsing 		.argname = "format",
185017236d2Sjsing 		.desc = "Output format (DER or PEM)",
186017236d2Sjsing 		.type = OPTION_ARG_FORMAT,
187*e7718adaStb 		.opt.value = &cfg.outformat,
188017236d2Sjsing 	},
189017236d2Sjsing 	{
190017236d2Sjsing 		.name = "text",
191017236d2Sjsing 		.desc = "Print out the CRL in text form",
192017236d2Sjsing 		.type = OPTION_FLAG,
193*e7718adaStb 		.opt.flag = &cfg.text,
194017236d2Sjsing 	},
195017236d2Sjsing 	{
196017236d2Sjsing 		.name = "verify",
197017236d2Sjsing 		.desc = "Verify the signature on the CRL",
198017236d2Sjsing 		.type = OPTION_FLAG,
199*e7718adaStb 		.opt.flag = &cfg.verify,
200017236d2Sjsing 	},
201d220e929Sbcook 	{NULL},
202dab3f910Sjsing };
203dab3f910Sjsing 
204017236d2Sjsing static void
crl_usage(void)205017236d2Sjsing crl_usage(void)
206017236d2Sjsing {
207017236d2Sjsing 	fprintf(stderr,
208017236d2Sjsing 	    "usage: crl [-CAfile file] [-CApath dir] [-fingerprint] [-hash]\n"
209017236d2Sjsing 	    "    [-in file] [-inform DER | PEM] [-issuer] [-lastupdate]\n"
210017236d2Sjsing 	    "    [-nextupdate] [-noout] [-out file] [-outform DER | PEM]\n"
211017236d2Sjsing 	    "    [-text]\n\n");
212017236d2Sjsing 	options_usage(crl_options);
213017236d2Sjsing }
214017236d2Sjsing 
215dab3f910Sjsing static X509_CRL *load_crl(char *file, int format);
216dab3f910Sjsing static BIO *bio_out = NULL;
217dab3f910Sjsing 
218dab3f910Sjsing int
crl_main(int argc,char ** argv)219dab3f910Sjsing crl_main(int argc, char **argv)
220dab3f910Sjsing {
221dab3f910Sjsing 	unsigned long nmflag = 0;
222dab3f910Sjsing 	X509_CRL *x = NULL;
223017236d2Sjsing 	int ret = 1, i;
224dab3f910Sjsing 	BIO *out = NULL;
225dab3f910Sjsing 	X509_STORE *store = NULL;
22673e19d3eStb 	X509_STORE_CTX *ctx = NULL;
227dab3f910Sjsing 	X509_LOOKUP *lookup = NULL;
2283d522683Stb 	X509_OBJECT *xobj = NULL;
229dab3f910Sjsing 	EVP_PKEY *pkey;
230017236d2Sjsing 	const EVP_MD *digest;
231017236d2Sjsing 	char *digest_name = NULL;
232dab3f910Sjsing 
23351811eadSderaadt 	if (pledge("stdio cpath wpath rpath", NULL) == -1) {
2349bc487adSdoug 		perror("pledge");
235e370f0eeSdoug 		exit(1);
236e370f0eeSdoug 	}
2379bc487adSdoug 
238017236d2Sjsing 	if (bio_out == NULL) {
239dab3f910Sjsing 		if ((bio_out = BIO_new(BIO_s_file())) != NULL) {
240dab3f910Sjsing 			BIO_set_fp(bio_out, stdout, BIO_NOCLOSE);
241dab3f910Sjsing 		}
242017236d2Sjsing 	}
243dab3f910Sjsing 
244020b59f8Sjsg 	digest = EVP_sha256();
245017236d2Sjsing 
246*e7718adaStb 	memset(&cfg, 0, sizeof(cfg));
247*e7718adaStb 	cfg.informat = FORMAT_PEM;
248*e7718adaStb 	cfg.outformat = FORMAT_PEM;
249017236d2Sjsing 
250beba0da1Sjsing 	if (options_parse(argc, argv, crl_options, &digest_name, NULL) != 0) {
251017236d2Sjsing 		crl_usage();
252017236d2Sjsing 		goto end;
253017236d2Sjsing 	}
254017236d2Sjsing 
255*e7718adaStb 	if (cfg.cafile != NULL || cfg.capath != NULL)
256*e7718adaStb 		cfg.verify = 1;
257017236d2Sjsing 
258*e7718adaStb 	if (cfg.nameopt != NULL) {
259*e7718adaStb 		if (set_name_ex(&nmflag, cfg.nameopt) != 1) {
260017236d2Sjsing 			fprintf(stderr,
261017236d2Sjsing 			    "Invalid -nameopt argument '%s'\n",
262*e7718adaStb 			    cfg.nameopt);
263dab3f910Sjsing 			goto end;
264dab3f910Sjsing 		}
265dab3f910Sjsing 	}
266dab3f910Sjsing 
267017236d2Sjsing 	if (digest_name != NULL) {
268017236d2Sjsing 		if ((digest = EVP_get_digestbyname(digest_name)) == NULL) {
269017236d2Sjsing 			fprintf(stderr,
270017236d2Sjsing 			    "Unknown message digest algorithm '%s'\n",
271017236d2Sjsing 			    digest_name);
272dab3f910Sjsing 			goto end;
273dab3f910Sjsing 		}
274017236d2Sjsing 	}
275017236d2Sjsing 
276*e7718adaStb 	x = load_crl(cfg.infile, cfg.informat);
277017236d2Sjsing 	if (x == NULL)
278dab3f910Sjsing 		goto end;
279017236d2Sjsing 
280*e7718adaStb 	if (cfg.verify) {
281dab3f910Sjsing 		store = X509_STORE_new();
28273e19d3eStb 		if (store == NULL)
28373e19d3eStb 			goto end;
284dab3f910Sjsing 		lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
285dab3f910Sjsing 		if (lookup == NULL)
286dab3f910Sjsing 			goto end;
287*e7718adaStb 		if (!X509_LOOKUP_load_file(lookup, cfg.cafile,
288017236d2Sjsing 		    X509_FILETYPE_PEM))
289dab3f910Sjsing 			X509_LOOKUP_load_file(lookup, NULL,
290dab3f910Sjsing 			    X509_FILETYPE_DEFAULT);
291dab3f910Sjsing 
292dab3f910Sjsing 		lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
293dab3f910Sjsing 		if (lookup == NULL)
294dab3f910Sjsing 			goto end;
295*e7718adaStb 		if (!X509_LOOKUP_add_dir(lookup, cfg.capath,
296017236d2Sjsing 		    X509_FILETYPE_PEM))
297dab3f910Sjsing 			X509_LOOKUP_add_dir(lookup, NULL,
298dab3f910Sjsing 			    X509_FILETYPE_DEFAULT);
299dab3f910Sjsing 		ERR_clear_error();
300dab3f910Sjsing 
30173e19d3eStb 		if ((ctx = X509_STORE_CTX_new()) == NULL)
30273e19d3eStb 			goto end;
3033d522683Stb 		if ((xobj = X509_OBJECT_new()) == NULL)
3043d522683Stb 			goto end;
30573e19d3eStb 
30673e19d3eStb 		if (!X509_STORE_CTX_init(ctx, store, NULL, NULL)) {
307dab3f910Sjsing 			BIO_printf(bio_err,
308dab3f910Sjsing 			    "Error initialising X509 store\n");
309dab3f910Sjsing 			goto end;
310dab3f910Sjsing 		}
31173e19d3eStb 		i = X509_STORE_get_by_subject(ctx, X509_LU_X509,
3123d522683Stb 		    X509_CRL_get_issuer(x), xobj);
313dab3f910Sjsing 		if (i <= 0) {
314dab3f910Sjsing 			BIO_printf(bio_err,
315dab3f910Sjsing 			    "Error getting CRL issuer certificate\n");
316dab3f910Sjsing 			goto end;
317dab3f910Sjsing 		}
3183d522683Stb 		pkey = X509_get_pubkey(X509_OBJECT_get0_X509(xobj));
3193d522683Stb 		X509_OBJECT_free(xobj);
3203d522683Stb 		xobj = NULL;
321dab3f910Sjsing 		if (!pkey) {
322dab3f910Sjsing 			BIO_printf(bio_err,
323dab3f910Sjsing 			    "Error getting CRL issuer public key\n");
324dab3f910Sjsing 			goto end;
325dab3f910Sjsing 		}
326dab3f910Sjsing 		i = X509_CRL_verify(x, pkey);
327dab3f910Sjsing 		EVP_PKEY_free(pkey);
328dab3f910Sjsing 		if (i < 0)
329dab3f910Sjsing 			goto end;
330dab3f910Sjsing 		if (i == 0)
331dab3f910Sjsing 			BIO_printf(bio_err, "verify failure\n");
332dab3f910Sjsing 		else
333dab3f910Sjsing 			BIO_printf(bio_err, "verify OK\n");
334dab3f910Sjsing 	}
335017236d2Sjsing 
336017236d2Sjsing 	/* Print requested information the order that the flags were given. */
337017236d2Sjsing 	for (i = 1; i <= argc; i++) {
338*e7718adaStb 		if (cfg.issuer == i) {
339dab3f910Sjsing 			print_name(bio_out, "issuer=",
340dab3f910Sjsing 			    X509_CRL_get_issuer(x), nmflag);
341dab3f910Sjsing 		}
342*e7718adaStb 		if (cfg.crlnumber == i) {
343dab3f910Sjsing 			ASN1_INTEGER *crlnum;
344dab3f910Sjsing 			crlnum = X509_CRL_get_ext_d2i(x,
345dab3f910Sjsing 			    NID_crl_number, NULL, NULL);
346dab3f910Sjsing 			BIO_printf(bio_out, "crlNumber=");
347dab3f910Sjsing 			if (crlnum) {
348dab3f910Sjsing 				i2a_ASN1_INTEGER(bio_out, crlnum);
349dab3f910Sjsing 				ASN1_INTEGER_free(crlnum);
350dab3f910Sjsing 			} else
351dab3f910Sjsing 				BIO_puts(bio_out, "<NONE>");
352dab3f910Sjsing 			BIO_printf(bio_out, "\n");
353dab3f910Sjsing 		}
354*e7718adaStb 		if (cfg.hash == i) {
355dab3f910Sjsing 			BIO_printf(bio_out, "%08lx\n",
356dab3f910Sjsing 			    X509_NAME_hash(X509_CRL_get_issuer(x)));
357dab3f910Sjsing 		}
358dab3f910Sjsing #ifndef OPENSSL_NO_MD5
359*e7718adaStb 		if (cfg.hash_old == i) {
360dab3f910Sjsing 			BIO_printf(bio_out, "%08lx\n",
361dab3f910Sjsing 			    X509_NAME_hash_old(X509_CRL_get_issuer(x)));
362dab3f910Sjsing 		}
363dab3f910Sjsing #endif
364*e7718adaStb 		if (cfg.lastupdate == i) {
365dab3f910Sjsing 			BIO_printf(bio_out, "lastUpdate=");
366dab3f910Sjsing 			ASN1_TIME_print(bio_out,
367dab3f910Sjsing 			    X509_CRL_get_lastUpdate(x));
368dab3f910Sjsing 			BIO_printf(bio_out, "\n");
369dab3f910Sjsing 		}
370*e7718adaStb 		if (cfg.nextupdate == i) {
371dab3f910Sjsing 			BIO_printf(bio_out, "nextUpdate=");
372dab3f910Sjsing 			if (X509_CRL_get_nextUpdate(x))
373dab3f910Sjsing 				ASN1_TIME_print(bio_out,
374dab3f910Sjsing 				    X509_CRL_get_nextUpdate(x));
375dab3f910Sjsing 			else
376dab3f910Sjsing 				BIO_printf(bio_out, "NONE");
377dab3f910Sjsing 			BIO_printf(bio_out, "\n");
378dab3f910Sjsing 		}
379*e7718adaStb 		if (cfg.fingerprint == i) {
380dab3f910Sjsing 			int j;
381dab3f910Sjsing 			unsigned int n;
382dab3f910Sjsing 			unsigned char md[EVP_MAX_MD_SIZE];
383dab3f910Sjsing 
384dab3f910Sjsing 			if (!X509_CRL_digest(x, digest, md, &n)) {
385dab3f910Sjsing 				BIO_printf(bio_err, "out of memory\n");
386dab3f910Sjsing 				goto end;
387dab3f910Sjsing 			}
388dab3f910Sjsing 			BIO_printf(bio_out, "%s Fingerprint=",
389dab3f910Sjsing 			    OBJ_nid2sn(EVP_MD_type(digest)));
390dab3f910Sjsing 			for (j = 0; j < (int) n; j++) {
391dab3f910Sjsing 				BIO_printf(bio_out, "%02X%c", md[j],
392dab3f910Sjsing 				    (j + 1 == (int)n) ? '\n' : ':');
393dab3f910Sjsing 			}
394dab3f910Sjsing 		}
395dab3f910Sjsing 	}
396017236d2Sjsing 
397dab3f910Sjsing 	out = BIO_new(BIO_s_file());
398dab3f910Sjsing 	if (out == NULL) {
399dab3f910Sjsing 		ERR_print_errors(bio_err);
400dab3f910Sjsing 		goto end;
401dab3f910Sjsing 	}
402*e7718adaStb 	if (cfg.outfile == NULL) {
403dab3f910Sjsing 		BIO_set_fp(out, stdout, BIO_NOCLOSE);
404dab3f910Sjsing 	} else {
405*e7718adaStb 		if (BIO_write_filename(out, cfg.outfile) <= 0) {
406*e7718adaStb 			perror(cfg.outfile);
407dab3f910Sjsing 			goto end;
408dab3f910Sjsing 		}
409dab3f910Sjsing 	}
410dab3f910Sjsing 
411*e7718adaStb 	if (cfg.text)
412dab3f910Sjsing 		X509_CRL_print(out, x);
413dab3f910Sjsing 
414*e7718adaStb 	if (cfg.noout) {
415dab3f910Sjsing 		ret = 0;
416dab3f910Sjsing 		goto end;
417dab3f910Sjsing 	}
418*e7718adaStb 	if (cfg.outformat == FORMAT_ASN1)
419dab3f910Sjsing 		i = (int) i2d_X509_CRL_bio(out, x);
420*e7718adaStb 	else if (cfg.outformat == FORMAT_PEM)
421dab3f910Sjsing 		i = PEM_write_bio_X509_CRL(out, x);
422dab3f910Sjsing 	else {
423dab3f910Sjsing 		BIO_printf(bio_err,
424dab3f910Sjsing 		    "bad output format specified for outfile\n");
425dab3f910Sjsing 		goto end;
426dab3f910Sjsing 	}
427dab3f910Sjsing 	if (!i) {
428dab3f910Sjsing 		BIO_printf(bio_err, "unable to write CRL\n");
429dab3f910Sjsing 		goto end;
430dab3f910Sjsing 	}
431dab3f910Sjsing 	ret = 0;
432dab3f910Sjsing 
433dab3f910Sjsing  end:
434dab3f910Sjsing 	BIO_free_all(out);
435dab3f910Sjsing 	BIO_free_all(bio_out);
436dab3f910Sjsing 	bio_out = NULL;
437dab3f910Sjsing 	X509_CRL_free(x);
43873e19d3eStb 	X509_STORE_CTX_free(ctx);
439dab3f910Sjsing 	X509_STORE_free(store);
4403d522683Stb 	X509_OBJECT_free(xobj);
441dab3f910Sjsing 
442dab3f910Sjsing 	return (ret);
443dab3f910Sjsing }
444dab3f910Sjsing 
445dab3f910Sjsing static X509_CRL *
load_crl(char * infile,int format)446dab3f910Sjsing load_crl(char *infile, int format)
447dab3f910Sjsing {
448dab3f910Sjsing 	X509_CRL *x = NULL;
449dab3f910Sjsing 	BIO *in = NULL;
450dab3f910Sjsing 
451dab3f910Sjsing 	in = BIO_new(BIO_s_file());
452dab3f910Sjsing 	if (in == NULL) {
453dab3f910Sjsing 		ERR_print_errors(bio_err);
454dab3f910Sjsing 		goto end;
455dab3f910Sjsing 	}
456dab3f910Sjsing 	if (infile == NULL)
457dab3f910Sjsing 		BIO_set_fp(in, stdin, BIO_NOCLOSE);
458dab3f910Sjsing 	else {
459dab3f910Sjsing 		if (BIO_read_filename(in, infile) <= 0) {
460dab3f910Sjsing 			perror(infile);
461dab3f910Sjsing 			goto end;
462dab3f910Sjsing 		}
463dab3f910Sjsing 	}
464dab3f910Sjsing 	if (format == FORMAT_ASN1)
465dab3f910Sjsing 		x = d2i_X509_CRL_bio(in, NULL);
466dab3f910Sjsing 	else if (format == FORMAT_PEM)
467dab3f910Sjsing 		x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
468dab3f910Sjsing 	else {
469dab3f910Sjsing 		BIO_printf(bio_err,
470dab3f910Sjsing 		    "bad input format specified for input crl\n");
471dab3f910Sjsing 		goto end;
472dab3f910Sjsing 	}
473dab3f910Sjsing 	if (x == NULL) {
474dab3f910Sjsing 		BIO_printf(bio_err, "unable to load CRL\n");
475dab3f910Sjsing 		ERR_print_errors(bio_err);
476dab3f910Sjsing 		goto end;
477dab3f910Sjsing 	}
478dab3f910Sjsing 
479dab3f910Sjsing  end:
480dab3f910Sjsing 	BIO_free(in);
481dab3f910Sjsing 	return (x);
482dab3f910Sjsing }
483