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