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