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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 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 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 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