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

Annotation of src/usr.bin/openssl/req.c, Revision 1.20

1.20    ! tb          1: /* $OpenBSD: req.c,v 1.19 2020/08/09 16:38:24 jsing 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: /* Until the key-gen callbacks are modified to use newer prototypes, we allow
                     60:  * deprecated functions for openssl-internal code */
                     61: #ifdef OPENSSL_NO_DEPRECATED
                     62: #undef OPENSSL_NO_DEPRECATED
                     63: #endif
                     64:
1.17      inoguchi   65: #include <ctype.h>
                     66: #include <limits.h>
1.1       jsing      67: #include <stdio.h>
                     68: #include <stdlib.h>
                     69: #include <string.h>
                     70: #include <time.h>
                     71:
                     72: #include "apps.h"
                     73:
                     74: #include <openssl/asn1.h>
                     75: #include <openssl/bio.h>
                     76: #include <openssl/bn.h>
                     77: #include <openssl/conf.h>
                     78: #include <openssl/err.h>
                     79: #include <openssl/evp.h>
                     80: #include <openssl/objects.h>
                     81: #include <openssl/pem.h>
                     82: #include <openssl/x509.h>
                     83: #include <openssl/x509v3.h>
                     84:
                     85: #include <openssl/dsa.h>
                     86:
                     87: #include <openssl/rsa.h>
                     88:
                     89: #define SECTION                "req"
                     90:
                     91: #define BITS           "default_bits"
                     92: #define KEYFILE                "default_keyfile"
                     93: #define PROMPT         "prompt"
                     94: #define DISTINGUISHED_NAME     "distinguished_name"
                     95: #define ATTRIBUTES     "attributes"
                     96: #define V3_EXTENSIONS  "x509_extensions"
                     97: #define REQ_EXTENSIONS "req_extensions"
                     98: #define STRING_MASK    "string_mask"
                     99: #define UTF8_IN                "utf8"
                    100:
1.3       sthen     101: #define DEFAULT_KEY_LENGTH     2048
1.1       jsing     102: #define MIN_KEY_LENGTH         384
                    103:
1.13      miod      104: static int make_REQ(X509_REQ * req, EVP_PKEY * pkey, char *dn, int multirdn,
1.1       jsing     105:     int attribs, unsigned long chtype);
                    106: static int build_subject(X509_REQ * req, char *subj, unsigned long chtype,
                    107:     int multirdn);
                    108: static int prompt_info(X509_REQ * req,
                    109:     STACK_OF(CONF_VALUE) * dn_sk, char *dn_sect,
                    110:     STACK_OF(CONF_VALUE) * attr_sk, char *attr_sect, int attribs,
                    111:     unsigned long chtype);
                    112: static int auto_info(X509_REQ * req, STACK_OF(CONF_VALUE) * sk,
                    113:     STACK_OF(CONF_VALUE) * attr, int attribs,
                    114:     unsigned long chtype);
                    115: static int add_attribute_object(X509_REQ * req, char *text, const char *def,
                    116:     char *value, int nid, int n_min,
                    117:     int n_max, unsigned long chtype);
                    118: static int add_DN_object(X509_NAME * n, char *text, const char *def, char *value,
                    119:     int nid, int n_min, int n_max, unsigned long chtype, int mval);
                    120: static int genpkey_cb(EVP_PKEY_CTX * ctx);
                    121: static int req_check_len(int len, int n_min, int n_max);
                    122: static int check_end(const char *str, const char *end);
                    123: static EVP_PKEY_CTX *set_keygen_ctx(BIO * err, const char *gstr, int *pkey_type,
1.7       bcook     124:     long *pkeylen, char **palgnam);
1.17      inoguchi  125: static unsigned long ext_name_hash(const OPENSSL_STRING *a);
                    126: static int ext_name_cmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b);
                    127: static void exts_cleanup(OPENSSL_STRING *x);
                    128: static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv);
1.1       jsing     129: static CONF *req_conf = NULL;
1.17      inoguchi  130: static CONF *addext_conf = NULL;
1.19      jsing     131:
                    132: struct {
                    133:        LHASH_OF(OPENSSL_STRING) *addexts;
                    134:        BIO *addext_bio;
                    135:        int batch;
                    136:        unsigned long chtype;
                    137:        int days;
                    138:        const EVP_MD *digest;
                    139:        char *extensions;
                    140:        char *infile;
                    141:        int informat;
                    142:        char *keyalg;
                    143:        char *keyfile;
                    144:        int keyform;
                    145:        char *keyout;
                    146:        int kludge;
                    147:        int modulus;
                    148:        int multirdn;
                    149:        int newhdr;
                    150:        long newkey;
                    151:        int newreq;
                    152:        unsigned long nmflag;
                    153:        int nodes;
                    154:        int noout;
                    155:        char *outfile;
                    156:        int outformat;
                    157:        char *passargin;
                    158:        char *passargout;
                    159:        STACK_OF(OPENSSL_STRING) *pkeyopts;
                    160:        int pubkey;
                    161:        char *req_exts;
                    162:        unsigned long reqflag;
                    163:        ASN1_INTEGER *serial;
                    164:        STACK_OF(OPENSSL_STRING) *sigopts;
                    165:        char *subj;
                    166:        int subject;
                    167:        char *template;
                    168:        int text;
                    169:        int verbose;
                    170:        int verify;
                    171:        int x509;
                    172: } req_config;
                    173:
                    174: static int
                    175: req_opt_addext(char *arg)
                    176: {
                    177:        int i;
                    178:
                    179:        if (req_config.addexts == NULL) {
                    180:                req_config.addexts = (LHASH_OF(OPENSSL_STRING) *)lh_new(
                    181:                    (LHASH_HASH_FN_TYPE)ext_name_hash,
                    182:                    (LHASH_COMP_FN_TYPE)ext_name_cmp);
                    183:                req_config.addext_bio = BIO_new(BIO_s_mem());
                    184:                if (req_config.addexts == NULL ||
                    185:                    req_config.addext_bio == NULL)
                    186:                        return (1);
                    187:        }
                    188:        i = duplicated(req_config.addexts, arg);
                    189:        if (i == 1)
                    190:                return (1);
                    191:        if (i < 0 || BIO_printf(req_config.addext_bio, "%s\n", arg) < 0)
                    192:                return (1);
                    193:
                    194:        return (0);
                    195: }
                    196:
                    197: static int
                    198: req_opt_days(char *arg)
                    199: {
                    200:        const char *errstr;
                    201:
                    202:        req_config.days = strtonum(arg, 1, INT_MAX, &errstr);
                    203:        if (errstr != NULL) {
                    204:                BIO_printf(bio_err, "bad -days %s, using 0: %s\n",
                    205:                    arg, errstr);
                    206:                req_config.days = 30;
                    207:        }
                    208:        return (0);
                    209: }
                    210:
                    211: static int
                    212: req_opt_digest(int argc, char **argv, int *argsused)
                    213: {
                    214:        char *name = argv[0];
                    215:
                    216:        if (*name++ != '-')
                    217:                return (1);
                    218:
                    219:        if ((req_config.digest = EVP_get_digestbyname(name)) == NULL)
                    220:                return (1);
                    221:
                    222:        *argsused = 1;
                    223:        return (0);
                    224: }
                    225:
                    226: static int
                    227: req_opt_newkey(char *arg)
                    228: {
                    229:        req_config.keyalg = arg;
                    230:        req_config.newreq = 1;
                    231:        return (0);
                    232: }
                    233:
                    234: static int
                    235: req_opt_nameopt(char *arg)
                    236: {
                    237:        if (!set_name_ex(&req_config.nmflag, arg))
                    238:                return (1);
                    239:        return (0);
                    240: }
                    241:
                    242: static int
                    243: req_opt_pkeyopt(char *arg)
                    244: {
                    245:        if (req_config.pkeyopts == NULL)
                    246:                req_config.pkeyopts = sk_OPENSSL_STRING_new_null();
                    247:        if (req_config.pkeyopts == NULL)
                    248:                return (1);
                    249:        if (!sk_OPENSSL_STRING_push(req_config.pkeyopts, arg))
                    250:                return (1);
                    251:        return (0);
                    252: }
                    253:
                    254: static int
                    255: req_opt_reqopt(char *arg)
                    256: {
                    257:        if (!set_cert_ex(&req_config.reqflag, arg))
                    258:                return (1);
                    259:        return (0);
                    260: }
                    261:
                    262: static int
                    263: req_opt_set_serial(char *arg)
                    264: {
                    265:        req_config.serial = s2i_ASN1_INTEGER(NULL, arg);
                    266:        if (req_config.serial == NULL)
                    267:                return (1);
                    268:        return (0);
                    269: }
                    270:
                    271: static int
                    272: req_opt_sigopt(char *arg)
                    273: {
                    274:        if (req_config.sigopts == NULL)
                    275:                req_config.sigopts = sk_OPENSSL_STRING_new_null();
                    276:        if (req_config.sigopts == NULL)
                    277:                return (1);
                    278:        if (!sk_OPENSSL_STRING_push(req_config.sigopts, arg))
                    279:                return (1);
                    280:        return (0);
                    281: }
                    282:
                    283: static int
                    284: req_opt_utf8(void)
                    285: {
                    286:        req_config.chtype = MBSTRING_UTF8;
                    287:        return (0);
                    288: }
                    289:
                    290: static const struct option req_options[] = {
                    291:        {
                    292:                .name = "addext",
                    293:                .argname = "key=value",
                    294:                .desc = "Additional certificate extension (may be repeated)",
                    295:                .type = OPTION_ARG_FUNC,
                    296:                .opt.argfunc = req_opt_addext,
                    297:        },
                    298:        {
                    299:                .name = "asn1-kludge",
                    300:                .type = OPTION_VALUE,
                    301:                .opt.value = &req_config.kludge,
                    302:                .value = 1,
                    303:        },
                    304:        {
                    305:                .name = "batch",
                    306:                .desc = "Operate in batch mode",
                    307:                .type = OPTION_FLAG,
                    308:                .opt.flag = &req_config.batch,
                    309:        },
                    310:        {
                    311:                .name = "config",
                    312:                .argname = "file",
                    313:                .desc = "Configuration file to use as request template",
                    314:                .type = OPTION_ARG,
                    315:                .opt.arg = &req_config.template,
                    316:        },
                    317:        {
                    318:                .name = "days",
                    319:                .argname = "number",
                    320:                .desc = "Number of days generated certificate is valid for",
                    321:                .type = OPTION_ARG_FUNC,
                    322:                .opt.argfunc = req_opt_days,
                    323:        },
                    324:        {
                    325:                .name = "extensions",
                    326:                .argname = "section",
                    327:                .desc = "Config section to use for certificate extensions",
                    328:                .type = OPTION_ARG,
                    329:                .opt.arg = &req_config.extensions,
                    330:        },
                    331:        {
                    332:                .name = "in",
                    333:                .argname = "file",
                    334:                .desc = "Input file (default stdin)",
                    335:                .type = OPTION_ARG,
                    336:                .opt.arg = &req_config.infile,
                    337:        },
                    338:        {
                    339:                .name = "inform",
                    340:                .argname = "format",
                    341:                .desc = "Input format (DER or PEM (default))",
                    342:                .type = OPTION_ARG_FORMAT,
                    343:                .opt.value = &req_config.informat,
                    344:        },
                    345:        {
                    346:                .name = "key",
                    347:                .argname = "file",
                    348:                .desc = "Private key file",
                    349:                .type = OPTION_ARG,
                    350:                .opt.arg = &req_config.keyfile,
                    351:        },
                    352:        {
                    353:                .name = "keyform",
                    354:                .argname = "format",
                    355:                .desc = "Private key format (DER or PEM (default))",
                    356:                .type = OPTION_ARG_FORMAT,
                    357:                .opt.value = &req_config.keyform,
                    358:        },
                    359:        {
                    360:                .name = "keyout",
                    361:                .argname = "file",
                    362:                .desc = "Private key output file",
                    363:                .type = OPTION_ARG,
                    364:                .opt.arg = &req_config.keyout,
                    365:        },
                    366:        {
                    367:                .name = "modulus",
                    368:                .desc = "Print RSA modulus",
                    369:                .type = OPTION_FLAG,
                    370:                .opt.flag = &req_config.modulus,
                    371:        },
                    372:        {
                    373:                .name = "multivalue-rdn",
                    374:                .desc = "Enable support for multivalued RDNs",
                    375:                .type = OPTION_FLAG,
                    376:                .opt.flag = &req_config.multirdn,
                    377:        },
                    378:        {
                    379:                .name = "nameopt",
                    380:                .argname = "arg",
                    381:                .desc = "Certificate name options",
                    382:                .type = OPTION_ARG_FUNC,
                    383:                .opt.argfunc = req_opt_nameopt,
                    384:        },
                    385:        {
                    386:                .name = "new",
                    387:                .desc = "New request",
                    388:                .type = OPTION_FLAG,
                    389:                .opt.flag = &req_config.newreq,
                    390:        },
                    391:        {
                    392:                .name = "newhdr",
                    393:                .desc = "Include 'NEW' in header lines",
                    394:                .type = OPTION_FLAG,
                    395:                .opt.flag = &req_config.newhdr,
                    396:        },
                    397:        {
                    398:                .name = "newkey",
                    399:                .argname = "param",
                    400:                .desc = "Generate a new key using given parameters",
                    401:                .type = OPTION_ARG_FUNC,
                    402:                .opt.argfunc = req_opt_newkey,
                    403:        },
                    404:        {
                    405:                .name = "no-asn1-kludge",
                    406:                .type = OPTION_VALUE,
                    407:                .opt.value = &req_config.kludge,
                    408:                .value = 0,
                    409:        },
                    410:        {
                    411:                .name = "nodes",
                    412:                .desc = "Do not encrypt output private key",
                    413:                .type = OPTION_FLAG,
                    414:                .opt.flag = &req_config.nodes,
                    415:        },
                    416:        {
                    417:                .name = "noout",
                    418:                .desc = "Do not output request",
                    419:                .type = OPTION_FLAG,
                    420:                .opt.flag = &req_config.noout,
                    421:        },
                    422:        {
                    423:                .name = "out",
                    424:                .argname = "file",
                    425:                .desc = "Output file (default stdout)",
                    426:                .type = OPTION_ARG,
                    427:                .opt.arg = &req_config.outfile,
                    428:        },
                    429:        {
                    430:                .name = "outform",
                    431:                .argname = "format",
                    432:                .desc = "Output format (DER or PEM (default))",
                    433:                .type = OPTION_ARG_FORMAT,
                    434:                .opt.value = &req_config.outformat,
                    435:        },
                    436:        {
                    437:                .name = "passin",
                    438:                .argname = "source",
                    439:                .desc = "Private key input password source",
                    440:                .type = OPTION_ARG,
                    441:                .opt.arg = &req_config.passargin,
                    442:        },
                    443:        {
                    444:                .name = "passout",
                    445:                .argname = "source",
                    446:                .desc = "Private key output password source",
                    447:                .type = OPTION_ARG,
                    448:                .opt.arg = &req_config.passargout,
                    449:        },
                    450:        {
                    451:                .name = "pkeyopt",
                    452:                .argname = "opt:val",
                    453:                .desc = "Set the public key algorithm option opt to val",
                    454:                .type = OPTION_ARG_FUNC,
                    455:                .opt.argfunc = req_opt_pkeyopt,
                    456:        },
                    457:        {
                    458:                .name = "pubkey",
                    459:                .desc = "Output the public key",
                    460:                .type = OPTION_FLAG,
                    461:                .opt.flag = &req_config.pubkey,
                    462:        },
                    463:        {
                    464:                .name = "reqexts",
                    465:                .argname = "section",
                    466:                .desc = "Config section to use for request extensions",
                    467:                .type = OPTION_ARG,
                    468:                .opt.arg = &req_config.req_exts,
                    469:        },
                    470:        {
                    471:                .name = "reqopt",
                    472:                .argname = "option",
                    473:                .desc = "Request text options",
                    474:                .type = OPTION_ARG_FUNC,
                    475:                .opt.argfunc = req_opt_reqopt,
                    476:        },
                    477:        {
                    478:                .name = "set_serial",
                    479:                .argname = "serial",
                    480:                .desc = "Serial number to use for generated certificate",
                    481:                .type = OPTION_ARG_FUNC,
                    482:                .opt.argfunc = req_opt_set_serial,
                    483:        },
                    484:        {
                    485:                .name = "sigopt",
                    486:                .argname = "name:val",
                    487:                .desc = "Signature options",
                    488:                .type = OPTION_ARG_FUNC,
                    489:                .opt.argfunc = req_opt_sigopt,
                    490:        },
                    491:        {
                    492:                .name = "subj",
                    493:                .argname = "name",
                    494:                .desc = "Set or modify the request subject",
                    495:                .type = OPTION_ARG,
                    496:                .opt.arg = &req_config.subj,
                    497:        },
                    498:        {
                    499:                .name = "subject",
                    500:                .desc = "Output the subject of the request",
                    501:                .type = OPTION_FLAG,
                    502:                .opt.flag = &req_config.subject,
                    503:        },
                    504:        {
                    505:                .name = "text",
                    506:                .desc = "Print request in text form",
                    507:                .type = OPTION_FLAG,
                    508:                .opt.flag = &req_config.text,
                    509:        },
                    510:        {
                    511:                .name = "utf8",
                    512:                .desc = "Input characters are in UTF-8 (default ASCII)",
                    513:                .type = OPTION_FUNC,
                    514:                .opt.func = req_opt_utf8,
                    515:        },
                    516:        {
                    517:                .name = "verbose",
                    518:                .desc = "Verbose",
                    519:                .type = OPTION_FLAG,
                    520:                .opt.flag = &req_config.verbose,
                    521:        },
                    522:        {
                    523:                .name = "verify",
                    524:                .desc = "Verify signature on request",
                    525:                .type = OPTION_FLAG,
                    526:                .opt.flag = &req_config.verify,
                    527:        },
                    528:        {
                    529:                .name = "x509",
                    530:                .desc = "Output an X.509 structure instead of a certificate request",
                    531:                .type = OPTION_FLAG,
                    532:                .opt.flag = &req_config.x509,
                    533:        },
                    534:        {
                    535:                .name = NULL,
                    536:                .desc = "",
                    537:                .type = OPTION_ARGV_FUNC,
                    538:                .opt.argvfunc = req_opt_digest,
                    539:        },
                    540:        { NULL },
                    541: };
                    542:
                    543: static void
                    544: req_usage(void)
                    545: {
                    546:        fprintf(stderr,
                    547:            "usage: req [-addext ext] [-asn1-kludge] [-batch] [-config file]\n"
                    548:            "    [-days n] [-extensions section] [-in file]\n"
                    549:            "    [-inform der | pem] [-key keyfile] [-keyform der | pem]\n"
                    550:            "    [-keyout file] [-md4 | -md5 | -sha1] [-modulus]\n"
                    551:            "    [-multivalue-rdn] [-nameopt option] [-new] [-newhdr]\n"
                    552:            "    [-newkey arg] [-no-asn1-kludge] [-nodes] [-noout]\n"
                    553:            "    [-out file] [-outform der | pem] [-passin arg]\n"
                    554:            "    [-passout arg] [-pkeyopt opt:value] [-pubkey]\n"
                    555:            "    [-reqexts section] [-reqopt option] [-set_serial n]\n"
                    556:            "    [-sigopt nm:v] [-subj arg] [-subject] [-text] [-utf8]\n"
                    557:            "    [-verbose] [-verify] [-x509]\n\n");
                    558:
                    559:        options_usage(req_options);
                    560:        fprintf(stderr, "\n");
                    561: }
1.1       jsing     562:
                    563: int
                    564: req_main(int argc, char **argv)
                    565: {
1.19      jsing     566:        int ex = 1;
1.1       jsing     567:        X509 *x509ss = NULL;
                    568:        X509_REQ *req = NULL;
                    569:        EVP_PKEY_CTX *genctx = NULL;
                    570:        char *keyalgstr = NULL;
1.19      jsing     571:        const EVP_CIPHER *cipher = NULL;
1.1       jsing     572:        EVP_PKEY *pkey = NULL;
1.19      jsing     573:        int i = 0, pkey_type = -1;
1.1       jsing     574:        BIO *in = NULL, *out = NULL;
                    575:        char *passin = NULL, *passout = NULL;
1.19      jsing     576:        const EVP_MD *md_alg = NULL;
1.1       jsing     577:        char *p;
1.10      doug      578:
                    579:        if (single_execution) {
1.14      deraadt   580:                if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
1.10      doug      581:                        perror("pledge");
1.12      doug      582:                        exit(1);
                    583:                }
1.10      doug      584:        }
1.1       jsing     585:
1.19      jsing     586:        memset(&req_config, 0, sizeof(req_config));
                    587:
                    588:        req_config.chtype = MBSTRING_ASC;
                    589:        req_config.days = 30;
                    590:        req_config.digest = EVP_sha256();
                    591:        req_config.newkey = -1;
                    592:        req_config.informat = FORMAT_PEM;
                    593:        req_config.keyform = FORMAT_PEM;
                    594:        req_config.outformat = FORMAT_PEM;
                    595:
                    596:        if (options_parse(argc, argv, req_options, NULL, NULL) != 0) {
                    597:                req_usage();
                    598:                return (1);
                    599:        }
                    600:
1.1       jsing     601:        req_conf = NULL;
1.3       sthen     602:        cipher = EVP_aes_256_cbc();
1.2       jsing     603:
1.19      jsing     604:        if (!app_passwd(bio_err, req_config.passargin, req_config.passargout, &passin, &passout)) {
1.1       jsing     605:                BIO_printf(bio_err, "Error getting passwords\n");
                    606:                goto end;
                    607:        }
1.19      jsing     608:        if (req_config.template != NULL) {
1.1       jsing     609:                long errline = -1;
                    610:
1.19      jsing     611:                if (req_config.verbose)
                    612:                        BIO_printf(bio_err, "Using configuration from %s\n", req_config.template);
1.18      inoguchi  613:                if ((req_conf = NCONF_new(NULL)) == NULL)
                    614:                        goto end;
1.19      jsing     615:                if(!NCONF_load(req_conf, req_config.template, &errline)) {
                    616:                        BIO_printf(bio_err, "error on line %ld of %s\n", errline, req_config.template);
1.1       jsing     617:                        goto end;
                    618:                }
                    619:        } else {
                    620:                req_conf = config;
                    621:
                    622:                if (req_conf == NULL) {
                    623:                        BIO_printf(bio_err, "Unable to load config info from %s\n", default_config_file);
1.19      jsing     624:                        if (req_config.newreq)
1.1       jsing     625:                                goto end;
1.19      jsing     626:                } else if (req_config.verbose)
1.1       jsing     627:                        BIO_printf(bio_err, "Using configuration from %s\n",
                    628:                            default_config_file);
                    629:        }
                    630:
1.19      jsing     631:        if (req_config.addext_bio != NULL) {
1.17      inoguchi  632:                long errline = -1;
1.19      jsing     633:                if (req_config.verbose)
1.17      inoguchi  634:                        BIO_printf(bio_err,
                    635:                            "Using additional configuration from command line\n");
1.18      inoguchi  636:                if ((addext_conf = NCONF_new(NULL)) == NULL)
                    637:                        goto end;
1.19      jsing     638:                if (!NCONF_load_bio(addext_conf, req_config.addext_bio, &errline)) {
1.17      inoguchi  639:                        BIO_printf(bio_err,
                    640:                            "req: Error on line %ld of config input\n",
                    641:                            errline);
                    642:                        goto end;
                    643:                }
                    644:        }
                    645:
1.1       jsing     646:        if (req_conf != NULL) {
                    647:                if (!load_config(bio_err, req_conf))
                    648:                        goto end;
                    649:                p = NCONF_get_string(req_conf, NULL, "oid_file");
                    650:                if (p == NULL)
                    651:                        ERR_clear_error();
                    652:                if (p != NULL) {
                    653:                        BIO *oid_bio;
                    654:
                    655:                        oid_bio = BIO_new_file(p, "r");
                    656:                        if (oid_bio == NULL) {
                    657:                                /*
                    658:                                BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
                    659:                                ERR_print_errors(bio_err);
                    660:                                */
                    661:                        } else {
                    662:                                OBJ_create_objects(oid_bio);
                    663:                                BIO_free(oid_bio);
                    664:                        }
                    665:                }
                    666:        }
                    667:        if (!add_oid_section(bio_err, req_conf))
                    668:                goto end;
                    669:
                    670:        if (md_alg == NULL) {
                    671:                p = NCONF_get_string(req_conf, SECTION, "default_md");
                    672:                if (p == NULL)
                    673:                        ERR_clear_error();
                    674:                if (p != NULL) {
                    675:                        if ((md_alg = EVP_get_digestbyname(p)) != NULL)
1.19      jsing     676:                                req_config.digest = md_alg;
1.1       jsing     677:                }
                    678:        }
1.19      jsing     679:        if (!req_config.extensions) {
                    680:                req_config.extensions = NCONF_get_string(req_conf, SECTION, V3_EXTENSIONS);
                    681:                if (!req_config.extensions)
1.1       jsing     682:                        ERR_clear_error();
                    683:        }
1.19      jsing     684:        if (req_config.extensions) {
1.1       jsing     685:                /* Check syntax of file */
                    686:                X509V3_CTX ctx;
                    687:                X509V3_set_ctx_test(&ctx);
                    688:                X509V3_set_nconf(&ctx, req_conf);
1.19      jsing     689:                if (!X509V3_EXT_add_nconf(req_conf, &ctx, req_config.extensions, NULL)) {
1.1       jsing     690:                        BIO_printf(bio_err,
1.19      jsing     691:                            "Error Loading extension section %s\n", req_config.extensions);
1.1       jsing     692:                        goto end;
                    693:                }
                    694:        }
1.17      inoguchi  695:        if (addext_conf != NULL) {
                    696:                /* Check syntax of command line extensions */
                    697:                X509V3_CTX ctx;
                    698:                X509V3_set_ctx_test(&ctx);
                    699:                X509V3_set_nconf(&ctx, addext_conf);
                    700:                if (!X509V3_EXT_add_nconf(addext_conf, &ctx, "default", NULL)) {
                    701:                        BIO_printf(bio_err,
                    702:                            "Error Loading command line extensions\n");
                    703:                        goto end;
                    704:                }
                    705:        }
1.1       jsing     706:        if (!passin) {
                    707:                passin = NCONF_get_string(req_conf, SECTION, "input_password");
                    708:                if (!passin)
                    709:                        ERR_clear_error();
                    710:        }
                    711:        if (!passout) {
                    712:                passout = NCONF_get_string(req_conf, SECTION, "output_password");
                    713:                if (!passout)
                    714:                        ERR_clear_error();
                    715:        }
                    716:        p = NCONF_get_string(req_conf, SECTION, STRING_MASK);
                    717:        if (!p)
                    718:                ERR_clear_error();
                    719:
                    720:        if (p && !ASN1_STRING_set_default_mask_asc(p)) {
                    721:                BIO_printf(bio_err, "Invalid global string mask setting %s\n", p);
                    722:                goto end;
                    723:        }
1.19      jsing     724:        if (req_config.chtype != MBSTRING_UTF8) {
1.1       jsing     725:                p = NCONF_get_string(req_conf, SECTION, UTF8_IN);
                    726:                if (!p)
                    727:                        ERR_clear_error();
                    728:                else if (!strcmp(p, "yes"))
1.19      jsing     729:                        req_config.chtype = MBSTRING_UTF8;
1.1       jsing     730:        }
1.19      jsing     731:        if (!req_config.req_exts) {
                    732:                req_config.req_exts = NCONF_get_string(req_conf, SECTION, REQ_EXTENSIONS);
                    733:                if (!req_config.req_exts)
1.1       jsing     734:                        ERR_clear_error();
                    735:        }
1.19      jsing     736:        if (req_config.req_exts) {
1.1       jsing     737:                /* Check syntax of file */
                    738:                X509V3_CTX ctx;
                    739:                X509V3_set_ctx_test(&ctx);
                    740:                X509V3_set_nconf(&ctx, req_conf);
1.19      jsing     741:                if (!X509V3_EXT_add_nconf(req_conf, &ctx, req_config.req_exts, NULL)) {
1.1       jsing     742:                        BIO_printf(bio_err,
                    743:                            "Error Loading request extension section %s\n",
1.19      jsing     744:                            req_config.req_exts);
1.1       jsing     745:                        goto end;
                    746:                }
                    747:        }
                    748:        in = BIO_new(BIO_s_file());
                    749:        out = BIO_new(BIO_s_file());
                    750:        if ((in == NULL) || (out == NULL))
                    751:                goto end;
                    752:
1.19      jsing     753:        if (req_config.keyfile != NULL) {
                    754:                pkey = load_key(bio_err, req_config.keyfile, req_config.keyform, 0, passin,
1.1       jsing     755:                    "Private Key");
                    756:                if (!pkey) {
                    757:                        /*
                    758:                         * load_key() has already printed an appropriate
                    759:                         * message
                    760:                         */
                    761:                        goto end;
                    762:                }
                    763:        }
1.19      jsing     764:        if (req_config.newreq && (pkey == NULL)) {
                    765:                if (!NCONF_get_number(req_conf, SECTION, BITS, &req_config.newkey)) {
                    766:                        req_config.newkey = DEFAULT_KEY_LENGTH;
1.1       jsing     767:                }
1.19      jsing     768:                if (req_config.keyalg) {
                    769:                        genctx = set_keygen_ctx(bio_err, req_config.keyalg, &pkey_type, &req_config.newkey,
1.7       bcook     770:                            &keyalgstr);
1.1       jsing     771:                        if (!genctx)
                    772:                                goto end;
                    773:                }
1.19      jsing     774:                if (req_config.newkey < MIN_KEY_LENGTH && (pkey_type == EVP_PKEY_RSA || pkey_type == EVP_PKEY_DSA)) {
1.1       jsing     775:                        BIO_printf(bio_err, "private key length is too short,\n");
1.19      jsing     776:                        BIO_printf(bio_err, "it needs to be at least %d bits, not %ld\n", MIN_KEY_LENGTH, req_config.newkey);
1.1       jsing     777:                        goto end;
                    778:                }
                    779:                if (!genctx) {
1.19      jsing     780:                        genctx = set_keygen_ctx(bio_err, NULL, &pkey_type, &req_config.newkey,
1.7       bcook     781:                            &keyalgstr);
1.1       jsing     782:                        if (!genctx)
                    783:                                goto end;
                    784:                }
1.19      jsing     785:                if (req_config.pkeyopts) {
1.1       jsing     786:                        char *genopt;
1.19      jsing     787:                        for (i = 0; i < sk_OPENSSL_STRING_num(req_config.pkeyopts); i++) {
                    788:                                genopt = sk_OPENSSL_STRING_value(req_config.pkeyopts, i);
1.1       jsing     789:                                if (pkey_ctrl_string(genctx, genopt) <= 0) {
                    790:                                        BIO_printf(bio_err,
                    791:                                            "parameter error \"%s\"\n",
                    792:                                            genopt);
                    793:                                        ERR_print_errors(bio_err);
                    794:                                        goto end;
                    795:                                }
                    796:                        }
                    797:                }
                    798:                BIO_printf(bio_err, "Generating a %ld bit %s private key\n",
1.19      jsing     799:                    req_config.newkey, keyalgstr);
1.1       jsing     800:
                    801:                EVP_PKEY_CTX_set_cb(genctx, genpkey_cb);
                    802:                EVP_PKEY_CTX_set_app_data(genctx, bio_err);
                    803:
                    804:                if (EVP_PKEY_keygen(genctx, &pkey) <= 0) {
                    805:                        BIO_puts(bio_err, "Error Generating Key\n");
                    806:                        goto end;
                    807:                }
                    808:                EVP_PKEY_CTX_free(genctx);
                    809:                genctx = NULL;
                    810:
1.19      jsing     811:                if (req_config.keyout == NULL) {
                    812:                        req_config.keyout = NCONF_get_string(req_conf, SECTION, KEYFILE);
                    813:                        if (req_config.keyout == NULL)
1.1       jsing     814:                                ERR_clear_error();
                    815:                }
1.19      jsing     816:                if (req_config.keyout == NULL) {
1.1       jsing     817:                        BIO_printf(bio_err, "writing new private key to stdout\n");
                    818:                        BIO_set_fp(out, stdout, BIO_NOCLOSE);
                    819:                } else {
1.19      jsing     820:                        BIO_printf(bio_err, "writing new private key to '%s'\n", req_config.keyout);
                    821:                        if (BIO_write_filename(out, req_config.keyout) <= 0) {
                    822:                                perror(req_config.keyout);
1.1       jsing     823:                                goto end;
                    824:                        }
                    825:                }
                    826:
                    827:                p = NCONF_get_string(req_conf, SECTION, "encrypt_rsa_key");
                    828:                if (p == NULL) {
                    829:                        ERR_clear_error();
                    830:                        p = NCONF_get_string(req_conf, SECTION, "encrypt_key");
                    831:                        if (p == NULL)
                    832:                                ERR_clear_error();
                    833:                }
                    834:                if ((p != NULL) && (strcmp(p, "no") == 0))
                    835:                        cipher = NULL;
1.19      jsing     836:                if (req_config.nodes)
1.1       jsing     837:                        cipher = NULL;
                    838:
                    839:                i = 0;
1.15      jsing     840:  loop:
1.1       jsing     841:                if (!PEM_write_bio_PrivateKey(out, pkey, cipher,
                    842:                        NULL, 0, NULL, passout)) {
                    843:                        if ((ERR_GET_REASON(ERR_peek_error()) ==
                    844:                                PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3)) {
                    845:                                ERR_clear_error();
                    846:                                i++;
                    847:                                goto loop;
                    848:                        }
                    849:                        goto end;
                    850:                }
                    851:                BIO_printf(bio_err, "-----\n");
                    852:        }
1.19      jsing     853:        if (!req_config.newreq) {
1.1       jsing     854:                /*
                    855:                 * Since we are using a pre-existing certificate request, the
                    856:                 * kludge 'format' info should not be changed.
                    857:                 */
1.19      jsing     858:                req_config.kludge = -1;
                    859:                if (req_config.infile == NULL)
1.1       jsing     860:                        BIO_set_fp(in, stdin, BIO_NOCLOSE);
                    861:                else {
1.19      jsing     862:                        if (BIO_read_filename(in, req_config.infile) <= 0) {
                    863:                                perror(req_config.infile);
1.1       jsing     864:                                goto end;
                    865:                        }
                    866:                }
                    867:
1.19      jsing     868:                if (req_config.informat == FORMAT_ASN1)
1.1       jsing     869:                        req = d2i_X509_REQ_bio(in, NULL);
1.19      jsing     870:                else if (req_config.informat == FORMAT_PEM)
1.1       jsing     871:                        req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
                    872:                else {
                    873:                        BIO_printf(bio_err, "bad input format specified for X509 request\n");
                    874:                        goto end;
                    875:                }
                    876:                if (req == NULL) {
                    877:                        BIO_printf(bio_err, "unable to load X509 request\n");
                    878:                        goto end;
                    879:                }
                    880:        }
1.19      jsing     881:        if (req_config.newreq || req_config.x509) {
1.1       jsing     882:                if (pkey == NULL) {
                    883:                        BIO_printf(bio_err, "you need to specify a private key\n");
                    884:                        goto end;
                    885:                }
                    886:                if (req == NULL) {
                    887:                        req = X509_REQ_new();
                    888:                        if (req == NULL) {
                    889:                                goto end;
                    890:                        }
1.19      jsing     891:                        i = make_REQ(req, pkey, req_config.subj, req_config.multirdn, !req_config.x509, req_config.chtype);
                    892:                        req_config.subj = NULL; /* done processing '-subj' option */
                    893:                        if ((req_config.kludge > 0) && !sk_X509_ATTRIBUTE_num(req->req_info->attributes)) {
1.1       jsing     894:                                sk_X509_ATTRIBUTE_free(req->req_info->attributes);
                    895:                                req->req_info->attributes = NULL;
                    896:                        }
                    897:                        if (!i) {
                    898:                                BIO_printf(bio_err, "problems making Certificate Request\n");
                    899:                                goto end;
                    900:                        }
                    901:                }
1.19      jsing     902:                if (req_config.x509) {
1.1       jsing     903:                        EVP_PKEY *tmppkey;
                    904:                        X509V3_CTX ext_ctx;
                    905:                        if ((x509ss = X509_new()) == NULL)
                    906:                                goto end;
                    907:
                    908:                        /* Set version to V3 */
1.19      jsing     909:                        if ((req_config.extensions != NULL || addext_conf != NULL) &&
1.17      inoguchi  910:                            !X509_set_version(x509ss, 2))
1.1       jsing     911:                                goto end;
1.19      jsing     912:                        if (req_config.serial) {
                    913:                                if (!X509_set_serialNumber(x509ss, req_config.serial))
1.1       jsing     914:                                        goto end;
                    915:                        } else {
                    916:                                if (!rand_serial(NULL,
                    917:                                        X509_get_serialNumber(x509ss)))
                    918:                                        goto end;
                    919:                        }
                    920:
                    921:                        if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req)))
                    922:                                goto end;
                    923:                        if (!X509_gmtime_adj(X509_get_notBefore(x509ss), 0))
                    924:                                goto end;
1.19      jsing     925:                        if (!X509_time_adj_ex(X509_get_notAfter(x509ss), req_config.days, 0, NULL))
1.1       jsing     926:                                goto end;
                    927:                        if (!X509_set_subject_name(x509ss, X509_REQ_get_subject_name(req)))
                    928:                                goto end;
                    929:                        tmppkey = X509_REQ_get_pubkey(req);
                    930:                        if (!tmppkey || !X509_set_pubkey(x509ss, tmppkey))
                    931:                                goto end;
                    932:                        EVP_PKEY_free(tmppkey);
                    933:
                    934:                        /* Set up V3 context struct */
                    935:
                    936:                        X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0);
                    937:                        X509V3_set_nconf(&ext_ctx, req_conf);
                    938:
                    939:                        /* Add extensions */
1.19      jsing     940:                        if (req_config.extensions && !X509V3_EXT_add_nconf(req_conf,
                    941:                                &ext_ctx, req_config.extensions, x509ss)) {
1.1       jsing     942:                                BIO_printf(bio_err,
                    943:                                    "Error Loading extension section %s\n",
1.19      jsing     944:                                    req_config.extensions);
1.1       jsing     945:                                goto end;
                    946:                        }
1.17      inoguchi  947:                        if (addext_conf != NULL &&
                    948:                            !X509V3_EXT_add_nconf(addext_conf, &ext_ctx,
                    949:                                    "default", x509ss)) {
                    950:                                BIO_printf(bio_err,
                    951:                                    "Error Loading command line extensions\n");
                    952:                                goto end;
                    953:                        }
1.19      jsing     954:                        i = do_X509_sign(bio_err, x509ss, pkey, req_config.digest, req_config.sigopts);
1.1       jsing     955:                        if (!i) {
                    956:                                ERR_print_errors(bio_err);
                    957:                                goto end;
                    958:                        }
                    959:                } else {
                    960:                        X509V3_CTX ext_ctx;
                    961:
                    962:                        /* Set up V3 context struct */
                    963:
                    964:                        X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0);
                    965:                        X509V3_set_nconf(&ext_ctx, req_conf);
                    966:
                    967:                        /* Add extensions */
1.19      jsing     968:                        if (req_config.req_exts && !X509V3_EXT_REQ_add_nconf(req_conf,
                    969:                                &ext_ctx, req_config.req_exts, req)) {
1.1       jsing     970:                                BIO_printf(bio_err,
                    971:                                    "Error Loading extension section %s\n",
1.19      jsing     972:                                    req_config.req_exts);
1.1       jsing     973:                                goto end;
                    974:                        }
1.17      inoguchi  975:                        if (addext_conf != NULL &&
                    976:                            !X509V3_EXT_REQ_add_nconf(addext_conf, &ext_ctx,
                    977:                                    "default", req)) {
                    978:                                BIO_printf(bio_err,
                    979:                                    "Error Loading command line extensions\n");
                    980:                                goto end;
                    981:                        }
1.19      jsing     982:                        i = do_X509_REQ_sign(bio_err, req, pkey, req_config.digest, req_config.sigopts);
1.1       jsing     983:                        if (!i) {
                    984:                                ERR_print_errors(bio_err);
                    985:                                goto end;
                    986:                        }
                    987:                }
                    988:        }
1.19      jsing     989:        if (req_config.subj && req_config.x509) {
                    990:                BIO_printf(bio_err, "Cannot modify certificate subject\n");
1.1       jsing     991:                goto end;
                    992:        }
1.19      jsing     993:        if (req_config.subj && !req_config.x509) {
                    994:                if (req_config.verbose) {
1.1       jsing     995:                        BIO_printf(bio_err, "Modifying Request's Subject\n");
1.19      jsing     996:                        print_name(bio_err, "old subject=", X509_REQ_get_subject_name(req), req_config.nmflag);
1.1       jsing     997:                }
1.19      jsing     998:                if (build_subject(req, req_config.subj, req_config.chtype, req_config.multirdn) == 0) {
1.1       jsing     999:                        BIO_printf(bio_err, "ERROR: cannot modify subject\n");
                   1000:                        ex = 1;
                   1001:                        goto end;
                   1002:                }
                   1003:
1.19      jsing    1004:                if (req_config.verbose) {
                   1005:                        print_name(bio_err, "new subject=", X509_REQ_get_subject_name(req), req_config.nmflag);
1.1       jsing    1006:                }
                   1007:        }
1.19      jsing    1008:        if (req_config.verify && !req_config.x509) {
1.1       jsing    1009:                int tmp = 0;
                   1010:
                   1011:                if (pkey == NULL) {
                   1012:                        pkey = X509_REQ_get_pubkey(req);
                   1013:                        tmp = 1;
                   1014:                        if (pkey == NULL)
                   1015:                                goto end;
                   1016:                }
                   1017:                i = X509_REQ_verify(req, pkey);
                   1018:                if (tmp) {
                   1019:                        EVP_PKEY_free(pkey);
                   1020:                        pkey = NULL;
                   1021:                }
                   1022:                if (i < 0) {
                   1023:                        goto end;
                   1024:                } else if (i == 0) {
                   1025:                        BIO_printf(bio_err, "verify failure\n");
                   1026:                        ERR_print_errors(bio_err);
                   1027:                } else          /* if (i > 0) */
                   1028:                        BIO_printf(bio_err, "verify OK\n");
                   1029:        }
1.19      jsing    1030:        if (req_config.noout && !req_config.text && !req_config.modulus && !req_config.subject && !req_config.pubkey) {
1.1       jsing    1031:                ex = 0;
                   1032:                goto end;
                   1033:        }
1.19      jsing    1034:        if (req_config.outfile == NULL) {
1.1       jsing    1035:                BIO_set_fp(out, stdout, BIO_NOCLOSE);
                   1036:        } else {
1.19      jsing    1037:                if ((req_config.keyout != NULL) && (strcmp(req_config.outfile, req_config.keyout) == 0))
                   1038:                        i = (int) BIO_append_filename(out, req_config.outfile);
1.1       jsing    1039:                else
1.19      jsing    1040:                        i = (int) BIO_write_filename(out, req_config.outfile);
1.1       jsing    1041:                if (!i) {
1.19      jsing    1042:                        perror(req_config.outfile);
1.1       jsing    1043:                        goto end;
                   1044:                }
                   1045:        }
                   1046:
1.19      jsing    1047:        if (req_config.pubkey) {
1.1       jsing    1048:                EVP_PKEY *tpubkey;
                   1049:                tpubkey = X509_REQ_get_pubkey(req);
                   1050:                if (tpubkey == NULL) {
                   1051:                        BIO_printf(bio_err, "Error getting public key\n");
                   1052:                        ERR_print_errors(bio_err);
                   1053:                        goto end;
                   1054:                }
                   1055:                PEM_write_bio_PUBKEY(out, tpubkey);
                   1056:                EVP_PKEY_free(tpubkey);
                   1057:        }
1.19      jsing    1058:        if (req_config.text) {
                   1059:                if (req_config.x509)
                   1060:                        X509_print_ex(out, x509ss, req_config.nmflag, req_config.reqflag);
1.1       jsing    1061:                else
1.19      jsing    1062:                        X509_REQ_print_ex(out, req, req_config.nmflag, req_config.reqflag);
1.1       jsing    1063:        }
1.19      jsing    1064:        if (req_config.subject) {
                   1065:                if (req_config.x509)
                   1066:                        print_name(out, "subject=", X509_get_subject_name(x509ss), req_config.nmflag);
1.1       jsing    1067:                else
1.19      jsing    1068:                        print_name(out, "subject=", X509_REQ_get_subject_name(req), req_config.nmflag);
1.1       jsing    1069:        }
1.19      jsing    1070:        if (req_config.modulus) {
1.1       jsing    1071:                EVP_PKEY *tpubkey;
                   1072:
1.19      jsing    1073:                if (req_config.x509)
1.1       jsing    1074:                        tpubkey = X509_get_pubkey(x509ss);
                   1075:                else
                   1076:                        tpubkey = X509_REQ_get_pubkey(req);
                   1077:                if (tpubkey == NULL) {
                   1078:                        fprintf(stdout, "Modulus=unavailable\n");
                   1079:                        goto end;
                   1080:                }
                   1081:                fprintf(stdout, "Modulus=");
                   1082:                if (EVP_PKEY_base_id(tpubkey) == EVP_PKEY_RSA)
                   1083:                        BN_print(out, tpubkey->pkey.rsa->n);
                   1084:                else
                   1085:                        fprintf(stdout, "Wrong Algorithm type");
                   1086:                EVP_PKEY_free(tpubkey);
                   1087:                fprintf(stdout, "\n");
                   1088:        }
1.19      jsing    1089:        if (!req_config.noout && !req_config.x509) {
                   1090:                if (req_config.outformat == FORMAT_ASN1)
1.1       jsing    1091:                        i = i2d_X509_REQ_bio(out, req);
1.19      jsing    1092:                else if (req_config.outformat == FORMAT_PEM) {
                   1093:                        if (req_config.newhdr)
1.1       jsing    1094:                                i = PEM_write_bio_X509_REQ_NEW(out, req);
                   1095:                        else
                   1096:                                i = PEM_write_bio_X509_REQ(out, req);
                   1097:                } else {
                   1098:                        BIO_printf(bio_err, "bad output format specified for outfile\n");
                   1099:                        goto end;
                   1100:                }
                   1101:                if (!i) {
                   1102:                        BIO_printf(bio_err, "unable to write X509 request\n");
                   1103:                        goto end;
                   1104:                }
                   1105:        }
1.19      jsing    1106:        if (!req_config.noout && req_config.x509 && (x509ss != NULL)) {
                   1107:                if (req_config.outformat == FORMAT_ASN1)
1.1       jsing    1108:                        i = i2d_X509_bio(out, x509ss);
1.19      jsing    1109:                else if (req_config.outformat == FORMAT_PEM)
1.1       jsing    1110:                        i = PEM_write_bio_X509(out, x509ss);
                   1111:                else {
                   1112:                        BIO_printf(bio_err, "bad output format specified for outfile\n");
                   1113:                        goto end;
                   1114:                }
                   1115:                if (!i) {
                   1116:                        BIO_printf(bio_err, "unable to write X509 certificate\n");
                   1117:                        goto end;
                   1118:                }
                   1119:        }
                   1120:        ex = 0;
1.15      jsing    1121:  end:
1.1       jsing    1122:        if (ex) {
                   1123:                ERR_print_errors(bio_err);
                   1124:        }
                   1125:        if ((req_conf != NULL) && (req_conf != config))
                   1126:                NCONF_free(req_conf);
1.17      inoguchi 1127:        NCONF_free(addext_conf);
1.19      jsing    1128:        BIO_free(req_config.addext_bio);
1.1       jsing    1129:        BIO_free(in);
                   1130:        BIO_free_all(out);
                   1131:        EVP_PKEY_free(pkey);
                   1132:        if (genctx)
                   1133:                EVP_PKEY_CTX_free(genctx);
1.19      jsing    1134:        if (req_config.pkeyopts)
                   1135:                sk_OPENSSL_STRING_free(req_config.pkeyopts);
                   1136:        if (req_config.sigopts)
                   1137:                sk_OPENSSL_STRING_free(req_config.sigopts);
                   1138:        lh_OPENSSL_STRING_doall(req_config.addexts, (LHASH_DOALL_FN_TYPE)exts_cleanup);
                   1139:        lh_OPENSSL_STRING_free(req_config.addexts);
1.1       jsing    1140:        free(keyalgstr);
                   1141:        X509_REQ_free(req);
                   1142:        X509_free(x509ss);
1.19      jsing    1143:        ASN1_INTEGER_free(req_config.serial);
                   1144:        if (req_config.passargin && passin)
1.1       jsing    1145:                free(passin);
1.19      jsing    1146:        if (req_config.passargout && passout)
1.1       jsing    1147:                free(passout);
                   1148:        OBJ_cleanup();
                   1149:
                   1150:        return (ex);
                   1151: }
                   1152:
                   1153: static int
                   1154: make_REQ(X509_REQ * req, EVP_PKEY * pkey, char *subj, int multirdn,
                   1155:     int attribs, unsigned long chtype)
                   1156: {
                   1157:        int ret = 0, i;
                   1158:        char no_prompt = 0;
                   1159:        STACK_OF(CONF_VALUE) * dn_sk, *attr_sk = NULL;
                   1160:        char *tmp, *dn_sect, *attr_sect;
                   1161:
                   1162:        tmp = NCONF_get_string(req_conf, SECTION, PROMPT);
                   1163:        if (tmp == NULL)
                   1164:                ERR_clear_error();
                   1165:        if ((tmp != NULL) && !strcmp(tmp, "no"))
                   1166:                no_prompt = 1;
                   1167:
                   1168:        dn_sect = NCONF_get_string(req_conf, SECTION, DISTINGUISHED_NAME);
                   1169:        if (dn_sect == NULL) {
                   1170:                BIO_printf(bio_err, "unable to find '%s' in config\n",
                   1171:                    DISTINGUISHED_NAME);
                   1172:                goto err;
                   1173:        }
                   1174:        dn_sk = NCONF_get_section(req_conf, dn_sect);
                   1175:        if (dn_sk == NULL) {
                   1176:                BIO_printf(bio_err, "unable to get '%s' section\n", dn_sect);
                   1177:                goto err;
                   1178:        }
                   1179:        attr_sect = NCONF_get_string(req_conf, SECTION, ATTRIBUTES);
                   1180:        if (attr_sect == NULL) {
                   1181:                ERR_clear_error();
                   1182:                attr_sk = NULL;
                   1183:        } else {
                   1184:                attr_sk = NCONF_get_section(req_conf, attr_sect);
                   1185:                if (attr_sk == NULL) {
                   1186:                        BIO_printf(bio_err, "unable to get '%s' section\n", attr_sect);
                   1187:                        goto err;
                   1188:                }
                   1189:        }
                   1190:
                   1191:        /* setup version number */
                   1192:        if (!X509_REQ_set_version(req, 0L))
                   1193:                goto err;       /* version 1 */
                   1194:
                   1195:        if (no_prompt)
                   1196:                i = auto_info(req, dn_sk, attr_sk, attribs, chtype);
                   1197:        else {
                   1198:                if (subj)
                   1199:                        i = build_subject(req, subj, chtype, multirdn);
                   1200:                else
                   1201:                        i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs, chtype);
                   1202:        }
                   1203:        if (!i)
                   1204:                goto err;
                   1205:
                   1206:        if (!X509_REQ_set_pubkey(req, pkey))
                   1207:                goto err;
                   1208:
                   1209:        ret = 1;
1.15      jsing    1210:  err:
1.1       jsing    1211:        return (ret);
                   1212: }
                   1213:
                   1214: /*
                   1215:  * subject is expected to be in the format /type0=value0/type1=value1/type2=...
                   1216:  * where characters may be escaped by \
                   1217:  */
                   1218: static int
                   1219: build_subject(X509_REQ * req, char *subject, unsigned long chtype, int multirdn)
                   1220: {
                   1221:        X509_NAME *n;
                   1222:
                   1223:        if (!(n = parse_name(subject, chtype, multirdn)))
                   1224:                return 0;
                   1225:
                   1226:        if (!X509_REQ_set_subject_name(req, n)) {
                   1227:                X509_NAME_free(n);
                   1228:                return 0;
                   1229:        }
                   1230:        X509_NAME_free(n);
                   1231:        return 1;
                   1232: }
                   1233:
                   1234:
                   1235: static int
                   1236: prompt_info(X509_REQ * req,
                   1237:     STACK_OF(CONF_VALUE) * dn_sk, char *dn_sect,
                   1238:     STACK_OF(CONF_VALUE) * attr_sk, char *attr_sect, int attribs,
                   1239:     unsigned long chtype)
                   1240: {
                   1241:        int i;
                   1242:        char *p, *q;
                   1243:        char buf[100];
                   1244:        int nid, mval;
                   1245:        long n_min, n_max;
                   1246:        char *type, *value;
                   1247:        const char *def;
                   1248:        CONF_VALUE *v;
                   1249:        X509_NAME *subj;
                   1250:        subj = X509_REQ_get_subject_name(req);
                   1251:
1.19      jsing    1252:        if (!req_config.batch) {
1.1       jsing    1253:                BIO_printf(bio_err, "You are about to be asked to enter information that will be incorporated\n");
                   1254:                BIO_printf(bio_err, "into your certificate request.\n");
                   1255:                BIO_printf(bio_err, "What you are about to enter is what is called a Distinguished Name or a DN.\n");
                   1256:                BIO_printf(bio_err, "There are quite a few fields but you can leave some blank\n");
                   1257:                BIO_printf(bio_err, "For some fields there will be a default value,\n");
                   1258:                BIO_printf(bio_err, "If you enter '.', the field will be left blank.\n");
                   1259:                BIO_printf(bio_err, "-----\n");
                   1260:        }
                   1261:        if (sk_CONF_VALUE_num(dn_sk)) {
                   1262:                i = -1;
1.15      jsing    1263:  start:                for (;;) {
1.1       jsing    1264:                        int ret;
                   1265:                        i++;
                   1266:                        if (sk_CONF_VALUE_num(dn_sk) <= i)
                   1267:                                break;
                   1268:
                   1269:                        v = sk_CONF_VALUE_value(dn_sk, i);
                   1270:                        p = q = NULL;
                   1271:                        type = v->name;
                   1272:                        if (!check_end(type, "_min") || !check_end(type, "_max") ||
                   1273:                            !check_end(type, "_default") ||
                   1274:                            !check_end(type, "_value"))
                   1275:                                continue;
                   1276:                        /*
                   1277:                         * Skip past any leading X. X: X, etc to allow for
                   1278:                         * multiple instances
                   1279:                         */
                   1280:                        for (p = v->name; *p; p++)
                   1281:                                if ((*p == ':') || (*p == ',') ||
                   1282:                                    (*p == '.')) {
                   1283:                                        p++;
                   1284:                                        if (*p)
                   1285:                                                type = p;
                   1286:                                        break;
                   1287:                                }
                   1288:                        if (*type == '+') {
                   1289:                                mval = -1;
                   1290:                                type++;
                   1291:                        } else
                   1292:                                mval = 0;
                   1293:                        /* If OBJ not recognised ignore it */
                   1294:                        if ((nid = OBJ_txt2nid(type)) == NID_undef)
                   1295:                                goto start;
                   1296:                        ret = snprintf(buf, sizeof buf, "%s_default", v->name);
1.16      deraadt  1297:                        if (ret < 0 || ret >= sizeof(buf)) {
1.1       jsing    1298:                                BIO_printf(bio_err, "Name '%s' too long for default\n",
                   1299:                                    v->name);
                   1300:                                return 0;
                   1301:                        }
                   1302:                        if ((def = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) {
                   1303:                                ERR_clear_error();
                   1304:                                def = "";
                   1305:                        }
                   1306:                        ret = snprintf(buf, sizeof buf, "%s_value", v->name);
1.16      deraadt  1307:                        if (ret < 0 || ret >= sizeof(buf)) {
1.1       jsing    1308:                                BIO_printf(bio_err, "Name '%s' too long for value\n",
                   1309:                                    v->name);
                   1310:                                return 0;
                   1311:                        }
                   1312:                        if ((value = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) {
                   1313:                                ERR_clear_error();
                   1314:                                value = NULL;
                   1315:                        }
                   1316:                        ret = snprintf(buf, sizeof buf, "%s_min", v->name);
1.16      deraadt  1317:                        if (ret < 0 || ret >= sizeof(buf)) {
1.1       jsing    1318:                                BIO_printf(bio_err, "Name '%s' too long for min\n",
                   1319:                                    v->name);
                   1320:                                return 0;
                   1321:                        }
                   1322:                        if (!NCONF_get_number(req_conf, dn_sect, buf, &n_min)) {
                   1323:                                ERR_clear_error();
                   1324:                                n_min = -1;
                   1325:                        }
                   1326:                        ret = snprintf(buf, sizeof buf, "%s_max", v->name);
1.16      deraadt  1327:                        if (ret < 0 || ret >= sizeof(buf)) {
1.1       jsing    1328:                                BIO_printf(bio_err, "Name '%s' too long for max\n",
                   1329:                                    v->name);
                   1330:                                return 0;
                   1331:                        }
                   1332:                        if (!NCONF_get_number(req_conf, dn_sect, buf, &n_max)) {
                   1333:                                ERR_clear_error();
                   1334:                                n_max = -1;
                   1335:                        }
                   1336:                        if (!add_DN_object(subj, v->value, def, value, nid,
                   1337:                                n_min, n_max, chtype, mval))
                   1338:                                return 0;
                   1339:                }
                   1340:                if (X509_NAME_entry_count(subj) == 0) {
                   1341:                        BIO_printf(bio_err, "error, no objects specified in config file\n");
                   1342:                        return 0;
                   1343:                }
                   1344:                if (attribs) {
                   1345:                        if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0) &&
1.19      jsing    1346:                            (!req_config.batch)) {
1.1       jsing    1347:                                BIO_printf(bio_err,
                   1348:                                    "\nPlease enter the following 'extra' attributes\n");
                   1349:                                BIO_printf(bio_err,
                   1350:                                    "to be sent with your certificate request\n");
                   1351:                        }
                   1352:                        i = -1;
                   1353: start2:                        for (;;) {
                   1354:                                int ret;
                   1355:                                i++;
                   1356:                                if ((attr_sk == NULL) ||
                   1357:                                    (sk_CONF_VALUE_num(attr_sk) <= i))
                   1358:                                        break;
                   1359:
                   1360:                                v = sk_CONF_VALUE_value(attr_sk, i);
                   1361:                                type = v->name;
                   1362:                                if ((nid = OBJ_txt2nid(type)) == NID_undef)
                   1363:                                        goto start2;
                   1364:                                ret = snprintf(buf, sizeof buf, "%s_default", type);
1.16      deraadt  1365:                                if (ret < 0 || ret >= sizeof(buf)) {
1.1       jsing    1366:                                        BIO_printf(bio_err, "Name '%s' too long for default\n",
                   1367:                                            v->name);
                   1368:                                        return 0;
                   1369:                                }
                   1370:                                if ((def = NCONF_get_string(req_conf, attr_sect, buf))
                   1371:                                    == NULL) {
                   1372:                                        ERR_clear_error();
                   1373:                                        def = "";
                   1374:                                }
                   1375:                                ret = snprintf(buf, sizeof buf, "%s_value", type);
1.16      deraadt  1376:                                if (ret < 0 || ret >= sizeof(buf)) {
1.1       jsing    1377:                                        BIO_printf(bio_err, "Name '%s' too long for value\n",
                   1378:                                            v->name);
                   1379:                                        return 0;
                   1380:                                }
                   1381:                                if ((value = NCONF_get_string(req_conf, attr_sect, buf))
                   1382:                                    == NULL) {
                   1383:                                        ERR_clear_error();
                   1384:                                        value = NULL;
                   1385:                                }
                   1386:                                ret = snprintf(buf, sizeof buf, "%s_min", type);
1.16      deraadt  1387:                                if (ret < 0 || ret >= sizeof(buf)) {
1.1       jsing    1388:                                        BIO_printf(bio_err, "Name '%s' too long for min\n",
                   1389:                                            v->name);
                   1390:                                        return 0;
                   1391:                                }
                   1392:                                if (!NCONF_get_number(req_conf, attr_sect, buf, &n_min)) {
                   1393:                                        ERR_clear_error();
                   1394:                                        n_min = -1;
                   1395:                                }
                   1396:                                ret = snprintf(buf, sizeof buf, "%s_max", type);
1.16      deraadt  1397:                                if (ret < 0 || ret >= sizeof(buf)) {
1.1       jsing    1398:                                        BIO_printf(bio_err, "Name '%s' too long for max\n",
                   1399:                                            v->name);
                   1400:                                        return 0;
                   1401:                                }
                   1402:                                if (!NCONF_get_number(req_conf, attr_sect, buf, &n_max)) {
                   1403:                                        ERR_clear_error();
                   1404:                                        n_max = -1;
                   1405:                                }
                   1406:                                if (!add_attribute_object(req,
                   1407:                                        v->value, def, value, nid, n_min, n_max, chtype))
                   1408:                                        return 0;
                   1409:                        }
                   1410:                }
                   1411:        } else {
                   1412:                BIO_printf(bio_err, "No template, please set one up.\n");
                   1413:                return 0;
                   1414:        }
                   1415:
                   1416:        return 1;
                   1417:
                   1418: }
                   1419:
                   1420: static int
                   1421: auto_info(X509_REQ * req, STACK_OF(CONF_VALUE) * dn_sk,
                   1422:     STACK_OF(CONF_VALUE) * attr_sk, int attribs, unsigned long chtype)
                   1423: {
                   1424:        int i;
                   1425:        char *p, *q;
                   1426:        char *type;
                   1427:        CONF_VALUE *v;
                   1428:        X509_NAME *subj;
                   1429:
                   1430:        subj = X509_REQ_get_subject_name(req);
                   1431:
                   1432:        for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
                   1433:                int mval;
                   1434:                v = sk_CONF_VALUE_value(dn_sk, i);
                   1435:                p = q = NULL;
                   1436:                type = v->name;
                   1437:                /*
                   1438:                 * Skip past any leading X. X: X, etc to allow for multiple
                   1439:                 * instances
                   1440:                 */
                   1441:                for (p = v->name; *p; p++)
                   1442:                        if ((*p == ':') || (*p == ',') || (*p == '.')) {
                   1443:                                p++;
                   1444:                                if (*p)
                   1445:                                        type = p;
                   1446:                                break;
                   1447:                        }
                   1448:                if (*p == '+') {
                   1449:                        p++;
                   1450:                        mval = -1;
                   1451:                } else
                   1452:                        mval = 0;
                   1453:                if (!X509_NAME_add_entry_by_txt(subj, type, chtype,
                   1454:                        (unsigned char *) v->value, -1, -1, mval))
                   1455:                        return 0;
                   1456:
                   1457:        }
                   1458:
                   1459:        if (!X509_NAME_entry_count(subj)) {
                   1460:                BIO_printf(bio_err, "error, no objects specified in config file\n");
                   1461:                return 0;
                   1462:        }
                   1463:        if (attribs) {
                   1464:                for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) {
                   1465:                        v = sk_CONF_VALUE_value(attr_sk, i);
                   1466:                        if (!X509_REQ_add1_attr_by_txt(req, v->name, chtype,
                   1467:                                (unsigned char *) v->value, -1))
                   1468:                                return 0;
                   1469:                }
                   1470:        }
                   1471:        return 1;
                   1472: }
                   1473:
                   1474:
                   1475: static int
                   1476: add_DN_object(X509_NAME * n, char *text, const char *def, char *value,
                   1477:     int nid, int n_min, int n_max, unsigned long chtype, int mval)
                   1478: {
                   1479:        int i, ret = 0;
                   1480:        char buf[1024];
1.15      jsing    1481:  start:
1.19      jsing    1482:        if (!req_config.batch)
1.1       jsing    1483:                BIO_printf(bio_err, "%s [%s]:", text, def);
                   1484:        (void) BIO_flush(bio_err);
                   1485:        if (value != NULL) {
                   1486:                strlcpy(buf, value, sizeof buf);
                   1487:                strlcat(buf, "\n", sizeof buf);
                   1488:                BIO_printf(bio_err, "%s\n", value);
                   1489:        } else {
                   1490:                buf[0] = '\0';
1.19      jsing    1491:                if (!req_config.batch) {
1.1       jsing    1492:                        if (!fgets(buf, sizeof buf, stdin))
                   1493:                                return 0;
                   1494:                } else {
                   1495:                        buf[0] = '\n';
                   1496:                        buf[1] = '\0';
                   1497:                }
                   1498:        }
                   1499:
                   1500:        if (buf[0] == '\0')
                   1501:                return (0);
                   1502:        else if (buf[0] == '\n') {
                   1503:                if ((def == NULL) || (def[0] == '\0'))
                   1504:                        return (1);
                   1505:                strlcpy(buf, def, sizeof buf);
                   1506:                strlcat(buf, "\n", sizeof buf);
                   1507:        } else if ((buf[0] == '.') && (buf[1] == '\n'))
                   1508:                return (1);
                   1509:
                   1510:        i = strlen(buf);
                   1511:        if (buf[i - 1] != '\n') {
                   1512:                BIO_printf(bio_err, "weird input :-(\n");
                   1513:                return (0);
                   1514:        }
                   1515:        buf[--i] = '\0';
                   1516:        if (!req_check_len(i, n_min, n_max))
                   1517:                goto start;
                   1518:        if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
                   1519:                (unsigned char *) buf, -1, -1, mval))
                   1520:                goto err;
                   1521:        ret = 1;
1.15      jsing    1522:  err:
1.1       jsing    1523:        return (ret);
                   1524: }
                   1525:
                   1526: static int
                   1527: add_attribute_object(X509_REQ * req, char *text, const char *def,
                   1528:     char *value, int nid, int n_min,
                   1529:     int n_max, unsigned long chtype)
                   1530: {
                   1531:        int i;
                   1532:        static char buf[1024];
                   1533:
1.15      jsing    1534:  start:
1.19      jsing    1535:        if (!req_config.batch)
1.1       jsing    1536:                BIO_printf(bio_err, "%s [%s]:", text, def);
                   1537:        (void) BIO_flush(bio_err);
                   1538:        if (value != NULL) {
                   1539:                strlcpy(buf, value, sizeof buf);
                   1540:                strlcat(buf, "\n", sizeof buf);
                   1541:                BIO_printf(bio_err, "%s\n", value);
                   1542:        } else {
                   1543:                buf[0] = '\0';
1.19      jsing    1544:                if (!req_config.batch) {
1.1       jsing    1545:                        if (!fgets(buf, sizeof buf, stdin))
                   1546:                                return 0;
                   1547:                } else {
                   1548:                        buf[0] = '\n';
                   1549:                        buf[1] = '\0';
                   1550:                }
                   1551:        }
                   1552:
                   1553:        if (buf[0] == '\0')
                   1554:                return (0);
                   1555:        else if (buf[0] == '\n') {
                   1556:                if ((def == NULL) || (def[0] == '\0'))
                   1557:                        return (1);
                   1558:                strlcpy(buf, def, sizeof buf);
                   1559:                strlcat(buf, "\n", sizeof buf);
                   1560:        } else if ((buf[0] == '.') && (buf[1] == '\n'))
                   1561:                return (1);
                   1562:
                   1563:        i = strlen(buf);
                   1564:        if (buf[i - 1] != '\n') {
                   1565:                BIO_printf(bio_err, "weird input :-(\n");
                   1566:                return (0);
                   1567:        }
                   1568:        buf[--i] = '\0';
                   1569:        if (!req_check_len(i, n_min, n_max))
                   1570:                goto start;
                   1571:
                   1572:        if (!X509_REQ_add1_attr_by_NID(req, nid, chtype,
                   1573:                (unsigned char *) buf, -1)) {
                   1574:                BIO_printf(bio_err, "Error adding attribute\n");
                   1575:                ERR_print_errors(bio_err);
                   1576:                goto err;
                   1577:        }
                   1578:        return (1);
1.15      jsing    1579:  err:
1.1       jsing    1580:        return (0);
                   1581: }
                   1582:
                   1583: static int
                   1584: req_check_len(int len, int n_min, int n_max)
                   1585: {
                   1586:        if ((n_min > 0) && (len < n_min)) {
                   1587:                BIO_printf(bio_err, "string is too short, it needs to be at least %d bytes long\n", n_min);
                   1588:                return (0);
                   1589:        }
                   1590:        if ((n_max >= 0) && (len > n_max)) {
                   1591:                BIO_printf(bio_err, "string is too long, it needs to be less than  %d bytes long\n", n_max);
                   1592:                return (0);
                   1593:        }
                   1594:        return (1);
                   1595: }
                   1596:
                   1597: /* Check if the end of a string matches 'end' */
                   1598: static int
                   1599: check_end(const char *str, const char *end)
                   1600: {
                   1601:        int elen, slen;
                   1602:        const char *tmp;
                   1603:        elen = strlen(end);
                   1604:        slen = strlen(str);
                   1605:        if (elen > slen)
                   1606:                return 1;
                   1607:        tmp = str + slen - elen;
                   1608:        return strcmp(tmp, end);
                   1609: }
                   1610:
                   1611: static EVP_PKEY_CTX *
                   1612: set_keygen_ctx(BIO * err, const char *gstr, int *pkey_type,
1.7       bcook    1613:     long *pkeylen, char **palgnam)
1.1       jsing    1614: {
                   1615:        EVP_PKEY_CTX *gctx = NULL;
                   1616:        EVP_PKEY *param = NULL;
                   1617:        long keylen = -1;
                   1618:        BIO *pbio = NULL;
                   1619:        const char *paramfile = NULL;
                   1620:        const char *errstr;
                   1621:
                   1622:        if (gstr == NULL) {
                   1623:                *pkey_type = EVP_PKEY_RSA;
                   1624:                keylen = *pkeylen;
                   1625:        } else if (gstr[0] >= '0' && gstr[0] <= '9') {
                   1626:                *pkey_type = EVP_PKEY_RSA;
                   1627:                keylen = strtonum(gstr, 0, LONG_MAX, &errstr);
                   1628:                if (errstr) {
                   1629:                        BIO_printf(err, "bad algorithm %s: %s\n", gstr, errstr);
                   1630:                        return NULL;
                   1631:                }
                   1632:                *pkeylen = keylen;
                   1633:        } else if (!strncmp(gstr, "param:", 6))
                   1634:                paramfile = gstr + 6;
                   1635:        else {
                   1636:                const char *p = strchr(gstr, ':');
                   1637:                int len;
                   1638:                const EVP_PKEY_ASN1_METHOD *ameth;
                   1639:
                   1640:                if (p)
                   1641:                        len = p - gstr;
                   1642:                else
                   1643:                        len = strlen(gstr);
                   1644:
1.7       bcook    1645:                ameth = EVP_PKEY_asn1_find_str(NULL, gstr, len);
1.1       jsing    1646:
                   1647:                if (!ameth) {
                   1648:                        BIO_printf(err, "Unknown algorithm %.*s\n", len, gstr);
                   1649:                        return NULL;
                   1650:                }
                   1651:                EVP_PKEY_asn1_get0_info(NULL, pkey_type, NULL, NULL, NULL,
                   1652:                    ameth);
                   1653:                if (*pkey_type == EVP_PKEY_RSA) {
                   1654:                        if (p) {
                   1655:                                keylen = strtonum(p + 1, 0, LONG_MAX, &errstr);
                   1656:                                if (errstr) {
                   1657:                                        BIO_printf(err, "bad algorithm %s: %s\n",
                   1658:                                            p + 1, errstr);
                   1659:                                        return NULL;
                   1660:                                }
                   1661:                                *pkeylen = keylen;
                   1662:                        } else
                   1663:                                keylen = *pkeylen;
                   1664:                } else if (p)
                   1665:                        paramfile = p + 1;
                   1666:        }
                   1667:
                   1668:        if (paramfile) {
                   1669:                pbio = BIO_new_file(paramfile, "r");
                   1670:                if (!pbio) {
                   1671:                        BIO_printf(err, "Can't open parameter file %s\n",
                   1672:                            paramfile);
                   1673:                        return NULL;
                   1674:                }
                   1675:                param = PEM_read_bio_Parameters(pbio, NULL);
                   1676:
                   1677:                if (!param) {
                   1678:                        X509 *x;
                   1679:                        (void) BIO_reset(pbio);
                   1680:                        x = PEM_read_bio_X509(pbio, NULL, NULL, NULL);
                   1681:                        if (x) {
                   1682:                                param = X509_get_pubkey(x);
                   1683:                                X509_free(x);
                   1684:                        }
                   1685:                }
                   1686:                BIO_free(pbio);
                   1687:
                   1688:                if (!param) {
                   1689:                        BIO_printf(err, "Error reading parameter file %s\n",
                   1690:                            paramfile);
                   1691:                        return NULL;
                   1692:                }
                   1693:                if (*pkey_type == -1)
                   1694:                        *pkey_type = EVP_PKEY_id(param);
                   1695:                else if (*pkey_type != EVP_PKEY_base_id(param)) {
                   1696:                        BIO_printf(err, "Key Type does not match parameters\n");
                   1697:                        EVP_PKEY_free(param);
                   1698:                        return NULL;
                   1699:                }
                   1700:        }
                   1701:        if (palgnam) {
                   1702:                const EVP_PKEY_ASN1_METHOD *ameth;
                   1703:                const char *anam;
1.7       bcook    1704:                ameth = EVP_PKEY_asn1_find(NULL, *pkey_type);
1.1       jsing    1705:                if (!ameth) {
                   1706:                        BIO_puts(err, "Internal error: can't find key algorithm\n");
                   1707:                        return NULL;
                   1708:                }
                   1709:                EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &anam, ameth);
1.4       jsing    1710:                *palgnam = strdup(anam);
1.1       jsing    1711:        }
                   1712:        if (param) {
1.7       bcook    1713:                gctx = EVP_PKEY_CTX_new(param, NULL);
1.1       jsing    1714:                *pkeylen = EVP_PKEY_bits(param);
                   1715:                EVP_PKEY_free(param);
                   1716:        } else
1.7       bcook    1717:                gctx = EVP_PKEY_CTX_new_id(*pkey_type, NULL);
1.1       jsing    1718:
                   1719:        if (!gctx) {
                   1720:                BIO_puts(err, "Error allocating keygen context\n");
                   1721:                ERR_print_errors(err);
                   1722:                return NULL;
                   1723:        }
                   1724:        if (EVP_PKEY_keygen_init(gctx) <= 0) {
                   1725:                BIO_puts(err, "Error initializing keygen context\n");
                   1726:                ERR_print_errors(err);
                   1727:                return NULL;
                   1728:        }
                   1729:        if ((*pkey_type == EVP_PKEY_RSA) && (keylen != -1)) {
                   1730:                if (EVP_PKEY_CTX_set_rsa_keygen_bits(gctx, keylen) <= 0) {
                   1731:                        BIO_puts(err, "Error setting RSA keysize\n");
                   1732:                        ERR_print_errors(err);
                   1733:                        EVP_PKEY_CTX_free(gctx);
                   1734:                        return NULL;
                   1735:                }
                   1736:        }
                   1737:
                   1738:        return gctx;
                   1739: }
                   1740:
                   1741: static int
                   1742: genpkey_cb(EVP_PKEY_CTX * ctx)
                   1743: {
                   1744:        char c = '*';
                   1745:        BIO *b = EVP_PKEY_CTX_get_app_data(ctx);
                   1746:        int p;
                   1747:        p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
                   1748:        if (p == 0)
                   1749:                c = '.';
                   1750:        if (p == 1)
                   1751:                c = '+';
                   1752:        if (p == 2)
                   1753:                c = '*';
                   1754:        if (p == 3)
                   1755:                c = '\n';
                   1756:        BIO_write(b, &c, 1);
                   1757:        (void) BIO_flush(b);
                   1758:        return 1;
                   1759: }
                   1760:
                   1761: static int
                   1762: do_sign_init(BIO * err, EVP_MD_CTX * ctx, EVP_PKEY * pkey,
                   1763:     const EVP_MD * md, STACK_OF(OPENSSL_STRING) * sigopts)
                   1764: {
                   1765:        EVP_PKEY_CTX *pkctx = NULL;
                   1766:        int i;
                   1767:        EVP_MD_CTX_init(ctx);
                   1768:        if (!EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey))
                   1769:                return 0;
                   1770:        for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) {
                   1771:                char *sigopt = sk_OPENSSL_STRING_value(sigopts, i);
                   1772:                if (pkey_ctrl_string(pkctx, sigopt) <= 0) {
                   1773:                        BIO_printf(err, "parameter error \"%s\"\n", sigopt);
                   1774:                        ERR_print_errors(bio_err);
                   1775:                        return 0;
                   1776:                }
                   1777:        }
                   1778:        return 1;
                   1779: }
                   1780:
                   1781: int
                   1782: do_X509_sign(BIO * err, X509 * x, EVP_PKEY * pkey, const EVP_MD * md,
                   1783:     STACK_OF(OPENSSL_STRING) * sigopts)
                   1784: {
                   1785:        int rv;
                   1786:        EVP_MD_CTX mctx;
                   1787:        EVP_MD_CTX_init(&mctx);
                   1788:        rv = do_sign_init(err, &mctx, pkey, md, sigopts);
                   1789:        if (rv > 0)
                   1790:                rv = X509_sign_ctx(x, &mctx);
                   1791:        EVP_MD_CTX_cleanup(&mctx);
                   1792:        return rv > 0 ? 1 : 0;
                   1793: }
                   1794:
                   1795:
                   1796: int
                   1797: do_X509_REQ_sign(BIO * err, X509_REQ * x, EVP_PKEY * pkey, const EVP_MD * md,
                   1798:     STACK_OF(OPENSSL_STRING) * sigopts)
                   1799: {
                   1800:        int rv;
                   1801:        EVP_MD_CTX mctx;
                   1802:        EVP_MD_CTX_init(&mctx);
                   1803:        rv = do_sign_init(err, &mctx, pkey, md, sigopts);
                   1804:        if (rv > 0)
                   1805:                rv = X509_REQ_sign_ctx(x, &mctx);
                   1806:        EVP_MD_CTX_cleanup(&mctx);
                   1807:        return rv > 0 ? 1 : 0;
                   1808: }
                   1809:
                   1810:
                   1811:
                   1812: int
                   1813: do_X509_CRL_sign(BIO * err, X509_CRL * x, EVP_PKEY * pkey, const EVP_MD * md,
                   1814:     STACK_OF(OPENSSL_STRING) * sigopts)
                   1815: {
                   1816:        int rv;
                   1817:        EVP_MD_CTX mctx;
                   1818:        EVP_MD_CTX_init(&mctx);
                   1819:        rv = do_sign_init(err, &mctx, pkey, md, sigopts);
                   1820:        if (rv > 0)
                   1821:                rv = X509_CRL_sign_ctx(x, &mctx);
                   1822:        EVP_MD_CTX_cleanup(&mctx);
                   1823:        return rv > 0 ? 1 : 0;
1.17      inoguchi 1824: }
                   1825:
                   1826: static unsigned long
                   1827: ext_name_hash(const OPENSSL_STRING *a)
                   1828: {
                   1829:        return lh_strhash((const char *)a);
                   1830: }
                   1831:
                   1832: static int
                   1833: ext_name_cmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b)
                   1834: {
                   1835:        return strcmp((const char *)a, (const char *)b);
                   1836: }
                   1837:
                   1838: static void
                   1839: exts_cleanup(OPENSSL_STRING *x)
                   1840: {
                   1841:        free((char *)x);
                   1842: }
                   1843:
                   1844: /*
                   1845:  * Is the |kv| key already duplicated ? This is remarkably tricky to get right.
                   1846:  * Return 0 if unique, -1 on runtime error; 1 if found or a syntax error.
                   1847:  */
                   1848: static int
                   1849: duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv)
                   1850: {
                   1851:        char *p;
                   1852:        size_t off;
                   1853:
                   1854:        /* Check syntax. */
                   1855:        /* Skip leading whitespace, make a copy. */
                   1856:        while (*kv && isspace(*kv))
                   1857:                if (*++kv == '\0')
                   1858:                        return 1;
                   1859:        if ((p = strchr(kv, '=')) == NULL)
                   1860:                return 1;
                   1861:        off = p - kv;
                   1862:        if ((kv = strdup(kv)) == NULL)
                   1863:                return -1;
                   1864:
                   1865:        /* Skip trailing space before the equal sign. */
                   1866:        for (p = kv + off; p > kv; --p)
                   1867:                if (!isspace(p[-1]))
                   1868:                        break;
                   1869:        if (p == kv) {
                   1870:                free(kv);
                   1871:                return 1;
                   1872:        }
                   1873:        *p = '\0';
                   1874:
                   1875:        /* See if "key" is there by attempting to add it. */
                   1876:        if ((p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING*)kv))
                   1877:            != NULL || lh_OPENSSL_STRING_error(addexts)) {
                   1878:                free(p != NULL ? p : kv);
                   1879:                return -1;
                   1880:        }
                   1881:
                   1882:        return 0;
1.1       jsing    1883: }