summaryrefslogtreecommitdiff
path: root/src/usr.bin/openssl/pkcs12.c
diff options
context:
space:
mode:
authorjsing <>2014-08-26 17:47:25 +0000
committerjsing <>2014-08-26 17:47:25 +0000
commitf3755acd5513f85ff734de6a822b6f804d3776ce (patch)
tree1f859a78eae941040f58599de8c0e1e56d61fdad /src/usr.bin/openssl/pkcs12.c
parent0779b9f30aa9875c290af18a4362799668829707 (diff)
downloadopenbsd-f3755acd5513f85ff734de6a822b6f804d3776ce.tar.gz
openbsd-f3755acd5513f85ff734de6a822b6f804d3776ce.tar.bz2
openbsd-f3755acd5513f85ff734de6a822b6f804d3776ce.zip
Move openssl(1) from /usr/sbin/openssl to /usr/bin/openssl, since it is not
a system/superuser binary. At the same time, move the source code from its current lib/libssl/src/apps location to a more appropriate home under usr.bin/openssl. ok deraadt@ miod@
Diffstat (limited to 'src/usr.bin/openssl/pkcs12.c')
-rw-r--r--src/usr.bin/openssl/pkcs12.c913
1 files changed, 913 insertions, 0 deletions
diff --git a/src/usr.bin/openssl/pkcs12.c b/src/usr.bin/openssl/pkcs12.c
new file mode 100644
index 0000000000..77b7c31d01
--- /dev/null
+++ b/src/usr.bin/openssl/pkcs12.c
@@ -0,0 +1,913 @@
1/* $OpenBSD: pkcs12.c,v 1.1 2014/08/26 17:47:25 jsing Exp $ */
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
61#if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_SHA1)
62
63#include <stdio.h>
64#include <stdlib.h>
65#include <string.h>
66
67#include "apps.h"
68
69#include <openssl/crypto.h>
70#include <openssl/err.h>
71#include <openssl/pem.h>
72#include <openssl/pkcs12.h>
73
74const EVP_CIPHER *enc;
75
76#define NOKEYS 0x1
77#define NOCERTS 0x2
78#define INFO 0x4
79#define CLCERTS 0x8
80#define CACERTS 0x10
81
82int get_cert_chain(X509 * cert, X509_STORE * store, STACK_OF(X509) ** chain);
83int dump_certs_keys_p12(BIO * out, PKCS12 * p12, char *pass, int passlen,
84 int options, char *pempass);
85int dump_certs_pkeys_bags(BIO * out, STACK_OF(PKCS12_SAFEBAG) * bags, char *pass,
86 int passlen, int options, char *pempass);
87int dump_certs_pkeys_bag(BIO * out, PKCS12_SAFEBAG * bags, char *pass, int passlen,
88 int options, char *pempass);
89int print_attribs(BIO * out, STACK_OF(X509_ATTRIBUTE) * attrlst, const char *name);
90void hex_prin(BIO * out, unsigned char *buf, int len);
91int alg_print(BIO * x, X509_ALGOR * alg);
92int cert_load(BIO * in, STACK_OF(X509) * sk);
93static int set_pbe(BIO * err, int *ppbe, const char *str);
94
95int pkcs12_main(int, char **);
96
97int
98pkcs12_main(int argc, char **argv)
99{
100 ENGINE *e = NULL;
101 char *infile = NULL, *outfile = NULL, *keyname = NULL;
102 char *certfile = NULL;
103 BIO *in = NULL, *out = NULL;
104 char **args;
105 char *name = NULL;
106 char *csp_name = NULL;
107 int add_lmk = 0;
108 PKCS12 *p12 = NULL;
109 char pass[50], macpass[50];
110 int export_cert = 0;
111 int options = 0;
112 int chain = 0;
113 int badarg = 0;
114 int iter = PKCS12_DEFAULT_ITER;
115 int maciter = PKCS12_DEFAULT_ITER;
116 int twopass = 0;
117 int keytype = 0;
118 int cert_pbe;
119 int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
120 int ret = 1;
121 int macver = 1;
122 int noprompt = 0;
123 STACK_OF(OPENSSL_STRING) * canames = NULL;
124 char *cpass = NULL, *mpass = NULL;
125 char *passargin = NULL, *passargout = NULL, *passarg = NULL;
126 char *passin = NULL, *passout = NULL;
127 char *macalg = NULL;
128 char *CApath = NULL, *CAfile = NULL;
129#ifndef OPENSSL_NO_ENGINE
130 char *engine = NULL;
131#endif
132
133 cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
134
135 enc = EVP_des_ede3_cbc();
136
137 args = argv + 1;
138
139 while (*args) {
140 if (*args[0] == '-') {
141 if (!strcmp(*args, "-nokeys"))
142 options |= NOKEYS;
143 else if (!strcmp(*args, "-keyex"))
144 keytype = KEY_EX;
145 else if (!strcmp(*args, "-keysig"))
146 keytype = KEY_SIG;
147 else if (!strcmp(*args, "-nocerts"))
148 options |= NOCERTS;
149 else if (!strcmp(*args, "-clcerts"))
150 options |= CLCERTS;
151 else if (!strcmp(*args, "-cacerts"))
152 options |= CACERTS;
153 else if (!strcmp(*args, "-noout"))
154 options |= (NOKEYS | NOCERTS);
155 else if (!strcmp(*args, "-info"))
156 options |= INFO;
157 else if (!strcmp(*args, "-chain"))
158 chain = 1;
159 else if (!strcmp(*args, "-twopass"))
160 twopass = 1;
161 else if (!strcmp(*args, "-nomacver"))
162 macver = 0;
163 else if (!strcmp(*args, "-descert"))
164 cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
165 else if (!strcmp(*args, "-export"))
166 export_cert = 1;
167 else if (!strcmp(*args, "-des"))
168 enc = EVP_des_cbc();
169 else if (!strcmp(*args, "-des3"))
170 enc = EVP_des_ede3_cbc();
171#ifndef OPENSSL_NO_IDEA
172 else if (!strcmp(*args, "-idea"))
173 enc = EVP_idea_cbc();
174#endif
175#ifndef OPENSSL_NO_AES
176 else if (!strcmp(*args, "-aes128"))
177 enc = EVP_aes_128_cbc();
178 else if (!strcmp(*args, "-aes192"))
179 enc = EVP_aes_192_cbc();
180 else if (!strcmp(*args, "-aes256"))
181 enc = EVP_aes_256_cbc();
182#endif
183#ifndef OPENSSL_NO_CAMELLIA
184 else if (!strcmp(*args, "-camellia128"))
185 enc = EVP_camellia_128_cbc();
186 else if (!strcmp(*args, "-camellia192"))
187 enc = EVP_camellia_192_cbc();
188 else if (!strcmp(*args, "-camellia256"))
189 enc = EVP_camellia_256_cbc();
190#endif
191 else if (!strcmp(*args, "-noiter"))
192 iter = 1;
193 else if (!strcmp(*args, "-maciter"))
194 maciter = PKCS12_DEFAULT_ITER;
195 else if (!strcmp(*args, "-nomaciter"))
196 maciter = 1;
197 else if (!strcmp(*args, "-nomac"))
198 maciter = -1;
199 else if (!strcmp(*args, "-macalg"))
200 if (args[1]) {
201 args++;
202 macalg = *args;
203 } else
204 badarg = 1;
205 else if (!strcmp(*args, "-nodes"))
206 enc = NULL;
207 else if (!strcmp(*args, "-certpbe")) {
208 if (!set_pbe(bio_err, &cert_pbe, *++args))
209 badarg = 1;
210 } else if (!strcmp(*args, "-keypbe")) {
211 if (!set_pbe(bio_err, &key_pbe, *++args))
212 badarg = 1;
213 } else if (!strcmp(*args, "-inkey")) {
214 if (args[1]) {
215 args++;
216 keyname = *args;
217 } else
218 badarg = 1;
219 } else if (!strcmp(*args, "-certfile")) {
220 if (args[1]) {
221 args++;
222 certfile = *args;
223 } else
224 badarg = 1;
225 } else if (!strcmp(*args, "-name")) {
226 if (args[1]) {
227 args++;
228 name = *args;
229 } else
230 badarg = 1;
231 } else if (!strcmp(*args, "-LMK"))
232 add_lmk = 1;
233 else if (!strcmp(*args, "-CSP")) {
234 if (args[1]) {
235 args++;
236 csp_name = *args;
237 } else
238 badarg = 1;
239 } else if (!strcmp(*args, "-caname")) {
240 if (args[1]) {
241 args++;
242 if (!canames)
243 canames = sk_OPENSSL_STRING_new_null();
244 sk_OPENSSL_STRING_push(canames, *args);
245 } else
246 badarg = 1;
247 } else if (!strcmp(*args, "-in")) {
248 if (args[1]) {
249 args++;
250 infile = *args;
251 } else
252 badarg = 1;
253 } else if (!strcmp(*args, "-out")) {
254 if (args[1]) {
255 args++;
256 outfile = *args;
257 } else
258 badarg = 1;
259 } else if (!strcmp(*args, "-passin")) {
260 if (args[1]) {
261 args++;
262 passargin = *args;
263 } else
264 badarg = 1;
265 } else if (!strcmp(*args, "-passout")) {
266 if (args[1]) {
267 args++;
268 passargout = *args;
269 } else
270 badarg = 1;
271 } else if (!strcmp(*args, "-password")) {
272 if (args[1]) {
273 args++;
274 passarg = *args;
275 noprompt = 1;
276 } else
277 badarg = 1;
278 } else if (!strcmp(*args, "-CApath")) {
279 if (args[1]) {
280 args++;
281 CApath = *args;
282 } else
283 badarg = 1;
284 } else if (!strcmp(*args, "-CAfile")) {
285 if (args[1]) {
286 args++;
287 CAfile = *args;
288 } else
289 badarg = 1;
290#ifndef OPENSSL_NO_ENGINE
291 } else if (!strcmp(*args, "-engine")) {
292 if (args[1]) {
293 args++;
294 engine = *args;
295 } else
296 badarg = 1;
297#endif
298 } else
299 badarg = 1;
300
301 } else
302 badarg = 1;
303 args++;
304 }
305
306 if (badarg) {
307 BIO_printf(bio_err, "Usage: pkcs12 [options]\n");
308 BIO_printf(bio_err, "where options are\n");
309 BIO_printf(bio_err, "-export output PKCS12 file\n");
310 BIO_printf(bio_err, "-chain add certificate chain\n");
311 BIO_printf(bio_err, "-inkey file private key if not infile\n");
312 BIO_printf(bio_err, "-certfile f add all certs in f\n");
313 BIO_printf(bio_err, "-CApath arg - PEM format directory of CA's\n");
314 BIO_printf(bio_err, "-CAfile arg - PEM format file of CA's\n");
315 BIO_printf(bio_err, "-name \"name\" use name as friendly name\n");
316 BIO_printf(bio_err, "-caname \"nm\" use nm as CA friendly name (can be used more than once).\n");
317 BIO_printf(bio_err, "-in infile input filename\n");
318 BIO_printf(bio_err, "-out outfile output filename\n");
319 BIO_printf(bio_err, "-noout don't output anything, just verify.\n");
320 BIO_printf(bio_err, "-nomacver don't verify MAC.\n");
321 BIO_printf(bio_err, "-nocerts don't output certificates.\n");
322 BIO_printf(bio_err, "-clcerts only output client certificates.\n");
323 BIO_printf(bio_err, "-cacerts only output CA certificates.\n");
324 BIO_printf(bio_err, "-nokeys don't output private keys.\n");
325 BIO_printf(bio_err, "-info give info about PKCS#12 structure.\n");
326 BIO_printf(bio_err, "-des encrypt private keys with DES\n");
327 BIO_printf(bio_err, "-des3 encrypt private keys with triple DES (default)\n");
328#ifndef OPENSSL_NO_IDEA
329 BIO_printf(bio_err, "-idea encrypt private keys with idea\n");
330#endif
331#ifndef OPENSSL_NO_AES
332 BIO_printf(bio_err, "-aes128, -aes192, -aes256\n");
333 BIO_printf(bio_err, " encrypt PEM output with cbc aes\n");
334#endif
335#ifndef OPENSSL_NO_CAMELLIA
336 BIO_printf(bio_err, "-camellia128, -camellia192, -camellia256\n");
337 BIO_printf(bio_err, " encrypt PEM output with cbc camellia\n");
338#endif
339 BIO_printf(bio_err, "-nodes don't encrypt private keys\n");
340 BIO_printf(bio_err, "-noiter don't use encryption iteration\n");
341 BIO_printf(bio_err, "-nomaciter don't use MAC iteration\n");
342 BIO_printf(bio_err, "-maciter use MAC iteration\n");
343 BIO_printf(bio_err, "-nomac don't generate MAC\n");
344 BIO_printf(bio_err, "-twopass separate MAC, encryption passwords\n");
345 BIO_printf(bio_err, "-descert encrypt PKCS#12 certificates with triple DES (default RC2-40)\n");
346 BIO_printf(bio_err, "-certpbe alg specify certificate PBE algorithm (default RC2-40)\n");
347 BIO_printf(bio_err, "-keypbe alg specify private key PBE algorithm (default 3DES)\n");
348 BIO_printf(bio_err, "-macalg alg digest algorithm used in MAC (default SHA1)\n");
349 BIO_printf(bio_err, "-keyex set MS key exchange type\n");
350 BIO_printf(bio_err, "-keysig set MS key signature type\n");
351 BIO_printf(bio_err, "-password p set import/export password source\n");
352 BIO_printf(bio_err, "-passin p input file pass phrase source\n");
353 BIO_printf(bio_err, "-passout p output file pass phrase source\n");
354#ifndef OPENSSL_NO_ENGINE
355 BIO_printf(bio_err, "-engine e use engine e, possibly a hardware device.\n");
356#endif
357 BIO_printf(bio_err, "-CSP name Microsoft CSP name\n");
358 BIO_printf(bio_err, "-LMK Add local machine keyset attribute to private key\n");
359 goto end;
360 }
361#ifndef OPENSSL_NO_ENGINE
362 e = setup_engine(bio_err, engine, 0);
363#endif
364
365 if (passarg) {
366 if (export_cert)
367 passargout = passarg;
368 else
369 passargin = passarg;
370 }
371 if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
372 BIO_printf(bio_err, "Error getting passwords\n");
373 goto end;
374 }
375 if (!cpass) {
376 if (export_cert)
377 cpass = passout;
378 else
379 cpass = passin;
380 }
381 if (cpass) {
382 mpass = cpass;
383 noprompt = 1;
384 } else {
385 cpass = pass;
386 mpass = macpass;
387 }
388
389 ERR_load_crypto_strings();
390
391
392 if (!infile)
393 in = BIO_new_fp(stdin, BIO_NOCLOSE);
394 else
395 in = BIO_new_file(infile, "rb");
396 if (!in) {
397 BIO_printf(bio_err, "Error opening input file %s\n",
398 infile ? infile : "<stdin>");
399 perror(infile);
400 goto end;
401 }
402
403 if (!outfile) {
404 out = BIO_new_fp(stdout, BIO_NOCLOSE);
405 } else
406 out = BIO_new_file(outfile, "wb");
407 if (!out) {
408 BIO_printf(bio_err, "Error opening output file %s\n",
409 outfile ? outfile : "<stdout>");
410 perror(outfile);
411 goto end;
412 }
413 if (twopass) {
414 if (EVP_read_pw_string(macpass, sizeof macpass, "Enter MAC Password:", export_cert)) {
415 BIO_printf(bio_err, "Can't read Password\n");
416 goto end;
417 }
418 }
419 if (export_cert) {
420 EVP_PKEY *key = NULL;
421 X509 *ucert = NULL, *x = NULL;
422 STACK_OF(X509) * certs = NULL;
423 const EVP_MD *macmd = NULL;
424 unsigned char *catmp = NULL;
425 int i;
426
427 if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) {
428 BIO_printf(bio_err, "Nothing to do!\n");
429 goto export_end;
430 }
431 if (options & NOCERTS)
432 chain = 0;
433
434 if (!(options & NOKEYS)) {
435 key = load_key(bio_err, keyname ? keyname : infile,
436 FORMAT_PEM, 1, passin, e, "private key");
437 if (!key)
438 goto export_end;
439 }
440
441 /* Load in all certs in input file */
442 if (!(options & NOCERTS)) {
443 certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e,
444 "certificates");
445 if (!certs)
446 goto export_end;
447
448 if (key) {
449 /* Look for matching private key */
450 for (i = 0; i < sk_X509_num(certs); i++) {
451 x = sk_X509_value(certs, i);
452 if (X509_check_private_key(x, key)) {
453 ucert = x;
454 /* Zero keyid and alias */
455 X509_keyid_set1(ucert, NULL, 0);
456 X509_alias_set1(ucert, NULL, 0);
457 /* Remove from list */
458 (void) sk_X509_delete(certs, i);
459 break;
460 }
461 }
462 if (!ucert) {
463 BIO_printf(bio_err, "No certificate matches private key\n");
464 goto export_end;
465 }
466 }
467 }
468
469 /* Add any more certificates asked for */
470 if (certfile) {
471 STACK_OF(X509) * morecerts = NULL;
472 if (!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM,
473 NULL, e,
474 "certificates from certfile")))
475 goto export_end;
476 while (sk_X509_num(morecerts) > 0)
477 sk_X509_push(certs, sk_X509_shift(morecerts));
478 sk_X509_free(morecerts);
479 }
480
481
482 /* If chaining get chain from user cert */
483 if (chain) {
484 int vret;
485 STACK_OF(X509) * chain2;
486 X509_STORE *store = X509_STORE_new();
487 if (!store) {
488 BIO_printf(bio_err, "Memory allocation error\n");
489 goto export_end;
490 }
491 if (!X509_STORE_load_locations(store, CAfile, CApath))
492 X509_STORE_set_default_paths(store);
493
494 vret = get_cert_chain(ucert, store, &chain2);
495 X509_STORE_free(store);
496
497 if (!vret) {
498 /* Exclude verified certificate */
499 for (i = 1; i < sk_X509_num(chain2); i++)
500 sk_X509_push(certs, sk_X509_value(chain2, i));
501 /* Free first certificate */
502 X509_free(sk_X509_value(chain2, 0));
503 sk_X509_free(chain2);
504 } else {
505 if (vret >= 0)
506 BIO_printf(bio_err, "Error %s getting chain.\n",
507 X509_verify_cert_error_string(vret));
508 else
509 ERR_print_errors(bio_err);
510 goto export_end;
511 }
512 }
513 /* Add any CA names */
514
515 for (i = 0; i < sk_OPENSSL_STRING_num(canames); i++) {
516 catmp = (unsigned char *) sk_OPENSSL_STRING_value(canames, i);
517 X509_alias_set1(sk_X509_value(certs, i), catmp, -1);
518 }
519
520 if (csp_name && key)
521 EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name,
522 MBSTRING_ASC, (unsigned char *) csp_name, -1);
523
524 if (add_lmk && key)
525 EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1);
526
527
528 if (!noprompt &&
529 EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:", 1)) {
530 BIO_printf(bio_err, "Can't read Password\n");
531 goto export_end;
532 }
533 if (!twopass)
534 strlcpy(macpass, pass, sizeof macpass);
535
536
537 p12 = PKCS12_create(cpass, name, key, ucert, certs,
538 key_pbe, cert_pbe, iter, -1, keytype);
539
540 if (!p12) {
541 ERR_print_errors(bio_err);
542 goto export_end;
543 }
544 if (macalg) {
545 macmd = EVP_get_digestbyname(macalg);
546 if (!macmd) {
547 BIO_printf(bio_err, "Unknown digest algorithm %s\n",
548 macalg);
549 }
550 }
551 if (maciter != -1)
552 PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd);
553
554
555 i2d_PKCS12_bio(out, p12);
556
557 ret = 0;
558
559export_end:
560
561 if (key)
562 EVP_PKEY_free(key);
563 if (certs)
564 sk_X509_pop_free(certs, X509_free);
565 if (ucert)
566 X509_free(ucert);
567
568 goto end;
569
570 }
571 if (!(p12 = d2i_PKCS12_bio(in, NULL))) {
572 ERR_print_errors(bio_err);
573 goto end;
574 }
575 if (!noprompt && EVP_read_pw_string(pass, sizeof pass, "Enter Import Password:", 0)) {
576 BIO_printf(bio_err, "Can't read Password\n");
577 goto end;
578 }
579
580 if (!twopass)
581 strlcpy(macpass, pass, sizeof macpass);
582
583 if ((options & INFO) && p12->mac)
584 BIO_printf(bio_err, "MAC Iteration %ld\n", p12->mac->iter ? ASN1_INTEGER_get(p12->mac->iter) : 1);
585 if (macver) {
586 /* If we enter empty password try no password first */
587 if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) {
588 /* If mac and crypto pass the same set it to NULL too */
589 if (!twopass)
590 cpass = NULL;
591 } else if (!PKCS12_verify_mac(p12, mpass, -1)) {
592 BIO_printf(bio_err, "Mac verify error: invalid password?\n");
593 ERR_print_errors(bio_err);
594 goto end;
595 }
596 BIO_printf(bio_err, "MAC verified OK\n");
597 }
598 if (!dump_certs_keys_p12(out, p12, cpass, -1, options, passout)) {
599 BIO_printf(bio_err, "Error outputting keys and certificates\n");
600 ERR_print_errors(bio_err);
601 goto end;
602 }
603 ret = 0;
604end:
605 if (p12)
606 PKCS12_free(p12);
607 BIO_free(in);
608 BIO_free_all(out);
609 if (canames)
610 sk_OPENSSL_STRING_free(canames);
611 free(passin);
612 free(passout);
613
614 return (ret);
615}
616
617int
618dump_certs_keys_p12(BIO * out, PKCS12 * p12, char *pass,
619 int passlen, int options, char *pempass)
620{
621 STACK_OF(PKCS7) * asafes = NULL;
622 STACK_OF(PKCS12_SAFEBAG) * bags;
623 int i, bagnid;
624 int ret = 0;
625 PKCS7 *p7;
626
627 if (!(asafes = PKCS12_unpack_authsafes(p12)))
628 return 0;
629 for (i = 0; i < sk_PKCS7_num(asafes); i++) {
630 p7 = sk_PKCS7_value(asafes, i);
631 bagnid = OBJ_obj2nid(p7->type);
632 if (bagnid == NID_pkcs7_data) {
633 bags = PKCS12_unpack_p7data(p7);
634 if (options & INFO)
635 BIO_printf(bio_err, "PKCS7 Data\n");
636 } else if (bagnid == NID_pkcs7_encrypted) {
637 if (options & INFO) {
638 BIO_printf(bio_err, "PKCS7 Encrypted data: ");
639 alg_print(bio_err,
640 p7->d.encrypted->enc_data->algorithm);
641 }
642 bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
643 } else
644 continue;
645 if (!bags)
646 goto err;
647 if (!dump_certs_pkeys_bags(out, bags, pass, passlen,
648 options, pempass)) {
649 sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
650 goto err;
651 }
652 sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
653 bags = NULL;
654 }
655 ret = 1;
656
657err:
658
659 if (asafes)
660 sk_PKCS7_pop_free(asafes, PKCS7_free);
661 return ret;
662}
663
664int
665dump_certs_pkeys_bags(BIO * out, STACK_OF(PKCS12_SAFEBAG) * bags,
666 char *pass, int passlen, int options, char *pempass)
667{
668 int i;
669 for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
670 if (!dump_certs_pkeys_bag(out,
671 sk_PKCS12_SAFEBAG_value(bags, i),
672 pass, passlen,
673 options, pempass))
674 return 0;
675 }
676 return 1;
677}
678
679int
680dump_certs_pkeys_bag(BIO * out, PKCS12_SAFEBAG * bag, char *pass,
681 int passlen, int options, char *pempass)
682{
683 EVP_PKEY *pkey;
684 PKCS8_PRIV_KEY_INFO *p8;
685 X509 *x509;
686
687 switch (M_PKCS12_bag_type(bag)) {
688 case NID_keyBag:
689 if (options & INFO)
690 BIO_printf(bio_err, "Key bag\n");
691 if (options & NOKEYS)
692 return 1;
693 print_attribs(out, bag->attrib, "Bag Attributes");
694 p8 = bag->value.keybag;
695 if (!(pkey = EVP_PKCS82PKEY(p8)))
696 return 0;
697 print_attribs(out, p8->attributes, "Key Attributes");
698 PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass);
699 EVP_PKEY_free(pkey);
700 break;
701
702 case NID_pkcs8ShroudedKeyBag:
703 if (options & INFO) {
704 BIO_printf(bio_err, "Shrouded Keybag: ");
705 alg_print(bio_err, bag->value.shkeybag->algor);
706 }
707 if (options & NOKEYS)
708 return 1;
709 print_attribs(out, bag->attrib, "Bag Attributes");
710 if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen)))
711 return 0;
712 if (!(pkey = EVP_PKCS82PKEY(p8))) {
713 PKCS8_PRIV_KEY_INFO_free(p8);
714 return 0;
715 }
716 print_attribs(out, p8->attributes, "Key Attributes");
717 PKCS8_PRIV_KEY_INFO_free(p8);
718 PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass);
719 EVP_PKEY_free(pkey);
720 break;
721
722 case NID_certBag:
723 if (options & INFO)
724 BIO_printf(bio_err, "Certificate bag\n");
725 if (options & NOCERTS)
726 return 1;
727 if (PKCS12_get_attr(bag, NID_localKeyID)) {
728 if (options & CACERTS)
729 return 1;
730 } else if (options & CLCERTS)
731 return 1;
732 print_attribs(out, bag->attrib, "Bag Attributes");
733 if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate)
734 return 1;
735 if (!(x509 = PKCS12_certbag2x509(bag)))
736 return 0;
737 dump_cert_text(out, x509);
738 PEM_write_bio_X509(out, x509);
739 X509_free(x509);
740 break;
741
742 case NID_safeContentsBag:
743 if (options & INFO)
744 BIO_printf(bio_err, "Safe Contents bag\n");
745 print_attribs(out, bag->attrib, "Bag Attributes");
746 return dump_certs_pkeys_bags(out, bag->value.safes, pass,
747 passlen, options, pempass);
748
749 default:
750 BIO_printf(bio_err, "Warning unsupported bag type: ");
751 i2a_ASN1_OBJECT(bio_err, bag->type);
752 BIO_printf(bio_err, "\n");
753 return 1;
754 break;
755 }
756 return 1;
757}
758
759/* Given a single certificate return a verified chain or NULL if error */
760
761/* Hope this is OK .... */
762
763int
764get_cert_chain(X509 * cert, X509_STORE * store, STACK_OF(X509) ** chain)
765{
766 X509_STORE_CTX store_ctx;
767 STACK_OF(X509) * chn;
768 int i = 0;
769
770 /*
771 * FIXME: Should really check the return status of
772 * X509_STORE_CTX_init for an error, but how that fits into the
773 * return value of this function is less obvious.
774 */
775 X509_STORE_CTX_init(&store_ctx, store, cert, NULL);
776 if (X509_verify_cert(&store_ctx) <= 0) {
777 i = X509_STORE_CTX_get_error(&store_ctx);
778 if (i == 0)
779 /*
780 * avoid returning 0 if X509_verify_cert() did not
781 * set an appropriate error value in the context
782 */
783 i = -1;
784 chn = NULL;
785 goto err;
786 } else
787 chn = X509_STORE_CTX_get1_chain(&store_ctx);
788err:
789 X509_STORE_CTX_cleanup(&store_ctx);
790 *chain = chn;
791
792 return i;
793}
794
795int
796alg_print(BIO * x, X509_ALGOR * alg)
797{
798 PBEPARAM *pbe;
799 const unsigned char *p;
800 p = alg->parameter->value.sequence->data;
801 pbe = d2i_PBEPARAM(NULL, &p, alg->parameter->value.sequence->length);
802 if (!pbe)
803 return 1;
804 BIO_printf(bio_err, "%s, Iteration %ld\n",
805 OBJ_nid2ln(OBJ_obj2nid(alg->algorithm)),
806 ASN1_INTEGER_get(pbe->iter));
807 PBEPARAM_free(pbe);
808 return 1;
809}
810
811/* Load all certificates from a given file */
812
813int
814cert_load(BIO * in, STACK_OF(X509) * sk)
815{
816 int ret;
817 X509 *cert;
818 ret = 0;
819 while ((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
820 ret = 1;
821 sk_X509_push(sk, cert);
822 }
823 if (ret)
824 ERR_clear_error();
825 return ret;
826}
827
828/* Generalised attribute print: handle PKCS#8 and bag attributes */
829
830int
831print_attribs(BIO * out, STACK_OF(X509_ATTRIBUTE) * attrlst, const char *name)
832{
833 X509_ATTRIBUTE *attr;
834 ASN1_TYPE *av;
835 char *value;
836 int i, attr_nid;
837 if (!attrlst) {
838 BIO_printf(out, "%s: <No Attributes>\n", name);
839 return 1;
840 }
841 if (!sk_X509_ATTRIBUTE_num(attrlst)) {
842 BIO_printf(out, "%s: <Empty Attributes>\n", name);
843 return 1;
844 }
845 BIO_printf(out, "%s\n", name);
846 for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) {
847 attr = sk_X509_ATTRIBUTE_value(attrlst, i);
848 attr_nid = OBJ_obj2nid(attr->object);
849 BIO_printf(out, " ");
850 if (attr_nid == NID_undef) {
851 i2a_ASN1_OBJECT(out, attr->object);
852 BIO_printf(out, ": ");
853 } else
854 BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid));
855
856 if (sk_ASN1_TYPE_num(attr->value.set)) {
857 av = sk_ASN1_TYPE_value(attr->value.set, 0);
858 switch (av->type) {
859 case V_ASN1_BMPSTRING:
860 value = OPENSSL_uni2asc(av->value.bmpstring->data,
861 av->value.bmpstring->length);
862 BIO_printf(out, "%s\n", value);
863 free(value);
864 break;
865
866 case V_ASN1_OCTET_STRING:
867 hex_prin(out, av->value.octet_string->data,
868 av->value.octet_string->length);
869 BIO_printf(out, "\n");
870 break;
871
872 case V_ASN1_BIT_STRING:
873 hex_prin(out, av->value.bit_string->data,
874 av->value.bit_string->length);
875 BIO_printf(out, "\n");
876 break;
877
878 default:
879 BIO_printf(out, "<Unsupported tag %d>\n", av->type);
880 break;
881 }
882 } else
883 BIO_printf(out, "<No Values>\n");
884 }
885 return 1;
886}
887
888void
889hex_prin(BIO * out, unsigned char *buf, int len)
890{
891 int i;
892 for (i = 0; i < len; i++)
893 BIO_printf(out, "%02X ", buf[i]);
894}
895
896static int
897set_pbe(BIO * err, int *ppbe, const char *str)
898{
899 if (!str)
900 return 0;
901 if (!strcmp(str, "NONE")) {
902 *ppbe = -1;
903 return 1;
904 }
905 *ppbe = OBJ_txt2nid(str);
906 if (*ppbe == NID_undef) {
907 BIO_printf(bio_err, "Unknown PBE algorithm %s\n", str);
908 return 0;
909 }
910 return 1;
911}
912
913#endif