crl.c 10.9 KB
Newer Older
R
Rich Salz 已提交
1 2
/*
 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
3
 *
R
Rich Salz 已提交
4 5 6 7
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
8 9 10 11 12 13
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "apps.h"
14 15 16 17 18
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/pem.h>
19

20 21 22 23 24
typedef enum OPTION_choice {
    OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
    OPT_INFORM, OPT_IN, OPT_OUTFORM, OPT_OUT, OPT_KEYFORM, OPT_KEY,
    OPT_ISSUER, OPT_LASTUPDATE, OPT_NEXTUPDATE, OPT_FINGERPRINT,
    OPT_CRLNUMBER, OPT_BADSIG, OPT_GENDELTA, OPT_CAPATH, OPT_CAFILE,
25 26
    OPT_NOCAPATH, OPT_NOCAFILE, OPT_VERIFY, OPT_TEXT, OPT_HASH, OPT_HASH_OLD,
    OPT_NOOUT, OPT_NAMEOPT, OPT_MD
27
} OPTION_CHOICE;
28

29 30 31 32 33 34
OPTIONS crl_options[] = {
    {"help", OPT_HELP, '-', "Display this summary"},
    {"inform", OPT_INFORM, 'F', "Input format; default PEM"},
    {"in", OPT_IN, '<', "Input file - default stdin"},
    {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"},
    {"out", OPT_OUT, '>', "output file - default stdout"},
35 36
    {"keyform", OPT_KEYFORM, 'F', "Private key file format (PEM or ENGINE)"},
    {"key", OPT_KEY, '<', "CRL signing Private key to use"},
37 38 39 40 41 42
    {"issuer", OPT_ISSUER, '-', "Print issuer DN"},
    {"lastupdate", OPT_LASTUPDATE, '-', "Set lastUpdate field"},
    {"nextupdate", OPT_NEXTUPDATE, '-', "Set nextUpdate field"},
    {"noout", OPT_NOOUT, '-', "No CRL output"},
    {"fingerprint", OPT_FINGERPRINT, '-', "Print the crl fingerprint"},
    {"crlnumber", OPT_CRLNUMBER, '-', "Print CRL number"},
43
    {"badsig", OPT_BADSIG, '-', "Corrupt last byte of loaded CRL signature (for test)" },
44 45 46
    {"gendelta", OPT_GENDELTA, '<'},
    {"CApath", OPT_CAPATH, '/', "Verify CRL using certificates in dir"},
    {"CAfile", OPT_CAFILE, '<', "Verify CRL using certificates in file name"},
47 48 49 50
    {"no-CAfile", OPT_NOCAFILE, '-',
     "Do not load the default certificates file"},
    {"no-CApath", OPT_NOCAPATH, '-',
     "Do not load certificates from the default certificates directory"},
51
    {"verify", OPT_VERIFY, '-', "Verify CRL signature"},
52 53
    {"text", OPT_TEXT, '-', "Print out a text format version"},
    {"hash", OPT_HASH, '-', "Print hash value"},
54 55
    {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
    {"", 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 65 66
{
    X509_CRL *x = NULL;
    BIO *out = NULL;
    X509_STORE *store = NULL;
R
Rich Salz 已提交
67
    X509_STORE_CTX *ctx = NULL;
68
    X509_LOOKUP *lookup = NULL;
R
Rich Salz 已提交
69
    X509_OBJECT *xobj = NULL;
70
    EVP_PKEY *pkey;
71 72
    const EVP_MD *digest = EVP_sha1();
    unsigned long nmflag = 0;
73
    char nmflag_set = 0;
74 75 76
    char *infile = NULL, *outfile = NULL, *crldiff = NULL, *keyfile = NULL;
    char *CAfile = NULL, *CApath = NULL, *prog;
    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 83
#ifndef OPENSSL_NO_MD5
    int hash_old = 0;
84
#endif
85

86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
    prog = opt_init(argc, argv, crl_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(crl_options);
            ret = 0;
            goto end;
        case OPT_INFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
                goto opthelp;
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUTFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
                goto opthelp;
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_KEYFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat))
                goto opthelp;
            break;
        case OPT_KEY:
            keyfile = opt_arg();
            break;
        case OPT_GENDELTA:
            crldiff = opt_arg();
            break;
        case OPT_CAPATH:
            CApath = opt_arg();
124
            do_ver = 1;
125 126 127
            break;
        case OPT_CAFILE:
            CAfile = opt_arg();
128
            do_ver = 1;
129
            break;
130 131 132 133 134 135
        case OPT_NOCAPATH:
            noCApath =  1;
            break;
        case OPT_NOCAFILE:
            noCAfile =  1;
            break;
136
        case OPT_HASH_OLD:
137
#ifndef OPENSSL_NO_MD5
138
            hash_old = ++num;
139
#endif
140
            break;
141 142 143 144 145 146 147 148 149 150
        case OPT_VERIFY:
            do_ver = 1;
            break;
        case OPT_TEXT:
            text = 1;
            break;
        case OPT_HASH:
            hash = ++num;
            break;
        case OPT_ISSUER:
151
            issuer = ++num;
152 153
            break;
        case OPT_LASTUPDATE:
154
            lastupdate = ++num;
155 156
            break;
        case OPT_NEXTUPDATE:
157
            nextupdate = ++num;
158 159
            break;
        case OPT_NOOUT:
160
            noout = ++num;
161 162
            break;
        case OPT_FINGERPRINT:
163
            fingerprint = ++num;
164 165
            break;
        case OPT_CRLNUMBER:
166
            crlnumber = ++num;
167 168
            break;
        case OPT_BADSIG:
169 170
            badsig = 1;
            break;
171
        case OPT_NAMEOPT:
172
            nmflag_set = 1;
173 174 175 176 177 178
            if (!set_name_ex(&nmflag, opt_arg()))
                goto opthelp;
            break;
        case OPT_MD:
            if (!opt_md(opt_unknown(), &digest))
                goto opthelp;
179 180
        }
    }
181
    argc = opt_num_rest();
K
Kurt Roeckx 已提交
182 183
    if (argc != 0)
        goto opthelp;
184

185 186 187
    if (!nmflag_set)
        nmflag = XN_FLAG_ONELINE;

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 197
        if (lookup == NULL)
            goto end;
R
Rich Salz 已提交
198
        ctx = X509_STORE_CTX_new();
199
        if (ctx == NULL || !X509_STORE_CTX_init(ctx, store, NULL, NULL)) {
200 201 202
            BIO_printf(bio_err, "Error initialising X509 store\n");
            goto end;
        }
203

R
Rich Salz 已提交
204 205
        xobj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_X509,
                                                 X509_CRL_get_issuer(x));
R
Rich Salz 已提交
206
        if (xobj == NULL) {
207 208 209
            BIO_printf(bio_err, "Error getting CRL issuer certificate\n");
            goto end;
        }
R
Rich Salz 已提交
210 211
        pkey = X509_get_pubkey(X509_OBJECT_get0_X509(xobj));
        X509_OBJECT_free(xobj);
212 213 214 215 216
        if (!pkey) {
            BIO_printf(bio_err, "Error getting CRL issuer public key\n");
            goto end;
        }
        i = X509_CRL_verify(x, pkey);
R
Rich Salz 已提交
217
        EVP_PKEY_free(pkey);
218 219 220 221 222 223 224
        if (i < 0)
            goto end;
        if (i == 0)
            BIO_printf(bio_err, "verify failure\n");
        else
            BIO_printf(bio_err, "verify OK\n");
    }
225

226 227 228 229 230 231 232 233 234
    if (crldiff) {
        X509_CRL *newcrl, *delta;
        if (!keyfile) {
            BIO_puts(bio_err, "Missing CRL signing key\n");
            goto end;
        }
        newcrl = load_crl(crldiff, informat);
        if (!newcrl)
            goto end;
235
        pkey = load_key(keyfile, keyformat, 0, NULL, NULL, "CRL signing key");
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
        if (!pkey) {
            X509_CRL_free(newcrl);
            goto end;
        }
        delta = X509_CRL_diff(x, newcrl, pkey, digest, 0);
        X509_CRL_free(newcrl);
        EVP_PKEY_free(pkey);
        if (delta) {
            X509_CRL_free(x);
            x = delta;
        } else {
            BIO_puts(bio_err, "Error creating delta CRL\n");
            goto end;
        }
    }
251

D
Dr. Stephen Henson 已提交
252 253 254 255 256 257 258 259
    if (badsig) {
        ASN1_BIT_STRING *sig;

        X509_CRL_get0_signature(&sig, NULL, x);
        if (!corrupt_signature(sig))
            goto end;
    }

260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
    if (num) {
        for (i = 1; i <= num; i++) {
            if (issuer == i) {
                print_name(bio_out, "issuer=", X509_CRL_get_issuer(x),
                           nmflag);
            }
            if (crlnumber == i) {
                ASN1_INTEGER *crlnum;
                crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL);
                BIO_printf(bio_out, "crlNumber=");
                if (crlnum) {
                    i2a_ASN1_INTEGER(bio_out, crlnum);
                    ASN1_INTEGER_free(crlnum);
                } else
                    BIO_puts(bio_out, "<NONE>");
                BIO_printf(bio_out, "\n");
            }
            if (hash == i) {
                BIO_printf(bio_out, "%08lx\n",
                           X509_NAME_hash(X509_CRL_get_issuer(x)));
            }
281
#ifndef OPENSSL_NO_MD5
282 283 284 285
            if (hash_old == i) {
                BIO_printf(bio_out, "%08lx\n",
                           X509_NAME_hash_old(X509_CRL_get_issuer(x)));
            }
286
#endif
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
            if (lastupdate == i) {
                BIO_printf(bio_out, "lastUpdate=");
                ASN1_TIME_print(bio_out, X509_CRL_get_lastUpdate(x));
                BIO_printf(bio_out, "\n");
            }
            if (nextupdate == i) {
                BIO_printf(bio_out, "nextUpdate=");
                if (X509_CRL_get_nextUpdate(x))
                    ASN1_TIME_print(bio_out, X509_CRL_get_nextUpdate(x));
                else
                    BIO_printf(bio_out, "NONE");
                BIO_printf(bio_out, "\n");
            }
            if (fingerprint == i) {
                int j;
                unsigned int n;
                unsigned char md[EVP_MAX_MD_SIZE];
304

305 306 307 308 309 310 311 312 313 314 315 316 317
                if (!X509_CRL_digest(x, digest, md, &n)) {
                    BIO_printf(bio_err, "out of memory\n");
                    goto end;
                }
                BIO_printf(bio_out, "%s Fingerprint=",
                           OBJ_nid2sn(EVP_MD_type(digest)));
                for (j = 0; j < (int)n; j++) {
                    BIO_printf(bio_out, "%02X%c", md[j], (j + 1 == (int)n)
                               ? '\n' : ':');
                }
            }
        }
    }
318
    out = bio_open_default(outfile, 'w', outformat);
319
    if (out == NULL)
320
        goto end;
321

322 323
    if (text)
        X509_CRL_print(out, x);
324

325 326 327 328
    if (noout) {
        ret = 0;
        goto end;
    }
329

330 331
    if (outformat == FORMAT_ASN1)
        i = (int)i2d_X509_CRL_bio(out, x);
332
    else
333 334 335 336 337 338
        i = PEM_write_bio_X509_CRL(out, x);
    if (!i) {
        BIO_printf(bio_err, "unable to write CRL\n");
        goto end;
    }
    ret = 0;
339

340 341 342 343 344
 end:
    if (ret != 0)
        ERR_print_errors(bio_err);
    BIO_free_all(out);
    X509_CRL_free(x);
R
Rich Salz 已提交
345 346
    X509_STORE_CTX_free(ctx);
    X509_STORE_free(store);
347
    return (ret);
348
}