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, '<', "Other CRL to compare/diff to the Input one"}, 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 } 348