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