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