x509.c 36.3 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 = NULL;
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
            sk_ASN1_OBJECT_push(trust, objtmp);
280
            objtmp = NULL;
281
            trustout = 1;
282 283 284
            break;
        case OPT_ADDREJECT:
            if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
285
                BIO_printf(bio_err,
286 287 288
                           "%s: Invalid reject object value %s\n",
                           prog, opt_arg());
                goto opthelp;
289
            }
290 291 292
            if (reject == NULL
                && (reject = sk_ASN1_OBJECT_new_null()) == NULL)
                goto end;
293
            sk_ASN1_OBJECT_push(reject, objtmp);
294
            objtmp = NULL;
295
            trustout = 1;
296 297 298
            break;
        case OPT_SETALIAS:
            alias = opt_arg();
299
            trustout = 1;
300 301 302 303 304 305
            break;
        case OPT_CERTOPT:
            if (!set_cert_ex(&certflag, opt_arg()))
                goto opthelp;
            break;
        case OPT_NAMEOPT:
306
            nmflag_set = 1;
307 308 309 310
            if (!set_name_ex(&nmflag, opt_arg()))
                goto opthelp;
            break;
        case OPT_ENGINE:
R
Rich Salz 已提交
311
            e = setup_engine(opt_arg(), 0);
312 313
            break;
        case OPT_C:
314
            C = ++num;
315 316
            break;
        case OPT_EMAIL:
317
            email = ++num;
318 319
            break;
        case OPT_OCSP_URI:
320
            ocsp_uri = ++num;
321 322
            break;
        case OPT_SERIAL:
323
            serial = ++num;
324 325
            break;
        case OPT_NEXT_SERIAL:
326
            next_serial = ++num;
327 328
            break;
        case OPT_MODULUS:
329
            modulus = ++num;
330 331
            break;
        case OPT_PUBKEY:
332
            pubkey = ++num;
333 334
            break;
        case OPT_X509TOREQ:
335
            x509req = ++num;
336 337
            break;
        case OPT_TEXT:
338
            text = ++num;
339 340
            break;
        case OPT_SUBJECT:
341
            subject = ++num;
342 343
            break;
        case OPT_ISSUER:
344
            issuer = ++num;
345 346
            break;
        case OPT_FINGERPRINT:
347
            fingerprint = ++num;
348 349 350 351 352 353 354 355
            break;
        case OPT_HASH:
            subject_hash = ++num;
            break;
        case OPT_ISSUER_HASH:
            issuer_hash = ++num;
            break;
        case OPT_PURPOSE:
356
            pprint = ++num;
357 358
            break;
        case OPT_STARTDATE:
359
            startdate = ++num;
360 361
            break;
        case OPT_ENDDATE:
362
            enddate = ++num;
363 364
            break;
        case OPT_NOOUT:
365
            noout = ++num;
366 367 368 369 370
            break;
        case OPT_NOCERT:
            nocert = 1;
            break;
        case OPT_TRUSTOUT:
371
            trustout = 1;
372 373
            break;
        case OPT_CLRTRUST:
374
            clrtrust = ++num;
375 376
            break;
        case OPT_CLRREJECT:
377
            clrreject = ++num;
378 379
            break;
        case OPT_ALIAS:
380
            aliasout = ++num;
381 382
            break;
        case OPT_CACREATESERIAL:
383
            CA_createserial = ++num;
384 385
            break;
        case OPT_CLREXT:
386
            clrext = 1;
387 388
            break;
        case OPT_OCSPID:
389
            ocspid = ++num;
390 391
            break;
        case OPT_BADSIG:
392 393
            badsig = 1;
            break;
394 395 396 397 398 399 400
#ifndef OPENSSL_NO_MD5
        case OPT_SUBJECT_HASH_OLD:
            subject_hash_old = ++num;
            break;
        case OPT_ISSUER_HASH_OLD:
            issuer_hash_old = ++num;
            break;
401 402 403 404
#else
        case OPT_SUBJECT_HASH_OLD:
        case OPT_ISSUER_HASH_OLD:
            break;
405 406 407 408 409 410 411
#endif
        case OPT_DATES:
            startdate = ++num;
            enddate = ++num;
            break;
        case OPT_CHECKEND:
            checkend = 1;
R
Richard Levitte 已提交
412 413 414 415 416 417 418 419 420 421
            {
                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;
                }
422
            }
423 424 425 426 427 428 429 430 431 432 433 434 435
            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;
436
        }
437 438 439 440 441 442
    }
    argc = opt_num_rest();
    argv = opt_rest();
    if (argc != 0) {
        BIO_printf(bio_err, "%s: Unknown parameter %s\n", prog, argv[0]);
        goto opthelp;
443 444
    }

445 446 447
    if (!nmflag_set)
        nmflag = XN_FLAG_ONELINE;

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

452
    if (need_rand)
453
        app_RAND_load_file(NULL, 0);
454

455
    if (!app_passwd(passinarg, NULL, &passin, NULL)) {
456 457 458 459 460 461 462 463 464 465
        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) {
466
        fkey = load_pubkey(fkeyfile, keyformat, 0, NULL, e, "Forced key");
467 468 469 470 471 472 473 474 475 476 477 478 479 480
        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 已提交
481
        if ((extconf = app_load_config(extfile)) == NULL)
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
            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;
        }
508
        in = bio_open_default(infile, 'r', informat);
509
        if (in == NULL)
510 511 512 513 514 515 516 517 518
            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 已提交
519
        if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) {
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
            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();
544
            if (sno == NULL || !rand_serial(NULL, sno))
545 546 547 548 549 550 551 552
                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 已提交
553
        if (!X509_set_issuer_name(x, X509_REQ_get_subject_name(req)))
554
            goto end;
D
Dr. Stephen Henson 已提交
555
        if (!X509_set_subject_name(x, X509_REQ_get_subject_name(req)))
556 557 558 559 560 561 562
            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 已提交
563
            pkey = X509_REQ_get0_pubkey(req);
564 565 566
            X509_set_pubkey(x, pkey);
        }
    } else
567
        x = load_cert(infile, informat, "Certificate");
568 569 570 571

    if (x == NULL)
        goto end;
    if (CA_flag) {
572
        xca = load_cert(CAfile, CAformat, "CA Certificate");
573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594
        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);
        }
595
        objtmp = NULL;
596 597 598 599 600 601 602
    }

    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);
        }
603
        objtmp = NULL;
604 605
    }

D
Dr. Stephen Henson 已提交
606 607 608 609 610 611 612
    if (badsig) {
        ASN1_BIT_STRING *signature;
        X509_get0_signature(&signature, NULL, x);
        if (!corrupt_signature(signature))
            goto end;
    }

613 614 615
    if (num) {
        for (i = 1; i <= num; i++) {
            if (issuer == i) {
616
                print_name(out, "issuer=", X509_get_issuer_name(x), nmflag);
617
            } else if (subject == i) {
618
                print_name(out, "subject=",
619 620
                           X509_get_subject_name(x), nmflag);
            } else if (serial == i) {
621 622 623
                BIO_printf(out, "serial=");
                i2a_ASN1_INTEGER(out, X509_get_serialNumber(x));
                BIO_printf(out, "\n");
624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
            } 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++)
648
                    BIO_printf(out, "%s\n",
649 650 651 652 653 654
                               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)
655
                    BIO_printf(out, "%s\n", alstr);
656
                else
657
                    BIO_puts(out, "<No Alias>\n");
658
            } else if (subject_hash == i) {
659
                BIO_printf(out, "%08lx\n", X509_subject_name_hash(x));
660
            }
D
Dr. Stephen Henson 已提交
661
#ifndef OPENSSL_NO_MD5
662
            else if (subject_hash_old == i) {
663
                BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x));
664
            }
D
Dr. Stephen Henson 已提交
665
#endif
666
            else if (issuer_hash == i) {
667
                BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x));
668
            }
D
Dr. Stephen Henson 已提交
669
#ifndef OPENSSL_NO_MD5
670
            else if (issuer_hash_old == i) {
671
                BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x));
672
            }
D
Dr. Stephen Henson 已提交
673
#endif
674 675 676
            else if (pprint == i) {
                X509_PURPOSE *ptmp;
                int j;
677
                BIO_printf(out, "Certificate purposes:\n");
678 679
                for (j = 0; j < X509_PURPOSE_get_count(); j++) {
                    ptmp = X509_PURPOSE_get0(j);
680
                    purpose_print(out, x, ptmp);
681 682 683 684
                }
            } else if (modulus == i) {
                EVP_PKEY *pkey;

D
Dr. Stephen Henson 已提交
685
                pkey = X509_get0_pubkey(x);
686 687 688 689 690
                if (pkey == NULL) {
                    BIO_printf(bio_err, "Modulus=unavailable\n");
                    ERR_print_errors(bio_err);
                    goto end;
                }
691
                BIO_printf(out, "Modulus=");
692
#ifndef OPENSSL_NO_RSA
R
Richard Levitte 已提交
693
                if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
694
                    const BIGNUM *n;
R
Richard Levitte 已提交
695 696 697
                    RSA_get0_key(EVP_PKEY_get0_RSA(pkey), &n, NULL, NULL);
                    BN_print(out, n);
                } else
698
#endif
699
#ifndef OPENSSL_NO_DSA
M
Matt Caswell 已提交
700
                if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) {
701
                    const BIGNUM *dsapub = NULL;
M
Matt Caswell 已提交
702 703 704
                    DSA_get0_key(EVP_PKEY_get0_DSA(pkey), &dsapub, NULL);
                    BN_print(out, dsapub);
                } else
705
#endif
M
Matt Caswell 已提交
706
                {
707
                    BIO_printf(out, "Wrong Algorithm type");
M
Matt Caswell 已提交
708
                }
709
                BIO_printf(out, "\n");
710 711 712
            } else if (pubkey == i) {
                EVP_PKEY *pkey;

D
Dr. Stephen Henson 已提交
713
                pkey = X509_get0_pubkey(x);
714 715 716 717 718
                if (pkey == NULL) {
                    BIO_printf(bio_err, "Error getting public key\n");
                    ERR_print_errors(bio_err);
                    goto end;
                }
719
                PEM_write_bio_PUBKEY(out, pkey);
720 721 722
            } else if (C == i) {
                unsigned char *d;
                char *m;
723
                int len;
724 725

                X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof buf);
726 727 728
                BIO_printf(out, "/*\n"
                                " * Subject: %s\n", buf);

M
Matt Caswell 已提交
729
                X509_NAME_oneline(X509_get_issuer_name(x), buf, sizeof buf);
730 731
                BIO_printf(out, " * Issuer:  %s\n"
                                " */\n", buf);
732

733
                len = i2d_X509(x, NULL);
R
Rich Salz 已提交
734
                m = app_malloc(len, "x509 name buffer");
735
                d = (unsigned char *)m;
736 737
                len = i2d_X509_NAME(X509_get_subject_name(x), &d);
                print_array(out, "the_subject_name", len, (unsigned char *)m);
738
                d = (unsigned char *)m;
739 740
                len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d);
                print_array(out, "the_public_key", len, (unsigned char *)m);
741
                d = (unsigned char *)m;
742 743
                len = i2d_X509(x, &d);
                print_array(out, "the_certificate", len, (unsigned char *)m);
744 745
                OPENSSL_free(m);
            } else if (text == i) {
746
                X509_print_ex(out, x, nmflag, certflag);
747
            } else if (startdate == i) {
748 749 750
                BIO_puts(out, "notBefore=");
                ASN1_TIME_print(out, X509_get_notBefore(x));
                BIO_puts(out, "\n");
751
            } else if (enddate == i) {
752 753 754
                BIO_puts(out, "notAfter=");
                ASN1_TIME_print(out, X509_get_notAfter(x));
                BIO_puts(out, "\n");
755 756 757 758 759 760 761 762 763 764 765 766 767
            } 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;
                }
768
                BIO_printf(out, "%s Fingerprint=",
769 770
                           OBJ_nid2sn(EVP_MD_type(fdig)));
                for (j = 0; j < (int)n; j++) {
771
                    BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n)
772 773 774 775 776 777 778 779
                               ? '\n' : ':');
                }
            }

            /* should be in the library */
            else if ((sign_flag == i) && (x509req == 0)) {
                BIO_printf(bio_err, "Getting Private key\n");
                if (Upkey == NULL) {
780
                    Upkey = load_key(keyfile, keyformat, 0,
781 782 783 784 785 786 787 788 789 790 791
                                     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) {
792
                    CApkey = load_key(CAkeyfile, CAkeyformat,
793 794 795 796 797 798 799 800 801
                                      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,
802
                                  extconf, extsect, sno, reqfile))
803 804 805 806 807 808 809 810 811
                    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 {
812
                    pk = load_key(keyfile, keyformat, 0,
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 839 840 841 842 843 844 845 846 847 848 849
                                  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;
    }

850
    print_cert_checks(out, x, checkhost, checkemail, checkip);
851

852
    if (noout || nocert) {
853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875
        ret = 0;
        goto end;
    }

    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)
876
        app_RAND_write_file(NULL);
877 878 879 880 881 882 883 884 885
    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 已提交
886
    sk_OPENSSL_STRING_free(sigopts);
887 888 889 890
    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);
891
    ASN1_OBJECT_free(objtmp);
R
Rich Salz 已提交
892
    OPENSSL_free(passin);
893
    return (ret);
894 895 896 897 898 899 900 901 902 903 904 905 906
}

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 已提交
907
    buf = app_malloc(len, "serial# buffer");
908
    if (serialfile == NULL) {
R
Rich Salz 已提交
909
        OPENSSL_strlcpy(buf, CAfile, len);
910 911 912 913 914
        for (p = buf; *p; p++)
            if (*p == '.') {
                *p = '\0';
                break;
            }
R
Rich Salz 已提交
915
        OPENSSL_strlcat(buf, POSTFIX, len);
916
    } else
R
Rich Salz 已提交
917
        OPENSSL_strlcpy(buf, serialfile, len);
918 919 920 921 922 923 924 925 926 927 928 929

    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;
930

931
 end:
R
Rich Salz 已提交
932
    OPENSSL_free(buf);
933 934 935
    BN_free(serial);
    return bs;
}
936 937

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

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

R
Rich Salz 已提交
956 957
    xsc = X509_STORE_CTX_new();
    if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, x, NULL)) {
958 959 960 961 962
        BIO_printf(bio_err, "Error initialising X509 store\n");
        goto end;
    }
    if (sno)
        bs = sno;
963
    else if ((bs = x509_load_serial(CAfile, serialfile, create)) == NULL)
964 965 966 967 968 969
        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 已提交
970 971 972
    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)
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 1003 1004 1005 1006
        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;
    }

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

R
Rich Salz 已提交
1019
static int callb(int ok, X509_STORE_CTX *ctx)
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 1047 1048 1049 1050
{
    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;
    }
}
1051 1052

/* self sign */
1053 1054 1055 1056 1057 1058 1059 1060 1061
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;

1062
    if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL)
1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
        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;
}
1086

1087
static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
1088
{
1089
    int id, i, idret;
F
FdaSilvaYY 已提交
1090
    const char *pname;
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103
    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;
1104
}