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