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

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