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