1 /* $OpenBSD: crl.c,v 1.11 2018/02/07 05:47:55 jsing Exp $ */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to. The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
26 * 1. Redistributions of source code must retain the copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 * must display the following acknowledgement:
33 * "This product includes cryptographic software written by
34 * Eric Young (eay@cryptsoft.com)"
35 * The word 'cryptographic' can be left out if the rouines from the library
36 * being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 * the apps directory (application code) you must include an acknowledgement:
39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed. i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
65 #include <openssl/bio.h>
66 #include <openssl/err.h>
67 #include <openssl/pem.h>
68 #include <openssl/x509.h>
69 #include <openssl/x509v3.h>
91 static struct option crl_options
[] = {
95 .desc
= "Verify the CRL using certificates in the given file",
97 .opt
.arg
= &crl_config
.cafile
,
102 .desc
= "Verify the CRL using certificates in the given path",
104 .opt
.arg
= &crl_config
.capath
,
108 .desc
= "Print the CRL number",
109 .type
= OPTION_FLAG_ORD
,
110 .opt
.flag
= &crl_config
.crlnumber
,
113 .name
= "fingerprint",
114 .desc
= "Print the CRL fingerprint",
115 .type
= OPTION_FLAG_ORD
,
116 .opt
.flag
= &crl_config
.fingerprint
,
120 .desc
= "Print the hash of the issuer name",
121 .type
= OPTION_FLAG_ORD
,
122 .opt
.flag
= &crl_config
.hash
,
126 .desc
= "Print an old-style (MD5) hash of the issuer name",
127 .type
= OPTION_FLAG_ORD
,
128 .opt
.flag
= &crl_config
.hash_old
,
133 .desc
= "Input file to read from (stdin if unspecified)",
135 .opt
.arg
= &crl_config
.infile
,
140 .desc
= "Input format (DER or PEM)",
141 .type
= OPTION_ARG_FORMAT
,
142 .opt
.value
= &crl_config
.informat
,
146 .desc
= "Print the issuer name",
147 .type
= OPTION_FLAG_ORD
,
148 .opt
.flag
= &crl_config
.issuer
,
151 .name
= "lastupdate",
152 .desc
= "Print the lastUpdate field",
153 .type
= OPTION_FLAG_ORD
,
154 .opt
.flag
= &crl_config
.lastupdate
,
158 .argname
= "options",
159 .desc
= "Specify certificate name options",
161 .opt
.arg
= &crl_config
.nameopt
,
164 .name
= "nextupdate",
165 .desc
= "Print the nextUpdate field",
166 .type
= OPTION_FLAG_ORD
,
167 .opt
.flag
= &crl_config
.nextupdate
,
171 .desc
= "Do not output the encoded version of the CRL",
173 .opt
.flag
= &crl_config
.noout
,
178 .desc
= "Output file to write to (stdout if unspecified)",
180 .opt
.arg
= &crl_config
.outfile
,
185 .desc
= "Output format (DER or PEM)",
186 .type
= OPTION_ARG_FORMAT
,
187 .opt
.value
= &crl_config
.outformat
,
191 .desc
= "Print out the CRL in text form",
193 .opt
.flag
= &crl_config
.text
,
197 .desc
= "Verify the signature on the CRL",
199 .opt
.flag
= &crl_config
.verify
,
208 "usage: crl [-CAfile file] [-CApath dir] [-fingerprint] [-hash]\n"
209 " [-in file] [-inform DER | PEM] [-issuer] [-lastupdate]\n"
210 " [-nextupdate] [-noout] [-out file] [-outform DER | PEM]\n"
212 options_usage(crl_options
);
215 static X509_CRL
*load_crl(char *file
, int format
);
216 static BIO
*bio_out
= NULL
;
219 crl_main(int argc
, char **argv
)
221 unsigned long nmflag
= 0;
225 X509_STORE
*store
= NULL
;
227 X509_LOOKUP
*lookup
= NULL
;
230 const EVP_MD
*digest
;
231 char *digest_name
= NULL
;
233 if (single_execution
) {
234 if (pledge("stdio cpath wpath rpath", NULL
) == -1) {
240 if (bio_out
== NULL
) {
241 if ((bio_out
= BIO_new(BIO_s_file())) != NULL
) {
242 BIO_set_fp(bio_out
, stdout
, BIO_NOCLOSE
);
248 memset(&crl_config
, 0, sizeof(crl_config
));
249 crl_config
.informat
= FORMAT_PEM
;
250 crl_config
.outformat
= FORMAT_PEM
;
252 if (options_parse(argc
, argv
, crl_options
, &digest_name
, NULL
) != 0) {
257 if (crl_config
.cafile
!= NULL
|| crl_config
.capath
!= NULL
)
258 crl_config
.verify
= 1;
260 if (crl_config
.nameopt
!= NULL
) {
261 if (set_name_ex(&nmflag
, crl_config
.nameopt
) != 1) {
263 "Invalid -nameopt argument '%s'\n",
269 if (digest_name
!= NULL
) {
270 if ((digest
= EVP_get_digestbyname(digest_name
)) == NULL
) {
272 "Unknown message digest algorithm '%s'\n",
278 x
= load_crl(crl_config
.infile
, crl_config
.informat
);
282 if (crl_config
.verify
) {
283 store
= X509_STORE_new();
284 lookup
= X509_STORE_add_lookup(store
, X509_LOOKUP_file());
287 if (!X509_LOOKUP_load_file(lookup
, crl_config
.cafile
,
289 X509_LOOKUP_load_file(lookup
, NULL
,
290 X509_FILETYPE_DEFAULT
);
292 lookup
= X509_STORE_add_lookup(store
, X509_LOOKUP_hash_dir());
295 if (!X509_LOOKUP_add_dir(lookup
, crl_config
.capath
,
297 X509_LOOKUP_add_dir(lookup
, NULL
,
298 X509_FILETYPE_DEFAULT
);
301 if (!X509_STORE_CTX_init(&ctx
, store
, NULL
, NULL
)) {
303 "Error initialising X509 store\n");
306 i
= X509_STORE_get_by_subject(&ctx
, X509_LU_X509
,
307 X509_CRL_get_issuer(x
), &xobj
);
310 "Error getting CRL issuer certificate\n");
313 pkey
= X509_get_pubkey(xobj
.data
.x509
);
314 X509_OBJECT_free_contents(&xobj
);
317 "Error getting CRL issuer public key\n");
320 i
= X509_CRL_verify(x
, pkey
);
325 BIO_printf(bio_err
, "verify failure\n");
327 BIO_printf(bio_err
, "verify OK\n");
330 /* Print requested information the order that the flags were given. */
331 for (i
= 1; i
<= argc
; i
++) {
332 if (crl_config
.issuer
== i
) {
333 print_name(bio_out
, "issuer=",
334 X509_CRL_get_issuer(x
), nmflag
);
336 if (crl_config
.crlnumber
== i
) {
337 ASN1_INTEGER
*crlnum
;
338 crlnum
= X509_CRL_get_ext_d2i(x
,
339 NID_crl_number
, NULL
, NULL
);
340 BIO_printf(bio_out
, "crlNumber=");
342 i2a_ASN1_INTEGER(bio_out
, crlnum
);
343 ASN1_INTEGER_free(crlnum
);
345 BIO_puts(bio_out
, "<NONE>");
346 BIO_printf(bio_out
, "\n");
348 if (crl_config
.hash
== i
) {
349 BIO_printf(bio_out
, "%08lx\n",
350 X509_NAME_hash(X509_CRL_get_issuer(x
)));
352 #ifndef OPENSSL_NO_MD5
353 if (crl_config
.hash_old
== i
) {
354 BIO_printf(bio_out
, "%08lx\n",
355 X509_NAME_hash_old(X509_CRL_get_issuer(x
)));
358 if (crl_config
.lastupdate
== i
) {
359 BIO_printf(bio_out
, "lastUpdate=");
360 ASN1_TIME_print(bio_out
,
361 X509_CRL_get_lastUpdate(x
));
362 BIO_printf(bio_out
, "\n");
364 if (crl_config
.nextupdate
== i
) {
365 BIO_printf(bio_out
, "nextUpdate=");
366 if (X509_CRL_get_nextUpdate(x
))
367 ASN1_TIME_print(bio_out
,
368 X509_CRL_get_nextUpdate(x
));
370 BIO_printf(bio_out
, "NONE");
371 BIO_printf(bio_out
, "\n");
373 if (crl_config
.fingerprint
== i
) {
376 unsigned char md
[EVP_MAX_MD_SIZE
];
378 if (!X509_CRL_digest(x
, digest
, md
, &n
)) {
379 BIO_printf(bio_err
, "out of memory\n");
382 BIO_printf(bio_out
, "%s Fingerprint=",
383 OBJ_nid2sn(EVP_MD_type(digest
)));
384 for (j
= 0; j
< (int) n
; j
++) {
385 BIO_printf(bio_out
, "%02X%c", md
[j
],
386 (j
+ 1 == (int)n
) ? '\n' : ':');
391 out
= BIO_new(BIO_s_file());
393 ERR_print_errors(bio_err
);
396 if (crl_config
.outfile
== NULL
) {
397 BIO_set_fp(out
, stdout
, BIO_NOCLOSE
);
399 if (BIO_write_filename(out
, crl_config
.outfile
) <= 0) {
400 perror(crl_config
.outfile
);
406 X509_CRL_print(out
, x
);
408 if (crl_config
.noout
) {
412 if (crl_config
.outformat
== FORMAT_ASN1
)
413 i
= (int) i2d_X509_CRL_bio(out
, x
);
414 else if (crl_config
.outformat
== FORMAT_PEM
)
415 i
= PEM_write_bio_X509_CRL(out
, x
);
418 "bad output format specified for outfile\n");
422 BIO_printf(bio_err
, "unable to write CRL\n");
429 BIO_free_all(bio_out
);
433 X509_STORE_CTX_cleanup(&ctx
);
434 X509_STORE_free(store
);
441 load_crl(char *infile
, int format
)
446 in
= BIO_new(BIO_s_file());
448 ERR_print_errors(bio_err
);
452 BIO_set_fp(in
, stdin
, BIO_NOCLOSE
);
454 if (BIO_read_filename(in
, infile
) <= 0) {
459 if (format
== FORMAT_ASN1
)
460 x
= d2i_X509_CRL_bio(in
, NULL
);
461 else if (format
== FORMAT_PEM
)
462 x
= PEM_read_bio_X509_CRL(in
, NULL
, NULL
, NULL
);
465 "bad input format specified for input crl\n");
469 BIO_printf(bio_err
, "unable to load CRL\n");
470 ERR_print_errors(bio_err
);