[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.28

1.27      tb          1: /* $OpenBSD: x509.c,v 1.26 2021/11/26 16:23:27 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;
                    155: } x509_config;
                    156:
                    157: static int
                    158: x509_opt_addreject(char *arg)
                    159: {
                    160:        if ((x509_config.objtmp = OBJ_txt2obj(arg, 0)) == NULL) {
                    161:                BIO_printf(bio_err, "Invalid reject object value %s\n", arg);
                    162:                return (1);
                    163:        }
                    164:
                    165:        if (x509_config.reject == NULL &&
                    166:            (x509_config.reject = sk_ASN1_OBJECT_new_null()) == NULL)
                    167:                return (1);
                    168:
                    169:        if (!sk_ASN1_OBJECT_push(x509_config.reject, x509_config.objtmp))
                    170:                return (1);
                    171:
                    172:        x509_config.trustout = 1;
                    173:        return (0);
                    174: }
                    175:
                    176: static int
                    177: x509_opt_addtrust(char *arg)
                    178: {
                    179:        if ((x509_config.objtmp = OBJ_txt2obj(arg, 0)) == NULL) {
                    180:                BIO_printf(bio_err, "Invalid trust object value %s\n", arg);
                    181:                return (1);
                    182:        }
                    183:
                    184:        if (x509_config.trust == NULL &&
                    185:            (x509_config.trust = sk_ASN1_OBJECT_new_null()) == NULL)
                    186:                return (1);
                    187:
                    188:        if (!sk_ASN1_OBJECT_push(x509_config.trust, x509_config.objtmp))
                    189:                return (1);
                    190:
                    191:        x509_config.trustout = 1;
                    192:        return (0);
                    193: }
                    194:
                    195: static int
                    196: x509_opt_ca(char *arg)
                    197: {
                    198:        x509_config.CAfile = arg;
                    199:        x509_config.CA_flag = ++x509_config.num;
                    200:        return (0);
                    201: }
                    202:
                    203: static int
                    204: x509_opt_certopt(char *arg)
                    205: {
                    206:        if (!set_cert_ex(&x509_config.certflag, arg))
                    207:                return (1);
                    208:
                    209:        return (0);
                    210: }
                    211:
                    212: static int
                    213: x509_opt_checkend(char *arg)
                    214: {
                    215:        const char *errstr;
                    216:
                    217:        x509_config.checkoffset = strtonum(arg, 0, INT_MAX, &errstr);
                    218:        if (errstr != NULL) {
                    219:                BIO_printf(bio_err, "checkend unusable: %s\n", errstr);
                    220:                return (1);
                    221:        }
                    222:        x509_config.checkend = 1;
                    223:        return (0);
                    224: }
                    225:
                    226: static int
                    227: x509_opt_dates(void)
                    228: {
                    229:        x509_config.startdate = ++x509_config.num;
                    230:        x509_config.enddate = ++x509_config.num;
                    231:        return (0);
                    232: }
                    233:
                    234: static int
                    235: x509_opt_days(char *arg)
                    236: {
                    237:        const char *errstr;
                    238:
                    239:        x509_config.days = strtonum(arg, 1, INT_MAX, &errstr);
                    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:
                    255:        if ((x509_config.md_alg = EVP_get_digestbyname(name)) != NULL) {
                    256:                x509_config.digest = x509_config.md_alg;
                    257:        } else {
                    258:                BIO_printf(bio_err, "unknown option %s\n", *argv);
                    259:                x509_config.badops = 1;
                    260:                return (1);
                    261:        }
                    262:
                    263:        *argsused = 1;
                    264:        return (0);
                    265: }
                    266:
                    267: static int
                    268: x509_opt_nameopt(char *arg)
                    269: {
                    270:        if (!set_name_ex(&x509_config.nmflag, arg))
                    271:                return (1);
                    272:
                    273:        return (0);
                    274: }
                    275:
                    276: static int
                    277: x509_opt_set_serial(char *arg)
                    278: {
                    279:        ASN1_INTEGER_free(x509_config.sno);
                    280:        if ((x509_config.sno = s2i_ASN1_INTEGER(NULL, arg)) == NULL)
                    281:                return (1);
                    282:
                    283:        return (0);
                    284: }
                    285:
                    286: static int
                    287: x509_opt_setalias(char *arg)
                    288: {
                    289:        x509_config.alias = arg;
                    290:        x509_config.trustout = 1;
                    291:        return (0);
                    292: }
                    293:
                    294: static int
                    295: x509_opt_signkey(char *arg)
                    296: {
                    297:        x509_config.keyfile = arg;
                    298:        x509_config.sign_flag = ++x509_config.num;
                    299:        return (0);
                    300: }
                    301:
                    302: static int
                    303: x509_opt_sigopt(char *arg)
                    304: {
                    305:        if (x509_config.sigopts == NULL &&
                    306:            (x509_config.sigopts = sk_OPENSSL_STRING_new_null()) == NULL)
                    307:                return (1);
                    308:
                    309:        if (!sk_OPENSSL_STRING_push(x509_config.sigopts, arg))
                    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,
                    320:                .opt.order = &x509_config.C,
                    321:                .order = &x509_config.num,
                    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,
                    341:                .opt.order = &x509_config.aliasout,
                    342:                .order = &x509_config.num,
                    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,
                    355:                .opt.order = &x509_config.CA_createserial,
                    356:                .order = &x509_config.num,
                    357:        },
                    358:        {
                    359:                .name = "CAform",
                    360:                .argname = "fmt",
                    361:                .desc = "CA format - default PEM",
                    362:                .type = OPTION_ARG_FORMAT,
                    363:                .opt.value = &x509_config.CAformat,
                    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,
                    371:                .opt.arg = &x509_config.CAkeyfile,
                    372:        },
                    373:        {
                    374:                .name = "CAkeyform",
                    375:                .argname = "fmt",
                    376:                .desc = "CA key format - default PEM",
                    377:                .type = OPTION_ARG_FORMAT,
                    378:                .opt.value = &x509_config.CAkeyformat,
                    379:        },
                    380:        {
                    381:                .name = "CAserial",
                    382:                .argname = "file",
                    383:                .desc = "Serial file",
                    384:                .type = OPTION_ARG,
                    385:                .opt.arg = &x509_config.CAserial,
                    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,
                    406:                .opt.flag = &x509_config.clrext,
                    407:        },
                    408:        {
                    409:                .name = "clrreject",
                    410:                .desc = "Clear all rejected purposes",
                    411:                .type = OPTION_ORDER,
                    412:                .opt.order = &x509_config.clrreject,
                    413:                .order = &x509_config.num,
                    414:        },
                    415:        {
                    416:                .name = "clrtrust",
                    417:                .desc = "Clear all trusted purposes",
                    418:                .type = OPTION_ORDER,
                    419:                .opt.order = &x509_config.clrtrust,
                    420:                .order = &x509_config.num,
                    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,
                    439:                .opt.order = &x509_config.email,
                    440:                .order = &x509_config.num,
                    441:        },
                    442:        {
                    443:                .name = "enddate",
                    444:                .desc = "Print notAfter field",
                    445:                .type = OPTION_ORDER,
                    446:                .opt.order = &x509_config.enddate,
                    447:                .order = &x509_config.num,
                    448:        },
                    449:        {
                    450:                .name = "extensions",
                    451:                .argname = "section",
                    452:                .desc = "Section from config file with X509V3 extensions to add",
                    453:                .type = OPTION_ARG,
                    454:                .opt.arg = &x509_config.extsect,
                    455:        },
                    456:        {
                    457:                .name = "extfile",
                    458:                .argname = "file",
                    459:                .desc = "Configuration file with X509V3 extensions to add",
                    460:                .type = OPTION_ARG,
                    461:                .opt.arg = &x509_config.extfile,
                    462:        },
                    463:        {
                    464:                .name = "fingerprint",
                    465:                .desc = "Print the certificate fingerprint",
                    466:                .type = OPTION_ORDER,
                    467:                .opt.order = &x509_config.fingerprint,
                    468:                .order = &x509_config.num,
                    469:        },
                    470:        {
                    471:                .name = "hash",
                    472:                .desc = "Synonym for -subject_hash",
                    473:                .type = OPTION_ORDER,
                    474:                .opt.order = &x509_config.subject_hash,
                    475:                .order = &x509_config.num,
                    476:        },
                    477:        {
                    478:                .name = "in",
                    479:                .argname = "file",
                    480:                .desc = "Input file - default stdin",
                    481:                .type = OPTION_ARG,
                    482:                .opt.arg = &x509_config.infile,
                    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,
                    489:                .opt.value = &x509_config.informat,
                    490:        },
                    491:        {
                    492:                .name = "issuer",
                    493:                .desc = "Print issuer name",
                    494:                .type = OPTION_ORDER,
                    495:                .opt.order = &x509_config.issuer,
                    496:                .order = &x509_config.num,
                    497:        },
                    498:        {
                    499:                .name = "issuer_hash",
                    500:                .desc = "Print issuer hash value",
                    501:                .type = OPTION_ORDER,
                    502:                .opt.order = &x509_config.issuer_hash,
                    503:                .order = &x509_config.num,
                    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,
                    510:                .opt.order = &x509_config.issuer_hash_old,
                    511:                .order = &x509_config.num,
                    512:        },
                    513: #endif
                    514:        {
                    515:                .name = "keyform",
                    516:                .argname = "fmt",
                    517:                .desc = "Private key format - default PEM",
                    518:                .type = OPTION_ARG_FORMAT,
                    519:                .opt.value = &x509_config.keyformat,
                    520:        },
                    521:        {
                    522:                .name = "modulus",
                    523:                .desc = "Print the RSA key modulus",
                    524:                .type = OPTION_ORDER,
                    525:                .opt.order = &x509_config.modulus,
                    526:                .order = &x509_config.num,
                    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,
                    539:                .opt.order = &x509_config.next_serial,
                    540:                .order = &x509_config.num,
                    541:        },
                    542:        {
                    543:                .name = "noout",
                    544:                .desc = "No certificate output",
                    545:                .type = OPTION_ORDER,
                    546:                .opt.order = &x509_config.noout,
                    547:                .order = &x509_config.num,
                    548:        },
                    549:        {
                    550:                .name = "ocsp_uri",
                    551:                .desc = "Print OCSP Responder URL(s)",
                    552:                .type = OPTION_ORDER,
                    553:                .opt.order = &x509_config.ocsp_uri,
                    554:                .order = &x509_config.num,
                    555:        },
                    556:        {
                    557:                .name = "ocspid",
                    558:                .desc = "Print OCSP hash values for the subject name and public key",
                    559:                .type = OPTION_ORDER,
                    560:                .opt.order = &x509_config.ocspid,
                    561:                .order = &x509_config.num,
                    562:        },
                    563:        {
                    564:                .name = "out",
                    565:                .argname = "file",
                    566:                .desc = "Output file - default stdout",
                    567:                .type = OPTION_ARG,
                    568:                .opt.arg = &x509_config.outfile,
                    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,
                    575:                .opt.value = &x509_config.outformat,
                    576:        },
                    577:        {
                    578:                .name = "passin",
                    579:                .argname = "src",
                    580:                .desc = "Private key password source",
                    581:                .type = OPTION_ARG,
                    582:                .opt.arg = &x509_config.passargin,
                    583:        },
                    584:        {
                    585:                .name = "pubkey",
                    586:                .desc = "Output the public key",
                    587:                .type = OPTION_ORDER,
                    588:                .opt.order = &x509_config.pubkey,
                    589:                .order = &x509_config.num,
                    590:        },
                    591:        {
                    592:                .name = "purpose",
                    593:                .desc = "Print out certificate purposes",
                    594:                .type = OPTION_ORDER,
                    595:                .opt.order = &x509_config.pprint,
                    596:                .order = &x509_config.num,
                    597:        },
                    598:        {
                    599:                .name = "req",
                    600:                .desc = "Input is a certificate request, sign and output",
                    601:                .type = OPTION_FLAG,
                    602:                .opt.flag = &x509_config.reqfile,
                    603:        },
                    604:        {
                    605:                .name = "serial",
                    606:                .desc = "Print serial number value",
                    607:                .type = OPTION_ORDER,
                    608:                .opt.order = &x509_config.serial,
                    609:                .order = &x509_config.num,
                    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,
                    643:                .opt.order = &x509_config.startdate,
                    644:                .order = &x509_config.num,
                    645:        },
                    646:        {
                    647:                .name = "subject",
                    648:                .desc = "Print subject name",
                    649:                .type = OPTION_ORDER,
                    650:                .opt.order = &x509_config.subject,
                    651:                .order = &x509_config.num,
                    652:        },
                    653:        {
                    654:                .name = "subject_hash",
                    655:                .desc = "Print subject hash value",
                    656:                .type = OPTION_ORDER,
                    657:                .opt.order = &x509_config.subject_hash,
                    658:                .order = &x509_config.num,
                    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,
                    665:                .opt.order = &x509_config.subject_hash_old,
                    666:                .order = &x509_config.num,
                    667:        },
                    668: #endif
                    669:        {
                    670:                .name = "text",
                    671:                .desc = "Print the certificate in text form",
                    672:                .type = OPTION_ORDER,
                    673:                .opt.order = &x509_config.text,
                    674:                .order = &x509_config.num,
                    675:        },
                    676:        {
                    677:                .name = "trustout",
                    678:                .desc = "Output a trusted certificate",
                    679:                .type = OPTION_FLAG,
                    680:                .opt.flag = &x509_config.trustout,
                    681:        },
                    682:        {
                    683:                .name = "x509toreq",
                    684:                .desc = "Output a certification request object",
                    685:                .type = OPTION_ORDER,
                    686:                .opt.order = &x509_config.x509req,
                    687:                .order = &x509_config.num,
                    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:
                    738:        if (single_execution) {
1.14      deraadt   739:                if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
1.10      doug      740:                        perror("pledge");
1.12      doug      741:                        exit(1);
                    742:                }
1.10      doug      743:        }
1.1       jsing     744:
1.19      inoguchi  745:        memset(&x509_config, 0, sizeof(x509_config));
                    746:        x509_config.days = DEF_DAYS;
                    747:        x509_config.informat = FORMAT_PEM;
                    748:        x509_config.outformat = FORMAT_PEM;
                    749:        x509_config.keyformat = FORMAT_PEM;
                    750:        x509_config.CAformat = FORMAT_PEM;
                    751:        x509_config.CAkeyformat = FORMAT_PEM;
1.1       jsing     752:
                    753:        STDout = BIO_new_fp(stdout, BIO_NOCLOSE);
                    754:
                    755:        ctx = X509_STORE_new();
                    756:        if (ctx == NULL)
                    757:                goto end;
                    758:        X509_STORE_set_verify_cb(ctx, callb);
                    759:
1.19      inoguchi  760:        if (options_parse(argc, argv, x509_options, NULL, NULL) != 0)
                    761:                goto bad;
1.1       jsing     762:
1.19      inoguchi  763:        if (x509_config.badops) {
1.16      jsing     764:  bad:
1.19      inoguchi  765:                x509_usage();
1.1       jsing     766:                goto end;
                    767:        }
                    768:
1.19      inoguchi  769:        if (!app_passwd(bio_err, x509_config.passargin, NULL, &passin, NULL)) {
1.1       jsing     770:                BIO_printf(bio_err, "Error getting password\n");
                    771:                goto end;
                    772:        }
                    773:        if (!X509_STORE_set_default_paths(ctx)) {
                    774:                ERR_print_errors(bio_err);
                    775:                goto end;
                    776:        }
1.20      inoguchi  777:        if ((x509_config.CAkeyfile == NULL) && (x509_config.CA_flag) &&
                    778:            (x509_config.CAformat == FORMAT_PEM)) {
1.19      inoguchi  779:                x509_config.CAkeyfile = x509_config.CAfile;
                    780:        } else if ((x509_config.CA_flag) && (x509_config.CAkeyfile == NULL)) {
1.1       jsing     781:                BIO_printf(bio_err,
                    782:                    "need to specify a CAkey if using the CA command\n");
                    783:                goto end;
                    784:        }
1.21      inoguchi  785:        if (x509_config.extfile != NULL) {
1.1       jsing     786:                long errorline = -1;
                    787:                X509V3_CTX ctx2;
                    788:                extconf = NCONF_new(NULL);
1.19      inoguchi  789:                if (!NCONF_load(extconf, x509_config.extfile, &errorline)) {
1.1       jsing     790:                        if (errorline <= 0)
                    791:                                BIO_printf(bio_err,
                    792:                                    "error loading the config file '%s'\n",
1.19      inoguchi  793:                                    x509_config.extfile);
1.1       jsing     794:                        else
                    795:                                BIO_printf(bio_err,
                    796:                                    "error on line %ld of config file '%s'\n",
1.19      inoguchi  797:                                    errorline, x509_config.extfile);
1.1       jsing     798:                        goto end;
                    799:                }
1.21      inoguchi  800:                if (x509_config.extsect == NULL) {
1.20      inoguchi  801:                        x509_config.extsect = NCONF_get_string(extconf,
                    802:                            "default", "extensions");
1.21      inoguchi  803:                        if (x509_config.extsect == NULL) {
1.1       jsing     804:                                ERR_clear_error();
1.19      inoguchi  805:                                x509_config.extsect = "default";
1.1       jsing     806:                        }
                    807:                }
                    808:                X509V3_set_ctx_test(&ctx2);
                    809:                X509V3_set_nconf(&ctx2, extconf);
1.20      inoguchi  810:                if (!X509V3_EXT_add_nconf(extconf, &ctx2, x509_config.extsect,
                    811:                    NULL)) {
1.1       jsing     812:                        BIO_printf(bio_err,
                    813:                            "Error Loading extension section %s\n",
1.19      inoguchi  814:                            x509_config.extsect);
1.1       jsing     815:                        ERR_print_errors(bio_err);
                    816:                        goto end;
                    817:                }
                    818:        }
1.19      inoguchi  819:        if (x509_config.reqfile) {
1.1       jsing     820:                EVP_PKEY *pkey;
                    821:                BIO *in;
                    822:
1.19      inoguchi  823:                if (!x509_config.sign_flag && !x509_config.CA_flag) {
1.20      inoguchi  824:                        BIO_printf(bio_err,
                    825:                            "We need a private key to sign with\n");
1.1       jsing     826:                        goto end;
                    827:                }
                    828:                in = BIO_new(BIO_s_file());
                    829:                if (in == NULL) {
                    830:                        ERR_print_errors(bio_err);
                    831:                        goto end;
                    832:                }
1.19      inoguchi  833:                if (x509_config.infile == NULL)
1.1       jsing     834:                        BIO_set_fp(in, stdin, BIO_NOCLOSE | BIO_FP_TEXT);
                    835:                else {
1.19      inoguchi  836:                        if (BIO_read_filename(in, x509_config.infile) <= 0) {
                    837:                                perror(x509_config.infile);
1.1       jsing     838:                                BIO_free(in);
                    839:                                goto end;
                    840:                        }
                    841:                }
                    842:                req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
                    843:                BIO_free(in);
                    844:
                    845:                if (req == NULL) {
                    846:                        ERR_print_errors(bio_err);
                    847:                        goto end;
                    848:                }
                    849:                if ((pkey = X509_REQ_get_pubkey(req)) == NULL) {
                    850:                        BIO_printf(bio_err, "error unpacking public key\n");
                    851:                        goto end;
                    852:                }
                    853:                i = X509_REQ_verify(req, pkey);
                    854:                EVP_PKEY_free(pkey);
                    855:                if (i < 0) {
                    856:                        BIO_printf(bio_err, "Signature verification error\n");
                    857:                        ERR_print_errors(bio_err);
                    858:                        goto end;
                    859:                }
                    860:                if (i == 0) {
1.20      inoguchi  861:                        BIO_printf(bio_err,
                    862:                            "Signature did not match the certificate request\n");
1.1       jsing     863:                        goto end;
                    864:                } else
                    865:                        BIO_printf(bio_err, "Signature ok\n");
                    866:
1.20      inoguchi  867:                print_name(bio_err, "subject=", X509_REQ_get_subject_name(req),
                    868:                    x509_config.nmflag);
1.1       jsing     869:
                    870:                if ((x = X509_new()) == NULL)
                    871:                        goto end;
                    872:
1.19      inoguchi  873:                if (x509_config.sno == NULL) {
                    874:                        x509_config.sno = ASN1_INTEGER_new();
1.21      inoguchi  875:                        if (x509_config.sno == NULL ||
1.20      inoguchi  876:                            !rand_serial(NULL, x509_config.sno))
1.1       jsing     877:                                goto end;
1.19      inoguchi  878:                        if (!X509_set_serialNumber(x, x509_config.sno))
1.1       jsing     879:                                goto end;
1.19      inoguchi  880:                        ASN1_INTEGER_free(x509_config.sno);
                    881:                        x509_config.sno = NULL;
                    882:                } else if (!X509_set_serialNumber(x, x509_config.sno))
1.1       jsing     883:                        goto end;
                    884:
1.25      tb        885:                if (!X509_set_issuer_name(x, X509_REQ_get_subject_name(req)))
1.1       jsing     886:                        goto end;
1.25      tb        887:                if (!X509_set_subject_name(x, X509_REQ_get_subject_name(req)))
1.1       jsing     888:                        goto end;
                    889:
1.23      inoguchi  890:                if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL)
                    891:                        goto end;
                    892:                if (X509_time_adj_ex(X509_get_notAfter(x), x509_config.days, 0,
                    893:                    NULL) == NULL)
                    894:                        goto end;
1.1       jsing     895:
1.23      inoguchi  896:                if ((pkey = X509_REQ_get_pubkey(req)) == NULL)
                    897:                        goto end;
                    898:                if (!X509_set_pubkey(x, pkey)) {
                    899:                        EVP_PKEY_free(pkey);
                    900:                        goto end;
                    901:                }
1.1       jsing     902:                EVP_PKEY_free(pkey);
1.23      inoguchi  903:        } else {
1.20      inoguchi  904:                x = load_cert(bio_err, x509_config.infile, x509_config.informat,
                    905:                    NULL, "Certificate");
1.23      inoguchi  906:        }
1.1       jsing     907:        if (x == NULL)
                    908:                goto end;
1.23      inoguchi  909:
1.19      inoguchi  910:        if (x509_config.CA_flag) {
1.20      inoguchi  911:                xca = load_cert(bio_err, x509_config.CAfile,
                    912:                    x509_config.CAformat, NULL, "CA Certificate");
1.1       jsing     913:                if (xca == NULL)
                    914:                        goto end;
                    915:        }
1.19      inoguchi  916:        if (!x509_config.noout || x509_config.text || x509_config.next_serial) {
1.20      inoguchi  917:                OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3");
1.1       jsing     918:
                    919:                out = BIO_new(BIO_s_file());
                    920:                if (out == NULL) {
                    921:                        ERR_print_errors(bio_err);
                    922:                        goto end;
                    923:                }
1.19      inoguchi  924:                if (x509_config.outfile == NULL) {
1.1       jsing     925:                        BIO_set_fp(out, stdout, BIO_NOCLOSE);
                    926:                } else {
1.19      inoguchi  927:                        if (BIO_write_filename(out, x509_config.outfile) <= 0) {
                    928:                                perror(x509_config.outfile);
1.1       jsing     929:                                goto end;
                    930:                        }
                    931:                }
                    932:        }
1.23      inoguchi  933:        if (x509_config.alias != NULL) {
                    934:                if (!X509_alias_set1(x, (unsigned char *)x509_config.alias, -1))
                    935:                        goto end;
                    936:        }
1.1       jsing     937:
1.19      inoguchi  938:        if (x509_config.clrtrust)
1.1       jsing     939:                X509_trust_clear(x);
1.19      inoguchi  940:        if (x509_config.clrreject)
1.1       jsing     941:                X509_reject_clear(x);
                    942:
1.21      inoguchi  943:        if (x509_config.trust != NULL) {
1.19      inoguchi  944:                for (i = 0; i < sk_ASN1_OBJECT_num(x509_config.trust); i++) {
1.20      inoguchi  945:                        x509_config.objtmp = sk_ASN1_OBJECT_value(
                    946:                            x509_config.trust, i);
1.23      inoguchi  947:                        if (!X509_add1_trust_object(x, x509_config.objtmp))
                    948:                                goto end;
1.1       jsing     949:                }
                    950:        }
1.21      inoguchi  951:        if (x509_config.reject != NULL) {
1.19      inoguchi  952:                for (i = 0; i < sk_ASN1_OBJECT_num(x509_config.reject); i++) {
1.20      inoguchi  953:                        x509_config.objtmp = sk_ASN1_OBJECT_value(
                    954:                            x509_config.reject, i);
1.23      inoguchi  955:                        if (!X509_add1_reject_object(x, x509_config.objtmp))
                    956:                                goto end;
1.1       jsing     957:                }
                    958:        }
1.19      inoguchi  959:        if (x509_config.num) {
                    960:                for (i = 1; i <= x509_config.num; i++) {
                    961:                        if (x509_config.issuer == i) {
1.1       jsing     962:                                print_name(STDout, "issuer= ",
1.20      inoguchi  963:                                    X509_get_issuer_name(x),
                    964:                                    x509_config.nmflag);
1.19      inoguchi  965:                        } else if (x509_config.subject == i) {
1.1       jsing     966:                                print_name(STDout, "subject= ",
1.20      inoguchi  967:                                    X509_get_subject_name(x),
                    968:                                    x509_config.nmflag);
1.19      inoguchi  969:                        } else if (x509_config.serial == i) {
1.1       jsing     970:                                BIO_printf(STDout, "serial=");
                    971:                                i2a_ASN1_INTEGER(STDout,
                    972:                                    X509_get_serialNumber(x));
                    973:                                BIO_printf(STDout, "\n");
1.19      inoguchi  974:                        } else if (x509_config.next_serial == i) {
1.1       jsing     975:                                BIGNUM *bnser;
                    976:                                ASN1_INTEGER *ser;
                    977:                                ser = X509_get_serialNumber(x);
1.23      inoguchi  978:                                if (ser == NULL)
                    979:                                        goto end;
1.1       jsing     980:                                bnser = ASN1_INTEGER_to_BN(ser, NULL);
1.21      inoguchi  981:                                if (bnser == NULL)
1.1       jsing     982:                                        goto end;
1.22      inoguchi  983:                                if (!BN_add_word(bnser, 1)) {
                    984:                                        BN_free(bnser);
1.1       jsing     985:                                        goto end;
1.22      inoguchi  986:                                }
1.1       jsing     987:                                ser = BN_to_ASN1_INTEGER(bnser, NULL);
1.22      inoguchi  988:                                if (ser == NULL) {
                    989:                                        BN_free(bnser);
1.1       jsing     990:                                        goto end;
1.22      inoguchi  991:                                }
1.1       jsing     992:                                BN_free(bnser);
                    993:                                i2a_ASN1_INTEGER(out, ser);
                    994:                                ASN1_INTEGER_free(ser);
                    995:                                BIO_puts(out, "\n");
1.20      inoguchi  996:                        } else if ((x509_config.email == i) ||
                    997:                            (x509_config.ocsp_uri == i)) {
1.1       jsing     998:                                int j;
                    999:                                STACK_OF(OPENSSL_STRING) *emlst;
1.19      inoguchi 1000:                                if (x509_config.email == i)
1.1       jsing    1001:                                        emlst = X509_get1_email(x);
                   1002:                                else
                   1003:                                        emlst = X509_get1_ocsp(x);
                   1004:                                for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
                   1005:                                        BIO_printf(STDout, "%s\n",
                   1006:                                            sk_OPENSSL_STRING_value(emlst, j));
                   1007:                                X509_email_free(emlst);
1.19      inoguchi 1008:                        } else if (x509_config.aliasout == i) {
1.24      schwarze 1009:                                unsigned char *albuf;
                   1010:                                int buflen;
                   1011:                                albuf = X509_alias_get0(x, &buflen);
                   1012:                                if (albuf != NULL)
                   1013:                                        BIO_printf(STDout, "%.*s\n",
                   1014:                                            buflen, albuf);
1.1       jsing    1015:                                else
                   1016:                                        BIO_puts(STDout, "<No Alias>\n");
1.19      inoguchi 1017:                        } else if (x509_config.subject_hash == i) {
1.20      inoguchi 1018:                                BIO_printf(STDout, "%08lx\n",
                   1019:                                    X509_subject_name_hash(x));
1.1       jsing    1020:                        }
                   1021: #ifndef OPENSSL_NO_MD5
1.19      inoguchi 1022:                        else if (x509_config.subject_hash_old == i) {
1.20      inoguchi 1023:                                BIO_printf(STDout, "%08lx\n",
                   1024:                                    X509_subject_name_hash_old(x));
1.1       jsing    1025:                        }
                   1026: #endif
1.19      inoguchi 1027:                        else if (x509_config.issuer_hash == i) {
1.20      inoguchi 1028:                                BIO_printf(STDout, "%08lx\n",
                   1029:                                    X509_issuer_name_hash(x));
1.1       jsing    1030:                        }
                   1031: #ifndef OPENSSL_NO_MD5
1.19      inoguchi 1032:                        else if (x509_config.issuer_hash_old == i) {
1.20      inoguchi 1033:                                BIO_printf(STDout, "%08lx\n",
                   1034:                                    X509_issuer_name_hash_old(x));
1.1       jsing    1035:                        }
                   1036: #endif
1.19      inoguchi 1037:                        else if (x509_config.pprint == i) {
1.1       jsing    1038:                                X509_PURPOSE *ptmp;
                   1039:                                int j;
                   1040:                                BIO_printf(STDout, "Certificate purposes:\n");
                   1041:                                for (j = 0; j < X509_PURPOSE_get_count(); j++) {
                   1042:                                        ptmp = X509_PURPOSE_get0(j);
                   1043:                                        purpose_print(STDout, x, ptmp);
                   1044:                                }
1.19      inoguchi 1045:                        } else if (x509_config.modulus == i) {
1.1       jsing    1046:                                EVP_PKEY *pkey;
                   1047:
1.28    ! tb       1048:                                pkey = X509_get0_pubkey(x);
1.1       jsing    1049:                                if (pkey == NULL) {
1.20      inoguchi 1050:                                        BIO_printf(bio_err,
                   1051:                                            "Modulus=unavailable\n");
1.1       jsing    1052:                                        ERR_print_errors(bio_err);
                   1053:                                        goto end;
                   1054:                                }
                   1055:                                BIO_printf(STDout, "Modulus=");
1.27      tb       1056:                                if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
                   1057:                                        RSA *rsa = EVP_PKEY_get0_RSA(pkey);
                   1058:                                        const BIGNUM *n = NULL;
                   1059:
                   1060:                                        RSA_get0_key(rsa, &n, NULL, NULL);
                   1061:                                        BN_print(STDout, n);
                   1062:                                } else if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) {
                   1063:                                        DSA *dsa = EVP_PKEY_get0_DSA(pkey);
                   1064:                                        const BIGNUM *pub_key = NULL;
                   1065:
                   1066:                                        DSA_get0_key(dsa, &pub_key, NULL);
                   1067:
                   1068:                                        BN_print(STDout, pub_key);
                   1069:                                } else
1.20      inoguchi 1070:                                        BIO_printf(STDout,
                   1071:                                            "Wrong Algorithm type");
1.1       jsing    1072:                                BIO_printf(STDout, "\n");
1.19      inoguchi 1073:                        } else if (x509_config.pubkey == i) {
1.1       jsing    1074:                                EVP_PKEY *pkey;
                   1075:
1.28    ! tb       1076:                                pkey = X509_get0_pubkey(x);
1.1       jsing    1077:                                if (pkey == NULL) {
1.20      inoguchi 1078:                                        BIO_printf(bio_err,
                   1079:                                            "Error getting public key\n");
1.1       jsing    1080:                                        ERR_print_errors(bio_err);
                   1081:                                        goto end;
                   1082:                                }
                   1083:                                PEM_write_bio_PUBKEY(STDout, pkey);
1.19      inoguchi 1084:                        } else if (x509_config.C == i) {
1.1       jsing    1085:                                unsigned char *d;
                   1086:                                char *m;
                   1087:                                int y, z;
                   1088:
1.23      inoguchi 1089:                                m = X509_NAME_oneline(X509_get_subject_name(x),
1.1       jsing    1090:                                    buf, sizeof buf);
1.23      inoguchi 1091:                                if (m == NULL)
                   1092:                                        goto end;
1.1       jsing    1093:                                BIO_printf(STDout, "/* subject:%s */\n", buf);
1.20      inoguchi 1094:                                m = X509_NAME_oneline(X509_get_issuer_name(x),
                   1095:                                    buf, sizeof buf);
1.23      inoguchi 1096:                                if (m == NULL)
                   1097:                                        goto end;
1.1       jsing    1098:                                BIO_printf(STDout, "/* issuer :%s */\n", buf);
                   1099:
                   1100:                                z = i2d_X509(x, NULL);
1.23      inoguchi 1101:                                if (z < 0)
                   1102:                                        goto end;
                   1103:
1.1       jsing    1104:                                m = malloc(z);
1.8       bcook    1105:                                if (m == NULL) {
                   1106:                                        BIO_printf(bio_err, "out of mem\n");
                   1107:                                        goto end;
                   1108:                                }
1.1       jsing    1109:
                   1110:                                d = (unsigned char *) m;
                   1111:                                z = i2d_X509_NAME(X509_get_subject_name(x), &d);
1.23      inoguchi 1112:                                if (z < 0) {
                   1113:                                        free(m);
                   1114:                                        goto end;
                   1115:                                }
1.20      inoguchi 1116:                                BIO_printf(STDout,
                   1117:                                    "unsigned char XXX_subject_name[%d]={\n", z);
1.1       jsing    1118:                                d = (unsigned char *) m;
                   1119:                                for (y = 0; y < z; y++) {
                   1120:                                        BIO_printf(STDout, "0x%02X,", d[y]);
                   1121:                                        if ((y & 0x0f) == 0x0f)
                   1122:                                                BIO_printf(STDout, "\n");
                   1123:                                }
                   1124:                                if (y % 16 != 0)
                   1125:                                        BIO_printf(STDout, "\n");
                   1126:                                BIO_printf(STDout, "};\n");
                   1127:
                   1128:                                z = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d);
1.23      inoguchi 1129:                                if (z < 0) {
                   1130:                                        free(m);
                   1131:                                        goto end;
                   1132:                                }
1.20      inoguchi 1133:                                BIO_printf(STDout,
                   1134:                                    "unsigned char XXX_public_key[%d]={\n", z);
1.1       jsing    1135:                                d = (unsigned char *) m;
                   1136:                                for (y = 0; y < z; y++) {
                   1137:                                        BIO_printf(STDout, "0x%02X,", d[y]);
                   1138:                                        if ((y & 0x0f) == 0x0f)
                   1139:                                                BIO_printf(STDout, "\n");
                   1140:                                }
                   1141:                                if (y % 16 != 0)
                   1142:                                        BIO_printf(STDout, "\n");
                   1143:                                BIO_printf(STDout, "};\n");
                   1144:
                   1145:                                z = i2d_X509(x, &d);
1.23      inoguchi 1146:                                if (z < 0) {
                   1147:                                        free(m);
                   1148:                                        goto end;
                   1149:                                }
1.20      inoguchi 1150:                                BIO_printf(STDout,
                   1151:                                    "unsigned char XXX_certificate[%d]={\n", z);
1.1       jsing    1152:                                d = (unsigned char *) m;
                   1153:                                for (y = 0; y < z; y++) {
                   1154:                                        BIO_printf(STDout, "0x%02X,", d[y]);
                   1155:                                        if ((y & 0x0f) == 0x0f)
                   1156:                                                BIO_printf(STDout, "\n");
                   1157:                                }
                   1158:                                if (y % 16 != 0)
                   1159:                                        BIO_printf(STDout, "\n");
                   1160:                                BIO_printf(STDout, "};\n");
                   1161:
                   1162:                                free(m);
1.19      inoguchi 1163:                        } else if (x509_config.text == i) {
1.23      inoguchi 1164:                                if(!X509_print_ex(STDout, x, x509_config.nmflag,
                   1165:                                    x509_config.certflag))
                   1166:                                        goto end;
1.19      inoguchi 1167:                        } else if (x509_config.startdate == i) {
1.18      beck     1168:                                ASN1_TIME *nB = X509_get_notBefore(x);
1.1       jsing    1169:                                BIO_puts(STDout, "notBefore=");
1.20      inoguchi 1170:                                if (ASN1_time_parse(nB->data, nB->length, NULL,
                   1171:                                    0) == -1)
                   1172:                                        BIO_puts(STDout,
                   1173:                                            "INVALID RFC5280 TIME");
1.18      beck     1174:                                else
                   1175:                                        ASN1_TIME_print(STDout, nB);
1.1       jsing    1176:                                BIO_puts(STDout, "\n");
1.19      inoguchi 1177:                        } else if (x509_config.enddate == i) {
1.18      beck     1178:                                ASN1_TIME *nA = X509_get_notAfter(x);
1.1       jsing    1179:                                BIO_puts(STDout, "notAfter=");
1.20      inoguchi 1180:                                if (ASN1_time_parse(nA->data, nA->length, NULL,
                   1181:                                    0) == -1)
                   1182:                                        BIO_puts(STDout,
                   1183:                                            "INVALID RFC5280 TIME");
1.18      beck     1184:                                else
                   1185:                                        ASN1_TIME_print(STDout, nA);
1.1       jsing    1186:                                BIO_puts(STDout, "\n");
1.19      inoguchi 1187:                        } else if (x509_config.fingerprint == i) {
1.1       jsing    1188:                                int j;
                   1189:                                unsigned int n;
                   1190:                                unsigned char md[EVP_MAX_MD_SIZE];
1.19      inoguchi 1191:                                const EVP_MD *fdig = x509_config.digest;
1.1       jsing    1192:
1.21      inoguchi 1193:                                if (fdig == NULL)
1.17      jsg      1194:                                        fdig = EVP_sha256();
1.1       jsing    1195:
                   1196:                                if (!X509_digest(x, fdig, md, &n)) {
                   1197:                                        BIO_printf(bio_err, "out of memory\n");
                   1198:                                        goto end;
                   1199:                                }
                   1200:                                BIO_printf(STDout, "%s Fingerprint=",
                   1201:                                    OBJ_nid2sn(EVP_MD_type(fdig)));
                   1202:                                for (j = 0; j < (int) n; j++) {
                   1203:                                        BIO_printf(STDout, "%02X%c", md[j],
                   1204:                                            (j + 1 == (int)n) ? '\n' : ':');
                   1205:                                }
1.20      inoguchi 1206:
1.1       jsing    1207:                        /* should be in the library */
1.20      inoguchi 1208:                        } else if ((x509_config.sign_flag == i) &&
                   1209:                            (x509_config.x509req == 0)) {
1.1       jsing    1210:                                BIO_printf(bio_err, "Getting Private key\n");
                   1211:                                if (Upkey == NULL) {
                   1212:                                        Upkey = load_key(bio_err,
1.20      inoguchi 1213:                                            x509_config.keyfile,
                   1214:                                            x509_config.keyformat, 0, passin,
                   1215:                                            "Private key");
1.1       jsing    1216:                                        if (Upkey == NULL)
                   1217:                                                goto end;
                   1218:                                }
1.20      inoguchi 1219:                                if (!sign(x, Upkey, x509_config.days,
                   1220:                                    x509_config.clrext, x509_config.digest,
1.19      inoguchi 1221:                                    extconf, x509_config.extsect))
1.1       jsing    1222:                                        goto end;
1.19      inoguchi 1223:                        } else if (x509_config.CA_flag == i) {
1.1       jsing    1224:                                BIO_printf(bio_err, "Getting CA Private Key\n");
1.19      inoguchi 1225:                                if (x509_config.CAkeyfile != NULL) {
1.1       jsing    1226:                                        CApkey = load_key(bio_err,
1.20      inoguchi 1227:                                            x509_config.CAkeyfile,
                   1228:                                            x509_config.CAkeyformat, 0, passin,
                   1229:                                            "CA Private Key");
1.1       jsing    1230:                                        if (CApkey == NULL)
                   1231:                                                goto end;
                   1232:                                }
1.20      inoguchi 1233:                                if (!x509_certify(ctx, x509_config.CAfile,
                   1234:                                    x509_config.digest, x, xca, CApkey,
                   1235:                                    x509_config.sigopts, x509_config.CAserial,
                   1236:                                    x509_config.CA_createserial,
                   1237:                                    x509_config.days, x509_config.clrext,
                   1238:                                    extconf, x509_config.extsect,
                   1239:                                    x509_config.sno))
1.1       jsing    1240:                                        goto end;
1.19      inoguchi 1241:                        } else if (x509_config.x509req == i) {
1.1       jsing    1242:                                EVP_PKEY *pk;
                   1243:
1.20      inoguchi 1244:                                BIO_printf(bio_err,
                   1245:                                    "Getting request Private Key\n");
1.19      inoguchi 1246:                                if (x509_config.keyfile == NULL) {
1.20      inoguchi 1247:                                        BIO_printf(bio_err,
                   1248:                                            "no request key file specified\n");
1.1       jsing    1249:                                        goto end;
                   1250:                                } else {
                   1251:                                        pk = load_key(bio_err,
1.20      inoguchi 1252:                                            x509_config.keyfile,
                   1253:                                            x509_config.keyformat, 0, passin,
                   1254:                                            "request key");
1.1       jsing    1255:                                        if (pk == NULL)
                   1256:                                                goto end;
                   1257:                                }
                   1258:
1.20      inoguchi 1259:                                BIO_printf(bio_err,
                   1260:                                    "Generating certificate request\n");
1.1       jsing    1261:
1.19      inoguchi 1262:                                rq = X509_to_X509_REQ(x, pk, x509_config.digest);
1.1       jsing    1263:                                EVP_PKEY_free(pk);
                   1264:                                if (rq == NULL) {
                   1265:                                        ERR_print_errors(bio_err);
                   1266:                                        goto end;
                   1267:                                }
1.19      inoguchi 1268:                                if (!x509_config.noout) {
1.23      inoguchi 1269:                                        if (!X509_REQ_print(out, rq))
                   1270:                                                goto end;
                   1271:                                        if (!PEM_write_bio_X509_REQ(out, rq))
                   1272:                                                goto end;
1.1       jsing    1273:                                }
1.19      inoguchi 1274:                                x509_config.noout = 1;
                   1275:                        } else if (x509_config.ocspid == i) {
1.23      inoguchi 1276:                                if (!X509_ocspid_print(out, x))
                   1277:                                        goto end;
1.1       jsing    1278:                        }
                   1279:                }
                   1280:        }
1.19      inoguchi 1281:        if (x509_config.checkend) {
                   1282:                time_t tcheck = time(NULL) + x509_config.checkoffset;
1.18      beck     1283:                int timecheck = X509_cmp_time(X509_get_notAfter(x), &tcheck);
                   1284:                if (timecheck == 0) {
                   1285:                        BIO_printf(out, "Certificate expiry time is invalid\n");
                   1286:                        ret = 1;
                   1287:                } else if (timecheck < 0) {
1.1       jsing    1288:                        BIO_printf(out, "Certificate will expire\n");
                   1289:                        ret = 1;
                   1290:                } else {
                   1291:                        BIO_printf(out, "Certificate will not expire\n");
                   1292:                        ret = 0;
                   1293:                }
                   1294:                goto end;
                   1295:        }
1.19      inoguchi 1296:        if (x509_config.noout) {
1.1       jsing    1297:                ret = 0;
                   1298:                goto end;
                   1299:        }
1.19      inoguchi 1300:        if (x509_config.outformat == FORMAT_ASN1)
1.1       jsing    1301:                i = i2d_X509_bio(out, x);
1.19      inoguchi 1302:        else if (x509_config.outformat == FORMAT_PEM) {
                   1303:                if (x509_config.trustout)
1.1       jsing    1304:                        i = PEM_write_bio_X509_AUX(out, x);
                   1305:                else
                   1306:                        i = PEM_write_bio_X509(out, x);
                   1307:        } else {
1.20      inoguchi 1308:                BIO_printf(bio_err,
                   1309:                    "bad output format specified for outfile\n");
1.1       jsing    1310:                goto end;
                   1311:        }
                   1312:        if (!i) {
                   1313:                BIO_printf(bio_err, "unable to write certificate\n");
                   1314:                ERR_print_errors(bio_err);
                   1315:                goto end;
                   1316:        }
                   1317:        ret = 0;
                   1318:
1.16      jsing    1319:  end:
1.1       jsing    1320:        OBJ_cleanup();
                   1321:        NCONF_free(extconf);
                   1322:        BIO_free_all(out);
                   1323:        BIO_free_all(STDout);
                   1324:        X509_STORE_free(ctx);
                   1325:        X509_REQ_free(req);
                   1326:        X509_free(x);
                   1327:        X509_free(xca);
                   1328:        EVP_PKEY_free(Upkey);
                   1329:        EVP_PKEY_free(CApkey);
1.19      inoguchi 1330:        sk_OPENSSL_STRING_free(x509_config.sigopts);
1.1       jsing    1331:        X509_REQ_free(rq);
1.19      inoguchi 1332:        ASN1_INTEGER_free(x509_config.sno);
                   1333:        sk_ASN1_OBJECT_pop_free(x509_config.trust, ASN1_OBJECT_free);
                   1334:        sk_ASN1_OBJECT_pop_free(x509_config.reject, ASN1_OBJECT_free);
1.1       jsing    1335:        free(passin);
                   1336:
                   1337:        return (ret);
                   1338: }
                   1339:
                   1340: static ASN1_INTEGER *
                   1341: x509_load_serial(char *CAfile, char *serialfile, int create)
                   1342: {
                   1343:        char *buf = NULL, *p;
                   1344:        ASN1_INTEGER *bs = NULL;
                   1345:        BIGNUM *serial = NULL;
                   1346:        size_t len;
                   1347:
                   1348:        len = ((serialfile == NULL) ? (strlen(CAfile) + strlen(POSTFIX) + 1) :
                   1349:            (strlen(serialfile))) + 1;
                   1350:        buf = malloc(len);
                   1351:        if (buf == NULL) {
                   1352:                BIO_printf(bio_err, "out of mem\n");
                   1353:                goto end;
                   1354:        }
                   1355:        if (serialfile == NULL) {
                   1356:                strlcpy(buf, CAfile, len);
                   1357:                for (p = buf; *p; p++)
                   1358:                        if (*p == '.') {
                   1359:                                *p = '\0';
                   1360:                                break;
                   1361:                        }
                   1362:                strlcat(buf, POSTFIX, len);
                   1363:        } else
                   1364:                strlcpy(buf, serialfile, len);
                   1365:
                   1366:        serial = load_serial(buf, create, NULL);
                   1367:        if (serial == NULL)
                   1368:                goto end;
                   1369:
                   1370:        if (!BN_add_word(serial, 1)) {
                   1371:                BIO_printf(bio_err, "add_word failure\n");
                   1372:                goto end;
                   1373:        }
                   1374:        if (!save_serial(buf, NULL, serial, &bs))
                   1375:                goto end;
                   1376:
1.16      jsing    1377:  end:
1.1       jsing    1378:        free(buf);
                   1379:        BN_free(serial);
                   1380:
                   1381:        return bs;
                   1382: }
                   1383:
                   1384: static int
                   1385: x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, X509 *x,
                   1386:     X509 *xca, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *sigopts,
                   1387:     char *serialfile, int create, int days, int clrext, CONF *conf,
                   1388:     char *section, ASN1_INTEGER *sno)
                   1389: {
                   1390:        int ret = 0;
                   1391:        ASN1_INTEGER *bs = NULL;
1.25      tb       1392:        X509_STORE_CTX *xsc = NULL;
1.1       jsing    1393:        EVP_PKEY *upkey;
                   1394:
                   1395:        upkey = X509_get_pubkey(xca);
1.23      inoguchi 1396:        if (upkey == NULL)
                   1397:                goto end;
1.1       jsing    1398:        EVP_PKEY_copy_parameters(upkey, pkey);
                   1399:        EVP_PKEY_free(upkey);
                   1400:
1.25      tb       1401:        if ((xsc = X509_STORE_CTX_new()) == NULL)
                   1402:                goto end;
                   1403:        if (!X509_STORE_CTX_init(xsc, ctx, x, NULL)) {
1.1       jsing    1404:                BIO_printf(bio_err, "Error initialising X509 store\n");
                   1405:                goto end;
                   1406:        }
1.21      inoguchi 1407:        if (sno != NULL)
1.1       jsing    1408:                bs = sno;
1.21      inoguchi 1409:        else if ((bs = x509_load_serial(CAfile, serialfile, create)) == NULL)
1.1       jsing    1410:                goto end;
                   1411:
                   1412: /*     if (!X509_STORE_add_cert(ctx,x)) goto end;*/
                   1413:
                   1414:        /*
                   1415:         * NOTE: this certificate can/should be self signed, unless it was a
                   1416:         * certificate request in which case it is not.
                   1417:         */
1.25      tb       1418:        X509_STORE_CTX_set_cert(xsc, x);
                   1419:        X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
                   1420:        if (!x509_config.reqfile && X509_verify_cert(xsc) <= 0)
1.1       jsing    1421:                goto end;
                   1422:
                   1423:        if (!X509_check_private_key(xca, pkey)) {
1.20      inoguchi 1424:                BIO_printf(bio_err,
                   1425:                    "CA certificate and CA private key do not match\n");
1.1       jsing    1426:                goto end;
                   1427:        }
                   1428:        if (!X509_set_issuer_name(x, X509_get_subject_name(xca)))
                   1429:                goto end;
                   1430:        if (!X509_set_serialNumber(x, bs))
                   1431:                goto end;
                   1432:
                   1433:        if (X509_gmtime_adj(X509_get_notBefore(x), 0L) == NULL)
                   1434:                goto end;
                   1435:
                   1436:        /* hardwired expired */
                   1437:        if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL)
                   1438:                goto end;
                   1439:
                   1440:        if (clrext) {
1.23      inoguchi 1441:                while (X509_get_ext_count(x) > 0) {
                   1442:                        if (X509_delete_ext(x, 0) == NULL)
                   1443:                                goto end;
                   1444:                }
1.1       jsing    1445:        }
1.21      inoguchi 1446:        if (conf != NULL) {
1.1       jsing    1447:                X509V3_CTX ctx2;
1.23      inoguchi 1448:                if (!X509_set_version(x, 2))    /* version 3 certificate */
                   1449:                        goto end;
1.1       jsing    1450:                X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
                   1451:                X509V3_set_nconf(&ctx2, conf);
                   1452:                if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x))
                   1453:                        goto end;
                   1454:        }
                   1455:        if (!do_X509_sign(bio_err, x, pkey, digest, sigopts))
                   1456:                goto end;
1.23      inoguchi 1457:
1.1       jsing    1458:        ret = 1;
1.16      jsing    1459:  end:
1.25      tb       1460:        X509_STORE_CTX_free(xsc);
1.1       jsing    1461:        if (!ret)
                   1462:                ERR_print_errors(bio_err);
1.21      inoguchi 1463:        if (sno == NULL)
1.1       jsing    1464:                ASN1_INTEGER_free(bs);
                   1465:        return ret;
                   1466: }
                   1467:
                   1468: static int
                   1469: callb(int ok, X509_STORE_CTX *ctx)
                   1470: {
                   1471:        int err;
                   1472:        X509 *err_cert;
                   1473:
                   1474:        /*
                   1475:         * it is ok to use a self signed certificate This case will catch
                   1476:         * both the initial ok == 0 and the final ok == 1 calls to this
                   1477:         * function
                   1478:         */
                   1479:        err = X509_STORE_CTX_get_error(ctx);
                   1480:        if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
                   1481:                return 1;
                   1482:
                   1483:        /*
                   1484:         * BAD we should have gotten an error.  Normally if everything worked
                   1485:         * X509_STORE_CTX_get_error(ctx) will still be set to
                   1486:         * DEPTH_ZERO_SELF_....
                   1487:         */
                   1488:        if (ok) {
1.20      inoguchi 1489:                BIO_printf(bio_err,
                   1490:                    "error with certificate to be certified - should be self signed\n");
1.1       jsing    1491:                return 0;
                   1492:        } else {
                   1493:                err_cert = X509_STORE_CTX_get_current_cert(ctx);
                   1494:                print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0);
1.20      inoguchi 1495:                BIO_printf(bio_err,
                   1496:                    "error with certificate - error %d at depth %d\n%s\n",
1.1       jsing    1497:                    err, X509_STORE_CTX_get_error_depth(ctx),
                   1498:                    X509_verify_cert_error_string(err));
                   1499:                return 1;
                   1500:        }
                   1501: }
                   1502:
                   1503: /* self sign */
                   1504: static int
                   1505: sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest,
                   1506:     CONF *conf, char *section)
                   1507: {
                   1508:        EVP_PKEY *pktmp;
                   1509:
                   1510:        pktmp = X509_get_pubkey(x);
1.23      inoguchi 1511:        if (pktmp == NULL)
                   1512:                goto err;
1.1       jsing    1513:        EVP_PKEY_copy_parameters(pktmp, pkey);
                   1514:        EVP_PKEY_save_parameters(pktmp, 1);
                   1515:        EVP_PKEY_free(pktmp);
                   1516:
                   1517:        if (!X509_set_issuer_name(x, X509_get_subject_name(x)))
                   1518:                goto err;
                   1519:        if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL)
                   1520:                goto err;
                   1521:
                   1522:        /* Lets just make it 12:00am GMT, Jan 1 1970 */
                   1523:        /* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */
                   1524:        /* 28 days to be certified */
                   1525:
                   1526:        if (X509_gmtime_adj(X509_get_notAfter(x),
                   1527:            (long) 60 * 60 * 24 * days) == NULL)
                   1528:                goto err;
                   1529:
                   1530:        if (!X509_set_pubkey(x, pkey))
                   1531:                goto err;
                   1532:        if (clrext) {
1.23      inoguchi 1533:                while (X509_get_ext_count(x) > 0) {
                   1534:                        if (X509_delete_ext(x, 0) == NULL)
                   1535:                                goto err;
                   1536:                }
1.1       jsing    1537:        }
1.21      inoguchi 1538:        if (conf != NULL) {
1.1       jsing    1539:                X509V3_CTX ctx;
1.23      inoguchi 1540:                if (!X509_set_version(x, 2))    /* version 3 certificate */
                   1541:                        goto err;
1.1       jsing    1542:                X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
                   1543:                X509V3_set_nconf(&ctx, conf);
                   1544:                if (!X509V3_EXT_add_nconf(conf, &ctx, section, x))
                   1545:                        goto err;
                   1546:        }
                   1547:        if (!X509_sign(x, pkey, digest))
                   1548:                goto err;
1.20      inoguchi 1549:
1.1       jsing    1550:        return 1;
                   1551:
1.16      jsing    1552:  err:
1.1       jsing    1553:        ERR_print_errors(bio_err);
                   1554:        return 0;
                   1555: }
                   1556:
                   1557: static int
                   1558: purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
                   1559: {
                   1560:        int id, i, idret;
                   1561:        char *pname;
                   1562:
                   1563:        id = X509_PURPOSE_get_id(pt);
                   1564:        pname = X509_PURPOSE_get0_name(pt);
                   1565:        for (i = 0; i < 2; i++) {
                   1566:                idret = X509_check_purpose(cert, id, i);
                   1567:                BIO_printf(bio, "%s%s : ", pname, i ? " CA" : "");
                   1568:                if (idret == 1)
                   1569:                        BIO_printf(bio, "Yes\n");
                   1570:                else if (idret == 0)
                   1571:                        BIO_printf(bio, "No\n");
                   1572:                else
                   1573:                        BIO_printf(bio, "Yes (WARNING code=%d)\n", idret);
                   1574:        }
                   1575:        return 1;
                   1576: }