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