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

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