OLD | NEW |
| (Empty) |
1 /* pkcs12.c */ | |
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | |
3 * project. | |
4 */ | |
5 /* ==================================================================== | |
6 * Copyright (c) 1999-2006 The OpenSSL Project. All rights reserved. | |
7 * | |
8 * Redistribution and use in source and binary forms, with or without | |
9 * modification, are permitted provided that the following conditions | |
10 * are met: | |
11 * | |
12 * 1. Redistributions of source code must retain the above copyright | |
13 * notice, this list of conditions and the following disclaimer. | |
14 * | |
15 * 2. Redistributions in binary form must reproduce the above copyright | |
16 * notice, this list of conditions and the following disclaimer in | |
17 * the documentation and/or other materials provided with the | |
18 * distribution. | |
19 * | |
20 * 3. All advertising materials mentioning features or use of this | |
21 * software must display the following acknowledgment: | |
22 * "This product includes software developed by the OpenSSL Project | |
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | |
24 * | |
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
26 * endorse or promote products derived from this software without | |
27 * prior written permission. For written permission, please contact | |
28 * licensing@OpenSSL.org. | |
29 * | |
30 * 5. Products derived from this software may not be called "OpenSSL" | |
31 * nor may "OpenSSL" appear in their names without prior written | |
32 * permission of the OpenSSL Project. | |
33 * | |
34 * 6. Redistributions of any form whatsoever must retain the following | |
35 * acknowledgment: | |
36 * "This product includes software developed by the OpenSSL Project | |
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | |
38 * | |
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
50 * OF THE POSSIBILITY OF SUCH DAMAGE. | |
51 * ==================================================================== | |
52 * | |
53 * This product includes cryptographic software written by Eric Young | |
54 * (eay@cryptsoft.com). This product includes software written by Tim | |
55 * Hudson (tjh@cryptsoft.com). | |
56 * | |
57 */ | |
58 | |
59 #include <openssl/opensslconf.h> | |
60 #if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_SHA1) | |
61 | |
62 #include <stdio.h> | |
63 #include <stdlib.h> | |
64 #include <string.h> | |
65 #include "apps.h" | |
66 #include <openssl/crypto.h> | |
67 #include <openssl/err.h> | |
68 #include <openssl/pem.h> | |
69 #include <openssl/pkcs12.h> | |
70 | |
71 #define PROG pkcs12_main | |
72 | |
73 const EVP_CIPHER *enc; | |
74 | |
75 | |
76 #define NOKEYS 0x1 | |
77 #define NOCERTS 0x2 | |
78 #define INFO 0x4 | |
79 #define CLCERTS 0x8 | |
80 #define CACERTS 0x10 | |
81 | |
82 int get_cert_chain (X509 *cert, X509_STORE *store, STACK_OF(X509) **chain); | |
83 int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen, int opti
ons, char *pempass); | |
84 int dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags, char *pass, | |
85 int passlen, int options, char *pempass); | |
86 int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bags, char *pass, int passlen
, int options, char *pempass); | |
87 int print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst,const char *name); | |
88 void hex_prin(BIO *out, unsigned char *buf, int len); | |
89 int alg_print(BIO *x, X509_ALGOR *alg); | |
90 int cert_load(BIO *in, STACK_OF(X509) *sk); | |
91 static int set_pbe(BIO *err, int *ppbe, const char *str); | |
92 | |
93 int MAIN(int, char **); | |
94 | |
95 int MAIN(int argc, char **argv) | |
96 { | |
97 ENGINE *e = NULL; | |
98 char *infile=NULL, *outfile=NULL, *keyname = NULL; | |
99 char *certfile=NULL; | |
100 BIO *in=NULL, *out = NULL; | |
101 char **args; | |
102 char *name = NULL; | |
103 char *csp_name = NULL; | |
104 int add_lmk = 0; | |
105 PKCS12 *p12 = NULL; | |
106 char pass[50], macpass[50]; | |
107 int export_cert = 0; | |
108 int options = 0; | |
109 int chain = 0; | |
110 int badarg = 0; | |
111 int iter = PKCS12_DEFAULT_ITER; | |
112 int maciter = PKCS12_DEFAULT_ITER; | |
113 int twopass = 0; | |
114 int keytype = 0; | |
115 int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC; | |
116 int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; | |
117 int ret = 1; | |
118 int macver = 1; | |
119 int noprompt = 0; | |
120 STACK_OF(OPENSSL_STRING) *canames = NULL; | |
121 char *cpass = NULL, *mpass = NULL; | |
122 char *passargin = NULL, *passargout = NULL, *passarg = NULL; | |
123 char *passin = NULL, *passout = NULL; | |
124 char *inrand = NULL; | |
125 char *macalg = NULL; | |
126 char *CApath = NULL, *CAfile = NULL; | |
127 #ifndef OPENSSL_NO_ENGINE | |
128 char *engine=NULL; | |
129 #endif | |
130 | |
131 apps_startup(); | |
132 | |
133 enc = EVP_des_ede3_cbc(); | |
134 if (bio_err == NULL ) bio_err = BIO_new_fp (stderr, BIO_NOCLOSE); | |
135 | |
136 if (!load_config(bio_err, NULL)) | |
137 goto end; | |
138 | |
139 args = argv + 1; | |
140 | |
141 | |
142 while (*args) { | |
143 if (*args[0] == '-') { | |
144 if (!strcmp (*args, "-nokeys")) options |= NOKEYS; | |
145 else if (!strcmp (*args, "-keyex")) keytype = KEY_EX; | |
146 else if (!strcmp (*args, "-keysig")) keytype = KEY_SIG; | |
147 else if (!strcmp (*args, "-nocerts")) options |= NOCERTS; | |
148 else if (!strcmp (*args, "-clcerts")) options |= CLCERTS; | |
149 else if (!strcmp (*args, "-cacerts")) options |= CACERTS; | |
150 else if (!strcmp (*args, "-noout")) options |= (NOKEYS|NOCERTS); | |
151 else if (!strcmp (*args, "-info")) options |= INFO; | |
152 else if (!strcmp (*args, "-chain")) chain = 1; | |
153 else if (!strcmp (*args, "-twopass")) twopass = 1; | |
154 else if (!strcmp (*args, "-nomacver")) macver = 0; | |
155 else if (!strcmp (*args, "-descert")) | |
156 cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; | |
157 else if (!strcmp (*args, "-export")) export_cert = 1; | |
158 else if (!strcmp (*args, "-des")) enc=EVP_des_cbc(); | |
159 else if (!strcmp (*args, "-des3")) enc = EVP_des_ede3_cbc(); | |
160 #ifndef OPENSSL_NO_IDEA | |
161 else if (!strcmp (*args, "-idea")) enc=EVP_idea_cbc(); | |
162 #endif | |
163 #ifndef OPENSSL_NO_SEED | |
164 else if (!strcmp(*args, "-seed")) enc=EVP_seed_cbc(); | |
165 #endif | |
166 #ifndef OPENSSL_NO_AES | |
167 else if (!strcmp(*args,"-aes128")) enc=EVP_aes_128_cbc(); | |
168 else if (!strcmp(*args,"-aes192")) enc=EVP_aes_192_cbc(); | |
169 else if (!strcmp(*args,"-aes256")) enc=EVP_aes_256_cbc(); | |
170 #endif | |
171 #ifndef OPENSSL_NO_CAMELLIA | |
172 else if (!strcmp(*args,"-camellia128")) enc=EVP_camellia_128_cbc
(); | |
173 else if (!strcmp(*args,"-camellia192")) enc=EVP_camellia_192_cbc
(); | |
174 else if (!strcmp(*args,"-camellia256")) enc=EVP_camellia_256_cbc
(); | |
175 #endif | |
176 else if (!strcmp (*args, "-noiter")) iter = 1; | |
177 else if (!strcmp (*args, "-maciter")) | |
178 maciter = PKCS12_DEFAULT_ITER; | |
179 else if (!strcmp (*args, "-nomaciter")) | |
180 maciter = 1; | |
181 else if (!strcmp (*args, "-nomac")) | |
182 maciter = -1; | |
183 else if (!strcmp (*args, "-macalg")) | |
184 if (args[1]) { | |
185 args++; | |
186 macalg = *args; | |
187 } else badarg = 1; | |
188 else if (!strcmp (*args, "-nodes")) enc=NULL; | |
189 else if (!strcmp (*args, "-certpbe")) { | |
190 if (!set_pbe(bio_err, &cert_pbe, *++args)) | |
191 badarg = 1; | |
192 } else if (!strcmp (*args, "-keypbe")) { | |
193 if (!set_pbe(bio_err, &key_pbe, *++args)) | |
194 badarg = 1; | |
195 } else if (!strcmp (*args, "-rand")) { | |
196 if (args[1]) { | |
197 args++; | |
198 inrand = *args; | |
199 } else badarg = 1; | |
200 } else if (!strcmp (*args, "-inkey")) { | |
201 if (args[1]) { | |
202 args++; | |
203 keyname = *args; | |
204 } else badarg = 1; | |
205 } else if (!strcmp (*args, "-certfile")) { | |
206 if (args[1]) { | |
207 args++; | |
208 certfile = *args; | |
209 } else badarg = 1; | |
210 } else if (!strcmp (*args, "-name")) { | |
211 if (args[1]) { | |
212 args++; | |
213 name = *args; | |
214 } else badarg = 1; | |
215 } else if (!strcmp (*args, "-LMK")) | |
216 add_lmk = 1; | |
217 else if (!strcmp (*args, "-CSP")) { | |
218 if (args[1]) { | |
219 args++; | |
220 csp_name = *args; | |
221 } else badarg = 1; | |
222 } else if (!strcmp (*args, "-caname")) { | |
223 if (args[1]) { | |
224 args++; | |
225 if (!canames) canames = sk_OPENSSL_STRING_new_null(); | |
226 sk_OPENSSL_STRING_push(canames, *args); | |
227 } else badarg = 1; | |
228 } else if (!strcmp (*args, "-in")) { | |
229 if (args[1]) { | |
230 args++; | |
231 infile = *args; | |
232 } else badarg = 1; | |
233 } else if (!strcmp (*args, "-out")) { | |
234 if (args[1]) { | |
235 args++; | |
236 outfile = *args; | |
237 } else badarg = 1; | |
238 } else if (!strcmp(*args,"-passin")) { | |
239 if (args[1]) { | |
240 args++; | |
241 passargin = *args; | |
242 } else badarg = 1; | |
243 } else if (!strcmp(*args,"-passout")) { | |
244 if (args[1]) { | |
245 args++; | |
246 passargout = *args; | |
247 } else badarg = 1; | |
248 } else if (!strcmp (*args, "-password")) { | |
249 if (args[1]) { | |
250 args++; | |
251 passarg = *args; | |
252 noprompt = 1; | |
253 } else badarg = 1; | |
254 } else if (!strcmp(*args,"-CApath")) { | |
255 if (args[1]) { | |
256 args++; | |
257 CApath = *args; | |
258 } else badarg = 1; | |
259 } else if (!strcmp(*args,"-CAfile")) { | |
260 if (args[1]) { | |
261 args++; | |
262 CAfile = *args; | |
263 } else badarg = 1; | |
264 #ifndef OPENSSL_NO_ENGINE | |
265 } else if (!strcmp(*args,"-engine")) { | |
266 if (args[1]) { | |
267 args++; | |
268 engine = *args; | |
269 } else badarg = 1; | |
270 #endif | |
271 } else badarg = 1; | |
272 | |
273 } else badarg = 1; | |
274 args++; | |
275 } | |
276 | |
277 if (badarg) { | |
278 BIO_printf (bio_err, "Usage: pkcs12 [options]\n"); | |
279 BIO_printf (bio_err, "where options are\n"); | |
280 BIO_printf (bio_err, "-export output PKCS12 file\n"); | |
281 BIO_printf (bio_err, "-chain add certificate chain\n"); | |
282 BIO_printf (bio_err, "-inkey file private key if not infile\n"); | |
283 BIO_printf (bio_err, "-certfile f add all certs in f\n"); | |
284 BIO_printf (bio_err, "-CApath arg - PEM format directory of CA's\n"); | |
285 BIO_printf (bio_err, "-CAfile arg - PEM format file of CA's\n"); | |
286 BIO_printf (bio_err, "-name \"name\" use name as friendly name\n"); | |
287 BIO_printf (bio_err, "-caname \"nm\" use nm as CA friendly name (can be
used more than once).\n"); | |
288 BIO_printf (bio_err, "-in infile input filename\n"); | |
289 BIO_printf (bio_err, "-out outfile output filename\n"); | |
290 BIO_printf (bio_err, "-noout don't output anything, just verify.\
n"); | |
291 BIO_printf (bio_err, "-nomacver don't verify MAC.\n"); | |
292 BIO_printf (bio_err, "-nocerts don't output certificates.\n"); | |
293 BIO_printf (bio_err, "-clcerts only output client certificates.\n")
; | |
294 BIO_printf (bio_err, "-cacerts only output CA certificates.\n"); | |
295 BIO_printf (bio_err, "-nokeys don't output private keys.\n"); | |
296 BIO_printf (bio_err, "-info give info about PKCS#12 structure.\n
"); | |
297 BIO_printf (bio_err, "-des encrypt private keys with DES\n"); | |
298 BIO_printf (bio_err, "-des3 encrypt private keys with triple DES
(default)\n"); | |
299 #ifndef OPENSSL_NO_IDEA | |
300 BIO_printf (bio_err, "-idea encrypt private keys with idea\n"); | |
301 #endif | |
302 #ifndef OPENSSL_NO_SEED | |
303 BIO_printf (bio_err, "-seed encrypt private keys with seed\n"); | |
304 #endif | |
305 #ifndef OPENSSL_NO_AES | |
306 BIO_printf (bio_err, "-aes128, -aes192, -aes256\n"); | |
307 BIO_printf (bio_err, " encrypt PEM output with cbc aes\n"); | |
308 #endif | |
309 #ifndef OPENSSL_NO_CAMELLIA | |
310 BIO_printf (bio_err, "-camellia128, -camellia192, -camellia256\n"); | |
311 BIO_printf (bio_err, " encrypt PEM output with cbc camellia
\n"); | |
312 #endif | |
313 BIO_printf (bio_err, "-nodes don't encrypt private keys\n"); | |
314 BIO_printf (bio_err, "-noiter don't use encryption iteration\n"); | |
315 BIO_printf (bio_err, "-nomaciter don't use MAC iteration\n"); | |
316 BIO_printf (bio_err, "-maciter use MAC iteration\n"); | |
317 BIO_printf (bio_err, "-nomac don't generate MAC\n"); | |
318 BIO_printf (bio_err, "-twopass separate MAC, encryption passwords\n
"); | |
319 BIO_printf (bio_err, "-descert encrypt PKCS#12 certificates with tr
iple DES (default RC2-40)\n"); | |
320 BIO_printf (bio_err, "-certpbe alg specify certificate PBE algorithm (d
efault RC2-40)\n"); | |
321 BIO_printf (bio_err, "-keypbe alg specify private key PBE algorithm (d
efault 3DES)\n"); | |
322 BIO_printf (bio_err, "-macalg alg digest algorithm used in MAC (defaul
t SHA1)\n"); | |
323 BIO_printf (bio_err, "-keyex set MS key exchange type\n"); | |
324 BIO_printf (bio_err, "-keysig set MS key signature type\n"); | |
325 BIO_printf (bio_err, "-password p set import/export password source\n"
); | |
326 BIO_printf (bio_err, "-passin p input file pass phrase source\n"); | |
327 BIO_printf (bio_err, "-passout p output file pass phrase source\n"); | |
328 #ifndef OPENSSL_NO_ENGINE | |
329 BIO_printf (bio_err, "-engine e use engine e, possibly a hardware de
vice.\n"); | |
330 #endif | |
331 BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIS
T_SEPARATOR_CHAR); | |
332 BIO_printf(bio_err, " load the file (or the files in the d
irectory) into\n"); | |
333 BIO_printf(bio_err, " the random number generator\n"); | |
334 BIO_printf(bio_err, "-CSP name Microsoft CSP name\n"); | |
335 BIO_printf(bio_err, "-LMK Add local machine keyset attribute t
o private key\n"); | |
336 goto end; | |
337 } | |
338 | |
339 #ifndef OPENSSL_NO_ENGINE | |
340 e = setup_engine(bio_err, engine, 0); | |
341 #endif | |
342 | |
343 if(passarg) { | |
344 if(export_cert) passargout = passarg; | |
345 else passargin = passarg; | |
346 } | |
347 | |
348 if(!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { | |
349 BIO_printf(bio_err, "Error getting passwords\n"); | |
350 goto end; | |
351 } | |
352 | |
353 if(!cpass) { | |
354 if(export_cert) cpass = passout; | |
355 else cpass = passin; | |
356 } | |
357 | |
358 if(cpass) { | |
359 mpass = cpass; | |
360 noprompt = 1; | |
361 } else { | |
362 cpass = pass; | |
363 mpass = macpass; | |
364 } | |
365 | |
366 if(export_cert || inrand) { | |
367 app_RAND_load_file(NULL, bio_err, (inrand != NULL)); | |
368 if (inrand != NULL) | |
369 BIO_printf(bio_err,"%ld semi-random bytes loaded\n", | |
370 app_RAND_load_files(inrand)); | |
371 } | |
372 ERR_load_crypto_strings(); | |
373 | |
374 #ifdef CRYPTO_MDEBUG | |
375 CRYPTO_push_info("read files"); | |
376 #endif | |
377 | |
378 if (!infile) in = BIO_new_fp(stdin, BIO_NOCLOSE); | |
379 else in = BIO_new_file(infile, "rb"); | |
380 if (!in) { | |
381 BIO_printf(bio_err, "Error opening input file %s\n", | |
382 infile ? infile : "<stdin>"); | |
383 perror (infile); | |
384 goto end; | |
385 } | |
386 | |
387 #ifdef CRYPTO_MDEBUG | |
388 CRYPTO_pop_info(); | |
389 CRYPTO_push_info("write files"); | |
390 #endif | |
391 | |
392 if (!outfile) { | |
393 out = BIO_new_fp(stdout, BIO_NOCLOSE); | |
394 #ifdef OPENSSL_SYS_VMS | |
395 { | |
396 BIO *tmpbio = BIO_new(BIO_f_linebuffer()); | |
397 out = BIO_push(tmpbio, out); | |
398 } | |
399 #endif | |
400 } else out = BIO_new_file(outfile, "wb"); | |
401 if (!out) { | |
402 BIO_printf(bio_err, "Error opening output file %s\n", | |
403 outfile ? outfile : "<stdout>"); | |
404 perror (outfile); | |
405 goto end; | |
406 } | |
407 if (twopass) { | |
408 #ifdef CRYPTO_MDEBUG | |
409 CRYPTO_push_info("read MAC password"); | |
410 #endif | |
411 if(EVP_read_pw_string (macpass, sizeof macpass, "Enter MAC Password:", e
xport_cert)) | |
412 { | |
413 BIO_printf (bio_err, "Can't read Password\n"); | |
414 goto end; | |
415 } | |
416 #ifdef CRYPTO_MDEBUG | |
417 CRYPTO_pop_info(); | |
418 #endif | |
419 } | |
420 | |
421 if (export_cert) { | |
422 EVP_PKEY *key = NULL; | |
423 X509 *ucert = NULL, *x = NULL; | |
424 STACK_OF(X509) *certs=NULL; | |
425 const EVP_MD *macmd = NULL; | |
426 unsigned char *catmp = NULL; | |
427 int i; | |
428 | |
429 if ((options & (NOCERTS|NOKEYS)) == (NOCERTS|NOKEYS)) | |
430 { | |
431 BIO_printf(bio_err, "Nothing to do!\n"); | |
432 goto export_end; | |
433 } | |
434 | |
435 if (options & NOCERTS) | |
436 chain = 0; | |
437 | |
438 #ifdef CRYPTO_MDEBUG | |
439 CRYPTO_push_info("process -export_cert"); | |
440 CRYPTO_push_info("reading private key"); | |
441 #endif | |
442 if (!(options & NOKEYS)) | |
443 { | |
444 key = load_key(bio_err, keyname ? keyname : infile, | |
445 FORMAT_PEM, 1, passin, e, "private key"); | |
446 if (!key) | |
447 goto export_end; | |
448 } | |
449 | |
450 #ifdef CRYPTO_MDEBUG | |
451 CRYPTO_pop_info(); | |
452 CRYPTO_push_info("reading certs from input"); | |
453 #endif | |
454 | |
455 /* Load in all certs in input file */ | |
456 if(!(options & NOCERTS)) | |
457 { | |
458 certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e, | |
459 "certificates"); | |
460 if (!certs) | |
461 goto export_end; | |
462 | |
463 if (key) | |
464 { | |
465 /* Look for matching private key */ | |
466 for(i = 0; i < sk_X509_num(certs); i++) | |
467 { | |
468 x = sk_X509_value(certs, i); | |
469 if(X509_check_private_key(x, key)) | |
470 { | |
471 ucert = x; | |
472 /* Zero keyid and alias */ | |
473 X509_keyid_set1(ucert, NULL, 0); | |
474 X509_alias_set1(ucert, NULL, 0); | |
475 /* Remove from list */ | |
476 (void)sk_X509_delete(certs, i); | |
477 break; | |
478 } | |
479 } | |
480 if (!ucert) | |
481 { | |
482 BIO_printf(bio_err, "No certificate matches priv
ate key\n"); | |
483 goto export_end; | |
484 } | |
485 } | |
486 | |
487 } | |
488 | |
489 #ifdef CRYPTO_MDEBUG | |
490 CRYPTO_pop_info(); | |
491 CRYPTO_push_info("reading certs from input 2"); | |
492 #endif | |
493 | |
494 /* Add any more certificates asked for */ | |
495 if(certfile) | |
496 { | |
497 STACK_OF(X509) *morecerts=NULL; | |
498 if(!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM, | |
499 NULL, e, | |
500 "certificates from certfile"))) | |
501 goto export_end; | |
502 while(sk_X509_num(morecerts) > 0) | |
503 sk_X509_push(certs, sk_X509_shift(morecerts)); | |
504 sk_X509_free(morecerts); | |
505 } | |
506 | |
507 #ifdef CRYPTO_MDEBUG | |
508 CRYPTO_pop_info(); | |
509 CRYPTO_push_info("reading certs from certfile"); | |
510 #endif | |
511 | |
512 #ifdef CRYPTO_MDEBUG | |
513 CRYPTO_pop_info(); | |
514 CRYPTO_push_info("building chain"); | |
515 #endif | |
516 | |
517 /* If chaining get chain from user cert */ | |
518 if (chain) { | |
519 int vret; | |
520 STACK_OF(X509) *chain2; | |
521 X509_STORE *store = X509_STORE_new(); | |
522 if (!store) | |
523 { | |
524 BIO_printf (bio_err, "Memory allocation error\n"); | |
525 goto export_end; | |
526 } | |
527 if (!X509_STORE_load_locations(store, CAfile, CApath)) | |
528 X509_STORE_set_default_paths (store); | |
529 | |
530 vret = get_cert_chain (ucert, store, &chain2); | |
531 X509_STORE_free(store); | |
532 | |
533 if (!vret) { | |
534 /* Exclude verified certificate */ | |
535 for (i = 1; i < sk_X509_num (chain2) ; i++) | |
536 sk_X509_push(certs, sk_X509_value (chain2, i)); | |
537 /* Free first certificate */ | |
538 X509_free(sk_X509_value(chain2, 0)); | |
539 sk_X509_free(chain2); | |
540 } else { | |
541 if (vret >= 0) | |
542 BIO_printf (bio_err, "Error %s getting chain.\n"
, | |
543 X509_verify_cert_error_string(vret)); | |
544 else | |
545 ERR_print_errors(bio_err); | |
546 goto export_end; | |
547 } | |
548 } | |
549 | |
550 /* Add any CA names */ | |
551 | |
552 for (i = 0; i < sk_OPENSSL_STRING_num(canames); i++) | |
553 { | |
554 catmp = (unsigned char *)sk_OPENSSL_STRING_value(canames, i); | |
555 X509_alias_set1(sk_X509_value(certs, i), catmp, -1); | |
556 } | |
557 | |
558 if (csp_name && key) | |
559 EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name, | |
560 MBSTRING_ASC, (unsigned char *)csp_name, -1); | |
561 | |
562 if (add_lmk && key) | |
563 EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1); | |
564 | |
565 #ifdef CRYPTO_MDEBUG | |
566 CRYPTO_pop_info(); | |
567 CRYPTO_push_info("reading password"); | |
568 #endif | |
569 | |
570 if(!noprompt && | |
571 EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:",
1)) | |
572 { | |
573 BIO_printf (bio_err, "Can't read Password\n"); | |
574 goto export_end; | |
575 } | |
576 if (!twopass) BUF_strlcpy(macpass, pass, sizeof macpass); | |
577 | |
578 #ifdef CRYPTO_MDEBUG | |
579 CRYPTO_pop_info(); | |
580 CRYPTO_push_info("creating PKCS#12 structure"); | |
581 #endif | |
582 | |
583 p12 = PKCS12_create(cpass, name, key, ucert, certs, | |
584 key_pbe, cert_pbe, iter, -1, keytype); | |
585 | |
586 if (!p12) | |
587 { | |
588 ERR_print_errors (bio_err); | |
589 goto export_end; | |
590 } | |
591 | |
592 if (macalg) | |
593 { | |
594 macmd = EVP_get_digestbyname(macalg); | |
595 if (!macmd) | |
596 { | |
597 BIO_printf(bio_err, "Unknown digest algorithm %s\n", | |
598 macalg); | |
599 } | |
600 } | |
601 | |
602 if (maciter != -1) | |
603 PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd); | |
604 | |
605 #ifdef CRYPTO_MDEBUG | |
606 CRYPTO_pop_info(); | |
607 CRYPTO_push_info("writing pkcs12"); | |
608 #endif | |
609 | |
610 i2d_PKCS12_bio(out, p12); | |
611 | |
612 ret = 0; | |
613 | |
614 export_end: | |
615 #ifdef CRYPTO_MDEBUG | |
616 CRYPTO_pop_info(); | |
617 CRYPTO_pop_info(); | |
618 CRYPTO_push_info("process -export_cert: freeing"); | |
619 #endif | |
620 | |
621 if (key) EVP_PKEY_free(key); | |
622 if (certs) sk_X509_pop_free(certs, X509_free); | |
623 if (ucert) X509_free(ucert); | |
624 | |
625 #ifdef CRYPTO_MDEBUG | |
626 CRYPTO_pop_info(); | |
627 #endif | |
628 goto end; | |
629 | |
630 } | |
631 | |
632 if (!(p12 = d2i_PKCS12_bio (in, NULL))) { | |
633 ERR_print_errors(bio_err); | |
634 goto end; | |
635 } | |
636 | |
637 #ifdef CRYPTO_MDEBUG | |
638 CRYPTO_push_info("read import password"); | |
639 #endif | |
640 if(!noprompt && EVP_read_pw_string(pass, sizeof pass, "Enter Import Password
:", 0)) { | |
641 BIO_printf (bio_err, "Can't read Password\n"); | |
642 goto end; | |
643 } | |
644 #ifdef CRYPTO_MDEBUG | |
645 CRYPTO_pop_info(); | |
646 #endif | |
647 | |
648 if (!twopass) BUF_strlcpy(macpass, pass, sizeof macpass); | |
649 | |
650 if ((options & INFO) && p12->mac) BIO_printf (bio_err, "MAC Iteration %ld\n"
, p12->mac->iter ? ASN1_INTEGER_get (p12->mac->iter) : 1); | |
651 if(macver) { | |
652 #ifdef CRYPTO_MDEBUG | |
653 CRYPTO_push_info("verify MAC"); | |
654 #endif | |
655 /* If we enter empty password try no password first */ | |
656 if(!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) { | |
657 /* If mac and crypto pass the same set it to NULL too */ | |
658 if(!twopass) cpass = NULL; | |
659 } else if (!PKCS12_verify_mac(p12, mpass, -1)) { | |
660 BIO_printf (bio_err, "Mac verify error: invalid password?\n"); | |
661 ERR_print_errors (bio_err); | |
662 goto end; | |
663 } | |
664 BIO_printf (bio_err, "MAC verified OK\n"); | |
665 #ifdef CRYPTO_MDEBUG | |
666 CRYPTO_pop_info(); | |
667 #endif | |
668 } | |
669 | |
670 #ifdef CRYPTO_MDEBUG | |
671 CRYPTO_push_info("output keys and certificates"); | |
672 #endif | |
673 if (!dump_certs_keys_p12 (out, p12, cpass, -1, options, passout)) { | |
674 BIO_printf(bio_err, "Error outputting keys and certificates\n"); | |
675 ERR_print_errors (bio_err); | |
676 goto end; | |
677 } | |
678 #ifdef CRYPTO_MDEBUG | |
679 CRYPTO_pop_info(); | |
680 #endif | |
681 ret = 0; | |
682 end: | |
683 if (p12) PKCS12_free(p12); | |
684 if(export_cert || inrand) app_RAND_write_file(NULL, bio_err); | |
685 #ifdef CRYPTO_MDEBUG | |
686 CRYPTO_remove_all_info(); | |
687 #endif | |
688 BIO_free(in); | |
689 BIO_free_all(out); | |
690 if (canames) sk_OPENSSL_STRING_free(canames); | |
691 if(passin) OPENSSL_free(passin); | |
692 if(passout) OPENSSL_free(passout); | |
693 apps_shutdown(); | |
694 OPENSSL_EXIT(ret); | |
695 } | |
696 | |
697 int dump_certs_keys_p12 (BIO *out, PKCS12 *p12, char *pass, | |
698 int passlen, int options, char *pempass) | |
699 { | |
700 STACK_OF(PKCS7) *asafes = NULL; | |
701 STACK_OF(PKCS12_SAFEBAG) *bags; | |
702 int i, bagnid; | |
703 int ret = 0; | |
704 PKCS7 *p7; | |
705 | |
706 if (!( asafes = PKCS12_unpack_authsafes(p12))) return 0; | |
707 for (i = 0; i < sk_PKCS7_num (asafes); i++) { | |
708 p7 = sk_PKCS7_value (asafes, i); | |
709 bagnid = OBJ_obj2nid (p7->type); | |
710 if (bagnid == NID_pkcs7_data) { | |
711 bags = PKCS12_unpack_p7data(p7); | |
712 if (options & INFO) BIO_printf (bio_err, "PKCS7 Data\n")
; | |
713 } else if (bagnid == NID_pkcs7_encrypted) { | |
714 if (options & INFO) { | |
715 BIO_printf(bio_err, "PKCS7 Encrypted data: "); | |
716 alg_print(bio_err, | |
717 p7->d.encrypted->enc_data->algorithm); | |
718 } | |
719 bags = PKCS12_unpack_p7encdata(p7, pass, passlen); | |
720 } else continue; | |
721 if (!bags) goto err; | |
722 if (!dump_certs_pkeys_bags (out, bags, pass, passlen, | |
723 options, pempass)) { | |
724 sk_PKCS12_SAFEBAG_pop_free (bags, PKCS12_SAFEBAG_free); | |
725 goto err; | |
726 } | |
727 sk_PKCS12_SAFEBAG_pop_free (bags, PKCS12_SAFEBAG_free); | |
728 bags = NULL; | |
729 } | |
730 ret = 1; | |
731 | |
732 err: | |
733 | |
734 if (asafes) | |
735 sk_PKCS7_pop_free (asafes, PKCS7_free); | |
736 return ret; | |
737 } | |
738 | |
739 int dump_certs_pkeys_bags (BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags, | |
740 char *pass, int passlen, int options, char *pempass) | |
741 { | |
742 int i; | |
743 for (i = 0; i < sk_PKCS12_SAFEBAG_num (bags); i++) { | |
744 if (!dump_certs_pkeys_bag (out, | |
745 sk_PKCS12_SAFEBAG_value (bags, i), | |
746 pass, passlen, | |
747 options, pempass)) | |
748 return 0; | |
749 } | |
750 return 1; | |
751 } | |
752 | |
753 int dump_certs_pkeys_bag (BIO *out, PKCS12_SAFEBAG *bag, char *pass, | |
754 int passlen, int options, char *pempass) | |
755 { | |
756 EVP_PKEY *pkey; | |
757 PKCS8_PRIV_KEY_INFO *p8; | |
758 X509 *x509; | |
759 | |
760 switch (M_PKCS12_bag_type(bag)) | |
761 { | |
762 case NID_keyBag: | |
763 if (options & INFO) BIO_printf (bio_err, "Key bag\n"); | |
764 if (options & NOKEYS) return 1; | |
765 print_attribs (out, bag->attrib, "Bag Attributes"); | |
766 p8 = bag->value.keybag; | |
767 if (!(pkey = EVP_PKCS82PKEY (p8))) return 0; | |
768 print_attribs (out, p8->attributes, "Key Attributes"); | |
769 PEM_write_bio_PrivateKey (out, pkey, enc, NULL, 0, NULL, pempass
); | |
770 EVP_PKEY_free(pkey); | |
771 break; | |
772 | |
773 case NID_pkcs8ShroudedKeyBag: | |
774 if (options & INFO) { | |
775 BIO_printf (bio_err, "Shrouded Keybag: "); | |
776 alg_print (bio_err, bag->value.shkeybag->algor); | |
777 } | |
778 if (options & NOKEYS) return 1; | |
779 print_attribs (out, bag->attrib, "Bag Attributes"); | |
780 if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen))) | |
781 return 0; | |
782 if (!(pkey = EVP_PKCS82PKEY (p8))) { | |
783 PKCS8_PRIV_KEY_INFO_free(p8); | |
784 return 0; | |
785 } | |
786 print_attribs (out, p8->attributes, "Key Attributes"); | |
787 PKCS8_PRIV_KEY_INFO_free(p8); | |
788 PEM_write_bio_PrivateKey (out, pkey, enc, NULL, 0, NULL, pempass
); | |
789 EVP_PKEY_free(pkey); | |
790 break; | |
791 | |
792 case NID_certBag: | |
793 if (options & INFO) BIO_printf (bio_err, "Certificate bag\n"); | |
794 if (options & NOCERTS) return 1; | |
795 if (PKCS12_get_attr(bag, NID_localKeyID)) { | |
796 if (options & CACERTS) return 1; | |
797 } else if (options & CLCERTS) return 1; | |
798 print_attribs (out, bag->attrib, "Bag Attributes"); | |
799 if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate ) | |
800 return 1; | |
801 if (!(x509 = PKCS12_certbag2x509(bag))) return 0; | |
802 dump_cert_text (out, x509); | |
803 PEM_write_bio_X509 (out, x509); | |
804 X509_free(x509); | |
805 break; | |
806 | |
807 case NID_safeContentsBag: | |
808 if (options & INFO) BIO_printf (bio_err, "Safe Contents bag\n"); | |
809 print_attribs (out, bag->attrib, "Bag Attributes"); | |
810 return dump_certs_pkeys_bags (out, bag->value.safes, pass, | |
811 passlen, options, pe
mpass); | |
812 | |
813 default: | |
814 BIO_printf (bio_err, "Warning unsupported bag type: "); | |
815 i2a_ASN1_OBJECT (bio_err, bag->type); | |
816 BIO_printf (bio_err, "\n"); | |
817 return 1; | |
818 break; | |
819 } | |
820 return 1; | |
821 } | |
822 | |
823 /* Given a single certificate return a verified chain or NULL if error */ | |
824 | |
825 /* Hope this is OK .... */ | |
826 | |
827 int get_cert_chain (X509 *cert, X509_STORE *store, STACK_OF(X509) **chain) | |
828 { | |
829 X509_STORE_CTX store_ctx; | |
830 STACK_OF(X509) *chn; | |
831 int i = 0; | |
832 | |
833 /* FIXME: Should really check the return status of X509_STORE_CTX_init | |
834 * for an error, but how that fits into the return value of this | |
835 * function is less obvious. */ | |
836 X509_STORE_CTX_init(&store_ctx, store, cert, NULL); | |
837 if (X509_verify_cert(&store_ctx) <= 0) { | |
838 i = X509_STORE_CTX_get_error (&store_ctx); | |
839 if (i == 0) | |
840 /* avoid returning 0 if X509_verify_cert() did not | |
841 * set an appropriate error value in the context */ | |
842 i = -1; | |
843 chn = NULL; | |
844 goto err; | |
845 } else | |
846 chn = X509_STORE_CTX_get1_chain(&store_ctx); | |
847 err: | |
848 X509_STORE_CTX_cleanup(&store_ctx); | |
849 *chain = chn; | |
850 | |
851 return i; | |
852 } | |
853 | |
854 int alg_print (BIO *x, X509_ALGOR *alg) | |
855 { | |
856 PBEPARAM *pbe; | |
857 const unsigned char *p; | |
858 p = alg->parameter->value.sequence->data; | |
859 pbe = d2i_PBEPARAM(NULL, &p, alg->parameter->value.sequence->length); | |
860 if (!pbe) | |
861 return 1; | |
862 BIO_printf (bio_err, "%s, Iteration %ld\n", | |
863 OBJ_nid2ln(OBJ_obj2nid(alg->algorithm)), | |
864 ASN1_INTEGER_get(pbe->iter)); | |
865 PBEPARAM_free (pbe); | |
866 return 1; | |
867 } | |
868 | |
869 /* Load all certificates from a given file */ | |
870 | |
871 int cert_load(BIO *in, STACK_OF(X509) *sk) | |
872 { | |
873 int ret; | |
874 X509 *cert; | |
875 ret = 0; | |
876 #ifdef CRYPTO_MDEBUG | |
877 CRYPTO_push_info("cert_load(): reading one cert"); | |
878 #endif | |
879 while((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) { | |
880 #ifdef CRYPTO_MDEBUG | |
881 CRYPTO_pop_info(); | |
882 #endif | |
883 ret = 1; | |
884 sk_X509_push(sk, cert); | |
885 #ifdef CRYPTO_MDEBUG | |
886 CRYPTO_push_info("cert_load(): reading one cert"); | |
887 #endif | |
888 } | |
889 #ifdef CRYPTO_MDEBUG | |
890 CRYPTO_pop_info(); | |
891 #endif | |
892 if(ret) ERR_clear_error(); | |
893 return ret; | |
894 } | |
895 | |
896 /* Generalised attribute print: handle PKCS#8 and bag attributes */ | |
897 | |
898 int print_attribs (BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst,const char *name) | |
899 { | |
900 X509_ATTRIBUTE *attr; | |
901 ASN1_TYPE *av; | |
902 char *value; | |
903 int i, attr_nid; | |
904 if(!attrlst) { | |
905 BIO_printf(out, "%s: <No Attributes>\n", name); | |
906 return 1; | |
907 } | |
908 if(!sk_X509_ATTRIBUTE_num(attrlst)) { | |
909 BIO_printf(out, "%s: <Empty Attributes>\n", name); | |
910 return 1; | |
911 } | |
912 BIO_printf(out, "%s\n", name); | |
913 for(i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) { | |
914 attr = sk_X509_ATTRIBUTE_value(attrlst, i); | |
915 attr_nid = OBJ_obj2nid(attr->object); | |
916 BIO_printf(out, " "); | |
917 if(attr_nid == NID_undef) { | |
918 i2a_ASN1_OBJECT (out, attr->object); | |
919 BIO_printf(out, ": "); | |
920 } else BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid)); | |
921 | |
922 if(sk_ASN1_TYPE_num(attr->value.set)) { | |
923 av = sk_ASN1_TYPE_value(attr->value.set, 0); | |
924 switch(av->type) { | |
925 case V_ASN1_BMPSTRING: | |
926 value = OPENSSL_uni2asc(av->value.bmpstring->dat
a, | |
927 av->value.bmpstring->length); | |
928 BIO_printf(out, "%s\n", value); | |
929 OPENSSL_free(value); | |
930 break; | |
931 | |
932 case V_ASN1_OCTET_STRING: | |
933 hex_prin(out, av->value.octet_string->data, | |
934 av->value.octet_string->length); | |
935 BIO_printf(out, "\n"); | |
936 break; | |
937 | |
938 case V_ASN1_BIT_STRING: | |
939 hex_prin(out, av->value.bit_string->data, | |
940 av->value.bit_string->length); | |
941 BIO_printf(out, "\n"); | |
942 break; | |
943 | |
944 default: | |
945 BIO_printf(out, "<Unsupported tag %d>\n"
, av->type); | |
946 break; | |
947 } | |
948 } else BIO_printf(out, "<No Values>\n"); | |
949 } | |
950 return 1; | |
951 } | |
952 | |
953 void hex_prin(BIO *out, unsigned char *buf, int len) | |
954 { | |
955 int i; | |
956 for (i = 0; i < len; i++) BIO_printf (out, "%02X ", buf[i]); | |
957 } | |
958 | |
959 static int set_pbe(BIO *err, int *ppbe, const char *str) | |
960 { | |
961 if (!str) | |
962 return 0; | |
963 if (!strcmp(str, "NONE")) | |
964 { | |
965 *ppbe = -1; | |
966 return 1; | |
967 } | |
968 *ppbe=OBJ_txt2nid(str); | |
969 if (*ppbe == NID_undef) | |
970 { | |
971 BIO_printf(bio_err, "Unknown PBE algorithm %s\n", str); | |
972 return 0; | |
973 } | |
974 return 1; | |
975 } | |
976 | |
977 #endif | |
OLD | NEW |