|
1 /* apps/req.c */ |
|
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 <time.h> |
|
68 #include <string.h> |
|
69 #ifdef OPENSSL_NO_STDIO |
|
70 #define APPS_WIN16 |
|
71 #endif |
|
72 #include "apps.h" |
|
73 #include <openssl/bio.h> |
|
74 #include <openssl/evp.h> |
|
75 #include <openssl/conf.h> |
|
76 #include <openssl/err.h> |
|
77 #include <openssl/asn1.h> |
|
78 #include <openssl/x509.h> |
|
79 #include <openssl/x509v3.h> |
|
80 #include <openssl/objects.h> |
|
81 #include <openssl/pem.h> |
|
82 #include <openssl/bn.h> |
|
83 #ifndef OPENSSL_NO_RSA |
|
84 #include <openssl/rsa.h> |
|
85 #endif |
|
86 #ifndef OPENSSL_NO_DSA |
|
87 #include <openssl/dsa.h> |
|
88 #endif |
|
89 |
|
90 #define SECTION "req" |
|
91 |
|
92 #define BITS "default_bits" |
|
93 #define KEYFILE "default_keyfile" |
|
94 #define PROMPT "prompt" |
|
95 #define DISTINGUISHED_NAME "distinguished_name" |
|
96 #define ATTRIBUTES "attributes" |
|
97 #define V3_EXTENSIONS "x509_extensions" |
|
98 #define REQ_EXTENSIONS "req_extensions" |
|
99 #define STRING_MASK "string_mask" |
|
100 #define UTF8_IN "utf8" |
|
101 |
|
102 #define DEFAULT_KEY_LENGTH 512 |
|
103 #define MIN_KEY_LENGTH 384 |
|
104 |
|
105 #undef PROG |
|
106 #define PROG req_main |
|
107 |
|
108 /* -inform arg - input format - default PEM (DER or PEM) |
|
109 * -outform arg - output format - default PEM |
|
110 * -in arg - input file - default stdin |
|
111 * -out arg - output file - default stdout |
|
112 * -verify - check request signature |
|
113 * -noout - don't print stuff out. |
|
114 * -text - print out human readable text. |
|
115 * -nodes - no des encryption |
|
116 * -config file - Load configuration file. |
|
117 * -key file - make a request using key in file (or use it for verification). |
|
118 * -keyform arg - key file format. |
|
119 * -rand file(s) - load the file(s) into the PRNG. |
|
120 * -newkey - make a key and a request. |
|
121 * -modulus - print RSA modulus. |
|
122 * -pubkey - output Public Key. |
|
123 * -x509 - output a self signed X509 structure instead. |
|
124 * -asn1-kludge - output new certificate request in a format that some CA's |
|
125 * require. This format is wrong |
|
126 */ |
|
127 |
|
128 static int make_REQ(X509_REQ *req,EVP_PKEY *pkey,char *dn,int mutlirdn, |
|
129 int attribs,unsigned long chtype); |
|
130 static int build_subject(X509_REQ *req, char *subj, unsigned long chtype, |
|
131 int multirdn); |
|
132 static int prompt_info(X509_REQ *req, |
|
133 STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect, |
|
134 STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect, int attribs, |
|
135 unsigned long chtype); |
|
136 static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *sk, |
|
137 STACK_OF(CONF_VALUE) *attr, int attribs, |
|
138 unsigned long chtype); |
|
139 static int add_attribute_object(X509_REQ *req, char *text, const char *def, |
|
140 char *value, int nid, int n_min, |
|
141 int n_max, unsigned long chtype); |
|
142 static int add_DN_object(X509_NAME *n, char *text, const char *def, char *value, |
|
143 int nid,int n_min,int n_max, unsigned long chtype, int mval); |
|
144 #ifndef OPENSSL_NO_RSA |
|
145 static int MS_CALLBACK req_cb(int p, int n, BN_GENCB *cb); |
|
146 #endif |
|
147 static int req_check_len(int len,int n_min,int n_max); |
|
148 static int check_end(const char *str, const char *end); |
|
149 #ifndef MONOLITH |
|
150 static char *default_config_file=NULL; |
|
151 #endif |
|
152 static CONF *req_conf=NULL; |
|
153 static int batch=0; |
|
154 |
|
155 #define TYPE_RSA 1 |
|
156 #define TYPE_DSA 2 |
|
157 #define TYPE_DH 3 |
|
158 #define TYPE_EC 4 |
|
159 |
|
160 |
|
161 |
|
162 int MAIN(int, char **); |
|
163 |
|
164 int MAIN(int argc, char **argv) |
|
165 { |
|
166 ENGINE *e = NULL; |
|
167 #ifndef OPENSSL_NO_DSA |
|
168 DSA *dsa_params=NULL; |
|
169 #endif |
|
170 #ifndef OPENSSL_NO_ECDSA |
|
171 EC_KEY *ec_params = NULL; |
|
172 #endif |
|
173 unsigned long nmflag = 0, reqflag = 0; |
|
174 int ex=1,x509=0,days=30; |
|
175 X509 *x509ss=NULL; |
|
176 X509_REQ *req=NULL; |
|
177 EVP_PKEY *pkey=NULL; |
|
178 int i=0,badops=0,newreq=0,verbose=0,pkey_type=TYPE_RSA; |
|
179 long newkey = -1; |
|
180 BIO *in=NULL,*out=NULL; |
|
181 int informat,outformat,verify=0,noout=0,text=0,keyform=FORMAT_PEM; |
|
182 int nodes=0,kludge=0,newhdr=0,subject=0,pubkey=0; |
|
183 char *infile,*outfile,*prog,*keyfile=NULL,*template=NULL,*keyout=NULL; |
|
184 #ifndef OPENSSL_NO_ENGINE |
|
185 char *engine=NULL; |
|
186 #endif |
|
187 char *extensions = NULL; |
|
188 char *req_exts = NULL; |
|
189 const EVP_CIPHER *cipher=NULL; |
|
190 ASN1_INTEGER *serial = NULL; |
|
191 int modulus=0; |
|
192 char *inrand=NULL; |
|
193 char *passargin = NULL, *passargout = NULL; |
|
194 char *passin = NULL, *passout = NULL; |
|
195 char *p; |
|
196 char *subj = NULL; |
|
197 int multirdn = 0; |
|
198 const EVP_MD *md_alg=NULL,*digest=EVP_sha1(); |
|
199 unsigned long chtype = MBSTRING_ASC; |
|
200 #ifndef MONOLITH |
|
201 char *to_free; |
|
202 long errline; |
|
203 #endif |
|
204 |
|
205 req_conf = NULL; |
|
206 #ifndef OPENSSL_NO_DES |
|
207 cipher=EVP_des_ede3_cbc(); |
|
208 #endif |
|
209 apps_startup(); |
|
210 |
|
211 if (bio_err == NULL) |
|
212 if ((bio_err=BIO_new(BIO_s_file())) != NULL) |
|
213 BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); |
|
214 |
|
215 |
|
216 infile=NULL; |
|
217 outfile=NULL; |
|
218 informat=FORMAT_PEM; |
|
219 outformat=FORMAT_PEM; |
|
220 |
|
221 prog=argv[0]; |
|
222 argc--; |
|
223 argv++; |
|
224 while (argc >= 1) |
|
225 { |
|
226 if (strcmp(*argv,"-inform") == 0) |
|
227 { |
|
228 if (--argc < 1) goto bad; |
|
229 informat=str2fmt(*(++argv)); |
|
230 } |
|
231 else if (strcmp(*argv,"-outform") == 0) |
|
232 { |
|
233 if (--argc < 1) goto bad; |
|
234 outformat=str2fmt(*(++argv)); |
|
235 } |
|
236 #ifndef OPENSSL_NO_ENGINE |
|
237 else if (strcmp(*argv,"-engine") == 0) |
|
238 { |
|
239 if (--argc < 1) goto bad; |
|
240 engine= *(++argv); |
|
241 } |
|
242 #endif |
|
243 else if (strcmp(*argv,"-key") == 0) |
|
244 { |
|
245 if (--argc < 1) goto bad; |
|
246 keyfile= *(++argv); |
|
247 } |
|
248 else if (strcmp(*argv,"-pubkey") == 0) |
|
249 { |
|
250 pubkey=1; |
|
251 } |
|
252 else if ((strcmp(*argv,"-new") == 0)) |
|
253 { |
|
254 newreq=1; |
|
255 } |
|
256 else if (strcmp(*argv,"-config") == 0) |
|
257 { |
|
258 if (--argc < 1) goto bad; |
|
259 template= *(++argv); |
|
260 } |
|
261 else if (strcmp(*argv,"-keyform") == 0) |
|
262 { |
|
263 if (--argc < 1) goto bad; |
|
264 keyform=str2fmt(*(++argv)); |
|
265 } |
|
266 else if (strcmp(*argv,"-in") == 0) |
|
267 { |
|
268 if (--argc < 1) goto bad; |
|
269 infile= *(++argv); |
|
270 } |
|
271 else if (strcmp(*argv,"-out") == 0) |
|
272 { |
|
273 if (--argc < 1) goto bad; |
|
274 outfile= *(++argv); |
|
275 } |
|
276 else if (strcmp(*argv,"-keyout") == 0) |
|
277 { |
|
278 if (--argc < 1) goto bad; |
|
279 keyout= *(++argv); |
|
280 } |
|
281 else if (strcmp(*argv,"-passin") == 0) |
|
282 { |
|
283 if (--argc < 1) goto bad; |
|
284 passargin= *(++argv); |
|
285 } |
|
286 else if (strcmp(*argv,"-passout") == 0) |
|
287 { |
|
288 if (--argc < 1) goto bad; |
|
289 passargout= *(++argv); |
|
290 } |
|
291 else if (strcmp(*argv,"-rand") == 0) |
|
292 { |
|
293 if (--argc < 1) goto bad; |
|
294 inrand= *(++argv); |
|
295 } |
|
296 else if (strcmp(*argv,"-newkey") == 0) |
|
297 { |
|
298 int is_numeric; |
|
299 |
|
300 if (--argc < 1) goto bad; |
|
301 p= *(++argv); |
|
302 is_numeric = p[0] >= '0' && p[0] <= '9'; |
|
303 if (strncmp("rsa:",p,4) == 0 || is_numeric) |
|
304 { |
|
305 pkey_type=TYPE_RSA; |
|
306 if(!is_numeric) |
|
307 p+=4; |
|
308 newkey= atoi(p); |
|
309 } |
|
310 else |
|
311 #ifndef OPENSSL_NO_DSA |
|
312 if (strncmp("dsa:",p,4) == 0) |
|
313 { |
|
314 X509 *xtmp=NULL; |
|
315 EVP_PKEY *dtmp; |
|
316 |
|
317 pkey_type=TYPE_DSA; |
|
318 p+=4; |
|
319 if ((in=BIO_new_file(p,"r")) == NULL) |
|
320 { |
|
321 perror(p); |
|
322 goto end; |
|
323 } |
|
324 if ((dsa_params=PEM_read_bio_DSAparams(in,NULL,NULL,NULL)) == NULL) |
|
325 { |
|
326 ERR_clear_error(); |
|
327 (void)BIO_reset(in); |
|
328 if ((xtmp=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL) |
|
329 { |
|
330 BIO_printf(bio_err,"unable to load DSA parameters from file\n"); |
|
331 goto end; |
|
332 } |
|
333 |
|
334 if ((dtmp=X509_get_pubkey(xtmp)) == NULL) goto end; |
|
335 if (dtmp->type == EVP_PKEY_DSA) |
|
336 dsa_params=DSAparams_dup(dtmp->pkey.dsa); |
|
337 EVP_PKEY_free(dtmp); |
|
338 X509_free(xtmp); |
|
339 if (dsa_params == NULL) |
|
340 { |
|
341 BIO_printf(bio_err,"Certificate does not contain DSA parameters\n"); |
|
342 goto end; |
|
343 } |
|
344 } |
|
345 BIO_free(in); |
|
346 in=NULL; |
|
347 newkey=BN_num_bits(dsa_params->p); |
|
348 } |
|
349 else |
|
350 #endif |
|
351 #ifndef OPENSSL_NO_ECDSA |
|
352 if (strncmp("ec:",p,3) == 0) |
|
353 { |
|
354 X509 *xtmp=NULL; |
|
355 EVP_PKEY *dtmp; |
|
356 EC_GROUP *group; |
|
357 |
|
358 pkey_type=TYPE_EC; |
|
359 p+=3; |
|
360 if ((in=BIO_new_file(p,"r")) == NULL) |
|
361 { |
|
362 perror(p); |
|
363 goto end; |
|
364 } |
|
365 if ((ec_params = EC_KEY_new()) == NULL) |
|
366 goto end; |
|
367 group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL); |
|
368 if (group == NULL) |
|
369 { |
|
370 EC_KEY_free(ec_params); |
|
371 ERR_clear_error(); |
|
372 (void)BIO_reset(in); |
|
373 if ((xtmp=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL) |
|
374 { |
|
375 BIO_printf(bio_err,"unable to load EC parameters from file\n"); |
|
376 goto end; |
|
377 } |
|
378 |
|
379 if ((dtmp=X509_get_pubkey(xtmp))==NULL) |
|
380 goto end; |
|
381 if (dtmp->type == EVP_PKEY_EC) |
|
382 ec_params = EC_KEY_dup(dtmp->pkey.ec); |
|
383 EVP_PKEY_free(dtmp); |
|
384 X509_free(xtmp); |
|
385 if (ec_params == NULL) |
|
386 { |
|
387 BIO_printf(bio_err,"Certificate does not contain EC parameters\n"); |
|
388 goto end; |
|
389 } |
|
390 } |
|
391 else |
|
392 { |
|
393 if (EC_KEY_set_group(ec_params, group) == 0) |
|
394 goto end; |
|
395 EC_GROUP_free(group); |
|
396 } |
|
397 |
|
398 BIO_free(in); |
|
399 in=NULL; |
|
400 newkey = EC_GROUP_get_degree(EC_KEY_get0_group(ec_params)); |
|
401 } |
|
402 else |
|
403 #endif |
|
404 #ifndef OPENSSL_NO_DH |
|
405 if (strncmp("dh:",p,4) == 0) |
|
406 { |
|
407 pkey_type=TYPE_DH; |
|
408 p+=3; |
|
409 } |
|
410 else |
|
411 #endif |
|
412 { |
|
413 goto bad; |
|
414 } |
|
415 |
|
416 newreq=1; |
|
417 } |
|
418 else if (strcmp(*argv,"-batch") == 0) |
|
419 batch=1; |
|
420 else if (strcmp(*argv,"-newhdr") == 0) |
|
421 newhdr=1; |
|
422 else if (strcmp(*argv,"-modulus") == 0) |
|
423 modulus=1; |
|
424 else if (strcmp(*argv,"-verify") == 0) |
|
425 verify=1; |
|
426 else if (strcmp(*argv,"-nodes") == 0) |
|
427 nodes=1; |
|
428 else if (strcmp(*argv,"-noout") == 0) |
|
429 noout=1; |
|
430 else if (strcmp(*argv,"-verbose") == 0) |
|
431 verbose=1; |
|
432 else if (strcmp(*argv,"-utf8") == 0) |
|
433 chtype = MBSTRING_UTF8; |
|
434 else if (strcmp(*argv,"-nameopt") == 0) |
|
435 { |
|
436 if (--argc < 1) goto bad; |
|
437 if (!set_name_ex(&nmflag, *(++argv))) goto bad; |
|
438 } |
|
439 else if (strcmp(*argv,"-reqopt") == 0) |
|
440 { |
|
441 if (--argc < 1) goto bad; |
|
442 if (!set_cert_ex(&reqflag, *(++argv))) goto bad; |
|
443 } |
|
444 else if (strcmp(*argv,"-subject") == 0) |
|
445 subject=1; |
|
446 else if (strcmp(*argv,"-text") == 0) |
|
447 text=1; |
|
448 else if (strcmp(*argv,"-x509") == 0) |
|
449 x509=1; |
|
450 else if (strcmp(*argv,"-asn1-kludge") == 0) |
|
451 kludge=1; |
|
452 else if (strcmp(*argv,"-no-asn1-kludge") == 0) |
|
453 kludge=0; |
|
454 else if (strcmp(*argv,"-subj") == 0) |
|
455 { |
|
456 if (--argc < 1) goto bad; |
|
457 subj= *(++argv); |
|
458 } |
|
459 else if (strcmp(*argv,"-multivalue-rdn") == 0) |
|
460 multirdn=1; |
|
461 else if (strcmp(*argv,"-days") == 0) |
|
462 { |
|
463 if (--argc < 1) goto bad; |
|
464 days= atoi(*(++argv)); |
|
465 if (days == 0) days=30; |
|
466 } |
|
467 else if (strcmp(*argv,"-set_serial") == 0) |
|
468 { |
|
469 if (--argc < 1) goto bad; |
|
470 serial = s2i_ASN1_INTEGER(NULL, *(++argv)); |
|
471 if (!serial) goto bad; |
|
472 } |
|
473 else if ((md_alg=EVP_get_digestbyname(&((*argv)[1]))) != NULL) |
|
474 { |
|
475 /* ok */ |
|
476 digest=md_alg; |
|
477 } |
|
478 else if (strcmp(*argv,"-extensions") == 0) |
|
479 { |
|
480 if (--argc < 1) goto bad; |
|
481 extensions = *(++argv); |
|
482 } |
|
483 else if (strcmp(*argv,"-reqexts") == 0) |
|
484 { |
|
485 if (--argc < 1) goto bad; |
|
486 req_exts = *(++argv); |
|
487 } |
|
488 else |
|
489 { |
|
490 BIO_printf(bio_err,"unknown option %s\n",*argv); |
|
491 badops=1; |
|
492 break; |
|
493 } |
|
494 argc--; |
|
495 argv++; |
|
496 } |
|
497 |
|
498 if (badops) |
|
499 { |
|
500 bad: |
|
501 BIO_printf(bio_err,"%s [options] <infile >outfile\n",prog); |
|
502 BIO_printf(bio_err,"where options are\n"); |
|
503 BIO_printf(bio_err," -inform arg input format - DER or PEM\n"); |
|
504 BIO_printf(bio_err," -outform arg output format - DER or PEM\n"); |
|
505 BIO_printf(bio_err," -in arg input file\n"); |
|
506 BIO_printf(bio_err," -out arg output file\n"); |
|
507 BIO_printf(bio_err," -text text form of request\n"); |
|
508 BIO_printf(bio_err," -pubkey output public key\n"); |
|
509 BIO_printf(bio_err," -noout do not output REQ\n"); |
|
510 BIO_printf(bio_err," -verify verify signature on REQ\n"); |
|
511 BIO_printf(bio_err," -modulus RSA modulus\n"); |
|
512 BIO_printf(bio_err," -nodes don't encrypt the output key\n"); |
|
513 #ifndef OPENSSL_NO_ENGINE |
|
514 BIO_printf(bio_err," -engine e use engine e, possibly a hardware device\n"); |
|
515 #endif |
|
516 BIO_printf(bio_err," -subject output the request's subject\n"); |
|
517 BIO_printf(bio_err," -passin private key password source\n"); |
|
518 BIO_printf(bio_err," -key file use the private key contained in file\n"); |
|
519 BIO_printf(bio_err," -keyform arg key file format\n"); |
|
520 BIO_printf(bio_err," -keyout arg file to send the key to\n"); |
|
521 BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); |
|
522 BIO_printf(bio_err," load the file (or the files in the directory) into\n"); |
|
523 BIO_printf(bio_err," the random number generator\n"); |
|
524 BIO_printf(bio_err," -newkey rsa:bits generate a new RSA key of 'bits' in size\n"); |
|
525 BIO_printf(bio_err," -newkey dsa:file generate a new DSA key, parameters taken from CA in 'file'\n"); |
|
526 #ifndef OPENSSL_NO_ECDSA |
|
527 BIO_printf(bio_err," -newkey ec:file generate a new EC key, parameters taken from CA in 'file'\n"); |
|
528 #endif |
|
529 BIO_printf(bio_err," -[digest] Digest to sign with (md5, sha1, md2, mdc2, md4)\n"); |
|
530 BIO_printf(bio_err," -config file request template file.\n"); |
|
531 BIO_printf(bio_err," -subj arg set or modify request subject\n"); |
|
532 BIO_printf(bio_err," -multivalue-rdn enable support for multivalued RDNs\n"); |
|
533 BIO_printf(bio_err," -new new request.\n"); |
|
534 BIO_printf(bio_err," -batch do not ask anything during request generation\n"); |
|
535 BIO_printf(bio_err," -x509 output a x509 structure instead of a cert. req.\n"); |
|
536 BIO_printf(bio_err," -days number of days a certificate generated by -x509 is valid for.\n"); |
|
537 BIO_printf(bio_err," -set_serial serial number to use for a certificate generated by -x509.\n"); |
|
538 BIO_printf(bio_err," -newhdr output \"NEW\" in the header lines\n"); |
|
539 BIO_printf(bio_err," -asn1-kludge Output the 'request' in a format that is wrong but some CA's\n"); |
|
540 BIO_printf(bio_err," have been reported as requiring\n"); |
|
541 BIO_printf(bio_err," -extensions .. specify certificate extension section (override value in config file)\n"); |
|
542 BIO_printf(bio_err," -reqexts .. specify request extension section (override value in config file)\n"); |
|
543 BIO_printf(bio_err," -utf8 input characters are UTF8 (default ASCII)\n"); |
|
544 BIO_printf(bio_err," -nameopt arg - various certificate name options\n"); |
|
545 BIO_printf(bio_err," -reqopt arg - various request text options\n\n"); |
|
546 goto end; |
|
547 } |
|
548 |
|
549 ERR_load_crypto_strings(); |
|
550 if(!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { |
|
551 BIO_printf(bio_err, "Error getting passwords\n"); |
|
552 goto end; |
|
553 } |
|
554 |
|
555 #ifndef MONOLITH /* else this has happened in openssl.c (global `config') */ |
|
556 /* Lets load up our environment a little */ |
|
557 p=getenv("OPENSSL_CONF"); |
|
558 if (p == NULL) |
|
559 p=getenv("SSLEAY_CONF"); |
|
560 if (p == NULL) |
|
561 p=to_free=make_config_name(); |
|
562 default_config_file=p; |
|
563 config=NCONF_new(NULL); |
|
564 i=NCONF_load(config, p, &errline); |
|
565 #endif |
|
566 |
|
567 if (template != NULL) |
|
568 { |
|
569 long errline = -1; |
|
570 |
|
571 if( verbose ) |
|
572 BIO_printf(bio_err,"Using configuration from %s\n",template); |
|
573 req_conf=NCONF_new(NULL); |
|
574 i=NCONF_load(req_conf,template,&errline); |
|
575 if (i == 0) |
|
576 { |
|
577 BIO_printf(bio_err,"error on line %ld of %s\n",errline,template); |
|
578 goto end; |
|
579 } |
|
580 } |
|
581 else |
|
582 { |
|
583 req_conf=config; |
|
584 |
|
585 if (req_conf == NULL) |
|
586 { |
|
587 BIO_printf(bio_err,"Unable to load config info from %s\n", default_config_file); |
|
588 if (newreq) |
|
589 goto end; |
|
590 } |
|
591 else if( verbose ) |
|
592 BIO_printf(bio_err,"Using configuration from %s\n", |
|
593 default_config_file); |
|
594 } |
|
595 |
|
596 if (req_conf != NULL) |
|
597 { |
|
598 if (!load_config(bio_err, req_conf)) |
|
599 goto end; |
|
600 p=NCONF_get_string(req_conf,NULL,"oid_file"); |
|
601 if (p == NULL) |
|
602 ERR_clear_error(); |
|
603 if (p != NULL) |
|
604 { |
|
605 BIO *oid_bio; |
|
606 |
|
607 oid_bio=BIO_new_file(p,"r"); |
|
608 if (oid_bio == NULL) |
|
609 { |
|
610 /* |
|
611 BIO_printf(bio_err,"problems opening %s for extra oid's\n",p); |
|
612 ERR_print_errors(bio_err); |
|
613 */ |
|
614 } |
|
615 else |
|
616 { |
|
617 OBJ_create_objects(oid_bio); |
|
618 BIO_free(oid_bio); |
|
619 } |
|
620 } |
|
621 } |
|
622 if(!add_oid_section(bio_err, req_conf)) goto end; |
|
623 |
|
624 if (md_alg == NULL) |
|
625 { |
|
626 p=NCONF_get_string(req_conf,SECTION,"default_md"); |
|
627 if (p == NULL) |
|
628 ERR_clear_error(); |
|
629 if (p != NULL) |
|
630 { |
|
631 if ((md_alg=EVP_get_digestbyname(p)) != NULL) |
|
632 digest=md_alg; |
|
633 } |
|
634 } |
|
635 |
|
636 if (!extensions) |
|
637 { |
|
638 extensions = NCONF_get_string(req_conf, SECTION, V3_EXTENSIONS); |
|
639 if (!extensions) |
|
640 ERR_clear_error(); |
|
641 } |
|
642 if (extensions) { |
|
643 /* Check syntax of file */ |
|
644 X509V3_CTX ctx; |
|
645 X509V3_set_ctx_test(&ctx); |
|
646 X509V3_set_nconf(&ctx, req_conf); |
|
647 if(!X509V3_EXT_add_nconf(req_conf, &ctx, extensions, NULL)) { |
|
648 BIO_printf(bio_err, |
|
649 "Error Loading extension section %s\n", extensions); |
|
650 goto end; |
|
651 } |
|
652 } |
|
653 |
|
654 if(!passin) |
|
655 { |
|
656 passin = NCONF_get_string(req_conf, SECTION, "input_password"); |
|
657 if (!passin) |
|
658 ERR_clear_error(); |
|
659 } |
|
660 |
|
661 if(!passout) |
|
662 { |
|
663 passout = NCONF_get_string(req_conf, SECTION, "output_password"); |
|
664 if (!passout) |
|
665 ERR_clear_error(); |
|
666 } |
|
667 |
|
668 p = NCONF_get_string(req_conf, SECTION, STRING_MASK); |
|
669 if (!p) |
|
670 ERR_clear_error(); |
|
671 |
|
672 if(p && !ASN1_STRING_set_default_mask_asc(p)) { |
|
673 BIO_printf(bio_err, "Invalid global string mask setting %s\n", p); |
|
674 goto end; |
|
675 } |
|
676 |
|
677 if (chtype != MBSTRING_UTF8) |
|
678 { |
|
679 p = NCONF_get_string(req_conf, SECTION, UTF8_IN); |
|
680 if (!p) |
|
681 ERR_clear_error(); |
|
682 else if (!strcmp(p, "yes")) |
|
683 chtype = MBSTRING_UTF8; |
|
684 } |
|
685 |
|
686 |
|
687 if(!req_exts) |
|
688 { |
|
689 req_exts = NCONF_get_string(req_conf, SECTION, REQ_EXTENSIONS); |
|
690 if (!req_exts) |
|
691 ERR_clear_error(); |
|
692 } |
|
693 if(req_exts) { |
|
694 /* Check syntax of file */ |
|
695 X509V3_CTX ctx; |
|
696 X509V3_set_ctx_test(&ctx); |
|
697 X509V3_set_nconf(&ctx, req_conf); |
|
698 if(!X509V3_EXT_add_nconf(req_conf, &ctx, req_exts, NULL)) { |
|
699 BIO_printf(bio_err, |
|
700 "Error Loading request extension section %s\n", |
|
701 req_exts); |
|
702 goto end; |
|
703 } |
|
704 } |
|
705 |
|
706 in=BIO_new(BIO_s_file()); |
|
707 out=BIO_new(BIO_s_file()); |
|
708 if ((in == NULL) || (out == NULL)) |
|
709 goto end; |
|
710 |
|
711 #ifndef OPENSSL_NO_ENGINE |
|
712 e = setup_engine(bio_err, engine, 0); |
|
713 #endif |
|
714 |
|
715 if (keyfile != NULL) |
|
716 { |
|
717 pkey = load_key(bio_err, keyfile, keyform, 0, passin, e, |
|
718 "Private Key"); |
|
719 if (!pkey) |
|
720 { |
|
721 /* load_key() has already printed an appropriate |
|
722 message */ |
|
723 goto end; |
|
724 } |
|
725 if (EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA || |
|
726 EVP_PKEY_type(pkey->type) == EVP_PKEY_EC) |
|
727 { |
|
728 char *randfile = NCONF_get_string(req_conf,SECTION,"RANDFILE"); |
|
729 if (randfile == NULL) |
|
730 ERR_clear_error(); |
|
731 app_RAND_load_file(randfile, bio_err, 0); |
|
732 } |
|
733 } |
|
734 |
|
735 if (newreq && (pkey == NULL)) |
|
736 { |
|
737 #ifndef OPENSSL_NO_RSA |
|
738 BN_GENCB cb; |
|
739 #endif |
|
740 char *randfile = NCONF_get_string(req_conf,SECTION,"RANDFILE"); |
|
741 if (randfile == NULL) |
|
742 ERR_clear_error(); |
|
743 app_RAND_load_file(randfile, bio_err, 0); |
|
744 if (inrand) |
|
745 app_RAND_load_files(inrand); |
|
746 |
|
747 if (newkey <= 0) |
|
748 { |
|
749 if (!NCONF_get_number(req_conf,SECTION,BITS, &newkey)) |
|
750 newkey=DEFAULT_KEY_LENGTH; |
|
751 } |
|
752 |
|
753 if (newkey < MIN_KEY_LENGTH && (pkey_type == TYPE_RSA || pkey_type == TYPE_DSA)) |
|
754 { |
|
755 BIO_printf(bio_err,"private key length is too short,\n"); |
|
756 BIO_printf(bio_err,"it needs to be at least %d bits, not %ld\n",MIN_KEY_LENGTH,newkey); |
|
757 goto end; |
|
758 } |
|
759 BIO_printf(bio_err,"Generating a %ld bit %s private key\n", |
|
760 newkey,(pkey_type == TYPE_RSA)?"RSA": |
|
761 (pkey_type == TYPE_DSA)?"DSA":"EC"); |
|
762 |
|
763 if ((pkey=EVP_PKEY_new()) == NULL) goto end; |
|
764 |
|
765 #ifndef OPENSSL_NO_RSA |
|
766 BN_GENCB_set(&cb, req_cb, bio_err); |
|
767 if (pkey_type == TYPE_RSA) |
|
768 { |
|
769 RSA *rsa = RSA_new(); |
|
770 BIGNUM *bn = BN_new(); |
|
771 if(!bn || !rsa || !BN_set_word(bn, 0x10001) || |
|
772 !RSA_generate_key_ex(rsa, newkey, bn, &cb) || |
|
773 !EVP_PKEY_assign_RSA(pkey, rsa)) |
|
774 { |
|
775 if(bn) BN_free(bn); |
|
776 if(rsa) RSA_free(rsa); |
|
777 goto end; |
|
778 } |
|
779 BN_free(bn); |
|
780 } |
|
781 else |
|
782 #endif |
|
783 #ifndef OPENSSL_NO_DSA |
|
784 if (pkey_type == TYPE_DSA) |
|
785 { |
|
786 if (!DSA_generate_key(dsa_params)) goto end; |
|
787 if (!EVP_PKEY_assign_DSA(pkey,dsa_params)) goto end; |
|
788 dsa_params=NULL; |
|
789 } |
|
790 #endif |
|
791 #ifndef OPENSSL_NO_ECDSA |
|
792 if (pkey_type == TYPE_EC) |
|
793 { |
|
794 if (!EC_KEY_generate_key(ec_params)) goto end; |
|
795 if (!EVP_PKEY_assign_EC_KEY(pkey, ec_params)) |
|
796 goto end; |
|
797 ec_params = NULL; |
|
798 } |
|
799 #endif |
|
800 |
|
801 app_RAND_write_file(randfile, bio_err); |
|
802 |
|
803 if (pkey == NULL) goto end; |
|
804 |
|
805 if (keyout == NULL) |
|
806 { |
|
807 keyout=NCONF_get_string(req_conf,SECTION,KEYFILE); |
|
808 if (keyout == NULL) |
|
809 ERR_clear_error(); |
|
810 } |
|
811 |
|
812 if (keyout == NULL) |
|
813 { |
|
814 BIO_printf(bio_err,"writing new private key to stdout\n"); |
|
815 BIO_set_fp(out,stdout,BIO_NOCLOSE); |
|
816 |
|
817 #ifdef OPENSSL_SYS_VMS |
|
818 { |
|
819 BIO *tmpbio = BIO_new(BIO_f_linebuffer()); |
|
820 out = BIO_push(tmpbio, out); |
|
821 } |
|
822 #endif |
|
823 } |
|
824 else |
|
825 { |
|
826 BIO_printf(bio_err,"writing new private key to '%s'\n",keyout); |
|
827 if (BIO_write_filename(out,keyout) <= 0) |
|
828 { |
|
829 perror(keyout); |
|
830 goto end; |
|
831 } |
|
832 } |
|
833 |
|
834 p=NCONF_get_string(req_conf,SECTION,"encrypt_rsa_key"); |
|
835 if (p == NULL) |
|
836 { |
|
837 ERR_clear_error(); |
|
838 p=NCONF_get_string(req_conf,SECTION,"encrypt_key"); |
|
839 if (p == NULL) |
|
840 ERR_clear_error(); |
|
841 } |
|
842 if ((p != NULL) && (strcmp(p,"no") == 0)) |
|
843 cipher=NULL; |
|
844 if (nodes) cipher=NULL; |
|
845 |
|
846 i=0; |
|
847 loop: |
|
848 if (!PEM_write_bio_PrivateKey(out,pkey,cipher, |
|
849 NULL,0,NULL,passout)) |
|
850 { |
|
851 if ((ERR_GET_REASON(ERR_peek_error()) == |
|
852 PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3)) |
|
853 { |
|
854 ERR_clear_error(); |
|
855 i++; |
|
856 goto loop; |
|
857 } |
|
858 goto end; |
|
859 } |
|
860 BIO_printf(bio_err,"-----\n"); |
|
861 } |
|
862 |
|
863 if (!newreq) |
|
864 { |
|
865 /* Since we are using a pre-existing certificate |
|
866 * request, the kludge 'format' info should not be |
|
867 * changed. */ |
|
868 kludge= -1; |
|
869 if (infile == NULL) |
|
870 BIO_set_fp(in,stdin,BIO_NOCLOSE); |
|
871 |
|
872 else |
|
873 { |
|
874 if (BIO_read_filename(in,infile) <= 0) |
|
875 { |
|
876 perror(infile); |
|
877 goto end; |
|
878 } |
|
879 } |
|
880 |
|
881 if (informat == FORMAT_ASN1) |
|
882 req=d2i_X509_REQ_bio(in,NULL); |
|
883 else if (informat == FORMAT_PEM) |
|
884 req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL); |
|
885 else |
|
886 { |
|
887 BIO_printf(bio_err,"bad input format specified for X509 request\n"); |
|
888 goto end; |
|
889 } |
|
890 if (req == NULL) |
|
891 { |
|
892 BIO_printf(bio_err,"unable to load X509 request\n"); |
|
893 goto end; |
|
894 } |
|
895 } |
|
896 |
|
897 if (newreq || x509) |
|
898 { |
|
899 if (pkey == NULL) |
|
900 { |
|
901 BIO_printf(bio_err,"you need to specify a private key\n"); |
|
902 goto end; |
|
903 } |
|
904 #ifndef OPENSSL_NO_DSA |
|
905 if (pkey->type == EVP_PKEY_DSA) |
|
906 digest=EVP_dss1(); |
|
907 #endif |
|
908 #ifndef OPENSSL_NO_ECDSA |
|
909 if (pkey->type == EVP_PKEY_EC) |
|
910 digest=EVP_ecdsa(); |
|
911 #endif |
|
912 if (req == NULL) |
|
913 { |
|
914 req=X509_REQ_new(); |
|
915 if (req == NULL) |
|
916 { |
|
917 goto end; |
|
918 } |
|
919 |
|
920 i=make_REQ(req,pkey,subj,multirdn,!x509, chtype); |
|
921 subj=NULL; /* done processing '-subj' option */ |
|
922 if ((kludge > 0) && !sk_X509_ATTRIBUTE_num(req->req_info->attributes)) |
|
923 { |
|
924 sk_X509_ATTRIBUTE_free(req->req_info->attributes); |
|
925 req->req_info->attributes = NULL; |
|
926 } |
|
927 if (!i) |
|
928 { |
|
929 BIO_printf(bio_err,"problems making Certificate Request\n"); |
|
930 goto end; |
|
931 } |
|
932 } |
|
933 if (x509) |
|
934 { |
|
935 EVP_PKEY *tmppkey; |
|
936 X509V3_CTX ext_ctx; |
|
937 if ((x509ss=X509_new()) == NULL) goto end; |
|
938 |
|
939 /* Set version to V3 */ |
|
940 if(extensions && !X509_set_version(x509ss, 2)) goto end; |
|
941 if (serial) |
|
942 { |
|
943 if (!X509_set_serialNumber(x509ss, serial)) goto end; |
|
944 } |
|
945 else |
|
946 { |
|
947 if (!rand_serial(NULL, |
|
948 X509_get_serialNumber(x509ss))) |
|
949 goto end; |
|
950 } |
|
951 |
|
952 if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req))) goto end; |
|
953 if (!X509_gmtime_adj(X509_get_notBefore(x509ss),0)) goto end; |
|
954 if (!X509_gmtime_adj(X509_get_notAfter(x509ss), (long)60*60*24*days)) goto end; |
|
955 if (!X509_set_subject_name(x509ss, X509_REQ_get_subject_name(req))) goto end; |
|
956 tmppkey = X509_REQ_get_pubkey(req); |
|
957 if (!tmppkey || !X509_set_pubkey(x509ss,tmppkey)) goto end; |
|
958 EVP_PKEY_free(tmppkey); |
|
959 |
|
960 /* Set up V3 context struct */ |
|
961 |
|
962 X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0); |
|
963 X509V3_set_nconf(&ext_ctx, req_conf); |
|
964 |
|
965 /* Add extensions */ |
|
966 if(extensions && !X509V3_EXT_add_nconf(req_conf, |
|
967 &ext_ctx, extensions, x509ss)) |
|
968 { |
|
969 BIO_printf(bio_err, |
|
970 "Error Loading extension section %s\n", |
|
971 extensions); |
|
972 goto end; |
|
973 } |
|
974 |
|
975 if (!(i=X509_sign(x509ss,pkey,digest))) |
|
976 goto end; |
|
977 } |
|
978 else |
|
979 { |
|
980 X509V3_CTX ext_ctx; |
|
981 |
|
982 /* Set up V3 context struct */ |
|
983 |
|
984 X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0); |
|
985 X509V3_set_nconf(&ext_ctx, req_conf); |
|
986 |
|
987 /* Add extensions */ |
|
988 if(req_exts && !X509V3_EXT_REQ_add_nconf(req_conf, |
|
989 &ext_ctx, req_exts, req)) |
|
990 { |
|
991 BIO_printf(bio_err, |
|
992 "Error Loading extension section %s\n", |
|
993 req_exts); |
|
994 goto end; |
|
995 } |
|
996 if (!(i=X509_REQ_sign(req,pkey,digest))) |
|
997 goto end; |
|
998 } |
|
999 } |
|
1000 |
|
1001 if (subj && x509) |
|
1002 { |
|
1003 BIO_printf(bio_err, "Cannot modifiy certificate subject\n"); |
|
1004 goto end; |
|
1005 } |
|
1006 |
|
1007 if (subj && !x509) |
|
1008 { |
|
1009 if (verbose) |
|
1010 { |
|
1011 BIO_printf(bio_err, "Modifying Request's Subject\n"); |
|
1012 print_name(bio_err, "old subject=", X509_REQ_get_subject_name(req), nmflag); |
|
1013 } |
|
1014 |
|
1015 if (build_subject(req, subj, chtype, multirdn) == 0) |
|
1016 { |
|
1017 BIO_printf(bio_err, "ERROR: cannot modify subject\n"); |
|
1018 ex=1; |
|
1019 goto end; |
|
1020 } |
|
1021 |
|
1022 req->req_info->enc.modified = 1; |
|
1023 |
|
1024 if (verbose) |
|
1025 { |
|
1026 print_name(bio_err, "new subject=", X509_REQ_get_subject_name(req), nmflag); |
|
1027 } |
|
1028 } |
|
1029 |
|
1030 if (verify && !x509) |
|
1031 { |
|
1032 int tmp=0; |
|
1033 |
|
1034 if (pkey == NULL) |
|
1035 { |
|
1036 pkey=X509_REQ_get_pubkey(req); |
|
1037 tmp=1; |
|
1038 if (pkey == NULL) goto end; |
|
1039 } |
|
1040 |
|
1041 i=X509_REQ_verify(req,pkey); |
|
1042 if (tmp) { |
|
1043 EVP_PKEY_free(pkey); |
|
1044 pkey=NULL; |
|
1045 } |
|
1046 |
|
1047 if (i < 0) |
|
1048 { |
|
1049 goto end; |
|
1050 } |
|
1051 else if (i == 0) |
|
1052 { |
|
1053 BIO_printf(bio_err,"verify failure\n"); |
|
1054 ERR_print_errors(bio_err); |
|
1055 } |
|
1056 else /* if (i > 0) */ |
|
1057 BIO_printf(bio_err,"verify OK\n"); |
|
1058 } |
|
1059 |
|
1060 if (noout && !text && !modulus && !subject && !pubkey) |
|
1061 { |
|
1062 ex=0; |
|
1063 goto end; |
|
1064 } |
|
1065 |
|
1066 if (outfile == NULL) |
|
1067 { |
|
1068 BIO_set_fp(out,stdout,BIO_NOCLOSE); |
|
1069 #ifdef OPENSSL_SYS_VMS |
|
1070 { |
|
1071 BIO *tmpbio = BIO_new(BIO_f_linebuffer()); |
|
1072 out = BIO_push(tmpbio, out); |
|
1073 } |
|
1074 #endif |
|
1075 } |
|
1076 else |
|
1077 { |
|
1078 if ((keyout != NULL) && (strcmp(outfile,keyout) == 0)) |
|
1079 i=(int)BIO_append_filename(out,outfile); |
|
1080 else |
|
1081 i=(int)BIO_write_filename(out,outfile); |
|
1082 if (!i) |
|
1083 { |
|
1084 perror(outfile); |
|
1085 goto end; |
|
1086 } |
|
1087 } |
|
1088 |
|
1089 if (pubkey) |
|
1090 { |
|
1091 EVP_PKEY *tpubkey; |
|
1092 tpubkey=X509_REQ_get_pubkey(req); |
|
1093 if (tpubkey == NULL) |
|
1094 { |
|
1095 BIO_printf(bio_err,"Error getting public key\n"); |
|
1096 ERR_print_errors(bio_err); |
|
1097 goto end; |
|
1098 } |
|
1099 PEM_write_bio_PUBKEY(out, tpubkey); |
|
1100 EVP_PKEY_free(tpubkey); |
|
1101 } |
|
1102 |
|
1103 if (text) |
|
1104 { |
|
1105 if (x509) |
|
1106 X509_print_ex(out, x509ss, nmflag, reqflag); |
|
1107 else |
|
1108 X509_REQ_print_ex(out, req, nmflag, reqflag); |
|
1109 } |
|
1110 |
|
1111 if(subject) |
|
1112 { |
|
1113 if(x509) |
|
1114 print_name(out, "subject=", X509_get_subject_name(x509ss), nmflag); |
|
1115 else |
|
1116 print_name(out, "subject=", X509_REQ_get_subject_name(req), nmflag); |
|
1117 } |
|
1118 |
|
1119 if (modulus) |
|
1120 { |
|
1121 EVP_PKEY *tpubkey; |
|
1122 |
|
1123 if (x509) |
|
1124 tpubkey=X509_get_pubkey(x509ss); |
|
1125 else |
|
1126 tpubkey=X509_REQ_get_pubkey(req); |
|
1127 if (tpubkey == NULL) |
|
1128 { |
|
1129 fprintf(stdout,"Modulus=unavailable\n"); |
|
1130 goto end; |
|
1131 } |
|
1132 |
|
1133 fprintf(stdout,"Modulus="); |
|
1134 |
|
1135 #ifndef OPENSSL_NO_RSA |
|
1136 if (tpubkey->type == EVP_PKEY_RSA) |
|
1137 BN_print(out,tpubkey->pkey.rsa->n); |
|
1138 else |
|
1139 #endif |
|
1140 fprintf(stdout,"Wrong Algorithm type"); |
|
1141 EVP_PKEY_free(tpubkey); |
|
1142 fprintf(stdout,"\n"); |
|
1143 |
|
1144 } |
|
1145 |
|
1146 if (!noout && !x509) |
|
1147 { |
|
1148 if (outformat == FORMAT_ASN1) |
|
1149 i=i2d_X509_REQ_bio(out,req); |
|
1150 else if (outformat == FORMAT_PEM) { |
|
1151 if(newhdr) i=PEM_write_bio_X509_REQ_NEW(out,req); |
|
1152 else i=PEM_write_bio_X509_REQ(out,req); |
|
1153 } else { |
|
1154 BIO_printf(bio_err,"bad output format specified for outfile\n"); |
|
1155 goto end; |
|
1156 } |
|
1157 if (!i) |
|
1158 { |
|
1159 BIO_printf(bio_err,"unable to write X509 request\n"); |
|
1160 goto end; |
|
1161 } |
|
1162 } |
|
1163 if (!noout && x509 && (x509ss != NULL)) |
|
1164 { |
|
1165 if (outformat == FORMAT_ASN1) |
|
1166 i=i2d_X509_bio(out,x509ss); |
|
1167 else if (outformat == FORMAT_PEM) |
|
1168 i=PEM_write_bio_X509(out,x509ss); |
|
1169 else { |
|
1170 BIO_printf(bio_err,"bad output format specified for outfile\n"); |
|
1171 goto end; |
|
1172 } |
|
1173 if (!i) |
|
1174 { |
|
1175 BIO_printf(bio_err,"unable to write X509 certificate\n"); |
|
1176 goto end; |
|
1177 } |
|
1178 } |
|
1179 ex=0; |
|
1180 end: |
|
1181 #ifndef MONOLITH |
|
1182 if(to_free) |
|
1183 OPENSSL_free(to_free); |
|
1184 #endif |
|
1185 if (ex) |
|
1186 { |
|
1187 ERR_print_errors(bio_err); |
|
1188 } |
|
1189 if ((req_conf != NULL) && (req_conf != config)) NCONF_free(req_conf); |
|
1190 BIO_free(in); |
|
1191 BIO_free_all(out); |
|
1192 EVP_PKEY_free(pkey); |
|
1193 X509_REQ_free(req); |
|
1194 X509_free(x509ss); |
|
1195 ASN1_INTEGER_free(serial); |
|
1196 if(passargin && passin) OPENSSL_free(passin); |
|
1197 if(passargout && passout) OPENSSL_free(passout); |
|
1198 OBJ_cleanup(); |
|
1199 #ifndef OPENSSL_NO_DSA |
|
1200 if (dsa_params != NULL) DSA_free(dsa_params); |
|
1201 #endif |
|
1202 #ifndef OPENSSL_NO_ECDSA |
|
1203 if (ec_params != NULL) EC_KEY_free(ec_params); |
|
1204 #endif |
|
1205 apps_shutdown(); |
|
1206 OPENSSL_EXIT(ex); |
|
1207 } |
|
1208 |
|
1209 static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn, |
|
1210 int attribs, unsigned long chtype) |
|
1211 { |
|
1212 int ret=0,i; |
|
1213 char no_prompt = 0; |
|
1214 STACK_OF(CONF_VALUE) *dn_sk, *attr_sk = NULL; |
|
1215 char *tmp, *dn_sect,*attr_sect; |
|
1216 |
|
1217 tmp=NCONF_get_string(req_conf,SECTION,PROMPT); |
|
1218 if (tmp == NULL) |
|
1219 ERR_clear_error(); |
|
1220 if((tmp != NULL) && !strcmp(tmp, "no")) no_prompt = 1; |
|
1221 |
|
1222 dn_sect=NCONF_get_string(req_conf,SECTION,DISTINGUISHED_NAME); |
|
1223 if (dn_sect == NULL) |
|
1224 { |
|
1225 BIO_printf(bio_err,"unable to find '%s' in config\n", |
|
1226 DISTINGUISHED_NAME); |
|
1227 goto err; |
|
1228 } |
|
1229 dn_sk=NCONF_get_section(req_conf,dn_sect); |
|
1230 if (dn_sk == NULL) |
|
1231 { |
|
1232 BIO_printf(bio_err,"unable to get '%s' section\n",dn_sect); |
|
1233 goto err; |
|
1234 } |
|
1235 |
|
1236 attr_sect=NCONF_get_string(req_conf,SECTION,ATTRIBUTES); |
|
1237 if (attr_sect == NULL) |
|
1238 { |
|
1239 ERR_clear_error(); |
|
1240 attr_sk=NULL; |
|
1241 } |
|
1242 else |
|
1243 { |
|
1244 attr_sk=NCONF_get_section(req_conf,attr_sect); |
|
1245 if (attr_sk == NULL) |
|
1246 { |
|
1247 BIO_printf(bio_err,"unable to get '%s' section\n",attr_sect); |
|
1248 goto err; |
|
1249 } |
|
1250 } |
|
1251 |
|
1252 /* setup version number */ |
|
1253 if (!X509_REQ_set_version(req,0L)) goto err; /* version 1 */ |
|
1254 |
|
1255 if (no_prompt) |
|
1256 i = auto_info(req, dn_sk, attr_sk, attribs, chtype); |
|
1257 else |
|
1258 { |
|
1259 if (subj) |
|
1260 i = build_subject(req, subj, chtype, multirdn); |
|
1261 else |
|
1262 i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs, chtype); |
|
1263 } |
|
1264 if(!i) goto err; |
|
1265 |
|
1266 if (!X509_REQ_set_pubkey(req,pkey)) goto err; |
|
1267 |
|
1268 ret=1; |
|
1269 err: |
|
1270 return(ret); |
|
1271 } |
|
1272 |
|
1273 /* |
|
1274 * subject is expected to be in the format /type0=value0/type1=value1/type2=... |
|
1275 * where characters may be escaped by \ |
|
1276 */ |
|
1277 static int build_subject(X509_REQ *req, char *subject, unsigned long chtype, int multirdn) |
|
1278 { |
|
1279 X509_NAME *n; |
|
1280 |
|
1281 if (!(n = parse_name(subject, chtype, multirdn))) |
|
1282 return 0; |
|
1283 |
|
1284 if (!X509_REQ_set_subject_name(req, n)) |
|
1285 { |
|
1286 X509_NAME_free(n); |
|
1287 return 0; |
|
1288 } |
|
1289 X509_NAME_free(n); |
|
1290 return 1; |
|
1291 } |
|
1292 |
|
1293 |
|
1294 static int prompt_info(X509_REQ *req, |
|
1295 STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect, |
|
1296 STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect, int attribs, |
|
1297 unsigned long chtype) |
|
1298 { |
|
1299 int i; |
|
1300 char *p,*q; |
|
1301 char buf[100]; |
|
1302 int nid, mval; |
|
1303 long n_min,n_max; |
|
1304 char *type, *value; |
|
1305 const char *def; |
|
1306 CONF_VALUE *v; |
|
1307 X509_NAME *subj; |
|
1308 subj = X509_REQ_get_subject_name(req); |
|
1309 |
|
1310 if(!batch) |
|
1311 { |
|
1312 BIO_printf(bio_err,"You are about to be asked to enter information that will be incorporated\n"); |
|
1313 BIO_printf(bio_err,"into your certificate request.\n"); |
|
1314 BIO_printf(bio_err,"What you are about to enter is what is called a Distinguished Name or a DN.\n"); |
|
1315 BIO_printf(bio_err,"There are quite a few fields but you can leave some blank\n"); |
|
1316 BIO_printf(bio_err,"For some fields there will be a default value,\n"); |
|
1317 BIO_printf(bio_err,"If you enter '.', the field will be left blank.\n"); |
|
1318 BIO_printf(bio_err,"-----\n"); |
|
1319 } |
|
1320 |
|
1321 |
|
1322 if (sk_CONF_VALUE_num(dn_sk)) |
|
1323 { |
|
1324 i= -1; |
|
1325 start: for (;;) |
|
1326 { |
|
1327 i++; |
|
1328 if (sk_CONF_VALUE_num(dn_sk) <= i) break; |
|
1329 |
|
1330 v=sk_CONF_VALUE_value(dn_sk,i); |
|
1331 p=q=NULL; |
|
1332 type=v->name; |
|
1333 if(!check_end(type,"_min") || !check_end(type,"_max") || |
|
1334 !check_end(type,"_default") || |
|
1335 !check_end(type,"_value")) continue; |
|
1336 /* Skip past any leading X. X: X, etc to allow for |
|
1337 * multiple instances |
|
1338 */ |
|
1339 for(p = v->name; *p ; p++) |
|
1340 if ((*p == ':') || (*p == ',') || |
|
1341 (*p == '.')) { |
|
1342 p++; |
|
1343 if(*p) type = p; |
|
1344 break; |
|
1345 } |
|
1346 if (*type == '+') |
|
1347 { |
|
1348 mval = -1; |
|
1349 type++; |
|
1350 } |
|
1351 else |
|
1352 mval = 0; |
|
1353 /* If OBJ not recognised ignore it */ |
|
1354 if ((nid=OBJ_txt2nid(type)) == NID_undef) goto start; |
|
1355 if (BIO_snprintf(buf,sizeof buf,"%s_default",v->name) |
|
1356 >= (int)sizeof(buf)) |
|
1357 { |
|
1358 BIO_printf(bio_err,"Name '%s' too long\n",v->name); |
|
1359 return 0; |
|
1360 } |
|
1361 |
|
1362 if ((def=NCONF_get_string(req_conf,dn_sect,buf)) == NULL) |
|
1363 { |
|
1364 ERR_clear_error(); |
|
1365 def=""; |
|
1366 } |
|
1367 |
|
1368 BIO_snprintf(buf,sizeof buf,"%s_value",v->name); |
|
1369 if ((value=NCONF_get_string(req_conf,dn_sect,buf)) == NULL) |
|
1370 { |
|
1371 ERR_clear_error(); |
|
1372 value=NULL; |
|
1373 } |
|
1374 |
|
1375 BIO_snprintf(buf,sizeof buf,"%s_min",v->name); |
|
1376 if (!NCONF_get_number(req_conf,dn_sect,buf, &n_min)) |
|
1377 { |
|
1378 ERR_clear_error(); |
|
1379 n_min = -1; |
|
1380 } |
|
1381 |
|
1382 BIO_snprintf(buf,sizeof buf,"%s_max",v->name); |
|
1383 if (!NCONF_get_number(req_conf,dn_sect,buf, &n_max)) |
|
1384 { |
|
1385 ERR_clear_error(); |
|
1386 n_max = -1; |
|
1387 } |
|
1388 |
|
1389 if (!add_DN_object(subj,v->value,def,value,nid, |
|
1390 n_min,n_max, chtype, mval)) |
|
1391 return 0; |
|
1392 } |
|
1393 if (X509_NAME_entry_count(subj) == 0) |
|
1394 { |
|
1395 BIO_printf(bio_err,"error, no objects specified in config file\n"); |
|
1396 return 0; |
|
1397 } |
|
1398 |
|
1399 if (attribs) |
|
1400 { |
|
1401 if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0) && (!batch)) |
|
1402 { |
|
1403 BIO_printf(bio_err,"\nPlease enter the following 'extra' attributes\n"); |
|
1404 BIO_printf(bio_err,"to be sent with your certificate request\n"); |
|
1405 } |
|
1406 |
|
1407 i= -1; |
|
1408 start2: for (;;) |
|
1409 { |
|
1410 i++; |
|
1411 if ((attr_sk == NULL) || |
|
1412 (sk_CONF_VALUE_num(attr_sk) <= i)) |
|
1413 break; |
|
1414 |
|
1415 v=sk_CONF_VALUE_value(attr_sk,i); |
|
1416 type=v->name; |
|
1417 if ((nid=OBJ_txt2nid(type)) == NID_undef) |
|
1418 goto start2; |
|
1419 |
|
1420 if (BIO_snprintf(buf,sizeof buf,"%s_default",type) |
|
1421 >= (int)sizeof(buf)) |
|
1422 { |
|
1423 BIO_printf(bio_err,"Name '%s' too long\n",v->name); |
|
1424 return 0; |
|
1425 } |
|
1426 |
|
1427 if ((def=NCONF_get_string(req_conf,attr_sect,buf)) |
|
1428 == NULL) |
|
1429 { |
|
1430 ERR_clear_error(); |
|
1431 def=""; |
|
1432 } |
|
1433 |
|
1434 |
|
1435 BIO_snprintf(buf,sizeof buf,"%s_value",type); |
|
1436 if ((value=NCONF_get_string(req_conf,attr_sect,buf)) |
|
1437 == NULL) |
|
1438 { |
|
1439 ERR_clear_error(); |
|
1440 value=NULL; |
|
1441 } |
|
1442 |
|
1443 BIO_snprintf(buf,sizeof buf,"%s_min",type); |
|
1444 if (!NCONF_get_number(req_conf,attr_sect,buf, &n_min)) |
|
1445 n_min = -1; |
|
1446 |
|
1447 BIO_snprintf(buf,sizeof buf,"%s_max",type); |
|
1448 if (!NCONF_get_number(req_conf,attr_sect,buf, &n_max)) |
|
1449 n_max = -1; |
|
1450 |
|
1451 if (!add_attribute_object(req, |
|
1452 v->value,def,value,nid,n_min,n_max, chtype)) |
|
1453 return 0; |
|
1454 } |
|
1455 } |
|
1456 } |
|
1457 else |
|
1458 { |
|
1459 BIO_printf(bio_err,"No template, please set one up.\n"); |
|
1460 return 0; |
|
1461 } |
|
1462 |
|
1463 return 1; |
|
1464 |
|
1465 } |
|
1466 |
|
1467 static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk, |
|
1468 STACK_OF(CONF_VALUE) *attr_sk, int attribs, unsigned long chtype) |
|
1469 { |
|
1470 int i; |
|
1471 char *p,*q; |
|
1472 char *type; |
|
1473 CONF_VALUE *v; |
|
1474 X509_NAME *subj; |
|
1475 |
|
1476 subj = X509_REQ_get_subject_name(req); |
|
1477 |
|
1478 for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) |
|
1479 { |
|
1480 int mval; |
|
1481 v=sk_CONF_VALUE_value(dn_sk,i); |
|
1482 p=q=NULL; |
|
1483 type=v->name; |
|
1484 /* Skip past any leading X. X: X, etc to allow for |
|
1485 * multiple instances |
|
1486 */ |
|
1487 for(p = v->name; *p ; p++) |
|
1488 #ifndef CHARSET_EBCDIC |
|
1489 if ((*p == ':') || (*p == ',') || (*p == '.')) { |
|
1490 #else |
|
1491 if ((*p == os_toascii[':']) || (*p == os_toascii[',']) || (*p == os_toascii['.'])) { |
|
1492 #endif |
|
1493 p++; |
|
1494 if(*p) type = p; |
|
1495 break; |
|
1496 } |
|
1497 #ifndef CHARSET_EBCDIC |
|
1498 if (*p == '+') |
|
1499 #else |
|
1500 if (*p == os_toascii['+']) |
|
1501 #endif |
|
1502 { |
|
1503 p++; |
|
1504 mval = -1; |
|
1505 } |
|
1506 else |
|
1507 mval = 0; |
|
1508 if (!X509_NAME_add_entry_by_txt(subj,type, chtype, |
|
1509 (unsigned char *) v->value,-1,-1,mval)) return 0; |
|
1510 |
|
1511 } |
|
1512 |
|
1513 if (!X509_NAME_entry_count(subj)) |
|
1514 { |
|
1515 BIO_printf(bio_err,"error, no objects specified in config file\n"); |
|
1516 return 0; |
|
1517 } |
|
1518 if (attribs) |
|
1519 { |
|
1520 for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) |
|
1521 { |
|
1522 v=sk_CONF_VALUE_value(attr_sk,i); |
|
1523 if(!X509_REQ_add1_attr_by_txt(req, v->name, chtype, |
|
1524 (unsigned char *)v->value, -1)) return 0; |
|
1525 } |
|
1526 } |
|
1527 return 1; |
|
1528 } |
|
1529 |
|
1530 |
|
1531 static int add_DN_object(X509_NAME *n, char *text, const char *def, char *value, |
|
1532 int nid, int n_min, int n_max, unsigned long chtype, int mval) |
|
1533 { |
|
1534 int i,ret=0; |
|
1535 MS_STATIC char buf[1024]; |
|
1536 start: |
|
1537 if (!batch) BIO_printf(bio_err,"%s [%s]:",text,def); |
|
1538 (void)BIO_flush(bio_err); |
|
1539 if(value != NULL) |
|
1540 { |
|
1541 BUF_strlcpy(buf,value,sizeof buf); |
|
1542 BUF_strlcat(buf,"\n",sizeof buf); |
|
1543 BIO_printf(bio_err,"%s\n",value); |
|
1544 } |
|
1545 else |
|
1546 { |
|
1547 buf[0]='\0'; |
|
1548 if (!batch) |
|
1549 { |
|
1550 fgets(buf,sizeof buf,stdin); |
|
1551 } |
|
1552 else |
|
1553 { |
|
1554 buf[0] = '\n'; |
|
1555 buf[1] = '\0'; |
|
1556 } |
|
1557 } |
|
1558 |
|
1559 if (buf[0] == '\0') return(0); |
|
1560 else if (buf[0] == '\n') |
|
1561 { |
|
1562 if ((def == NULL) || (def[0] == '\0')) |
|
1563 return(1); |
|
1564 BUF_strlcpy(buf,def,sizeof buf); |
|
1565 BUF_strlcat(buf,"\n",sizeof buf); |
|
1566 } |
|
1567 else if ((buf[0] == '.') && (buf[1] == '\n')) return(1); |
|
1568 |
|
1569 i=strlen(buf); |
|
1570 if (buf[i-1] != '\n') |
|
1571 { |
|
1572 BIO_printf(bio_err,"weird input :-(\n"); |
|
1573 return(0); |
|
1574 } |
|
1575 buf[--i]='\0'; |
|
1576 #ifdef CHARSET_EBCDIC |
|
1577 ebcdic2ascii(buf, buf, i); |
|
1578 #endif |
|
1579 if(!req_check_len(i, n_min, n_max)) goto start; |
|
1580 if (!X509_NAME_add_entry_by_NID(n,nid, chtype, |
|
1581 (unsigned char *) buf, -1,-1,mval)) goto err; |
|
1582 ret=1; |
|
1583 err: |
|
1584 return(ret); |
|
1585 } |
|
1586 |
|
1587 static int add_attribute_object(X509_REQ *req, char *text, const char *def, |
|
1588 char *value, int nid, int n_min, |
|
1589 int n_max, unsigned long chtype) |
|
1590 { |
|
1591 int i; |
|
1592 static char buf[1024]; |
|
1593 |
|
1594 start: |
|
1595 if (!batch) BIO_printf(bio_err,"%s [%s]:",text,def); |
|
1596 (void)BIO_flush(bio_err); |
|
1597 if (value != NULL) |
|
1598 { |
|
1599 BUF_strlcpy(buf,value,sizeof buf); |
|
1600 BUF_strlcat(buf,"\n",sizeof buf); |
|
1601 BIO_printf(bio_err,"%s\n",value); |
|
1602 } |
|
1603 else |
|
1604 { |
|
1605 buf[0]='\0'; |
|
1606 if (!batch) |
|
1607 { |
|
1608 fgets(buf,sizeof buf,stdin); |
|
1609 } |
|
1610 else |
|
1611 { |
|
1612 buf[0] = '\n'; |
|
1613 buf[1] = '\0'; |
|
1614 } |
|
1615 } |
|
1616 |
|
1617 if (buf[0] == '\0') return(0); |
|
1618 else if (buf[0] == '\n') |
|
1619 { |
|
1620 if ((def == NULL) || (def[0] == '\0')) |
|
1621 return(1); |
|
1622 BUF_strlcpy(buf,def,sizeof buf); |
|
1623 BUF_strlcat(buf,"\n",sizeof buf); |
|
1624 } |
|
1625 else if ((buf[0] == '.') && (buf[1] == '\n')) return(1); |
|
1626 |
|
1627 i=strlen(buf); |
|
1628 if (buf[i-1] != '\n') |
|
1629 { |
|
1630 BIO_printf(bio_err,"weird input :-(\n"); |
|
1631 return(0); |
|
1632 } |
|
1633 buf[--i]='\0'; |
|
1634 #ifdef CHARSET_EBCDIC |
|
1635 ebcdic2ascii(buf, buf, i); |
|
1636 #endif |
|
1637 if(!req_check_len(i, n_min, n_max)) goto start; |
|
1638 |
|
1639 if(!X509_REQ_add1_attr_by_NID(req, nid, chtype, |
|
1640 (unsigned char *)buf, -1)) { |
|
1641 BIO_printf(bio_err, "Error adding attribute\n"); |
|
1642 ERR_print_errors(bio_err); |
|
1643 goto err; |
|
1644 } |
|
1645 |
|
1646 return(1); |
|
1647 err: |
|
1648 return(0); |
|
1649 } |
|
1650 |
|
1651 #ifndef OPENSSL_NO_RSA |
|
1652 static int MS_CALLBACK req_cb(int p, int n, BN_GENCB *cb) |
|
1653 { |
|
1654 char c='*'; |
|
1655 |
|
1656 if (p == 0) c='.'; |
|
1657 if (p == 1) c='+'; |
|
1658 if (p == 2) c='*'; |
|
1659 if (p == 3) c='\n'; |
|
1660 BIO_write(cb->arg,&c,1); |
|
1661 (void)BIO_flush(cb->arg); |
|
1662 #ifdef LINT |
|
1663 p=n; |
|
1664 #endif |
|
1665 return 1; |
|
1666 } |
|
1667 #endif |
|
1668 |
|
1669 static int req_check_len(int len, int n_min, int n_max) |
|
1670 { |
|
1671 if ((n_min > 0) && (len < n_min)) |
|
1672 { |
|
1673 BIO_printf(bio_err,"string is too short, it needs to be at least %d bytes long\n",n_min); |
|
1674 return(0); |
|
1675 } |
|
1676 if ((n_max >= 0) && (len > n_max)) |
|
1677 { |
|
1678 BIO_printf(bio_err,"string is too long, it needs to be less than %d bytes long\n",n_max); |
|
1679 return(0); |
|
1680 } |
|
1681 return(1); |
|
1682 } |
|
1683 |
|
1684 /* Check if the end of a string matches 'end' */ |
|
1685 static int check_end(const char *str, const char *end) |
|
1686 { |
|
1687 int elen, slen; |
|
1688 const char *tmp; |
|
1689 elen = strlen(end); |
|
1690 slen = strlen(str); |
|
1691 if(elen > slen) return 1; |
|
1692 tmp = str + slen - elen; |
|
1693 return strcmp(tmp, end); |
|
1694 } |