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

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