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

1.30    ! joshua      1: /* $OpenBSD: x509.c,v 1.29 2021/12/12 20:34:04 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:
1.30    ! joshua    738:        if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
        !           739:                perror("pledge");
        !           740:                exit(1);
1.10      doug      741:        }
1.1       jsing     742:
1.19      inoguchi  743:        memset(&x509_config, 0, sizeof(x509_config));
                    744:        x509_config.days = DEF_DAYS;
                    745:        x509_config.informat = FORMAT_PEM;
                    746:        x509_config.outformat = FORMAT_PEM;
                    747:        x509_config.keyformat = FORMAT_PEM;
                    748:        x509_config.CAformat = FORMAT_PEM;
                    749:        x509_config.CAkeyformat = FORMAT_PEM;
1.1       jsing     750:
                    751:        STDout = BIO_new_fp(stdout, BIO_NOCLOSE);
                    752:
                    753:        ctx = X509_STORE_new();
                    754:        if (ctx == NULL)
                    755:                goto end;
                    756:        X509_STORE_set_verify_cb(ctx, callb);
                    757:
1.19      inoguchi  758:        if (options_parse(argc, argv, x509_options, NULL, NULL) != 0)
                    759:                goto bad;
1.1       jsing     760:
1.19      inoguchi  761:        if (x509_config.badops) {
1.16      jsing     762:  bad:
1.19      inoguchi  763:                x509_usage();
1.1       jsing     764:                goto end;
                    765:        }
                    766:
1.19      inoguchi  767:        if (!app_passwd(bio_err, x509_config.passargin, NULL, &passin, NULL)) {
1.1       jsing     768:                BIO_printf(bio_err, "Error getting password\n");
                    769:                goto end;
                    770:        }
                    771:        if (!X509_STORE_set_default_paths(ctx)) {
                    772:                ERR_print_errors(bio_err);
                    773:                goto end;
                    774:        }
1.20      inoguchi  775:        if ((x509_config.CAkeyfile == NULL) && (x509_config.CA_flag) &&
                    776:            (x509_config.CAformat == FORMAT_PEM)) {
1.19      inoguchi  777:                x509_config.CAkeyfile = x509_config.CAfile;
                    778:        } else if ((x509_config.CA_flag) && (x509_config.CAkeyfile == NULL)) {
1.1       jsing     779:                BIO_printf(bio_err,
                    780:                    "need to specify a CAkey if using the CA command\n");
                    781:                goto end;
                    782:        }
1.21      inoguchi  783:        if (x509_config.extfile != NULL) {
1.1       jsing     784:                long errorline = -1;
                    785:                X509V3_CTX ctx2;
                    786:                extconf = NCONF_new(NULL);
1.19      inoguchi  787:                if (!NCONF_load(extconf, x509_config.extfile, &errorline)) {
1.1       jsing     788:                        if (errorline <= 0)
                    789:                                BIO_printf(bio_err,
                    790:                                    "error loading the config file '%s'\n",
1.19      inoguchi  791:                                    x509_config.extfile);
1.1       jsing     792:                        else
                    793:                                BIO_printf(bio_err,
                    794:                                    "error on line %ld of config file '%s'\n",
1.19      inoguchi  795:                                    errorline, x509_config.extfile);
1.1       jsing     796:                        goto end;
                    797:                }
1.21      inoguchi  798:                if (x509_config.extsect == NULL) {
1.20      inoguchi  799:                        x509_config.extsect = NCONF_get_string(extconf,
                    800:                            "default", "extensions");
1.21      inoguchi  801:                        if (x509_config.extsect == NULL) {
1.1       jsing     802:                                ERR_clear_error();
1.19      inoguchi  803:                                x509_config.extsect = "default";
1.1       jsing     804:                        }
                    805:                }
                    806:                X509V3_set_ctx_test(&ctx2);
                    807:                X509V3_set_nconf(&ctx2, extconf);
1.20      inoguchi  808:                if (!X509V3_EXT_add_nconf(extconf, &ctx2, x509_config.extsect,
                    809:                    NULL)) {
1.1       jsing     810:                        BIO_printf(bio_err,
                    811:                            "Error Loading extension section %s\n",
1.19      inoguchi  812:                            x509_config.extsect);
1.1       jsing     813:                        ERR_print_errors(bio_err);
                    814:                        goto end;
                    815:                }
                    816:        }
1.19      inoguchi  817:        if (x509_config.reqfile) {
1.1       jsing     818:                EVP_PKEY *pkey;
                    819:                BIO *in;
                    820:
1.19      inoguchi  821:                if (!x509_config.sign_flag && !x509_config.CA_flag) {
1.20      inoguchi  822:                        BIO_printf(bio_err,
                    823:                            "We need a private key to sign with\n");
1.1       jsing     824:                        goto end;
                    825:                }
                    826:                in = BIO_new(BIO_s_file());
                    827:                if (in == NULL) {
                    828:                        ERR_print_errors(bio_err);
                    829:                        goto end;
                    830:                }
1.19      inoguchi  831:                if (x509_config.infile == NULL)
1.1       jsing     832:                        BIO_set_fp(in, stdin, BIO_NOCLOSE | BIO_FP_TEXT);
                    833:                else {
1.19      inoguchi  834:                        if (BIO_read_filename(in, x509_config.infile) <= 0) {
                    835:                                perror(x509_config.infile);
1.1       jsing     836:                                BIO_free(in);
                    837:                                goto end;
                    838:                        }
                    839:                }
                    840:                req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
                    841:                BIO_free(in);
                    842:
                    843:                if (req == NULL) {
                    844:                        ERR_print_errors(bio_err);
                    845:                        goto end;
                    846:                }
1.29      tb        847:                if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) {
1.1       jsing     848:                        BIO_printf(bio_err, "error unpacking public key\n");
                    849:                        goto end;
                    850:                }
                    851:                i = X509_REQ_verify(req, pkey);
                    852:                if (i < 0) {
                    853:                        BIO_printf(bio_err, "Signature verification error\n");
                    854:                        ERR_print_errors(bio_err);
                    855:                        goto end;
                    856:                }
                    857:                if (i == 0) {
1.20      inoguchi  858:                        BIO_printf(bio_err,
                    859:                            "Signature did not match the certificate request\n");
1.1       jsing     860:                        goto end;
                    861:                } else
                    862:                        BIO_printf(bio_err, "Signature ok\n");
                    863:
1.20      inoguchi  864:                print_name(bio_err, "subject=", X509_REQ_get_subject_name(req),
                    865:                    x509_config.nmflag);
1.1       jsing     866:
                    867:                if ((x = X509_new()) == NULL)
                    868:                        goto end;
                    869:
1.19      inoguchi  870:                if (x509_config.sno == NULL) {
                    871:                        x509_config.sno = ASN1_INTEGER_new();
1.21      inoguchi  872:                        if (x509_config.sno == NULL ||
1.20      inoguchi  873:                            !rand_serial(NULL, x509_config.sno))
1.1       jsing     874:                                goto end;
1.19      inoguchi  875:                        if (!X509_set_serialNumber(x, x509_config.sno))
1.1       jsing     876:                                goto end;
1.19      inoguchi  877:                        ASN1_INTEGER_free(x509_config.sno);
                    878:                        x509_config.sno = NULL;
                    879:                } else if (!X509_set_serialNumber(x, x509_config.sno))
1.1       jsing     880:                        goto end;
                    881:
1.25      tb        882:                if (!X509_set_issuer_name(x, X509_REQ_get_subject_name(req)))
1.1       jsing     883:                        goto end;
1.25      tb        884:                if (!X509_set_subject_name(x, X509_REQ_get_subject_name(req)))
1.1       jsing     885:                        goto end;
                    886:
1.23      inoguchi  887:                if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL)
                    888:                        goto end;
                    889:                if (X509_time_adj_ex(X509_get_notAfter(x), x509_config.days, 0,
                    890:                    NULL) == NULL)
                    891:                        goto end;
1.1       jsing     892:
1.29      tb        893:                if ((pkey = X509_REQ_get0_pubkey(req)) == NULL)
1.23      inoguchi  894:                        goto end;
                    895:                if (!X509_set_pubkey(x, pkey)) {
                    896:                        EVP_PKEY_free(pkey);
                    897:                        goto end;
                    898:                }
                    899:        } else {
1.20      inoguchi  900:                x = load_cert(bio_err, x509_config.infile, x509_config.informat,
                    901:                    NULL, "Certificate");
1.23      inoguchi  902:        }
1.1       jsing     903:        if (x == NULL)
                    904:                goto end;
1.23      inoguchi  905:
1.19      inoguchi  906:        if (x509_config.CA_flag) {
1.20      inoguchi  907:                xca = load_cert(bio_err, x509_config.CAfile,
                    908:                    x509_config.CAformat, NULL, "CA Certificate");
1.1       jsing     909:                if (xca == NULL)
                    910:                        goto end;
                    911:        }
1.19      inoguchi  912:        if (!x509_config.noout || x509_config.text || x509_config.next_serial) {
1.20      inoguchi  913:                OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3");
1.1       jsing     914:
                    915:                out = BIO_new(BIO_s_file());
                    916:                if (out == NULL) {
                    917:                        ERR_print_errors(bio_err);
                    918:                        goto end;
                    919:                }
1.19      inoguchi  920:                if (x509_config.outfile == NULL) {
1.1       jsing     921:                        BIO_set_fp(out, stdout, BIO_NOCLOSE);
                    922:                } else {
1.19      inoguchi  923:                        if (BIO_write_filename(out, x509_config.outfile) <= 0) {
                    924:                                perror(x509_config.outfile);
1.1       jsing     925:                                goto end;
                    926:                        }
                    927:                }
                    928:        }
1.23      inoguchi  929:        if (x509_config.alias != NULL) {
                    930:                if (!X509_alias_set1(x, (unsigned char *)x509_config.alias, -1))
                    931:                        goto end;
                    932:        }
1.1       jsing     933:
1.19      inoguchi  934:        if (x509_config.clrtrust)
1.1       jsing     935:                X509_trust_clear(x);
1.19      inoguchi  936:        if (x509_config.clrreject)
1.1       jsing     937:                X509_reject_clear(x);
                    938:
1.21      inoguchi  939:        if (x509_config.trust != NULL) {
1.19      inoguchi  940:                for (i = 0; i < sk_ASN1_OBJECT_num(x509_config.trust); i++) {
1.20      inoguchi  941:                        x509_config.objtmp = sk_ASN1_OBJECT_value(
                    942:                            x509_config.trust, i);
1.23      inoguchi  943:                        if (!X509_add1_trust_object(x, x509_config.objtmp))
                    944:                                goto end;
1.1       jsing     945:                }
                    946:        }
1.21      inoguchi  947:        if (x509_config.reject != NULL) {
1.19      inoguchi  948:                for (i = 0; i < sk_ASN1_OBJECT_num(x509_config.reject); i++) {
1.20      inoguchi  949:                        x509_config.objtmp = sk_ASN1_OBJECT_value(
                    950:                            x509_config.reject, i);
1.23      inoguchi  951:                        if (!X509_add1_reject_object(x, x509_config.objtmp))
                    952:                                goto end;
1.1       jsing     953:                }
                    954:        }
1.19      inoguchi  955:        if (x509_config.num) {
                    956:                for (i = 1; i <= x509_config.num; i++) {
                    957:                        if (x509_config.issuer == i) {
1.1       jsing     958:                                print_name(STDout, "issuer= ",
1.20      inoguchi  959:                                    X509_get_issuer_name(x),
                    960:                                    x509_config.nmflag);
1.19      inoguchi  961:                        } else if (x509_config.subject == i) {
1.1       jsing     962:                                print_name(STDout, "subject= ",
1.20      inoguchi  963:                                    X509_get_subject_name(x),
                    964:                                    x509_config.nmflag);
1.19      inoguchi  965:                        } else if (x509_config.serial == i) {
1.1       jsing     966:                                BIO_printf(STDout, "serial=");
                    967:                                i2a_ASN1_INTEGER(STDout,
                    968:                                    X509_get_serialNumber(x));
                    969:                                BIO_printf(STDout, "\n");
1.19      inoguchi  970:                        } else if (x509_config.next_serial == i) {
1.1       jsing     971:                                BIGNUM *bnser;
                    972:                                ASN1_INTEGER *ser;
                    973:                                ser = X509_get_serialNumber(x);
1.23      inoguchi  974:                                if (ser == NULL)
                    975:                                        goto end;
1.1       jsing     976:                                bnser = ASN1_INTEGER_to_BN(ser, NULL);
1.21      inoguchi  977:                                if (bnser == NULL)
1.1       jsing     978:                                        goto end;
1.22      inoguchi  979:                                if (!BN_add_word(bnser, 1)) {
                    980:                                        BN_free(bnser);
1.1       jsing     981:                                        goto end;
1.22      inoguchi  982:                                }
1.1       jsing     983:                                ser = BN_to_ASN1_INTEGER(bnser, NULL);
1.22      inoguchi  984:                                if (ser == NULL) {
                    985:                                        BN_free(bnser);
1.1       jsing     986:                                        goto end;
1.22      inoguchi  987:                                }
1.1       jsing     988:                                BN_free(bnser);
                    989:                                i2a_ASN1_INTEGER(out, ser);
                    990:                                ASN1_INTEGER_free(ser);
                    991:                                BIO_puts(out, "\n");
1.20      inoguchi  992:                        } else if ((x509_config.email == i) ||
                    993:                            (x509_config.ocsp_uri == i)) {
1.1       jsing     994:                                int j;
                    995:                                STACK_OF(OPENSSL_STRING) *emlst;
1.19      inoguchi  996:                                if (x509_config.email == i)
1.1       jsing     997:                                        emlst = X509_get1_email(x);
                    998:                                else
                    999:                                        emlst = X509_get1_ocsp(x);
                   1000:                                for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
                   1001:                                        BIO_printf(STDout, "%s\n",
                   1002:                                            sk_OPENSSL_STRING_value(emlst, j));
                   1003:                                X509_email_free(emlst);
1.19      inoguchi 1004:                        } else if (x509_config.aliasout == i) {
1.24      schwarze 1005:                                unsigned char *albuf;
                   1006:                                int buflen;
                   1007:                                albuf = X509_alias_get0(x, &buflen);
                   1008:                                if (albuf != NULL)
                   1009:                                        BIO_printf(STDout, "%.*s\n",
                   1010:                                            buflen, albuf);
1.1       jsing    1011:                                else
                   1012:                                        BIO_puts(STDout, "<No Alias>\n");
1.19      inoguchi 1013:                        } else if (x509_config.subject_hash == i) {
1.20      inoguchi 1014:                                BIO_printf(STDout, "%08lx\n",
                   1015:                                    X509_subject_name_hash(x));
1.1       jsing    1016:                        }
                   1017: #ifndef OPENSSL_NO_MD5
1.19      inoguchi 1018:                        else if (x509_config.subject_hash_old == i) {
1.20      inoguchi 1019:                                BIO_printf(STDout, "%08lx\n",
                   1020:                                    X509_subject_name_hash_old(x));
1.1       jsing    1021:                        }
                   1022: #endif
1.19      inoguchi 1023:                        else if (x509_config.issuer_hash == i) {
1.20      inoguchi 1024:                                BIO_printf(STDout, "%08lx\n",
                   1025:                                    X509_issuer_name_hash(x));
1.1       jsing    1026:                        }
                   1027: #ifndef OPENSSL_NO_MD5
1.19      inoguchi 1028:                        else if (x509_config.issuer_hash_old == i) {
1.20      inoguchi 1029:                                BIO_printf(STDout, "%08lx\n",
                   1030:                                    X509_issuer_name_hash_old(x));
1.1       jsing    1031:                        }
                   1032: #endif
1.19      inoguchi 1033:                        else if (x509_config.pprint == i) {
1.1       jsing    1034:                                X509_PURPOSE *ptmp;
                   1035:                                int j;
                   1036:                                BIO_printf(STDout, "Certificate purposes:\n");
                   1037:                                for (j = 0; j < X509_PURPOSE_get_count(); j++) {
                   1038:                                        ptmp = X509_PURPOSE_get0(j);
                   1039:                                        purpose_print(STDout, x, ptmp);
                   1040:                                }
1.19      inoguchi 1041:                        } else if (x509_config.modulus == i) {
1.1       jsing    1042:                                EVP_PKEY *pkey;
                   1043:
1.28      tb       1044:                                pkey = X509_get0_pubkey(x);
1.1       jsing    1045:                                if (pkey == NULL) {
1.20      inoguchi 1046:                                        BIO_printf(bio_err,
                   1047:                                            "Modulus=unavailable\n");
1.1       jsing    1048:                                        ERR_print_errors(bio_err);
                   1049:                                        goto end;
                   1050:                                }
                   1051:                                BIO_printf(STDout, "Modulus=");
1.27      tb       1052:                                if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
                   1053:                                        RSA *rsa = EVP_PKEY_get0_RSA(pkey);
                   1054:                                        const BIGNUM *n = NULL;
                   1055:
                   1056:                                        RSA_get0_key(rsa, &n, NULL, NULL);
                   1057:                                        BN_print(STDout, n);
                   1058:                                } else if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) {
                   1059:                                        DSA *dsa = EVP_PKEY_get0_DSA(pkey);
                   1060:                                        const BIGNUM *pub_key = NULL;
                   1061:
                   1062:                                        DSA_get0_key(dsa, &pub_key, NULL);
                   1063:
                   1064:                                        BN_print(STDout, pub_key);
                   1065:                                } else
1.20      inoguchi 1066:                                        BIO_printf(STDout,
                   1067:                                            "Wrong Algorithm type");
1.1       jsing    1068:                                BIO_printf(STDout, "\n");
1.19      inoguchi 1069:                        } else if (x509_config.pubkey == i) {
1.1       jsing    1070:                                EVP_PKEY *pkey;
                   1071:
1.28      tb       1072:                                pkey = X509_get0_pubkey(x);
1.1       jsing    1073:                                if (pkey == NULL) {
1.20      inoguchi 1074:                                        BIO_printf(bio_err,
                   1075:                                            "Error getting public key\n");
1.1       jsing    1076:                                        ERR_print_errors(bio_err);
                   1077:                                        goto end;
                   1078:                                }
                   1079:                                PEM_write_bio_PUBKEY(STDout, pkey);
1.19      inoguchi 1080:                        } else if (x509_config.C == i) {
1.1       jsing    1081:                                unsigned char *d;
                   1082:                                char *m;
                   1083:                                int y, z;
                   1084:
1.23      inoguchi 1085:                                m = X509_NAME_oneline(X509_get_subject_name(x),
1.1       jsing    1086:                                    buf, sizeof buf);
1.23      inoguchi 1087:                                if (m == NULL)
                   1088:                                        goto end;
1.1       jsing    1089:                                BIO_printf(STDout, "/* subject:%s */\n", buf);
1.20      inoguchi 1090:                                m = X509_NAME_oneline(X509_get_issuer_name(x),
                   1091:                                    buf, sizeof buf);
1.23      inoguchi 1092:                                if (m == NULL)
                   1093:                                        goto end;
1.1       jsing    1094:                                BIO_printf(STDout, "/* issuer :%s */\n", buf);
                   1095:
                   1096:                                z = i2d_X509(x, NULL);
1.23      inoguchi 1097:                                if (z < 0)
                   1098:                                        goto end;
                   1099:
1.1       jsing    1100:                                m = malloc(z);
1.8       bcook    1101:                                if (m == NULL) {
                   1102:                                        BIO_printf(bio_err, "out of mem\n");
                   1103:                                        goto end;
                   1104:                                }
1.1       jsing    1105:
                   1106:                                d = (unsigned char *) m;
                   1107:                                z = i2d_X509_NAME(X509_get_subject_name(x), &d);
1.23      inoguchi 1108:                                if (z < 0) {
                   1109:                                        free(m);
                   1110:                                        goto end;
                   1111:                                }
1.20      inoguchi 1112:                                BIO_printf(STDout,
                   1113:                                    "unsigned char XXX_subject_name[%d]={\n", z);
1.1       jsing    1114:                                d = (unsigned char *) m;
                   1115:                                for (y = 0; y < z; y++) {
                   1116:                                        BIO_printf(STDout, "0x%02X,", d[y]);
                   1117:                                        if ((y & 0x0f) == 0x0f)
                   1118:                                                BIO_printf(STDout, "\n");
                   1119:                                }
                   1120:                                if (y % 16 != 0)
                   1121:                                        BIO_printf(STDout, "\n");
                   1122:                                BIO_printf(STDout, "};\n");
                   1123:
                   1124:                                z = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d);
1.23      inoguchi 1125:                                if (z < 0) {
                   1126:                                        free(m);
                   1127:                                        goto end;
                   1128:                                }
1.20      inoguchi 1129:                                BIO_printf(STDout,
                   1130:                                    "unsigned char XXX_public_key[%d]={\n", z);
1.1       jsing    1131:                                d = (unsigned char *) m;
                   1132:                                for (y = 0; y < z; y++) {
                   1133:                                        BIO_printf(STDout, "0x%02X,", d[y]);
                   1134:                                        if ((y & 0x0f) == 0x0f)
                   1135:                                                BIO_printf(STDout, "\n");
                   1136:                                }
                   1137:                                if (y % 16 != 0)
                   1138:                                        BIO_printf(STDout, "\n");
                   1139:                                BIO_printf(STDout, "};\n");
                   1140:
                   1141:                                z = i2d_X509(x, &d);
1.23      inoguchi 1142:                                if (z < 0) {
                   1143:                                        free(m);
                   1144:                                        goto end;
                   1145:                                }
1.20      inoguchi 1146:                                BIO_printf(STDout,
                   1147:                                    "unsigned char XXX_certificate[%d]={\n", z);
1.1       jsing    1148:                                d = (unsigned char *) m;
                   1149:                                for (y = 0; y < z; y++) {
                   1150:                                        BIO_printf(STDout, "0x%02X,", d[y]);
                   1151:                                        if ((y & 0x0f) == 0x0f)
                   1152:                                                BIO_printf(STDout, "\n");
                   1153:                                }
                   1154:                                if (y % 16 != 0)
                   1155:                                        BIO_printf(STDout, "\n");
                   1156:                                BIO_printf(STDout, "};\n");
                   1157:
                   1158:                                free(m);
1.19      inoguchi 1159:                        } else if (x509_config.text == i) {
1.23      inoguchi 1160:                                if(!X509_print_ex(STDout, x, x509_config.nmflag,
                   1161:                                    x509_config.certflag))
                   1162:                                        goto end;
1.19      inoguchi 1163:                        } else if (x509_config.startdate == i) {
1.18      beck     1164:                                ASN1_TIME *nB = X509_get_notBefore(x);
1.1       jsing    1165:                                BIO_puts(STDout, "notBefore=");
1.20      inoguchi 1166:                                if (ASN1_time_parse(nB->data, nB->length, NULL,
                   1167:                                    0) == -1)
                   1168:                                        BIO_puts(STDout,
                   1169:                                            "INVALID RFC5280 TIME");
1.18      beck     1170:                                else
                   1171:                                        ASN1_TIME_print(STDout, nB);
1.1       jsing    1172:                                BIO_puts(STDout, "\n");
1.19      inoguchi 1173:                        } else if (x509_config.enddate == i) {
1.18      beck     1174:                                ASN1_TIME *nA = X509_get_notAfter(x);
1.1       jsing    1175:                                BIO_puts(STDout, "notAfter=");
1.20      inoguchi 1176:                                if (ASN1_time_parse(nA->data, nA->length, NULL,
                   1177:                                    0) == -1)
                   1178:                                        BIO_puts(STDout,
                   1179:                                            "INVALID RFC5280 TIME");
1.18      beck     1180:                                else
                   1181:                                        ASN1_TIME_print(STDout, nA);
1.1       jsing    1182:                                BIO_puts(STDout, "\n");
1.19      inoguchi 1183:                        } else if (x509_config.fingerprint == i) {
1.1       jsing    1184:                                int j;
                   1185:                                unsigned int n;
                   1186:                                unsigned char md[EVP_MAX_MD_SIZE];
1.19      inoguchi 1187:                                const EVP_MD *fdig = x509_config.digest;
1.1       jsing    1188:
1.21      inoguchi 1189:                                if (fdig == NULL)
1.17      jsg      1190:                                        fdig = EVP_sha256();
1.1       jsing    1191:
                   1192:                                if (!X509_digest(x, fdig, md, &n)) {
                   1193:                                        BIO_printf(bio_err, "out of memory\n");
                   1194:                                        goto end;
                   1195:                                }
                   1196:                                BIO_printf(STDout, "%s Fingerprint=",
                   1197:                                    OBJ_nid2sn(EVP_MD_type(fdig)));
                   1198:                                for (j = 0; j < (int) n; j++) {
                   1199:                                        BIO_printf(STDout, "%02X%c", md[j],
                   1200:                                            (j + 1 == (int)n) ? '\n' : ':');
                   1201:                                }
1.20      inoguchi 1202:
1.1       jsing    1203:                        /* should be in the library */
1.20      inoguchi 1204:                        } else if ((x509_config.sign_flag == i) &&
                   1205:                            (x509_config.x509req == 0)) {
1.1       jsing    1206:                                BIO_printf(bio_err, "Getting Private key\n");
                   1207:                                if (Upkey == NULL) {
                   1208:                                        Upkey = load_key(bio_err,
1.20      inoguchi 1209:                                            x509_config.keyfile,
                   1210:                                            x509_config.keyformat, 0, passin,
                   1211:                                            "Private key");
1.1       jsing    1212:                                        if (Upkey == NULL)
                   1213:                                                goto end;
                   1214:                                }
1.20      inoguchi 1215:                                if (!sign(x, Upkey, x509_config.days,
                   1216:                                    x509_config.clrext, x509_config.digest,
1.19      inoguchi 1217:                                    extconf, x509_config.extsect))
1.1       jsing    1218:                                        goto end;
1.19      inoguchi 1219:                        } else if (x509_config.CA_flag == i) {
1.1       jsing    1220:                                BIO_printf(bio_err, "Getting CA Private Key\n");
1.19      inoguchi 1221:                                if (x509_config.CAkeyfile != NULL) {
1.1       jsing    1222:                                        CApkey = load_key(bio_err,
1.20      inoguchi 1223:                                            x509_config.CAkeyfile,
                   1224:                                            x509_config.CAkeyformat, 0, passin,
                   1225:                                            "CA Private Key");
1.1       jsing    1226:                                        if (CApkey == NULL)
                   1227:                                                goto end;
                   1228:                                }
1.20      inoguchi 1229:                                if (!x509_certify(ctx, x509_config.CAfile,
                   1230:                                    x509_config.digest, x, xca, CApkey,
                   1231:                                    x509_config.sigopts, x509_config.CAserial,
                   1232:                                    x509_config.CA_createserial,
                   1233:                                    x509_config.days, x509_config.clrext,
                   1234:                                    extconf, x509_config.extsect,
                   1235:                                    x509_config.sno))
1.1       jsing    1236:                                        goto end;
1.19      inoguchi 1237:                        } else if (x509_config.x509req == i) {
1.1       jsing    1238:                                EVP_PKEY *pk;
                   1239:
1.20      inoguchi 1240:                                BIO_printf(bio_err,
                   1241:                                    "Getting request Private Key\n");
1.19      inoguchi 1242:                                if (x509_config.keyfile == NULL) {
1.20      inoguchi 1243:                                        BIO_printf(bio_err,
                   1244:                                            "no request key file specified\n");
1.1       jsing    1245:                                        goto end;
                   1246:                                } else {
                   1247:                                        pk = load_key(bio_err,
1.20      inoguchi 1248:                                            x509_config.keyfile,
                   1249:                                            x509_config.keyformat, 0, passin,
                   1250:                                            "request key");
1.1       jsing    1251:                                        if (pk == NULL)
                   1252:                                                goto end;
                   1253:                                }
                   1254:
1.20      inoguchi 1255:                                BIO_printf(bio_err,
                   1256:                                    "Generating certificate request\n");
1.1       jsing    1257:
1.19      inoguchi 1258:                                rq = X509_to_X509_REQ(x, pk, x509_config.digest);
1.1       jsing    1259:                                EVP_PKEY_free(pk);
                   1260:                                if (rq == NULL) {
                   1261:                                        ERR_print_errors(bio_err);
                   1262:                                        goto end;
                   1263:                                }
1.19      inoguchi 1264:                                if (!x509_config.noout) {
1.23      inoguchi 1265:                                        if (!X509_REQ_print(out, rq))
                   1266:                                                goto end;
                   1267:                                        if (!PEM_write_bio_X509_REQ(out, rq))
                   1268:                                                goto end;
1.1       jsing    1269:                                }
1.19      inoguchi 1270:                                x509_config.noout = 1;
                   1271:                        } else if (x509_config.ocspid == i) {
1.23      inoguchi 1272:                                if (!X509_ocspid_print(out, x))
                   1273:                                        goto end;
1.1       jsing    1274:                        }
                   1275:                }
                   1276:        }
1.19      inoguchi 1277:        if (x509_config.checkend) {
                   1278:                time_t tcheck = time(NULL) + x509_config.checkoffset;
1.18      beck     1279:                int timecheck = X509_cmp_time(X509_get_notAfter(x), &tcheck);
                   1280:                if (timecheck == 0) {
                   1281:                        BIO_printf(out, "Certificate expiry time is invalid\n");
                   1282:                        ret = 1;
                   1283:                } else if (timecheck < 0) {
1.1       jsing    1284:                        BIO_printf(out, "Certificate will expire\n");
                   1285:                        ret = 1;
                   1286:                } else {
                   1287:                        BIO_printf(out, "Certificate will not expire\n");
                   1288:                        ret = 0;
                   1289:                }
                   1290:                goto end;
                   1291:        }
1.19      inoguchi 1292:        if (x509_config.noout) {
1.1       jsing    1293:                ret = 0;
                   1294:                goto end;
                   1295:        }
1.19      inoguchi 1296:        if (x509_config.outformat == FORMAT_ASN1)
1.1       jsing    1297:                i = i2d_X509_bio(out, x);
1.19      inoguchi 1298:        else if (x509_config.outformat == FORMAT_PEM) {
                   1299:                if (x509_config.trustout)
1.1       jsing    1300:                        i = PEM_write_bio_X509_AUX(out, x);
                   1301:                else
                   1302:                        i = PEM_write_bio_X509(out, x);
                   1303:        } else {
1.20      inoguchi 1304:                BIO_printf(bio_err,
                   1305:                    "bad output format specified for outfile\n");
1.1       jsing    1306:                goto end;
                   1307:        }
                   1308:        if (!i) {
                   1309:                BIO_printf(bio_err, "unable to write certificate\n");
                   1310:                ERR_print_errors(bio_err);
                   1311:                goto end;
                   1312:        }
                   1313:        ret = 0;
                   1314:
1.16      jsing    1315:  end:
1.1       jsing    1316:        OBJ_cleanup();
                   1317:        NCONF_free(extconf);
                   1318:        BIO_free_all(out);
                   1319:        BIO_free_all(STDout);
                   1320:        X509_STORE_free(ctx);
                   1321:        X509_REQ_free(req);
                   1322:        X509_free(x);
                   1323:        X509_free(xca);
                   1324:        EVP_PKEY_free(Upkey);
                   1325:        EVP_PKEY_free(CApkey);
1.19      inoguchi 1326:        sk_OPENSSL_STRING_free(x509_config.sigopts);
1.1       jsing    1327:        X509_REQ_free(rq);
1.19      inoguchi 1328:        ASN1_INTEGER_free(x509_config.sno);
                   1329:        sk_ASN1_OBJECT_pop_free(x509_config.trust, ASN1_OBJECT_free);
                   1330:        sk_ASN1_OBJECT_pop_free(x509_config.reject, ASN1_OBJECT_free);
1.1       jsing    1331:        free(passin);
                   1332:
                   1333:        return (ret);
                   1334: }
                   1335:
                   1336: static ASN1_INTEGER *
                   1337: x509_load_serial(char *CAfile, char *serialfile, int create)
                   1338: {
                   1339:        char *buf = NULL, *p;
                   1340:        ASN1_INTEGER *bs = NULL;
                   1341:        BIGNUM *serial = NULL;
                   1342:        size_t len;
                   1343:
                   1344:        len = ((serialfile == NULL) ? (strlen(CAfile) + strlen(POSTFIX) + 1) :
                   1345:            (strlen(serialfile))) + 1;
                   1346:        buf = malloc(len);
                   1347:        if (buf == NULL) {
                   1348:                BIO_printf(bio_err, "out of mem\n");
                   1349:                goto end;
                   1350:        }
                   1351:        if (serialfile == NULL) {
                   1352:                strlcpy(buf, CAfile, len);
                   1353:                for (p = buf; *p; p++)
                   1354:                        if (*p == '.') {
                   1355:                                *p = '\0';
                   1356:                                break;
                   1357:                        }
                   1358:                strlcat(buf, POSTFIX, len);
                   1359:        } else
                   1360:                strlcpy(buf, serialfile, len);
                   1361:
                   1362:        serial = load_serial(buf, create, NULL);
                   1363:        if (serial == NULL)
                   1364:                goto end;
                   1365:
                   1366:        if (!BN_add_word(serial, 1)) {
                   1367:                BIO_printf(bio_err, "add_word failure\n");
                   1368:                goto end;
                   1369:        }
                   1370:        if (!save_serial(buf, NULL, serial, &bs))
                   1371:                goto end;
                   1372:
1.16      jsing    1373:  end:
1.1       jsing    1374:        free(buf);
                   1375:        BN_free(serial);
                   1376:
                   1377:        return bs;
                   1378: }
                   1379:
                   1380: static int
                   1381: x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, X509 *x,
                   1382:     X509 *xca, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *sigopts,
                   1383:     char *serialfile, int create, int days, int clrext, CONF *conf,
                   1384:     char *section, ASN1_INTEGER *sno)
                   1385: {
                   1386:        int ret = 0;
                   1387:        ASN1_INTEGER *bs = NULL;
1.25      tb       1388:        X509_STORE_CTX *xsc = NULL;
1.1       jsing    1389:        EVP_PKEY *upkey;
                   1390:
1.29      tb       1391:        upkey = X509_get0_pubkey(xca);
1.23      inoguchi 1392:        if (upkey == NULL)
                   1393:                goto end;
1.1       jsing    1394:        EVP_PKEY_copy_parameters(upkey, pkey);
                   1395:
1.25      tb       1396:        if ((xsc = X509_STORE_CTX_new()) == NULL)
                   1397:                goto end;
                   1398:        if (!X509_STORE_CTX_init(xsc, ctx, x, NULL)) {
1.1       jsing    1399:                BIO_printf(bio_err, "Error initialising X509 store\n");
                   1400:                goto end;
                   1401:        }
1.21      inoguchi 1402:        if (sno != NULL)
1.1       jsing    1403:                bs = sno;
1.21      inoguchi 1404:        else if ((bs = x509_load_serial(CAfile, serialfile, create)) == NULL)
1.1       jsing    1405:                goto end;
                   1406:
                   1407: /*     if (!X509_STORE_add_cert(ctx,x)) goto end;*/
                   1408:
                   1409:        /*
                   1410:         * NOTE: this certificate can/should be self signed, unless it was a
                   1411:         * certificate request in which case it is not.
                   1412:         */
1.25      tb       1413:        X509_STORE_CTX_set_cert(xsc, x);
                   1414:        X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
                   1415:        if (!x509_config.reqfile && X509_verify_cert(xsc) <= 0)
1.1       jsing    1416:                goto end;
                   1417:
                   1418:        if (!X509_check_private_key(xca, pkey)) {
1.20      inoguchi 1419:                BIO_printf(bio_err,
                   1420:                    "CA certificate and CA private key do not match\n");
1.1       jsing    1421:                goto end;
                   1422:        }
                   1423:        if (!X509_set_issuer_name(x, X509_get_subject_name(xca)))
                   1424:                goto end;
                   1425:        if (!X509_set_serialNumber(x, bs))
                   1426:                goto end;
                   1427:
                   1428:        if (X509_gmtime_adj(X509_get_notBefore(x), 0L) == NULL)
                   1429:                goto end;
                   1430:
                   1431:        /* hardwired expired */
                   1432:        if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL)
                   1433:                goto end;
                   1434:
                   1435:        if (clrext) {
1.23      inoguchi 1436:                while (X509_get_ext_count(x) > 0) {
                   1437:                        if (X509_delete_ext(x, 0) == NULL)
                   1438:                                goto end;
                   1439:                }
1.1       jsing    1440:        }
1.21      inoguchi 1441:        if (conf != NULL) {
1.1       jsing    1442:                X509V3_CTX ctx2;
1.23      inoguchi 1443:                if (!X509_set_version(x, 2))    /* version 3 certificate */
                   1444:                        goto end;
1.1       jsing    1445:                X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
                   1446:                X509V3_set_nconf(&ctx2, conf);
                   1447:                if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x))
                   1448:                        goto end;
                   1449:        }
                   1450:        if (!do_X509_sign(bio_err, x, pkey, digest, sigopts))
                   1451:                goto end;
1.23      inoguchi 1452:
1.1       jsing    1453:        ret = 1;
1.16      jsing    1454:  end:
1.25      tb       1455:        X509_STORE_CTX_free(xsc);
1.1       jsing    1456:        if (!ret)
                   1457:                ERR_print_errors(bio_err);
1.21      inoguchi 1458:        if (sno == NULL)
1.1       jsing    1459:                ASN1_INTEGER_free(bs);
                   1460:        return ret;
                   1461: }
                   1462:
                   1463: static int
                   1464: callb(int ok, X509_STORE_CTX *ctx)
                   1465: {
                   1466:        int err;
                   1467:        X509 *err_cert;
                   1468:
                   1469:        /*
                   1470:         * it is ok to use a self signed certificate This case will catch
                   1471:         * both the initial ok == 0 and the final ok == 1 calls to this
                   1472:         * function
                   1473:         */
                   1474:        err = X509_STORE_CTX_get_error(ctx);
                   1475:        if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
                   1476:                return 1;
                   1477:
                   1478:        /*
                   1479:         * BAD we should have gotten an error.  Normally if everything worked
                   1480:         * X509_STORE_CTX_get_error(ctx) will still be set to
                   1481:         * DEPTH_ZERO_SELF_....
                   1482:         */
                   1483:        if (ok) {
1.20      inoguchi 1484:                BIO_printf(bio_err,
                   1485:                    "error with certificate to be certified - should be self signed\n");
1.1       jsing    1486:                return 0;
                   1487:        } else {
                   1488:                err_cert = X509_STORE_CTX_get_current_cert(ctx);
                   1489:                print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0);
1.20      inoguchi 1490:                BIO_printf(bio_err,
                   1491:                    "error with certificate - error %d at depth %d\n%s\n",
1.1       jsing    1492:                    err, X509_STORE_CTX_get_error_depth(ctx),
                   1493:                    X509_verify_cert_error_string(err));
                   1494:                return 1;
                   1495:        }
                   1496: }
                   1497:
                   1498: /* self sign */
                   1499: static int
                   1500: sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest,
                   1501:     CONF *conf, char *section)
                   1502: {
                   1503:        EVP_PKEY *pktmp;
                   1504:
1.29      tb       1505:        pktmp = X509_get0_pubkey(x);
1.23      inoguchi 1506:        if (pktmp == NULL)
                   1507:                goto err;
1.1       jsing    1508:        EVP_PKEY_copy_parameters(pktmp, pkey);
                   1509:        EVP_PKEY_save_parameters(pktmp, 1);
                   1510:
                   1511:        if (!X509_set_issuer_name(x, X509_get_subject_name(x)))
                   1512:                goto err;
                   1513:        if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL)
                   1514:                goto err;
                   1515:
                   1516:        /* Lets just make it 12:00am GMT, Jan 1 1970 */
                   1517:        /* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */
                   1518:        /* 28 days to be certified */
                   1519:
                   1520:        if (X509_gmtime_adj(X509_get_notAfter(x),
                   1521:            (long) 60 * 60 * 24 * days) == NULL)
                   1522:                goto err;
                   1523:
                   1524:        if (!X509_set_pubkey(x, pkey))
                   1525:                goto err;
                   1526:        if (clrext) {
1.23      inoguchi 1527:                while (X509_get_ext_count(x) > 0) {
                   1528:                        if (X509_delete_ext(x, 0) == NULL)
                   1529:                                goto err;
                   1530:                }
1.1       jsing    1531:        }
1.21      inoguchi 1532:        if (conf != NULL) {
1.1       jsing    1533:                X509V3_CTX ctx;
1.23      inoguchi 1534:                if (!X509_set_version(x, 2))    /* version 3 certificate */
                   1535:                        goto err;
1.1       jsing    1536:                X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
                   1537:                X509V3_set_nconf(&ctx, conf);
                   1538:                if (!X509V3_EXT_add_nconf(conf, &ctx, section, x))
                   1539:                        goto err;
                   1540:        }
                   1541:        if (!X509_sign(x, pkey, digest))
                   1542:                goto err;
1.20      inoguchi 1543:
1.1       jsing    1544:        return 1;
                   1545:
1.16      jsing    1546:  err:
1.1       jsing    1547:        ERR_print_errors(bio_err);
                   1548:        return 0;
                   1549: }
                   1550:
                   1551: static int
                   1552: purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
                   1553: {
                   1554:        int id, i, idret;
                   1555:        char *pname;
                   1556:
                   1557:        id = X509_PURPOSE_get_id(pt);
                   1558:        pname = X509_PURPOSE_get0_name(pt);
                   1559:        for (i = 0; i < 2; i++) {
                   1560:                idret = X509_check_purpose(cert, id, i);
                   1561:                BIO_printf(bio, "%s%s : ", pname, i ? " CA" : "");
                   1562:                if (idret == 1)
                   1563:                        BIO_printf(bio, "Yes\n");
                   1564:                else if (idret == 0)
                   1565:                        BIO_printf(bio, "No\n");
                   1566:                else
                   1567:                        BIO_printf(bio, "Yes (WARNING code=%d)\n", idret);
                   1568:        }
                   1569:        return 1;
                   1570: }