1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: req.c,v 1.23 2022/02/03 17:44:04 tb Exp $ */
2f5b1c8a1SJohn Marino /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3f5b1c8a1SJohn Marino * All rights reserved.
4f5b1c8a1SJohn Marino *
5f5b1c8a1SJohn Marino * This package is an SSL implementation written
6f5b1c8a1SJohn Marino * by Eric Young (eay@cryptsoft.com).
7f5b1c8a1SJohn Marino * The implementation was written so as to conform with Netscapes SSL.
8f5b1c8a1SJohn Marino *
9f5b1c8a1SJohn Marino * This library is free for commercial and non-commercial use as long as
10f5b1c8a1SJohn Marino * the following conditions are aheared to. The following conditions
11f5b1c8a1SJohn Marino * apply to all code found in this distribution, be it the RC4, RSA,
12f5b1c8a1SJohn Marino * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13f5b1c8a1SJohn Marino * included with this distribution is covered by the same copyright terms
14f5b1c8a1SJohn Marino * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15f5b1c8a1SJohn Marino *
16f5b1c8a1SJohn Marino * Copyright remains Eric Young's, and as such any Copyright notices in
17f5b1c8a1SJohn Marino * the code are not to be removed.
18f5b1c8a1SJohn Marino * If this package is used in a product, Eric Young should be given attribution
19f5b1c8a1SJohn Marino * as the author of the parts of the library used.
20f5b1c8a1SJohn Marino * This can be in the form of a textual message at program startup or
21f5b1c8a1SJohn Marino * in documentation (online or textual) provided with the package.
22f5b1c8a1SJohn Marino *
23f5b1c8a1SJohn Marino * Redistribution and use in source and binary forms, with or without
24f5b1c8a1SJohn Marino * modification, are permitted provided that the following conditions
25f5b1c8a1SJohn Marino * are met:
26f5b1c8a1SJohn Marino * 1. Redistributions of source code must retain the copyright
27f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer.
28f5b1c8a1SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
29f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer in the
30f5b1c8a1SJohn Marino * documentation and/or other materials provided with the distribution.
31f5b1c8a1SJohn Marino * 3. All advertising materials mentioning features or use of this software
32f5b1c8a1SJohn Marino * must display the following acknowledgement:
33f5b1c8a1SJohn Marino * "This product includes cryptographic software written by
34f5b1c8a1SJohn Marino * Eric Young (eay@cryptsoft.com)"
35f5b1c8a1SJohn Marino * The word 'cryptographic' can be left out if the rouines from the library
36f5b1c8a1SJohn Marino * being used are not cryptographic related :-).
37f5b1c8a1SJohn Marino * 4. If you include any Windows specific code (or a derivative thereof) from
38f5b1c8a1SJohn Marino * the apps directory (application code) you must include an acknowledgement:
39f5b1c8a1SJohn Marino * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40f5b1c8a1SJohn Marino *
41f5b1c8a1SJohn Marino * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42f5b1c8a1SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43f5b1c8a1SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44f5b1c8a1SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45f5b1c8a1SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46f5b1c8a1SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47f5b1c8a1SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48f5b1c8a1SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49f5b1c8a1SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50f5b1c8a1SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51f5b1c8a1SJohn Marino * SUCH DAMAGE.
52f5b1c8a1SJohn Marino *
53f5b1c8a1SJohn Marino * The licence and distribution terms for any publically available version or
54f5b1c8a1SJohn Marino * derivative of this code cannot be changed. i.e. this code cannot simply be
55f5b1c8a1SJohn Marino * copied and put under another distribution licence
56f5b1c8a1SJohn Marino * [including the GNU Public Licence.]
57f5b1c8a1SJohn Marino */
58f5b1c8a1SJohn Marino
59f5b1c8a1SJohn Marino /* Until the key-gen callbacks are modified to use newer prototypes, we allow
60f5b1c8a1SJohn Marino * deprecated functions for openssl-internal code */
61f5b1c8a1SJohn Marino #ifdef OPENSSL_NO_DEPRECATED
62f5b1c8a1SJohn Marino #undef OPENSSL_NO_DEPRECATED
63f5b1c8a1SJohn Marino #endif
64f5b1c8a1SJohn Marino
65cca6fc52SDaniel Fojt #include <ctype.h>
66cca6fc52SDaniel Fojt #include <limits.h>
67f5b1c8a1SJohn Marino #include <stdio.h>
68f5b1c8a1SJohn Marino #include <stdlib.h>
69f5b1c8a1SJohn Marino #include <string.h>
70f5b1c8a1SJohn Marino #include <time.h>
71f5b1c8a1SJohn Marino
72f5b1c8a1SJohn Marino #include "apps.h"
73f5b1c8a1SJohn Marino
74f5b1c8a1SJohn Marino #include <openssl/asn1.h>
75f5b1c8a1SJohn Marino #include <openssl/bio.h>
76f5b1c8a1SJohn Marino #include <openssl/bn.h>
77f5b1c8a1SJohn Marino #include <openssl/conf.h>
78f5b1c8a1SJohn Marino #include <openssl/err.h>
79f5b1c8a1SJohn Marino #include <openssl/evp.h>
80f5b1c8a1SJohn Marino #include <openssl/objects.h>
81f5b1c8a1SJohn Marino #include <openssl/pem.h>
82f5b1c8a1SJohn Marino #include <openssl/x509.h>
83f5b1c8a1SJohn Marino #include <openssl/x509v3.h>
84f5b1c8a1SJohn Marino
85f5b1c8a1SJohn Marino #include <openssl/dsa.h>
86f5b1c8a1SJohn Marino
87f5b1c8a1SJohn Marino #include <openssl/rsa.h>
88f5b1c8a1SJohn Marino
89f5b1c8a1SJohn Marino #define SECTION "req"
90f5b1c8a1SJohn Marino
91f5b1c8a1SJohn Marino #define BITS "default_bits"
92f5b1c8a1SJohn Marino #define KEYFILE "default_keyfile"
93f5b1c8a1SJohn Marino #define PROMPT "prompt"
94f5b1c8a1SJohn Marino #define DISTINGUISHED_NAME "distinguished_name"
95f5b1c8a1SJohn Marino #define ATTRIBUTES "attributes"
96f5b1c8a1SJohn Marino #define V3_EXTENSIONS "x509_extensions"
97f5b1c8a1SJohn Marino #define REQ_EXTENSIONS "req_extensions"
98f5b1c8a1SJohn Marino #define STRING_MASK "string_mask"
99f5b1c8a1SJohn Marino #define UTF8_IN "utf8"
100f5b1c8a1SJohn Marino
101f5b1c8a1SJohn Marino #define DEFAULT_KEY_LENGTH 2048
102f5b1c8a1SJohn Marino #define MIN_KEY_LENGTH 384
103f5b1c8a1SJohn Marino
104f5b1c8a1SJohn Marino static int make_REQ(X509_REQ * req, EVP_PKEY * pkey, char *dn, int multirdn,
105f5b1c8a1SJohn Marino int attribs, unsigned long chtype);
106f5b1c8a1SJohn Marino static int build_subject(X509_REQ * req, char *subj, unsigned long chtype,
107f5b1c8a1SJohn Marino int multirdn);
108f5b1c8a1SJohn Marino static int prompt_info(X509_REQ * req,
109f5b1c8a1SJohn Marino STACK_OF(CONF_VALUE) * dn_sk, char *dn_sect,
110f5b1c8a1SJohn Marino STACK_OF(CONF_VALUE) * attr_sk, char *attr_sect, int attribs,
111f5b1c8a1SJohn Marino unsigned long chtype);
112f5b1c8a1SJohn Marino static int auto_info(X509_REQ * req, STACK_OF(CONF_VALUE) * sk,
113f5b1c8a1SJohn Marino STACK_OF(CONF_VALUE) * attr, int attribs,
114f5b1c8a1SJohn Marino unsigned long chtype);
115f5b1c8a1SJohn Marino static int add_attribute_object(X509_REQ * req, char *text, const char *def,
116f5b1c8a1SJohn Marino char *value, int nid, int n_min,
117f5b1c8a1SJohn Marino int n_max, unsigned long chtype);
118f5b1c8a1SJohn Marino static int add_DN_object(X509_NAME * n, char *text, const char *def, char *value,
119f5b1c8a1SJohn Marino int nid, int n_min, int n_max, unsigned long chtype, int mval);
120f5b1c8a1SJohn Marino static int genpkey_cb(EVP_PKEY_CTX * ctx);
121f5b1c8a1SJohn Marino static int req_check_len(int len, int n_min, int n_max);
122f5b1c8a1SJohn Marino static int check_end(const char *str, const char *end);
123f5b1c8a1SJohn Marino static EVP_PKEY_CTX *set_keygen_ctx(BIO * err, const char *gstr, int *pkey_type,
124f5b1c8a1SJohn Marino long *pkeylen, char **palgnam);
125cca6fc52SDaniel Fojt static unsigned long ext_name_hash(const OPENSSL_STRING *a);
126cca6fc52SDaniel Fojt static int ext_name_cmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b);
127cca6fc52SDaniel Fojt static void exts_cleanup(OPENSSL_STRING *x);
128cca6fc52SDaniel Fojt static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv);
129f5b1c8a1SJohn Marino static CONF *req_conf = NULL;
130cca6fc52SDaniel Fojt static CONF *addext_conf = NULL;
1318edacedfSDaniel Fojt
1328edacedfSDaniel Fojt struct {
1338edacedfSDaniel Fojt LHASH_OF(OPENSSL_STRING) *addexts;
1348edacedfSDaniel Fojt BIO *addext_bio;
1358edacedfSDaniel Fojt int batch;
1368edacedfSDaniel Fojt unsigned long chtype;
1378edacedfSDaniel Fojt int days;
1388edacedfSDaniel Fojt const EVP_MD *digest;
1398edacedfSDaniel Fojt char *extensions;
1408edacedfSDaniel Fojt char *infile;
1418edacedfSDaniel Fojt int informat;
1428edacedfSDaniel Fojt char *keyalg;
1438edacedfSDaniel Fojt char *keyfile;
1448edacedfSDaniel Fojt int keyform;
1458edacedfSDaniel Fojt char *keyout;
1468edacedfSDaniel Fojt int modulus;
1478edacedfSDaniel Fojt int multirdn;
1488edacedfSDaniel Fojt int newhdr;
1498edacedfSDaniel Fojt long newkey;
1508edacedfSDaniel Fojt int newreq;
1518edacedfSDaniel Fojt unsigned long nmflag;
1528edacedfSDaniel Fojt int nodes;
1538edacedfSDaniel Fojt int noout;
1548edacedfSDaniel Fojt char *outfile;
1558edacedfSDaniel Fojt int outformat;
1568edacedfSDaniel Fojt char *passargin;
1578edacedfSDaniel Fojt char *passargout;
1588edacedfSDaniel Fojt STACK_OF(OPENSSL_STRING) *pkeyopts;
1598edacedfSDaniel Fojt int pubkey;
1608edacedfSDaniel Fojt char *req_exts;
1618edacedfSDaniel Fojt unsigned long reqflag;
1628edacedfSDaniel Fojt ASN1_INTEGER *serial;
1638edacedfSDaniel Fojt STACK_OF(OPENSSL_STRING) *sigopts;
1648edacedfSDaniel Fojt char *subj;
1658edacedfSDaniel Fojt int subject;
1668edacedfSDaniel Fojt char *template;
1678edacedfSDaniel Fojt int text;
1688edacedfSDaniel Fojt int verbose;
1698edacedfSDaniel Fojt int verify;
1708edacedfSDaniel Fojt int x509;
1718edacedfSDaniel Fojt } req_config;
1728edacedfSDaniel Fojt
1738edacedfSDaniel Fojt static int
req_opt_addext(char * arg)1748edacedfSDaniel Fojt req_opt_addext(char *arg)
1758edacedfSDaniel Fojt {
1768edacedfSDaniel Fojt int i;
1778edacedfSDaniel Fojt
1788edacedfSDaniel Fojt if (req_config.addexts == NULL) {
1798edacedfSDaniel Fojt req_config.addexts = (LHASH_OF(OPENSSL_STRING) *)lh_new(
1808edacedfSDaniel Fojt (LHASH_HASH_FN_TYPE)ext_name_hash,
1818edacedfSDaniel Fojt (LHASH_COMP_FN_TYPE)ext_name_cmp);
1828edacedfSDaniel Fojt req_config.addext_bio = BIO_new(BIO_s_mem());
1838edacedfSDaniel Fojt if (req_config.addexts == NULL ||
1848edacedfSDaniel Fojt req_config.addext_bio == NULL)
1858edacedfSDaniel Fojt return (1);
1868edacedfSDaniel Fojt }
1878edacedfSDaniel Fojt i = duplicated(req_config.addexts, arg);
1888edacedfSDaniel Fojt if (i == 1)
1898edacedfSDaniel Fojt return (1);
1908edacedfSDaniel Fojt if (i < 0 || BIO_printf(req_config.addext_bio, "%s\n", arg) < 0)
1918edacedfSDaniel Fojt return (1);
1928edacedfSDaniel Fojt
1938edacedfSDaniel Fojt return (0);
1948edacedfSDaniel Fojt }
1958edacedfSDaniel Fojt
1968edacedfSDaniel Fojt static int
req_opt_days(char * arg)1978edacedfSDaniel Fojt req_opt_days(char *arg)
1988edacedfSDaniel Fojt {
1998edacedfSDaniel Fojt const char *errstr;
2008edacedfSDaniel Fojt
2018edacedfSDaniel Fojt req_config.days = strtonum(arg, 1, INT_MAX, &errstr);
2028edacedfSDaniel Fojt if (errstr != NULL) {
2038edacedfSDaniel Fojt BIO_printf(bio_err, "bad -days %s, using 0: %s\n",
2048edacedfSDaniel Fojt arg, errstr);
2058edacedfSDaniel Fojt req_config.days = 30;
2068edacedfSDaniel Fojt }
2078edacedfSDaniel Fojt return (0);
2088edacedfSDaniel Fojt }
2098edacedfSDaniel Fojt
2108edacedfSDaniel Fojt static int
req_opt_digest(int argc,char ** argv,int * argsused)2118edacedfSDaniel Fojt req_opt_digest(int argc, char **argv, int *argsused)
2128edacedfSDaniel Fojt {
2138edacedfSDaniel Fojt char *name = argv[0];
2148edacedfSDaniel Fojt
2158edacedfSDaniel Fojt if (*name++ != '-')
2168edacedfSDaniel Fojt return (1);
2178edacedfSDaniel Fojt
2188edacedfSDaniel Fojt if ((req_config.digest = EVP_get_digestbyname(name)) == NULL)
2198edacedfSDaniel Fojt return (1);
2208edacedfSDaniel Fojt
2218edacedfSDaniel Fojt *argsused = 1;
2228edacedfSDaniel Fojt return (0);
2238edacedfSDaniel Fojt }
2248edacedfSDaniel Fojt
2258edacedfSDaniel Fojt static int
req_opt_newkey(char * arg)2268edacedfSDaniel Fojt req_opt_newkey(char *arg)
2278edacedfSDaniel Fojt {
2288edacedfSDaniel Fojt req_config.keyalg = arg;
2298edacedfSDaniel Fojt req_config.newreq = 1;
2308edacedfSDaniel Fojt return (0);
2318edacedfSDaniel Fojt }
2328edacedfSDaniel Fojt
2338edacedfSDaniel Fojt static int
req_opt_nameopt(char * arg)2348edacedfSDaniel Fojt req_opt_nameopt(char *arg)
2358edacedfSDaniel Fojt {
2368edacedfSDaniel Fojt if (!set_name_ex(&req_config.nmflag, arg))
2378edacedfSDaniel Fojt return (1);
2388edacedfSDaniel Fojt return (0);
2398edacedfSDaniel Fojt }
2408edacedfSDaniel Fojt
2418edacedfSDaniel Fojt static int
req_opt_pkeyopt(char * arg)2428edacedfSDaniel Fojt req_opt_pkeyopt(char *arg)
2438edacedfSDaniel Fojt {
2448edacedfSDaniel Fojt if (req_config.pkeyopts == NULL)
2458edacedfSDaniel Fojt req_config.pkeyopts = sk_OPENSSL_STRING_new_null();
2468edacedfSDaniel Fojt if (req_config.pkeyopts == NULL)
2478edacedfSDaniel Fojt return (1);
2488edacedfSDaniel Fojt if (!sk_OPENSSL_STRING_push(req_config.pkeyopts, arg))
2498edacedfSDaniel Fojt return (1);
2508edacedfSDaniel Fojt return (0);
2518edacedfSDaniel Fojt }
2528edacedfSDaniel Fojt
2538edacedfSDaniel Fojt static int
req_opt_reqopt(char * arg)2548edacedfSDaniel Fojt req_opt_reqopt(char *arg)
2558edacedfSDaniel Fojt {
2568edacedfSDaniel Fojt if (!set_cert_ex(&req_config.reqflag, arg))
2578edacedfSDaniel Fojt return (1);
2588edacedfSDaniel Fojt return (0);
2598edacedfSDaniel Fojt }
2608edacedfSDaniel Fojt
2618edacedfSDaniel Fojt static int
req_opt_set_serial(char * arg)2628edacedfSDaniel Fojt req_opt_set_serial(char *arg)
2638edacedfSDaniel Fojt {
2648edacedfSDaniel Fojt req_config.serial = s2i_ASN1_INTEGER(NULL, arg);
2658edacedfSDaniel Fojt if (req_config.serial == NULL)
2668edacedfSDaniel Fojt return (1);
2678edacedfSDaniel Fojt return (0);
2688edacedfSDaniel Fojt }
2698edacedfSDaniel Fojt
2708edacedfSDaniel Fojt static int
req_opt_sigopt(char * arg)2718edacedfSDaniel Fojt req_opt_sigopt(char *arg)
2728edacedfSDaniel Fojt {
2738edacedfSDaniel Fojt if (req_config.sigopts == NULL)
2748edacedfSDaniel Fojt req_config.sigopts = sk_OPENSSL_STRING_new_null();
2758edacedfSDaniel Fojt if (req_config.sigopts == NULL)
2768edacedfSDaniel Fojt return (1);
2778edacedfSDaniel Fojt if (!sk_OPENSSL_STRING_push(req_config.sigopts, arg))
2788edacedfSDaniel Fojt return (1);
2798edacedfSDaniel Fojt return (0);
2808edacedfSDaniel Fojt }
2818edacedfSDaniel Fojt
2828edacedfSDaniel Fojt static int
req_opt_utf8(void)2838edacedfSDaniel Fojt req_opt_utf8(void)
2848edacedfSDaniel Fojt {
2858edacedfSDaniel Fojt req_config.chtype = MBSTRING_UTF8;
2868edacedfSDaniel Fojt return (0);
2878edacedfSDaniel Fojt }
2888edacedfSDaniel Fojt
2898edacedfSDaniel Fojt static const struct option req_options[] = {
2908edacedfSDaniel Fojt {
2918edacedfSDaniel Fojt .name = "addext",
2928edacedfSDaniel Fojt .argname = "key=value",
2938edacedfSDaniel Fojt .desc = "Additional certificate extension (may be repeated)",
2948edacedfSDaniel Fojt .type = OPTION_ARG_FUNC,
2958edacedfSDaniel Fojt .opt.argfunc = req_opt_addext,
2968edacedfSDaniel Fojt },
2978edacedfSDaniel Fojt {
2988edacedfSDaniel Fojt .name = "batch",
2998edacedfSDaniel Fojt .desc = "Operate in batch mode",
3008edacedfSDaniel Fojt .type = OPTION_FLAG,
3018edacedfSDaniel Fojt .opt.flag = &req_config.batch,
3028edacedfSDaniel Fojt },
3038edacedfSDaniel Fojt {
3048edacedfSDaniel Fojt .name = "config",
3058edacedfSDaniel Fojt .argname = "file",
3068edacedfSDaniel Fojt .desc = "Configuration file to use as request template",
3078edacedfSDaniel Fojt .type = OPTION_ARG,
3088edacedfSDaniel Fojt .opt.arg = &req_config.template,
3098edacedfSDaniel Fojt },
3108edacedfSDaniel Fojt {
3118edacedfSDaniel Fojt .name = "days",
3128edacedfSDaniel Fojt .argname = "number",
3138edacedfSDaniel Fojt .desc = "Number of days generated certificate is valid for",
3148edacedfSDaniel Fojt .type = OPTION_ARG_FUNC,
3158edacedfSDaniel Fojt .opt.argfunc = req_opt_days,
3168edacedfSDaniel Fojt },
3178edacedfSDaniel Fojt {
3188edacedfSDaniel Fojt .name = "extensions",
3198edacedfSDaniel Fojt .argname = "section",
3208edacedfSDaniel Fojt .desc = "Config section to use for certificate extensions",
3218edacedfSDaniel Fojt .type = OPTION_ARG,
3228edacedfSDaniel Fojt .opt.arg = &req_config.extensions,
3238edacedfSDaniel Fojt },
3248edacedfSDaniel Fojt {
3258edacedfSDaniel Fojt .name = "in",
3268edacedfSDaniel Fojt .argname = "file",
3278edacedfSDaniel Fojt .desc = "Input file (default stdin)",
3288edacedfSDaniel Fojt .type = OPTION_ARG,
3298edacedfSDaniel Fojt .opt.arg = &req_config.infile,
3308edacedfSDaniel Fojt },
3318edacedfSDaniel Fojt {
3328edacedfSDaniel Fojt .name = "inform",
3338edacedfSDaniel Fojt .argname = "format",
3348edacedfSDaniel Fojt .desc = "Input format (DER or PEM (default))",
3358edacedfSDaniel Fojt .type = OPTION_ARG_FORMAT,
3368edacedfSDaniel Fojt .opt.value = &req_config.informat,
3378edacedfSDaniel Fojt },
3388edacedfSDaniel Fojt {
3398edacedfSDaniel Fojt .name = "key",
3408edacedfSDaniel Fojt .argname = "file",
3418edacedfSDaniel Fojt .desc = "Private key file",
3428edacedfSDaniel Fojt .type = OPTION_ARG,
3438edacedfSDaniel Fojt .opt.arg = &req_config.keyfile,
3448edacedfSDaniel Fojt },
3458edacedfSDaniel Fojt {
3468edacedfSDaniel Fojt .name = "keyform",
3478edacedfSDaniel Fojt .argname = "format",
3488edacedfSDaniel Fojt .desc = "Private key format (DER or PEM (default))",
3498edacedfSDaniel Fojt .type = OPTION_ARG_FORMAT,
3508edacedfSDaniel Fojt .opt.value = &req_config.keyform,
3518edacedfSDaniel Fojt },
3528edacedfSDaniel Fojt {
3538edacedfSDaniel Fojt .name = "keyout",
3548edacedfSDaniel Fojt .argname = "file",
3558edacedfSDaniel Fojt .desc = "Private key output file",
3568edacedfSDaniel Fojt .type = OPTION_ARG,
3578edacedfSDaniel Fojt .opt.arg = &req_config.keyout,
3588edacedfSDaniel Fojt },
3598edacedfSDaniel Fojt {
3608edacedfSDaniel Fojt .name = "modulus",
3618edacedfSDaniel Fojt .desc = "Print RSA modulus",
3628edacedfSDaniel Fojt .type = OPTION_FLAG,
3638edacedfSDaniel Fojt .opt.flag = &req_config.modulus,
3648edacedfSDaniel Fojt },
3658edacedfSDaniel Fojt {
3668edacedfSDaniel Fojt .name = "multivalue-rdn",
3678edacedfSDaniel Fojt .desc = "Enable support for multivalued RDNs",
3688edacedfSDaniel Fojt .type = OPTION_FLAG,
3698edacedfSDaniel Fojt .opt.flag = &req_config.multirdn,
3708edacedfSDaniel Fojt },
3718edacedfSDaniel Fojt {
3728edacedfSDaniel Fojt .name = "nameopt",
3738edacedfSDaniel Fojt .argname = "arg",
3748edacedfSDaniel Fojt .desc = "Certificate name options",
3758edacedfSDaniel Fojt .type = OPTION_ARG_FUNC,
3768edacedfSDaniel Fojt .opt.argfunc = req_opt_nameopt,
3778edacedfSDaniel Fojt },
3788edacedfSDaniel Fojt {
3798edacedfSDaniel Fojt .name = "new",
3808edacedfSDaniel Fojt .desc = "New request",
3818edacedfSDaniel Fojt .type = OPTION_FLAG,
3828edacedfSDaniel Fojt .opt.flag = &req_config.newreq,
3838edacedfSDaniel Fojt },
3848edacedfSDaniel Fojt {
3858edacedfSDaniel Fojt .name = "newhdr",
3868edacedfSDaniel Fojt .desc = "Include 'NEW' in header lines",
3878edacedfSDaniel Fojt .type = OPTION_FLAG,
3888edacedfSDaniel Fojt .opt.flag = &req_config.newhdr,
3898edacedfSDaniel Fojt },
3908edacedfSDaniel Fojt {
3918edacedfSDaniel Fojt .name = "newkey",
3928edacedfSDaniel Fojt .argname = "param",
3938edacedfSDaniel Fojt .desc = "Generate a new key using given parameters",
3948edacedfSDaniel Fojt .type = OPTION_ARG_FUNC,
3958edacedfSDaniel Fojt .opt.argfunc = req_opt_newkey,
3968edacedfSDaniel Fojt },
3978edacedfSDaniel Fojt {
3988edacedfSDaniel Fojt .name = "nodes",
3998edacedfSDaniel Fojt .desc = "Do not encrypt output private key",
4008edacedfSDaniel Fojt .type = OPTION_FLAG,
4018edacedfSDaniel Fojt .opt.flag = &req_config.nodes,
4028edacedfSDaniel Fojt },
4038edacedfSDaniel Fojt {
4048edacedfSDaniel Fojt .name = "noout",
4058edacedfSDaniel Fojt .desc = "Do not output request",
4068edacedfSDaniel Fojt .type = OPTION_FLAG,
4078edacedfSDaniel Fojt .opt.flag = &req_config.noout,
4088edacedfSDaniel Fojt },
4098edacedfSDaniel Fojt {
4108edacedfSDaniel Fojt .name = "out",
4118edacedfSDaniel Fojt .argname = "file",
4128edacedfSDaniel Fojt .desc = "Output file (default stdout)",
4138edacedfSDaniel Fojt .type = OPTION_ARG,
4148edacedfSDaniel Fojt .opt.arg = &req_config.outfile,
4158edacedfSDaniel Fojt },
4168edacedfSDaniel Fojt {
4178edacedfSDaniel Fojt .name = "outform",
4188edacedfSDaniel Fojt .argname = "format",
4198edacedfSDaniel Fojt .desc = "Output format (DER or PEM (default))",
4208edacedfSDaniel Fojt .type = OPTION_ARG_FORMAT,
4218edacedfSDaniel Fojt .opt.value = &req_config.outformat,
4228edacedfSDaniel Fojt },
4238edacedfSDaniel Fojt {
4248edacedfSDaniel Fojt .name = "passin",
4258edacedfSDaniel Fojt .argname = "source",
4268edacedfSDaniel Fojt .desc = "Private key input password source",
4278edacedfSDaniel Fojt .type = OPTION_ARG,
4288edacedfSDaniel Fojt .opt.arg = &req_config.passargin,
4298edacedfSDaniel Fojt },
4308edacedfSDaniel Fojt {
4318edacedfSDaniel Fojt .name = "passout",
4328edacedfSDaniel Fojt .argname = "source",
4338edacedfSDaniel Fojt .desc = "Private key output password source",
4348edacedfSDaniel Fojt .type = OPTION_ARG,
4358edacedfSDaniel Fojt .opt.arg = &req_config.passargout,
4368edacedfSDaniel Fojt },
4378edacedfSDaniel Fojt {
4388edacedfSDaniel Fojt .name = "pkeyopt",
4398edacedfSDaniel Fojt .argname = "opt:val",
4408edacedfSDaniel Fojt .desc = "Set the public key algorithm option opt to val",
4418edacedfSDaniel Fojt .type = OPTION_ARG_FUNC,
4428edacedfSDaniel Fojt .opt.argfunc = req_opt_pkeyopt,
4438edacedfSDaniel Fojt },
4448edacedfSDaniel Fojt {
4458edacedfSDaniel Fojt .name = "pubkey",
4468edacedfSDaniel Fojt .desc = "Output the public key",
4478edacedfSDaniel Fojt .type = OPTION_FLAG,
4488edacedfSDaniel Fojt .opt.flag = &req_config.pubkey,
4498edacedfSDaniel Fojt },
4508edacedfSDaniel Fojt {
4518edacedfSDaniel Fojt .name = "reqexts",
4528edacedfSDaniel Fojt .argname = "section",
4538edacedfSDaniel Fojt .desc = "Config section to use for request extensions",
4548edacedfSDaniel Fojt .type = OPTION_ARG,
4558edacedfSDaniel Fojt .opt.arg = &req_config.req_exts,
4568edacedfSDaniel Fojt },
4578edacedfSDaniel Fojt {
4588edacedfSDaniel Fojt .name = "reqopt",
4598edacedfSDaniel Fojt .argname = "option",
4608edacedfSDaniel Fojt .desc = "Request text options",
4618edacedfSDaniel Fojt .type = OPTION_ARG_FUNC,
4628edacedfSDaniel Fojt .opt.argfunc = req_opt_reqopt,
4638edacedfSDaniel Fojt },
4648edacedfSDaniel Fojt {
4658edacedfSDaniel Fojt .name = "set_serial",
4668edacedfSDaniel Fojt .argname = "serial",
4678edacedfSDaniel Fojt .desc = "Serial number to use for generated certificate",
4688edacedfSDaniel Fojt .type = OPTION_ARG_FUNC,
4698edacedfSDaniel Fojt .opt.argfunc = req_opt_set_serial,
4708edacedfSDaniel Fojt },
4718edacedfSDaniel Fojt {
4728edacedfSDaniel Fojt .name = "sigopt",
4738edacedfSDaniel Fojt .argname = "name:val",
4748edacedfSDaniel Fojt .desc = "Signature options",
4758edacedfSDaniel Fojt .type = OPTION_ARG_FUNC,
4768edacedfSDaniel Fojt .opt.argfunc = req_opt_sigopt,
4778edacedfSDaniel Fojt },
4788edacedfSDaniel Fojt {
4798edacedfSDaniel Fojt .name = "subj",
4808edacedfSDaniel Fojt .argname = "name",
4818edacedfSDaniel Fojt .desc = "Set or modify the request subject",
4828edacedfSDaniel Fojt .type = OPTION_ARG,
4838edacedfSDaniel Fojt .opt.arg = &req_config.subj,
4848edacedfSDaniel Fojt },
4858edacedfSDaniel Fojt {
4868edacedfSDaniel Fojt .name = "subject",
4878edacedfSDaniel Fojt .desc = "Output the subject of the request",
4888edacedfSDaniel Fojt .type = OPTION_FLAG,
4898edacedfSDaniel Fojt .opt.flag = &req_config.subject,
4908edacedfSDaniel Fojt },
4918edacedfSDaniel Fojt {
4928edacedfSDaniel Fojt .name = "text",
4938edacedfSDaniel Fojt .desc = "Print request in text form",
4948edacedfSDaniel Fojt .type = OPTION_FLAG,
4958edacedfSDaniel Fojt .opt.flag = &req_config.text,
4968edacedfSDaniel Fojt },
4978edacedfSDaniel Fojt {
4988edacedfSDaniel Fojt .name = "utf8",
4998edacedfSDaniel Fojt .desc = "Input characters are in UTF-8 (default ASCII)",
5008edacedfSDaniel Fojt .type = OPTION_FUNC,
5018edacedfSDaniel Fojt .opt.func = req_opt_utf8,
5028edacedfSDaniel Fojt },
5038edacedfSDaniel Fojt {
5048edacedfSDaniel Fojt .name = "verbose",
5058edacedfSDaniel Fojt .desc = "Verbose",
5068edacedfSDaniel Fojt .type = OPTION_FLAG,
5078edacedfSDaniel Fojt .opt.flag = &req_config.verbose,
5088edacedfSDaniel Fojt },
5098edacedfSDaniel Fojt {
5108edacedfSDaniel Fojt .name = "verify",
5118edacedfSDaniel Fojt .desc = "Verify signature on request",
5128edacedfSDaniel Fojt .type = OPTION_FLAG,
5138edacedfSDaniel Fojt .opt.flag = &req_config.verify,
5148edacedfSDaniel Fojt },
5158edacedfSDaniel Fojt {
5168edacedfSDaniel Fojt .name = "x509",
5178edacedfSDaniel Fojt .desc = "Output an X.509 structure instead of a certificate request",
5188edacedfSDaniel Fojt .type = OPTION_FLAG,
5198edacedfSDaniel Fojt .opt.flag = &req_config.x509,
5208edacedfSDaniel Fojt },
5218edacedfSDaniel Fojt {
5228edacedfSDaniel Fojt .name = NULL,
5238edacedfSDaniel Fojt .desc = "",
5248edacedfSDaniel Fojt .type = OPTION_ARGV_FUNC,
5258edacedfSDaniel Fojt .opt.argvfunc = req_opt_digest,
5268edacedfSDaniel Fojt },
5278edacedfSDaniel Fojt { NULL },
5288edacedfSDaniel Fojt };
5298edacedfSDaniel Fojt
5308edacedfSDaniel Fojt static void
req_usage(void)5318edacedfSDaniel Fojt req_usage(void)
5328edacedfSDaniel Fojt {
5338edacedfSDaniel Fojt fprintf(stderr,
534*de0e0e4dSAntonio Huete Jimenez "usage: req [-addext ext] [-batch] [-config file]\n"
5358edacedfSDaniel Fojt " [-days n] [-extensions section] [-in file]\n"
5368edacedfSDaniel Fojt " [-inform der | pem] [-key keyfile] [-keyform der | pem]\n"
5378edacedfSDaniel Fojt " [-keyout file] [-md4 | -md5 | -sha1] [-modulus]\n"
5388edacedfSDaniel Fojt " [-multivalue-rdn] [-nameopt option] [-new] [-newhdr]\n"
539*de0e0e4dSAntonio Huete Jimenez " [-newkey arg] [-nodes] [-noout]\n"
5408edacedfSDaniel Fojt " [-out file] [-outform der | pem] [-passin arg]\n"
5418edacedfSDaniel Fojt " [-passout arg] [-pkeyopt opt:value] [-pubkey]\n"
5428edacedfSDaniel Fojt " [-reqexts section] [-reqopt option] [-set_serial n]\n"
5438edacedfSDaniel Fojt " [-sigopt nm:v] [-subj arg] [-subject] [-text] [-utf8]\n"
5448edacedfSDaniel Fojt " [-verbose] [-verify] [-x509]\n\n");
5458edacedfSDaniel Fojt
5468edacedfSDaniel Fojt options_usage(req_options);
5478edacedfSDaniel Fojt fprintf(stderr, "\n");
5488edacedfSDaniel Fojt }
549f5b1c8a1SJohn Marino
550f5b1c8a1SJohn Marino int
req_main(int argc,char ** argv)551f5b1c8a1SJohn Marino req_main(int argc, char **argv)
552f5b1c8a1SJohn Marino {
5538edacedfSDaniel Fojt int ex = 1;
554f5b1c8a1SJohn Marino X509 *x509ss = NULL;
555f5b1c8a1SJohn Marino X509_REQ *req = NULL;
556f5b1c8a1SJohn Marino EVP_PKEY_CTX *genctx = NULL;
557f5b1c8a1SJohn Marino char *keyalgstr = NULL;
558f5b1c8a1SJohn Marino const EVP_CIPHER *cipher = NULL;
5598edacedfSDaniel Fojt EVP_PKEY *pkey = NULL;
5608edacedfSDaniel Fojt int i = 0, pkey_type = -1;
5618edacedfSDaniel Fojt BIO *in = NULL, *out = NULL;
562f5b1c8a1SJohn Marino char *passin = NULL, *passout = NULL;
5638edacedfSDaniel Fojt const EVP_MD *md_alg = NULL;
564f5b1c8a1SJohn Marino char *p;
565f5b1c8a1SJohn Marino
566f5b1c8a1SJohn Marino if (single_execution) {
56772c33676SMaxim Ag if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
568f5b1c8a1SJohn Marino perror("pledge");
569f5b1c8a1SJohn Marino exit(1);
570f5b1c8a1SJohn Marino }
571f5b1c8a1SJohn Marino }
572f5b1c8a1SJohn Marino
5738edacedfSDaniel Fojt memset(&req_config, 0, sizeof(req_config));
5748edacedfSDaniel Fojt
5758edacedfSDaniel Fojt req_config.chtype = MBSTRING_ASC;
5768edacedfSDaniel Fojt req_config.days = 30;
5778edacedfSDaniel Fojt req_config.digest = EVP_sha256();
5788edacedfSDaniel Fojt req_config.newkey = -1;
5798edacedfSDaniel Fojt req_config.informat = FORMAT_PEM;
5808edacedfSDaniel Fojt req_config.keyform = FORMAT_PEM;
5818edacedfSDaniel Fojt req_config.outformat = FORMAT_PEM;
5828edacedfSDaniel Fojt
5838edacedfSDaniel Fojt if (options_parse(argc, argv, req_options, NULL, NULL) != 0) {
5848edacedfSDaniel Fojt req_usage();
5858edacedfSDaniel Fojt return (1);
5868edacedfSDaniel Fojt }
5878edacedfSDaniel Fojt
588f5b1c8a1SJohn Marino req_conf = NULL;
589f5b1c8a1SJohn Marino cipher = EVP_aes_256_cbc();
590f5b1c8a1SJohn Marino
5918edacedfSDaniel Fojt if (!app_passwd(bio_err, req_config.passargin, req_config.passargout, &passin, &passout)) {
592f5b1c8a1SJohn Marino BIO_printf(bio_err, "Error getting passwords\n");
593f5b1c8a1SJohn Marino goto end;
594f5b1c8a1SJohn Marino }
5958edacedfSDaniel Fojt if (req_config.template != NULL) {
596f5b1c8a1SJohn Marino long errline = -1;
597f5b1c8a1SJohn Marino
5988edacedfSDaniel Fojt if (req_config.verbose)
5998edacedfSDaniel Fojt BIO_printf(bio_err, "Using configuration from %s\n", req_config.template);
600cca6fc52SDaniel Fojt if ((req_conf = NCONF_new(NULL)) == NULL)
601cca6fc52SDaniel Fojt goto end;
6028edacedfSDaniel Fojt if(!NCONF_load(req_conf, req_config.template, &errline)) {
6038edacedfSDaniel Fojt BIO_printf(bio_err, "error on line %ld of %s\n", errline, req_config.template);
604f5b1c8a1SJohn Marino goto end;
605f5b1c8a1SJohn Marino }
606f5b1c8a1SJohn Marino } else {
607f5b1c8a1SJohn Marino req_conf = config;
608f5b1c8a1SJohn Marino
609f5b1c8a1SJohn Marino if (req_conf == NULL) {
610f5b1c8a1SJohn Marino BIO_printf(bio_err, "Unable to load config info from %s\n", default_config_file);
6118edacedfSDaniel Fojt if (req_config.newreq)
612f5b1c8a1SJohn Marino goto end;
6138edacedfSDaniel Fojt } else if (req_config.verbose)
614f5b1c8a1SJohn Marino BIO_printf(bio_err, "Using configuration from %s\n",
615f5b1c8a1SJohn Marino default_config_file);
616f5b1c8a1SJohn Marino }
617f5b1c8a1SJohn Marino
6188edacedfSDaniel Fojt if (req_config.addext_bio != NULL) {
619cca6fc52SDaniel Fojt long errline = -1;
6208edacedfSDaniel Fojt if (req_config.verbose)
621cca6fc52SDaniel Fojt BIO_printf(bio_err,
622cca6fc52SDaniel Fojt "Using additional configuration from command line\n");
623cca6fc52SDaniel Fojt if ((addext_conf = NCONF_new(NULL)) == NULL)
624cca6fc52SDaniel Fojt goto end;
6258edacedfSDaniel Fojt if (!NCONF_load_bio(addext_conf, req_config.addext_bio, &errline)) {
626cca6fc52SDaniel Fojt BIO_printf(bio_err,
627cca6fc52SDaniel Fojt "req: Error on line %ld of config input\n",
628cca6fc52SDaniel Fojt errline);
629cca6fc52SDaniel Fojt goto end;
630cca6fc52SDaniel Fojt }
631cca6fc52SDaniel Fojt }
632cca6fc52SDaniel Fojt
633f5b1c8a1SJohn Marino if (req_conf != NULL) {
634f5b1c8a1SJohn Marino if (!load_config(bio_err, req_conf))
635f5b1c8a1SJohn Marino goto end;
636f5b1c8a1SJohn Marino p = NCONF_get_string(req_conf, NULL, "oid_file");
637f5b1c8a1SJohn Marino if (p == NULL)
638f5b1c8a1SJohn Marino ERR_clear_error();
639f5b1c8a1SJohn Marino if (p != NULL) {
640f5b1c8a1SJohn Marino BIO *oid_bio;
641f5b1c8a1SJohn Marino
642f5b1c8a1SJohn Marino oid_bio = BIO_new_file(p, "r");
643f5b1c8a1SJohn Marino if (oid_bio == NULL) {
644f5b1c8a1SJohn Marino /*
645f5b1c8a1SJohn Marino BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
646f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
647f5b1c8a1SJohn Marino */
648f5b1c8a1SJohn Marino } else {
649f5b1c8a1SJohn Marino OBJ_create_objects(oid_bio);
650f5b1c8a1SJohn Marino BIO_free(oid_bio);
651f5b1c8a1SJohn Marino }
652f5b1c8a1SJohn Marino }
653f5b1c8a1SJohn Marino }
654f5b1c8a1SJohn Marino if (!add_oid_section(bio_err, req_conf))
655f5b1c8a1SJohn Marino goto end;
656f5b1c8a1SJohn Marino
657f5b1c8a1SJohn Marino if (md_alg == NULL) {
658f5b1c8a1SJohn Marino p = NCONF_get_string(req_conf, SECTION, "default_md");
659f5b1c8a1SJohn Marino if (p == NULL)
660f5b1c8a1SJohn Marino ERR_clear_error();
661f5b1c8a1SJohn Marino if (p != NULL) {
662f5b1c8a1SJohn Marino if ((md_alg = EVP_get_digestbyname(p)) != NULL)
6638edacedfSDaniel Fojt req_config.digest = md_alg;
664f5b1c8a1SJohn Marino }
665f5b1c8a1SJohn Marino }
6668edacedfSDaniel Fojt if (!req_config.extensions) {
6678edacedfSDaniel Fojt req_config.extensions = NCONF_get_string(req_conf, SECTION, V3_EXTENSIONS);
6688edacedfSDaniel Fojt if (!req_config.extensions)
669f5b1c8a1SJohn Marino ERR_clear_error();
670f5b1c8a1SJohn Marino }
6718edacedfSDaniel Fojt if (req_config.extensions) {
672f5b1c8a1SJohn Marino /* Check syntax of file */
673f5b1c8a1SJohn Marino X509V3_CTX ctx;
674f5b1c8a1SJohn Marino X509V3_set_ctx_test(&ctx);
675f5b1c8a1SJohn Marino X509V3_set_nconf(&ctx, req_conf);
6768edacedfSDaniel Fojt if (!X509V3_EXT_add_nconf(req_conf, &ctx, req_config.extensions, NULL)) {
677f5b1c8a1SJohn Marino BIO_printf(bio_err,
6788edacedfSDaniel Fojt "Error Loading extension section %s\n", req_config.extensions);
679f5b1c8a1SJohn Marino goto end;
680f5b1c8a1SJohn Marino }
681f5b1c8a1SJohn Marino }
682cca6fc52SDaniel Fojt if (addext_conf != NULL) {
683cca6fc52SDaniel Fojt /* Check syntax of command line extensions */
684cca6fc52SDaniel Fojt X509V3_CTX ctx;
685cca6fc52SDaniel Fojt X509V3_set_ctx_test(&ctx);
686cca6fc52SDaniel Fojt X509V3_set_nconf(&ctx, addext_conf);
687cca6fc52SDaniel Fojt if (!X509V3_EXT_add_nconf(addext_conf, &ctx, "default", NULL)) {
688cca6fc52SDaniel Fojt BIO_printf(bio_err,
689cca6fc52SDaniel Fojt "Error Loading command line extensions\n");
690cca6fc52SDaniel Fojt goto end;
691cca6fc52SDaniel Fojt }
692cca6fc52SDaniel Fojt }
693f5b1c8a1SJohn Marino if (!passin) {
694f5b1c8a1SJohn Marino passin = NCONF_get_string(req_conf, SECTION, "input_password");
695f5b1c8a1SJohn Marino if (!passin)
696f5b1c8a1SJohn Marino ERR_clear_error();
697f5b1c8a1SJohn Marino }
698f5b1c8a1SJohn Marino if (!passout) {
699f5b1c8a1SJohn Marino passout = NCONF_get_string(req_conf, SECTION, "output_password");
700f5b1c8a1SJohn Marino if (!passout)
701f5b1c8a1SJohn Marino ERR_clear_error();
702f5b1c8a1SJohn Marino }
703f5b1c8a1SJohn Marino p = NCONF_get_string(req_conf, SECTION, STRING_MASK);
704f5b1c8a1SJohn Marino if (!p)
705f5b1c8a1SJohn Marino ERR_clear_error();
706f5b1c8a1SJohn Marino
707f5b1c8a1SJohn Marino if (p && !ASN1_STRING_set_default_mask_asc(p)) {
708f5b1c8a1SJohn Marino BIO_printf(bio_err, "Invalid global string mask setting %s\n", p);
709f5b1c8a1SJohn Marino goto end;
710f5b1c8a1SJohn Marino }
7118edacedfSDaniel Fojt if (req_config.chtype != MBSTRING_UTF8) {
712f5b1c8a1SJohn Marino p = NCONF_get_string(req_conf, SECTION, UTF8_IN);
713f5b1c8a1SJohn Marino if (!p)
714f5b1c8a1SJohn Marino ERR_clear_error();
715f5b1c8a1SJohn Marino else if (!strcmp(p, "yes"))
7168edacedfSDaniel Fojt req_config.chtype = MBSTRING_UTF8;
717f5b1c8a1SJohn Marino }
7188edacedfSDaniel Fojt if (!req_config.req_exts) {
7198edacedfSDaniel Fojt req_config.req_exts = NCONF_get_string(req_conf, SECTION, REQ_EXTENSIONS);
7208edacedfSDaniel Fojt if (!req_config.req_exts)
721f5b1c8a1SJohn Marino ERR_clear_error();
722f5b1c8a1SJohn Marino }
7238edacedfSDaniel Fojt if (req_config.req_exts) {
724f5b1c8a1SJohn Marino /* Check syntax of file */
725f5b1c8a1SJohn Marino X509V3_CTX ctx;
726f5b1c8a1SJohn Marino X509V3_set_ctx_test(&ctx);
727f5b1c8a1SJohn Marino X509V3_set_nconf(&ctx, req_conf);
7288edacedfSDaniel Fojt if (!X509V3_EXT_add_nconf(req_conf, &ctx, req_config.req_exts, NULL)) {
729f5b1c8a1SJohn Marino BIO_printf(bio_err,
730f5b1c8a1SJohn Marino "Error Loading request extension section %s\n",
7318edacedfSDaniel Fojt req_config.req_exts);
732f5b1c8a1SJohn Marino goto end;
733f5b1c8a1SJohn Marino }
734f5b1c8a1SJohn Marino }
735f5b1c8a1SJohn Marino in = BIO_new(BIO_s_file());
736f5b1c8a1SJohn Marino out = BIO_new(BIO_s_file());
737f5b1c8a1SJohn Marino if ((in == NULL) || (out == NULL))
738f5b1c8a1SJohn Marino goto end;
739f5b1c8a1SJohn Marino
7408edacedfSDaniel Fojt if (req_config.keyfile != NULL) {
7418edacedfSDaniel Fojt pkey = load_key(bio_err, req_config.keyfile, req_config.keyform, 0, passin,
742f5b1c8a1SJohn Marino "Private Key");
743f5b1c8a1SJohn Marino if (!pkey) {
744f5b1c8a1SJohn Marino /*
745f5b1c8a1SJohn Marino * load_key() has already printed an appropriate
746f5b1c8a1SJohn Marino * message
747f5b1c8a1SJohn Marino */
748f5b1c8a1SJohn Marino goto end;
749f5b1c8a1SJohn Marino }
750f5b1c8a1SJohn Marino }
7518edacedfSDaniel Fojt if (req_config.newreq && (pkey == NULL)) {
7528edacedfSDaniel Fojt if (!NCONF_get_number(req_conf, SECTION, BITS, &req_config.newkey)) {
7538edacedfSDaniel Fojt req_config.newkey = DEFAULT_KEY_LENGTH;
754f5b1c8a1SJohn Marino }
7558edacedfSDaniel Fojt if (req_config.keyalg) {
7568edacedfSDaniel Fojt genctx = set_keygen_ctx(bio_err, req_config.keyalg, &pkey_type, &req_config.newkey,
757f5b1c8a1SJohn Marino &keyalgstr);
758f5b1c8a1SJohn Marino if (!genctx)
759f5b1c8a1SJohn Marino goto end;
760f5b1c8a1SJohn Marino }
7618edacedfSDaniel Fojt if (req_config.newkey < MIN_KEY_LENGTH && (pkey_type == EVP_PKEY_RSA || pkey_type == EVP_PKEY_DSA)) {
762f5b1c8a1SJohn Marino BIO_printf(bio_err, "private key length is too short,\n");
7638edacedfSDaniel Fojt BIO_printf(bio_err, "it needs to be at least %d bits, not %ld\n", MIN_KEY_LENGTH, req_config.newkey);
764f5b1c8a1SJohn Marino goto end;
765f5b1c8a1SJohn Marino }
766f5b1c8a1SJohn Marino if (!genctx) {
7678edacedfSDaniel Fojt genctx = set_keygen_ctx(bio_err, NULL, &pkey_type, &req_config.newkey,
768f5b1c8a1SJohn Marino &keyalgstr);
769f5b1c8a1SJohn Marino if (!genctx)
770f5b1c8a1SJohn Marino goto end;
771f5b1c8a1SJohn Marino }
7728edacedfSDaniel Fojt if (req_config.pkeyopts) {
773f5b1c8a1SJohn Marino char *genopt;
7748edacedfSDaniel Fojt for (i = 0; i < sk_OPENSSL_STRING_num(req_config.pkeyopts); i++) {
7758edacedfSDaniel Fojt genopt = sk_OPENSSL_STRING_value(req_config.pkeyopts, i);
776f5b1c8a1SJohn Marino if (pkey_ctrl_string(genctx, genopt) <= 0) {
777f5b1c8a1SJohn Marino BIO_printf(bio_err,
778f5b1c8a1SJohn Marino "parameter error \"%s\"\n",
779f5b1c8a1SJohn Marino genopt);
780f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
781f5b1c8a1SJohn Marino goto end;
782f5b1c8a1SJohn Marino }
783f5b1c8a1SJohn Marino }
784f5b1c8a1SJohn Marino }
785f5b1c8a1SJohn Marino BIO_printf(bio_err, "Generating a %ld bit %s private key\n",
7868edacedfSDaniel Fojt req_config.newkey, keyalgstr);
787f5b1c8a1SJohn Marino
788f5b1c8a1SJohn Marino EVP_PKEY_CTX_set_cb(genctx, genpkey_cb);
789f5b1c8a1SJohn Marino EVP_PKEY_CTX_set_app_data(genctx, bio_err);
790f5b1c8a1SJohn Marino
791f5b1c8a1SJohn Marino if (EVP_PKEY_keygen(genctx, &pkey) <= 0) {
792f5b1c8a1SJohn Marino BIO_puts(bio_err, "Error Generating Key\n");
793f5b1c8a1SJohn Marino goto end;
794f5b1c8a1SJohn Marino }
795f5b1c8a1SJohn Marino EVP_PKEY_CTX_free(genctx);
796f5b1c8a1SJohn Marino genctx = NULL;
797f5b1c8a1SJohn Marino
7988edacedfSDaniel Fojt if (req_config.keyout == NULL) {
7998edacedfSDaniel Fojt req_config.keyout = NCONF_get_string(req_conf, SECTION, KEYFILE);
8008edacedfSDaniel Fojt if (req_config.keyout == NULL)
801f5b1c8a1SJohn Marino ERR_clear_error();
802f5b1c8a1SJohn Marino }
8038edacedfSDaniel Fojt if (req_config.keyout == NULL) {
804f5b1c8a1SJohn Marino BIO_printf(bio_err, "writing new private key to stdout\n");
805f5b1c8a1SJohn Marino BIO_set_fp(out, stdout, BIO_NOCLOSE);
806f5b1c8a1SJohn Marino } else {
8078edacedfSDaniel Fojt BIO_printf(bio_err, "writing new private key to '%s'\n", req_config.keyout);
8088edacedfSDaniel Fojt if (BIO_write_filename(out, req_config.keyout) <= 0) {
8098edacedfSDaniel Fojt perror(req_config.keyout);
810f5b1c8a1SJohn Marino goto end;
811f5b1c8a1SJohn Marino }
812f5b1c8a1SJohn Marino }
813f5b1c8a1SJohn Marino
814f5b1c8a1SJohn Marino p = NCONF_get_string(req_conf, SECTION, "encrypt_rsa_key");
815f5b1c8a1SJohn Marino if (p == NULL) {
816f5b1c8a1SJohn Marino ERR_clear_error();
817f5b1c8a1SJohn Marino p = NCONF_get_string(req_conf, SECTION, "encrypt_key");
818f5b1c8a1SJohn Marino if (p == NULL)
819f5b1c8a1SJohn Marino ERR_clear_error();
820f5b1c8a1SJohn Marino }
821f5b1c8a1SJohn Marino if ((p != NULL) && (strcmp(p, "no") == 0))
822f5b1c8a1SJohn Marino cipher = NULL;
8238edacedfSDaniel Fojt if (req_config.nodes)
824f5b1c8a1SJohn Marino cipher = NULL;
825f5b1c8a1SJohn Marino
826f5b1c8a1SJohn Marino i = 0;
827f5b1c8a1SJohn Marino loop:
828f5b1c8a1SJohn Marino if (!PEM_write_bio_PrivateKey(out, pkey, cipher,
829f5b1c8a1SJohn Marino NULL, 0, NULL, passout)) {
830f5b1c8a1SJohn Marino if ((ERR_GET_REASON(ERR_peek_error()) ==
831f5b1c8a1SJohn Marino PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3)) {
832f5b1c8a1SJohn Marino ERR_clear_error();
833f5b1c8a1SJohn Marino i++;
834f5b1c8a1SJohn Marino goto loop;
835f5b1c8a1SJohn Marino }
836f5b1c8a1SJohn Marino goto end;
837f5b1c8a1SJohn Marino }
838f5b1c8a1SJohn Marino BIO_printf(bio_err, "-----\n");
839f5b1c8a1SJohn Marino }
8408edacedfSDaniel Fojt if (!req_config.newreq) {
8418edacedfSDaniel Fojt if (req_config.infile == NULL)
842f5b1c8a1SJohn Marino BIO_set_fp(in, stdin, BIO_NOCLOSE);
843f5b1c8a1SJohn Marino else {
8448edacedfSDaniel Fojt if (BIO_read_filename(in, req_config.infile) <= 0) {
8458edacedfSDaniel Fojt perror(req_config.infile);
846f5b1c8a1SJohn Marino goto end;
847f5b1c8a1SJohn Marino }
848f5b1c8a1SJohn Marino }
849f5b1c8a1SJohn Marino
8508edacedfSDaniel Fojt if (req_config.informat == FORMAT_ASN1)
851f5b1c8a1SJohn Marino req = d2i_X509_REQ_bio(in, NULL);
8528edacedfSDaniel Fojt else if (req_config.informat == FORMAT_PEM)
853f5b1c8a1SJohn Marino req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
854f5b1c8a1SJohn Marino else {
855f5b1c8a1SJohn Marino BIO_printf(bio_err, "bad input format specified for X509 request\n");
856f5b1c8a1SJohn Marino goto end;
857f5b1c8a1SJohn Marino }
858f5b1c8a1SJohn Marino if (req == NULL) {
859f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to load X509 request\n");
860f5b1c8a1SJohn Marino goto end;
861f5b1c8a1SJohn Marino }
862f5b1c8a1SJohn Marino }
8638edacedfSDaniel Fojt if (req_config.newreq || req_config.x509) {
864f5b1c8a1SJohn Marino if (pkey == NULL) {
865f5b1c8a1SJohn Marino BIO_printf(bio_err, "you need to specify a private key\n");
866f5b1c8a1SJohn Marino goto end;
867f5b1c8a1SJohn Marino }
868f5b1c8a1SJohn Marino if (req == NULL) {
869f5b1c8a1SJohn Marino req = X509_REQ_new();
870f5b1c8a1SJohn Marino if (req == NULL) {
871f5b1c8a1SJohn Marino goto end;
872f5b1c8a1SJohn Marino }
8738edacedfSDaniel Fojt i = make_REQ(req, pkey, req_config.subj, req_config.multirdn, !req_config.x509, req_config.chtype);
8748edacedfSDaniel Fojt req_config.subj = NULL; /* done processing '-subj' option */
875f5b1c8a1SJohn Marino if (!i) {
876f5b1c8a1SJohn Marino BIO_printf(bio_err, "problems making Certificate Request\n");
877f5b1c8a1SJohn Marino goto end;
878f5b1c8a1SJohn Marino }
879f5b1c8a1SJohn Marino }
8808edacedfSDaniel Fojt if (req_config.x509) {
881f5b1c8a1SJohn Marino EVP_PKEY *tmppkey;
882*de0e0e4dSAntonio Huete Jimenez
883f5b1c8a1SJohn Marino X509V3_CTX ext_ctx;
884f5b1c8a1SJohn Marino if ((x509ss = X509_new()) == NULL)
885f5b1c8a1SJohn Marino goto end;
886f5b1c8a1SJohn Marino
887f5b1c8a1SJohn Marino /* Set version to V3 */
8888edacedfSDaniel Fojt if ((req_config.extensions != NULL || addext_conf != NULL) &&
889cca6fc52SDaniel Fojt !X509_set_version(x509ss, 2))
890f5b1c8a1SJohn Marino goto end;
8918edacedfSDaniel Fojt if (req_config.serial) {
8928edacedfSDaniel Fojt if (!X509_set_serialNumber(x509ss, req_config.serial))
893f5b1c8a1SJohn Marino goto end;
894f5b1c8a1SJohn Marino } else {
895f5b1c8a1SJohn Marino if (!rand_serial(NULL,
896f5b1c8a1SJohn Marino X509_get_serialNumber(x509ss)))
897f5b1c8a1SJohn Marino goto end;
898f5b1c8a1SJohn Marino }
899f5b1c8a1SJohn Marino
900f5b1c8a1SJohn Marino if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req)))
901f5b1c8a1SJohn Marino goto end;
902f5b1c8a1SJohn Marino if (!X509_gmtime_adj(X509_get_notBefore(x509ss), 0))
903f5b1c8a1SJohn Marino goto end;
9048edacedfSDaniel Fojt if (!X509_time_adj_ex(X509_get_notAfter(x509ss), req_config.days, 0, NULL))
905f5b1c8a1SJohn Marino goto end;
906f5b1c8a1SJohn Marino if (!X509_set_subject_name(x509ss, X509_REQ_get_subject_name(req)))
907f5b1c8a1SJohn Marino goto end;
908*de0e0e4dSAntonio Huete Jimenez if ((tmppkey = X509_REQ_get0_pubkey(req)) == NULL)
909f5b1c8a1SJohn Marino goto end;
910*de0e0e4dSAntonio Huete Jimenez if (!X509_set_pubkey(x509ss, tmppkey))
911*de0e0e4dSAntonio Huete Jimenez goto end;
912f5b1c8a1SJohn Marino
913f5b1c8a1SJohn Marino /* Set up V3 context struct */
914f5b1c8a1SJohn Marino
915f5b1c8a1SJohn Marino X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0);
916f5b1c8a1SJohn Marino X509V3_set_nconf(&ext_ctx, req_conf);
917f5b1c8a1SJohn Marino
918f5b1c8a1SJohn Marino /* Add extensions */
9198edacedfSDaniel Fojt if (req_config.extensions && !X509V3_EXT_add_nconf(req_conf,
9208edacedfSDaniel Fojt &ext_ctx, req_config.extensions, x509ss)) {
921f5b1c8a1SJohn Marino BIO_printf(bio_err,
922f5b1c8a1SJohn Marino "Error Loading extension section %s\n",
9238edacedfSDaniel Fojt req_config.extensions);
924f5b1c8a1SJohn Marino goto end;
925f5b1c8a1SJohn Marino }
926cca6fc52SDaniel Fojt if (addext_conf != NULL &&
927cca6fc52SDaniel Fojt !X509V3_EXT_add_nconf(addext_conf, &ext_ctx,
928cca6fc52SDaniel Fojt "default", x509ss)) {
929cca6fc52SDaniel Fojt BIO_printf(bio_err,
930cca6fc52SDaniel Fojt "Error Loading command line extensions\n");
931cca6fc52SDaniel Fojt goto end;
932cca6fc52SDaniel Fojt }
9338edacedfSDaniel Fojt i = do_X509_sign(bio_err, x509ss, pkey, req_config.digest, req_config.sigopts);
934f5b1c8a1SJohn Marino if (!i) {
935f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
936f5b1c8a1SJohn Marino goto end;
937f5b1c8a1SJohn Marino }
938f5b1c8a1SJohn Marino } else {
939f5b1c8a1SJohn Marino X509V3_CTX ext_ctx;
940f5b1c8a1SJohn Marino
941f5b1c8a1SJohn Marino /* Set up V3 context struct */
942f5b1c8a1SJohn Marino
943f5b1c8a1SJohn Marino X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0);
944f5b1c8a1SJohn Marino X509V3_set_nconf(&ext_ctx, req_conf);
945f5b1c8a1SJohn Marino
946f5b1c8a1SJohn Marino /* Add extensions */
9478edacedfSDaniel Fojt if (req_config.req_exts && !X509V3_EXT_REQ_add_nconf(req_conf,
9488edacedfSDaniel Fojt &ext_ctx, req_config.req_exts, req)) {
949f5b1c8a1SJohn Marino BIO_printf(bio_err,
950f5b1c8a1SJohn Marino "Error Loading extension section %s\n",
9518edacedfSDaniel Fojt req_config.req_exts);
952f5b1c8a1SJohn Marino goto end;
953f5b1c8a1SJohn Marino }
954cca6fc52SDaniel Fojt if (addext_conf != NULL &&
955cca6fc52SDaniel Fojt !X509V3_EXT_REQ_add_nconf(addext_conf, &ext_ctx,
956cca6fc52SDaniel Fojt "default", req)) {
957cca6fc52SDaniel Fojt BIO_printf(bio_err,
958cca6fc52SDaniel Fojt "Error Loading command line extensions\n");
959cca6fc52SDaniel Fojt goto end;
960cca6fc52SDaniel Fojt }
9618edacedfSDaniel Fojt i = do_X509_REQ_sign(bio_err, req, pkey, req_config.digest, req_config.sigopts);
962f5b1c8a1SJohn Marino if (!i) {
963f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
964f5b1c8a1SJohn Marino goto end;
965f5b1c8a1SJohn Marino }
966f5b1c8a1SJohn Marino }
967f5b1c8a1SJohn Marino }
9688edacedfSDaniel Fojt if (req_config.subj && req_config.x509) {
9698edacedfSDaniel Fojt BIO_printf(bio_err, "Cannot modify certificate subject\n");
970f5b1c8a1SJohn Marino goto end;
971f5b1c8a1SJohn Marino }
9728edacedfSDaniel Fojt if (req_config.subj && !req_config.x509) {
9738edacedfSDaniel Fojt if (req_config.verbose) {
974f5b1c8a1SJohn Marino BIO_printf(bio_err, "Modifying Request's Subject\n");
9758edacedfSDaniel Fojt print_name(bio_err, "old subject=", X509_REQ_get_subject_name(req), req_config.nmflag);
976f5b1c8a1SJohn Marino }
9778edacedfSDaniel Fojt if (build_subject(req, req_config.subj, req_config.chtype, req_config.multirdn) == 0) {
978f5b1c8a1SJohn Marino BIO_printf(bio_err, "ERROR: cannot modify subject\n");
979f5b1c8a1SJohn Marino ex = 1;
980f5b1c8a1SJohn Marino goto end;
981f5b1c8a1SJohn Marino }
982f5b1c8a1SJohn Marino
9838edacedfSDaniel Fojt if (req_config.verbose) {
9848edacedfSDaniel Fojt print_name(bio_err, "new subject=", X509_REQ_get_subject_name(req), req_config.nmflag);
985f5b1c8a1SJohn Marino }
986f5b1c8a1SJohn Marino }
9878edacedfSDaniel Fojt if (req_config.verify && !req_config.x509) {
988*de0e0e4dSAntonio Huete Jimenez EVP_PKEY *pubkey = pkey;
989f5b1c8a1SJohn Marino
990*de0e0e4dSAntonio Huete Jimenez if (pubkey == NULL)
991*de0e0e4dSAntonio Huete Jimenez pubkey = X509_REQ_get0_pubkey(req);
992*de0e0e4dSAntonio Huete Jimenez if (pubkey == NULL)
993f5b1c8a1SJohn Marino goto end;
994*de0e0e4dSAntonio Huete Jimenez i = X509_REQ_verify(req, pubkey);
995f5b1c8a1SJohn Marino if (i < 0) {
996f5b1c8a1SJohn Marino goto end;
997f5b1c8a1SJohn Marino } else if (i == 0) {
998f5b1c8a1SJohn Marino BIO_printf(bio_err, "verify failure\n");
999f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
1000f5b1c8a1SJohn Marino } else /* if (i > 0) */
1001f5b1c8a1SJohn Marino BIO_printf(bio_err, "verify OK\n");
1002f5b1c8a1SJohn Marino }
10038edacedfSDaniel Fojt if (req_config.noout && !req_config.text && !req_config.modulus && !req_config.subject && !req_config.pubkey) {
1004f5b1c8a1SJohn Marino ex = 0;
1005f5b1c8a1SJohn Marino goto end;
1006f5b1c8a1SJohn Marino }
10078edacedfSDaniel Fojt if (req_config.outfile == NULL) {
1008f5b1c8a1SJohn Marino BIO_set_fp(out, stdout, BIO_NOCLOSE);
1009f5b1c8a1SJohn Marino } else {
10108edacedfSDaniel Fojt if ((req_config.keyout != NULL) && (strcmp(req_config.outfile, req_config.keyout) == 0))
10118edacedfSDaniel Fojt i = (int) BIO_append_filename(out, req_config.outfile);
1012f5b1c8a1SJohn Marino else
10138edacedfSDaniel Fojt i = (int) BIO_write_filename(out, req_config.outfile);
1014f5b1c8a1SJohn Marino if (!i) {
10158edacedfSDaniel Fojt perror(req_config.outfile);
1016f5b1c8a1SJohn Marino goto end;
1017f5b1c8a1SJohn Marino }
1018f5b1c8a1SJohn Marino }
1019f5b1c8a1SJohn Marino
10208edacedfSDaniel Fojt if (req_config.pubkey) {
1021f5b1c8a1SJohn Marino EVP_PKEY *tpubkey;
1022*de0e0e4dSAntonio Huete Jimenez
1023*de0e0e4dSAntonio Huete Jimenez if ((tpubkey = X509_REQ_get0_pubkey(req)) == NULL) {
1024f5b1c8a1SJohn Marino BIO_printf(bio_err, "Error getting public key\n");
1025f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
1026f5b1c8a1SJohn Marino goto end;
1027f5b1c8a1SJohn Marino }
1028f5b1c8a1SJohn Marino PEM_write_bio_PUBKEY(out, tpubkey);
1029f5b1c8a1SJohn Marino }
10308edacedfSDaniel Fojt if (req_config.text) {
10318edacedfSDaniel Fojt if (req_config.x509)
10328edacedfSDaniel Fojt X509_print_ex(out, x509ss, req_config.nmflag, req_config.reqflag);
1033f5b1c8a1SJohn Marino else
10348edacedfSDaniel Fojt X509_REQ_print_ex(out, req, req_config.nmflag, req_config.reqflag);
1035f5b1c8a1SJohn Marino }
10368edacedfSDaniel Fojt if (req_config.subject) {
10378edacedfSDaniel Fojt if (req_config.x509)
10388edacedfSDaniel Fojt print_name(out, "subject=", X509_get_subject_name(x509ss), req_config.nmflag);
1039f5b1c8a1SJohn Marino else
10408edacedfSDaniel Fojt print_name(out, "subject=", X509_REQ_get_subject_name(req), req_config.nmflag);
1041f5b1c8a1SJohn Marino }
10428edacedfSDaniel Fojt if (req_config.modulus) {
1043f5b1c8a1SJohn Marino EVP_PKEY *tpubkey;
1044f5b1c8a1SJohn Marino
10458edacedfSDaniel Fojt if (req_config.x509)
1046*de0e0e4dSAntonio Huete Jimenez tpubkey = X509_get0_pubkey(x509ss);
1047f5b1c8a1SJohn Marino else
1048*de0e0e4dSAntonio Huete Jimenez tpubkey = X509_REQ_get0_pubkey(req);
1049f5b1c8a1SJohn Marino if (tpubkey == NULL) {
1050f5b1c8a1SJohn Marino fprintf(stdout, "Modulus=unavailable\n");
1051f5b1c8a1SJohn Marino goto end;
1052f5b1c8a1SJohn Marino }
1053f5b1c8a1SJohn Marino fprintf(stdout, "Modulus=");
1054*de0e0e4dSAntonio Huete Jimenez if (EVP_PKEY_base_id(tpubkey) == EVP_PKEY_RSA) {
1055*de0e0e4dSAntonio Huete Jimenez const BIGNUM *n = NULL;
1056*de0e0e4dSAntonio Huete Jimenez
1057*de0e0e4dSAntonio Huete Jimenez RSA_get0_key(EVP_PKEY_get0_RSA(tpubkey), &n, NULL, NULL);
1058*de0e0e4dSAntonio Huete Jimenez
1059*de0e0e4dSAntonio Huete Jimenez BN_print(out, n);
1060*de0e0e4dSAntonio Huete Jimenez } else
1061f5b1c8a1SJohn Marino fprintf(stdout, "Wrong Algorithm type");
1062f5b1c8a1SJohn Marino fprintf(stdout, "\n");
1063f5b1c8a1SJohn Marino }
10648edacedfSDaniel Fojt if (!req_config.noout && !req_config.x509) {
10658edacedfSDaniel Fojt if (req_config.outformat == FORMAT_ASN1)
1066f5b1c8a1SJohn Marino i = i2d_X509_REQ_bio(out, req);
10678edacedfSDaniel Fojt else if (req_config.outformat == FORMAT_PEM) {
10688edacedfSDaniel Fojt if (req_config.newhdr)
1069f5b1c8a1SJohn Marino i = PEM_write_bio_X509_REQ_NEW(out, req);
1070f5b1c8a1SJohn Marino else
1071f5b1c8a1SJohn Marino i = PEM_write_bio_X509_REQ(out, req);
1072f5b1c8a1SJohn Marino } else {
1073f5b1c8a1SJohn Marino BIO_printf(bio_err, "bad output format specified for outfile\n");
1074f5b1c8a1SJohn Marino goto end;
1075f5b1c8a1SJohn Marino }
1076f5b1c8a1SJohn Marino if (!i) {
1077f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to write X509 request\n");
1078f5b1c8a1SJohn Marino goto end;
1079f5b1c8a1SJohn Marino }
1080f5b1c8a1SJohn Marino }
10818edacedfSDaniel Fojt if (!req_config.noout && req_config.x509 && (x509ss != NULL)) {
10828edacedfSDaniel Fojt if (req_config.outformat == FORMAT_ASN1)
1083f5b1c8a1SJohn Marino i = i2d_X509_bio(out, x509ss);
10848edacedfSDaniel Fojt else if (req_config.outformat == FORMAT_PEM)
1085f5b1c8a1SJohn Marino i = PEM_write_bio_X509(out, x509ss);
1086f5b1c8a1SJohn Marino else {
1087f5b1c8a1SJohn Marino BIO_printf(bio_err, "bad output format specified for outfile\n");
1088f5b1c8a1SJohn Marino goto end;
1089f5b1c8a1SJohn Marino }
1090f5b1c8a1SJohn Marino if (!i) {
1091f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to write X509 certificate\n");
1092f5b1c8a1SJohn Marino goto end;
1093f5b1c8a1SJohn Marino }
1094f5b1c8a1SJohn Marino }
1095f5b1c8a1SJohn Marino ex = 0;
1096f5b1c8a1SJohn Marino end:
1097f5b1c8a1SJohn Marino if (ex) {
1098f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
1099f5b1c8a1SJohn Marino }
1100f5b1c8a1SJohn Marino if ((req_conf != NULL) && (req_conf != config))
1101f5b1c8a1SJohn Marino NCONF_free(req_conf);
1102cca6fc52SDaniel Fojt NCONF_free(addext_conf);
11038edacedfSDaniel Fojt BIO_free(req_config.addext_bio);
1104f5b1c8a1SJohn Marino BIO_free(in);
1105f5b1c8a1SJohn Marino BIO_free_all(out);
1106f5b1c8a1SJohn Marino EVP_PKEY_free(pkey);
1107f5b1c8a1SJohn Marino if (genctx)
1108f5b1c8a1SJohn Marino EVP_PKEY_CTX_free(genctx);
11098edacedfSDaniel Fojt if (req_config.pkeyopts)
11108edacedfSDaniel Fojt sk_OPENSSL_STRING_free(req_config.pkeyopts);
11118edacedfSDaniel Fojt if (req_config.sigopts)
11128edacedfSDaniel Fojt sk_OPENSSL_STRING_free(req_config.sigopts);
11138edacedfSDaniel Fojt lh_OPENSSL_STRING_doall(req_config.addexts, (LHASH_DOALL_FN_TYPE)exts_cleanup);
11148edacedfSDaniel Fojt lh_OPENSSL_STRING_free(req_config.addexts);
1115f5b1c8a1SJohn Marino free(keyalgstr);
1116f5b1c8a1SJohn Marino X509_REQ_free(req);
1117f5b1c8a1SJohn Marino X509_free(x509ss);
11188edacedfSDaniel Fojt ASN1_INTEGER_free(req_config.serial);
11198edacedfSDaniel Fojt if (req_config.passargin && passin)
1120f5b1c8a1SJohn Marino free(passin);
11218edacedfSDaniel Fojt if (req_config.passargout && passout)
1122f5b1c8a1SJohn Marino free(passout);
1123f5b1c8a1SJohn Marino OBJ_cleanup();
1124f5b1c8a1SJohn Marino
1125f5b1c8a1SJohn Marino return (ex);
1126f5b1c8a1SJohn Marino }
1127f5b1c8a1SJohn Marino
1128f5b1c8a1SJohn Marino static int
make_REQ(X509_REQ * req,EVP_PKEY * pkey,char * subj,int multirdn,int attribs,unsigned long chtype)1129f5b1c8a1SJohn Marino make_REQ(X509_REQ * req, EVP_PKEY * pkey, char *subj, int multirdn,
1130f5b1c8a1SJohn Marino int attribs, unsigned long chtype)
1131f5b1c8a1SJohn Marino {
1132f5b1c8a1SJohn Marino int ret = 0, i;
1133f5b1c8a1SJohn Marino char no_prompt = 0;
1134f5b1c8a1SJohn Marino STACK_OF(CONF_VALUE) * dn_sk, *attr_sk = NULL;
1135f5b1c8a1SJohn Marino char *tmp, *dn_sect, *attr_sect;
1136f5b1c8a1SJohn Marino
1137f5b1c8a1SJohn Marino tmp = NCONF_get_string(req_conf, SECTION, PROMPT);
1138f5b1c8a1SJohn Marino if (tmp == NULL)
1139f5b1c8a1SJohn Marino ERR_clear_error();
1140f5b1c8a1SJohn Marino if ((tmp != NULL) && !strcmp(tmp, "no"))
1141f5b1c8a1SJohn Marino no_prompt = 1;
1142f5b1c8a1SJohn Marino
1143f5b1c8a1SJohn Marino dn_sect = NCONF_get_string(req_conf, SECTION, DISTINGUISHED_NAME);
1144f5b1c8a1SJohn Marino if (dn_sect == NULL) {
1145f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to find '%s' in config\n",
1146f5b1c8a1SJohn Marino DISTINGUISHED_NAME);
1147f5b1c8a1SJohn Marino goto err;
1148f5b1c8a1SJohn Marino }
1149f5b1c8a1SJohn Marino dn_sk = NCONF_get_section(req_conf, dn_sect);
1150f5b1c8a1SJohn Marino if (dn_sk == NULL) {
1151f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to get '%s' section\n", dn_sect);
1152f5b1c8a1SJohn Marino goto err;
1153f5b1c8a1SJohn Marino }
1154f5b1c8a1SJohn Marino attr_sect = NCONF_get_string(req_conf, SECTION, ATTRIBUTES);
1155f5b1c8a1SJohn Marino if (attr_sect == NULL) {
1156f5b1c8a1SJohn Marino ERR_clear_error();
1157f5b1c8a1SJohn Marino attr_sk = NULL;
1158f5b1c8a1SJohn Marino } else {
1159f5b1c8a1SJohn Marino attr_sk = NCONF_get_section(req_conf, attr_sect);
1160f5b1c8a1SJohn Marino if (attr_sk == NULL) {
1161f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to get '%s' section\n", attr_sect);
1162f5b1c8a1SJohn Marino goto err;
1163f5b1c8a1SJohn Marino }
1164f5b1c8a1SJohn Marino }
1165f5b1c8a1SJohn Marino
1166f5b1c8a1SJohn Marino /* setup version number */
1167f5b1c8a1SJohn Marino if (!X509_REQ_set_version(req, 0L))
1168f5b1c8a1SJohn Marino goto err; /* version 1 */
1169f5b1c8a1SJohn Marino
1170f5b1c8a1SJohn Marino if (no_prompt)
1171f5b1c8a1SJohn Marino i = auto_info(req, dn_sk, attr_sk, attribs, chtype);
1172f5b1c8a1SJohn Marino else {
1173f5b1c8a1SJohn Marino if (subj)
1174f5b1c8a1SJohn Marino i = build_subject(req, subj, chtype, multirdn);
1175f5b1c8a1SJohn Marino else
1176f5b1c8a1SJohn Marino i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs, chtype);
1177f5b1c8a1SJohn Marino }
1178f5b1c8a1SJohn Marino if (!i)
1179f5b1c8a1SJohn Marino goto err;
1180f5b1c8a1SJohn Marino
1181f5b1c8a1SJohn Marino if (!X509_REQ_set_pubkey(req, pkey))
1182f5b1c8a1SJohn Marino goto err;
1183f5b1c8a1SJohn Marino
1184f5b1c8a1SJohn Marino ret = 1;
1185f5b1c8a1SJohn Marino err:
1186f5b1c8a1SJohn Marino return (ret);
1187f5b1c8a1SJohn Marino }
1188f5b1c8a1SJohn Marino
1189f5b1c8a1SJohn Marino /*
1190f5b1c8a1SJohn Marino * subject is expected to be in the format /type0=value0/type1=value1/type2=...
1191f5b1c8a1SJohn Marino * where characters may be escaped by \
1192f5b1c8a1SJohn Marino */
1193f5b1c8a1SJohn Marino static int
build_subject(X509_REQ * req,char * subject,unsigned long chtype,int multirdn)1194f5b1c8a1SJohn Marino build_subject(X509_REQ * req, char *subject, unsigned long chtype, int multirdn)
1195f5b1c8a1SJohn Marino {
1196f5b1c8a1SJohn Marino X509_NAME *n;
1197f5b1c8a1SJohn Marino
1198f5b1c8a1SJohn Marino if (!(n = parse_name(subject, chtype, multirdn)))
1199f5b1c8a1SJohn Marino return 0;
1200f5b1c8a1SJohn Marino
1201f5b1c8a1SJohn Marino if (!X509_REQ_set_subject_name(req, n)) {
1202f5b1c8a1SJohn Marino X509_NAME_free(n);
1203f5b1c8a1SJohn Marino return 0;
1204f5b1c8a1SJohn Marino }
1205f5b1c8a1SJohn Marino X509_NAME_free(n);
1206f5b1c8a1SJohn Marino return 1;
1207f5b1c8a1SJohn Marino }
1208f5b1c8a1SJohn Marino
1209f5b1c8a1SJohn Marino
1210f5b1c8a1SJohn Marino static int
prompt_info(X509_REQ * req,STACK_OF (CONF_VALUE)* dn_sk,char * dn_sect,STACK_OF (CONF_VALUE)* attr_sk,char * attr_sect,int attribs,unsigned long chtype)1211f5b1c8a1SJohn Marino prompt_info(X509_REQ * req,
1212f5b1c8a1SJohn Marino STACK_OF(CONF_VALUE) * dn_sk, char *dn_sect,
1213f5b1c8a1SJohn Marino STACK_OF(CONF_VALUE) * attr_sk, char *attr_sect, int attribs,
1214f5b1c8a1SJohn Marino unsigned long chtype)
1215f5b1c8a1SJohn Marino {
1216f5b1c8a1SJohn Marino int i;
1217f5b1c8a1SJohn Marino char *p, *q;
1218f5b1c8a1SJohn Marino char buf[100];
1219f5b1c8a1SJohn Marino int nid, mval;
1220f5b1c8a1SJohn Marino long n_min, n_max;
1221f5b1c8a1SJohn Marino char *type, *value;
1222f5b1c8a1SJohn Marino const char *def;
1223f5b1c8a1SJohn Marino CONF_VALUE *v;
1224f5b1c8a1SJohn Marino X509_NAME *subj;
1225f5b1c8a1SJohn Marino subj = X509_REQ_get_subject_name(req);
1226f5b1c8a1SJohn Marino
12278edacedfSDaniel Fojt if (!req_config.batch) {
1228f5b1c8a1SJohn Marino BIO_printf(bio_err, "You are about to be asked to enter information that will be incorporated\n");
1229f5b1c8a1SJohn Marino BIO_printf(bio_err, "into your certificate request.\n");
1230f5b1c8a1SJohn Marino BIO_printf(bio_err, "What you are about to enter is what is called a Distinguished Name or a DN.\n");
1231f5b1c8a1SJohn Marino BIO_printf(bio_err, "There are quite a few fields but you can leave some blank\n");
1232f5b1c8a1SJohn Marino BIO_printf(bio_err, "For some fields there will be a default value,\n");
1233f5b1c8a1SJohn Marino BIO_printf(bio_err, "If you enter '.', the field will be left blank.\n");
1234f5b1c8a1SJohn Marino BIO_printf(bio_err, "-----\n");
1235f5b1c8a1SJohn Marino }
1236f5b1c8a1SJohn Marino if (sk_CONF_VALUE_num(dn_sk)) {
1237f5b1c8a1SJohn Marino i = -1;
1238f5b1c8a1SJohn Marino start: for (;;) {
1239f5b1c8a1SJohn Marino int ret;
1240f5b1c8a1SJohn Marino i++;
1241f5b1c8a1SJohn Marino if (sk_CONF_VALUE_num(dn_sk) <= i)
1242f5b1c8a1SJohn Marino break;
1243f5b1c8a1SJohn Marino
1244f5b1c8a1SJohn Marino v = sk_CONF_VALUE_value(dn_sk, i);
1245f5b1c8a1SJohn Marino p = q = NULL;
1246f5b1c8a1SJohn Marino type = v->name;
1247f5b1c8a1SJohn Marino if (!check_end(type, "_min") || !check_end(type, "_max") ||
1248f5b1c8a1SJohn Marino !check_end(type, "_default") ||
1249f5b1c8a1SJohn Marino !check_end(type, "_value"))
1250f5b1c8a1SJohn Marino continue;
1251f5b1c8a1SJohn Marino /*
1252f5b1c8a1SJohn Marino * Skip past any leading X. X: X, etc to allow for
1253f5b1c8a1SJohn Marino * multiple instances
1254f5b1c8a1SJohn Marino */
1255f5b1c8a1SJohn Marino for (p = v->name; *p; p++)
1256f5b1c8a1SJohn Marino if ((*p == ':') || (*p == ',') ||
1257f5b1c8a1SJohn Marino (*p == '.')) {
1258f5b1c8a1SJohn Marino p++;
1259f5b1c8a1SJohn Marino if (*p)
1260f5b1c8a1SJohn Marino type = p;
1261f5b1c8a1SJohn Marino break;
1262f5b1c8a1SJohn Marino }
1263f5b1c8a1SJohn Marino if (*type == '+') {
1264f5b1c8a1SJohn Marino mval = -1;
1265f5b1c8a1SJohn Marino type++;
1266f5b1c8a1SJohn Marino } else
1267f5b1c8a1SJohn Marino mval = 0;
1268f5b1c8a1SJohn Marino /* If OBJ not recognised ignore it */
1269f5b1c8a1SJohn Marino if ((nid = OBJ_txt2nid(type)) == NID_undef)
1270f5b1c8a1SJohn Marino goto start;
1271f5b1c8a1SJohn Marino ret = snprintf(buf, sizeof buf, "%s_default", v->name);
1272cca6fc52SDaniel Fojt if (ret < 0 || ret >= sizeof(buf)) {
1273f5b1c8a1SJohn Marino BIO_printf(bio_err, "Name '%s' too long for default\n",
1274f5b1c8a1SJohn Marino v->name);
1275f5b1c8a1SJohn Marino return 0;
1276f5b1c8a1SJohn Marino }
1277f5b1c8a1SJohn Marino if ((def = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) {
1278f5b1c8a1SJohn Marino ERR_clear_error();
1279f5b1c8a1SJohn Marino def = "";
1280f5b1c8a1SJohn Marino }
1281f5b1c8a1SJohn Marino ret = snprintf(buf, sizeof buf, "%s_value", v->name);
1282cca6fc52SDaniel Fojt if (ret < 0 || ret >= sizeof(buf)) {
1283f5b1c8a1SJohn Marino BIO_printf(bio_err, "Name '%s' too long for value\n",
1284f5b1c8a1SJohn Marino v->name);
1285f5b1c8a1SJohn Marino return 0;
1286f5b1c8a1SJohn Marino }
1287f5b1c8a1SJohn Marino if ((value = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) {
1288f5b1c8a1SJohn Marino ERR_clear_error();
1289f5b1c8a1SJohn Marino value = NULL;
1290f5b1c8a1SJohn Marino }
1291f5b1c8a1SJohn Marino ret = snprintf(buf, sizeof buf, "%s_min", v->name);
1292cca6fc52SDaniel Fojt if (ret < 0 || ret >= sizeof(buf)) {
1293f5b1c8a1SJohn Marino BIO_printf(bio_err, "Name '%s' too long for min\n",
1294f5b1c8a1SJohn Marino v->name);
1295f5b1c8a1SJohn Marino return 0;
1296f5b1c8a1SJohn Marino }
1297f5b1c8a1SJohn Marino if (!NCONF_get_number(req_conf, dn_sect, buf, &n_min)) {
1298f5b1c8a1SJohn Marino ERR_clear_error();
1299f5b1c8a1SJohn Marino n_min = -1;
1300f5b1c8a1SJohn Marino }
1301f5b1c8a1SJohn Marino ret = snprintf(buf, sizeof buf, "%s_max", v->name);
1302cca6fc52SDaniel Fojt if (ret < 0 || ret >= sizeof(buf)) {
1303f5b1c8a1SJohn Marino BIO_printf(bio_err, "Name '%s' too long for max\n",
1304f5b1c8a1SJohn Marino v->name);
1305f5b1c8a1SJohn Marino return 0;
1306f5b1c8a1SJohn Marino }
1307f5b1c8a1SJohn Marino if (!NCONF_get_number(req_conf, dn_sect, buf, &n_max)) {
1308f5b1c8a1SJohn Marino ERR_clear_error();
1309f5b1c8a1SJohn Marino n_max = -1;
1310f5b1c8a1SJohn Marino }
1311f5b1c8a1SJohn Marino if (!add_DN_object(subj, v->value, def, value, nid,
1312f5b1c8a1SJohn Marino n_min, n_max, chtype, mval))
1313f5b1c8a1SJohn Marino return 0;
1314f5b1c8a1SJohn Marino }
1315f5b1c8a1SJohn Marino if (X509_NAME_entry_count(subj) == 0) {
1316f5b1c8a1SJohn Marino BIO_printf(bio_err, "error, no objects specified in config file\n");
1317f5b1c8a1SJohn Marino return 0;
1318f5b1c8a1SJohn Marino }
1319f5b1c8a1SJohn Marino if (attribs) {
1320f5b1c8a1SJohn Marino if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0) &&
13218edacedfSDaniel Fojt (!req_config.batch)) {
1322f5b1c8a1SJohn Marino BIO_printf(bio_err,
1323f5b1c8a1SJohn Marino "\nPlease enter the following 'extra' attributes\n");
1324f5b1c8a1SJohn Marino BIO_printf(bio_err,
1325f5b1c8a1SJohn Marino "to be sent with your certificate request\n");
1326f5b1c8a1SJohn Marino }
1327f5b1c8a1SJohn Marino i = -1;
1328f5b1c8a1SJohn Marino start2: for (;;) {
1329f5b1c8a1SJohn Marino int ret;
1330f5b1c8a1SJohn Marino i++;
1331f5b1c8a1SJohn Marino if ((attr_sk == NULL) ||
1332f5b1c8a1SJohn Marino (sk_CONF_VALUE_num(attr_sk) <= i))
1333f5b1c8a1SJohn Marino break;
1334f5b1c8a1SJohn Marino
1335f5b1c8a1SJohn Marino v = sk_CONF_VALUE_value(attr_sk, i);
1336f5b1c8a1SJohn Marino type = v->name;
1337f5b1c8a1SJohn Marino if ((nid = OBJ_txt2nid(type)) == NID_undef)
1338f5b1c8a1SJohn Marino goto start2;
1339f5b1c8a1SJohn Marino ret = snprintf(buf, sizeof buf, "%s_default", type);
1340cca6fc52SDaniel Fojt if (ret < 0 || ret >= sizeof(buf)) {
1341f5b1c8a1SJohn Marino BIO_printf(bio_err, "Name '%s' too long for default\n",
1342f5b1c8a1SJohn Marino v->name);
1343f5b1c8a1SJohn Marino return 0;
1344f5b1c8a1SJohn Marino }
1345f5b1c8a1SJohn Marino if ((def = NCONF_get_string(req_conf, attr_sect, buf))
1346f5b1c8a1SJohn Marino == NULL) {
1347f5b1c8a1SJohn Marino ERR_clear_error();
1348f5b1c8a1SJohn Marino def = "";
1349f5b1c8a1SJohn Marino }
1350f5b1c8a1SJohn Marino ret = snprintf(buf, sizeof buf, "%s_value", type);
1351cca6fc52SDaniel Fojt if (ret < 0 || ret >= sizeof(buf)) {
1352f5b1c8a1SJohn Marino BIO_printf(bio_err, "Name '%s' too long for value\n",
1353f5b1c8a1SJohn Marino v->name);
1354f5b1c8a1SJohn Marino return 0;
1355f5b1c8a1SJohn Marino }
1356f5b1c8a1SJohn Marino if ((value = NCONF_get_string(req_conf, attr_sect, buf))
1357f5b1c8a1SJohn Marino == NULL) {
1358f5b1c8a1SJohn Marino ERR_clear_error();
1359f5b1c8a1SJohn Marino value = NULL;
1360f5b1c8a1SJohn Marino }
1361f5b1c8a1SJohn Marino ret = snprintf(buf, sizeof buf, "%s_min", type);
1362cca6fc52SDaniel Fojt if (ret < 0 || ret >= sizeof(buf)) {
1363f5b1c8a1SJohn Marino BIO_printf(bio_err, "Name '%s' too long for min\n",
1364f5b1c8a1SJohn Marino v->name);
1365f5b1c8a1SJohn Marino return 0;
1366f5b1c8a1SJohn Marino }
1367f5b1c8a1SJohn Marino if (!NCONF_get_number(req_conf, attr_sect, buf, &n_min)) {
1368f5b1c8a1SJohn Marino ERR_clear_error();
1369f5b1c8a1SJohn Marino n_min = -1;
1370f5b1c8a1SJohn Marino }
1371f5b1c8a1SJohn Marino ret = snprintf(buf, sizeof buf, "%s_max", type);
1372cca6fc52SDaniel Fojt if (ret < 0 || ret >= sizeof(buf)) {
1373f5b1c8a1SJohn Marino BIO_printf(bio_err, "Name '%s' too long for max\n",
1374f5b1c8a1SJohn Marino v->name);
1375f5b1c8a1SJohn Marino return 0;
1376f5b1c8a1SJohn Marino }
1377f5b1c8a1SJohn Marino if (!NCONF_get_number(req_conf, attr_sect, buf, &n_max)) {
1378f5b1c8a1SJohn Marino ERR_clear_error();
1379f5b1c8a1SJohn Marino n_max = -1;
1380f5b1c8a1SJohn Marino }
1381f5b1c8a1SJohn Marino if (!add_attribute_object(req,
1382f5b1c8a1SJohn Marino v->value, def, value, nid, n_min, n_max, chtype))
1383f5b1c8a1SJohn Marino return 0;
1384f5b1c8a1SJohn Marino }
1385f5b1c8a1SJohn Marino }
1386f5b1c8a1SJohn Marino } else {
1387f5b1c8a1SJohn Marino BIO_printf(bio_err, "No template, please set one up.\n");
1388f5b1c8a1SJohn Marino return 0;
1389f5b1c8a1SJohn Marino }
1390f5b1c8a1SJohn Marino
1391f5b1c8a1SJohn Marino return 1;
1392f5b1c8a1SJohn Marino
1393f5b1c8a1SJohn Marino }
1394f5b1c8a1SJohn Marino
1395f5b1c8a1SJohn Marino static int
auto_info(X509_REQ * req,STACK_OF (CONF_VALUE)* dn_sk,STACK_OF (CONF_VALUE)* attr_sk,int attribs,unsigned long chtype)1396f5b1c8a1SJohn Marino auto_info(X509_REQ * req, STACK_OF(CONF_VALUE) * dn_sk,
1397f5b1c8a1SJohn Marino STACK_OF(CONF_VALUE) * attr_sk, int attribs, unsigned long chtype)
1398f5b1c8a1SJohn Marino {
1399f5b1c8a1SJohn Marino int i;
1400f5b1c8a1SJohn Marino char *p, *q;
1401f5b1c8a1SJohn Marino char *type;
1402f5b1c8a1SJohn Marino CONF_VALUE *v;
1403f5b1c8a1SJohn Marino X509_NAME *subj;
1404f5b1c8a1SJohn Marino
1405f5b1c8a1SJohn Marino subj = X509_REQ_get_subject_name(req);
1406f5b1c8a1SJohn Marino
1407f5b1c8a1SJohn Marino for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
1408f5b1c8a1SJohn Marino int mval;
1409f5b1c8a1SJohn Marino v = sk_CONF_VALUE_value(dn_sk, i);
1410f5b1c8a1SJohn Marino p = q = NULL;
1411f5b1c8a1SJohn Marino type = v->name;
1412f5b1c8a1SJohn Marino /*
1413f5b1c8a1SJohn Marino * Skip past any leading X. X: X, etc to allow for multiple
1414f5b1c8a1SJohn Marino * instances
1415f5b1c8a1SJohn Marino */
1416f5b1c8a1SJohn Marino for (p = v->name; *p; p++)
1417f5b1c8a1SJohn Marino if ((*p == ':') || (*p == ',') || (*p == '.')) {
1418f5b1c8a1SJohn Marino p++;
1419f5b1c8a1SJohn Marino if (*p)
1420f5b1c8a1SJohn Marino type = p;
1421f5b1c8a1SJohn Marino break;
1422f5b1c8a1SJohn Marino }
1423f5b1c8a1SJohn Marino if (*p == '+') {
1424f5b1c8a1SJohn Marino p++;
1425f5b1c8a1SJohn Marino mval = -1;
1426f5b1c8a1SJohn Marino } else
1427f5b1c8a1SJohn Marino mval = 0;
1428f5b1c8a1SJohn Marino if (!X509_NAME_add_entry_by_txt(subj, type, chtype,
1429f5b1c8a1SJohn Marino (unsigned char *) v->value, -1, -1, mval))
1430f5b1c8a1SJohn Marino return 0;
1431f5b1c8a1SJohn Marino
1432f5b1c8a1SJohn Marino }
1433f5b1c8a1SJohn Marino
1434f5b1c8a1SJohn Marino if (!X509_NAME_entry_count(subj)) {
1435f5b1c8a1SJohn Marino BIO_printf(bio_err, "error, no objects specified in config file\n");
1436f5b1c8a1SJohn Marino return 0;
1437f5b1c8a1SJohn Marino }
1438f5b1c8a1SJohn Marino if (attribs) {
1439f5b1c8a1SJohn Marino for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) {
1440f5b1c8a1SJohn Marino v = sk_CONF_VALUE_value(attr_sk, i);
1441f5b1c8a1SJohn Marino if (!X509_REQ_add1_attr_by_txt(req, v->name, chtype,
1442f5b1c8a1SJohn Marino (unsigned char *) v->value, -1))
1443f5b1c8a1SJohn Marino return 0;
1444f5b1c8a1SJohn Marino }
1445f5b1c8a1SJohn Marino }
1446f5b1c8a1SJohn Marino return 1;
1447f5b1c8a1SJohn Marino }
1448f5b1c8a1SJohn Marino
1449f5b1c8a1SJohn Marino
1450f5b1c8a1SJohn Marino static int
add_DN_object(X509_NAME * n,char * text,const char * def,char * value,int nid,int n_min,int n_max,unsigned long chtype,int mval)1451f5b1c8a1SJohn Marino add_DN_object(X509_NAME * n, char *text, const char *def, char *value,
1452f5b1c8a1SJohn Marino int nid, int n_min, int n_max, unsigned long chtype, int mval)
1453f5b1c8a1SJohn Marino {
1454f5b1c8a1SJohn Marino int i, ret = 0;
1455f5b1c8a1SJohn Marino char buf[1024];
1456f5b1c8a1SJohn Marino start:
14578edacedfSDaniel Fojt if (!req_config.batch)
1458f5b1c8a1SJohn Marino BIO_printf(bio_err, "%s [%s]:", text, def);
1459f5b1c8a1SJohn Marino (void) BIO_flush(bio_err);
1460f5b1c8a1SJohn Marino if (value != NULL) {
1461f5b1c8a1SJohn Marino strlcpy(buf, value, sizeof buf);
1462f5b1c8a1SJohn Marino strlcat(buf, "\n", sizeof buf);
1463f5b1c8a1SJohn Marino BIO_printf(bio_err, "%s\n", value);
1464f5b1c8a1SJohn Marino } else {
1465f5b1c8a1SJohn Marino buf[0] = '\0';
14668edacedfSDaniel Fojt if (!req_config.batch) {
1467f5b1c8a1SJohn Marino if (!fgets(buf, sizeof buf, stdin))
1468f5b1c8a1SJohn Marino return 0;
1469f5b1c8a1SJohn Marino } else {
1470f5b1c8a1SJohn Marino buf[0] = '\n';
1471f5b1c8a1SJohn Marino buf[1] = '\0';
1472f5b1c8a1SJohn Marino }
1473f5b1c8a1SJohn Marino }
1474f5b1c8a1SJohn Marino
1475f5b1c8a1SJohn Marino if (buf[0] == '\0')
1476f5b1c8a1SJohn Marino return (0);
1477f5b1c8a1SJohn Marino else if (buf[0] == '\n') {
1478f5b1c8a1SJohn Marino if ((def == NULL) || (def[0] == '\0'))
1479f5b1c8a1SJohn Marino return (1);
1480f5b1c8a1SJohn Marino strlcpy(buf, def, sizeof buf);
1481f5b1c8a1SJohn Marino strlcat(buf, "\n", sizeof buf);
1482f5b1c8a1SJohn Marino } else if ((buf[0] == '.') && (buf[1] == '\n'))
1483f5b1c8a1SJohn Marino return (1);
1484f5b1c8a1SJohn Marino
1485f5b1c8a1SJohn Marino i = strlen(buf);
1486f5b1c8a1SJohn Marino if (buf[i - 1] != '\n') {
1487f5b1c8a1SJohn Marino BIO_printf(bio_err, "weird input :-(\n");
1488f5b1c8a1SJohn Marino return (0);
1489f5b1c8a1SJohn Marino }
1490f5b1c8a1SJohn Marino buf[--i] = '\0';
1491f5b1c8a1SJohn Marino if (!req_check_len(i, n_min, n_max))
1492f5b1c8a1SJohn Marino goto start;
1493f5b1c8a1SJohn Marino if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
1494f5b1c8a1SJohn Marino (unsigned char *) buf, -1, -1, mval))
1495f5b1c8a1SJohn Marino goto err;
1496f5b1c8a1SJohn Marino ret = 1;
1497f5b1c8a1SJohn Marino err:
1498f5b1c8a1SJohn Marino return (ret);
1499f5b1c8a1SJohn Marino }
1500f5b1c8a1SJohn Marino
1501f5b1c8a1SJohn Marino static int
add_attribute_object(X509_REQ * req,char * text,const char * def,char * value,int nid,int n_min,int n_max,unsigned long chtype)1502f5b1c8a1SJohn Marino add_attribute_object(X509_REQ * req, char *text, const char *def,
1503f5b1c8a1SJohn Marino char *value, int nid, int n_min,
1504f5b1c8a1SJohn Marino int n_max, unsigned long chtype)
1505f5b1c8a1SJohn Marino {
1506f5b1c8a1SJohn Marino int i;
1507f5b1c8a1SJohn Marino static char buf[1024];
1508f5b1c8a1SJohn Marino
1509f5b1c8a1SJohn Marino start:
15108edacedfSDaniel Fojt if (!req_config.batch)
1511f5b1c8a1SJohn Marino BIO_printf(bio_err, "%s [%s]:", text, def);
1512f5b1c8a1SJohn Marino (void) BIO_flush(bio_err);
1513f5b1c8a1SJohn Marino if (value != NULL) {
1514f5b1c8a1SJohn Marino strlcpy(buf, value, sizeof buf);
1515f5b1c8a1SJohn Marino strlcat(buf, "\n", sizeof buf);
1516f5b1c8a1SJohn Marino BIO_printf(bio_err, "%s\n", value);
1517f5b1c8a1SJohn Marino } else {
1518f5b1c8a1SJohn Marino buf[0] = '\0';
15198edacedfSDaniel Fojt if (!req_config.batch) {
1520f5b1c8a1SJohn Marino if (!fgets(buf, sizeof buf, stdin))
1521f5b1c8a1SJohn Marino return 0;
1522f5b1c8a1SJohn Marino } else {
1523f5b1c8a1SJohn Marino buf[0] = '\n';
1524f5b1c8a1SJohn Marino buf[1] = '\0';
1525f5b1c8a1SJohn Marino }
1526f5b1c8a1SJohn Marino }
1527f5b1c8a1SJohn Marino
1528f5b1c8a1SJohn Marino if (buf[0] == '\0')
1529f5b1c8a1SJohn Marino return (0);
1530f5b1c8a1SJohn Marino else if (buf[0] == '\n') {
1531f5b1c8a1SJohn Marino if ((def == NULL) || (def[0] == '\0'))
1532f5b1c8a1SJohn Marino return (1);
1533f5b1c8a1SJohn Marino strlcpy(buf, def, sizeof buf);
1534f5b1c8a1SJohn Marino strlcat(buf, "\n", sizeof buf);
1535f5b1c8a1SJohn Marino } else if ((buf[0] == '.') && (buf[1] == '\n'))
1536f5b1c8a1SJohn Marino return (1);
1537f5b1c8a1SJohn Marino
1538f5b1c8a1SJohn Marino i = strlen(buf);
1539f5b1c8a1SJohn Marino if (buf[i - 1] != '\n') {
1540f5b1c8a1SJohn Marino BIO_printf(bio_err, "weird input :-(\n");
1541f5b1c8a1SJohn Marino return (0);
1542f5b1c8a1SJohn Marino }
1543f5b1c8a1SJohn Marino buf[--i] = '\0';
1544f5b1c8a1SJohn Marino if (!req_check_len(i, n_min, n_max))
1545f5b1c8a1SJohn Marino goto start;
1546f5b1c8a1SJohn Marino
1547f5b1c8a1SJohn Marino if (!X509_REQ_add1_attr_by_NID(req, nid, chtype,
1548f5b1c8a1SJohn Marino (unsigned char *) buf, -1)) {
1549f5b1c8a1SJohn Marino BIO_printf(bio_err, "Error adding attribute\n");
1550f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
1551f5b1c8a1SJohn Marino goto err;
1552f5b1c8a1SJohn Marino }
1553f5b1c8a1SJohn Marino return (1);
1554f5b1c8a1SJohn Marino err:
1555f5b1c8a1SJohn Marino return (0);
1556f5b1c8a1SJohn Marino }
1557f5b1c8a1SJohn Marino
1558f5b1c8a1SJohn Marino static int
req_check_len(int len,int n_min,int n_max)1559f5b1c8a1SJohn Marino req_check_len(int len, int n_min, int n_max)
1560f5b1c8a1SJohn Marino {
1561f5b1c8a1SJohn Marino if ((n_min > 0) && (len < n_min)) {
1562f5b1c8a1SJohn Marino BIO_printf(bio_err, "string is too short, it needs to be at least %d bytes long\n", n_min);
1563f5b1c8a1SJohn Marino return (0);
1564f5b1c8a1SJohn Marino }
1565f5b1c8a1SJohn Marino if ((n_max >= 0) && (len > n_max)) {
1566f5b1c8a1SJohn Marino BIO_printf(bio_err, "string is too long, it needs to be less than %d bytes long\n", n_max);
1567f5b1c8a1SJohn Marino return (0);
1568f5b1c8a1SJohn Marino }
1569f5b1c8a1SJohn Marino return (1);
1570f5b1c8a1SJohn Marino }
1571f5b1c8a1SJohn Marino
1572f5b1c8a1SJohn Marino /* Check if the end of a string matches 'end' */
1573f5b1c8a1SJohn Marino static int
check_end(const char * str,const char * end)1574f5b1c8a1SJohn Marino check_end(const char *str, const char *end)
1575f5b1c8a1SJohn Marino {
1576f5b1c8a1SJohn Marino int elen, slen;
1577f5b1c8a1SJohn Marino const char *tmp;
1578f5b1c8a1SJohn Marino elen = strlen(end);
1579f5b1c8a1SJohn Marino slen = strlen(str);
1580f5b1c8a1SJohn Marino if (elen > slen)
1581f5b1c8a1SJohn Marino return 1;
1582f5b1c8a1SJohn Marino tmp = str + slen - elen;
1583f5b1c8a1SJohn Marino return strcmp(tmp, end);
1584f5b1c8a1SJohn Marino }
1585f5b1c8a1SJohn Marino
1586f5b1c8a1SJohn Marino static EVP_PKEY_CTX *
set_keygen_ctx(BIO * err,const char * gstr,int * pkey_type,long * pkeylen,char ** palgnam)1587f5b1c8a1SJohn Marino set_keygen_ctx(BIO * err, const char *gstr, int *pkey_type,
1588f5b1c8a1SJohn Marino long *pkeylen, char **palgnam)
1589f5b1c8a1SJohn Marino {
1590f5b1c8a1SJohn Marino EVP_PKEY_CTX *gctx = NULL;
1591f5b1c8a1SJohn Marino EVP_PKEY *param = NULL;
1592f5b1c8a1SJohn Marino long keylen = -1;
1593f5b1c8a1SJohn Marino BIO *pbio = NULL;
1594f5b1c8a1SJohn Marino const char *paramfile = NULL;
1595f5b1c8a1SJohn Marino const char *errstr;
1596f5b1c8a1SJohn Marino
1597f5b1c8a1SJohn Marino if (gstr == NULL) {
1598f5b1c8a1SJohn Marino *pkey_type = EVP_PKEY_RSA;
1599f5b1c8a1SJohn Marino keylen = *pkeylen;
1600f5b1c8a1SJohn Marino } else if (gstr[0] >= '0' && gstr[0] <= '9') {
1601f5b1c8a1SJohn Marino *pkey_type = EVP_PKEY_RSA;
1602f5b1c8a1SJohn Marino keylen = strtonum(gstr, 0, LONG_MAX, &errstr);
1603f5b1c8a1SJohn Marino if (errstr) {
1604f5b1c8a1SJohn Marino BIO_printf(err, "bad algorithm %s: %s\n", gstr, errstr);
1605f5b1c8a1SJohn Marino return NULL;
1606f5b1c8a1SJohn Marino }
1607f5b1c8a1SJohn Marino *pkeylen = keylen;
1608f5b1c8a1SJohn Marino } else if (!strncmp(gstr, "param:", 6))
1609f5b1c8a1SJohn Marino paramfile = gstr + 6;
1610f5b1c8a1SJohn Marino else {
1611f5b1c8a1SJohn Marino const char *p = strchr(gstr, ':');
1612f5b1c8a1SJohn Marino int len;
1613f5b1c8a1SJohn Marino const EVP_PKEY_ASN1_METHOD *ameth;
1614f5b1c8a1SJohn Marino
1615f5b1c8a1SJohn Marino if (p)
1616f5b1c8a1SJohn Marino len = p - gstr;
1617f5b1c8a1SJohn Marino else
1618f5b1c8a1SJohn Marino len = strlen(gstr);
1619f5b1c8a1SJohn Marino
1620f5b1c8a1SJohn Marino ameth = EVP_PKEY_asn1_find_str(NULL, gstr, len);
1621f5b1c8a1SJohn Marino
1622f5b1c8a1SJohn Marino if (!ameth) {
1623f5b1c8a1SJohn Marino BIO_printf(err, "Unknown algorithm %.*s\n", len, gstr);
1624f5b1c8a1SJohn Marino return NULL;
1625f5b1c8a1SJohn Marino }
1626f5b1c8a1SJohn Marino EVP_PKEY_asn1_get0_info(NULL, pkey_type, NULL, NULL, NULL,
1627f5b1c8a1SJohn Marino ameth);
1628f5b1c8a1SJohn Marino if (*pkey_type == EVP_PKEY_RSA) {
1629f5b1c8a1SJohn Marino if (p) {
1630f5b1c8a1SJohn Marino keylen = strtonum(p + 1, 0, LONG_MAX, &errstr);
1631f5b1c8a1SJohn Marino if (errstr) {
1632f5b1c8a1SJohn Marino BIO_printf(err, "bad algorithm %s: %s\n",
1633f5b1c8a1SJohn Marino p + 1, errstr);
1634f5b1c8a1SJohn Marino return NULL;
1635f5b1c8a1SJohn Marino }
1636f5b1c8a1SJohn Marino *pkeylen = keylen;
1637f5b1c8a1SJohn Marino } else
1638f5b1c8a1SJohn Marino keylen = *pkeylen;
1639f5b1c8a1SJohn Marino } else if (p)
1640f5b1c8a1SJohn Marino paramfile = p + 1;
1641f5b1c8a1SJohn Marino }
1642f5b1c8a1SJohn Marino
1643f5b1c8a1SJohn Marino if (paramfile) {
1644f5b1c8a1SJohn Marino pbio = BIO_new_file(paramfile, "r");
1645f5b1c8a1SJohn Marino if (!pbio) {
1646f5b1c8a1SJohn Marino BIO_printf(err, "Can't open parameter file %s\n",
1647f5b1c8a1SJohn Marino paramfile);
1648f5b1c8a1SJohn Marino return NULL;
1649f5b1c8a1SJohn Marino }
1650f5b1c8a1SJohn Marino param = PEM_read_bio_Parameters(pbio, NULL);
1651f5b1c8a1SJohn Marino
1652f5b1c8a1SJohn Marino if (!param) {
1653f5b1c8a1SJohn Marino X509 *x;
1654f5b1c8a1SJohn Marino (void) BIO_reset(pbio);
1655f5b1c8a1SJohn Marino x = PEM_read_bio_X509(pbio, NULL, NULL, NULL);
1656f5b1c8a1SJohn Marino if (x) {
1657f5b1c8a1SJohn Marino param = X509_get_pubkey(x);
1658f5b1c8a1SJohn Marino X509_free(x);
1659f5b1c8a1SJohn Marino }
1660f5b1c8a1SJohn Marino }
1661f5b1c8a1SJohn Marino BIO_free(pbio);
1662f5b1c8a1SJohn Marino
1663f5b1c8a1SJohn Marino if (!param) {
1664f5b1c8a1SJohn Marino BIO_printf(err, "Error reading parameter file %s\n",
1665f5b1c8a1SJohn Marino paramfile);
1666f5b1c8a1SJohn Marino return NULL;
1667f5b1c8a1SJohn Marino }
1668f5b1c8a1SJohn Marino if (*pkey_type == -1)
1669f5b1c8a1SJohn Marino *pkey_type = EVP_PKEY_id(param);
1670f5b1c8a1SJohn Marino else if (*pkey_type != EVP_PKEY_base_id(param)) {
1671f5b1c8a1SJohn Marino BIO_printf(err, "Key Type does not match parameters\n");
1672f5b1c8a1SJohn Marino EVP_PKEY_free(param);
1673f5b1c8a1SJohn Marino return NULL;
1674f5b1c8a1SJohn Marino }
1675f5b1c8a1SJohn Marino }
1676f5b1c8a1SJohn Marino if (palgnam) {
1677f5b1c8a1SJohn Marino const EVP_PKEY_ASN1_METHOD *ameth;
1678f5b1c8a1SJohn Marino const char *anam;
1679f5b1c8a1SJohn Marino ameth = EVP_PKEY_asn1_find(NULL, *pkey_type);
1680f5b1c8a1SJohn Marino if (!ameth) {
1681f5b1c8a1SJohn Marino BIO_puts(err, "Internal error: can't find key algorithm\n");
1682f5b1c8a1SJohn Marino return NULL;
1683f5b1c8a1SJohn Marino }
1684f5b1c8a1SJohn Marino EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &anam, ameth);
1685f5b1c8a1SJohn Marino *palgnam = strdup(anam);
1686f5b1c8a1SJohn Marino }
1687f5b1c8a1SJohn Marino if (param) {
1688f5b1c8a1SJohn Marino gctx = EVP_PKEY_CTX_new(param, NULL);
1689f5b1c8a1SJohn Marino *pkeylen = EVP_PKEY_bits(param);
1690f5b1c8a1SJohn Marino EVP_PKEY_free(param);
1691f5b1c8a1SJohn Marino } else
1692f5b1c8a1SJohn Marino gctx = EVP_PKEY_CTX_new_id(*pkey_type, NULL);
1693f5b1c8a1SJohn Marino
1694f5b1c8a1SJohn Marino if (!gctx) {
1695f5b1c8a1SJohn Marino BIO_puts(err, "Error allocating keygen context\n");
1696f5b1c8a1SJohn Marino ERR_print_errors(err);
1697f5b1c8a1SJohn Marino return NULL;
1698f5b1c8a1SJohn Marino }
1699f5b1c8a1SJohn Marino if (EVP_PKEY_keygen_init(gctx) <= 0) {
1700f5b1c8a1SJohn Marino BIO_puts(err, "Error initializing keygen context\n");
1701f5b1c8a1SJohn Marino ERR_print_errors(err);
1702f5b1c8a1SJohn Marino return NULL;
1703f5b1c8a1SJohn Marino }
1704f5b1c8a1SJohn Marino if ((*pkey_type == EVP_PKEY_RSA) && (keylen != -1)) {
1705f5b1c8a1SJohn Marino if (EVP_PKEY_CTX_set_rsa_keygen_bits(gctx, keylen) <= 0) {
1706f5b1c8a1SJohn Marino BIO_puts(err, "Error setting RSA keysize\n");
1707f5b1c8a1SJohn Marino ERR_print_errors(err);
1708f5b1c8a1SJohn Marino EVP_PKEY_CTX_free(gctx);
1709f5b1c8a1SJohn Marino return NULL;
1710f5b1c8a1SJohn Marino }
1711f5b1c8a1SJohn Marino }
1712f5b1c8a1SJohn Marino
1713f5b1c8a1SJohn Marino return gctx;
1714f5b1c8a1SJohn Marino }
1715f5b1c8a1SJohn Marino
1716f5b1c8a1SJohn Marino static int
genpkey_cb(EVP_PKEY_CTX * ctx)1717f5b1c8a1SJohn Marino genpkey_cb(EVP_PKEY_CTX * ctx)
1718f5b1c8a1SJohn Marino {
1719f5b1c8a1SJohn Marino char c = '*';
1720f5b1c8a1SJohn Marino BIO *b = EVP_PKEY_CTX_get_app_data(ctx);
1721f5b1c8a1SJohn Marino int p;
1722f5b1c8a1SJohn Marino p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
1723f5b1c8a1SJohn Marino if (p == 0)
1724f5b1c8a1SJohn Marino c = '.';
1725f5b1c8a1SJohn Marino if (p == 1)
1726f5b1c8a1SJohn Marino c = '+';
1727f5b1c8a1SJohn Marino if (p == 2)
1728f5b1c8a1SJohn Marino c = '*';
1729f5b1c8a1SJohn Marino if (p == 3)
1730f5b1c8a1SJohn Marino c = '\n';
1731f5b1c8a1SJohn Marino BIO_write(b, &c, 1);
1732f5b1c8a1SJohn Marino (void) BIO_flush(b);
1733f5b1c8a1SJohn Marino return 1;
1734f5b1c8a1SJohn Marino }
1735f5b1c8a1SJohn Marino
1736f5b1c8a1SJohn Marino static int
do_sign_init(BIO * err,EVP_MD_CTX * ctx,EVP_PKEY * pkey,const EVP_MD * md,STACK_OF (OPENSSL_STRING)* sigopts)1737f5b1c8a1SJohn Marino do_sign_init(BIO * err, EVP_MD_CTX * ctx, EVP_PKEY * pkey,
1738f5b1c8a1SJohn Marino const EVP_MD * md, STACK_OF(OPENSSL_STRING) * sigopts)
1739f5b1c8a1SJohn Marino {
1740f5b1c8a1SJohn Marino EVP_PKEY_CTX *pkctx = NULL;
1741f5b1c8a1SJohn Marino int i;
1742f5b1c8a1SJohn Marino EVP_MD_CTX_init(ctx);
1743f5b1c8a1SJohn Marino if (!EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey))
1744f5b1c8a1SJohn Marino return 0;
1745f5b1c8a1SJohn Marino for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) {
1746f5b1c8a1SJohn Marino char *sigopt = sk_OPENSSL_STRING_value(sigopts, i);
1747f5b1c8a1SJohn Marino if (pkey_ctrl_string(pkctx, sigopt) <= 0) {
1748f5b1c8a1SJohn Marino BIO_printf(err, "parameter error \"%s\"\n", sigopt);
1749f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
1750f5b1c8a1SJohn Marino return 0;
1751f5b1c8a1SJohn Marino }
1752f5b1c8a1SJohn Marino }
1753f5b1c8a1SJohn Marino return 1;
1754f5b1c8a1SJohn Marino }
1755f5b1c8a1SJohn Marino
1756f5b1c8a1SJohn Marino int
do_X509_sign(BIO * err,X509 * x,EVP_PKEY * pkey,const EVP_MD * md,STACK_OF (OPENSSL_STRING)* sigopts)1757f5b1c8a1SJohn Marino do_X509_sign(BIO * err, X509 * x, EVP_PKEY * pkey, const EVP_MD * md,
1758f5b1c8a1SJohn Marino STACK_OF(OPENSSL_STRING) * sigopts)
1759f5b1c8a1SJohn Marino {
1760*de0e0e4dSAntonio Huete Jimenez EVP_MD_CTX *mctx;
1761f5b1c8a1SJohn Marino int rv;
1762*de0e0e4dSAntonio Huete Jimenez
1763*de0e0e4dSAntonio Huete Jimenez if ((mctx = EVP_MD_CTX_new()) == NULL)
1764*de0e0e4dSAntonio Huete Jimenez return 0;
1765*de0e0e4dSAntonio Huete Jimenez
1766*de0e0e4dSAntonio Huete Jimenez rv = do_sign_init(err, mctx, pkey, md, sigopts);
1767f5b1c8a1SJohn Marino if (rv > 0)
1768*de0e0e4dSAntonio Huete Jimenez rv = X509_sign_ctx(x, mctx);
1769*de0e0e4dSAntonio Huete Jimenez
1770*de0e0e4dSAntonio Huete Jimenez EVP_MD_CTX_free(mctx);
1771*de0e0e4dSAntonio Huete Jimenez
1772*de0e0e4dSAntonio Huete Jimenez return rv > 0;
1773f5b1c8a1SJohn Marino }
1774f5b1c8a1SJohn Marino
1775f5b1c8a1SJohn Marino
1776f5b1c8a1SJohn Marino int
do_X509_REQ_sign(BIO * err,X509_REQ * x,EVP_PKEY * pkey,const EVP_MD * md,STACK_OF (OPENSSL_STRING)* sigopts)1777f5b1c8a1SJohn Marino do_X509_REQ_sign(BIO * err, X509_REQ * x, EVP_PKEY * pkey, const EVP_MD * md,
1778f5b1c8a1SJohn Marino STACK_OF(OPENSSL_STRING) * sigopts)
1779f5b1c8a1SJohn Marino {
1780*de0e0e4dSAntonio Huete Jimenez EVP_MD_CTX *mctx;
1781f5b1c8a1SJohn Marino int rv;
1782*de0e0e4dSAntonio Huete Jimenez
1783*de0e0e4dSAntonio Huete Jimenez if ((mctx = EVP_MD_CTX_new()) == NULL)
1784*de0e0e4dSAntonio Huete Jimenez return 0;
1785*de0e0e4dSAntonio Huete Jimenez
1786*de0e0e4dSAntonio Huete Jimenez rv = do_sign_init(err, mctx, pkey, md, sigopts);
1787f5b1c8a1SJohn Marino if (rv > 0)
1788*de0e0e4dSAntonio Huete Jimenez rv = X509_REQ_sign_ctx(x, mctx);
1789*de0e0e4dSAntonio Huete Jimenez
1790*de0e0e4dSAntonio Huete Jimenez EVP_MD_CTX_free(mctx);
1791*de0e0e4dSAntonio Huete Jimenez
1792*de0e0e4dSAntonio Huete Jimenez return rv > 0;
1793f5b1c8a1SJohn Marino }
1794f5b1c8a1SJohn Marino
1795f5b1c8a1SJohn Marino
1796f5b1c8a1SJohn Marino
1797f5b1c8a1SJohn Marino int
do_X509_CRL_sign(BIO * err,X509_CRL * x,EVP_PKEY * pkey,const EVP_MD * md,STACK_OF (OPENSSL_STRING)* sigopts)1798f5b1c8a1SJohn Marino do_X509_CRL_sign(BIO * err, X509_CRL * x, EVP_PKEY * pkey, const EVP_MD * md,
1799f5b1c8a1SJohn Marino STACK_OF(OPENSSL_STRING) * sigopts)
1800f5b1c8a1SJohn Marino {
1801f5b1c8a1SJohn Marino int rv;
1802*de0e0e4dSAntonio Huete Jimenez EVP_MD_CTX *mctx;
1803*de0e0e4dSAntonio Huete Jimenez
1804*de0e0e4dSAntonio Huete Jimenez if ((mctx = EVP_MD_CTX_new()) == NULL)
1805*de0e0e4dSAntonio Huete Jimenez return 0;
1806*de0e0e4dSAntonio Huete Jimenez
1807*de0e0e4dSAntonio Huete Jimenez rv = do_sign_init(err, mctx, pkey, md, sigopts);
1808f5b1c8a1SJohn Marino if (rv > 0)
1809*de0e0e4dSAntonio Huete Jimenez rv = X509_CRL_sign_ctx(x, mctx);
1810*de0e0e4dSAntonio Huete Jimenez
1811*de0e0e4dSAntonio Huete Jimenez EVP_MD_CTX_free(mctx);
1812*de0e0e4dSAntonio Huete Jimenez
1813*de0e0e4dSAntonio Huete Jimenez return rv > 0;
1814f5b1c8a1SJohn Marino }
1815cca6fc52SDaniel Fojt
1816cca6fc52SDaniel Fojt static unsigned long
ext_name_hash(const OPENSSL_STRING * a)1817cca6fc52SDaniel Fojt ext_name_hash(const OPENSSL_STRING *a)
1818cca6fc52SDaniel Fojt {
1819cca6fc52SDaniel Fojt return lh_strhash((const char *)a);
1820cca6fc52SDaniel Fojt }
1821cca6fc52SDaniel Fojt
1822cca6fc52SDaniel Fojt static int
ext_name_cmp(const OPENSSL_STRING * a,const OPENSSL_STRING * b)1823cca6fc52SDaniel Fojt ext_name_cmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b)
1824cca6fc52SDaniel Fojt {
1825cca6fc52SDaniel Fojt return strcmp((const char *)a, (const char *)b);
1826cca6fc52SDaniel Fojt }
1827cca6fc52SDaniel Fojt
1828cca6fc52SDaniel Fojt static void
exts_cleanup(OPENSSL_STRING * x)1829cca6fc52SDaniel Fojt exts_cleanup(OPENSSL_STRING *x)
1830cca6fc52SDaniel Fojt {
1831cca6fc52SDaniel Fojt free((char *)x);
1832cca6fc52SDaniel Fojt }
1833cca6fc52SDaniel Fojt
1834cca6fc52SDaniel Fojt /*
1835cca6fc52SDaniel Fojt * Is the |kv| key already duplicated ? This is remarkably tricky to get right.
1836cca6fc52SDaniel Fojt * Return 0 if unique, -1 on runtime error; 1 if found or a syntax error.
1837cca6fc52SDaniel Fojt */
1838cca6fc52SDaniel Fojt static int
duplicated(LHASH_OF (OPENSSL_STRING)* addexts,char * kv)1839cca6fc52SDaniel Fojt duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv)
1840cca6fc52SDaniel Fojt {
1841cca6fc52SDaniel Fojt char *p;
1842cca6fc52SDaniel Fojt size_t off;
1843cca6fc52SDaniel Fojt
1844cca6fc52SDaniel Fojt /* Check syntax. */
1845cca6fc52SDaniel Fojt /* Skip leading whitespace, make a copy. */
1846cca6fc52SDaniel Fojt while (*kv && isspace(*kv))
1847cca6fc52SDaniel Fojt if (*++kv == '\0')
1848cca6fc52SDaniel Fojt return 1;
1849cca6fc52SDaniel Fojt if ((p = strchr(kv, '=')) == NULL)
1850cca6fc52SDaniel Fojt return 1;
1851cca6fc52SDaniel Fojt off = p - kv;
1852cca6fc52SDaniel Fojt if ((kv = strdup(kv)) == NULL)
1853cca6fc52SDaniel Fojt return -1;
1854cca6fc52SDaniel Fojt
1855cca6fc52SDaniel Fojt /* Skip trailing space before the equal sign. */
1856cca6fc52SDaniel Fojt for (p = kv + off; p > kv; --p)
1857cca6fc52SDaniel Fojt if (!isspace(p[-1]))
1858cca6fc52SDaniel Fojt break;
1859cca6fc52SDaniel Fojt if (p == kv) {
1860cca6fc52SDaniel Fojt free(kv);
1861cca6fc52SDaniel Fojt return 1;
1862cca6fc52SDaniel Fojt }
1863cca6fc52SDaniel Fojt *p = '\0';
1864cca6fc52SDaniel Fojt
1865cca6fc52SDaniel Fojt /* See if "key" is there by attempting to add it. */
1866cca6fc52SDaniel Fojt if ((p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING*)kv))
1867cca6fc52SDaniel Fojt != NULL || lh_OPENSSL_STRING_error(addexts)) {
1868cca6fc52SDaniel Fojt free(p != NULL ? p : kv);
1869cca6fc52SDaniel Fojt return -1;
1870cca6fc52SDaniel Fojt }
1871cca6fc52SDaniel Fojt
1872cca6fc52SDaniel Fojt return 0;
1873cca6fc52SDaniel Fojt }
1874