Annotation of src/usr.bin/openssl/pkcs12.c, Revision 1.2
1.2 ! jsing 1: /* $OpenBSD: pkcs12.c,v 1.1 2014/08/26 17:47:25 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 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: if (!infile)
390: in = BIO_new_fp(stdin, BIO_NOCLOSE);
391: else
392: in = BIO_new_file(infile, "rb");
393: if (!in) {
394: BIO_printf(bio_err, "Error opening input file %s\n",
395: infile ? infile : "<stdin>");
396: perror(infile);
397: goto end;
398: }
399:
400: if (!outfile) {
401: out = BIO_new_fp(stdout, BIO_NOCLOSE);
402: } else
403: out = BIO_new_file(outfile, "wb");
404: if (!out) {
405: BIO_printf(bio_err, "Error opening output file %s\n",
406: outfile ? outfile : "<stdout>");
407: perror(outfile);
408: goto end;
409: }
410: if (twopass) {
411: if (EVP_read_pw_string(macpass, sizeof macpass, "Enter MAC Password:", export_cert)) {
412: BIO_printf(bio_err, "Can't read Password\n");
413: goto end;
414: }
415: }
416: if (export_cert) {
417: EVP_PKEY *key = NULL;
418: X509 *ucert = NULL, *x = NULL;
419: STACK_OF(X509) * certs = NULL;
420: const EVP_MD *macmd = NULL;
421: unsigned char *catmp = NULL;
422: int i;
423:
424: if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) {
425: BIO_printf(bio_err, "Nothing to do!\n");
426: goto export_end;
427: }
428: if (options & NOCERTS)
429: chain = 0;
430:
431: if (!(options & NOKEYS)) {
432: key = load_key(bio_err, keyname ? keyname : infile,
433: FORMAT_PEM, 1, passin, e, "private key");
434: if (!key)
435: goto export_end;
436: }
437:
438: /* Load in all certs in input file */
439: if (!(options & NOCERTS)) {
440: certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e,
441: "certificates");
442: if (!certs)
443: goto export_end;
444:
445: if (key) {
446: /* Look for matching private key */
447: for (i = 0; i < sk_X509_num(certs); i++) {
448: x = sk_X509_value(certs, i);
449: if (X509_check_private_key(x, key)) {
450: ucert = x;
451: /* Zero keyid and alias */
452: X509_keyid_set1(ucert, NULL, 0);
453: X509_alias_set1(ucert, NULL, 0);
454: /* Remove from list */
455: (void) sk_X509_delete(certs, i);
456: break;
457: }
458: }
459: if (!ucert) {
460: BIO_printf(bio_err, "No certificate matches private key\n");
461: goto export_end;
462: }
463: }
464: }
465:
466: /* Add any more certificates asked for */
467: if (certfile) {
468: STACK_OF(X509) * morecerts = NULL;
469: if (!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM,
470: NULL, e,
471: "certificates from certfile")))
472: goto export_end;
473: while (sk_X509_num(morecerts) > 0)
474: sk_X509_push(certs, sk_X509_shift(morecerts));
475: sk_X509_free(morecerts);
476: }
477:
478:
479: /* If chaining get chain from user cert */
480: if (chain) {
481: int vret;
482: STACK_OF(X509) * chain2;
483: X509_STORE *store = X509_STORE_new();
484: if (!store) {
485: BIO_printf(bio_err, "Memory allocation error\n");
486: goto export_end;
487: }
488: if (!X509_STORE_load_locations(store, CAfile, CApath))
489: X509_STORE_set_default_paths(store);
490:
491: vret = get_cert_chain(ucert, store, &chain2);
492: X509_STORE_free(store);
493:
494: if (!vret) {
495: /* Exclude verified certificate */
496: for (i = 1; i < sk_X509_num(chain2); i++)
497: sk_X509_push(certs, sk_X509_value(chain2, i));
498: /* Free first certificate */
499: X509_free(sk_X509_value(chain2, 0));
500: sk_X509_free(chain2);
501: } else {
502: if (vret >= 0)
503: BIO_printf(bio_err, "Error %s getting chain.\n",
504: X509_verify_cert_error_string(vret));
505: else
506: ERR_print_errors(bio_err);
507: goto export_end;
508: }
509: }
510: /* Add any CA names */
511:
512: for (i = 0; i < sk_OPENSSL_STRING_num(canames); i++) {
513: catmp = (unsigned char *) sk_OPENSSL_STRING_value(canames, i);
514: X509_alias_set1(sk_X509_value(certs, i), catmp, -1);
515: }
516:
517: if (csp_name && key)
518: EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name,
519: MBSTRING_ASC, (unsigned char *) csp_name, -1);
520:
521: if (add_lmk && key)
522: EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1);
523:
524:
525: if (!noprompt &&
526: EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:", 1)) {
527: BIO_printf(bio_err, "Can't read Password\n");
528: goto export_end;
529: }
530: if (!twopass)
531: strlcpy(macpass, pass, sizeof macpass);
532:
533:
534: p12 = PKCS12_create(cpass, name, key, ucert, certs,
535: key_pbe, cert_pbe, iter, -1, keytype);
536:
537: if (!p12) {
538: ERR_print_errors(bio_err);
539: goto export_end;
540: }
541: if (macalg) {
542: macmd = EVP_get_digestbyname(macalg);
543: if (!macmd) {
544: BIO_printf(bio_err, "Unknown digest algorithm %s\n",
545: macalg);
546: }
547: }
548: if (maciter != -1)
549: PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd);
550:
551:
552: i2d_PKCS12_bio(out, p12);
553:
554: ret = 0;
555:
556: export_end:
557:
558: if (key)
559: EVP_PKEY_free(key);
560: if (certs)
561: sk_X509_pop_free(certs, X509_free);
562: if (ucert)
563: X509_free(ucert);
564:
565: goto end;
566:
567: }
568: if (!(p12 = d2i_PKCS12_bio(in, NULL))) {
569: ERR_print_errors(bio_err);
570: goto end;
571: }
572: if (!noprompt && EVP_read_pw_string(pass, sizeof pass, "Enter Import Password:", 0)) {
573: BIO_printf(bio_err, "Can't read Password\n");
574: goto end;
575: }
576:
577: if (!twopass)
578: strlcpy(macpass, pass, sizeof macpass);
579:
580: if ((options & INFO) && p12->mac)
581: BIO_printf(bio_err, "MAC Iteration %ld\n", p12->mac->iter ? ASN1_INTEGER_get(p12->mac->iter) : 1);
582: if (macver) {
583: /* If we enter empty password try no password first */
584: if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) {
585: /* If mac and crypto pass the same set it to NULL too */
586: if (!twopass)
587: cpass = NULL;
588: } else if (!PKCS12_verify_mac(p12, mpass, -1)) {
589: BIO_printf(bio_err, "Mac verify error: invalid password?\n");
590: ERR_print_errors(bio_err);
591: goto end;
592: }
593: BIO_printf(bio_err, "MAC verified OK\n");
594: }
595: if (!dump_certs_keys_p12(out, p12, cpass, -1, options, passout)) {
596: BIO_printf(bio_err, "Error outputting keys and certificates\n");
597: ERR_print_errors(bio_err);
598: goto end;
599: }
600: ret = 0;
601: end:
602: if (p12)
603: PKCS12_free(p12);
604: BIO_free(in);
605: BIO_free_all(out);
606: if (canames)
607: sk_OPENSSL_STRING_free(canames);
608: free(passin);
609: free(passout);
610:
611: return (ret);
612: }
613:
614: int
615: dump_certs_keys_p12(BIO * out, PKCS12 * p12, char *pass,
616: int passlen, int options, char *pempass)
617: {
618: STACK_OF(PKCS7) * asafes = NULL;
619: STACK_OF(PKCS12_SAFEBAG) * bags;
620: int i, bagnid;
621: int ret = 0;
622: PKCS7 *p7;
623:
624: if (!(asafes = PKCS12_unpack_authsafes(p12)))
625: return 0;
626: for (i = 0; i < sk_PKCS7_num(asafes); i++) {
627: p7 = sk_PKCS7_value(asafes, i);
628: bagnid = OBJ_obj2nid(p7->type);
629: if (bagnid == NID_pkcs7_data) {
630: bags = PKCS12_unpack_p7data(p7);
631: if (options & INFO)
632: BIO_printf(bio_err, "PKCS7 Data\n");
633: } else if (bagnid == NID_pkcs7_encrypted) {
634: if (options & INFO) {
635: BIO_printf(bio_err, "PKCS7 Encrypted data: ");
636: alg_print(bio_err,
637: p7->d.encrypted->enc_data->algorithm);
638: }
639: bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
640: } else
641: continue;
642: if (!bags)
643: goto err;
644: if (!dump_certs_pkeys_bags(out, bags, pass, passlen,
645: options, pempass)) {
646: sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
647: goto err;
648: }
649: sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
650: bags = NULL;
651: }
652: ret = 1;
653:
654: err:
655:
656: if (asafes)
657: sk_PKCS7_pop_free(asafes, PKCS7_free);
658: return ret;
659: }
660:
661: int
662: dump_certs_pkeys_bags(BIO * out, STACK_OF(PKCS12_SAFEBAG) * bags,
663: char *pass, int passlen, int options, char *pempass)
664: {
665: int i;
666: for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
667: if (!dump_certs_pkeys_bag(out,
668: sk_PKCS12_SAFEBAG_value(bags, i),
669: pass, passlen,
670: options, pempass))
671: return 0;
672: }
673: return 1;
674: }
675:
676: int
677: dump_certs_pkeys_bag(BIO * out, PKCS12_SAFEBAG * bag, char *pass,
678: int passlen, int options, char *pempass)
679: {
680: EVP_PKEY *pkey;
681: PKCS8_PRIV_KEY_INFO *p8;
682: X509 *x509;
683:
684: switch (M_PKCS12_bag_type(bag)) {
685: case NID_keyBag:
686: if (options & INFO)
687: BIO_printf(bio_err, "Key bag\n");
688: if (options & NOKEYS)
689: return 1;
690: print_attribs(out, bag->attrib, "Bag Attributes");
691: p8 = bag->value.keybag;
692: if (!(pkey = EVP_PKCS82PKEY(p8)))
693: return 0;
694: print_attribs(out, p8->attributes, "Key Attributes");
695: PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass);
696: EVP_PKEY_free(pkey);
697: break;
698:
699: case NID_pkcs8ShroudedKeyBag:
700: if (options & INFO) {
701: BIO_printf(bio_err, "Shrouded Keybag: ");
702: alg_print(bio_err, bag->value.shkeybag->algor);
703: }
704: if (options & NOKEYS)
705: return 1;
706: print_attribs(out, bag->attrib, "Bag Attributes");
707: if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen)))
708: return 0;
709: if (!(pkey = EVP_PKCS82PKEY(p8))) {
710: PKCS8_PRIV_KEY_INFO_free(p8);
711: return 0;
712: }
713: print_attribs(out, p8->attributes, "Key Attributes");
714: PKCS8_PRIV_KEY_INFO_free(p8);
715: PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass);
716: EVP_PKEY_free(pkey);
717: break;
718:
719: case NID_certBag:
720: if (options & INFO)
721: BIO_printf(bio_err, "Certificate bag\n");
722: if (options & NOCERTS)
723: return 1;
724: if (PKCS12_get_attr(bag, NID_localKeyID)) {
725: if (options & CACERTS)
726: return 1;
727: } else if (options & CLCERTS)
728: return 1;
729: print_attribs(out, bag->attrib, "Bag Attributes");
730: if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate)
731: return 1;
732: if (!(x509 = PKCS12_certbag2x509(bag)))
733: return 0;
734: dump_cert_text(out, x509);
735: PEM_write_bio_X509(out, x509);
736: X509_free(x509);
737: break;
738:
739: case NID_safeContentsBag:
740: if (options & INFO)
741: BIO_printf(bio_err, "Safe Contents bag\n");
742: print_attribs(out, bag->attrib, "Bag Attributes");
743: return dump_certs_pkeys_bags(out, bag->value.safes, pass,
744: passlen, options, pempass);
745:
746: default:
747: BIO_printf(bio_err, "Warning unsupported bag type: ");
748: i2a_ASN1_OBJECT(bio_err, bag->type);
749: BIO_printf(bio_err, "\n");
750: return 1;
751: break;
752: }
753: return 1;
754: }
755:
756: /* Given a single certificate return a verified chain or NULL if error */
757:
758: /* Hope this is OK .... */
759:
760: int
761: get_cert_chain(X509 * cert, X509_STORE * store, STACK_OF(X509) ** chain)
762: {
763: X509_STORE_CTX store_ctx;
764: STACK_OF(X509) * chn;
765: int i = 0;
766:
767: /*
768: * FIXME: Should really check the return status of
769: * X509_STORE_CTX_init for an error, but how that fits into the
770: * return value of this function is less obvious.
771: */
772: X509_STORE_CTX_init(&store_ctx, store, cert, NULL);
773: if (X509_verify_cert(&store_ctx) <= 0) {
774: i = X509_STORE_CTX_get_error(&store_ctx);
775: if (i == 0)
776: /*
777: * avoid returning 0 if X509_verify_cert() did not
778: * set an appropriate error value in the context
779: */
780: i = -1;
781: chn = NULL;
782: goto err;
783: } else
784: chn = X509_STORE_CTX_get1_chain(&store_ctx);
785: err:
786: X509_STORE_CTX_cleanup(&store_ctx);
787: *chain = chn;
788:
789: return i;
790: }
791:
792: int
793: alg_print(BIO * x, X509_ALGOR * alg)
794: {
795: PBEPARAM *pbe;
796: const unsigned char *p;
797: p = alg->parameter->value.sequence->data;
798: pbe = d2i_PBEPARAM(NULL, &p, alg->parameter->value.sequence->length);
799: if (!pbe)
800: return 1;
801: BIO_printf(bio_err, "%s, Iteration %ld\n",
802: OBJ_nid2ln(OBJ_obj2nid(alg->algorithm)),
803: ASN1_INTEGER_get(pbe->iter));
804: PBEPARAM_free(pbe);
805: return 1;
806: }
807:
808: /* Load all certificates from a given file */
809:
810: int
811: cert_load(BIO * in, STACK_OF(X509) * sk)
812: {
813: int ret;
814: X509 *cert;
815: ret = 0;
816: while ((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
817: ret = 1;
818: sk_X509_push(sk, cert);
819: }
820: if (ret)
821: ERR_clear_error();
822: return ret;
823: }
824:
825: /* Generalised attribute print: handle PKCS#8 and bag attributes */
826:
827: int
828: print_attribs(BIO * out, STACK_OF(X509_ATTRIBUTE) * attrlst, const char *name)
829: {
830: X509_ATTRIBUTE *attr;
831: ASN1_TYPE *av;
832: char *value;
833: int i, attr_nid;
834: if (!attrlst) {
835: BIO_printf(out, "%s: <No Attributes>\n", name);
836: return 1;
837: }
838: if (!sk_X509_ATTRIBUTE_num(attrlst)) {
839: BIO_printf(out, "%s: <Empty Attributes>\n", name);
840: return 1;
841: }
842: BIO_printf(out, "%s\n", name);
843: for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) {
844: attr = sk_X509_ATTRIBUTE_value(attrlst, i);
845: attr_nid = OBJ_obj2nid(attr->object);
846: BIO_printf(out, " ");
847: if (attr_nid == NID_undef) {
848: i2a_ASN1_OBJECT(out, attr->object);
849: BIO_printf(out, ": ");
850: } else
851: BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid));
852:
853: if (sk_ASN1_TYPE_num(attr->value.set)) {
854: av = sk_ASN1_TYPE_value(attr->value.set, 0);
855: switch (av->type) {
856: case V_ASN1_BMPSTRING:
857: value = OPENSSL_uni2asc(av->value.bmpstring->data,
858: av->value.bmpstring->length);
859: BIO_printf(out, "%s\n", value);
860: free(value);
861: break;
862:
863: case V_ASN1_OCTET_STRING:
864: hex_prin(out, av->value.octet_string->data,
865: av->value.octet_string->length);
866: BIO_printf(out, "\n");
867: break;
868:
869: case V_ASN1_BIT_STRING:
870: hex_prin(out, av->value.bit_string->data,
871: av->value.bit_string->length);
872: BIO_printf(out, "\n");
873: break;
874:
875: default:
876: BIO_printf(out, "<Unsupported tag %d>\n", av->type);
877: break;
878: }
879: } else
880: BIO_printf(out, "<No Values>\n");
881: }
882: return 1;
883: }
884:
885: void
886: hex_prin(BIO * out, unsigned char *buf, int len)
887: {
888: int i;
889: for (i = 0; i < len; i++)
890: BIO_printf(out, "%02X ", buf[i]);
891: }
892:
893: static int
894: set_pbe(BIO * err, int *ppbe, const char *str)
895: {
896: if (!str)
897: return 0;
898: if (!strcmp(str, "NONE")) {
899: *ppbe = -1;
900: return 1;
901: }
902: *ppbe = OBJ_txt2nid(str);
903: if (*ppbe == NID_undef) {
904: BIO_printf(bio_err, "Unknown PBE algorithm %s\n", str);
905: return 0;
906: }
907: return 1;
908: }
909:
910: #endif