[BACK]Return to x509.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / openssl

Annotation of src/usr.bin/openssl/x509.c, Revision 1.34

1.34    ! tb          1: /* $OpenBSD: x509.c,v 1.33 2023/04/14 06:47:07 tb Exp $ */
1.1       jsing       2: /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
                      3:  * All rights reserved.
                      4:  *
                      5:  * This package is an SSL implementation written
                      6:  * by Eric Young (eay@cryptsoft.com).
                      7:  * The implementation was written so as to conform with Netscapes SSL.
                      8:  *
                      9:  * This library is free for commercial and non-commercial use as long as
                     10:  * the following conditions are aheared to.  The following conditions
                     11:  * apply to all code found in this distribution, be it the RC4, RSA,
                     12:  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
                     13:  * included with this distribution is covered by the same copyright terms
                     14:  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
                     15:  *
                     16:  * Copyright remains Eric Young's, and as such any Copyright notices in
                     17:  * the code are not to be removed.
                     18:  * If this package is used in a product, Eric Young should be given attribution
                     19:  * as the author of the parts of the library used.
                     20:  * This can be in the form of a textual message at program startup or
                     21:  * in documentation (online or textual) provided with the package.
                     22:  *
                     23:  * Redistribution and use in source and binary forms, with or without
                     24:  * modification, are permitted provided that the following conditions
                     25:  * are met:
                     26:  * 1. Redistributions of source code must retain the copyright
                     27:  *    notice, this list of conditions and the following disclaimer.
                     28:  * 2. Redistributions in binary form must reproduce the above copyright
                     29:  *    notice, this list of conditions and the following disclaimer in the
                     30:  *    documentation and/or other materials provided with the distribution.
                     31:  * 3. All advertising materials mentioning features or use of this software
                     32:  *    must display the following acknowledgement:
                     33:  *    "This product includes cryptographic software written by
                     34:  *     Eric Young (eay@cryptsoft.com)"
                     35:  *    The word 'cryptographic' can be left out if the rouines from the library
                     36:  *    being used are not cryptographic related :-).
                     37:  * 4. If you include any Windows specific code (or a derivative thereof) from
                     38:  *    the apps directory (application code) you must include an acknowledgement:
                     39:  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
                     40:  *
                     41:  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
                     42:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     43:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     44:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     45:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     46:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     47:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     48:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     49:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     50:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     51:  * SUCH DAMAGE.
                     52:  *
                     53:  * The licence and distribution terms for any publically available version or
                     54:  * derivative of this code cannot be changed.  i.e. this code cannot simply be
                     55:  * copied and put under another distribution licence
                     56:  * [including the GNU Public Licence.]
                     57:  */
                     58:
                     59: #include <assert.h>
1.20      inoguchi   60: #include <limits.h>
1.1       jsing      61: #include <stdio.h>
                     62: #include <stdlib.h>
                     63: #include <string.h>
                     64:
                     65: #include "apps.h"
                     66:
                     67: #include <openssl/asn1.h>
                     68: #include <openssl/bio.h>
                     69: #include <openssl/bn.h>
1.20      inoguchi   70: #include <openssl/dsa.h>
1.1       jsing      71: #include <openssl/err.h>
                     72: #include <openssl/evp.h>
                     73: #include <openssl/objects.h>
                     74: #include <openssl/pem.h>
1.20      inoguchi   75: #include <openssl/rsa.h>
1.1       jsing      76: #include <openssl/x509.h>
                     77: #include <openssl/x509v3.h>
                     78:
                     79: #define        POSTFIX ".srl"
                     80: #define DEF_DAYS       30
                     81:
                     82: static int callb(int ok, X509_STORE_CTX *ctx);
                     83: static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
                     84:     const EVP_MD *digest, CONF *conf, char *section);
                     85: static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
                     86:     X509 *x, X509 *xca, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *sigopts,
                     87:     char *serial, int create, int days, int clrext, CONF *conf, char *section,
                     88:     ASN1_INTEGER *sno);
                     89: static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
1.19      inoguchi   90:
                     91: static struct {
                     92:        char *alias;
                     93:        int aliasout;
                     94:        int badops;
                     95:        int C;
                     96:        int CA_createserial;
                     97:        int CA_flag;
                     98:        char *CAfile;
                     99:        int CAformat;
                    100:        char *CAkeyfile;
                    101:        int CAkeyformat;
                    102:        char *CAserial;
                    103:        unsigned long certflag;
                    104:        int checkend;
                    105:        int checkoffset;
                    106:        int clrext;
                    107:        int clrreject;
                    108:        int clrtrust;
                    109:        int days;
                    110:        const EVP_MD *digest;
                    111:        int email;
                    112:        int enddate;
                    113:        char *extfile;
                    114:        char *extsect;
                    115:        int fingerprint;
                    116:        char *infile;
                    117:        int informat;
                    118:        int issuer;
                    119:        int issuer_hash;
                    120: #ifndef OPENSSL_NO_MD5
                    121:        int issuer_hash_old;
                    122: #endif
                    123:        char *keyfile;
                    124:        int keyformat;
                    125:        const EVP_MD *md_alg;
                    126:        int modulus;
                    127:        int next_serial;
                    128:        unsigned long nmflag;
                    129:        int noout;
                    130:        int num;
                    131:        int ocspid;
                    132:        ASN1_OBJECT *objtmp;
                    133:        int ocsp_uri;
                    134:        char *outfile;
                    135:        int outformat;
                    136:        char *passargin;
                    137:        int pprint;
                    138:        int pubkey;
                    139:        STACK_OF(ASN1_OBJECT) *reject;
                    140:        int reqfile;
                    141:        int serial;
                    142:        int sign_flag;
                    143:        STACK_OF(OPENSSL_STRING) *sigopts;
                    144:        ASN1_INTEGER *sno;
                    145:        int startdate;
                    146:        int subject;
                    147:        int subject_hash;
                    148: #ifndef OPENSSL_NO_MD5
                    149:        int subject_hash_old;
                    150: #endif
                    151:        int text;
                    152:        STACK_OF(ASN1_OBJECT) *trust;
                    153:        int trustout;
                    154:        int x509req;
1.31      tb        155: } cfg;
1.19      inoguchi  156:
                    157: static int
                    158: x509_opt_addreject(char *arg)
                    159: {
1.31      tb        160:        if ((cfg.objtmp = OBJ_txt2obj(arg, 0)) == NULL) {
1.19      inoguchi  161:                BIO_printf(bio_err, "Invalid reject object value %s\n", arg);
                    162:                return (1);
                    163:        }
                    164:
1.31      tb        165:        if (cfg.reject == NULL &&
                    166:            (cfg.reject = sk_ASN1_OBJECT_new_null()) == NULL)
1.19      inoguchi  167:                return (1);
                    168:
1.31      tb        169:        if (!sk_ASN1_OBJECT_push(cfg.reject, cfg.objtmp))
1.19      inoguchi  170:                return (1);
                    171:
1.31      tb        172:        cfg.trustout = 1;
1.19      inoguchi  173:        return (0);
                    174: }
                    175:
                    176: static int
                    177: x509_opt_addtrust(char *arg)
                    178: {
1.31      tb        179:        if ((cfg.objtmp = OBJ_txt2obj(arg, 0)) == NULL) {
1.19      inoguchi  180:                BIO_printf(bio_err, "Invalid trust object value %s\n", arg);
                    181:                return (1);
                    182:        }
                    183:
1.31      tb        184:        if (cfg.trust == NULL &&
                    185:            (cfg.trust = sk_ASN1_OBJECT_new_null()) == NULL)
1.19      inoguchi  186:                return (1);
                    187:
1.31      tb        188:        if (!sk_ASN1_OBJECT_push(cfg.trust, cfg.objtmp))
1.19      inoguchi  189:                return (1);
                    190:
1.31      tb        191:        cfg.trustout = 1;
1.19      inoguchi  192:        return (0);
                    193: }
                    194:
                    195: static int
                    196: x509_opt_ca(char *arg)
                    197: {
1.31      tb        198:        cfg.CAfile = arg;
                    199:        cfg.CA_flag = ++cfg.num;
1.19      inoguchi  200:        return (0);
                    201: }
                    202:
                    203: static int
                    204: x509_opt_certopt(char *arg)
                    205: {
1.31      tb        206:        if (!set_cert_ex(&cfg.certflag, arg))
1.19      inoguchi  207:                return (1);
                    208:
                    209:        return (0);
                    210: }
                    211:
                    212: static int
                    213: x509_opt_checkend(char *arg)
                    214: {
                    215:        const char *errstr;
                    216:
1.31      tb        217:        cfg.checkoffset = strtonum(arg, 0, INT_MAX, &errstr);
1.19      inoguchi  218:        if (errstr != NULL) {
                    219:                BIO_printf(bio_err, "checkend unusable: %s\n", errstr);
                    220:                return (1);
                    221:        }
1.31      tb        222:        cfg.checkend = 1;
1.19      inoguchi  223:        return (0);
                    224: }
                    225:
                    226: static int
                    227: x509_opt_dates(void)
                    228: {
1.31      tb        229:        cfg.startdate = ++cfg.num;
                    230:        cfg.enddate = ++cfg.num;
1.19      inoguchi  231:        return (0);
                    232: }
                    233:
                    234: static int
                    235: x509_opt_days(char *arg)
                    236: {
                    237:        const char *errstr;
                    238:
1.31      tb        239:        cfg.days = strtonum(arg, 1, INT_MAX, &errstr);
1.19      inoguchi  240:        if (errstr != NULL) {
                    241:                BIO_printf(bio_err, "bad number of days: %s\n", errstr);
                    242:                return (1);
                    243:        }
                    244:        return (0);
                    245: }
                    246:
                    247: static int
                    248: x509_opt_digest(int argc, char **argv, int *argsused)
                    249: {
                    250:        char *name = argv[0];
                    251:
                    252:        if (*name++ != '-')
                    253:                return (1);
                    254:
1.31      tb        255:        if ((cfg.md_alg = EVP_get_digestbyname(name)) != NULL) {
                    256:                cfg.digest = cfg.md_alg;
1.19      inoguchi  257:        } else {
                    258:                BIO_printf(bio_err, "unknown option %s\n", *argv);
1.31      tb        259:                cfg.badops = 1;
1.19      inoguchi  260:                return (1);
                    261:        }
                    262:
                    263:        *argsused = 1;
                    264:        return (0);
                    265: }
                    266:
                    267: static int
                    268: x509_opt_nameopt(char *arg)
                    269: {
1.31      tb        270:        if (!set_name_ex(&cfg.nmflag, arg))
1.19      inoguchi  271:                return (1);
                    272:
                    273:        return (0);
                    274: }
                    275:
                    276: static int
                    277: x509_opt_set_serial(char *arg)
                    278: {
1.31      tb        279:        ASN1_INTEGER_free(cfg.sno);
                    280:        if ((cfg.sno = s2i_ASN1_INTEGER(NULL, arg)) == NULL)
1.19      inoguchi  281:                return (1);
                    282:
                    283:        return (0);
                    284: }
                    285:
                    286: static int
                    287: x509_opt_setalias(char *arg)
                    288: {
1.31      tb        289:        cfg.alias = arg;
                    290:        cfg.trustout = 1;
1.19      inoguchi  291:        return (0);
                    292: }
                    293:
                    294: static int
                    295: x509_opt_signkey(char *arg)
                    296: {
1.31      tb        297:        cfg.keyfile = arg;
                    298:        cfg.sign_flag = ++cfg.num;
1.19      inoguchi  299:        return (0);
                    300: }
                    301:
                    302: static int
                    303: x509_opt_sigopt(char *arg)
                    304: {
1.31      tb        305:        if (cfg.sigopts == NULL &&
                    306:            (cfg.sigopts = sk_OPENSSL_STRING_new_null()) == NULL)
1.19      inoguchi  307:                return (1);
                    308:
1.31      tb        309:        if (!sk_OPENSSL_STRING_push(cfg.sigopts, arg))
1.19      inoguchi  310:                return (1);
                    311:
                    312:        return (0);
                    313: }
                    314:
                    315: static const struct option x509_options[] = {
                    316:        {
                    317:                .name = "C",
                    318:                .desc = "Convert the certificate into C code",
                    319:                .type = OPTION_ORDER,
1.31      tb        320:                .opt.order = &cfg.C,
                    321:                .order = &cfg.num,
1.19      inoguchi  322:        },
                    323:        {
                    324:                .name = "addreject",
                    325:                .argname = "arg",
                    326:                .desc = "Reject certificate for a given purpose",
                    327:                .type = OPTION_ARG_FUNC,
                    328:                .opt.argfunc = x509_opt_addreject,
                    329:        },
                    330:        {
                    331:                .name = "addtrust",
                    332:                .argname = "arg",
                    333:                .desc = "Trust certificate for a given purpose",
                    334:                .type = OPTION_ARG_FUNC,
                    335:                .opt.argfunc = x509_opt_addtrust,
                    336:        },
                    337:        {
                    338:                .name = "alias",
                    339:                .desc = "Output certificate alias",
                    340:                .type = OPTION_ORDER,
1.31      tb        341:                .opt.order = &cfg.aliasout,
                    342:                .order = &cfg.num,
1.19      inoguchi  343:        },
                    344:        {
                    345:                .name = "CA",
                    346:                .argname = "file",
                    347:                .desc = "CA certificate in PEM format unless -CAform is specified",
                    348:                .type = OPTION_ARG_FUNC,
                    349:                .opt.argfunc = x509_opt_ca,
                    350:        },
                    351:        {
                    352:                .name = "CAcreateserial",
                    353:                .desc = "Create serial number file if it does not exist",
                    354:                .type = OPTION_ORDER,
1.31      tb        355:                .opt.order = &cfg.CA_createserial,
                    356:                .order = &cfg.num,
1.19      inoguchi  357:        },
                    358:        {
                    359:                .name = "CAform",
                    360:                .argname = "fmt",
                    361:                .desc = "CA format - default PEM",
                    362:                .type = OPTION_ARG_FORMAT,
1.31      tb        363:                .opt.value = &cfg.CAformat,
1.19      inoguchi  364:        },
                    365:        {
                    366:                .name = "CAkey",
                    367:                .argname = "file",
                    368:                .desc = "CA key in PEM format unless -CAkeyform is specified\n"
                    369:                        "if omitted, the key is assumed to be in the CA file",
                    370:                .type = OPTION_ARG,
1.31      tb        371:                .opt.arg = &cfg.CAkeyfile,
1.19      inoguchi  372:        },
                    373:        {
                    374:                .name = "CAkeyform",
                    375:                .argname = "fmt",
                    376:                .desc = "CA key format - default PEM",
                    377:                .type = OPTION_ARG_FORMAT,
1.31      tb        378:                .opt.value = &cfg.CAkeyformat,
1.19      inoguchi  379:        },
                    380:        {
                    381:                .name = "CAserial",
                    382:                .argname = "file",
                    383:                .desc = "Serial file",
                    384:                .type = OPTION_ARG,
1.31      tb        385:                .opt.arg = &cfg.CAserial,
1.19      inoguchi  386:        },
                    387:        {
                    388:                .name = "certopt",
                    389:                .argname = "option",
                    390:                .desc = "Various certificate text options",
                    391:                .type = OPTION_ARG_FUNC,
                    392:                .opt.argfunc = x509_opt_certopt,
                    393:        },
                    394:        {
                    395:                .name = "checkend",
                    396:                .argname = "arg",
                    397:                .desc = "Check whether the cert expires in the next arg seconds\n"
                    398:                        "exit 1 if so, 0 if not",
                    399:                .type = OPTION_ARG_FUNC,
                    400:                .opt.argfunc = x509_opt_checkend,
                    401:        },
                    402:        {
                    403:                .name = "clrext",
                    404:                .desc = "Clear all extensions",
                    405:                .type = OPTION_FLAG,
1.31      tb        406:                .opt.flag = &cfg.clrext,
1.19      inoguchi  407:        },
                    408:        {
                    409:                .name = "clrreject",
                    410:                .desc = "Clear all rejected purposes",
                    411:                .type = OPTION_ORDER,
1.31      tb        412:                .opt.order = &cfg.clrreject,
                    413:                .order = &cfg.num,
1.19      inoguchi  414:        },
                    415:        {
                    416:                .name = "clrtrust",
                    417:                .desc = "Clear all trusted purposes",
                    418:                .type = OPTION_ORDER,
1.31      tb        419:                .opt.order = &cfg.clrtrust,
                    420:                .order = &cfg.num,
1.19      inoguchi  421:        },
                    422:        {
                    423:                .name = "dates",
                    424:                .desc = "Both Before and After dates",
                    425:                .type = OPTION_FUNC,
                    426:                .opt.func = x509_opt_dates,
                    427:        },
                    428:        {
                    429:                .name = "days",
                    430:                .argname = "arg",
                    431:                .desc = "How long till expiry of a signed certificate - def 30 days",
                    432:                .type = OPTION_ARG_FUNC,
                    433:                .opt.argfunc = x509_opt_days,
                    434:        },
                    435:        {
                    436:                .name = "email",
                    437:                .desc = "Print email address(es)",
                    438:                .type = OPTION_ORDER,
1.31      tb        439:                .opt.order = &cfg.email,
                    440:                .order = &cfg.num,
1.19      inoguchi  441:        },
                    442:        {
                    443:                .name = "enddate",
                    444:                .desc = "Print notAfter field",
                    445:                .type = OPTION_ORDER,
1.31      tb        446:                .opt.order = &cfg.enddate,
                    447:                .order = &cfg.num,
1.19      inoguchi  448:        },
                    449:        {
                    450:                .name = "extensions",
                    451:                .argname = "section",
                    452:                .desc = "Section from config file with X509V3 extensions to add",
                    453:                .type = OPTION_ARG,
1.31      tb        454:                .opt.arg = &cfg.extsect,
1.19      inoguchi  455:        },
                    456:        {
                    457:                .name = "extfile",
                    458:                .argname = "file",
                    459:                .desc = "Configuration file with X509V3 extensions to add",
                    460:                .type = OPTION_ARG,
1.31      tb        461:                .opt.arg = &cfg.extfile,
1.19      inoguchi  462:        },
                    463:        {
                    464:                .name = "fingerprint",
                    465:                .desc = "Print the certificate fingerprint",
                    466:                .type = OPTION_ORDER,
1.31      tb        467:                .opt.order = &cfg.fingerprint,
                    468:                .order = &cfg.num,
1.19      inoguchi  469:        },
                    470:        {
                    471:                .name = "hash",
                    472:                .desc = "Synonym for -subject_hash",
                    473:                .type = OPTION_ORDER,
1.31      tb        474:                .opt.order = &cfg.subject_hash,
                    475:                .order = &cfg.num,
1.19      inoguchi  476:        },
                    477:        {
                    478:                .name = "in",
                    479:                .argname = "file",
                    480:                .desc = "Input file - default stdin",
                    481:                .type = OPTION_ARG,
1.31      tb        482:                .opt.arg = &cfg.infile,
1.19      inoguchi  483:        },
                    484:        {
                    485:                .name = "inform",
                    486:                .argname = "fmt",
                    487:                .desc = "Input format - default PEM (one of DER, NET or PEM)",
                    488:                .type = OPTION_ARG_FORMAT,
1.31      tb        489:                .opt.value = &cfg.informat,
1.19      inoguchi  490:        },
                    491:        {
                    492:                .name = "issuer",
                    493:                .desc = "Print issuer name",
                    494:                .type = OPTION_ORDER,
1.31      tb        495:                .opt.order = &cfg.issuer,
                    496:                .order = &cfg.num,
1.19      inoguchi  497:        },
                    498:        {
                    499:                .name = "issuer_hash",
                    500:                .desc = "Print issuer hash value",
                    501:                .type = OPTION_ORDER,
1.31      tb        502:                .opt.order = &cfg.issuer_hash,
                    503:                .order = &cfg.num,
1.19      inoguchi  504:        },
                    505: #ifndef OPENSSL_NO_MD5
                    506:        {
                    507:                .name = "issuer_hash_old",
                    508:                .desc = "Print old-style (MD5) issuer hash value",
                    509:                .type = OPTION_ORDER,
1.31      tb        510:                .opt.order = &cfg.issuer_hash_old,
                    511:                .order = &cfg.num,
1.19      inoguchi  512:        },
                    513: #endif
                    514:        {
                    515:                .name = "keyform",
                    516:                .argname = "fmt",
                    517:                .desc = "Private key format - default PEM",
                    518:                .type = OPTION_ARG_FORMAT,
1.31      tb        519:                .opt.value = &cfg.keyformat,
1.19      inoguchi  520:        },
                    521:        {
                    522:                .name = "modulus",
                    523:                .desc = "Print the RSA key modulus",
                    524:                .type = OPTION_ORDER,
1.31      tb        525:                .opt.order = &cfg.modulus,
                    526:                .order = &cfg.num,
1.19      inoguchi  527:        },
                    528:        {
                    529:                .name = "nameopt",
                    530:                .argname = "option",
                    531:                .desc = "Various certificate name options",
                    532:                .type = OPTION_ARG_FUNC,
                    533:                .opt.argfunc = x509_opt_nameopt,
                    534:        },
                    535:        {
                    536:                .name = "next_serial",
                    537:                .desc = "Print the next serial number",
                    538:                .type = OPTION_ORDER,
1.31      tb        539:                .opt.order = &cfg.next_serial,
                    540:                .order = &cfg.num,
1.19      inoguchi  541:        },
                    542:        {
                    543:                .name = "noout",
                    544:                .desc = "No certificate output",
                    545:                .type = OPTION_ORDER,
1.31      tb        546:                .opt.order = &cfg.noout,
                    547:                .order = &cfg.num,
1.19      inoguchi  548:        },
                    549:        {
                    550:                .name = "ocsp_uri",
                    551:                .desc = "Print OCSP Responder URL(s)",
                    552:                .type = OPTION_ORDER,
1.31      tb        553:                .opt.order = &cfg.ocsp_uri,
                    554:                .order = &cfg.num,
1.19      inoguchi  555:        },
                    556:        {
                    557:                .name = "ocspid",
                    558:                .desc = "Print OCSP hash values for the subject name and public key",
                    559:                .type = OPTION_ORDER,
1.31      tb        560:                .opt.order = &cfg.ocspid,
                    561:                .order = &cfg.num,
1.19      inoguchi  562:        },
                    563:        {
                    564:                .name = "out",
                    565:                .argname = "file",
                    566:                .desc = "Output file - default stdout",
                    567:                .type = OPTION_ARG,
1.31      tb        568:                .opt.arg = &cfg.outfile,
1.19      inoguchi  569:        },
                    570:        {
                    571:                .name = "outform",
                    572:                .argname = "fmt",
                    573:                .desc = "Output format - default PEM (one of DER, NET or PEM)",
                    574:                .type = OPTION_ARG_FORMAT,
1.31      tb        575:                .opt.value = &cfg.outformat,
1.19      inoguchi  576:        },
                    577:        {
                    578:                .name = "passin",
                    579:                .argname = "src",
                    580:                .desc = "Private key password source",
                    581:                .type = OPTION_ARG,
1.31      tb        582:                .opt.arg = &cfg.passargin,
1.19      inoguchi  583:        },
                    584:        {
                    585:                .name = "pubkey",
                    586:                .desc = "Output the public key",
                    587:                .type = OPTION_ORDER,
1.31      tb        588:                .opt.order = &cfg.pubkey,
                    589:                .order = &cfg.num,
1.19      inoguchi  590:        },
                    591:        {
                    592:                .name = "purpose",
                    593:                .desc = "Print out certificate purposes",
                    594:                .type = OPTION_ORDER,
1.31      tb        595:                .opt.order = &cfg.pprint,
                    596:                .order = &cfg.num,
1.19      inoguchi  597:        },
                    598:        {
                    599:                .name = "req",
                    600:                .desc = "Input is a certificate request, sign and output",
                    601:                .type = OPTION_FLAG,
1.31      tb        602:                .opt.flag = &cfg.reqfile,
1.19      inoguchi  603:        },
                    604:        {
                    605:                .name = "serial",
                    606:                .desc = "Print serial number value",
                    607:                .type = OPTION_ORDER,
1.31      tb        608:                .opt.order = &cfg.serial,
                    609:                .order = &cfg.num,
1.19      inoguchi  610:        },
                    611:        {
                    612:                .name = "set_serial",
                    613:                .argname = "n",
                    614:                .desc = "Serial number to use",
                    615:                .type = OPTION_ARG_FUNC,
                    616:                .opt.argfunc = x509_opt_set_serial,
                    617:        },
                    618:        {
                    619:                .name = "setalias",
                    620:                .argname = "arg",
                    621:                .desc = "Set certificate alias",
                    622:                .type = OPTION_ARG_FUNC,
                    623:                .opt.argfunc = x509_opt_setalias,
                    624:        },
                    625:        {
                    626:                .name = "signkey",
                    627:                .argname = "file",
                    628:                .desc = "Self sign cert with arg",
                    629:                .type = OPTION_ARG_FUNC,
                    630:                .opt.argfunc = x509_opt_signkey,
                    631:        },
                    632:        {
                    633:                .name = "sigopt",
                    634:                .argname = "nm:v",
                    635:                .desc = "Various signature algorithm options",
                    636:                .type = OPTION_ARG_FUNC,
                    637:                .opt.argfunc = x509_opt_sigopt,
                    638:        },
                    639:        {
                    640:                .name = "startdate",
                    641:                .desc = "Print notBefore field",
                    642:                .type = OPTION_ORDER,
1.31      tb        643:                .opt.order = &cfg.startdate,
                    644:                .order = &cfg.num,
1.19      inoguchi  645:        },
                    646:        {
                    647:                .name = "subject",
                    648:                .desc = "Print subject name",
                    649:                .type = OPTION_ORDER,
1.31      tb        650:                .opt.order = &cfg.subject,
                    651:                .order = &cfg.num,
1.19      inoguchi  652:        },
                    653:        {
                    654:                .name = "subject_hash",
                    655:                .desc = "Print subject hash value",
                    656:                .type = OPTION_ORDER,
1.31      tb        657:                .opt.order = &cfg.subject_hash,
                    658:                .order = &cfg.num,
1.19      inoguchi  659:        },
                    660: #ifndef OPENSSL_NO_MD5
                    661:        {
                    662:                .name = "subject_hash_old",
                    663:                .desc = "Print old-style (MD5) subject hash value",
                    664:                .type = OPTION_ORDER,
1.31      tb        665:                .opt.order = &cfg.subject_hash_old,
                    666:                .order = &cfg.num,
1.19      inoguchi  667:        },
                    668: #endif
                    669:        {
                    670:                .name = "text",
                    671:                .desc = "Print the certificate in text form",
                    672:                .type = OPTION_ORDER,
1.31      tb        673:                .opt.order = &cfg.text,
                    674:                .order = &cfg.num,
1.19      inoguchi  675:        },
                    676:        {
                    677:                .name = "trustout",
                    678:                .desc = "Output a trusted certificate",
                    679:                .type = OPTION_FLAG,
1.31      tb        680:                .opt.flag = &cfg.trustout,
1.19      inoguchi  681:        },
                    682:        {
                    683:                .name = "x509toreq",
                    684:                .desc = "Output a certification request object",
                    685:                .type = OPTION_ORDER,
1.31      tb        686:                .opt.order = &cfg.x509req,
                    687:                .order = &cfg.num,
1.19      inoguchi  688:        },
                    689:        {
                    690:                .name = NULL,
                    691:                .desc = "",
                    692:                .type = OPTION_ARGV_FUNC,
                    693:                .opt.argvfunc = x509_opt_digest,
                    694:        },
                    695:        { NULL },
                    696: };
                    697:
                    698: static void
                    699: x509_usage(void)
                    700: {
                    701:        fprintf(stderr, "usage: x509 "
                    702:            "[-C] [-addreject arg] [-addtrust arg] [-alias] [-CA file]\n"
                    703:            "    [-CAcreateserial] [-CAform der | pem] [-CAkey file]\n"
                    704:            "    [-CAkeyform der | pem] [-CAserial file] [-certopt option]\n"
                    705:            "    [-checkend arg] [-clrext] [-clrreject] [-clrtrust] [-dates]\n"
                    706:            "    [-days arg] [-email] [-enddate] [-extensions section]\n"
                    707:            "    [-extfile file] [-fingerprint] [-hash] [-in file]\n"
                    708:            "    [-inform der | net | pem] [-issuer] [-issuer_hash]\n"
                    709:            "    [-issuer_hash_old] [-keyform der | pem] [-md5 | -sha1]\n"
                    710:            "    [-modulus] [-nameopt option] [-next_serial] [-noout]\n"
                    711:            "    [-ocsp_uri] [-ocspid] [-out file]\n"
                    712:            "    [-outform der | net | pem] [-passin arg] [-pubkey]\n"
                    713:            "    [-purpose] [-req] [-serial] [-set_serial n] [-setalias arg]\n"
                    714:            "    [-signkey file] [-sigopt nm:v] [-startdate] [-subject]\n"
                    715:            "    [-subject_hash] [-subject_hash_old] [-text] [-trustout]\n"
                    716:            "    [-x509toreq]\n");
                    717:        fprintf(stderr, "\n");
                    718:        options_usage(x509_options);
                    719:        fprintf(stderr, "\n");
                    720: }
1.1       jsing     721:
                    722: int
                    723: x509_main(int argc, char **argv)
                    724: {
                    725:        int ret = 1;
                    726:        X509_REQ *req = NULL;
                    727:        X509 *x = NULL, *xca = NULL;
                    728:        EVP_PKEY *Upkey = NULL, *CApkey = NULL;
1.19      inoguchi  729:        int i;
1.1       jsing     730:        BIO *out = NULL;
                    731:        BIO *STDout = NULL;
                    732:        X509_STORE *ctx = NULL;
                    733:        X509_REQ *rq = NULL;
                    734:        char buf[256];
                    735:        CONF *extconf = NULL;
1.19      inoguchi  736:        char *passin = NULL;
1.10      doug      737:
1.30      joshua    738:        if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
                    739:                perror("pledge");
                    740:                exit(1);
1.10      doug      741:        }
1.1       jsing     742:
1.31      tb        743:        memset(&cfg, 0, sizeof(cfg));
                    744:        cfg.days = DEF_DAYS;
                    745:        cfg.informat = FORMAT_PEM;
                    746:        cfg.outformat = FORMAT_PEM;
                    747:        cfg.keyformat = FORMAT_PEM;
                    748:        cfg.CAformat = FORMAT_PEM;
                    749:        cfg.CAkeyformat = FORMAT_PEM;
1.1       jsing     750:
                    751:        STDout = BIO_new_fp(stdout, BIO_NOCLOSE);
                    752:
                    753:        ctx = X509_STORE_new();
                    754:        if (ctx == NULL)
                    755:                goto end;
                    756:        X509_STORE_set_verify_cb(ctx, callb);
                    757:
1.19      inoguchi  758:        if (options_parse(argc, argv, x509_options, NULL, NULL) != 0)
                    759:                goto bad;
1.1       jsing     760:
1.31      tb        761:        if (cfg.badops) {
1.16      jsing     762:  bad:
1.19      inoguchi  763:                x509_usage();
1.1       jsing     764:                goto end;
                    765:        }
                    766:
1.31      tb        767:        if (!app_passwd(bio_err, cfg.passargin, NULL, &passin, NULL)) {
1.1       jsing     768:                BIO_printf(bio_err, "Error getting password\n");
                    769:                goto end;
                    770:        }
                    771:        if (!X509_STORE_set_default_paths(ctx)) {
                    772:                ERR_print_errors(bio_err);
                    773:                goto end;
                    774:        }
1.32      tb        775:        if (cfg.CAkeyfile == NULL && cfg.CA_flag && cfg.CAformat == FORMAT_PEM) {
1.31      tb        776:                cfg.CAkeyfile = cfg.CAfile;
1.32      tb        777:        } else if (cfg.CA_flag && cfg.CAkeyfile == NULL) {
1.1       jsing     778:                BIO_printf(bio_err,
                    779:                    "need to specify a CAkey if using the CA command\n");
                    780:                goto end;
                    781:        }
1.31      tb        782:        if (cfg.extfile != NULL) {
1.1       jsing     783:                long errorline = -1;
                    784:                X509V3_CTX ctx2;
                    785:                extconf = NCONF_new(NULL);
1.31      tb        786:                if (!NCONF_load(extconf, cfg.extfile, &errorline)) {
1.1       jsing     787:                        if (errorline <= 0)
                    788:                                BIO_printf(bio_err,
                    789:                                    "error loading the config file '%s'\n",
1.31      tb        790:                                    cfg.extfile);
1.1       jsing     791:                        else
                    792:                                BIO_printf(bio_err,
                    793:                                    "error on line %ld of config file '%s'\n",
1.31      tb        794:                                    errorline, cfg.extfile);
1.1       jsing     795:                        goto end;
                    796:                }
1.31      tb        797:                if (cfg.extsect == NULL) {
1.32      tb        798:                        cfg.extsect = NCONF_get_string(extconf, "default",
                    799:                            "extensions");
1.31      tb        800:                        if (cfg.extsect == NULL) {
1.1       jsing     801:                                ERR_clear_error();
1.31      tb        802:                                cfg.extsect = "default";
1.1       jsing     803:                        }
                    804:                }
                    805:                X509V3_set_ctx_test(&ctx2);
                    806:                X509V3_set_nconf(&ctx2, extconf);
1.32      tb        807:                if (!X509V3_EXT_add_nconf(extconf, &ctx2, cfg.extsect, NULL)) {
1.1       jsing     808:                        BIO_printf(bio_err,
1.32      tb        809:                            "Error Loading extension section %s\n", cfg.extsect);
1.1       jsing     810:                        ERR_print_errors(bio_err);
                    811:                        goto end;
                    812:                }
                    813:        }
1.31      tb        814:        if (cfg.reqfile) {
1.1       jsing     815:                EVP_PKEY *pkey;
                    816:                BIO *in;
                    817:
1.31      tb        818:                if (!cfg.sign_flag && !cfg.CA_flag) {
1.20      inoguchi  819:                        BIO_printf(bio_err,
                    820:                            "We need a private key to sign with\n");
1.1       jsing     821:                        goto end;
                    822:                }
                    823:                in = BIO_new(BIO_s_file());
                    824:                if (in == NULL) {
                    825:                        ERR_print_errors(bio_err);
                    826:                        goto end;
                    827:                }
1.31      tb        828:                if (cfg.infile == NULL)
1.1       jsing     829:                        BIO_set_fp(in, stdin, BIO_NOCLOSE | BIO_FP_TEXT);
                    830:                else {
1.31      tb        831:                        if (BIO_read_filename(in, cfg.infile) <= 0) {
                    832:                                perror(cfg.infile);
1.1       jsing     833:                                BIO_free(in);
                    834:                                goto end;
                    835:                        }
                    836:                }
                    837:                req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
                    838:                BIO_free(in);
                    839:
                    840:                if (req == NULL) {
                    841:                        ERR_print_errors(bio_err);
                    842:                        goto end;
                    843:                }
1.29      tb        844:                if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) {
1.1       jsing     845:                        BIO_printf(bio_err, "error unpacking public key\n");
                    846:                        goto end;
                    847:                }
                    848:                i = X509_REQ_verify(req, pkey);
                    849:                if (i < 0) {
                    850:                        BIO_printf(bio_err, "Signature verification error\n");
                    851:                        ERR_print_errors(bio_err);
                    852:                        goto end;
                    853:                }
                    854:                if (i == 0) {
1.20      inoguchi  855:                        BIO_printf(bio_err,
                    856:                            "Signature did not match the certificate request\n");
1.1       jsing     857:                        goto end;
                    858:                } else
                    859:                        BIO_printf(bio_err, "Signature ok\n");
                    860:
1.20      inoguchi  861:                print_name(bio_err, "subject=", X509_REQ_get_subject_name(req),
1.31      tb        862:                    cfg.nmflag);
1.1       jsing     863:
                    864:                if ((x = X509_new()) == NULL)
                    865:                        goto end;
                    866:
1.31      tb        867:                if (cfg.sno == NULL) {
                    868:                        cfg.sno = ASN1_INTEGER_new();
1.32      tb        869:                        if (cfg.sno == NULL || !rand_serial(NULL, cfg.sno))
1.1       jsing     870:                                goto end;
1.31      tb        871:                        if (!X509_set_serialNumber(x, cfg.sno))
1.1       jsing     872:                                goto end;
1.31      tb        873:                        ASN1_INTEGER_free(cfg.sno);
                    874:                        cfg.sno = NULL;
                    875:                } else if (!X509_set_serialNumber(x, cfg.sno))
1.1       jsing     876:                        goto end;
                    877:
1.25      tb        878:                if (!X509_set_issuer_name(x, X509_REQ_get_subject_name(req)))
1.1       jsing     879:                        goto end;
1.25      tb        880:                if (!X509_set_subject_name(x, X509_REQ_get_subject_name(req)))
1.1       jsing     881:                        goto end;
                    882:
1.23      inoguchi  883:                if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL)
                    884:                        goto end;
1.31      tb        885:                if (X509_time_adj_ex(X509_get_notAfter(x), cfg.days, 0,
1.23      inoguchi  886:                    NULL) == NULL)
                    887:                        goto end;
1.1       jsing     888:
1.29      tb        889:                if ((pkey = X509_REQ_get0_pubkey(req)) == NULL)
1.23      inoguchi  890:                        goto end;
1.33      tb        891:                if (!X509_set_pubkey(x, pkey))
1.23      inoguchi  892:                        goto end;
                    893:        } else {
1.32      tb        894:                x = load_cert(bio_err, cfg.infile, cfg.informat, NULL,
                    895:                    "Certificate");
1.23      inoguchi  896:        }
1.1       jsing     897:        if (x == NULL)
                    898:                goto end;
1.23      inoguchi  899:
1.31      tb        900:        if (cfg.CA_flag) {
1.32      tb        901:                xca = load_cert(bio_err, cfg.CAfile, cfg.CAformat, NULL,
                    902:                    "CA Certificate");
1.1       jsing     903:                if (xca == NULL)
                    904:                        goto end;
                    905:        }
1.31      tb        906:        if (!cfg.noout || cfg.text || cfg.next_serial) {
1.20      inoguchi  907:                OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3");
1.1       jsing     908:
                    909:                out = BIO_new(BIO_s_file());
                    910:                if (out == NULL) {
                    911:                        ERR_print_errors(bio_err);
                    912:                        goto end;
                    913:                }
1.31      tb        914:                if (cfg.outfile == NULL) {
1.1       jsing     915:                        BIO_set_fp(out, stdout, BIO_NOCLOSE);
                    916:                } else {
1.31      tb        917:                        if (BIO_write_filename(out, cfg.outfile) <= 0) {
                    918:                                perror(cfg.outfile);
1.1       jsing     919:                                goto end;
                    920:                        }
                    921:                }
                    922:        }
1.31      tb        923:        if (cfg.alias != NULL) {
                    924:                if (!X509_alias_set1(x, (unsigned char *)cfg.alias, -1))
1.23      inoguchi  925:                        goto end;
                    926:        }
1.1       jsing     927:
1.31      tb        928:        if (cfg.clrtrust)
1.1       jsing     929:                X509_trust_clear(x);
1.31      tb        930:        if (cfg.clrreject)
1.1       jsing     931:                X509_reject_clear(x);
                    932:
1.31      tb        933:        if (cfg.trust != NULL) {
                    934:                for (i = 0; i < sk_ASN1_OBJECT_num(cfg.trust); i++) {
1.32      tb        935:                        cfg.objtmp = sk_ASN1_OBJECT_value(cfg.trust, i);
1.31      tb        936:                        if (!X509_add1_trust_object(x, cfg.objtmp))
1.23      inoguchi  937:                                goto end;
1.1       jsing     938:                }
                    939:        }
1.31      tb        940:        if (cfg.reject != NULL) {
                    941:                for (i = 0; i < sk_ASN1_OBJECT_num(cfg.reject); i++) {
1.32      tb        942:                        cfg.objtmp = sk_ASN1_OBJECT_value(cfg.reject, i);
1.31      tb        943:                        if (!X509_add1_reject_object(x, cfg.objtmp))
1.23      inoguchi  944:                                goto end;
1.1       jsing     945:                }
                    946:        }
1.31      tb        947:        if (cfg.num) {
                    948:                for (i = 1; i <= cfg.num; i++) {
                    949:                        if (cfg.issuer == i) {
1.1       jsing     950:                                print_name(STDout, "issuer= ",
1.32      tb        951:                                    X509_get_issuer_name(x), cfg.nmflag);
1.31      tb        952:                        } else if (cfg.subject == i) {
1.1       jsing     953:                                print_name(STDout, "subject= ",
1.32      tb        954:                                    X509_get_subject_name(x), cfg.nmflag);
1.31      tb        955:                        } else if (cfg.serial == i) {
1.1       jsing     956:                                BIO_printf(STDout, "serial=");
                    957:                                i2a_ASN1_INTEGER(STDout,
                    958:                                    X509_get_serialNumber(x));
                    959:                                BIO_printf(STDout, "\n");
1.31      tb        960:                        } else if (cfg.next_serial == i) {
1.1       jsing     961:                                BIGNUM *bnser;
                    962:                                ASN1_INTEGER *ser;
1.32      tb        963:
1.1       jsing     964:                                ser = X509_get_serialNumber(x);
1.23      inoguchi  965:                                if (ser == NULL)
                    966:                                        goto end;
1.1       jsing     967:                                bnser = ASN1_INTEGER_to_BN(ser, NULL);
1.21      inoguchi  968:                                if (bnser == NULL)
1.1       jsing     969:                                        goto end;
1.22      inoguchi  970:                                if (!BN_add_word(bnser, 1)) {
                    971:                                        BN_free(bnser);
1.1       jsing     972:                                        goto end;
1.22      inoguchi  973:                                }
1.1       jsing     974:                                ser = BN_to_ASN1_INTEGER(bnser, NULL);
1.22      inoguchi  975:                                if (ser == NULL) {
                    976:                                        BN_free(bnser);
1.1       jsing     977:                                        goto end;
1.22      inoguchi  978:                                }
1.1       jsing     979:                                BN_free(bnser);
                    980:                                i2a_ASN1_INTEGER(out, ser);
                    981:                                ASN1_INTEGER_free(ser);
                    982:                                BIO_puts(out, "\n");
1.32      tb        983:                        } else if (cfg.email == i || cfg.ocsp_uri == i) {
                    984:                                STACK_OF(OPENSSL_STRING) *emlst;
1.1       jsing     985:                                int j;
1.32      tb        986:
1.31      tb        987:                                if (cfg.email == i)
1.1       jsing     988:                                        emlst = X509_get1_email(x);
                    989:                                else
                    990:                                        emlst = X509_get1_ocsp(x);
                    991:                                for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
                    992:                                        BIO_printf(STDout, "%s\n",
                    993:                                            sk_OPENSSL_STRING_value(emlst, j));
                    994:                                X509_email_free(emlst);
1.31      tb        995:                        } else if (cfg.aliasout == i) {
1.24      schwarze  996:                                unsigned char *albuf;
                    997:                                int buflen;
                    998:                                albuf = X509_alias_get0(x, &buflen);
                    999:                                if (albuf != NULL)
                   1000:                                        BIO_printf(STDout, "%.*s\n",
                   1001:                                            buflen, albuf);
1.1       jsing    1002:                                else
                   1003:                                        BIO_puts(STDout, "<No Alias>\n");
1.31      tb       1004:                        } else if (cfg.subject_hash == i) {
1.20      inoguchi 1005:                                BIO_printf(STDout, "%08lx\n",
                   1006:                                    X509_subject_name_hash(x));
1.1       jsing    1007:                        }
                   1008: #ifndef OPENSSL_NO_MD5
1.31      tb       1009:                        else if (cfg.subject_hash_old == i) {
1.20      inoguchi 1010:                                BIO_printf(STDout, "%08lx\n",
                   1011:                                    X509_subject_name_hash_old(x));
1.1       jsing    1012:                        }
                   1013: #endif
1.31      tb       1014:                        else if (cfg.issuer_hash == i) {
1.20      inoguchi 1015:                                BIO_printf(STDout, "%08lx\n",
                   1016:                                    X509_issuer_name_hash(x));
1.1       jsing    1017:                        }
                   1018: #ifndef OPENSSL_NO_MD5
1.31      tb       1019:                        else if (cfg.issuer_hash_old == i) {
1.20      inoguchi 1020:                                BIO_printf(STDout, "%08lx\n",
                   1021:                                    X509_issuer_name_hash_old(x));
1.1       jsing    1022:                        }
                   1023: #endif
1.31      tb       1024:                        else if (cfg.pprint == i) {
1.1       jsing    1025:                                X509_PURPOSE *ptmp;
                   1026:                                int j;
1.32      tb       1027:
1.1       jsing    1028:                                BIO_printf(STDout, "Certificate purposes:\n");
                   1029:                                for (j = 0; j < X509_PURPOSE_get_count(); j++) {
                   1030:                                        ptmp = X509_PURPOSE_get0(j);
                   1031:                                        purpose_print(STDout, x, ptmp);
                   1032:                                }
1.31      tb       1033:                        } else if (cfg.modulus == i) {
1.1       jsing    1034:                                EVP_PKEY *pkey;
                   1035:
1.28      tb       1036:                                pkey = X509_get0_pubkey(x);
1.1       jsing    1037:                                if (pkey == NULL) {
1.20      inoguchi 1038:                                        BIO_printf(bio_err,
                   1039:                                            "Modulus=unavailable\n");
1.1       jsing    1040:                                        ERR_print_errors(bio_err);
                   1041:                                        goto end;
                   1042:                                }
                   1043:                                BIO_printf(STDout, "Modulus=");
1.27      tb       1044:                                if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
                   1045:                                        RSA *rsa = EVP_PKEY_get0_RSA(pkey);
                   1046:                                        const BIGNUM *n = NULL;
                   1047:
                   1048:                                        RSA_get0_key(rsa, &n, NULL, NULL);
                   1049:                                        BN_print(STDout, n);
                   1050:                                } else if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) {
                   1051:                                        DSA *dsa = EVP_PKEY_get0_DSA(pkey);
                   1052:                                        const BIGNUM *pub_key = NULL;
                   1053:
                   1054:                                        DSA_get0_key(dsa, &pub_key, NULL);
                   1055:
                   1056:                                        BN_print(STDout, pub_key);
                   1057:                                } else
1.20      inoguchi 1058:                                        BIO_printf(STDout,
                   1059:                                            "Wrong Algorithm type");
1.1       jsing    1060:                                BIO_printf(STDout, "\n");
1.31      tb       1061:                        } else if (cfg.pubkey == i) {
1.1       jsing    1062:                                EVP_PKEY *pkey;
                   1063:
1.28      tb       1064:                                pkey = X509_get0_pubkey(x);
1.1       jsing    1065:                                if (pkey == NULL) {
1.20      inoguchi 1066:                                        BIO_printf(bio_err,
                   1067:                                            "Error getting public key\n");
1.1       jsing    1068:                                        ERR_print_errors(bio_err);
                   1069:                                        goto end;
                   1070:                                }
                   1071:                                PEM_write_bio_PUBKEY(STDout, pkey);
1.31      tb       1072:                        } else if (cfg.C == i) {
1.1       jsing    1073:                                unsigned char *d;
                   1074:                                char *m;
                   1075:                                int y, z;
                   1076:
1.23      inoguchi 1077:                                m = X509_NAME_oneline(X509_get_subject_name(x),
1.1       jsing    1078:                                    buf, sizeof buf);
1.23      inoguchi 1079:                                if (m == NULL)
                   1080:                                        goto end;
1.1       jsing    1081:                                BIO_printf(STDout, "/* subject:%s */\n", buf);
1.20      inoguchi 1082:                                m = X509_NAME_oneline(X509_get_issuer_name(x),
                   1083:                                    buf, sizeof buf);
1.23      inoguchi 1084:                                if (m == NULL)
                   1085:                                        goto end;
1.1       jsing    1086:                                BIO_printf(STDout, "/* issuer :%s */\n", buf);
                   1087:
                   1088:                                z = i2d_X509(x, NULL);
1.23      inoguchi 1089:                                if (z < 0)
                   1090:                                        goto end;
                   1091:
1.1       jsing    1092:                                m = malloc(z);
1.8       bcook    1093:                                if (m == NULL) {
                   1094:                                        BIO_printf(bio_err, "out of mem\n");
                   1095:                                        goto end;
                   1096:                                }
1.1       jsing    1097:
                   1098:                                d = (unsigned char *) m;
                   1099:                                z = i2d_X509_NAME(X509_get_subject_name(x), &d);
1.23      inoguchi 1100:                                if (z < 0) {
                   1101:                                        free(m);
                   1102:                                        goto end;
                   1103:                                }
1.20      inoguchi 1104:                                BIO_printf(STDout,
                   1105:                                    "unsigned char XXX_subject_name[%d]={\n", z);
1.1       jsing    1106:                                d = (unsigned char *) m;
                   1107:                                for (y = 0; y < z; y++) {
                   1108:                                        BIO_printf(STDout, "0x%02X,", d[y]);
                   1109:                                        if ((y & 0x0f) == 0x0f)
                   1110:                                                BIO_printf(STDout, "\n");
                   1111:                                }
                   1112:                                if (y % 16 != 0)
                   1113:                                        BIO_printf(STDout, "\n");
                   1114:                                BIO_printf(STDout, "};\n");
                   1115:
                   1116:                                z = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d);
1.23      inoguchi 1117:                                if (z < 0) {
                   1118:                                        free(m);
                   1119:                                        goto end;
                   1120:                                }
1.20      inoguchi 1121:                                BIO_printf(STDout,
                   1122:                                    "unsigned char XXX_public_key[%d]={\n", z);
1.1       jsing    1123:                                d = (unsigned char *) m;
                   1124:                                for (y = 0; y < z; y++) {
                   1125:                                        BIO_printf(STDout, "0x%02X,", d[y]);
                   1126:                                        if ((y & 0x0f) == 0x0f)
                   1127:                                                BIO_printf(STDout, "\n");
                   1128:                                }
                   1129:                                if (y % 16 != 0)
                   1130:                                        BIO_printf(STDout, "\n");
                   1131:                                BIO_printf(STDout, "};\n");
                   1132:
                   1133:                                z = i2d_X509(x, &d);
1.23      inoguchi 1134:                                if (z < 0) {
                   1135:                                        free(m);
                   1136:                                        goto end;
                   1137:                                }
1.20      inoguchi 1138:                                BIO_printf(STDout,
                   1139:                                    "unsigned char XXX_certificate[%d]={\n", z);
1.1       jsing    1140:                                d = (unsigned char *) m;
                   1141:                                for (y = 0; y < z; y++) {
                   1142:                                        BIO_printf(STDout, "0x%02X,", d[y]);
                   1143:                                        if ((y & 0x0f) == 0x0f)
                   1144:                                                BIO_printf(STDout, "\n");
                   1145:                                }
                   1146:                                if (y % 16 != 0)
                   1147:                                        BIO_printf(STDout, "\n");
                   1148:                                BIO_printf(STDout, "};\n");
                   1149:
                   1150:                                free(m);
1.31      tb       1151:                        } else if (cfg.text == i) {
                   1152:                                if(!X509_print_ex(STDout, x, cfg.nmflag,
                   1153:                                    cfg.certflag))
1.23      inoguchi 1154:                                        goto end;
1.31      tb       1155:                        } else if (cfg.startdate == i) {
1.18      beck     1156:                                ASN1_TIME *nB = X509_get_notBefore(x);
1.32      tb       1157:
1.1       jsing    1158:                                BIO_puts(STDout, "notBefore=");
1.34    ! tb       1159:                                if (!ASN1_TIME_to_tm(nB, NULL))
1.20      inoguchi 1160:                                        BIO_puts(STDout,
                   1161:                                            "INVALID RFC5280 TIME");
1.18      beck     1162:                                else
                   1163:                                        ASN1_TIME_print(STDout, nB);
1.1       jsing    1164:                                BIO_puts(STDout, "\n");
1.31      tb       1165:                        } else if (cfg.enddate == i) {
1.18      beck     1166:                                ASN1_TIME *nA = X509_get_notAfter(x);
1.32      tb       1167:
1.1       jsing    1168:                                BIO_puts(STDout, "notAfter=");
1.34    ! tb       1169:                                if (!ASN1_TIME_to_tm(nA, NULL))
1.20      inoguchi 1170:                                        BIO_puts(STDout,
                   1171:                                            "INVALID RFC5280 TIME");
1.18      beck     1172:                                else
                   1173:                                        ASN1_TIME_print(STDout, nA);
1.1       jsing    1174:                                BIO_puts(STDout, "\n");
1.31      tb       1175:                        } else if (cfg.fingerprint == i) {
1.1       jsing    1176:                                int j;
                   1177:                                unsigned int n;
                   1178:                                unsigned char md[EVP_MAX_MD_SIZE];
1.31      tb       1179:                                const EVP_MD *fdig = cfg.digest;
1.1       jsing    1180:
1.21      inoguchi 1181:                                if (fdig == NULL)
1.17      jsg      1182:                                        fdig = EVP_sha256();
1.1       jsing    1183:
                   1184:                                if (!X509_digest(x, fdig, md, &n)) {
                   1185:                                        BIO_printf(bio_err, "out of memory\n");
                   1186:                                        goto end;
                   1187:                                }
                   1188:                                BIO_printf(STDout, "%s Fingerprint=",
                   1189:                                    OBJ_nid2sn(EVP_MD_type(fdig)));
                   1190:                                for (j = 0; j < (int) n; j++) {
                   1191:                                        BIO_printf(STDout, "%02X%c", md[j],
                   1192:                                            (j + 1 == (int)n) ? '\n' : ':');
                   1193:                                }
1.20      inoguchi 1194:
1.1       jsing    1195:                        /* should be in the library */
1.32      tb       1196:                        } else if (cfg.sign_flag == i && cfg.x509req == 0) {
1.1       jsing    1197:                                BIO_printf(bio_err, "Getting Private key\n");
                   1198:                                if (Upkey == NULL) {
1.32      tb       1199:                                        Upkey = load_key(bio_err, cfg.keyfile,
1.31      tb       1200:                                            cfg.keyformat, 0, passin,
1.20      inoguchi 1201:                                            "Private key");
1.1       jsing    1202:                                        if (Upkey == NULL)
                   1203:                                                goto end;
                   1204:                                }
1.31      tb       1205:                                if (!sign(x, Upkey, cfg.days,
                   1206:                                    cfg.clrext, cfg.digest,
                   1207:                                    extconf, cfg.extsect))
1.1       jsing    1208:                                        goto end;
1.31      tb       1209:                        } else if (cfg.CA_flag == i) {
1.1       jsing    1210:                                BIO_printf(bio_err, "Getting CA Private Key\n");
1.31      tb       1211:                                if (cfg.CAkeyfile != NULL) {
1.32      tb       1212:                                        CApkey = load_key(bio_err, cfg.CAkeyfile,
1.31      tb       1213:                                            cfg.CAkeyformat, 0, passin,
1.20      inoguchi 1214:                                            "CA Private Key");
1.1       jsing    1215:                                        if (CApkey == NULL)
                   1216:                                                goto end;
                   1217:                                }
1.32      tb       1218:                                if (!x509_certify(ctx, cfg.CAfile, cfg.digest,
                   1219:                                    x, xca, CApkey, cfg.sigopts, cfg.CAserial,
                   1220:                                    cfg.CA_createserial, cfg.days, cfg.clrext,
                   1221:                                    extconf, cfg.extsect, cfg.sno))
1.1       jsing    1222:                                        goto end;
1.31      tb       1223:                        } else if (cfg.x509req == i) {
1.1       jsing    1224:                                EVP_PKEY *pk;
                   1225:
1.20      inoguchi 1226:                                BIO_printf(bio_err,
                   1227:                                    "Getting request Private Key\n");
1.31      tb       1228:                                if (cfg.keyfile == NULL) {
1.20      inoguchi 1229:                                        BIO_printf(bio_err,
                   1230:                                            "no request key file specified\n");
1.1       jsing    1231:                                        goto end;
                   1232:                                } else {
1.32      tb       1233:                                        pk = load_key(bio_err, cfg.keyfile,
1.31      tb       1234:                                            cfg.keyformat, 0, passin,
1.20      inoguchi 1235:                                            "request key");
1.1       jsing    1236:                                        if (pk == NULL)
                   1237:                                                goto end;
                   1238:                                }
                   1239:
1.20      inoguchi 1240:                                BIO_printf(bio_err,
                   1241:                                    "Generating certificate request\n");
1.1       jsing    1242:
1.31      tb       1243:                                rq = X509_to_X509_REQ(x, pk, cfg.digest);
1.1       jsing    1244:                                EVP_PKEY_free(pk);
                   1245:                                if (rq == NULL) {
                   1246:                                        ERR_print_errors(bio_err);
                   1247:                                        goto end;
                   1248:                                }
1.31      tb       1249:                                if (!cfg.noout) {
1.23      inoguchi 1250:                                        if (!X509_REQ_print(out, rq))
                   1251:                                                goto end;
                   1252:                                        if (!PEM_write_bio_X509_REQ(out, rq))
                   1253:                                                goto end;
1.1       jsing    1254:                                }
1.31      tb       1255:                                cfg.noout = 1;
                   1256:                        } else if (cfg.ocspid == i) {
1.23      inoguchi 1257:                                if (!X509_ocspid_print(out, x))
                   1258:                                        goto end;
1.1       jsing    1259:                        }
                   1260:                }
                   1261:        }
1.31      tb       1262:        if (cfg.checkend) {
                   1263:                time_t tcheck = time(NULL) + cfg.checkoffset;
1.18      beck     1264:                int timecheck = X509_cmp_time(X509_get_notAfter(x), &tcheck);
                   1265:                if (timecheck == 0) {
                   1266:                        BIO_printf(out, "Certificate expiry time is invalid\n");
                   1267:                        ret = 1;
                   1268:                } else if (timecheck < 0) {
1.1       jsing    1269:                        BIO_printf(out, "Certificate will expire\n");
                   1270:                        ret = 1;
                   1271:                } else {
                   1272:                        BIO_printf(out, "Certificate will not expire\n");
                   1273:                        ret = 0;
                   1274:                }
                   1275:                goto end;
                   1276:        }
1.31      tb       1277:        if (cfg.noout) {
1.1       jsing    1278:                ret = 0;
                   1279:                goto end;
                   1280:        }
1.31      tb       1281:        if (cfg.outformat == FORMAT_ASN1)
1.1       jsing    1282:                i = i2d_X509_bio(out, x);
1.31      tb       1283:        else if (cfg.outformat == FORMAT_PEM) {
                   1284:                if (cfg.trustout)
1.1       jsing    1285:                        i = PEM_write_bio_X509_AUX(out, x);
                   1286:                else
                   1287:                        i = PEM_write_bio_X509(out, x);
                   1288:        } else {
1.20      inoguchi 1289:                BIO_printf(bio_err,
                   1290:                    "bad output format specified for outfile\n");
1.1       jsing    1291:                goto end;
                   1292:        }
                   1293:        if (!i) {
                   1294:                BIO_printf(bio_err, "unable to write certificate\n");
                   1295:                ERR_print_errors(bio_err);
                   1296:                goto end;
                   1297:        }
                   1298:        ret = 0;
                   1299:
1.16      jsing    1300:  end:
1.1       jsing    1301:        OBJ_cleanup();
                   1302:        NCONF_free(extconf);
                   1303:        BIO_free_all(out);
                   1304:        BIO_free_all(STDout);
                   1305:        X509_STORE_free(ctx);
                   1306:        X509_REQ_free(req);
                   1307:        X509_free(x);
                   1308:        X509_free(xca);
                   1309:        EVP_PKEY_free(Upkey);
                   1310:        EVP_PKEY_free(CApkey);
1.31      tb       1311:        sk_OPENSSL_STRING_free(cfg.sigopts);
1.1       jsing    1312:        X509_REQ_free(rq);
1.31      tb       1313:        ASN1_INTEGER_free(cfg.sno);
                   1314:        sk_ASN1_OBJECT_pop_free(cfg.trust, ASN1_OBJECT_free);
                   1315:        sk_ASN1_OBJECT_pop_free(cfg.reject, ASN1_OBJECT_free);
1.1       jsing    1316:        free(passin);
                   1317:
                   1318:        return (ret);
                   1319: }
                   1320:
                   1321: static ASN1_INTEGER *
                   1322: x509_load_serial(char *CAfile, char *serialfile, int create)
                   1323: {
                   1324:        char *buf = NULL, *p;
                   1325:        ASN1_INTEGER *bs = NULL;
                   1326:        BIGNUM *serial = NULL;
                   1327:        size_t len;
                   1328:
                   1329:        len = ((serialfile == NULL) ? (strlen(CAfile) + strlen(POSTFIX) + 1) :
                   1330:            (strlen(serialfile))) + 1;
                   1331:        buf = malloc(len);
                   1332:        if (buf == NULL) {
                   1333:                BIO_printf(bio_err, "out of mem\n");
                   1334:                goto end;
                   1335:        }
                   1336:        if (serialfile == NULL) {
                   1337:                strlcpy(buf, CAfile, len);
                   1338:                for (p = buf; *p; p++)
                   1339:                        if (*p == '.') {
                   1340:                                *p = '\0';
                   1341:                                break;
                   1342:                        }
                   1343:                strlcat(buf, POSTFIX, len);
                   1344:        } else
                   1345:                strlcpy(buf, serialfile, len);
                   1346:
                   1347:        serial = load_serial(buf, create, NULL);
                   1348:        if (serial == NULL)
                   1349:                goto end;
                   1350:
                   1351:        if (!BN_add_word(serial, 1)) {
                   1352:                BIO_printf(bio_err, "add_word failure\n");
                   1353:                goto end;
                   1354:        }
                   1355:        if (!save_serial(buf, NULL, serial, &bs))
                   1356:                goto end;
                   1357:
1.16      jsing    1358:  end:
1.1       jsing    1359:        free(buf);
                   1360:        BN_free(serial);
                   1361:
                   1362:        return bs;
                   1363: }
                   1364:
                   1365: static int
                   1366: x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, X509 *x,
                   1367:     X509 *xca, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *sigopts,
                   1368:     char *serialfile, int create, int days, int clrext, CONF *conf,
                   1369:     char *section, ASN1_INTEGER *sno)
                   1370: {
                   1371:        int ret = 0;
                   1372:        ASN1_INTEGER *bs = NULL;
1.25      tb       1373:        X509_STORE_CTX *xsc = NULL;
1.1       jsing    1374:        EVP_PKEY *upkey;
                   1375:
1.29      tb       1376:        upkey = X509_get0_pubkey(xca);
1.23      inoguchi 1377:        if (upkey == NULL)
                   1378:                goto end;
1.1       jsing    1379:        EVP_PKEY_copy_parameters(upkey, pkey);
                   1380:
1.25      tb       1381:        if ((xsc = X509_STORE_CTX_new()) == NULL)
                   1382:                goto end;
                   1383:        if (!X509_STORE_CTX_init(xsc, ctx, x, NULL)) {
1.1       jsing    1384:                BIO_printf(bio_err, "Error initialising X509 store\n");
                   1385:                goto end;
                   1386:        }
1.21      inoguchi 1387:        if (sno != NULL)
1.1       jsing    1388:                bs = sno;
1.21      inoguchi 1389:        else if ((bs = x509_load_serial(CAfile, serialfile, create)) == NULL)
1.1       jsing    1390:                goto end;
                   1391:
                   1392: /*     if (!X509_STORE_add_cert(ctx,x)) goto end;*/
                   1393:
                   1394:        /*
                   1395:         * NOTE: this certificate can/should be self signed, unless it was a
                   1396:         * certificate request in which case it is not.
                   1397:         */
1.25      tb       1398:        X509_STORE_CTX_set_cert(xsc, x);
                   1399:        X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
1.31      tb       1400:        if (!cfg.reqfile && X509_verify_cert(xsc) <= 0)
1.1       jsing    1401:                goto end;
                   1402:
                   1403:        if (!X509_check_private_key(xca, pkey)) {
1.20      inoguchi 1404:                BIO_printf(bio_err,
                   1405:                    "CA certificate and CA private key do not match\n");
1.1       jsing    1406:                goto end;
                   1407:        }
                   1408:        if (!X509_set_issuer_name(x, X509_get_subject_name(xca)))
                   1409:                goto end;
                   1410:        if (!X509_set_serialNumber(x, bs))
                   1411:                goto end;
                   1412:
                   1413:        if (X509_gmtime_adj(X509_get_notBefore(x), 0L) == NULL)
                   1414:                goto end;
                   1415:
                   1416:        /* hardwired expired */
                   1417:        if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL)
                   1418:                goto end;
                   1419:
                   1420:        if (clrext) {
1.23      inoguchi 1421:                while (X509_get_ext_count(x) > 0) {
                   1422:                        if (X509_delete_ext(x, 0) == NULL)
                   1423:                                goto end;
                   1424:                }
1.1       jsing    1425:        }
1.21      inoguchi 1426:        if (conf != NULL) {
1.1       jsing    1427:                X509V3_CTX ctx2;
1.23      inoguchi 1428:                if (!X509_set_version(x, 2))    /* version 3 certificate */
                   1429:                        goto end;
1.1       jsing    1430:                X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
                   1431:                X509V3_set_nconf(&ctx2, conf);
                   1432:                if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x))
                   1433:                        goto end;
                   1434:        }
                   1435:        if (!do_X509_sign(bio_err, x, pkey, digest, sigopts))
                   1436:                goto end;
1.23      inoguchi 1437:
1.1       jsing    1438:        ret = 1;
1.16      jsing    1439:  end:
1.25      tb       1440:        X509_STORE_CTX_free(xsc);
1.1       jsing    1441:        if (!ret)
                   1442:                ERR_print_errors(bio_err);
1.21      inoguchi 1443:        if (sno == NULL)
1.1       jsing    1444:                ASN1_INTEGER_free(bs);
                   1445:        return ret;
                   1446: }
                   1447:
                   1448: static int
                   1449: callb(int ok, X509_STORE_CTX *ctx)
                   1450: {
                   1451:        int err;
                   1452:        X509 *err_cert;
                   1453:
                   1454:        /*
                   1455:         * it is ok to use a self signed certificate This case will catch
                   1456:         * both the initial ok == 0 and the final ok == 1 calls to this
                   1457:         * function
                   1458:         */
                   1459:        err = X509_STORE_CTX_get_error(ctx);
                   1460:        if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
                   1461:                return 1;
                   1462:
                   1463:        /*
                   1464:         * BAD we should have gotten an error.  Normally if everything worked
                   1465:         * X509_STORE_CTX_get_error(ctx) will still be set to
                   1466:         * DEPTH_ZERO_SELF_....
                   1467:         */
                   1468:        if (ok) {
1.20      inoguchi 1469:                BIO_printf(bio_err,
                   1470:                    "error with certificate to be certified - should be self signed\n");
1.1       jsing    1471:                return 0;
                   1472:        } else {
                   1473:                err_cert = X509_STORE_CTX_get_current_cert(ctx);
                   1474:                print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0);
1.20      inoguchi 1475:                BIO_printf(bio_err,
                   1476:                    "error with certificate - error %d at depth %d\n%s\n",
1.1       jsing    1477:                    err, X509_STORE_CTX_get_error_depth(ctx),
                   1478:                    X509_verify_cert_error_string(err));
                   1479:                return 1;
                   1480:        }
                   1481: }
                   1482:
                   1483: /* self sign */
                   1484: static int
                   1485: sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest,
                   1486:     CONF *conf, char *section)
                   1487: {
                   1488:        EVP_PKEY *pktmp;
                   1489:
1.29      tb       1490:        pktmp = X509_get0_pubkey(x);
1.23      inoguchi 1491:        if (pktmp == NULL)
                   1492:                goto err;
1.1       jsing    1493:        EVP_PKEY_copy_parameters(pktmp, pkey);
                   1494:        EVP_PKEY_save_parameters(pktmp, 1);
                   1495:
                   1496:        if (!X509_set_issuer_name(x, X509_get_subject_name(x)))
                   1497:                goto err;
                   1498:        if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL)
                   1499:                goto err;
                   1500:
                   1501:        /* Lets just make it 12:00am GMT, Jan 1 1970 */
                   1502:        /* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */
                   1503:        /* 28 days to be certified */
                   1504:
                   1505:        if (X509_gmtime_adj(X509_get_notAfter(x),
                   1506:            (long) 60 * 60 * 24 * days) == NULL)
                   1507:                goto err;
                   1508:
                   1509:        if (!X509_set_pubkey(x, pkey))
                   1510:                goto err;
                   1511:        if (clrext) {
1.23      inoguchi 1512:                while (X509_get_ext_count(x) > 0) {
                   1513:                        if (X509_delete_ext(x, 0) == NULL)
                   1514:                                goto err;
                   1515:                }
1.1       jsing    1516:        }
1.21      inoguchi 1517:        if (conf != NULL) {
1.1       jsing    1518:                X509V3_CTX ctx;
1.23      inoguchi 1519:                if (!X509_set_version(x, 2))    /* version 3 certificate */
                   1520:                        goto err;
1.1       jsing    1521:                X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
                   1522:                X509V3_set_nconf(&ctx, conf);
                   1523:                if (!X509V3_EXT_add_nconf(conf, &ctx, section, x))
                   1524:                        goto err;
                   1525:        }
                   1526:        if (!X509_sign(x, pkey, digest))
                   1527:                goto err;
1.20      inoguchi 1528:
1.1       jsing    1529:        return 1;
                   1530:
1.16      jsing    1531:  err:
1.1       jsing    1532:        ERR_print_errors(bio_err);
                   1533:        return 0;
                   1534: }
                   1535:
                   1536: static int
                   1537: purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
                   1538: {
                   1539:        int id, i, idret;
                   1540:        char *pname;
                   1541:
                   1542:        id = X509_PURPOSE_get_id(pt);
                   1543:        pname = X509_PURPOSE_get0_name(pt);
                   1544:        for (i = 0; i < 2; i++) {
                   1545:                idret = X509_check_purpose(cert, id, i);
                   1546:                BIO_printf(bio, "%s%s : ", pname, i ? " CA" : "");
                   1547:                if (idret == 1)
                   1548:                        BIO_printf(bio, "Yes\n");
                   1549:                else if (idret == 0)
                   1550:                        BIO_printf(bio, "No\n");
                   1551:                else
                   1552:                        BIO_printf(bio, "Yes (WARNING code=%d)\n", idret);
                   1553:        }
                   1554:        return 1;
                   1555: }