1 /* $OpenBSD: pkcs12.c,v 1.29 2024/12/26 14:10:48 tb 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 #include <openssl/x509.h>
74
75 #define NOKEYS 0x1
76 #define NOCERTS 0x2
77 #define INFO 0x4
78 #define CLCERTS 0x8
79 #define CACERTS 0x10
80
81 static int get_cert_chain(X509 *cert, X509_STORE *store,
82 STACK_OF(X509) **chain);
83 static int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen,
84 int options, char *pempass);
85 static int dump_certs_pkeys_bags(BIO *out, const STACK_OF(PKCS12_SAFEBAG) *bags,
86 char *pass, int passlen, int options, char *pempass);
87 static int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bags, char *pass,
88 int passlen, int options, char *pempass);
89 static int print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst,
90 const char *name);
91 static void hex_prin(BIO *out, unsigned char *buf, int len);
92 static int alg_print(BIO *x, const X509_ALGOR *alg);
93 static int set_pbe(BIO *err, int *ppbe, const char *str);
94
95 static struct {
96 char *CAfile;
97 STACK_OF(OPENSSL_STRING) *canames;
98 char *CApath;
99 int cert_pbe;
100 char *certfile;
101 int chain;
102 const EVP_CIPHER *enc;
103 int export_cert;
104 int key_pbe;
105 char *keyname;
106 int keytype;
107 char *infile;
108 int iter;
109 char *macalg;
110 int maciter;
111 int macver;
112 char *name;
113 int noprompt;
114 int options;
115 char *outfile;
116 char *passarg;
117 char *passargin;
118 char *passargout;
119 int twopass;
120 } cfg;
121
122 static int
pkcs12_opt_canames(char * arg)123 pkcs12_opt_canames(char *arg)
124 {
125 if (cfg.canames == NULL &&
126 (cfg.canames = sk_OPENSSL_STRING_new_null()) == NULL)
127 return (1);
128
129 if (!sk_OPENSSL_STRING_push(cfg.canames, arg))
130 return (1);
131
132 return (0);
133 }
134
135 static int
pkcs12_opt_cert_pbe(char * arg)136 pkcs12_opt_cert_pbe(char *arg)
137 {
138 return (!set_pbe(bio_err, &cfg.cert_pbe, arg));
139 }
140
141 static int
pkcs12_opt_key_pbe(char * arg)142 pkcs12_opt_key_pbe(char *arg)
143 {
144 return (!set_pbe(bio_err, &cfg.key_pbe, arg));
145 }
146
147 static int
pkcs12_opt_passarg(char * arg)148 pkcs12_opt_passarg(char *arg)
149 {
150 cfg.passarg = arg;
151 cfg.noprompt = 1;
152 return (0);
153 }
154
get_cipher_by_name(char * name)155 static const EVP_CIPHER *get_cipher_by_name(char *name)
156 {
157 if (name == NULL || strcmp(name, "") == 0)
158 return (NULL);
159 #ifndef OPENSSL_NO_AES
160 else if (strcmp(name, "aes128") == 0)
161 return EVP_aes_128_cbc();
162 else if (strcmp(name, "aes192") == 0)
163 return EVP_aes_192_cbc();
164 else if (strcmp(name, "aes256") == 0)
165 return EVP_aes_256_cbc();
166 #endif
167 #ifndef OPENSSL_NO_CAMELLIA
168 else if (strcmp(name, "camellia128") == 0)
169 return EVP_camellia_128_cbc();
170 else if (strcmp(name, "camellia192") == 0)
171 return EVP_camellia_192_cbc();
172 else if (strcmp(name, "camellia256") == 0)
173 return EVP_camellia_256_cbc();
174 #endif
175 #ifndef OPENSSL_NO_DES
176 else if (strcmp(name, "des") == 0)
177 return EVP_des_cbc();
178 else if (strcmp(name, "des3") == 0)
179 return EVP_des_ede3_cbc();
180 #endif
181 #ifndef OPENSSL_NO_IDEA
182 else if (strcmp(name, "idea") == 0)
183 return EVP_idea_cbc();
184 #endif
185 else
186 return (NULL);
187 }
188
189 static int
pkcs12_opt_enc(int argc,char ** argv,int * argsused)190 pkcs12_opt_enc(int argc, char **argv, int *argsused)
191 {
192 char *name = argv[0];
193
194 if (*name++ != '-')
195 return (1);
196
197 if (strcmp(name, "nodes") == 0)
198 cfg.enc = NULL;
199 else if ((cfg.enc = get_cipher_by_name(name)) == NULL)
200 return (1);
201
202 *argsused = 1;
203 return (0);
204 }
205
206 static const struct option pkcs12_options[] = {
207 #ifndef OPENSSL_NO_AES
208 {
209 .name = "aes128",
210 .desc = "Encrypt PEM output with CBC AES",
211 .type = OPTION_ARGV_FUNC,
212 .opt.argvfunc = pkcs12_opt_enc,
213 },
214 {
215 .name = "aes192",
216 .desc = "Encrypt PEM output with CBC AES",
217 .type = OPTION_ARGV_FUNC,
218 .opt.argvfunc = pkcs12_opt_enc,
219 },
220 {
221 .name = "aes256",
222 .desc = "Encrypt PEM output with CBC AES",
223 .type = OPTION_ARGV_FUNC,
224 .opt.argvfunc = pkcs12_opt_enc,
225 },
226 #endif
227 #ifndef OPENSSL_NO_CAMELLIA
228 {
229 .name = "camellia128",
230 .desc = "Encrypt PEM output with CBC Camellia",
231 .type = OPTION_ARGV_FUNC,
232 .opt.argvfunc = pkcs12_opt_enc,
233 },
234 {
235 .name = "camellia192",
236 .desc = "Encrypt PEM output with CBC Camellia",
237 .type = OPTION_ARGV_FUNC,
238 .opt.argvfunc = pkcs12_opt_enc,
239 },
240 {
241 .name = "camellia256",
242 .desc = "Encrypt PEM output with CBC Camellia",
243 .type = OPTION_ARGV_FUNC,
244 .opt.argvfunc = pkcs12_opt_enc,
245 },
246 #endif
247 {
248 .name = "des",
249 .desc = "Encrypt private keys with DES",
250 .type = OPTION_ARGV_FUNC,
251 .opt.argvfunc = pkcs12_opt_enc,
252 },
253 {
254 .name = "des3",
255 .desc = "Encrypt private keys with triple DES (default)",
256 .type = OPTION_ARGV_FUNC,
257 .opt.argvfunc = pkcs12_opt_enc,
258 },
259 #ifndef OPENSSL_NO_IDEA
260 {
261 .name = "idea",
262 .desc = "Encrypt private keys with IDEA",
263 .type = OPTION_ARGV_FUNC,
264 .opt.argvfunc = pkcs12_opt_enc,
265 },
266 #endif
267 {
268 .name = "cacerts",
269 .desc = "Only output CA certificates",
270 .type = OPTION_VALUE_OR,
271 .opt.value = &cfg.options,
272 .value = CACERTS,
273 },
274 {
275 .name = "CAfile",
276 .argname = "file",
277 .desc = "PEM format file of CA certificates",
278 .type = OPTION_ARG,
279 .opt.arg = &cfg.CAfile,
280 },
281 {
282 .name = "caname",
283 .argname = "name",
284 .desc = "Use name as CA friendly name (can be used more than once)",
285 .type = OPTION_ARG_FUNC,
286 .opt.argfunc = pkcs12_opt_canames,
287 },
288 {
289 .name = "CApath",
290 .argname = "directory",
291 .desc = "PEM format directory of CA certificates",
292 .type = OPTION_ARG,
293 .opt.arg = &cfg.CApath,
294 },
295 {
296 .name = "certfile",
297 .argname = "file",
298 .desc = "Add all certs in file",
299 .type = OPTION_ARG,
300 .opt.arg = &cfg.certfile,
301 },
302 {
303 .name = "certpbe",
304 .argname = "alg",
305 .desc = "Specify certificate PBE algorithm (default RC2-40)",
306 .type = OPTION_ARG_FUNC,
307 .opt.argfunc = pkcs12_opt_cert_pbe,
308 },
309 {
310 .name = "chain",
311 .desc = "Add certificate chain",
312 .type = OPTION_FLAG,
313 .opt.flag = &cfg.chain,
314 },
315 {
316 .name = "clcerts",
317 .desc = "Only output client certificates",
318 .type = OPTION_VALUE_OR,
319 .opt.value = &cfg.options,
320 .value = CLCERTS,
321 },
322 {
323 .name = "descert",
324 .desc = "Encrypt PKCS#12 certificates with triple DES (default RC2-40)",
325 .type = OPTION_VALUE,
326 .opt.value = &cfg.cert_pbe,
327 .value = NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
328 },
329 {
330 .name = "export",
331 .desc = "Output PKCS#12 file",
332 .type = OPTION_FLAG,
333 .opt.flag = &cfg.export_cert,
334 },
335 {
336 .name = "in",
337 .argname = "file",
338 .desc = "Input filename",
339 .type = OPTION_ARG,
340 .opt.arg = &cfg.infile,
341 },
342 {
343 .name = "info",
344 .desc = "Give info about PKCS#12 structure",
345 .type = OPTION_VALUE_OR,
346 .opt.value = &cfg.options,
347 .value = INFO,
348 },
349 {
350 .name = "inkey",
351 .argname = "file",
352 .desc = "Private key if not infile",
353 .type = OPTION_ARG,
354 .opt.arg = &cfg.keyname,
355 },
356 {
357 .name = "keyex",
358 .desc = "Set MS key exchange type",
359 .type = OPTION_VALUE,
360 .opt.value = &cfg.keytype,
361 .value = KEY_EX,
362 },
363 {
364 .name = "keypbe",
365 .argname = "alg",
366 .desc = "Specify private key PBE algorithm (default 3DES)",
367 .type = OPTION_ARG_FUNC,
368 .opt.argfunc = pkcs12_opt_key_pbe,
369 },
370 {
371 .name = "keysig",
372 .desc = "Set MS key signature type",
373 .type = OPTION_VALUE,
374 .opt.value = &cfg.keytype,
375 .value = KEY_SIG,
376 },
377 {
378 .name = "macalg",
379 .argname = "alg",
380 .desc = "Digest algorithm used in MAC (default SHA1)",
381 .type = OPTION_ARG,
382 .opt.arg = &cfg.macalg,
383 },
384 {
385 .name = "maciter",
386 .desc = "Use MAC iteration",
387 .type = OPTION_VALUE,
388 .opt.value = &cfg.maciter,
389 .value = PKCS12_DEFAULT_ITER,
390 },
391 {
392 .name = "name",
393 .argname = "name",
394 .desc = "Use name as friendly name",
395 .type = OPTION_ARG,
396 .opt.arg = &cfg.name,
397 },
398 {
399 .name = "nocerts",
400 .desc = "Don't output certificates",
401 .type = OPTION_VALUE_OR,
402 .opt.value = &cfg.options,
403 .value = NOCERTS,
404 },
405 {
406 .name = "nodes",
407 .desc = "Don't encrypt private keys",
408 .type = OPTION_ARGV_FUNC,
409 .opt.argvfunc = pkcs12_opt_enc,
410 },
411 {
412 .name = "noiter",
413 .desc = "Don't use encryption iteration",
414 .type = OPTION_VALUE,
415 .opt.value = &cfg.iter,
416 .value = 1,
417 },
418 {
419 .name = "nokeys",
420 .desc = "Don't output private keys",
421 .type = OPTION_VALUE_OR,
422 .opt.value = &cfg.options,
423 .value = NOKEYS,
424 },
425 {
426 .name = "nomac",
427 .desc = "Don't generate MAC",
428 .type = OPTION_VALUE,
429 .opt.value = &cfg.maciter,
430 .value = -1,
431 },
432 {
433 .name = "nomaciter",
434 .desc = "Don't use MAC iteration",
435 .type = OPTION_VALUE,
436 .opt.value = &cfg.maciter,
437 .value = 1,
438 },
439 {
440 .name = "nomacver",
441 .desc = "Don't verify MAC",
442 .type = OPTION_VALUE,
443 .opt.value = &cfg.macver,
444 .value = 0,
445 },
446 {
447 .name = "noout",
448 .desc = "Don't output anything, just verify",
449 .type = OPTION_VALUE_OR,
450 .opt.value = &cfg.options,
451 .value = (NOKEYS | NOCERTS),
452 },
453 {
454 .name = "out",
455 .argname = "file",
456 .desc = "Output filename",
457 .type = OPTION_ARG,
458 .opt.arg = &cfg.outfile,
459 },
460 {
461 .name = "passin",
462 .argname = "arg",
463 .desc = "Input file passphrase source",
464 .type = OPTION_ARG,
465 .opt.arg = &cfg.passargin,
466 },
467 {
468 .name = "passout",
469 .argname = "arg",
470 .desc = "Output file passphrase source",
471 .type = OPTION_ARG,
472 .opt.arg = &cfg.passargout,
473 },
474 {
475 .name = "password",
476 .argname = "arg",
477 .desc = "Set import/export password source",
478 .type = OPTION_ARG_FUNC,
479 .opt.argfunc = pkcs12_opt_passarg,
480 },
481 {
482 .name = "twopass",
483 .desc = "Separate MAC, encryption passwords",
484 .type = OPTION_FLAG,
485 .opt.flag = &cfg.twopass,
486 },
487 { NULL },
488 };
489
490 static void
pkcs12_usage(void)491 pkcs12_usage(void)
492 {
493 fprintf(stderr, "usage: pkcs12 [-aes128 | -aes192 | -aes256 |");
494 fprintf(stderr, " -camellia128 |\n");
495 fprintf(stderr, " -camellia192 | -camellia256 | -des | -des3 |");
496 fprintf(stderr, " -idea]\n");
497 fprintf(stderr, " [-cacerts] [-CAfile file] [-caname name]\n");
498 fprintf(stderr, " [-CApath directory] [-certfile file]");
499 fprintf(stderr, " [-certpbe alg]\n");
500 fprintf(stderr, " [-chain] [-clcerts] [-CSP name] [-descert]");
501 fprintf(stderr, " [-export]\n");
502 fprintf(stderr, " [-in file] [-info] [-inkey file] [-keyex]");
503 fprintf(stderr, " [-keypbe alg]\n");
504 fprintf(stderr, " [-keysig] [-LMK] [-macalg alg] [-maciter]");
505 fprintf(stderr, " [-name name]\n");
506 fprintf(stderr, " [-nocerts] [-nodes] [-noiter] [-nokeys]");
507 fprintf(stderr, " [-nomac]\n");
508 fprintf(stderr, " [-nomaciter] [-nomacver] [-noout] [-out file]\n");
509 fprintf(stderr, " [-passin arg] [-passout arg] [-password arg]");
510 fprintf(stderr, " [-twopass]\n\n");
511 options_usage(pkcs12_options);
512 fprintf(stderr, "\n");
513 }
514
515 int
pkcs12_main(int argc,char ** argv)516 pkcs12_main(int argc, char **argv)
517 {
518 BIO *in = NULL, *out = NULL;
519 PKCS12 *p12 = NULL;
520 char pass[50], macpass[50];
521 int ret = 1;
522 char *cpass = NULL, *mpass = NULL;
523 char *passin = NULL, *passout = NULL;
524
525 if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
526 perror("pledge");
527 exit(1);
528 }
529
530 memset(&cfg, 0, sizeof(cfg));
531 cfg.cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
532 cfg.enc = EVP_des_ede3_cbc();
533 cfg.iter = PKCS12_DEFAULT_ITER;
534 cfg.key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
535 cfg.maciter = PKCS12_DEFAULT_ITER;
536 cfg.macver = 1;
537
538 if (options_parse(argc, argv, pkcs12_options, NULL, NULL) != 0) {
539 pkcs12_usage();
540 goto end;
541 }
542
543 if (cfg.passarg != NULL) {
544 if (cfg.export_cert)
545 cfg.passargout = cfg.passarg;
546 else
547 cfg.passargin = cfg.passarg;
548 }
549 if (!app_passwd(bio_err, cfg.passargin,
550 cfg.passargout, &passin, &passout)) {
551 BIO_printf(bio_err, "Error getting passwords\n");
552 goto end;
553 }
554 if (cpass == NULL) {
555 if (cfg.export_cert)
556 cpass = passout;
557 else
558 cpass = passin;
559 }
560 if (cpass != NULL) {
561 mpass = cpass;
562 cfg.noprompt = 1;
563 } else {
564 cpass = pass;
565 mpass = macpass;
566 }
567
568 if (cfg.infile == NULL)
569 in = BIO_new_fp(stdin, BIO_NOCLOSE);
570 else
571 in = BIO_new_file(cfg.infile, "rb");
572 if (in == NULL) {
573 BIO_printf(bio_err, "Error opening input file %s\n",
574 cfg.infile ? cfg.infile : "<stdin>");
575 perror(cfg.infile);
576 goto end;
577 }
578
579 if (cfg.outfile == NULL) {
580 out = BIO_new_fp(stdout, BIO_NOCLOSE);
581 } else
582 out = BIO_new_file(cfg.outfile, "wb");
583 if (out == NULL) {
584 BIO_printf(bio_err, "Error opening output file %s\n",
585 cfg.outfile ? cfg.outfile : "<stdout>");
586 perror(cfg.outfile);
587 goto end;
588 }
589 if (cfg.twopass) {
590 if (EVP_read_pw_string(macpass, sizeof macpass,
591 "Enter MAC Password:", cfg.export_cert)) {
592 BIO_printf(bio_err, "Can't read Password\n");
593 goto end;
594 }
595 }
596 if (cfg.export_cert) {
597 EVP_PKEY *key = NULL;
598 X509 *ucert = NULL, *x = NULL;
599 STACK_OF(X509) *certs = NULL;
600 const EVP_MD *macmd = NULL;
601 unsigned char *catmp = NULL;
602 int i;
603
604 if ((cfg.options & (NOCERTS | NOKEYS)) ==
605 (NOCERTS | NOKEYS)) {
606 BIO_printf(bio_err, "Nothing to do!\n");
607 goto export_end;
608 }
609 if (cfg.options & NOCERTS)
610 cfg.chain = 0;
611
612 if (!(cfg.options & NOKEYS)) {
613 key = load_key(bio_err, cfg.keyname ?
614 cfg.keyname : cfg.infile,
615 FORMAT_PEM, 1, passin, "private key");
616 if (!key)
617 goto export_end;
618 }
619
620 /* Load in all certs in input file */
621 if (!(cfg.options & NOCERTS)) {
622 certs = load_certs(bio_err, cfg.infile,
623 FORMAT_PEM, NULL, "certificates");
624 if (certs == NULL)
625 goto export_end;
626
627 if (key != NULL) {
628 /* Look for matching private key */
629 for (i = 0; i < sk_X509_num(certs); i++) {
630 x = sk_X509_value(certs, i);
631 if (X509_check_private_key(x, key)) {
632 ucert = x;
633 /* Zero keyid and alias */
634 X509_keyid_set1(ucert, NULL, 0);
635 X509_alias_set1(ucert, NULL, 0);
636 /* Remove from list */
637 (void) sk_X509_delete(certs, i);
638 break;
639 }
640 }
641 if (ucert == NULL) {
642 BIO_printf(bio_err,
643 "No certificate matches private key\n");
644 goto export_end;
645 }
646 }
647 }
648
649 /* Add any more certificates asked for */
650 if (cfg.certfile != NULL) {
651 STACK_OF(X509) *morecerts = NULL;
652 if ((morecerts = load_certs(bio_err,
653 cfg.certfile, FORMAT_PEM, NULL,
654 "certificates from certfile")) == NULL)
655 goto export_end;
656 while (sk_X509_num(morecerts) > 0) {
657 X509 *cert = sk_X509_shift(morecerts);
658
659 if (!sk_X509_push(certs, cert)) {
660 X509_free(cert);
661 sk_X509_pop_free(morecerts, X509_free);
662 goto export_end;
663 }
664 }
665
666 sk_X509_free(morecerts);
667 }
668
669
670 /* If chaining get chain from user cert */
671 if (cfg.chain) {
672 int vret;
673 STACK_OF(X509) *chain2;
674 X509_STORE *store = X509_STORE_new();
675 if (store == NULL) {
676 BIO_printf(bio_err,
677 "Memory allocation error\n");
678 goto export_end;
679 }
680 if (!X509_STORE_load_locations(store,
681 cfg.CAfile, cfg.CApath))
682 X509_STORE_set_default_paths(store);
683
684 vret = get_cert_chain(ucert, store, &chain2);
685 X509_STORE_free(store);
686
687 if (vret == X509_V_OK) {
688 /* Exclude verified certificate */
689 X509_free(sk_X509_shift(chain2));
690
691 while (sk_X509_num(chain2) > 0) {
692 X509 *cert = sk_X509_shift(chain2);
693
694 if (!sk_X509_push(certs, cert)) {
695 X509_free(cert);
696 sk_X509_pop_free(chain2,
697 X509_free);
698 goto export_end;
699 }
700 }
701 sk_X509_free(chain2);
702 } else {
703 if (vret != X509_V_ERR_UNSPECIFIED)
704 BIO_printf(bio_err,
705 "Error %s getting chain.\n",
706 X509_verify_cert_error_string(
707 vret));
708 else
709 ERR_print_errors(bio_err);
710 sk_X509_pop_free(chain2, X509_free);
711 goto export_end;
712 }
713 }
714 /* Add any CA names */
715
716 for (i = 0; i < sk_OPENSSL_STRING_num(cfg.canames);
717 i++) {
718 catmp = (unsigned char *) sk_OPENSSL_STRING_value(
719 cfg.canames, i);
720 X509_alias_set1(sk_X509_value(certs, i), catmp, -1);
721 }
722
723 if (!cfg.noprompt &&
724 EVP_read_pw_string(pass, sizeof pass,
725 "Enter Export Password:", 1)) {
726 BIO_printf(bio_err, "Can't read Password\n");
727 goto export_end;
728 }
729 if (!cfg.twopass)
730 strlcpy(macpass, pass, sizeof macpass);
731
732
733 p12 = PKCS12_create(cpass, cfg.name, key, ucert,
734 certs, cfg.key_pbe, cfg.cert_pbe,
735 cfg.iter, -1, cfg.keytype);
736
737 if (p12 == NULL) {
738 ERR_print_errors(bio_err);
739 goto export_end;
740 }
741 if (cfg.macalg != NULL) {
742 macmd = EVP_get_digestbyname(cfg.macalg);
743 if (macmd == NULL) {
744 BIO_printf(bio_err,
745 "Unknown digest algorithm %s\n",
746 cfg.macalg);
747 }
748 }
749 if (cfg.maciter != -1)
750 PKCS12_set_mac(p12, mpass, -1, NULL, 0,
751 cfg.maciter, macmd);
752
753 i2d_PKCS12_bio(out, p12);
754
755 ret = 0;
756
757 export_end:
758 EVP_PKEY_free(key);
759 sk_X509_pop_free(certs, X509_free);
760 X509_free(ucert);
761
762 goto end;
763
764 }
765 if ((p12 = d2i_PKCS12_bio(in, NULL)) == NULL) {
766 ERR_print_errors(bio_err);
767 goto end;
768 }
769 if (!cfg.noprompt && EVP_read_pw_string(pass, sizeof pass,
770 "Enter Import Password:", 0)) {
771 BIO_printf(bio_err, "Can't read Password\n");
772 goto end;
773 }
774
775 if (!cfg.twopass)
776 strlcpy(macpass, pass, sizeof macpass);
777
778 if ((cfg.options & INFO) != 0 && PKCS12_mac_present(p12)) {
779 const ASN1_INTEGER *iter;
780
781 PKCS12_get0_mac(NULL, NULL, NULL, &iter, p12);
782 BIO_printf(bio_err, "MAC Iteration %ld\n",
783 iter != NULL ? ASN1_INTEGER_get(iter) : 1);
784 }
785 if (cfg.macver) {
786 /* If we enter empty password try no password first */
787 if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) {
788 /* If mac and crypto pass the same set it to NULL too */
789 if (!cfg.twopass)
790 cpass = NULL;
791 } else if (!PKCS12_verify_mac(p12, mpass, -1)) {
792 BIO_printf(bio_err,
793 "Mac verify error: invalid password?\n");
794 ERR_print_errors(bio_err);
795 goto end;
796 }
797 BIO_printf(bio_err, "MAC verified OK\n");
798 }
799 if (!dump_certs_keys_p12(out, p12, cpass, -1, cfg.options,
800 passout)) {
801 BIO_printf(bio_err, "Error outputting keys and certificates\n");
802 ERR_print_errors(bio_err);
803 goto end;
804 }
805 ret = 0;
806 end:
807 PKCS12_free(p12);
808 BIO_free(in);
809 BIO_free_all(out);
810 sk_OPENSSL_STRING_free(cfg.canames);
811 free(passin);
812 free(passout);
813
814 return (ret);
815 }
816
817 static int
dump_certs_keys_p12(BIO * out,PKCS12 * p12,char * pass,int passlen,int options,char * pempass)818 dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen, int options,
819 char *pempass)
820 {
821 STACK_OF(PKCS7) *asafes = NULL;
822 STACK_OF(PKCS12_SAFEBAG) *bags;
823 int i, bagnid;
824 int ret = 0;
825 PKCS7 *p7;
826
827 if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
828 return 0;
829 for (i = 0; i < sk_PKCS7_num(asafes); i++) {
830 p7 = sk_PKCS7_value(asafes, i);
831 bagnid = OBJ_obj2nid(p7->type);
832 if (bagnid == NID_pkcs7_data) {
833 bags = PKCS12_unpack_p7data(p7);
834 if (options & INFO)
835 BIO_printf(bio_err, "PKCS7 Data\n");
836 } else if (bagnid == NID_pkcs7_encrypted) {
837 if (options & INFO) {
838 BIO_printf(bio_err, "PKCS7 Encrypted data: ");
839 alg_print(bio_err,
840 p7->d.encrypted->enc_data->algorithm);
841 }
842 bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
843 } else
844 continue;
845 if (bags == NULL)
846 goto err;
847 if (!dump_certs_pkeys_bags(out, bags, pass, passlen,
848 options, pempass)) {
849 sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
850 goto err;
851 }
852 sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
853 bags = NULL;
854 }
855 ret = 1;
856
857 err:
858 sk_PKCS7_pop_free(asafes, PKCS7_free);
859 return ret;
860 }
861
862 static int
dump_certs_pkeys_bags(BIO * out,const STACK_OF (PKCS12_SAFEBAG)* bags,char * pass,int passlen,int options,char * pempass)863 dump_certs_pkeys_bags(BIO *out, const STACK_OF(PKCS12_SAFEBAG) *bags,
864 char *pass, int passlen, int options, char *pempass)
865 {
866 int i;
867
868 for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
869 if (!dump_certs_pkeys_bag(out,
870 sk_PKCS12_SAFEBAG_value(bags, i),
871 pass, passlen,
872 options, pempass))
873 return 0;
874 }
875 return 1;
876 }
877
878 static int
dump_certs_pkeys_bag(BIO * out,PKCS12_SAFEBAG * bag,char * pass,int passlen,int options,char * pempass)879 dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bag, char *pass, int passlen,
880 int options, char *pempass)
881 {
882 EVP_PKEY *pkey;
883 const STACK_OF(X509_ATTRIBUTE) *attrs;
884 X509 *x509;
885
886 attrs = PKCS12_SAFEBAG_get0_attrs(bag);
887
888 switch (PKCS12_SAFEBAG_get_nid(bag)) {
889 case NID_keyBag:
890 {
891 const PKCS8_PRIV_KEY_INFO *p8;
892
893 if (options & INFO)
894 BIO_printf(bio_err, "Key bag\n");
895 if (options & NOKEYS)
896 return 1;
897 print_attribs(out, attrs, "Bag Attributes");
898 if ((p8 = PKCS12_SAFEBAG_get0_p8inf(bag)) == NULL)
899 return 0;
900 if ((pkey = EVP_PKCS82PKEY(p8)) == NULL)
901 return 0;
902 print_attribs(out, PKCS8_pkey_get0_attrs(p8), "Key Attributes");
903 PEM_write_bio_PrivateKey(out, pkey, cfg.enc, NULL, 0,
904 NULL, pempass);
905 EVP_PKEY_free(pkey);
906 break;
907 }
908
909 case NID_pkcs8ShroudedKeyBag:
910 {
911 PKCS8_PRIV_KEY_INFO *p8;
912
913 if (options & INFO) {
914 const X509_SIG *tp8;
915 const X509_ALGOR *tp8alg;
916
917 BIO_printf(bio_err, "Shrouded Keybag: ");
918 if ((tp8 = PKCS12_SAFEBAG_get0_pkcs8(bag)) == NULL)
919 return 0;
920 X509_SIG_get0(tp8, &tp8alg, NULL);
921 alg_print(bio_err, tp8alg);
922 }
923 if (options & NOKEYS)
924 return 1;
925 print_attribs(out, attrs, "Bag Attributes");
926 if ((p8 = PKCS12_decrypt_skey(bag, pass, passlen)) == NULL)
927 return 0;
928 if ((pkey = EVP_PKCS82PKEY(p8)) == NULL) {
929 PKCS8_PRIV_KEY_INFO_free(p8);
930 return 0;
931 }
932 print_attribs(out, PKCS8_pkey_get0_attrs(p8), "Key Attributes");
933 PKCS8_PRIV_KEY_INFO_free(p8);
934 PEM_write_bio_PrivateKey(out, pkey, cfg.enc, NULL, 0,
935 NULL, pempass);
936 EVP_PKEY_free(pkey);
937 break;
938 }
939
940 case NID_certBag:
941 if (options & INFO)
942 BIO_printf(bio_err, "Certificate bag\n");
943 if (options & NOCERTS)
944 return 1;
945 if (PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID) != NULL) {
946 if (options & CACERTS)
947 return 1;
948 } else if (options & CLCERTS)
949 return 1;
950 print_attribs(out, attrs, "Bag Attributes");
951 if (PKCS12_SAFEBAG_get_bag_nid(bag) != NID_x509Certificate)
952 return 1;
953 if ((x509 = PKCS12_certbag2x509(bag)) == NULL)
954 return 0;
955 dump_cert_text(out, x509);
956 PEM_write_bio_X509(out, x509);
957 X509_free(x509);
958 break;
959
960 case NID_safeContentsBag:
961 if (options & INFO)
962 BIO_printf(bio_err, "Safe Contents bag\n");
963 print_attribs(out, attrs, "Bag Attributes");
964 return dump_certs_pkeys_bags(out, PKCS12_SAFEBAG_get0_safes(bag),
965 pass, passlen, options, pempass);
966
967 default:
968 BIO_printf(bio_err, "Warning unsupported bag type: ");
969 i2a_ASN1_OBJECT(bio_err, PKCS12_SAFEBAG_get0_type(bag));
970 BIO_printf(bio_err, "\n");
971 return 1;
972 break;
973 }
974 return 1;
975 }
976
977 /* Given a single certificate return a verified chain or NULL if error */
978 static int
get_cert_chain(X509 * cert,X509_STORE * store,STACK_OF (X509)** out_chain)979 get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **out_chain)
980 {
981 X509_STORE_CTX *store_ctx = NULL;
982 STACK_OF(X509) *chain = NULL;
983 int ret = X509_V_ERR_UNSPECIFIED;
984
985 if ((store_ctx = X509_STORE_CTX_new()) == NULL)
986 goto err;
987 if (!X509_STORE_CTX_init(store_ctx, store, cert, NULL))
988 goto err;
989
990 if (X509_verify_cert(store_ctx) > 0) {
991 if ((chain = X509_STORE_CTX_get1_chain(store_ctx)) == NULL)
992 goto err;
993 }
994 ret = X509_STORE_CTX_get_error(store_ctx);
995
996 err:
997 X509_STORE_CTX_free(store_ctx);
998 *out_chain = chain;
999
1000 return ret;
1001 }
1002
1003 static int
alg_print(BIO * x,const X509_ALGOR * alg)1004 alg_print(BIO *x, const X509_ALGOR *alg)
1005 {
1006 PBEPARAM *pbe = NULL;
1007 const ASN1_OBJECT *aobj;
1008 int param_type;
1009 const void *param;
1010
1011 X509_ALGOR_get0(&aobj, ¶m_type, ¶m, alg);
1012 if (param_type == V_ASN1_SEQUENCE)
1013 pbe = ASN1_item_unpack(param, &PBEPARAM_it);
1014 if (pbe == NULL)
1015 return 1;
1016 BIO_printf(bio_err, "%s, Iteration %ld\n",
1017 OBJ_nid2ln(OBJ_obj2nid(aobj)),
1018 ASN1_INTEGER_get(pbe->iter));
1019 ASN1_item_free((ASN1_VALUE *)pbe, &PBEPARAM_it);
1020 return 1;
1021 }
1022
1023 /* Generalised attribute print: handle PKCS#8 and bag attributes */
1024 static void
print_attribute(BIO * out,const ASN1_TYPE * av)1025 print_attribute(BIO *out, const ASN1_TYPE *av)
1026 {
1027 char *value;
1028
1029 switch (av->type) {
1030 case V_ASN1_BMPSTRING:
1031 value = OPENSSL_uni2asc(
1032 av->value.bmpstring->data,
1033 av->value.bmpstring->length);
1034 BIO_printf(out, "%s\n", value);
1035 free(value);
1036 break;
1037
1038 case V_ASN1_OCTET_STRING:
1039 hex_prin(out, av->value.octet_string->data,
1040 av->value.octet_string->length);
1041 BIO_printf(out, "\n");
1042 break;
1043
1044 case V_ASN1_BIT_STRING:
1045 hex_prin(out, av->value.bit_string->data,
1046 av->value.bit_string->length);
1047 BIO_printf(out, "\n");
1048 break;
1049
1050 default:
1051 BIO_printf(out, "<Unsupported tag %d>\n",
1052 av->type);
1053 break;
1054 }
1055 }
1056
1057 static int
print_attribs(BIO * out,const STACK_OF (X509_ATTRIBUTE)* attrlst,const char * name)1058 print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst,
1059 const char *name)
1060 {
1061 X509_ATTRIBUTE *attr;
1062 ASN1_TYPE *av;
1063 int i, j, attr_nid;
1064
1065 if (attrlst == NULL) {
1066 BIO_printf(out, "%s: <No Attributes>\n", name);
1067 return 1;
1068 }
1069 if (!sk_X509_ATTRIBUTE_num(attrlst)) {
1070 BIO_printf(out, "%s: <Empty Attributes>\n", name);
1071 return 1;
1072 }
1073 BIO_printf(out, "%s\n", name);
1074 for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) {
1075 ASN1_OBJECT *obj;
1076
1077 attr = sk_X509_ATTRIBUTE_value(attrlst, i);
1078 obj = X509_ATTRIBUTE_get0_object(attr);
1079 attr_nid = OBJ_obj2nid(X509_ATTRIBUTE_get0_object(attr));
1080 BIO_printf(out, " ");
1081 if (attr_nid == NID_undef) {
1082 i2a_ASN1_OBJECT(out, obj);
1083 BIO_printf(out, ": ");
1084 } else
1085 BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid));
1086
1087 if (X509_ATTRIBUTE_count(attr)) {
1088 for (j = 0; j < X509_ATTRIBUTE_count(attr); j++) {
1089 av = X509_ATTRIBUTE_get0_type(attr, j);
1090 print_attribute(out, av);
1091 }
1092 } else
1093 BIO_printf(out, "<No Values>\n");
1094 }
1095 return 1;
1096 }
1097
1098 static void
hex_prin(BIO * out,unsigned char * buf,int len)1099 hex_prin(BIO *out, unsigned char *buf, int len)
1100 {
1101 int i;
1102
1103 for (i = 0; i < len; i++)
1104 BIO_printf(out, "%02X ", buf[i]);
1105 }
1106
1107 static int
set_pbe(BIO * err,int * ppbe,const char * str)1108 set_pbe(BIO *err, int *ppbe, const char *str)
1109 {
1110 if (str == NULL)
1111 return 0;
1112 if (strcmp(str, "NONE") == 0) {
1113 *ppbe = -1;
1114 return 1;
1115 }
1116 *ppbe = OBJ_txt2nid(str);
1117 if (*ppbe == NID_undef) {
1118 BIO_printf(bio_err, "Unknown PBE algorithm %s\n", str);
1119 return 0;
1120 }
1121 return 1;
1122 }
1123
1124 #endif
1125