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