x509.c 36.2 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 19 20 21 22
#include <openssl/bio.h>
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/objects.h>
#include <openssl/pem.h>
N
make  
Nils Larsch 已提交
23
#ifndef OPENSSL_NO_RSA
24
# include <openssl/rsa.h>
N
make  
Nils Larsch 已提交
25 26
#endif
#ifndef OPENSSL_NO_DSA
27
# include <openssl/dsa.h>
N
make  
Nils Larsch 已提交
28
#endif
29 30

#undef POSTFIX
31 32 33
#define POSTFIX ".srl"
#define DEF_DAYS        30

R
Rich Salz 已提交
34
static int callb(int ok, X509_STORE_CTX *ctx);
35 36 37 38 39 40
static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
                const EVP_MD *digest, CONF *conf, char *section);
static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
                        X509 *x, X509 *xca, EVP_PKEY *pkey,
                        STACK_OF(OPENSSL_STRING) *sigopts, char *serial,
                        int create, int days, int clrext, CONF *conf,
41
                        char *section, ASN1_INTEGER *sno, int reqfile);
42
static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70

typedef enum OPTION_choice {
    OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
    OPT_INFORM, OPT_OUTFORM, OPT_KEYFORM, OPT_REQ, OPT_CAFORM,
    OPT_CAKEYFORM, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE,
    OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_SIGNKEY, OPT_CA,
    OPT_CAKEY, OPT_CASERIAL, OPT_SET_SERIAL, OPT_FORCE_PUBKEY,
    OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_NAMEOPT,
    OPT_C, OPT_EMAIL, OPT_OCSP_URI, OPT_SERIAL, OPT_NEXT_SERIAL,
    OPT_MODULUS, OPT_PUBKEY, OPT_X509TOREQ, OPT_TEXT, OPT_HASH,
    OPT_ISSUER_HASH, OPT_SUBJECT, OPT_ISSUER, OPT_FINGERPRINT, OPT_DATES,
    OPT_PURPOSE, OPT_STARTDATE, OPT_ENDDATE, OPT_CHECKEND, OPT_CHECKHOST,
    OPT_CHECKEMAIL, OPT_CHECKIP, OPT_NOOUT, OPT_TRUSTOUT, OPT_CLRTRUST,
    OPT_CLRREJECT, OPT_ALIAS, OPT_CACREATESERIAL, OPT_CLREXT, OPT_OCSPID,
    OPT_SUBJECT_HASH_OLD,
    OPT_ISSUER_HASH_OLD,
    OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT
} OPTION_CHOICE;

OPTIONS x509_options[] = {
    {"help", OPT_HELP, '-', "Display this summary"},
    {"inform", OPT_INFORM, 'f',
     "Input format - default PEM (one of DER, NET or PEM)"},
    {"in", OPT_IN, '<', "Input file - default stdin"},
    {"outform", OPT_OUTFORM, 'f',
     "Output format - default PEM (one of DER, NET or PEM)"},
    {"out", OPT_OUT, '>', "Output file - default stdout"},
    {"keyform", OPT_KEYFORM, 'F', "Private key format - default PEM"},
71
    {"passin", OPT_PASSIN, 's', "Private key password/pass-phrase source"},
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
    {"serial", OPT_SERIAL, '-', "Print serial number value"},
    {"subject_hash", OPT_HASH, '-', "Print subject hash value"},
    {"issuer_hash", OPT_ISSUER_HASH, '-', "Print issuer hash value"},
    {"hash", OPT_HASH, '-', "Synonym for -subject_hash"},
    {"subject", OPT_SUBJECT, '-', "Print subject DN"},
    {"issuer", OPT_ISSUER, '-', "Print issuer DN"},
    {"email", OPT_EMAIL, '-', "Print email address(es)"},
    {"startdate", OPT_STARTDATE, '-', "Set notBefore field"},
    {"enddate", OPT_ENDDATE, '-', "Set notAfter field"},
    {"purpose", OPT_PURPOSE, '-', "Print out certificate purposes"},
    {"dates", OPT_DATES, '-', "Both Before and After dates"},
    {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"},
    {"pubkey", OPT_PUBKEY, '-', "Output the public key"},
    {"fingerprint", OPT_FINGERPRINT, '-',
     "Print the certificate fingerprint"},
    {"alias", OPT_ALIAS, '-', "Output certificate alias"},
    {"noout", OPT_NOOUT, '-', "No output, just status"},
    {"nocert", OPT_NOCERT, '-', "No certificate output"},
    {"ocspid", OPT_OCSPID, '-',
     "Print OCSP hash values for the subject name and public key"},
    {"ocsp_uri", OPT_OCSP_URI, '-', "Print OCSP Responder URL(s)"},
    {"trustout", OPT_TRUSTOUT, '-', "Output a trusted certificate"},
    {"clrtrust", OPT_CLRTRUST, '-', "Clear all trusted purposes"},
    {"clrext", OPT_CLREXT, '-', "Clear all rejected purposes"},
    {"addtrust", OPT_ADDTRUST, 's', "Trust certificate for a given purpose"},
    {"addreject", OPT_ADDREJECT, 's',
     "Reject certificate for a given purpose"},
    {"setalias", OPT_SETALIAS, 's', "Set certificate alias"},
    {"days", OPT_DAYS, 'n',
     "How long till expiry of a signed certificate - def 30 days"},
102
    {"checkend", OPT_CHECKEND, 'M',
103 104 105 106 107 108 109
     "Check whether the cert expires in the next arg seconds"},
    {OPT_MORE_STR, 1, 1, "Exit 1 if so, 0 if not"},
    {"signkey", OPT_SIGNKEY, '<', "Self sign cert with arg"},
    {"x509toreq", OPT_X509TOREQ, '-',
     "Output a certification request object"},
    {"req", OPT_REQ, '-', "Input is a certificate request, sign and output"},
    {"CA", OPT_CA, '<', "Set the CA certificate, must be PEM format"},
110
    {"CAkey", OPT_CAKEY, 's',
111 112 113
     "The CA key, must be PEM format; if not in CAfile"},
    {"CAcreateserial", OPT_CACREATESERIAL, '-',
     "Create serial number file if it does not exist"},
114
    {"CAserial", OPT_CASERIAL, 's', "Serial file"},
115 116 117 118 119 120 121 122 123 124 125 126
    {"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"},
    {"text", OPT_TEXT, '-', "Print the certificate in text form"},
    {"C", OPT_C, '-', "Print out C code forms"},
    {"extfile", OPT_EXTFILE, '<', "File with X509V3 extensions to add"},
    {"extensions", OPT_EXTENSIONS, 's', "Section from config file to use"},
    {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
    {"certopt", OPT_CERTOPT, 's', "Various certificate text options"},
    {"checkhost", OPT_CHECKHOST, 's', "Check certificate matches host"},
    {"checkemail", OPT_CHECKEMAIL, 's', "Check certificate matches email"},
    {"checkip", OPT_CHECKIP, 's', "Check certificate matches ipaddr"},
    {"CAform", OPT_CAFORM, 'F', "CA format - default PEM"},
    {"CAkeyform", OPT_CAKEYFORM, 'F', "CA key format - default PEM"},
127
    {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
128 129 130
    {"force_pubkey", OPT_FORCE_PUBKEY, '<'},
    {"next_serial", OPT_NEXT_SERIAL, '-'},
    {"clrreject", OPT_CLRREJECT, '-'},
131
    {"badsig", OPT_BADSIG, '-', "Corrupt last byte of certificate signature (for test)"},
132
    {"", OPT_MD, '-', "Any supported digest"},
133 134 135 136 137
#ifndef OPENSSL_NO_MD5
    {"subject_hash_old", OPT_SUBJECT_HASH_OLD, '-',
     "Print old-style (MD5) issuer hash value"},
    {"issuer_hash_old", OPT_ISSUER_HASH_OLD, '-',
     "Print old-style (MD5) subject hash value"},
138
#endif
139 140
#ifndef OPENSSL_NO_ENGINE
    {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
141 142 143
#endif
    {NULL}
};
144

145
int x509_main(int argc, char **argv)
146 147
{
    ASN1_INTEGER *sno = NULL;
148
    ASN1_OBJECT *objtmp;
149
    BIO *out = NULL;
150 151
    CONF *extconf = NULL;
    EVP_PKEY *Upkey = NULL, *CApkey = NULL, *fkey = NULL;
152
    STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
153 154 155 156 157 158 159 160
    STACK_OF(OPENSSL_STRING) *sigopts = NULL;
    X509 *x = NULL, *xca = NULL;
    X509_REQ *req = NULL, *rq = NULL;
    X509_STORE *ctx = NULL;
    const EVP_MD *digest = NULL;
    char *CAkeyfile = NULL, *CAserial = NULL, *fkeyfile = NULL, *alias = NULL;
    char *checkhost = NULL, *checkemail = NULL, *checkip = NULL;
    char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL;
161
    char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL;
R
Rich Salz 已提交
162 163 164 165
    char buf[256], *prog;
    int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0, pprint = 0;
    int C = 0, CAformat = FORMAT_PEM, CAkeyformat = FORMAT_PEM;
    int fingerprint = 0, reqfile = 0, need_rand = 0, checkend = 0;
166 167 168 169 170
    int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM;
    int next_serial = 0, subject_hash = 0, issuer_hash = 0, ocspid = 0;
    int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0;
    int ocsp_uri = 0, trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0;
    int ret = 1, i, num = 0, badsig = 0, clrext = 0, nocert = 0;
R
Rich Salz 已提交
171
    int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0;
172 173
    int enddate = 0;
    time_t checkoffset = 0;
174
    unsigned long nmflag = 0, certflag = 0;
175
    char nmflag_set = 0;
176 177 178 179
    OPTION_CHOICE o;
    ENGINE *e = NULL;
#ifndef OPENSSL_NO_MD5
    int subject_hash_old = 0, issuer_hash_old = 0;
180
#endif
181

182 183 184 185 186
    ctx = X509_STORE_new();
    if (ctx == NULL)
        goto end;
    X509_STORE_set_verify_cb(ctx, callb);

187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
    prog = opt_init(argc, argv, x509_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(x509_options);
            ret = 0;
            goto end;
        case OPT_INFORM:
            if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat))
                goto opthelp;
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUTFORM:
            if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat))
                goto opthelp;
            break;
        case OPT_KEYFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat))
                goto opthelp;
            break;
        case OPT_CAFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &CAformat))
                goto opthelp;
            break;
        case OPT_CAKEYFORM:
219
            if (!opt_format(opt_arg(), OPT_FMT_ANY, &CAkeyformat))
220 221 222 223 224 225 226 227 228 229
                goto opthelp;
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_REQ:
            reqfile = need_rand = 1;
            break;

        case OPT_SIGOPT:
230 231
            if (!sigopts)
                sigopts = sk_OPENSSL_STRING_new_null();
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
            if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
                goto opthelp;
            break;
        case OPT_DAYS:
            days = atoi(opt_arg());
            break;
        case OPT_PASSIN:
            passinarg = opt_arg();
            break;
        case OPT_EXTFILE:
            extfile = opt_arg();
            break;
        case OPT_EXTENSIONS:
            extsect = opt_arg();
            break;
        case OPT_SIGNKEY:
            keyfile = opt_arg();
249 250
            sign_flag = ++num;
            need_rand = 1;
251 252 253
            break;
        case OPT_CA:
            CAfile = opt_arg();
254 255
            CA_flag = ++num;
            need_rand = 1;
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
            break;
        case OPT_CAKEY:
            CAkeyfile = opt_arg();
            break;
        case OPT_CASERIAL:
            CAserial = opt_arg();
            break;
        case OPT_SET_SERIAL:
            if ((sno = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL)
                goto opthelp;
            break;
        case OPT_FORCE_PUBKEY:
            fkeyfile = opt_arg();
            break;
        case OPT_ADDTRUST:
            if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
                BIO_printf(bio_err,
                           "%s: Invalid trust object value %s\n",
                           prog, opt_arg());
                goto opthelp;
276
            }
277 278
            if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL)
                goto end;
279 280
            sk_ASN1_OBJECT_push(trust, objtmp);
            trustout = 1;
281 282 283
            break;
        case OPT_ADDREJECT:
            if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
284
                BIO_printf(bio_err,
285 286 287
                           "%s: Invalid reject object value %s\n",
                           prog, opt_arg());
                goto opthelp;
288
            }
289 290 291
            if (reject == NULL
                && (reject = sk_ASN1_OBJECT_new_null()) == NULL)
                goto end;
292 293
            sk_ASN1_OBJECT_push(reject, objtmp);
            trustout = 1;
294 295 296
            break;
        case OPT_SETALIAS:
            alias = opt_arg();
297
            trustout = 1;
298 299 300 301 302 303
            break;
        case OPT_CERTOPT:
            if (!set_cert_ex(&certflag, opt_arg()))
                goto opthelp;
            break;
        case OPT_NAMEOPT:
304
            nmflag_set = 1;
305 306 307 308
            if (!set_name_ex(&nmflag, opt_arg()))
                goto opthelp;
            break;
        case OPT_ENGINE:
R
Rich Salz 已提交
309
            e = setup_engine(opt_arg(), 0);
310 311
            break;
        case OPT_C:
312
            C = ++num;
313 314
            break;
        case OPT_EMAIL:
315
            email = ++num;
316 317
            break;
        case OPT_OCSP_URI:
318
            ocsp_uri = ++num;
319 320
            break;
        case OPT_SERIAL:
321
            serial = ++num;
322 323
            break;
        case OPT_NEXT_SERIAL:
324
            next_serial = ++num;
325 326
            break;
        case OPT_MODULUS:
327
            modulus = ++num;
328 329
            break;
        case OPT_PUBKEY:
330
            pubkey = ++num;
331 332
            break;
        case OPT_X509TOREQ:
333
            x509req = ++num;
334 335
            break;
        case OPT_TEXT:
336
            text = ++num;
337 338
            break;
        case OPT_SUBJECT:
339
            subject = ++num;
340 341
            break;
        case OPT_ISSUER:
342
            issuer = ++num;
343 344
            break;
        case OPT_FINGERPRINT:
345
            fingerprint = ++num;
346 347 348 349 350 351 352 353
            break;
        case OPT_HASH:
            subject_hash = ++num;
            break;
        case OPT_ISSUER_HASH:
            issuer_hash = ++num;
            break;
        case OPT_PURPOSE:
354
            pprint = ++num;
355 356
            break;
        case OPT_STARTDATE:
357
            startdate = ++num;
358 359
            break;
        case OPT_ENDDATE:
360
            enddate = ++num;
361 362
            break;
        case OPT_NOOUT:
363
            noout = ++num;
364 365 366 367 368
            break;
        case OPT_NOCERT:
            nocert = 1;
            break;
        case OPT_TRUSTOUT:
369
            trustout = 1;
370 371
            break;
        case OPT_CLRTRUST:
372
            clrtrust = ++num;
373 374
            break;
        case OPT_CLRREJECT:
375
            clrreject = ++num;
376 377
            break;
        case OPT_ALIAS:
378
            aliasout = ++num;
379 380
            break;
        case OPT_CACREATESERIAL:
381
            CA_createserial = ++num;
382 383
            break;
        case OPT_CLREXT:
384
            clrext = 1;
385 386
            break;
        case OPT_OCSPID:
387
            ocspid = ++num;
388 389
            break;
        case OPT_BADSIG:
390 391
            badsig = 1;
            break;
392 393 394 395 396 397 398
#ifndef OPENSSL_NO_MD5
        case OPT_SUBJECT_HASH_OLD:
            subject_hash_old = ++num;
            break;
        case OPT_ISSUER_HASH_OLD:
            issuer_hash_old = ++num;
            break;
399 400 401 402
#else
        case OPT_SUBJECT_HASH_OLD:
        case OPT_ISSUER_HASH_OLD:
            break;
403 404 405 406 407 408 409
#endif
        case OPT_DATES:
            startdate = ++num;
            enddate = ++num;
            break;
        case OPT_CHECKEND:
            checkend = 1;
R
Richard Levitte 已提交
410 411 412 413 414 415 416 417 418 419
            {
                intmax_t temp = 0;
                if (!opt_imax(opt_arg(), &temp))
                    goto opthelp;
                checkoffset = (time_t)temp;
                if ((intmax_t)checkoffset != temp) {
                    BIO_printf(bio_err, "%s: checkend time out of range %s\n",
                               prog, opt_arg());
                    goto opthelp;
                }
420
            }
421 422 423 424 425 426 427 428 429 430 431 432 433
            break;
        case OPT_CHECKHOST:
            checkhost = opt_arg();
            break;
        case OPT_CHECKEMAIL:
            checkemail = opt_arg();
            break;
        case OPT_CHECKIP:
            checkip = opt_arg();
            break;
        case OPT_MD:
            if (!opt_md(opt_unknown(), &digest))
                goto opthelp;
434
        }
435 436 437 438 439 440
    }
    argc = opt_num_rest();
    argv = opt_rest();
    if (argc != 0) {
        BIO_printf(bio_err, "%s: Unknown parameter %s\n", prog, argv[0]);
        goto opthelp;
441 442
    }

443 444 445
    if (!nmflag_set)
        nmflag = XN_FLAG_ONELINE;

446
    out = bio_open_default(outfile, 'w', outformat);
447
    if (out == NULL)
448
        goto end;
449

450
    if (need_rand)
451
        app_RAND_load_file(NULL, 0);
452

453
    if (!app_passwd(passinarg, NULL, &passin, NULL)) {
454 455 456 457 458 459 460 461 462 463
        BIO_printf(bio_err, "Error getting password\n");
        goto end;
    }

    if (!X509_STORE_set_default_paths(ctx)) {
        ERR_print_errors(bio_err);
        goto end;
    }

    if (fkeyfile) {
464
        fkey = load_pubkey(fkeyfile, keyformat, 0, NULL, e, "Forced key");
465 466 467 468 469 470 471 472 473 474 475 476 477 478
        if (fkey == NULL)
            goto end;
    }

    if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) {
        CAkeyfile = CAfile;
    } else if ((CA_flag) && (CAkeyfile == NULL)) {
        BIO_printf(bio_err,
                   "need to specify a CAkey if using the CA command\n");
        goto end;
    }

    if (extfile) {
        X509V3_CTX ctx2;
R
Rich Salz 已提交
479
        if ((extconf = app_load_config(extfile)) == NULL)
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
            goto end;
        if (!extsect) {
            extsect = NCONF_get_string(extconf, "default", "extensions");
            if (!extsect) {
                ERR_clear_error();
                extsect = "default";
            }
        }
        X509V3_set_ctx_test(&ctx2);
        X509V3_set_nconf(&ctx2, extconf);
        if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) {
            BIO_printf(bio_err,
                       "Error Loading extension section %s\n", extsect);
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (reqfile) {
        EVP_PKEY *pkey;
        BIO *in;

        if (!sign_flag && !CA_flag) {
            BIO_printf(bio_err, "We need a private key to sign with\n");
            goto end;
        }
506
        in = bio_open_default(infile, 'r', informat);
507
        if (in == NULL)
508 509 510 511 512 513 514 515 516
            goto end;
        req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
        BIO_free(in);

        if (req == NULL) {
            ERR_print_errors(bio_err);
            goto end;
        }

F
FdaSilvaYY 已提交
517
        if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) {
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
            BIO_printf(bio_err, "error unpacking public key\n");
            goto end;
        }
        i = X509_REQ_verify(req, pkey);
        if (i < 0) {
            BIO_printf(bio_err, "Signature verification error\n");
            ERR_print_errors(bio_err);
            goto end;
        }
        if (i == 0) {
            BIO_printf(bio_err,
                       "Signature did not match the certificate request\n");
            goto end;
        } else
            BIO_printf(bio_err, "Signature ok\n");

        print_name(bio_err, "subject=", X509_REQ_get_subject_name(req),
                   nmflag);

        if ((x = X509_new()) == NULL)
            goto end;

        if (sno == NULL) {
            sno = ASN1_INTEGER_new();
542
            if (sno == NULL || !rand_serial(NULL, sno))
543 544 545 546 547 548 549 550
                goto end;
            if (!X509_set_serialNumber(x, sno))
                goto end;
            ASN1_INTEGER_free(sno);
            sno = NULL;
        } else if (!X509_set_serialNumber(x, sno))
            goto end;

D
Dr. Stephen Henson 已提交
551
        if (!X509_set_issuer_name(x, X509_REQ_get_subject_name(req)))
552
            goto end;
D
Dr. Stephen Henson 已提交
553
        if (!X509_set_subject_name(x, X509_REQ_get_subject_name(req)))
554 555 556 557 558 559 560
            goto end;

        X509_gmtime_adj(X509_get_notBefore(x), 0);
        X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL);
        if (fkey)
            X509_set_pubkey(x, fkey);
        else {
F
FdaSilvaYY 已提交
561
            pkey = X509_REQ_get0_pubkey(req);
562 563 564
            X509_set_pubkey(x, pkey);
        }
    } else
565
        x = load_cert(infile, informat, "Certificate");
566 567 568 569

    if (x == NULL)
        goto end;
    if (CA_flag) {
570
        xca = load_cert(CAfile, CAformat, "CA Certificate");
571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604
        if (xca == NULL)
            goto end;
    }

    if (!noout || text || next_serial) {
        OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3");

    }

    if (alias)
        X509_alias_set1(x, (unsigned char *)alias, -1);

    if (clrtrust)
        X509_trust_clear(x);
    if (clrreject)
        X509_reject_clear(x);

    if (trust) {
        for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) {
            objtmp = sk_ASN1_OBJECT_value(trust, i);
            X509_add1_trust_object(x, objtmp);
        }
    }

    if (reject) {
        for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) {
            objtmp = sk_ASN1_OBJECT_value(reject, i);
            X509_add1_reject_object(x, objtmp);
        }
    }

    if (num) {
        for (i = 1; i <= num; i++) {
            if (issuer == i) {
605
                print_name(out, "issuer= ", X509_get_issuer_name(x), nmflag);
606
            } else if (subject == i) {
607
                print_name(out, "subject= ",
608 609
                           X509_get_subject_name(x), nmflag);
            } else if (serial == i) {
610 611 612
                BIO_printf(out, "serial=");
                i2a_ASN1_INTEGER(out, X509_get_serialNumber(x));
                BIO_printf(out, "\n");
613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
            } else if (next_serial == i) {
                BIGNUM *bnser;
                ASN1_INTEGER *ser;
                ser = X509_get_serialNumber(x);
                bnser = ASN1_INTEGER_to_BN(ser, NULL);
                if (!bnser)
                    goto end;
                if (!BN_add_word(bnser, 1))
                    goto end;
                ser = BN_to_ASN1_INTEGER(bnser, NULL);
                if (!ser)
                    goto end;
                BN_free(bnser);
                i2a_ASN1_INTEGER(out, ser);
                ASN1_INTEGER_free(ser);
                BIO_puts(out, "\n");
            } else if ((email == i) || (ocsp_uri == i)) {
                int j;
                STACK_OF(OPENSSL_STRING) *emlst;
                if (email == i)
                    emlst = X509_get1_email(x);
                else
                    emlst = X509_get1_ocsp(x);
                for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
637
                    BIO_printf(out, "%s\n",
638 639 640 641 642 643
                               sk_OPENSSL_STRING_value(emlst, j));
                X509_email_free(emlst);
            } else if (aliasout == i) {
                unsigned char *alstr;
                alstr = X509_alias_get0(x, NULL);
                if (alstr)
644
                    BIO_printf(out, "%s\n", alstr);
645
                else
646
                    BIO_puts(out, "<No Alias>\n");
647
            } else if (subject_hash == i) {
648
                BIO_printf(out, "%08lx\n", X509_subject_name_hash(x));
649
            }
D
Dr. Stephen Henson 已提交
650
#ifndef OPENSSL_NO_MD5
651
            else if (subject_hash_old == i) {
652
                BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x));
653
            }
D
Dr. Stephen Henson 已提交
654
#endif
655
            else if (issuer_hash == i) {
656
                BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x));
657
            }
D
Dr. Stephen Henson 已提交
658
#ifndef OPENSSL_NO_MD5
659
            else if (issuer_hash_old == i) {
660
                BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x));
661
            }
D
Dr. Stephen Henson 已提交
662
#endif
663 664 665
            else if (pprint == i) {
                X509_PURPOSE *ptmp;
                int j;
666
                BIO_printf(out, "Certificate purposes:\n");
667 668
                for (j = 0; j < X509_PURPOSE_get_count(); j++) {
                    ptmp = X509_PURPOSE_get0(j);
669
                    purpose_print(out, x, ptmp);
670 671 672 673
                }
            } else if (modulus == i) {
                EVP_PKEY *pkey;

D
Dr. Stephen Henson 已提交
674
                pkey = X509_get0_pubkey(x);
675 676 677 678 679
                if (pkey == NULL) {
                    BIO_printf(bio_err, "Modulus=unavailable\n");
                    ERR_print_errors(bio_err);
                    goto end;
                }
680
                BIO_printf(out, "Modulus=");
681
#ifndef OPENSSL_NO_RSA
R
Richard Levitte 已提交
682 683 684 685 686
                if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
                    BIGNUM *n;
                    RSA_get0_key(EVP_PKEY_get0_RSA(pkey), &n, NULL, NULL);
                    BN_print(out, n);
                } else
687
#endif
688
#ifndef OPENSSL_NO_DSA
M
Matt Caswell 已提交
689 690 691 692 693
                if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) {
                    BIGNUM *dsapub = NULL;
                    DSA_get0_key(EVP_PKEY_get0_DSA(pkey), &dsapub, NULL);
                    BN_print(out, dsapub);
                } else
694
#endif
M
Matt Caswell 已提交
695
                {
696
                    BIO_printf(out, "Wrong Algorithm type");
M
Matt Caswell 已提交
697
                }
698
                BIO_printf(out, "\n");
699 700 701
            } else if (pubkey == i) {
                EVP_PKEY *pkey;

D
Dr. Stephen Henson 已提交
702
                pkey = X509_get0_pubkey(x);
703 704 705 706 707
                if (pkey == NULL) {
                    BIO_printf(bio_err, "Error getting public key\n");
                    ERR_print_errors(bio_err);
                    goto end;
                }
708
                PEM_write_bio_PUBKEY(out, pkey);
709 710 711
            } else if (C == i) {
                unsigned char *d;
                char *m;
712
                int len;
713 714

                X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof buf);
715 716 717
                BIO_printf(out, "/*\n"
                                " * Subject: %s\n", buf);

M
Matt Caswell 已提交
718
                X509_NAME_oneline(X509_get_issuer_name(x), buf, sizeof buf);
719 720
                BIO_printf(out, " * Issuer:  %s\n"
                                " */\n", buf);
721

722
                len = i2d_X509(x, NULL);
R
Rich Salz 已提交
723
                m = app_malloc(len, "x509 name buffer");
724
                d = (unsigned char *)m;
725 726
                len = i2d_X509_NAME(X509_get_subject_name(x), &d);
                print_array(out, "the_subject_name", len, (unsigned char *)m);
727
                d = (unsigned char *)m;
728 729
                len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d);
                print_array(out, "the_public_key", len, (unsigned char *)m);
730
                d = (unsigned char *)m;
731 732
                len = i2d_X509(x, &d);
                print_array(out, "the_certificate", len, (unsigned char *)m);
733 734
                OPENSSL_free(m);
            } else if (text == i) {
735
                X509_print_ex(out, x, nmflag, certflag);
736
            } else if (startdate == i) {
737 738 739
                BIO_puts(out, "notBefore=");
                ASN1_TIME_print(out, X509_get_notBefore(x));
                BIO_puts(out, "\n");
740
            } else if (enddate == i) {
741 742 743
                BIO_puts(out, "notAfter=");
                ASN1_TIME_print(out, X509_get_notAfter(x));
                BIO_puts(out, "\n");
744 745 746 747 748 749 750 751 752 753 754 755 756
            } else if (fingerprint == i) {
                int j;
                unsigned int n;
                unsigned char md[EVP_MAX_MD_SIZE];
                const EVP_MD *fdig = digest;

                if (!fdig)
                    fdig = EVP_sha1();

                if (!X509_digest(x, fdig, md, &n)) {
                    BIO_printf(bio_err, "out of memory\n");
                    goto end;
                }
757
                BIO_printf(out, "%s Fingerprint=",
758 759
                           OBJ_nid2sn(EVP_MD_type(fdig)));
                for (j = 0; j < (int)n; j++) {
760
                    BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n)
761 762 763 764 765 766 767 768
                               ? '\n' : ':');
                }
            }

            /* should be in the library */
            else if ((sign_flag == i) && (x509req == 0)) {
                BIO_printf(bio_err, "Getting Private key\n");
                if (Upkey == NULL) {
769
                    Upkey = load_key(keyfile, keyformat, 0,
770 771 772 773 774 775 776 777 778 779 780
                                     passin, e, "Private key");
                    if (Upkey == NULL)
                        goto end;
                }

                assert(need_rand);
                if (!sign(x, Upkey, days, clrext, digest, extconf, extsect))
                    goto end;
            } else if (CA_flag == i) {
                BIO_printf(bio_err, "Getting CA Private Key\n");
                if (CAkeyfile != NULL) {
781
                    CApkey = load_key(CAkeyfile, CAkeyformat,
782 783 784 785 786 787 788 789 790
                                      0, passin, e, "CA Private Key");
                    if (CApkey == NULL)
                        goto end;
                }

                assert(need_rand);
                if (!x509_certify(ctx, CAfile, digest, x, xca,
                                  CApkey, sigopts,
                                  CAserial, CA_createserial, days, clrext,
791
                                  extconf, extsect, sno, reqfile))
792 793 794 795 796 797 798 799 800
                    goto end;
            } else if (x509req == i) {
                EVP_PKEY *pk;

                BIO_printf(bio_err, "Getting request Private Key\n");
                if (keyfile == NULL) {
                    BIO_printf(bio_err, "no request key file specified\n");
                    goto end;
                } else {
801
                    pk = load_key(keyfile, keyformat, 0,
802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838
                                  passin, e, "request key");
                    if (pk == NULL)
                        goto end;
                }

                BIO_printf(bio_err, "Generating certificate request\n");

                rq = X509_to_X509_REQ(x, pk, digest);
                EVP_PKEY_free(pk);
                if (rq == NULL) {
                    ERR_print_errors(bio_err);
                    goto end;
                }
                if (!noout) {
                    X509_REQ_print(out, rq);
                    PEM_write_bio_X509_REQ(out, rq);
                }
                noout = 1;
            } else if (ocspid == i) {
                X509_ocspid_print(out, x);
            }
        }
    }

    if (checkend) {
        time_t tcheck = time(NULL) + checkoffset;

        if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0) {
            BIO_printf(out, "Certificate will expire\n");
            ret = 1;
        } else {
            BIO_printf(out, "Certificate will not expire\n");
            ret = 0;
        }
        goto end;
    }

839
    print_cert_checks(out, x, checkhost, checkemail, checkip);
840

841
    if (noout || nocert) {
842 843 844 845
        ret = 0;
        goto end;
    }

846 847 848 849 850 851 852
    if (badsig) {
        ASN1_BIT_STRING *signature;
        unsigned char *s;
        X509_get0_signature(&signature, NULL, x);
        s = ASN1_STRING_data(signature);
        s[ASN1_STRING_length(signature) - 1] ^= 0x1;
    }
853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872

    if (outformat == FORMAT_ASN1)
        i = i2d_X509_bio(out, x);
    else if (outformat == FORMAT_PEM) {
        if (trustout)
            i = PEM_write_bio_X509_AUX(out, x);
        else
            i = PEM_write_bio_X509(out, x);
    } else {
        BIO_printf(bio_err, "bad output format specified for outfile\n");
        goto end;
    }
    if (!i) {
        BIO_printf(bio_err, "unable to write certificate\n");
        ERR_print_errors(bio_err);
        goto end;
    }
    ret = 0;
 end:
    if (need_rand)
873
        app_RAND_write_file(NULL);
874 875 876 877 878 879 880 881 882
    NCONF_free(extconf);
    BIO_free_all(out);
    X509_STORE_free(ctx);
    X509_REQ_free(req);
    X509_free(x);
    X509_free(xca);
    EVP_PKEY_free(Upkey);
    EVP_PKEY_free(CApkey);
    EVP_PKEY_free(fkey);
R
Rich Salz 已提交
883
    sk_OPENSSL_STRING_free(sigopts);
884 885 886 887
    X509_REQ_free(rq);
    ASN1_INTEGER_free(sno);
    sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
    sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
R
Rich Salz 已提交
888
    OPENSSL_free(passin);
889
    return (ret);
890 891 892 893 894 895 896 897 898 899 900 901 902
}

static ASN1_INTEGER *x509_load_serial(char *CAfile, char *serialfile,
                                      int create)
{
    char *buf = NULL, *p;
    ASN1_INTEGER *bs = NULL;
    BIGNUM *serial = NULL;
    size_t len;

    len = ((serialfile == NULL)
           ? (strlen(CAfile) + strlen(POSTFIX) + 1)
           : (strlen(serialfile))) + 1;
R
Rich Salz 已提交
903
    buf = app_malloc(len, "serial# buffer");
904
    if (serialfile == NULL) {
R
Rich Salz 已提交
905
        OPENSSL_strlcpy(buf, CAfile, len);
906 907 908 909 910
        for (p = buf; *p; p++)
            if (*p == '.') {
                *p = '\0';
                break;
            }
R
Rich Salz 已提交
911
        OPENSSL_strlcat(buf, POSTFIX, len);
912
    } else
R
Rich Salz 已提交
913
        OPENSSL_strlcpy(buf, serialfile, len);
914 915 916 917 918 919 920 921 922 923 924 925

    serial = load_serial(buf, create, NULL);
    if (serial == NULL)
        goto end;

    if (!BN_add_word(serial, 1)) {
        BIO_printf(bio_err, "add_word failure\n");
        goto end;
    }

    if (!save_serial(buf, NULL, serial, &bs))
        goto end;
926

927
 end:
R
Rich Salz 已提交
928
    OPENSSL_free(buf);
929 930 931
    BN_free(serial);
    return bs;
}
932 933

static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
934 935 936 937
                        X509 *x, X509 *xca, EVP_PKEY *pkey,
                        STACK_OF(OPENSSL_STRING) *sigopts,
                        char *serialfile, int create,
                        int days, int clrext, CONF *conf, char *section,
938
                        ASN1_INTEGER *sno, int reqfile)
939 940 941
{
    int ret = 0;
    ASN1_INTEGER *bs = NULL;
R
Rich Salz 已提交
942
    X509_STORE_CTX *xsc = NULL;
943 944
    EVP_PKEY *upkey;

D
Dr. Stephen Henson 已提交
945
    upkey = X509_get0_pubkey(xca);
946 947 948 949
    if (upkey == NULL) {
        BIO_printf(bio_err, "Error obtaining CA X509 public key\n");
        goto end;
    }
950 951
    EVP_PKEY_copy_parameters(upkey, pkey);

R
Rich Salz 已提交
952 953
    xsc = X509_STORE_CTX_new();
    if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, x, NULL)) {
954 955 956 957 958
        BIO_printf(bio_err, "Error initialising X509 store\n");
        goto end;
    }
    if (sno)
        bs = sno;
959
    else if ((bs = x509_load_serial(CAfile, serialfile, create)) == NULL)
960 961 962 963 964 965
        goto end;

    /*
     * NOTE: this certificate can/should be self signed, unless it was a
     * certificate request in which case it is not.
     */
R
Rich Salz 已提交
966 967 968
    X509_STORE_CTX_set_cert(xsc, x);
    X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
    if (!reqfile && X509_verify_cert(xsc) <= 0)
969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002
        goto end;

    if (!X509_check_private_key(xca, pkey)) {
        BIO_printf(bio_err,
                   "CA certificate and CA private key do not match\n");
        goto end;
    }

    if (!X509_set_issuer_name(x, X509_get_subject_name(xca)))
        goto end;
    if (!X509_set_serialNumber(x, bs))
        goto end;

    if (X509_gmtime_adj(X509_get_notBefore(x), 0L) == NULL)
        goto end;

    /* hardwired expired */
    if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL)
        goto end;

    if (clrext) {
        while (X509_get_ext_count(x) > 0)
            X509_delete_ext(x, 0);
    }

    if (conf) {
        X509V3_CTX ctx2;
        X509_set_version(x, 2); /* version 3 certificate */
        X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
        X509V3_set_nconf(&ctx2, conf);
        if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x))
            goto end;
    }

1003
    if (!do_X509_sign(x, pkey, digest, sigopts))
1004 1005 1006
        goto end;
    ret = 1;
 end:
R
Rich Salz 已提交
1007
    X509_STORE_CTX_free(xsc);
1008 1009 1010 1011 1012 1013
    if (!ret)
        ERR_print_errors(bio_err);
    if (!sno)
        ASN1_INTEGER_free(bs);
    return ret;
}
1014

R
Rich Salz 已提交
1015
static int callb(int ok, X509_STORE_CTX *ctx)
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046
{
    int err;
    X509 *err_cert;

    /*
     * it is ok to use a self signed certificate This case will catch both
     * the initial ok == 0 and the final ok == 1 calls to this function
     */
    err = X509_STORE_CTX_get_error(ctx);
    if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
        return 1;

    /*
     * BAD we should have gotten an error.  Normally if everything worked
     * X509_STORE_CTX_get_error(ctx) will still be set to
     * DEPTH_ZERO_SELF_....
     */
    if (ok) {
        BIO_printf(bio_err,
                   "error with certificate to be certified - should be self signed\n");
        return 0;
    } else {
        err_cert = X509_STORE_CTX_get_current_cert(ctx);
        print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0);
        BIO_printf(bio_err,
                   "error with certificate - error %d at depth %d\n%s\n", err,
                   X509_STORE_CTX_get_error_depth(ctx),
                   X509_verify_cert_error_string(err));
        return 1;
    }
}
1047 1048

/* self sign */
1049 1050 1051 1052 1053 1054 1055 1056 1057
static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
                const EVP_MD *digest, CONF *conf, char *section)
{

    if (!X509_set_issuer_name(x, X509_get_subject_name(x)))
        goto err;
    if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL)
        goto err;

1058
    if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL)
1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
        goto err;

    if (!X509_set_pubkey(x, pkey))
        goto err;
    if (clrext) {
        while (X509_get_ext_count(x) > 0)
            X509_delete_ext(x, 0);
    }
    if (conf) {
        X509V3_CTX ctx;
        X509_set_version(x, 2); /* version 3 certificate */
        X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
        X509V3_set_nconf(&ctx, conf);
        if (!X509V3_EXT_add_nconf(conf, &ctx, section, x))
            goto err;
    }
    if (!X509_sign(x, pkey, digest))
        goto err;
    return 1;
 err:
    ERR_print_errors(bio_err);
    return 0;
}
1082

1083
static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
1084
{
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099
    int id, i, idret;
    char *pname;
    id = X509_PURPOSE_get_id(pt);
    pname = X509_PURPOSE_get0_name(pt);
    for (i = 0; i < 2; i++) {
        idret = X509_check_purpose(cert, id, i);
        BIO_printf(bio, "%s%s : ", pname, i ? " CA" : "");
        if (idret == 1)
            BIO_printf(bio, "Yes\n");
        else if (idret == 0)
            BIO_printf(bio, "No\n");
        else
            BIO_printf(bio, "Yes (WARNING code=%d)\n", idret);
    }
    return 1;
1100
}