155714Skris/* apps/req.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8296341Sdelphij *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15296341Sdelphij *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22296341Sdelphij *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37296341Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40296341Sdelphij *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52296341Sdelphij *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
59296341Sdelphij/*
60296341Sdelphij * Until the key-gen callbacks are modified to use newer prototypes, we allow
61296341Sdelphij * deprecated functions for openssl-internal code
62296341Sdelphij */
63160814Ssimon#ifdef OPENSSL_NO_DEPRECATED
64296341Sdelphij# undef OPENSSL_NO_DEPRECATED
65160814Ssimon#endif
66160814Ssimon
6755714Skris#include <stdio.h>
6855714Skris#include <stdlib.h>
6955714Skris#include <time.h>
7055714Skris#include <string.h>
71109998Smarkm#ifdef OPENSSL_NO_STDIO
72296341Sdelphij# define APPS_WIN16
7355714Skris#endif
7455714Skris#include "apps.h"
7555714Skris#include <openssl/bio.h>
7655714Skris#include <openssl/evp.h>
7755714Skris#include <openssl/conf.h>
7855714Skris#include <openssl/err.h>
7955714Skris#include <openssl/asn1.h>
8055714Skris#include <openssl/x509.h>
8155714Skris#include <openssl/x509v3.h>
8255714Skris#include <openssl/objects.h>
8355714Skris#include <openssl/pem.h>
84160814Ssimon#include <openssl/bn.h>
85160814Ssimon#ifndef OPENSSL_NO_RSA
86296341Sdelphij# include <openssl/rsa.h>
87160814Ssimon#endif
88160814Ssimon#ifndef OPENSSL_NO_DSA
89296341Sdelphij# include <openssl/dsa.h>
90160814Ssimon#endif
9155714Skris
92296341Sdelphij#define SECTION         "req"
9355714Skris
94296341Sdelphij#define BITS            "default_bits"
95296341Sdelphij#define KEYFILE         "default_keyfile"
96296341Sdelphij#define PROMPT          "prompt"
97296341Sdelphij#define DISTINGUISHED_NAME      "distinguished_name"
98296341Sdelphij#define ATTRIBUTES      "attributes"
99296341Sdelphij#define V3_EXTENSIONS   "x509_extensions"
100296341Sdelphij#define REQ_EXTENSIONS  "req_extensions"
101296341Sdelphij#define STRING_MASK     "string_mask"
102296341Sdelphij#define UTF8_IN         "utf8"
10355714Skris
104296341Sdelphij#define DEFAULT_KEY_LENGTH      512
105296341Sdelphij#define MIN_KEY_LENGTH          384
10655714Skris
10755714Skris#undef PROG
108296341Sdelphij#define PROG    req_main
10955714Skris
110296341Sdelphij/*-
111296341Sdelphij * -inform arg  - input format - default PEM (DER or PEM)
11255714Skris * -outform arg - output format - default PEM
113296341Sdelphij * -in arg      - input file - default stdin
114296341Sdelphij * -out arg     - output file - default stdout
115296341Sdelphij * -verify      - check request signature
116296341Sdelphij * -noout       - don't print stuff out.
117296341Sdelphij * -text        - print out human readable text.
118296341Sdelphij * -nodes       - no des encryption
119296341Sdelphij * -config file - Load configuration file.
120296341Sdelphij * -key file    - make a request using key in file (or use it for verification).
121296341Sdelphij * -keyform arg - key file format.
12268651Skris * -rand file(s) - load the file(s) into the PRNG.
123296341Sdelphij * -newkey      - make a key and a request.
124296341Sdelphij * -modulus     - print RSA modulus.
125296341Sdelphij * -pubkey      - output Public Key.
126296341Sdelphij * -x509        - output a self signed X509 structure instead.
127296341Sdelphij * -asn1-kludge - output new certificate request in a format that some CA's
128296341Sdelphij *                require.  This format is wrong
12955714Skris */
13055714Skris
131296341Sdelphijstatic int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *dn, int mutlirdn,
132296341Sdelphij                    int attribs, unsigned long chtype);
133160814Ssimonstatic int build_subject(X509_REQ *req, char *subj, unsigned long chtype,
134296341Sdelphij                         int multirdn);
13559191Skrisstatic int prompt_info(X509_REQ *req,
136296341Sdelphij                       STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect,
137296341Sdelphij                       STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect,
138296341Sdelphij                       int attribs, unsigned long chtype);
13959191Skrisstatic int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *sk,
140296341Sdelphij                     STACK_OF(CONF_VALUE) *attr, int attribs,
141296341Sdelphij                     unsigned long chtype);
142160814Ssimonstatic int add_attribute_object(X509_REQ *req, char *text, const char *def,
143296341Sdelphij                                char *value, int nid, int n_min, int n_max,
144296341Sdelphij                                unsigned long chtype);
145296341Sdelphijstatic int add_DN_object(X509_NAME *n, char *text, const char *def,
146296341Sdelphij                         char *value, int nid, int n_min, int n_max,
147296341Sdelphij                         unsigned long chtype, int mval);
148238405Sjkimstatic int genpkey_cb(EVP_PKEY_CTX *ctx);
149296341Sdelphijstatic int req_check_len(int len, int n_min, int n_max);
150160814Ssimonstatic int check_end(const char *str, const char *end);
151296341Sdelphijstatic EVP_PKEY_CTX *set_keygen_ctx(BIO *err, const char *gstr,
152296341Sdelphij                                    int *pkey_type, long *pkeylen,
153296341Sdelphij                                    char **palgnam, ENGINE *keygen_engine);
15455714Skris#ifndef MONOLITH
155296341Sdelphijstatic char *default_config_file = NULL;
15655714Skris#endif
157296341Sdelphijstatic CONF *req_conf = NULL;
158296341Sdelphijstatic int batch = 0;
15955714Skris
16059191Skrisint MAIN(int, char **);
16159191Skris
16255714Skrisint MAIN(int argc, char **argv)
163296341Sdelphij{
164296341Sdelphij    ENGINE *e = NULL, *gen_eng = NULL;
165296341Sdelphij    unsigned long nmflag = 0, reqflag = 0;
166296341Sdelphij    int ex = 1, x509 = 0, days = 30;
167296341Sdelphij    X509 *x509ss = NULL;
168296341Sdelphij    X509_REQ *req = NULL;
169296341Sdelphij    EVP_PKEY_CTX *genctx = NULL;
170296341Sdelphij    const char *keyalg = NULL;
171296341Sdelphij    char *keyalgstr = NULL;
172296341Sdelphij    STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL;
173296341Sdelphij    EVP_PKEY *pkey = NULL;
174296341Sdelphij    int i = 0, badops = 0, newreq = 0, verbose = 0, pkey_type = -1;
175296341Sdelphij    long newkey = -1;
176296341Sdelphij    BIO *in = NULL, *out = NULL;
177296341Sdelphij    int informat, outformat, verify = 0, noout = 0, text = 0, keyform =
178296341Sdelphij        FORMAT_PEM;
179296341Sdelphij    int nodes = 0, kludge = 0, newhdr = 0, subject = 0, pubkey = 0;
180296341Sdelphij    char *infile, *outfile, *prog, *keyfile = NULL, *template =
181296341Sdelphij        NULL, *keyout = NULL;
182111147Snectar#ifndef OPENSSL_NO_ENGINE
183296341Sdelphij    char *engine = NULL;
184111147Snectar#endif
185296341Sdelphij    char *extensions = NULL;
186296341Sdelphij    char *req_exts = NULL;
187296341Sdelphij    const EVP_CIPHER *cipher = NULL;
188296341Sdelphij    ASN1_INTEGER *serial = NULL;
189296341Sdelphij    int modulus = 0;
190296341Sdelphij    char *inrand = NULL;
191296341Sdelphij    char *passargin = NULL, *passargout = NULL;
192296341Sdelphij    char *passin = NULL, *passout = NULL;
193296341Sdelphij    char *p;
194296341Sdelphij    char *subj = NULL;
195296341Sdelphij    int multirdn = 0;
196296341Sdelphij    const EVP_MD *md_alg = NULL, *digest = NULL;
197296341Sdelphij    unsigned long chtype = MBSTRING_ASC;
19855714Skris#ifndef MONOLITH
199296341Sdelphij    char *to_free;
200296341Sdelphij    long errline;
20155714Skris#endif
20255714Skris
203296341Sdelphij    req_conf = NULL;
204109998Smarkm#ifndef OPENSSL_NO_DES
205296341Sdelphij    cipher = EVP_des_ede3_cbc();
20655714Skris#endif
207296341Sdelphij    apps_startup();
20855714Skris
209296341Sdelphij    if (bio_err == NULL)
210296341Sdelphij        if ((bio_err = BIO_new(BIO_s_file())) != NULL)
211296341Sdelphij            BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
21255714Skris
213296341Sdelphij    infile = NULL;
214296341Sdelphij    outfile = NULL;
215296341Sdelphij    informat = FORMAT_PEM;
216296341Sdelphij    outformat = FORMAT_PEM;
21755714Skris
218296341Sdelphij    prog = argv[0];
219296341Sdelphij    argc--;
220296341Sdelphij    argv++;
221296341Sdelphij    while (argc >= 1) {
222296341Sdelphij        if (strcmp(*argv, "-inform") == 0) {
223296341Sdelphij            if (--argc < 1)
224296341Sdelphij                goto bad;
225296341Sdelphij            informat = str2fmt(*(++argv));
226296341Sdelphij        } else if (strcmp(*argv, "-outform") == 0) {
227296341Sdelphij            if (--argc < 1)
228296341Sdelphij                goto bad;
229296341Sdelphij            outformat = str2fmt(*(++argv));
230296341Sdelphij        }
231111147Snectar#ifndef OPENSSL_NO_ENGINE
232296341Sdelphij        else if (strcmp(*argv, "-engine") == 0) {
233296341Sdelphij            if (--argc < 1)
234296341Sdelphij                goto bad;
235296341Sdelphij            engine = *(++argv);
236296341Sdelphij        } else if (strcmp(*argv, "-keygen_engine") == 0) {
237296341Sdelphij            if (--argc < 1)
238296341Sdelphij                goto bad;
239296341Sdelphij            gen_eng = ENGINE_by_id(*(++argv));
240296341Sdelphij            if (gen_eng == NULL) {
241296341Sdelphij                BIO_printf(bio_err, "Can't find keygen engine %s\n", *argv);
242296341Sdelphij                goto end;
243296341Sdelphij            }
244296341Sdelphij        }
245111147Snectar#endif
246296341Sdelphij        else if (strcmp(*argv, "-key") == 0) {
247296341Sdelphij            if (--argc < 1)
248296341Sdelphij                goto bad;
249296341Sdelphij            keyfile = *(++argv);
250296341Sdelphij        } else if (strcmp(*argv, "-pubkey") == 0) {
251296341Sdelphij            pubkey = 1;
252296341Sdelphij        } else if (strcmp(*argv, "-new") == 0) {
253296341Sdelphij            newreq = 1;
254296341Sdelphij        } else if (strcmp(*argv, "-config") == 0) {
255296341Sdelphij            if (--argc < 1)
256296341Sdelphij                goto bad;
257296341Sdelphij            template = *(++argv);
258296341Sdelphij        } else if (strcmp(*argv, "-keyform") == 0) {
259296341Sdelphij            if (--argc < 1)
260296341Sdelphij                goto bad;
261296341Sdelphij            keyform = str2fmt(*(++argv));
262296341Sdelphij        } else if (strcmp(*argv, "-in") == 0) {
263296341Sdelphij            if (--argc < 1)
264296341Sdelphij                goto bad;
265296341Sdelphij            infile = *(++argv);
266296341Sdelphij        } else if (strcmp(*argv, "-out") == 0) {
267296341Sdelphij            if (--argc < 1)
268296341Sdelphij                goto bad;
269296341Sdelphij            outfile = *(++argv);
270296341Sdelphij        } else if (strcmp(*argv, "-keyout") == 0) {
271296341Sdelphij            if (--argc < 1)
272296341Sdelphij                goto bad;
273296341Sdelphij            keyout = *(++argv);
274296341Sdelphij        } else if (strcmp(*argv, "-passin") == 0) {
275296341Sdelphij            if (--argc < 1)
276296341Sdelphij                goto bad;
277296341Sdelphij            passargin = *(++argv);
278296341Sdelphij        } else if (strcmp(*argv, "-passout") == 0) {
279296341Sdelphij            if (--argc < 1)
280296341Sdelphij                goto bad;
281296341Sdelphij            passargout = *(++argv);
282296341Sdelphij        } else if (strcmp(*argv, "-rand") == 0) {
283296341Sdelphij            if (--argc < 1)
284296341Sdelphij                goto bad;
285296341Sdelphij            inrand = *(++argv);
286296341Sdelphij        } else if (strcmp(*argv, "-newkey") == 0) {
287296341Sdelphij            if (--argc < 1)
288296341Sdelphij                goto bad;
289296341Sdelphij            keyalg = *(++argv);
290296341Sdelphij            newreq = 1;
291296341Sdelphij        } else if (strcmp(*argv, "-pkeyopt") == 0) {
292296341Sdelphij            if (--argc < 1)
293296341Sdelphij                goto bad;
294296341Sdelphij            if (!pkeyopts)
295296341Sdelphij                pkeyopts = sk_OPENSSL_STRING_new_null();
296296341Sdelphij            if (!pkeyopts || !sk_OPENSSL_STRING_push(pkeyopts, *(++argv)))
297296341Sdelphij                goto bad;
298296341Sdelphij        } else if (strcmp(*argv, "-sigopt") == 0) {
299296341Sdelphij            if (--argc < 1)
300296341Sdelphij                goto bad;
301296341Sdelphij            if (!sigopts)
302296341Sdelphij                sigopts = sk_OPENSSL_STRING_new_null();
303296341Sdelphij            if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
304296341Sdelphij                goto bad;
305296341Sdelphij        } else if (strcmp(*argv, "-batch") == 0)
306296341Sdelphij            batch = 1;
307296341Sdelphij        else if (strcmp(*argv, "-newhdr") == 0)
308296341Sdelphij            newhdr = 1;
309296341Sdelphij        else if (strcmp(*argv, "-modulus") == 0)
310296341Sdelphij            modulus = 1;
311296341Sdelphij        else if (strcmp(*argv, "-verify") == 0)
312296341Sdelphij            verify = 1;
313296341Sdelphij        else if (strcmp(*argv, "-nodes") == 0)
314296341Sdelphij            nodes = 1;
315296341Sdelphij        else if (strcmp(*argv, "-noout") == 0)
316296341Sdelphij            noout = 1;
317296341Sdelphij        else if (strcmp(*argv, "-verbose") == 0)
318296341Sdelphij            verbose = 1;
319296341Sdelphij        else if (strcmp(*argv, "-utf8") == 0)
320296341Sdelphij            chtype = MBSTRING_UTF8;
321296341Sdelphij        else if (strcmp(*argv, "-nameopt") == 0) {
322296341Sdelphij            if (--argc < 1)
323296341Sdelphij                goto bad;
324296341Sdelphij            if (!set_name_ex(&nmflag, *(++argv)))
325296341Sdelphij                goto bad;
326296341Sdelphij        } else if (strcmp(*argv, "-reqopt") == 0) {
327296341Sdelphij            if (--argc < 1)
328296341Sdelphij                goto bad;
329296341Sdelphij            if (!set_cert_ex(&reqflag, *(++argv)))
330296341Sdelphij                goto bad;
331296341Sdelphij        } else if (strcmp(*argv, "-subject") == 0)
332296341Sdelphij            subject = 1;
333296341Sdelphij        else if (strcmp(*argv, "-text") == 0)
334296341Sdelphij            text = 1;
335296341Sdelphij        else if (strcmp(*argv, "-x509") == 0)
336296341Sdelphij            x509 = 1;
337296341Sdelphij        else if (strcmp(*argv, "-asn1-kludge") == 0)
338296341Sdelphij            kludge = 1;
339296341Sdelphij        else if (strcmp(*argv, "-no-asn1-kludge") == 0)
340296341Sdelphij            kludge = 0;
341296341Sdelphij        else if (strcmp(*argv, "-subj") == 0) {
342296341Sdelphij            if (--argc < 1)
343296341Sdelphij                goto bad;
344296341Sdelphij            subj = *(++argv);
345296341Sdelphij        } else if (strcmp(*argv, "-multivalue-rdn") == 0)
346296341Sdelphij            multirdn = 1;
347296341Sdelphij        else if (strcmp(*argv, "-days") == 0) {
348296341Sdelphij            if (--argc < 1)
349296341Sdelphij                goto bad;
350296341Sdelphij            days = atoi(*(++argv));
351296341Sdelphij            if (days == 0)
352296341Sdelphij                days = 30;
353296341Sdelphij        } else if (strcmp(*argv, "-set_serial") == 0) {
354296341Sdelphij            if (--argc < 1)
355296341Sdelphij                goto bad;
356296341Sdelphij            serial = s2i_ASN1_INTEGER(NULL, *(++argv));
357296341Sdelphij            if (!serial)
358296341Sdelphij                goto bad;
359296341Sdelphij        } else if (strcmp(*argv, "-extensions") == 0) {
360296341Sdelphij            if (--argc < 1)
361296341Sdelphij                goto bad;
362296341Sdelphij            extensions = *(++argv);
363296341Sdelphij        } else if (strcmp(*argv, "-reqexts") == 0) {
364296341Sdelphij            if (--argc < 1)
365296341Sdelphij                goto bad;
366296341Sdelphij            req_exts = *(++argv);
367296341Sdelphij        } else if ((md_alg = EVP_get_digestbyname(&((*argv)[1]))) != NULL) {
368296341Sdelphij            /* ok */
369296341Sdelphij            digest = md_alg;
370296341Sdelphij        } else {
371296341Sdelphij            BIO_printf(bio_err, "unknown option %s\n", *argv);
372296341Sdelphij            badops = 1;
373296341Sdelphij            break;
374296341Sdelphij        }
375296341Sdelphij        argc--;
376296341Sdelphij        argv++;
377296341Sdelphij    }
37855714Skris
379296341Sdelphij    if (badops) {
380296341Sdelphij bad:
381296341Sdelphij        BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog);
382296341Sdelphij        BIO_printf(bio_err, "where options  are\n");
383296341Sdelphij        BIO_printf(bio_err, " -inform arg    input format - DER or PEM\n");
384296341Sdelphij        BIO_printf(bio_err, " -outform arg   output format - DER or PEM\n");
385296341Sdelphij        BIO_printf(bio_err, " -in arg        input file\n");
386296341Sdelphij        BIO_printf(bio_err, " -out arg       output file\n");
387296341Sdelphij        BIO_printf(bio_err, " -text          text form of request\n");
388296341Sdelphij        BIO_printf(bio_err, " -pubkey        output public key\n");
389296341Sdelphij        BIO_printf(bio_err, " -noout         do not output REQ\n");
390296341Sdelphij        BIO_printf(bio_err, " -verify        verify signature on REQ\n");
391296341Sdelphij        BIO_printf(bio_err, " -modulus       RSA modulus\n");
392296341Sdelphij        BIO_printf(bio_err, " -nodes         don't encrypt the output key\n");
393111147Snectar#ifndef OPENSSL_NO_ENGINE
394296341Sdelphij        BIO_printf(bio_err,
395296341Sdelphij                   " -engine e      use engine e, possibly a hardware device\n");
396111147Snectar#endif
397296341Sdelphij        BIO_printf(bio_err, " -subject       output the request's subject\n");
398296341Sdelphij        BIO_printf(bio_err, " -passin        private key password source\n");
399296341Sdelphij        BIO_printf(bio_err,
400296341Sdelphij                   " -key file      use the private key contained in file\n");
401296341Sdelphij        BIO_printf(bio_err, " -keyform arg   key file format\n");
402296341Sdelphij        BIO_printf(bio_err, " -keyout arg    file to send the key to\n");
403296341Sdelphij        BIO_printf(bio_err, " -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR,
404296341Sdelphij                   LIST_SEPARATOR_CHAR);
405296341Sdelphij        BIO_printf(bio_err,
406296341Sdelphij                   "                load the file (or the files in the directory) into\n");
407296341Sdelphij        BIO_printf(bio_err, "                the random number generator\n");
408296341Sdelphij        BIO_printf(bio_err,
409296341Sdelphij                   " -newkey rsa:bits generate a new RSA key of 'bits' in size\n");
410296341Sdelphij        BIO_printf(bio_err,
411296341Sdelphij                   " -newkey dsa:file generate a new DSA key, parameters taken from CA in 'file'\n");
412160814Ssimon#ifndef OPENSSL_NO_ECDSA
413296341Sdelphij        BIO_printf(bio_err,
414296341Sdelphij                   " -newkey ec:file generate a new EC key, parameters taken from CA in 'file'\n");
415160814Ssimon#endif
416296341Sdelphij        BIO_printf(bio_err,
417296341Sdelphij                   " -[digest]      Digest to sign with (md5, sha1, md2, mdc2, md4)\n");
418296341Sdelphij        BIO_printf(bio_err, " -config file   request template file.\n");
419296341Sdelphij        BIO_printf(bio_err,
420296341Sdelphij                   " -subj arg      set or modify request subject\n");
421296341Sdelphij        BIO_printf(bio_err,
422296341Sdelphij                   " -multivalue-rdn enable support for multivalued RDNs\n");
423296341Sdelphij        BIO_printf(bio_err, " -new           new request.\n");
424296341Sdelphij        BIO_printf(bio_err,
425296341Sdelphij                   " -batch         do not ask anything during request generation\n");
426296341Sdelphij        BIO_printf(bio_err,
427296341Sdelphij                   " -x509          output a x509 structure instead of a cert. req.\n");
428296341Sdelphij        BIO_printf(bio_err,
429296341Sdelphij                   " -days          number of days a certificate generated by -x509 is valid for.\n");
430296341Sdelphij        BIO_printf(bio_err,
431296341Sdelphij                   " -set_serial    serial number to use for a certificate generated by -x509.\n");
432296341Sdelphij        BIO_printf(bio_err,
433296341Sdelphij                   " -newhdr        output \"NEW\" in the header lines\n");
434296341Sdelphij        BIO_printf(bio_err,
435296341Sdelphij                   " -asn1-kludge   Output the 'request' in a format that is wrong but some CA's\n");
436296341Sdelphij        BIO_printf(bio_err,
437296341Sdelphij                   "                have been reported as requiring\n");
438296341Sdelphij        BIO_printf(bio_err,
439296341Sdelphij                   " -extensions .. specify certificate extension section (override value in config file)\n");
440296341Sdelphij        BIO_printf(bio_err,
441296341Sdelphij                   " -reqexts ..    specify request extension section (override value in config file)\n");
442296341Sdelphij        BIO_printf(bio_err,
443296341Sdelphij                   " -utf8          input characters are UTF8 (default ASCII)\n");
444296341Sdelphij        BIO_printf(bio_err,
445296341Sdelphij                   " -nameopt arg    - various certificate name options\n");
446296341Sdelphij        BIO_printf(bio_err,
447296341Sdelphij                   " -reqopt arg    - various request text options\n\n");
448296341Sdelphij        goto end;
449296341Sdelphij    }
45055714Skris
451296341Sdelphij    ERR_load_crypto_strings();
452296341Sdelphij    if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
453296341Sdelphij        BIO_printf(bio_err, "Error getting passwords\n");
454296341Sdelphij        goto end;
455296341Sdelphij    }
456296341Sdelphij#ifndef MONOLITH                /* else this has happened in openssl.c
457296341Sdelphij                                 * (global `config') */
458296341Sdelphij    /* Lets load up our environment a little */
459296341Sdelphij    p = getenv("OPENSSL_CONF");
460296341Sdelphij    if (p == NULL)
461296341Sdelphij        p = getenv("SSLEAY_CONF");
462296341Sdelphij    if (p == NULL)
463296341Sdelphij        p = to_free = make_config_name();
464296341Sdelphij    default_config_file = p;
465296341Sdelphij    config = NCONF_new(NULL);
466296341Sdelphij    i = NCONF_load(config, p, &errline);
46755714Skris#endif
46855714Skris
469296341Sdelphij    if (template != NULL) {
470296341Sdelphij        long errline = -1;
47155714Skris
472296341Sdelphij        if (verbose)
473296341Sdelphij            BIO_printf(bio_err, "Using configuration from %s\n", template);
474296341Sdelphij        req_conf = NCONF_new(NULL);
475296341Sdelphij        i = NCONF_load(req_conf, template, &errline);
476296341Sdelphij        if (i == 0) {
477296341Sdelphij            BIO_printf(bio_err, "error on line %ld of %s\n", errline,
478296341Sdelphij                       template);
479296341Sdelphij            goto end;
480296341Sdelphij        }
481296341Sdelphij    } else {
482296341Sdelphij        req_conf = config;
483160814Ssimon
484296341Sdelphij        if (req_conf == NULL) {
485296341Sdelphij            BIO_printf(bio_err, "Unable to load config info from %s\n",
486296341Sdelphij                       default_config_file);
487296341Sdelphij            if (newreq)
488296341Sdelphij                goto end;
489296341Sdelphij        } else if (verbose)
490296341Sdelphij            BIO_printf(bio_err, "Using configuration from %s\n",
491296341Sdelphij                       default_config_file);
492296341Sdelphij    }
49355714Skris
494296341Sdelphij    if (req_conf != NULL) {
495296341Sdelphij        if (!load_config(bio_err, req_conf))
496296341Sdelphij            goto end;
497296341Sdelphij        p = NCONF_get_string(req_conf, NULL, "oid_file");
498296341Sdelphij        if (p == NULL)
499296341Sdelphij            ERR_clear_error();
500296341Sdelphij        if (p != NULL) {
501296341Sdelphij            BIO *oid_bio;
50255714Skris
503296341Sdelphij            oid_bio = BIO_new_file(p, "r");
504296341Sdelphij            if (oid_bio == NULL) {
505296341Sdelphij                /*-
506296341Sdelphij                BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
507296341Sdelphij                ERR_print_errors(bio_err);
508296341Sdelphij                */
509296341Sdelphij            } else {
510296341Sdelphij                OBJ_create_objects(oid_bio);
511296341Sdelphij                BIO_free(oid_bio);
512296341Sdelphij            }
513296341Sdelphij        }
514296341Sdelphij    }
515296341Sdelphij    if (!add_oid_section(bio_err, req_conf))
516296341Sdelphij        goto end;
51755714Skris
518296341Sdelphij    if (md_alg == NULL) {
519296341Sdelphij        p = NCONF_get_string(req_conf, SECTION, "default_md");
520296341Sdelphij        if (p == NULL)
521296341Sdelphij            ERR_clear_error();
522296341Sdelphij        if (p != NULL) {
523296341Sdelphij            if ((md_alg = EVP_get_digestbyname(p)) != NULL)
524296341Sdelphij                digest = md_alg;
525296341Sdelphij        }
526296341Sdelphij    }
52755714Skris
528296341Sdelphij    if (!extensions) {
529296341Sdelphij        extensions = NCONF_get_string(req_conf, SECTION, V3_EXTENSIONS);
530296341Sdelphij        if (!extensions)
531296341Sdelphij            ERR_clear_error();
532296341Sdelphij    }
533296341Sdelphij    if (extensions) {
534296341Sdelphij        /* Check syntax of file */
535296341Sdelphij        X509V3_CTX ctx;
536296341Sdelphij        X509V3_set_ctx_test(&ctx);
537296341Sdelphij        X509V3_set_nconf(&ctx, req_conf);
538296341Sdelphij        if (!X509V3_EXT_add_nconf(req_conf, &ctx, extensions, NULL)) {
539296341Sdelphij            BIO_printf(bio_err,
540296341Sdelphij                       "Error Loading extension section %s\n", extensions);
541296341Sdelphij            goto end;
542296341Sdelphij        }
543296341Sdelphij    }
54455714Skris
545296341Sdelphij    if (!passin) {
546296341Sdelphij        passin = NCONF_get_string(req_conf, SECTION, "input_password");
547296341Sdelphij        if (!passin)
548296341Sdelphij            ERR_clear_error();
549296341Sdelphij    }
55059191Skris
551296341Sdelphij    if (!passout) {
552296341Sdelphij        passout = NCONF_get_string(req_conf, SECTION, "output_password");
553296341Sdelphij        if (!passout)
554296341Sdelphij            ERR_clear_error();
555296341Sdelphij    }
55659191Skris
557296341Sdelphij    p = NCONF_get_string(req_conf, SECTION, STRING_MASK);
558296341Sdelphij    if (!p)
559296341Sdelphij        ERR_clear_error();
56059191Skris
561296341Sdelphij    if (p && !ASN1_STRING_set_default_mask_asc(p)) {
562296341Sdelphij        BIO_printf(bio_err, "Invalid global string mask setting %s\n", p);
563296341Sdelphij        goto end;
564296341Sdelphij    }
565109998Smarkm
566296341Sdelphij    if (chtype != MBSTRING_UTF8) {
567296341Sdelphij        p = NCONF_get_string(req_conf, SECTION, UTF8_IN);
568296341Sdelphij        if (!p)
569296341Sdelphij            ERR_clear_error();
570296341Sdelphij        else if (!strcmp(p, "yes"))
571296341Sdelphij            chtype = MBSTRING_UTF8;
572296341Sdelphij    }
573109998Smarkm
574296341Sdelphij    if (!req_exts) {
575296341Sdelphij        req_exts = NCONF_get_string(req_conf, SECTION, REQ_EXTENSIONS);
576296341Sdelphij        if (!req_exts)
577296341Sdelphij            ERR_clear_error();
578296341Sdelphij    }
579296341Sdelphij    if (req_exts) {
580296341Sdelphij        /* Check syntax of file */
581296341Sdelphij        X509V3_CTX ctx;
582296341Sdelphij        X509V3_set_ctx_test(&ctx);
583296341Sdelphij        X509V3_set_nconf(&ctx, req_conf);
584296341Sdelphij        if (!X509V3_EXT_add_nconf(req_conf, &ctx, req_exts, NULL)) {
585296341Sdelphij            BIO_printf(bio_err,
586296341Sdelphij                       "Error Loading request extension section %s\n",
587296341Sdelphij                       req_exts);
588296341Sdelphij            goto end;
589296341Sdelphij        }
590296341Sdelphij    }
59159191Skris
592296341Sdelphij    in = BIO_new(BIO_s_file());
593296341Sdelphij    out = BIO_new(BIO_s_file());
594296341Sdelphij    if ((in == NULL) || (out == NULL))
595296341Sdelphij        goto end;
59655714Skris
597111147Snectar#ifndef OPENSSL_NO_ENGINE
598296341Sdelphij    e = setup_engine(bio_err, engine, 0);
599111147Snectar#endif
600109998Smarkm
601296341Sdelphij    if (keyfile != NULL) {
602296341Sdelphij        pkey = load_key(bio_err, keyfile, keyform, 0, passin, e,
603296341Sdelphij                        "Private Key");
604296341Sdelphij        if (!pkey) {
605296341Sdelphij            /*
606296341Sdelphij             * load_key() has already printed an appropriate message
607296341Sdelphij             */
608296341Sdelphij            goto end;
609296341Sdelphij        } else {
610296341Sdelphij            char *randfile = NCONF_get_string(req_conf, SECTION, "RANDFILE");
611296341Sdelphij            if (randfile == NULL)
612296341Sdelphij                ERR_clear_error();
613296341Sdelphij            app_RAND_load_file(randfile, bio_err, 0);
614296341Sdelphij        }
615296341Sdelphij    }
61655714Skris
617296341Sdelphij    if (newreq && (pkey == NULL)) {
618296341Sdelphij        char *randfile = NCONF_get_string(req_conf, SECTION, "RANDFILE");
619296341Sdelphij        if (randfile == NULL)
620296341Sdelphij            ERR_clear_error();
621296341Sdelphij        app_RAND_load_file(randfile, bio_err, 0);
622296341Sdelphij        if (inrand)
623296341Sdelphij            app_RAND_load_files(inrand);
624238405Sjkim
625296341Sdelphij        if (!NCONF_get_number(req_conf, SECTION, BITS, &newkey)) {
626296341Sdelphij            newkey = DEFAULT_KEY_LENGTH;
627296341Sdelphij        }
628264331Sjkim
629296341Sdelphij        if (keyalg) {
630296341Sdelphij            genctx = set_keygen_ctx(bio_err, keyalg, &pkey_type, &newkey,
631296341Sdelphij                                    &keyalgstr, gen_eng);
632296341Sdelphij            if (!genctx)
633296341Sdelphij                goto end;
634296341Sdelphij        }
63555714Skris
636296341Sdelphij        if (newkey < MIN_KEY_LENGTH
637296341Sdelphij            && (pkey_type == EVP_PKEY_RSA || pkey_type == EVP_PKEY_DSA)) {
638296341Sdelphij            BIO_printf(bio_err, "private key length is too short,\n");
639296341Sdelphij            BIO_printf(bio_err, "it needs to be at least %d bits, not %ld\n",
640296341Sdelphij                       MIN_KEY_LENGTH, newkey);
641296341Sdelphij            goto end;
642296341Sdelphij        }
64355714Skris
644296341Sdelphij        if (!genctx) {
645296341Sdelphij            genctx = set_keygen_ctx(bio_err, NULL, &pkey_type, &newkey,
646296341Sdelphij                                    &keyalgstr, gen_eng);
647296341Sdelphij            if (!genctx)
648296341Sdelphij                goto end;
649296341Sdelphij        }
650238405Sjkim
651296341Sdelphij        if (pkeyopts) {
652296341Sdelphij            char *genopt;
653296341Sdelphij            for (i = 0; i < sk_OPENSSL_STRING_num(pkeyopts); i++) {
654296341Sdelphij                genopt = sk_OPENSSL_STRING_value(pkeyopts, i);
655296341Sdelphij                if (pkey_ctrl_string(genctx, genopt) <= 0) {
656296341Sdelphij                    BIO_printf(bio_err, "parameter error \"%s\"\n", genopt);
657296341Sdelphij                    ERR_print_errors(bio_err);
658296341Sdelphij                    goto end;
659296341Sdelphij                }
660296341Sdelphij            }
661296341Sdelphij        }
662238405Sjkim
663296341Sdelphij        BIO_printf(bio_err, "Generating a %ld bit %s private key\n",
664296341Sdelphij                   newkey, keyalgstr);
665238405Sjkim
666296341Sdelphij        EVP_PKEY_CTX_set_cb(genctx, genpkey_cb);
667296341Sdelphij        EVP_PKEY_CTX_set_app_data(genctx, bio_err);
66855714Skris
669296341Sdelphij        if (EVP_PKEY_keygen(genctx, &pkey) <= 0) {
670296341Sdelphij            BIO_puts(bio_err, "Error Generating Key\n");
671296341Sdelphij            goto end;
672296341Sdelphij        }
673238405Sjkim
674296341Sdelphij        EVP_PKEY_CTX_free(genctx);
675296341Sdelphij        genctx = NULL;
67655714Skris
677296341Sdelphij        app_RAND_write_file(randfile, bio_err);
678296341Sdelphij
679296341Sdelphij        if (keyout == NULL) {
680296341Sdelphij            keyout = NCONF_get_string(req_conf, SECTION, KEYFILE);
681296341Sdelphij            if (keyout == NULL)
682296341Sdelphij                ERR_clear_error();
683296341Sdelphij        }
684296341Sdelphij
685296341Sdelphij        if (keyout == NULL) {
686296341Sdelphij            BIO_printf(bio_err, "writing new private key to stdout\n");
687296341Sdelphij            BIO_set_fp(out, stdout, BIO_NOCLOSE);
688109998Smarkm#ifdef OPENSSL_SYS_VMS
689296341Sdelphij            {
690296341Sdelphij                BIO *tmpbio = BIO_new(BIO_f_linebuffer());
691296341Sdelphij                out = BIO_push(tmpbio, out);
692296341Sdelphij            }
69368651Skris#endif
694296341Sdelphij        } else {
695296341Sdelphij            BIO_printf(bio_err, "writing new private key to '%s'\n", keyout);
696296341Sdelphij            if (BIO_write_filename(out, keyout) <= 0) {
697296341Sdelphij                perror(keyout);
698296341Sdelphij                goto end;
699296341Sdelphij            }
700296341Sdelphij        }
70155714Skris
702296341Sdelphij        p = NCONF_get_string(req_conf, SECTION, "encrypt_rsa_key");
703296341Sdelphij        if (p == NULL) {
704296341Sdelphij            ERR_clear_error();
705296341Sdelphij            p = NCONF_get_string(req_conf, SECTION, "encrypt_key");
706296341Sdelphij            if (p == NULL)
707296341Sdelphij                ERR_clear_error();
708296341Sdelphij        }
709296341Sdelphij        if ((p != NULL) && (strcmp(p, "no") == 0))
710296341Sdelphij            cipher = NULL;
711296341Sdelphij        if (nodes)
712296341Sdelphij            cipher = NULL;
71355714Skris
714296341Sdelphij        i = 0;
715296341Sdelphij loop:
716296341Sdelphij        if (!PEM_write_bio_PrivateKey(out, pkey, cipher,
717296341Sdelphij                                      NULL, 0, NULL, passout)) {
718296341Sdelphij            if ((ERR_GET_REASON(ERR_peek_error()) ==
719296341Sdelphij                 PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3)) {
720296341Sdelphij                ERR_clear_error();
721296341Sdelphij                i++;
722296341Sdelphij                goto loop;
723296341Sdelphij            }
724296341Sdelphij            goto end;
725296341Sdelphij        }
726296341Sdelphij        BIO_printf(bio_err, "-----\n");
727296341Sdelphij    }
72855714Skris
729296341Sdelphij    if (!newreq) {
730296341Sdelphij        /*
731296341Sdelphij         * Since we are using a pre-existing certificate request, the kludge
732296341Sdelphij         * 'format' info should not be changed.
733296341Sdelphij         */
734296341Sdelphij        kludge = -1;
735296341Sdelphij        if (infile == NULL)
736296341Sdelphij            BIO_set_fp(in, stdin, BIO_NOCLOSE);
737296341Sdelphij        else {
738296341Sdelphij            if (BIO_read_filename(in, infile) <= 0) {
739296341Sdelphij                perror(infile);
740296341Sdelphij                goto end;
741296341Sdelphij            }
742296341Sdelphij        }
74355714Skris
744296341Sdelphij        if (informat == FORMAT_ASN1)
745296341Sdelphij            req = d2i_X509_REQ_bio(in, NULL);
746296341Sdelphij        else if (informat == FORMAT_PEM)
747296341Sdelphij            req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
748296341Sdelphij        else {
749296341Sdelphij            BIO_printf(bio_err,
750296341Sdelphij                       "bad input format specified for X509 request\n");
751296341Sdelphij            goto end;
752296341Sdelphij        }
753296341Sdelphij        if (req == NULL) {
754296341Sdelphij            BIO_printf(bio_err, "unable to load X509 request\n");
755296341Sdelphij            goto end;
756296341Sdelphij        }
757296341Sdelphij    }
758238405Sjkim
759296341Sdelphij    if (newreq || x509) {
760296341Sdelphij        if (pkey == NULL) {
761296341Sdelphij            BIO_printf(bio_err, "you need to specify a private key\n");
762296341Sdelphij            goto end;
763296341Sdelphij        }
76455714Skris
765296341Sdelphij        if (req == NULL) {
766296341Sdelphij            req = X509_REQ_new();
767296341Sdelphij            if (req == NULL) {
768296341Sdelphij                goto end;
769296341Sdelphij            }
77055714Skris
771296341Sdelphij            i = make_REQ(req, pkey, subj, multirdn, !x509, chtype);
772296341Sdelphij            subj = NULL;        /* done processing '-subj' option */
773296341Sdelphij            if ((kludge > 0)
774296341Sdelphij                && !sk_X509_ATTRIBUTE_num(req->req_info->attributes)) {
775296341Sdelphij                sk_X509_ATTRIBUTE_free(req->req_info->attributes);
776296341Sdelphij                req->req_info->attributes = NULL;
777296341Sdelphij            }
778296341Sdelphij            if (!i) {
779296341Sdelphij                BIO_printf(bio_err, "problems making Certificate Request\n");
780296341Sdelphij                goto end;
781296341Sdelphij            }
782296341Sdelphij        }
783296341Sdelphij        if (x509) {
784296341Sdelphij            EVP_PKEY *tmppkey;
785296341Sdelphij            X509V3_CTX ext_ctx;
786296341Sdelphij            if ((x509ss = X509_new()) == NULL)
787296341Sdelphij                goto end;
78855714Skris
789296341Sdelphij            /* Set version to V3 */
790296341Sdelphij            if (extensions && !X509_set_version(x509ss, 2))
791296341Sdelphij                goto end;
792296341Sdelphij            if (serial) {
793296341Sdelphij                if (!X509_set_serialNumber(x509ss, serial))
794296341Sdelphij                    goto end;
795296341Sdelphij            } else {
796296341Sdelphij                if (!rand_serial(NULL, X509_get_serialNumber(x509ss)))
797296341Sdelphij                    goto end;
798296341Sdelphij            }
79955714Skris
800296341Sdelphij            if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req)))
801296341Sdelphij                goto end;
802296341Sdelphij            if (!X509_gmtime_adj(X509_get_notBefore(x509ss), 0))
803296341Sdelphij                goto end;
804296341Sdelphij            if (!X509_time_adj_ex(X509_get_notAfter(x509ss), days, 0, NULL))
805296341Sdelphij                goto end;
806296341Sdelphij            if (!X509_set_subject_name
807296341Sdelphij                (x509ss, X509_REQ_get_subject_name(req)))
808296341Sdelphij                goto end;
809296341Sdelphij            tmppkey = X509_REQ_get_pubkey(req);
810296341Sdelphij            if (!tmppkey || !X509_set_pubkey(x509ss, tmppkey))
811296341Sdelphij                goto end;
812296341Sdelphij            EVP_PKEY_free(tmppkey);
81355714Skris
814296341Sdelphij            /* Set up V3 context struct */
81555714Skris
816296341Sdelphij            X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0);
817296341Sdelphij            X509V3_set_nconf(&ext_ctx, req_conf);
818238405Sjkim
819296341Sdelphij            /* Add extensions */
820296341Sdelphij            if (extensions && !X509V3_EXT_add_nconf(req_conf,
821296341Sdelphij                                                    &ext_ctx, extensions,
822296341Sdelphij                                                    x509ss)) {
823296341Sdelphij                BIO_printf(bio_err, "Error Loading extension section %s\n",
824296341Sdelphij                           extensions);
825296341Sdelphij                goto end;
826296341Sdelphij            }
82759191Skris
828296341Sdelphij            i = do_X509_sign(bio_err, x509ss, pkey, digest, sigopts);
829296341Sdelphij            if (!i) {
830296341Sdelphij                ERR_print_errors(bio_err);
831296341Sdelphij                goto end;
832296341Sdelphij            }
833296341Sdelphij        } else {
834296341Sdelphij            X509V3_CTX ext_ctx;
83559191Skris
836296341Sdelphij            /* Set up V3 context struct */
83759191Skris
838296341Sdelphij            X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0);
839296341Sdelphij            X509V3_set_nconf(&ext_ctx, req_conf);
84055714Skris
841296341Sdelphij            /* Add extensions */
842296341Sdelphij            if (req_exts && !X509V3_EXT_REQ_add_nconf(req_conf,
843296341Sdelphij                                                      &ext_ctx, req_exts,
844296341Sdelphij                                                      req)) {
845296341Sdelphij                BIO_printf(bio_err, "Error Loading extension section %s\n",
846296341Sdelphij                           req_exts);
847296341Sdelphij                goto end;
848296341Sdelphij            }
849296341Sdelphij            i = do_X509_REQ_sign(bio_err, req, pkey, digest, sigopts);
850296341Sdelphij            if (!i) {
851296341Sdelphij                ERR_print_errors(bio_err);
852296341Sdelphij                goto end;
853296341Sdelphij            }
854296341Sdelphij        }
855296341Sdelphij    }
856109998Smarkm
857296341Sdelphij    if (subj && x509) {
858296341Sdelphij        BIO_printf(bio_err, "Cannot modifiy certificate subject\n");
859296341Sdelphij        goto end;
860296341Sdelphij    }
861109998Smarkm
862296341Sdelphij    if (subj && !x509) {
863296341Sdelphij        if (verbose) {
864296341Sdelphij            BIO_printf(bio_err, "Modifying Request's Subject\n");
865296341Sdelphij            print_name(bio_err, "old subject=",
866296341Sdelphij                       X509_REQ_get_subject_name(req), nmflag);
867296341Sdelphij        }
868109998Smarkm
869296341Sdelphij        if (build_subject(req, subj, chtype, multirdn) == 0) {
870296341Sdelphij            BIO_printf(bio_err, "ERROR: cannot modify subject\n");
871296341Sdelphij            ex = 1;
872296341Sdelphij            goto end;
873296341Sdelphij        }
874109998Smarkm
875296341Sdelphij        req->req_info->enc.modified = 1;
876109998Smarkm
877296341Sdelphij        if (verbose) {
878296341Sdelphij            print_name(bio_err, "new subject=",
879296341Sdelphij                       X509_REQ_get_subject_name(req), nmflag);
880296341Sdelphij        }
881296341Sdelphij    }
88255714Skris
883296341Sdelphij    if (verify && !x509) {
884296341Sdelphij        int tmp = 0;
88555714Skris
886296341Sdelphij        if (pkey == NULL) {
887296341Sdelphij            pkey = X509_REQ_get_pubkey(req);
888296341Sdelphij            tmp = 1;
889296341Sdelphij            if (pkey == NULL)
890296341Sdelphij                goto end;
891296341Sdelphij        }
89255714Skris
893296341Sdelphij        i = X509_REQ_verify(req, pkey);
894296341Sdelphij        if (tmp) {
895296341Sdelphij            EVP_PKEY_free(pkey);
896296341Sdelphij            pkey = NULL;
897296341Sdelphij        }
89855714Skris
899296341Sdelphij        if (i < 0) {
900296341Sdelphij            goto end;
901296341Sdelphij        } else if (i == 0) {
902296341Sdelphij            BIO_printf(bio_err, "verify failure\n");
903296341Sdelphij            ERR_print_errors(bio_err);
904296341Sdelphij        } else                  /* if (i > 0) */
905296341Sdelphij            BIO_printf(bio_err, "verify OK\n");
906296341Sdelphij    }
90755714Skris
908296341Sdelphij    if (noout && !text && !modulus && !subject && !pubkey) {
909296341Sdelphij        ex = 0;
910296341Sdelphij        goto end;
911296341Sdelphij    }
912296341Sdelphij
913296341Sdelphij    if (outfile == NULL) {
914296341Sdelphij        BIO_set_fp(out, stdout, BIO_NOCLOSE);
915109998Smarkm#ifdef OPENSSL_SYS_VMS
916296341Sdelphij        {
917296341Sdelphij            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
918296341Sdelphij            out = BIO_push(tmpbio, out);
919296341Sdelphij        }
92068651Skris#endif
921296341Sdelphij    } else {
922296341Sdelphij        if ((keyout != NULL) && (strcmp(outfile, keyout) == 0))
923296341Sdelphij            i = (int)BIO_append_filename(out, outfile);
924296341Sdelphij        else
925296341Sdelphij            i = (int)BIO_write_filename(out, outfile);
926296341Sdelphij        if (!i) {
927296341Sdelphij            perror(outfile);
928296341Sdelphij            goto end;
929296341Sdelphij        }
930296341Sdelphij    }
93155714Skris
932296341Sdelphij    if (pubkey) {
933296341Sdelphij        EVP_PKEY *tpubkey;
934296341Sdelphij        tpubkey = X509_REQ_get_pubkey(req);
935296341Sdelphij        if (tpubkey == NULL) {
936296341Sdelphij            BIO_printf(bio_err, "Error getting public key\n");
937296341Sdelphij            ERR_print_errors(bio_err);
938296341Sdelphij            goto end;
939296341Sdelphij        }
940296341Sdelphij        PEM_write_bio_PUBKEY(out, tpubkey);
941296341Sdelphij        EVP_PKEY_free(tpubkey);
942296341Sdelphij    }
943109998Smarkm
944296341Sdelphij    if (text) {
945296341Sdelphij        if (x509)
946296341Sdelphij            X509_print_ex(out, x509ss, nmflag, reqflag);
947296341Sdelphij        else
948296341Sdelphij            X509_REQ_print_ex(out, req, nmflag, reqflag);
949296341Sdelphij    }
95055714Skris
951296341Sdelphij    if (subject) {
952296341Sdelphij        if (x509)
953296341Sdelphij            print_name(out, "subject=", X509_get_subject_name(x509ss),
954296341Sdelphij                       nmflag);
955296341Sdelphij        else
956296341Sdelphij            print_name(out, "subject=", X509_REQ_get_subject_name(req),
957296341Sdelphij                       nmflag);
958296341Sdelphij    }
959109998Smarkm
960296341Sdelphij    if (modulus) {
961296341Sdelphij        EVP_PKEY *tpubkey;
96255714Skris
963296341Sdelphij        if (x509)
964296341Sdelphij            tpubkey = X509_get_pubkey(x509ss);
965296341Sdelphij        else
966296341Sdelphij            tpubkey = X509_REQ_get_pubkey(req);
967296341Sdelphij        if (tpubkey == NULL) {
968296341Sdelphij            fprintf(stdout, "Modulus=unavailable\n");
969296341Sdelphij            goto end;
970296341Sdelphij        }
971296341Sdelphij        fprintf(stdout, "Modulus=");
972109998Smarkm#ifndef OPENSSL_NO_RSA
973296341Sdelphij        if (EVP_PKEY_base_id(tpubkey) == EVP_PKEY_RSA)
974296341Sdelphij            BN_print(out, tpubkey->pkey.rsa->n);
975296341Sdelphij        else
97655714Skris#endif
977296341Sdelphij            fprintf(stdout, "Wrong Algorithm type");
978296341Sdelphij        EVP_PKEY_free(tpubkey);
979296341Sdelphij        fprintf(stdout, "\n");
980296341Sdelphij    }
98155714Skris
982296341Sdelphij    if (!noout && !x509) {
983296341Sdelphij        if (outformat == FORMAT_ASN1)
984296341Sdelphij            i = i2d_X509_REQ_bio(out, req);
985296341Sdelphij        else if (outformat == FORMAT_PEM) {
986296341Sdelphij            if (newhdr)
987296341Sdelphij                i = PEM_write_bio_X509_REQ_NEW(out, req);
988296341Sdelphij            else
989296341Sdelphij                i = PEM_write_bio_X509_REQ(out, req);
990296341Sdelphij        } else {
991296341Sdelphij            BIO_printf(bio_err, "bad output format specified for outfile\n");
992296341Sdelphij            goto end;
993296341Sdelphij        }
994296341Sdelphij        if (!i) {
995296341Sdelphij            BIO_printf(bio_err, "unable to write X509 request\n");
996296341Sdelphij            goto end;
997296341Sdelphij        }
998296341Sdelphij    }
999296341Sdelphij    if (!noout && x509 && (x509ss != NULL)) {
1000296341Sdelphij        if (outformat == FORMAT_ASN1)
1001296341Sdelphij            i = i2d_X509_bio(out, x509ss);
1002296341Sdelphij        else if (outformat == FORMAT_PEM)
1003296341Sdelphij            i = PEM_write_bio_X509(out, x509ss);
1004296341Sdelphij        else {
1005296341Sdelphij            BIO_printf(bio_err, "bad output format specified for outfile\n");
1006296341Sdelphij            goto end;
1007296341Sdelphij        }
1008296341Sdelphij        if (!i) {
1009296341Sdelphij            BIO_printf(bio_err, "unable to write X509 certificate\n");
1010296341Sdelphij            goto end;
1011296341Sdelphij        }
1012296341Sdelphij    }
1013296341Sdelphij    ex = 0;
1014296341Sdelphij end:
1015109998Smarkm#ifndef MONOLITH
1016296341Sdelphij    if (to_free)
1017296341Sdelphij        OPENSSL_free(to_free);
1018109998Smarkm#endif
1019296341Sdelphij    if (ex) {
1020296341Sdelphij        ERR_print_errors(bio_err);
1021296341Sdelphij    }
1022296341Sdelphij    if ((req_conf != NULL) && (req_conf != config))
1023296341Sdelphij        NCONF_free(req_conf);
1024296341Sdelphij    BIO_free(in);
1025296341Sdelphij    BIO_free_all(out);
1026296341Sdelphij    EVP_PKEY_free(pkey);
1027296341Sdelphij    if (genctx)
1028296341Sdelphij        EVP_PKEY_CTX_free(genctx);
1029296341Sdelphij    if (pkeyopts)
1030296341Sdelphij        sk_OPENSSL_STRING_free(pkeyopts);
1031296341Sdelphij    if (sigopts)
1032296341Sdelphij        sk_OPENSSL_STRING_free(sigopts);
1033238405Sjkim#ifndef OPENSSL_NO_ENGINE
1034296341Sdelphij    if (gen_eng)
1035296341Sdelphij        ENGINE_free(gen_eng);
1036238405Sjkim#endif
1037296341Sdelphij    if (keyalgstr)
1038296341Sdelphij        OPENSSL_free(keyalgstr);
1039296341Sdelphij    X509_REQ_free(req);
1040296341Sdelphij    X509_free(x509ss);
1041296341Sdelphij    ASN1_INTEGER_free(serial);
1042296341Sdelphij    if (passargin && passin)
1043296341Sdelphij        OPENSSL_free(passin);
1044296341Sdelphij    if (passargout && passout)
1045296341Sdelphij        OPENSSL_free(passout);
1046296341Sdelphij    OBJ_cleanup();
1047296341Sdelphij    apps_shutdown();
1048296341Sdelphij    OPENSSL_EXIT(ex);
1049296341Sdelphij}
105055714Skris
1051160814Ssimonstatic int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn,
1052296341Sdelphij                    int attribs, unsigned long chtype)
1053296341Sdelphij{
1054296341Sdelphij    int ret = 0, i;
1055296341Sdelphij    char no_prompt = 0;
1056296341Sdelphij    STACK_OF(CONF_VALUE) *dn_sk, *attr_sk = NULL;
1057296341Sdelphij    char *tmp, *dn_sect, *attr_sect;
105859191Skris
1059296341Sdelphij    tmp = NCONF_get_string(req_conf, SECTION, PROMPT);
1060296341Sdelphij    if (tmp == NULL)
1061296341Sdelphij        ERR_clear_error();
1062296341Sdelphij    if ((tmp != NULL) && !strcmp(tmp, "no"))
1063296341Sdelphij        no_prompt = 1;
106459191Skris
1065296341Sdelphij    dn_sect = NCONF_get_string(req_conf, SECTION, DISTINGUISHED_NAME);
1066296341Sdelphij    if (dn_sect == NULL) {
1067296341Sdelphij        BIO_printf(bio_err, "unable to find '%s' in config\n",
1068296341Sdelphij                   DISTINGUISHED_NAME);
1069296341Sdelphij        goto err;
1070296341Sdelphij    }
1071296341Sdelphij    dn_sk = NCONF_get_section(req_conf, dn_sect);
1072296341Sdelphij    if (dn_sk == NULL) {
1073296341Sdelphij        BIO_printf(bio_err, "unable to get '%s' section\n", dn_sect);
1074296341Sdelphij        goto err;
1075296341Sdelphij    }
107655714Skris
1077296341Sdelphij    attr_sect = NCONF_get_string(req_conf, SECTION, ATTRIBUTES);
1078296341Sdelphij    if (attr_sect == NULL) {
1079296341Sdelphij        ERR_clear_error();
1080296341Sdelphij        attr_sk = NULL;
1081296341Sdelphij    } else {
1082296341Sdelphij        attr_sk = NCONF_get_section(req_conf, attr_sect);
1083296341Sdelphij        if (attr_sk == NULL) {
1084296341Sdelphij            BIO_printf(bio_err, "unable to get '%s' section\n", attr_sect);
1085296341Sdelphij            goto err;
1086296341Sdelphij        }
1087296341Sdelphij    }
108855714Skris
1089296341Sdelphij    /* setup version number */
1090296341Sdelphij    if (!X509_REQ_set_version(req, 0L))
1091296341Sdelphij        goto err;               /* version 1 */
109255714Skris
1093296341Sdelphij    if (no_prompt)
1094296341Sdelphij        i = auto_info(req, dn_sk, attr_sk, attribs, chtype);
1095296341Sdelphij    else {
1096296341Sdelphij        if (subj)
1097296341Sdelphij            i = build_subject(req, subj, chtype, multirdn);
1098296341Sdelphij        else
1099296341Sdelphij            i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs,
1100296341Sdelphij                            chtype);
1101296341Sdelphij    }
1102296341Sdelphij    if (!i)
1103296341Sdelphij        goto err;
110459191Skris
1105296341Sdelphij    if (!X509_REQ_set_pubkey(req, pkey))
1106296341Sdelphij        goto err;
110759191Skris
1108296341Sdelphij    ret = 1;
1109296341Sdelphij err:
1110296341Sdelphij    return (ret);
1111296341Sdelphij}
111259191Skris
1113109998Smarkm/*
1114109998Smarkm * subject is expected to be in the format /type0=value0/type1=value1/type2=...
1115109998Smarkm * where characters may be escaped by \
1116109998Smarkm */
1117296341Sdelphijstatic int build_subject(X509_REQ *req, char *subject, unsigned long chtype,
1118296341Sdelphij                         int multirdn)
1119296341Sdelphij{
1120296341Sdelphij    X509_NAME *n;
112159191Skris
1122296341Sdelphij    if (!(n = parse_name(subject, chtype, multirdn)))
1123296341Sdelphij        return 0;
1124109998Smarkm
1125296341Sdelphij    if (!X509_REQ_set_subject_name(req, n)) {
1126296341Sdelphij        X509_NAME_free(n);
1127296341Sdelphij        return 0;
1128296341Sdelphij    }
1129296341Sdelphij    X509_NAME_free(n);
1130296341Sdelphij    return 1;
1131109998Smarkm}
1132109998Smarkm
113359191Skrisstatic int prompt_info(X509_REQ *req,
1134296341Sdelphij                       STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect,
1135296341Sdelphij                       STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect,
1136296341Sdelphij                       int attribs, unsigned long chtype)
1137296341Sdelphij{
1138296341Sdelphij    int i;
1139296341Sdelphij    char *p, *q;
1140296341Sdelphij    char buf[100];
1141296341Sdelphij    int nid, mval;
1142296341Sdelphij    long n_min, n_max;
1143296341Sdelphij    char *type, *value;
1144296341Sdelphij    const char *def;
1145296341Sdelphij    CONF_VALUE *v;
1146296341Sdelphij    X509_NAME *subj;
1147296341Sdelphij    subj = X509_REQ_get_subject_name(req);
114855714Skris
1149296341Sdelphij    if (!batch) {
1150296341Sdelphij        BIO_printf(bio_err,
1151296341Sdelphij                   "You are about to be asked to enter information that will be incorporated\n");
1152296341Sdelphij        BIO_printf(bio_err, "into your certificate request.\n");
1153296341Sdelphij        BIO_printf(bio_err,
1154296341Sdelphij                   "What you are about to enter is what is called a Distinguished Name or a DN.\n");
1155296341Sdelphij        BIO_printf(bio_err,
1156296341Sdelphij                   "There are quite a few fields but you can leave some blank\n");
1157296341Sdelphij        BIO_printf(bio_err,
1158296341Sdelphij                   "For some fields there will be a default value,\n");
1159296341Sdelphij        BIO_printf(bio_err,
1160296341Sdelphij                   "If you enter '.', the field will be left blank.\n");
1161296341Sdelphij        BIO_printf(bio_err, "-----\n");
1162296341Sdelphij    }
116355714Skris
1164296341Sdelphij    if (sk_CONF_VALUE_num(dn_sk)) {
1165296341Sdelphij        i = -1;
1166296341Sdelphij start:for (;;) {
1167296341Sdelphij            i++;
1168296341Sdelphij            if (sk_CONF_VALUE_num(dn_sk) <= i)
1169296341Sdelphij                break;
1170109998Smarkm
1171296341Sdelphij            v = sk_CONF_VALUE_value(dn_sk, i);
1172296341Sdelphij            p = q = NULL;
1173296341Sdelphij            type = v->name;
1174296341Sdelphij            if (!check_end(type, "_min") || !check_end(type, "_max") ||
1175296341Sdelphij                !check_end(type, "_default") || !check_end(type, "_value"))
1176296341Sdelphij                continue;
1177296341Sdelphij            /*
1178296341Sdelphij             * Skip past any leading X. X: X, etc to allow for multiple
1179296341Sdelphij             * instances
1180296341Sdelphij             */
1181296341Sdelphij            for (p = v->name; *p; p++)
1182296341Sdelphij                if ((*p == ':') || (*p == ',') || (*p == '.')) {
1183296341Sdelphij                    p++;
1184296341Sdelphij                    if (*p)
1185296341Sdelphij                        type = p;
1186296341Sdelphij                    break;
1187296341Sdelphij                }
1188296341Sdelphij            if (*type == '+') {
1189296341Sdelphij                mval = -1;
1190296341Sdelphij                type++;
1191296341Sdelphij            } else
1192296341Sdelphij                mval = 0;
1193296341Sdelphij            /* If OBJ not recognised ignore it */
1194296341Sdelphij            if ((nid = OBJ_txt2nid(type)) == NID_undef)
1195296341Sdelphij                goto start;
1196296341Sdelphij            if (BIO_snprintf(buf, sizeof buf, "%s_default", v->name)
1197296341Sdelphij                >= (int)sizeof(buf)) {
1198296341Sdelphij                BIO_printf(bio_err, "Name '%s' too long\n", v->name);
1199296341Sdelphij                return 0;
1200296341Sdelphij            }
120155714Skris
1202296341Sdelphij            if ((def = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) {
1203296341Sdelphij                ERR_clear_error();
1204296341Sdelphij                def = "";
1205296341Sdelphij            }
1206109998Smarkm
1207296341Sdelphij            BIO_snprintf(buf, sizeof buf, "%s_value", v->name);
1208296341Sdelphij            if ((value = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) {
1209296341Sdelphij                ERR_clear_error();
1210296341Sdelphij                value = NULL;
1211296341Sdelphij            }
121255714Skris
1213296341Sdelphij            BIO_snprintf(buf, sizeof buf, "%s_min", v->name);
1214296341Sdelphij            if (!NCONF_get_number(req_conf, dn_sect, buf, &n_min)) {
1215296341Sdelphij                ERR_clear_error();
1216296341Sdelphij                n_min = -1;
1217296341Sdelphij            }
121855714Skris
1219296341Sdelphij            BIO_snprintf(buf, sizeof buf, "%s_max", v->name);
1220296341Sdelphij            if (!NCONF_get_number(req_conf, dn_sect, buf, &n_max)) {
1221296341Sdelphij                ERR_clear_error();
1222296341Sdelphij                n_max = -1;
1223296341Sdelphij            }
122455714Skris
1225296341Sdelphij            if (!add_DN_object(subj, v->value, def, value, nid,
1226296341Sdelphij                               n_min, n_max, chtype, mval))
1227296341Sdelphij                return 0;
1228296341Sdelphij        }
1229296341Sdelphij        if (X509_NAME_entry_count(subj) == 0) {
1230296341Sdelphij            BIO_printf(bio_err,
1231296341Sdelphij                       "error, no objects specified in config file\n");
1232296341Sdelphij            return 0;
1233296341Sdelphij        }
123455714Skris
1235296341Sdelphij        if (attribs) {
1236296341Sdelphij            if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0)
1237296341Sdelphij                && (!batch)) {
1238296341Sdelphij                BIO_printf(bio_err,
1239296341Sdelphij                           "\nPlease enter the following 'extra' attributes\n");
1240296341Sdelphij                BIO_printf(bio_err,
1241296341Sdelphij                           "to be sent with your certificate request\n");
1242296341Sdelphij            }
124355714Skris
1244296341Sdelphij            i = -1;
1245296341Sdelphij start2:   for (;;) {
1246296341Sdelphij                i++;
1247296341Sdelphij                if ((attr_sk == NULL) || (sk_CONF_VALUE_num(attr_sk) <= i))
1248296341Sdelphij                    break;
124955714Skris
1250296341Sdelphij                v = sk_CONF_VALUE_value(attr_sk, i);
1251296341Sdelphij                type = v->name;
1252296341Sdelphij                if ((nid = OBJ_txt2nid(type)) == NID_undef)
1253296341Sdelphij                    goto start2;
125455714Skris
1255296341Sdelphij                if (BIO_snprintf(buf, sizeof buf, "%s_default", type)
1256296341Sdelphij                    >= (int)sizeof(buf)) {
1257296341Sdelphij                    BIO_printf(bio_err, "Name '%s' too long\n", v->name);
1258296341Sdelphij                    return 0;
1259296341Sdelphij                }
1260109998Smarkm
1261296341Sdelphij                if ((def = NCONF_get_string(req_conf, attr_sect, buf))
1262296341Sdelphij                    == NULL) {
1263296341Sdelphij                    ERR_clear_error();
1264296341Sdelphij                    def = "";
1265296341Sdelphij                }
126655714Skris
1267296341Sdelphij                BIO_snprintf(buf, sizeof buf, "%s_value", type);
1268296341Sdelphij                if ((value = NCONF_get_string(req_conf, attr_sect, buf))
1269296341Sdelphij                    == NULL) {
1270296341Sdelphij                    ERR_clear_error();
1271296341Sdelphij                    value = NULL;
1272296341Sdelphij                }
127355714Skris
1274296341Sdelphij                BIO_snprintf(buf, sizeof buf, "%s_min", type);
1275296341Sdelphij                if (!NCONF_get_number(req_conf, attr_sect, buf, &n_min)) {
1276296341Sdelphij                    ERR_clear_error();
1277296341Sdelphij                    n_min = -1;
1278296341Sdelphij                }
127955714Skris
1280296341Sdelphij                BIO_snprintf(buf, sizeof buf, "%s_max", type);
1281296341Sdelphij                if (!NCONF_get_number(req_conf, attr_sect, buf, &n_max)) {
1282296341Sdelphij                    ERR_clear_error();
1283296341Sdelphij                    n_max = -1;
1284296341Sdelphij                }
128555714Skris
1286296341Sdelphij                if (!add_attribute_object(req,
1287296341Sdelphij                                          v->value, def, value, nid, n_min,
1288296341Sdelphij                                          n_max, chtype))
1289296341Sdelphij                    return 0;
1290296341Sdelphij            }
1291296341Sdelphij        }
1292296341Sdelphij    } else {
1293296341Sdelphij        BIO_printf(bio_err, "No template, please set one up.\n");
1294296341Sdelphij        return 0;
1295296341Sdelphij    }
129655714Skris
1297296341Sdelphij    return 1;
129855714Skris
1299296341Sdelphij}
1300296341Sdelphij
130159191Skrisstatic int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk,
1302296341Sdelphij                     STACK_OF(CONF_VALUE) *attr_sk, int attribs,
1303296341Sdelphij                     unsigned long chtype)
1304296341Sdelphij{
1305296341Sdelphij    int i;
1306296341Sdelphij    char *p, *q;
1307296341Sdelphij    char *type;
1308296341Sdelphij    CONF_VALUE *v;
1309296341Sdelphij    X509_NAME *subj;
131059191Skris
1311296341Sdelphij    subj = X509_REQ_get_subject_name(req);
131259191Skris
1313296341Sdelphij    for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
1314296341Sdelphij        int mval;
1315296341Sdelphij        v = sk_CONF_VALUE_value(dn_sk, i);
1316296341Sdelphij        p = q = NULL;
1317296341Sdelphij        type = v->name;
1318296341Sdelphij        /*
1319296341Sdelphij         * Skip past any leading X. X: X, etc to allow for multiple instances
1320296341Sdelphij         */
1321296341Sdelphij        for (p = v->name; *p; p++)
132268651Skris#ifndef CHARSET_EBCDIC
1323296341Sdelphij            if ((*p == ':') || (*p == ',') || (*p == '.')) {
132468651Skris#else
1325296341Sdelphij            if ((*p == os_toascii[':']) || (*p == os_toascii[','])
1326296341Sdelphij                || (*p == os_toascii['.'])) {
132768651Skris#endif
1328296341Sdelphij                p++;
1329296341Sdelphij                if (*p)
1330296341Sdelphij                    type = p;
1331296341Sdelphij                break;
1332296341Sdelphij            }
1333160814Ssimon#ifndef CHARSET_EBCDIC
1334296341Sdelphij        if (*p == '+')
1335160814Ssimon#else
1336296341Sdelphij        if (*p == os_toascii['+'])
1337160814Ssimon#endif
1338296341Sdelphij        {
1339296341Sdelphij            p++;
1340296341Sdelphij            mval = -1;
1341296341Sdelphij        } else
1342296341Sdelphij            mval = 0;
1343296341Sdelphij        if (!X509_NAME_add_entry_by_txt(subj, type, chtype,
1344296341Sdelphij                                        (unsigned char *)v->value, -1, -1,
1345296341Sdelphij                                        mval))
1346296341Sdelphij            return 0;
134759191Skris
1348296341Sdelphij    }
134959191Skris
1350296341Sdelphij    if (!X509_NAME_entry_count(subj)) {
1351296341Sdelphij        BIO_printf(bio_err, "error, no objects specified in config file\n");
1352296341Sdelphij        return 0;
1353296341Sdelphij    }
1354296341Sdelphij    if (attribs) {
1355296341Sdelphij        for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) {
1356296341Sdelphij            v = sk_CONF_VALUE_value(attr_sk, i);
1357296341Sdelphij            if (!X509_REQ_add1_attr_by_txt(req, v->name, chtype,
1358296341Sdelphij                                           (unsigned char *)v->value, -1))
1359296341Sdelphij                return 0;
1360296341Sdelphij        }
1361296341Sdelphij    }
1362296341Sdelphij    return 1;
1363296341Sdelphij}
136459191Skris
1365296341Sdelphijstatic int add_DN_object(X509_NAME *n, char *text, const char *def,
1366296341Sdelphij                         char *value, int nid, int n_min, int n_max,
1367296341Sdelphij                         unsigned long chtype, int mval)
1368296341Sdelphij{
1369296341Sdelphij    int i, ret = 0;
1370296341Sdelphij    MS_STATIC char buf[1024];
1371296341Sdelphij start:
1372296341Sdelphij    if (!batch)
1373296341Sdelphij        BIO_printf(bio_err, "%s [%s]:", text, def);
1374296341Sdelphij    (void)BIO_flush(bio_err);
1375296341Sdelphij    if (value != NULL) {
1376296341Sdelphij        BUF_strlcpy(buf, value, sizeof buf);
1377296341Sdelphij        BUF_strlcat(buf, "\n", sizeof buf);
1378296341Sdelphij        BIO_printf(bio_err, "%s\n", value);
1379296341Sdelphij    } else {
1380296341Sdelphij        buf[0] = '\0';
1381296341Sdelphij        if (!batch) {
1382296341Sdelphij            if (!fgets(buf, sizeof buf, stdin))
1383296341Sdelphij                return 0;
1384296341Sdelphij        } else {
1385296341Sdelphij            buf[0] = '\n';
1386296341Sdelphij            buf[1] = '\0';
1387296341Sdelphij        }
1388296341Sdelphij    }
138959191Skris
1390296341Sdelphij    if (buf[0] == '\0')
1391296341Sdelphij        return (0);
1392296341Sdelphij    else if (buf[0] == '\n') {
1393296341Sdelphij        if ((def == NULL) || (def[0] == '\0'))
1394296341Sdelphij            return (1);
1395296341Sdelphij        BUF_strlcpy(buf, def, sizeof buf);
1396296341Sdelphij        BUF_strlcat(buf, "\n", sizeof buf);
1397296341Sdelphij    } else if ((buf[0] == '.') && (buf[1] == '\n'))
1398296341Sdelphij        return (1);
139955714Skris
1400296341Sdelphij    i = strlen(buf);
1401296341Sdelphij    if (buf[i - 1] != '\n') {
1402296341Sdelphij        BIO_printf(bio_err, "weird input :-(\n");
1403296341Sdelphij        return (0);
1404296341Sdelphij    }
1405296341Sdelphij    buf[--i] = '\0';
140655714Skris#ifdef CHARSET_EBCDIC
1407296341Sdelphij    ebcdic2ascii(buf, buf, i);
140855714Skris#endif
1409296341Sdelphij    if (!req_check_len(i, n_min, n_max)) {
1410296341Sdelphij        if (batch || value)
1411296341Sdelphij            return 0;
1412296341Sdelphij        goto start;
1413296341Sdelphij    }
1414267258Sjkim
1415296341Sdelphij    if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
1416296341Sdelphij                                    (unsigned char *)buf, -1, -1, mval))
1417296341Sdelphij        goto err;
1418296341Sdelphij    ret = 1;
1419296341Sdelphij err:
1420296341Sdelphij    return (ret);
1421296341Sdelphij}
142255714Skris
1423160814Ssimonstatic int add_attribute_object(X509_REQ *req, char *text, const char *def,
1424296341Sdelphij                                char *value, int nid, int n_min,
1425296341Sdelphij                                int n_max, unsigned long chtype)
1426296341Sdelphij{
1427296341Sdelphij    int i;
1428296341Sdelphij    static char buf[1024];
142955714Skris
1430296341Sdelphij start:
1431296341Sdelphij    if (!batch)
1432296341Sdelphij        BIO_printf(bio_err, "%s [%s]:", text, def);
1433296341Sdelphij    (void)BIO_flush(bio_err);
1434296341Sdelphij    if (value != NULL) {
1435296341Sdelphij        BUF_strlcpy(buf, value, sizeof buf);
1436296341Sdelphij        BUF_strlcat(buf, "\n", sizeof buf);
1437296341Sdelphij        BIO_printf(bio_err, "%s\n", value);
1438296341Sdelphij    } else {
1439296341Sdelphij        buf[0] = '\0';
1440296341Sdelphij        if (!batch) {
1441296341Sdelphij            if (!fgets(buf, sizeof buf, stdin))
1442296341Sdelphij                return 0;
1443296341Sdelphij        } else {
1444296341Sdelphij            buf[0] = '\n';
1445296341Sdelphij            buf[1] = '\0';
1446296341Sdelphij        }
1447296341Sdelphij    }
144855714Skris
1449296341Sdelphij    if (buf[0] == '\0')
1450296341Sdelphij        return (0);
1451296341Sdelphij    else if (buf[0] == '\n') {
1452296341Sdelphij        if ((def == NULL) || (def[0] == '\0'))
1453296341Sdelphij            return (1);
1454296341Sdelphij        BUF_strlcpy(buf, def, sizeof buf);
1455296341Sdelphij        BUF_strlcat(buf, "\n", sizeof buf);
1456296341Sdelphij    } else if ((buf[0] == '.') && (buf[1] == '\n'))
1457296341Sdelphij        return (1);
145855714Skris
1459296341Sdelphij    i = strlen(buf);
1460296341Sdelphij    if (buf[i - 1] != '\n') {
1461296341Sdelphij        BIO_printf(bio_err, "weird input :-(\n");
1462296341Sdelphij        return (0);
1463296341Sdelphij    }
1464296341Sdelphij    buf[--i] = '\0';
146568651Skris#ifdef CHARSET_EBCDIC
1466296341Sdelphij    ebcdic2ascii(buf, buf, i);
146768651Skris#endif
1468296341Sdelphij    if (!req_check_len(i, n_min, n_max)) {
1469296341Sdelphij        if (batch || value)
1470296341Sdelphij            return 0;
1471296341Sdelphij        goto start;
1472296341Sdelphij    }
147355714Skris
1474296341Sdelphij    if (!X509_REQ_add1_attr_by_NID(req, nid, chtype,
1475296341Sdelphij                                   (unsigned char *)buf, -1)) {
1476296341Sdelphij        BIO_printf(bio_err, "Error adding attribute\n");
1477296341Sdelphij        ERR_print_errors(bio_err);
1478296341Sdelphij        goto err;
1479296341Sdelphij    }
148055714Skris
1481296341Sdelphij    return (1);
1482296341Sdelphij err:
1483296341Sdelphij    return (0);
1484296341Sdelphij}
148555714Skris
1486109998Smarkmstatic int req_check_len(int len, int n_min, int n_max)
1487296341Sdelphij{
1488296341Sdelphij    if ((n_min > 0) && (len < n_min)) {
1489296341Sdelphij        BIO_printf(bio_err,
1490296341Sdelphij                   "string is too short, it needs to be at least %d bytes long\n",
1491296341Sdelphij                   n_min);
1492296341Sdelphij        return (0);
1493296341Sdelphij    }
1494296341Sdelphij    if ((n_max >= 0) && (len > n_max)) {
1495296341Sdelphij        BIO_printf(bio_err,
1496296341Sdelphij                   "string is too long, it needs to be less than  %d bytes long\n",
1497296341Sdelphij                   n_max);
1498296341Sdelphij        return (0);
1499296341Sdelphij    }
1500296341Sdelphij    return (1);
1501296341Sdelphij}
150255714Skris
150355714Skris/* Check if the end of a string matches 'end' */
1504160814Ssimonstatic int check_end(const char *str, const char *end)
150555714Skris{
1506296341Sdelphij    int elen, slen;
1507296341Sdelphij    const char *tmp;
1508296341Sdelphij    elen = strlen(end);
1509296341Sdelphij    slen = strlen(str);
1510296341Sdelphij    if (elen > slen)
1511296341Sdelphij        return 1;
1512296341Sdelphij    tmp = str + slen - elen;
1513296341Sdelphij    return strcmp(tmp, end);
151455714Skris}
1515238405Sjkim
1516296341Sdelphijstatic EVP_PKEY_CTX *set_keygen_ctx(BIO *err, const char *gstr,
1517296341Sdelphij                                    int *pkey_type, long *pkeylen,
1518296341Sdelphij                                    char **palgnam, ENGINE *keygen_engine)
1519296341Sdelphij{
1520296341Sdelphij    EVP_PKEY_CTX *gctx = NULL;
1521296341Sdelphij    EVP_PKEY *param = NULL;
1522296341Sdelphij    long keylen = -1;
1523296341Sdelphij    BIO *pbio = NULL;
1524296341Sdelphij    const char *paramfile = NULL;
1525238405Sjkim
1526296341Sdelphij    if (gstr == NULL) {
1527296341Sdelphij        *pkey_type = EVP_PKEY_RSA;
1528296341Sdelphij        keylen = *pkeylen;
1529296341Sdelphij    } else if (gstr[0] >= '0' && gstr[0] <= '9') {
1530296341Sdelphij        *pkey_type = EVP_PKEY_RSA;
1531296341Sdelphij        keylen = atol(gstr);
1532296341Sdelphij        *pkeylen = keylen;
1533296341Sdelphij    } else if (!strncmp(gstr, "param:", 6))
1534296341Sdelphij        paramfile = gstr + 6;
1535296341Sdelphij    else {
1536296341Sdelphij        const char *p = strchr(gstr, ':');
1537296341Sdelphij        int len;
1538296341Sdelphij        ENGINE *tmpeng;
1539296341Sdelphij        const EVP_PKEY_ASN1_METHOD *ameth;
1540238405Sjkim
1541296341Sdelphij        if (p)
1542296341Sdelphij            len = p - gstr;
1543296341Sdelphij        else
1544296341Sdelphij            len = strlen(gstr);
1545296341Sdelphij        /*
1546296341Sdelphij         * The lookup of a the string will cover all engines so keep a note
1547296341Sdelphij         * of the implementation.
1548296341Sdelphij         */
1549238405Sjkim
1550296341Sdelphij        ameth = EVP_PKEY_asn1_find_str(&tmpeng, gstr, len);
1551238405Sjkim
1552296341Sdelphij        if (!ameth) {
1553296341Sdelphij            BIO_printf(err, "Unknown algorithm %.*s\n", len, gstr);
1554296341Sdelphij            return NULL;
1555296341Sdelphij        }
1556238405Sjkim
1557296341Sdelphij        EVP_PKEY_asn1_get0_info(NULL, pkey_type, NULL, NULL, NULL, ameth);
1558238405Sjkim#ifndef OPENSSL_NO_ENGINE
1559296341Sdelphij        if (tmpeng)
1560296341Sdelphij            ENGINE_finish(tmpeng);
1561238405Sjkim#endif
1562296341Sdelphij        if (*pkey_type == EVP_PKEY_RSA) {
1563296341Sdelphij            if (p) {
1564296341Sdelphij                keylen = atol(p + 1);
1565296341Sdelphij                *pkeylen = keylen;
1566296341Sdelphij            } else
1567296341Sdelphij                keylen = *pkeylen;
1568296341Sdelphij        } else if (p)
1569296341Sdelphij            paramfile = p + 1;
1570296341Sdelphij    }
1571238405Sjkim
1572296341Sdelphij    if (paramfile) {
1573296341Sdelphij        pbio = BIO_new_file(paramfile, "r");
1574296341Sdelphij        if (!pbio) {
1575296341Sdelphij            BIO_printf(err, "Can't open parameter file %s\n", paramfile);
1576296341Sdelphij            return NULL;
1577296341Sdelphij        }
1578296341Sdelphij        param = PEM_read_bio_Parameters(pbio, NULL);
1579238405Sjkim
1580296341Sdelphij        if (!param) {
1581296341Sdelphij            X509 *x;
1582296341Sdelphij            (void)BIO_reset(pbio);
1583296341Sdelphij            x = PEM_read_bio_X509(pbio, NULL, NULL, NULL);
1584296341Sdelphij            if (x) {
1585296341Sdelphij                param = X509_get_pubkey(x);
1586296341Sdelphij                X509_free(x);
1587296341Sdelphij            }
1588296341Sdelphij        }
1589238405Sjkim
1590296341Sdelphij        BIO_free(pbio);
1591238405Sjkim
1592296341Sdelphij        if (!param) {
1593296341Sdelphij            BIO_printf(err, "Error reading parameter file %s\n", paramfile);
1594296341Sdelphij            return NULL;
1595296341Sdelphij        }
1596296341Sdelphij        if (*pkey_type == -1)
1597296341Sdelphij            *pkey_type = EVP_PKEY_id(param);
1598296341Sdelphij        else if (*pkey_type != EVP_PKEY_base_id(param)) {
1599296341Sdelphij            BIO_printf(err, "Key Type does not match parameters\n");
1600296341Sdelphij            EVP_PKEY_free(param);
1601296341Sdelphij            return NULL;
1602296341Sdelphij        }
1603296341Sdelphij    }
1604238405Sjkim
1605296341Sdelphij    if (palgnam) {
1606296341Sdelphij        const EVP_PKEY_ASN1_METHOD *ameth;
1607296341Sdelphij        ENGINE *tmpeng;
1608296341Sdelphij        const char *anam;
1609296341Sdelphij        ameth = EVP_PKEY_asn1_find(&tmpeng, *pkey_type);
1610296341Sdelphij        if (!ameth) {
1611296341Sdelphij            BIO_puts(err, "Internal error: can't find key algorithm\n");
1612296341Sdelphij            return NULL;
1613296341Sdelphij        }
1614296341Sdelphij        EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &anam, ameth);
1615296341Sdelphij        *palgnam = BUF_strdup(anam);
1616238405Sjkim#ifndef OPENSSL_NO_ENGINE
1617296341Sdelphij        if (tmpeng)
1618296341Sdelphij            ENGINE_finish(tmpeng);
1619238405Sjkim#endif
1620296341Sdelphij    }
1621238405Sjkim
1622296341Sdelphij    if (param) {
1623296341Sdelphij        gctx = EVP_PKEY_CTX_new(param, keygen_engine);
1624296341Sdelphij        *pkeylen = EVP_PKEY_bits(param);
1625296341Sdelphij        EVP_PKEY_free(param);
1626296341Sdelphij    } else
1627296341Sdelphij        gctx = EVP_PKEY_CTX_new_id(*pkey_type, keygen_engine);
1628238405Sjkim
1629296341Sdelphij    if (!gctx) {
1630296341Sdelphij        BIO_puts(err, "Error allocating keygen context\n");
1631296341Sdelphij        ERR_print_errors(err);
1632296341Sdelphij        return NULL;
1633296341Sdelphij    }
1634238405Sjkim
1635296341Sdelphij    if (EVP_PKEY_keygen_init(gctx) <= 0) {
1636296341Sdelphij        BIO_puts(err, "Error initializing keygen context\n");
1637296341Sdelphij        ERR_print_errors(err);
1638296341Sdelphij        return NULL;
1639296341Sdelphij    }
1640238405Sjkim#ifndef OPENSSL_NO_RSA
1641296341Sdelphij    if ((*pkey_type == EVP_PKEY_RSA) && (keylen != -1)) {
1642296341Sdelphij        if (EVP_PKEY_CTX_set_rsa_keygen_bits(gctx, keylen) <= 0) {
1643296341Sdelphij            BIO_puts(err, "Error setting RSA keysize\n");
1644296341Sdelphij            ERR_print_errors(err);
1645296341Sdelphij            EVP_PKEY_CTX_free(gctx);
1646296341Sdelphij            return NULL;
1647296341Sdelphij        }
1648296341Sdelphij    }
1649238405Sjkim#endif
1650238405Sjkim
1651296341Sdelphij    return gctx;
1652296341Sdelphij}
1653238405Sjkim
1654238405Sjkimstatic int genpkey_cb(EVP_PKEY_CTX *ctx)
1655296341Sdelphij{
1656296341Sdelphij    char c = '*';
1657296341Sdelphij    BIO *b = EVP_PKEY_CTX_get_app_data(ctx);
1658296341Sdelphij    int p;
1659296341Sdelphij    p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
1660296341Sdelphij    if (p == 0)
1661296341Sdelphij        c = '.';
1662296341Sdelphij    if (p == 1)
1663296341Sdelphij        c = '+';
1664296341Sdelphij    if (p == 2)
1665296341Sdelphij        c = '*';
1666296341Sdelphij    if (p == 3)
1667296341Sdelphij        c = '\n';
1668296341Sdelphij    BIO_write(b, &c, 1);
1669296341Sdelphij    (void)BIO_flush(b);
1670238405Sjkim#ifdef LINT
1671296341Sdelphij    p = n;
1672238405Sjkim#endif
1673296341Sdelphij    return 1;
1674296341Sdelphij}
1675238405Sjkim
1676238405Sjkimstatic int do_sign_init(BIO *err, EVP_MD_CTX *ctx, EVP_PKEY *pkey,
1677296341Sdelphij                        const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts)
1678296341Sdelphij{
1679296341Sdelphij    EVP_PKEY_CTX *pkctx = NULL;
1680296341Sdelphij    int i;
1681296341Sdelphij    EVP_MD_CTX_init(ctx);
1682296341Sdelphij    if (!EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey))
1683296341Sdelphij        return 0;
1684296341Sdelphij    for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) {
1685296341Sdelphij        char *sigopt = sk_OPENSSL_STRING_value(sigopts, i);
1686296341Sdelphij        if (pkey_ctrl_string(pkctx, sigopt) <= 0) {
1687296341Sdelphij            BIO_printf(err, "parameter error \"%s\"\n", sigopt);
1688296341Sdelphij            ERR_print_errors(bio_err);
1689296341Sdelphij            return 0;
1690296341Sdelphij        }
1691296341Sdelphij    }
1692296341Sdelphij    return 1;
1693296341Sdelphij}
1694238405Sjkim
1695238405Sjkimint do_X509_sign(BIO *err, X509 *x, EVP_PKEY *pkey, const EVP_MD *md,
1696296341Sdelphij                 STACK_OF(OPENSSL_STRING) *sigopts)
1697296341Sdelphij{
1698296341Sdelphij    int rv;
1699296341Sdelphij    EVP_MD_CTX mctx;
1700296341Sdelphij    EVP_MD_CTX_init(&mctx);
1701296341Sdelphij    rv = do_sign_init(err, &mctx, pkey, md, sigopts);
1702296341Sdelphij    if (rv > 0)
1703296341Sdelphij        rv = X509_sign_ctx(x, &mctx);
1704296341Sdelphij    EVP_MD_CTX_cleanup(&mctx);
1705296341Sdelphij    return rv > 0 ? 1 : 0;
1706296341Sdelphij}
1707238405Sjkim
1708238405Sjkimint do_X509_REQ_sign(BIO *err, X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md,
1709296341Sdelphij                     STACK_OF(OPENSSL_STRING) *sigopts)
1710296341Sdelphij{
1711296341Sdelphij    int rv;
1712296341Sdelphij    EVP_MD_CTX mctx;
1713296341Sdelphij    EVP_MD_CTX_init(&mctx);
1714296341Sdelphij    rv = do_sign_init(err, &mctx, pkey, md, sigopts);
1715296341Sdelphij    if (rv > 0)
1716296341Sdelphij        rv = X509_REQ_sign_ctx(x, &mctx);
1717296341Sdelphij    EVP_MD_CTX_cleanup(&mctx);
1718296341Sdelphij    return rv > 0 ? 1 : 0;
1719296341Sdelphij}
1720238405Sjkim
1721238405Sjkimint do_X509_CRL_sign(BIO *err, X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md,
1722296341Sdelphij                     STACK_OF(OPENSSL_STRING) *sigopts)
1723296341Sdelphij{
1724296341Sdelphij    int rv;
1725296341Sdelphij    EVP_MD_CTX mctx;
1726296341Sdelphij    EVP_MD_CTX_init(&mctx);
1727296341Sdelphij    rv = do_sign_init(err, &mctx, pkey, md, sigopts);
1728296341Sdelphij    if (rv > 0)
1729296341Sdelphij        rv = X509_CRL_sign_ctx(x, &mctx);
1730296341Sdelphij    EVP_MD_CTX_cleanup(&mctx);
1731296341Sdelphij    return rv > 0 ? 1 : 0;
1732296341Sdelphij}
1733