xref: /openbsd/usr.bin/openssl/pkcs12.c (revision e7c3ccd1)
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, &param_type, &param, 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