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