xref: /onnv-gate/usr/src/common/openssl/apps/pkcs12.c (revision 6125:38a604bf8269)
10Sstevel@tonic-gate /* pkcs12.c */
20Sstevel@tonic-gate /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3*2139Sjp161948  * project.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate /* ====================================================================
6*2139Sjp161948  * Copyright (c) 1999-2002 The OpenSSL Project.  All rights reserved.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
90Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
100Sstevel@tonic-gate  * are met:
110Sstevel@tonic-gate  *
120Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
130Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
140Sstevel@tonic-gate  *
150Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
160Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
170Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
180Sstevel@tonic-gate  *    distribution.
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this
210Sstevel@tonic-gate  *    software must display the following acknowledgment:
220Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
230Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
240Sstevel@tonic-gate  *
250Sstevel@tonic-gate  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
260Sstevel@tonic-gate  *    endorse or promote products derived from this software without
270Sstevel@tonic-gate  *    prior written permission. For written permission, please contact
280Sstevel@tonic-gate  *    licensing@OpenSSL.org.
290Sstevel@tonic-gate  *
300Sstevel@tonic-gate  * 5. Products derived from this software may not be called "OpenSSL"
310Sstevel@tonic-gate  *    nor may "OpenSSL" appear in their names without prior written
320Sstevel@tonic-gate  *    permission of the OpenSSL Project.
330Sstevel@tonic-gate  *
340Sstevel@tonic-gate  * 6. Redistributions of any form whatsoever must retain the following
350Sstevel@tonic-gate  *    acknowledgment:
360Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
370Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
380Sstevel@tonic-gate  *
390Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
400Sstevel@tonic-gate  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
410Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
420Sstevel@tonic-gate  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
430Sstevel@tonic-gate  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
440Sstevel@tonic-gate  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
450Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
460Sstevel@tonic-gate  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
470Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
480Sstevel@tonic-gate  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
490Sstevel@tonic-gate  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
500Sstevel@tonic-gate  * OF THE POSSIBILITY OF SUCH DAMAGE.
510Sstevel@tonic-gate  * ====================================================================
520Sstevel@tonic-gate  *
530Sstevel@tonic-gate  * This product includes cryptographic software written by Eric Young
540Sstevel@tonic-gate  * (eay@cryptsoft.com).  This product includes software written by Tim
550Sstevel@tonic-gate  * Hudson (tjh@cryptsoft.com).
560Sstevel@tonic-gate  *
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate 
59*2139Sjp161948 #include <openssl/opensslconf.h>
60*2139Sjp161948 #if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_SHA1)
61*2139Sjp161948 
620Sstevel@tonic-gate #include <stdio.h>
630Sstevel@tonic-gate #include <stdlib.h>
640Sstevel@tonic-gate #include <string.h>
650Sstevel@tonic-gate #include "apps.h"
660Sstevel@tonic-gate #include <openssl/crypto.h>
670Sstevel@tonic-gate #include <openssl/err.h>
680Sstevel@tonic-gate #include <openssl/pem.h>
690Sstevel@tonic-gate #include <openssl/pkcs12.h>
700Sstevel@tonic-gate 
710Sstevel@tonic-gate #define PROG pkcs12_main
720Sstevel@tonic-gate 
730Sstevel@tonic-gate const EVP_CIPHER *enc;
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 
760Sstevel@tonic-gate #define NOKEYS		0x1
770Sstevel@tonic-gate #define NOCERTS 	0x2
780Sstevel@tonic-gate #define INFO		0x4
790Sstevel@tonic-gate #define CLCERTS		0x8
800Sstevel@tonic-gate #define CACERTS		0x10
810Sstevel@tonic-gate 
820Sstevel@tonic-gate int get_cert_chain (X509 *cert, X509_STORE *store, STACK_OF(X509) **chain);
830Sstevel@tonic-gate int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen, int options, char *pempass);
840Sstevel@tonic-gate int dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags, char *pass,
850Sstevel@tonic-gate 			  int passlen, int options, char *pempass);
860Sstevel@tonic-gate int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bags, char *pass, int passlen, int options, char *pempass);
87*2139Sjp161948 int print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst,const char *name);
880Sstevel@tonic-gate void hex_prin(BIO *out, unsigned char *buf, int len);
890Sstevel@tonic-gate int alg_print(BIO *x, X509_ALGOR *alg);
900Sstevel@tonic-gate int cert_load(BIO *in, STACK_OF(X509) *sk);
910Sstevel@tonic-gate 
920Sstevel@tonic-gate int MAIN(int, char **);
930Sstevel@tonic-gate 
MAIN(int argc,char ** argv)940Sstevel@tonic-gate int MAIN(int argc, char **argv)
950Sstevel@tonic-gate {
960Sstevel@tonic-gate     ENGINE *e = NULL;
970Sstevel@tonic-gate     char *infile=NULL, *outfile=NULL, *keyname = NULL;
980Sstevel@tonic-gate     char *certfile=NULL;
990Sstevel@tonic-gate     BIO *in=NULL, *out = NULL;
1000Sstevel@tonic-gate     char **args;
1010Sstevel@tonic-gate     char *name = NULL;
1020Sstevel@tonic-gate     char *csp_name = NULL;
1030Sstevel@tonic-gate     PKCS12 *p12 = NULL;
1040Sstevel@tonic-gate     char pass[50], macpass[50];
1050Sstevel@tonic-gate     int export_cert = 0;
1060Sstevel@tonic-gate     int options = 0;
1070Sstevel@tonic-gate     int chain = 0;
1080Sstevel@tonic-gate     int badarg = 0;
1090Sstevel@tonic-gate     int iter = PKCS12_DEFAULT_ITER;
1100Sstevel@tonic-gate     int maciter = PKCS12_DEFAULT_ITER;
1110Sstevel@tonic-gate     int twopass = 0;
1120Sstevel@tonic-gate     int keytype = 0;
1130Sstevel@tonic-gate     int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
1140Sstevel@tonic-gate     int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
1150Sstevel@tonic-gate     int ret = 1;
1160Sstevel@tonic-gate     int macver = 1;
1170Sstevel@tonic-gate     int noprompt = 0;
1180Sstevel@tonic-gate     STACK *canames = NULL;
1190Sstevel@tonic-gate     char *cpass = NULL, *mpass = NULL;
1200Sstevel@tonic-gate     char *passargin = NULL, *passargout = NULL, *passarg = NULL;
1210Sstevel@tonic-gate     char *passin = NULL, *passout = NULL;
1220Sstevel@tonic-gate     char *inrand = NULL;
1230Sstevel@tonic-gate     char *CApath = NULL, *CAfile = NULL;
1240Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
1250Sstevel@tonic-gate     char *engine=NULL;
1260Sstevel@tonic-gate #endif
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate     apps_startup();
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate     enc = EVP_des_ede3_cbc();
1310Sstevel@tonic-gate     if (bio_err == NULL ) bio_err = BIO_new_fp (stderr, BIO_NOCLOSE);
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate 	if (!load_config(bio_err, NULL))
1340Sstevel@tonic-gate 		goto end;
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate     args = argv + 1;
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate     while (*args) {
1400Sstevel@tonic-gate 	if (*args[0] == '-') {
1410Sstevel@tonic-gate 		if (!strcmp (*args, "-nokeys")) options |= NOKEYS;
1420Sstevel@tonic-gate 		else if (!strcmp (*args, "-keyex")) keytype = KEY_EX;
1430Sstevel@tonic-gate 		else if (!strcmp (*args, "-keysig")) keytype = KEY_SIG;
1440Sstevel@tonic-gate 		else if (!strcmp (*args, "-nocerts")) options |= NOCERTS;
1450Sstevel@tonic-gate 		else if (!strcmp (*args, "-clcerts")) options |= CLCERTS;
1460Sstevel@tonic-gate 		else if (!strcmp (*args, "-cacerts")) options |= CACERTS;
1470Sstevel@tonic-gate 		else if (!strcmp (*args, "-noout")) options |= (NOKEYS|NOCERTS);
1480Sstevel@tonic-gate 		else if (!strcmp (*args, "-info")) options |= INFO;
1490Sstevel@tonic-gate 		else if (!strcmp (*args, "-chain")) chain = 1;
1500Sstevel@tonic-gate 		else if (!strcmp (*args, "-twopass")) twopass = 1;
1510Sstevel@tonic-gate 		else if (!strcmp (*args, "-nomacver")) macver = 0;
1520Sstevel@tonic-gate 		else if (!strcmp (*args, "-descert"))
1530Sstevel@tonic-gate     			cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
1540Sstevel@tonic-gate 		else if (!strcmp (*args, "-export")) export_cert = 1;
1550Sstevel@tonic-gate 		else if (!strcmp (*args, "-des")) enc=EVP_des_cbc();
1560Sstevel@tonic-gate #ifndef OPENSSL_NO_IDEA
1570Sstevel@tonic-gate 		else if (!strcmp (*args, "-idea")) enc=EVP_idea_cbc();
1580Sstevel@tonic-gate #endif
1590Sstevel@tonic-gate 		else if (!strcmp (*args, "-des3")) enc = EVP_des_ede3_cbc();
1600Sstevel@tonic-gate #ifndef OPENSSL_NO_AES
1610Sstevel@tonic-gate 		else if (!strcmp(*args,"-aes128")) enc=EVP_aes_128_cbc();
1620Sstevel@tonic-gate 		else if (!strcmp(*args,"-aes192")) enc=EVP_aes_192_cbc();
1630Sstevel@tonic-gate 		else if (!strcmp(*args,"-aes256")) enc=EVP_aes_256_cbc();
164688Sjp161948 #endif
1650Sstevel@tonic-gate 		else if (!strcmp (*args, "-noiter")) iter = 1;
1660Sstevel@tonic-gate 		else if (!strcmp (*args, "-maciter"))
1670Sstevel@tonic-gate 					 maciter = PKCS12_DEFAULT_ITER;
1680Sstevel@tonic-gate 		else if (!strcmp (*args, "-nomaciter"))
1690Sstevel@tonic-gate 					 maciter = 1;
170*2139Sjp161948 		else if (!strcmp (*args, "-nomac"))
171*2139Sjp161948 					 maciter = -1;
1720Sstevel@tonic-gate 		else if (!strcmp (*args, "-nodes")) enc=NULL;
1730Sstevel@tonic-gate 		else if (!strcmp (*args, "-certpbe")) {
1740Sstevel@tonic-gate 			if (args[1]) {
1750Sstevel@tonic-gate 				args++;
176*2139Sjp161948 				if (!strcmp(*args, "NONE"))
177*2139Sjp161948 					cert_pbe = -1;
1780Sstevel@tonic-gate 				cert_pbe=OBJ_txt2nid(*args);
1790Sstevel@tonic-gate 				if(cert_pbe == NID_undef) {
1800Sstevel@tonic-gate 					BIO_printf(bio_err,
1810Sstevel@tonic-gate 						 "Unknown PBE algorithm %s\n", *args);
1820Sstevel@tonic-gate 					badarg = 1;
1830Sstevel@tonic-gate 				}
1840Sstevel@tonic-gate 			} else badarg = 1;
1850Sstevel@tonic-gate 		} else if (!strcmp (*args, "-keypbe")) {
1860Sstevel@tonic-gate 			if (args[1]) {
1870Sstevel@tonic-gate 				args++;
188*2139Sjp161948 				if (!strcmp(*args, "NONE"))
189*2139Sjp161948 					key_pbe = -1;
190*2139Sjp161948 				else
191*2139Sjp161948 					key_pbe=OBJ_txt2nid(*args);
1920Sstevel@tonic-gate 				if(key_pbe == NID_undef) {
1930Sstevel@tonic-gate 					BIO_printf(bio_err,
1940Sstevel@tonic-gate 						 "Unknown PBE algorithm %s\n", *args);
1950Sstevel@tonic-gate 					badarg = 1;
1960Sstevel@tonic-gate 				}
1970Sstevel@tonic-gate 			} else badarg = 1;
1980Sstevel@tonic-gate 		} else if (!strcmp (*args, "-rand")) {
1990Sstevel@tonic-gate 		    if (args[1]) {
2000Sstevel@tonic-gate 			args++;
2010Sstevel@tonic-gate 			inrand = *args;
2020Sstevel@tonic-gate 		    } else badarg = 1;
2030Sstevel@tonic-gate 		} else if (!strcmp (*args, "-inkey")) {
2040Sstevel@tonic-gate 		    if (args[1]) {
2050Sstevel@tonic-gate 			args++;
2060Sstevel@tonic-gate 			keyname = *args;
2070Sstevel@tonic-gate 		    } else badarg = 1;
2080Sstevel@tonic-gate 		} else if (!strcmp (*args, "-certfile")) {
2090Sstevel@tonic-gate 		    if (args[1]) {
2100Sstevel@tonic-gate 			args++;
2110Sstevel@tonic-gate 			certfile = *args;
2120Sstevel@tonic-gate 		    } else badarg = 1;
2130Sstevel@tonic-gate 		} else if (!strcmp (*args, "-name")) {
2140Sstevel@tonic-gate 		    if (args[1]) {
2150Sstevel@tonic-gate 			args++;
2160Sstevel@tonic-gate 			name = *args;
2170Sstevel@tonic-gate 		    } else badarg = 1;
2180Sstevel@tonic-gate 		} else if (!strcmp (*args, "-CSP")) {
2190Sstevel@tonic-gate 		    if (args[1]) {
2200Sstevel@tonic-gate 			args++;
2210Sstevel@tonic-gate 			csp_name = *args;
2220Sstevel@tonic-gate 		    } else badarg = 1;
2230Sstevel@tonic-gate 		} else if (!strcmp (*args, "-caname")) {
2240Sstevel@tonic-gate 		    if (args[1]) {
2250Sstevel@tonic-gate 			args++;
2260Sstevel@tonic-gate 			if (!canames) canames = sk_new_null();
2270Sstevel@tonic-gate 			sk_push(canames, *args);
2280Sstevel@tonic-gate 		    } else badarg = 1;
2290Sstevel@tonic-gate 		} else if (!strcmp (*args, "-in")) {
2300Sstevel@tonic-gate 		    if (args[1]) {
2310Sstevel@tonic-gate 			args++;
2320Sstevel@tonic-gate 			infile = *args;
2330Sstevel@tonic-gate 		    } else badarg = 1;
2340Sstevel@tonic-gate 		} else if (!strcmp (*args, "-out")) {
2350Sstevel@tonic-gate 		    if (args[1]) {
2360Sstevel@tonic-gate 			args++;
2370Sstevel@tonic-gate 			outfile = *args;
2380Sstevel@tonic-gate 		    } else badarg = 1;
2390Sstevel@tonic-gate 		} else if (!strcmp(*args,"-passin")) {
2400Sstevel@tonic-gate 		    if (args[1]) {
2410Sstevel@tonic-gate 			args++;
2420Sstevel@tonic-gate 			passargin = *args;
2430Sstevel@tonic-gate 		    } else badarg = 1;
2440Sstevel@tonic-gate 		} else if (!strcmp(*args,"-passout")) {
2450Sstevel@tonic-gate 		    if (args[1]) {
2460Sstevel@tonic-gate 			args++;
2470Sstevel@tonic-gate 			passargout = *args;
2480Sstevel@tonic-gate 		    } else badarg = 1;
2490Sstevel@tonic-gate 		} else if (!strcmp (*args, "-password")) {
2500Sstevel@tonic-gate 		    if (args[1]) {
2510Sstevel@tonic-gate 			args++;
2520Sstevel@tonic-gate 			passarg = *args;
2530Sstevel@tonic-gate 		    	noprompt = 1;
2540Sstevel@tonic-gate 		    } else badarg = 1;
2550Sstevel@tonic-gate 		} else if (!strcmp(*args,"-CApath")) {
2560Sstevel@tonic-gate 		    if (args[1]) {
2570Sstevel@tonic-gate 			args++;
2580Sstevel@tonic-gate 			CApath = *args;
2590Sstevel@tonic-gate 		    } else badarg = 1;
2600Sstevel@tonic-gate 		} else if (!strcmp(*args,"-CAfile")) {
2610Sstevel@tonic-gate 		    if (args[1]) {
2620Sstevel@tonic-gate 			args++;
2630Sstevel@tonic-gate 			CAfile = *args;
2640Sstevel@tonic-gate 		    } else badarg = 1;
2650Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
2660Sstevel@tonic-gate 		} else if (!strcmp(*args,"-engine")) {
2670Sstevel@tonic-gate 		    if (args[1]) {
2680Sstevel@tonic-gate 			args++;
2690Sstevel@tonic-gate 			engine = *args;
2700Sstevel@tonic-gate 		    } else badarg = 1;
2710Sstevel@tonic-gate #endif
2720Sstevel@tonic-gate 		} else badarg = 1;
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	} else badarg = 1;
2750Sstevel@tonic-gate 	args++;
2760Sstevel@tonic-gate     }
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate     if (badarg) {
2790Sstevel@tonic-gate 	BIO_printf (bio_err, "Usage: pkcs12 [options]\n");
2800Sstevel@tonic-gate 	BIO_printf (bio_err, "where options are\n");
2810Sstevel@tonic-gate 	BIO_printf (bio_err, "-export       output PKCS12 file\n");
2820Sstevel@tonic-gate 	BIO_printf (bio_err, "-chain        add certificate chain\n");
2830Sstevel@tonic-gate 	BIO_printf (bio_err, "-inkey file   private key if not infile\n");
2840Sstevel@tonic-gate 	BIO_printf (bio_err, "-certfile f   add all certs in f\n");
2850Sstevel@tonic-gate 	BIO_printf (bio_err, "-CApath arg   - PEM format directory of CA's\n");
2860Sstevel@tonic-gate 	BIO_printf (bio_err, "-CAfile arg   - PEM format file of CA's\n");
2870Sstevel@tonic-gate 	BIO_printf (bio_err, "-name \"name\"  use name as friendly name\n");
2880Sstevel@tonic-gate 	BIO_printf (bio_err, "-caname \"nm\"  use nm as CA friendly name (can be used more than once).\n");
2890Sstevel@tonic-gate 	BIO_printf (bio_err, "-in  infile   input filename\n");
2900Sstevel@tonic-gate 	BIO_printf (bio_err, "-out outfile  output filename\n");
2910Sstevel@tonic-gate 	BIO_printf (bio_err, "-noout        don't output anything, just verify.\n");
2920Sstevel@tonic-gate 	BIO_printf (bio_err, "-nomacver     don't verify MAC.\n");
2930Sstevel@tonic-gate 	BIO_printf (bio_err, "-nocerts      don't output certificates.\n");
2940Sstevel@tonic-gate 	BIO_printf (bio_err, "-clcerts      only output client certificates.\n");
2950Sstevel@tonic-gate 	BIO_printf (bio_err, "-cacerts      only output CA certificates.\n");
2960Sstevel@tonic-gate 	BIO_printf (bio_err, "-nokeys       don't output private keys.\n");
2970Sstevel@tonic-gate 	BIO_printf (bio_err, "-info         give info about PKCS#12 structure.\n");
2980Sstevel@tonic-gate 	BIO_printf (bio_err, "-des          encrypt private keys with DES\n");
2990Sstevel@tonic-gate 	BIO_printf (bio_err, "-des3         encrypt private keys with triple DES (default)\n");
3000Sstevel@tonic-gate #ifndef OPENSSL_NO_IDEA
3010Sstevel@tonic-gate 	BIO_printf (bio_err, "-idea         encrypt private keys with idea\n");
3020Sstevel@tonic-gate #endif
3030Sstevel@tonic-gate #ifndef OPENSSL_NO_AES
3040Sstevel@tonic-gate 	BIO_printf (bio_err, "-aes128, -aes192, -aes256\n");
3050Sstevel@tonic-gate 	BIO_printf (bio_err, "              encrypt PEM output with cbc aes\n");
3060Sstevel@tonic-gate #endif
3070Sstevel@tonic-gate 	BIO_printf (bio_err, "-nodes        don't encrypt private keys\n");
3080Sstevel@tonic-gate 	BIO_printf (bio_err, "-noiter       don't use encryption iteration\n");
3090Sstevel@tonic-gate 	BIO_printf (bio_err, "-maciter      use MAC iteration\n");
3100Sstevel@tonic-gate 	BIO_printf (bio_err, "-twopass      separate MAC, encryption passwords\n");
3110Sstevel@tonic-gate 	BIO_printf (bio_err, "-descert      encrypt PKCS#12 certificates with triple DES (default RC2-40)\n");
3120Sstevel@tonic-gate 	BIO_printf (bio_err, "-certpbe alg  specify certificate PBE algorithm (default RC2-40)\n");
3130Sstevel@tonic-gate 	BIO_printf (bio_err, "-keypbe alg   specify private key PBE algorithm (default 3DES)\n");
3140Sstevel@tonic-gate 	BIO_printf (bio_err, "-keyex        set MS key exchange type\n");
3150Sstevel@tonic-gate 	BIO_printf (bio_err, "-keysig       set MS key signature type\n");
3160Sstevel@tonic-gate 	BIO_printf (bio_err, "-password p   set import/export password source\n");
3170Sstevel@tonic-gate 	BIO_printf (bio_err, "-passin p     input file pass phrase source\n");
3180Sstevel@tonic-gate 	BIO_printf (bio_err, "-passout p    output file pass phrase source\n");
3190Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
3200Sstevel@tonic-gate 	BIO_printf (bio_err, "-engine e     use engine e, possibly a hardware device.\n");
3210Sstevel@tonic-gate #endif
3220Sstevel@tonic-gate 	BIO_printf(bio_err,  "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
3230Sstevel@tonic-gate 	BIO_printf(bio_err,  "              load the file (or the files in the directory) into\n");
3240Sstevel@tonic-gate 	BIO_printf(bio_err,  "              the random number generator\n");
3250Sstevel@tonic-gate     	goto end;
3260Sstevel@tonic-gate     }
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
3290Sstevel@tonic-gate     e = setup_engine(bio_err, engine, 0);
3300Sstevel@tonic-gate #endif
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate     if(passarg) {
3330Sstevel@tonic-gate 	if(export_cert) passargout = passarg;
3340Sstevel@tonic-gate 	else passargin = passarg;
3350Sstevel@tonic-gate     }
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate     if(!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
3380Sstevel@tonic-gate 	BIO_printf(bio_err, "Error getting passwords\n");
3390Sstevel@tonic-gate 	goto end;
3400Sstevel@tonic-gate     }
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate     if(!cpass) {
3430Sstevel@tonic-gate     	if(export_cert) cpass = passout;
3440Sstevel@tonic-gate     	else cpass = passin;
3450Sstevel@tonic-gate     }
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate     if(cpass) {
3480Sstevel@tonic-gate 	mpass = cpass;
3490Sstevel@tonic-gate 	noprompt = 1;
3500Sstevel@tonic-gate     } else {
3510Sstevel@tonic-gate 	cpass = pass;
3520Sstevel@tonic-gate 	mpass = macpass;
3530Sstevel@tonic-gate     }
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate     if(export_cert || inrand) {
3560Sstevel@tonic-gate     	app_RAND_load_file(NULL, bio_err, (inrand != NULL));
3570Sstevel@tonic-gate         if (inrand != NULL)
3580Sstevel@tonic-gate 		BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
3590Sstevel@tonic-gate 			app_RAND_load_files(inrand));
3600Sstevel@tonic-gate     }
3610Sstevel@tonic-gate     ERR_load_crypto_strings();
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
3640Sstevel@tonic-gate     CRYPTO_push_info("read files");
3650Sstevel@tonic-gate #endif
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate     if (!infile) in = BIO_new_fp(stdin, BIO_NOCLOSE);
3680Sstevel@tonic-gate     else in = BIO_new_file(infile, "rb");
3690Sstevel@tonic-gate     if (!in) {
3700Sstevel@tonic-gate 	    BIO_printf(bio_err, "Error opening input file %s\n",
3710Sstevel@tonic-gate 						infile ? infile : "<stdin>");
3720Sstevel@tonic-gate 	    perror (infile);
3730Sstevel@tonic-gate 	    goto end;
3740Sstevel@tonic-gate    }
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
3770Sstevel@tonic-gate     CRYPTO_pop_info();
3780Sstevel@tonic-gate     CRYPTO_push_info("write files");
3790Sstevel@tonic-gate #endif
3800Sstevel@tonic-gate 
3810Sstevel@tonic-gate     if (!outfile) {
3820Sstevel@tonic-gate 	out = BIO_new_fp(stdout, BIO_NOCLOSE);
3830Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS
3840Sstevel@tonic-gate 	{
3850Sstevel@tonic-gate 	    BIO *tmpbio = BIO_new(BIO_f_linebuffer());
3860Sstevel@tonic-gate 	    out = BIO_push(tmpbio, out);
3870Sstevel@tonic-gate 	}
3880Sstevel@tonic-gate #endif
3890Sstevel@tonic-gate     } else out = BIO_new_file(outfile, "wb");
3900Sstevel@tonic-gate     if (!out) {
3910Sstevel@tonic-gate 	BIO_printf(bio_err, "Error opening output file %s\n",
3920Sstevel@tonic-gate 						outfile ? outfile : "<stdout>");
3930Sstevel@tonic-gate 	perror (outfile);
3940Sstevel@tonic-gate 	goto end;
3950Sstevel@tonic-gate     }
3960Sstevel@tonic-gate     if (twopass) {
3970Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
3980Sstevel@tonic-gate     CRYPTO_push_info("read MAC password");
3990Sstevel@tonic-gate #endif
4000Sstevel@tonic-gate 	if(EVP_read_pw_string (macpass, sizeof macpass, "Enter MAC Password:", export_cert))
4010Sstevel@tonic-gate 	{
4020Sstevel@tonic-gate     	    BIO_printf (bio_err, "Can't read Password\n");
4030Sstevel@tonic-gate     	    goto end;
4040Sstevel@tonic-gate        	}
4050Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
4060Sstevel@tonic-gate     CRYPTO_pop_info();
4070Sstevel@tonic-gate #endif
4080Sstevel@tonic-gate     }
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate     if (export_cert) {
4110Sstevel@tonic-gate 	EVP_PKEY *key = NULL;
412*2139Sjp161948 	X509 *ucert = NULL, *x = NULL;
4130Sstevel@tonic-gate 	STACK_OF(X509) *certs=NULL;
414*2139Sjp161948 	unsigned char *catmp = NULL;
4150Sstevel@tonic-gate 	int i;
416*2139Sjp161948 
417*2139Sjp161948 	if ((options & (NOCERTS|NOKEYS)) == (NOCERTS|NOKEYS))
418*2139Sjp161948 		{
419*2139Sjp161948 		BIO_printf(bio_err, "Nothing to do!\n");
420*2139Sjp161948 		goto export_end;
421*2139Sjp161948 		}
422*2139Sjp161948 
423*2139Sjp161948 	if (options & NOCERTS)
424*2139Sjp161948 		chain = 0;
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
4270Sstevel@tonic-gate 	CRYPTO_push_info("process -export_cert");
4280Sstevel@tonic-gate 	CRYPTO_push_info("reading private key");
4290Sstevel@tonic-gate #endif
430*2139Sjp161948 	if (!(options & NOKEYS))
431*2139Sjp161948 		{
432*2139Sjp161948 		key = load_key(bio_err, keyname ? keyname : infile,
433*2139Sjp161948 				FORMAT_PEM, 1, passin, e, "private key");
434*2139Sjp161948 		if (!key)
435*2139Sjp161948 			goto export_end;
436*2139Sjp161948 		}
4370Sstevel@tonic-gate 
4380Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
4390Sstevel@tonic-gate 	CRYPTO_pop_info();
4400Sstevel@tonic-gate 	CRYPTO_push_info("reading certs from input");
4410Sstevel@tonic-gate #endif
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate 	/* Load in all certs in input file */
444*2139Sjp161948 	if(!(options & NOCERTS))
445*2139Sjp161948 		{
446*2139Sjp161948 		certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e,
447*2139Sjp161948 							"certificates");
448*2139Sjp161948 		if (!certs)
449*2139Sjp161948 			goto export_end;
450*2139Sjp161948 
451*2139Sjp161948 		if (key)
452*2139Sjp161948 			{
453*2139Sjp161948 			/* Look for matching private key */
454*2139Sjp161948 			for(i = 0; i < sk_X509_num(certs); i++)
455*2139Sjp161948 				{
456*2139Sjp161948 				x = sk_X509_value(certs, i);
457*2139Sjp161948 				if(X509_check_private_key(x, key))
458*2139Sjp161948 					{
459*2139Sjp161948 					ucert = x;
460*2139Sjp161948 					/* Zero keyid and alias */
461*2139Sjp161948 					X509_keyid_set1(ucert, NULL, 0);
462*2139Sjp161948 					X509_alias_set1(ucert, NULL, 0);
463*2139Sjp161948 					/* Remove from list */
464*2139Sjp161948 					sk_X509_delete(certs, i);
465*2139Sjp161948 					break;
466*2139Sjp161948 					}
467*2139Sjp161948 				}
468*2139Sjp161948 			if (!ucert)
469*2139Sjp161948 				{
470*2139Sjp161948 				BIO_printf(bio_err, "No certificate matches private key\n");
471*2139Sjp161948 				goto export_end;
472*2139Sjp161948 				}
473*2139Sjp161948 			}
474*2139Sjp161948 
475*2139Sjp161948 		}
4760Sstevel@tonic-gate 
4770Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
4780Sstevel@tonic-gate 	CRYPTO_pop_info();
4790Sstevel@tonic-gate 	CRYPTO_push_info("reading certs from input 2");
4800Sstevel@tonic-gate #endif
4810Sstevel@tonic-gate 
482*2139Sjp161948 	/* Add any more certificates asked for */
483*2139Sjp161948 	if(certfile)
484*2139Sjp161948 		{
485*2139Sjp161948 		STACK_OF(X509) *morecerts=NULL;
486*2139Sjp161948 		if(!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM,
487*2139Sjp161948 					    NULL, e,
488*2139Sjp161948 					    "certificates from certfile")))
489*2139Sjp161948 			goto export_end;
490*2139Sjp161948 		while(sk_X509_num(morecerts) > 0)
491*2139Sjp161948 			sk_X509_push(certs, sk_X509_shift(morecerts));
492*2139Sjp161948 		sk_X509_free(morecerts);
493*2139Sjp161948  		}
494*2139Sjp161948 
4950Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
4960Sstevel@tonic-gate 	CRYPTO_pop_info();
4970Sstevel@tonic-gate 	CRYPTO_push_info("reading certs from certfile");
4980Sstevel@tonic-gate #endif
4990Sstevel@tonic-gate 
5000Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
5010Sstevel@tonic-gate 	CRYPTO_pop_info();
5020Sstevel@tonic-gate 	CRYPTO_push_info("building chain");
5030Sstevel@tonic-gate #endif
5040Sstevel@tonic-gate 
5050Sstevel@tonic-gate 	/* If chaining get chain from user cert */
5060Sstevel@tonic-gate 	if (chain) {
5070Sstevel@tonic-gate         	int vret;
5080Sstevel@tonic-gate 		STACK_OF(X509) *chain2;
5090Sstevel@tonic-gate 		X509_STORE *store = X509_STORE_new();
5100Sstevel@tonic-gate 		if (!store)
5110Sstevel@tonic-gate 			{
5120Sstevel@tonic-gate 			BIO_printf (bio_err, "Memory allocation error\n");
5130Sstevel@tonic-gate 			goto export_end;
5140Sstevel@tonic-gate 			}
5150Sstevel@tonic-gate 		if (!X509_STORE_load_locations(store, CAfile, CApath))
5160Sstevel@tonic-gate 			X509_STORE_set_default_paths (store);
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 		vret = get_cert_chain (ucert, store, &chain2);
5190Sstevel@tonic-gate 		X509_STORE_free(store);
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 		if (!vret) {
5220Sstevel@tonic-gate 		    /* Exclude verified certificate */
5230Sstevel@tonic-gate 		    for (i = 1; i < sk_X509_num (chain2) ; i++)
5240Sstevel@tonic-gate 			sk_X509_push(certs, sk_X509_value (chain2, i));
5250Sstevel@tonic-gate 		    /* Free first certificate */
5260Sstevel@tonic-gate 		    X509_free(sk_X509_value(chain2, 0));
5270Sstevel@tonic-gate 		    sk_X509_free(chain2);
5280Sstevel@tonic-gate 		} else {
5290Sstevel@tonic-gate 			BIO_printf (bio_err, "Error %s getting chain.\n",
5300Sstevel@tonic-gate 					X509_verify_cert_error_string(vret));
5310Sstevel@tonic-gate 			goto export_end;
5320Sstevel@tonic-gate 		}
5330Sstevel@tonic-gate     	}
5340Sstevel@tonic-gate 
535*2139Sjp161948 	/* Add any CA names */
5360Sstevel@tonic-gate 
537*2139Sjp161948 	for (i = 0; i < sk_num(canames); i++)
538*2139Sjp161948 		{
539*2139Sjp161948 		catmp = (unsigned char *)sk_value(canames, i);
540*2139Sjp161948 		X509_alias_set1(sk_X509_value(certs, i), catmp, -1);
541*2139Sjp161948 		}
542*2139Sjp161948 
543*2139Sjp161948 	if (csp_name && key)
544*2139Sjp161948 		EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name,
545*2139Sjp161948 				MBSTRING_ASC, (unsigned char *)csp_name, -1);
546*2139Sjp161948 
5470Sstevel@tonic-gate 
5480Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
5490Sstevel@tonic-gate 	CRYPTO_pop_info();
550*2139Sjp161948 	CRYPTO_push_info("reading password");
5510Sstevel@tonic-gate #endif
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate 	if(!noprompt &&
554*2139Sjp161948 		EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:", 1))
555*2139Sjp161948 		{
556*2139Sjp161948 	    	BIO_printf (bio_err, "Can't read Password\n");
557*2139Sjp161948 	    	goto export_end;
558*2139Sjp161948         	}
5590Sstevel@tonic-gate 	if (!twopass) BUF_strlcpy(macpass, pass, sizeof macpass);
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
5620Sstevel@tonic-gate 	CRYPTO_pop_info();
563*2139Sjp161948 	CRYPTO_push_info("creating PKCS#12 structure");
5640Sstevel@tonic-gate #endif
5650Sstevel@tonic-gate 
566*2139Sjp161948 	p12 = PKCS12_create(cpass, name, key, ucert, certs,
567*2139Sjp161948 				key_pbe, cert_pbe, iter, -1, keytype);
5680Sstevel@tonic-gate 
569*2139Sjp161948 	if (!p12)
570*2139Sjp161948 		{
571*2139Sjp161948 	    	ERR_print_errors (bio_err);
572*2139Sjp161948 		goto export_end;
573*2139Sjp161948 		}
5740Sstevel@tonic-gate 
575*2139Sjp161948 	if (maciter != -1)
576*2139Sjp161948 		PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, NULL);
5770Sstevel@tonic-gate 
5780Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
5790Sstevel@tonic-gate 	CRYPTO_pop_info();
5800Sstevel@tonic-gate 	CRYPTO_push_info("writing pkcs12");
5810Sstevel@tonic-gate #endif
5820Sstevel@tonic-gate 
583*2139Sjp161948 	i2d_PKCS12_bio(out, p12);
5840Sstevel@tonic-gate 
5850Sstevel@tonic-gate 	ret = 0;
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate     export_end:
5880Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
5890Sstevel@tonic-gate 	CRYPTO_pop_info();
5900Sstevel@tonic-gate 	CRYPTO_pop_info();
5910Sstevel@tonic-gate 	CRYPTO_push_info("process -export_cert: freeing");
5920Sstevel@tonic-gate #endif
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate 	if (key) EVP_PKEY_free(key);
5950Sstevel@tonic-gate 	if (certs) sk_X509_pop_free(certs, X509_free);
596*2139Sjp161948 	if (ucert) X509_free(ucert);
5970Sstevel@tonic-gate 
5980Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
5990Sstevel@tonic-gate 	CRYPTO_pop_info();
6000Sstevel@tonic-gate #endif
6010Sstevel@tonic-gate 	goto end;
6020Sstevel@tonic-gate 
6030Sstevel@tonic-gate     }
6040Sstevel@tonic-gate 
6050Sstevel@tonic-gate     if (!(p12 = d2i_PKCS12_bio (in, NULL))) {
6060Sstevel@tonic-gate 	ERR_print_errors(bio_err);
6070Sstevel@tonic-gate 	goto end;
6080Sstevel@tonic-gate     }
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
6110Sstevel@tonic-gate     CRYPTO_push_info("read import password");
6120Sstevel@tonic-gate #endif
6130Sstevel@tonic-gate     if(!noprompt && EVP_read_pw_string(pass, sizeof pass, "Enter Import Password:", 0)) {
6140Sstevel@tonic-gate 	BIO_printf (bio_err, "Can't read Password\n");
6150Sstevel@tonic-gate 	goto end;
6160Sstevel@tonic-gate     }
6170Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
6180Sstevel@tonic-gate     CRYPTO_pop_info();
6190Sstevel@tonic-gate #endif
6200Sstevel@tonic-gate 
6210Sstevel@tonic-gate     if (!twopass) BUF_strlcpy(macpass, pass, sizeof macpass);
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate     if (options & INFO) BIO_printf (bio_err, "MAC Iteration %ld\n", p12->mac->iter ? ASN1_INTEGER_get (p12->mac->iter) : 1);
6240Sstevel@tonic-gate     if(macver) {
6250Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
6260Sstevel@tonic-gate     CRYPTO_push_info("verify MAC");
6270Sstevel@tonic-gate #endif
6280Sstevel@tonic-gate 	/* If we enter empty password try no password first */
629*2139Sjp161948 	if(!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) {
6300Sstevel@tonic-gate 		/* If mac and crypto pass the same set it to NULL too */
6310Sstevel@tonic-gate 		if(!twopass) cpass = NULL;
6320Sstevel@tonic-gate 	} else if (!PKCS12_verify_mac(p12, mpass, -1)) {
6330Sstevel@tonic-gate 	    BIO_printf (bio_err, "Mac verify error: invalid password?\n");
6340Sstevel@tonic-gate 	    ERR_print_errors (bio_err);
6350Sstevel@tonic-gate 	    goto end;
6360Sstevel@tonic-gate 	}
6370Sstevel@tonic-gate 	BIO_printf (bio_err, "MAC verified OK\n");
6380Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
6390Sstevel@tonic-gate     CRYPTO_pop_info();
6400Sstevel@tonic-gate #endif
6410Sstevel@tonic-gate     }
6420Sstevel@tonic-gate 
6430Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
6440Sstevel@tonic-gate     CRYPTO_push_info("output keys and certificates");
6450Sstevel@tonic-gate #endif
6460Sstevel@tonic-gate     if (!dump_certs_keys_p12 (out, p12, cpass, -1, options, passout)) {
6470Sstevel@tonic-gate 	BIO_printf(bio_err, "Error outputting keys and certificates\n");
6480Sstevel@tonic-gate 	ERR_print_errors (bio_err);
6490Sstevel@tonic-gate 	goto end;
6500Sstevel@tonic-gate     }
6510Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
6520Sstevel@tonic-gate     CRYPTO_pop_info();
6530Sstevel@tonic-gate #endif
6540Sstevel@tonic-gate     ret = 0;
6550Sstevel@tonic-gate  end:
6560Sstevel@tonic-gate     if (p12) PKCS12_free(p12);
6570Sstevel@tonic-gate     if(export_cert || inrand) app_RAND_write_file(NULL, bio_err);
6580Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
6590Sstevel@tonic-gate     CRYPTO_remove_all_info();
6600Sstevel@tonic-gate #endif
6610Sstevel@tonic-gate     BIO_free(in);
6620Sstevel@tonic-gate     BIO_free_all(out);
6630Sstevel@tonic-gate     if (canames) sk_free(canames);
6640Sstevel@tonic-gate     if(passin) OPENSSL_free(passin);
6650Sstevel@tonic-gate     if(passout) OPENSSL_free(passout);
6660Sstevel@tonic-gate     apps_shutdown();
6670Sstevel@tonic-gate     OPENSSL_EXIT(ret);
6680Sstevel@tonic-gate }
6690Sstevel@tonic-gate 
dump_certs_keys_p12(BIO * out,PKCS12 * p12,char * pass,int passlen,int options,char * pempass)6700Sstevel@tonic-gate int dump_certs_keys_p12 (BIO *out, PKCS12 *p12, char *pass,
6710Sstevel@tonic-gate 	     int passlen, int options, char *pempass)
6720Sstevel@tonic-gate {
673*2139Sjp161948 	STACK_OF(PKCS7) *asafes = NULL;
6740Sstevel@tonic-gate 	STACK_OF(PKCS12_SAFEBAG) *bags;
6750Sstevel@tonic-gate 	int i, bagnid;
676*2139Sjp161948 	int ret = 0;
6770Sstevel@tonic-gate 	PKCS7 *p7;
6780Sstevel@tonic-gate 
6790Sstevel@tonic-gate 	if (!( asafes = PKCS12_unpack_authsafes(p12))) return 0;
6800Sstevel@tonic-gate 	for (i = 0; i < sk_PKCS7_num (asafes); i++) {
6810Sstevel@tonic-gate 		p7 = sk_PKCS7_value (asafes, i);
6820Sstevel@tonic-gate 		bagnid = OBJ_obj2nid (p7->type);
6830Sstevel@tonic-gate 		if (bagnid == NID_pkcs7_data) {
6840Sstevel@tonic-gate 			bags = PKCS12_unpack_p7data(p7);
6850Sstevel@tonic-gate 			if (options & INFO) BIO_printf (bio_err, "PKCS7 Data\n");
6860Sstevel@tonic-gate 		} else if (bagnid == NID_pkcs7_encrypted) {
6870Sstevel@tonic-gate 			if (options & INFO) {
6880Sstevel@tonic-gate 				BIO_printf(bio_err, "PKCS7 Encrypted data: ");
6890Sstevel@tonic-gate 				alg_print(bio_err,
6900Sstevel@tonic-gate 					p7->d.encrypted->enc_data->algorithm);
6910Sstevel@tonic-gate 			}
6920Sstevel@tonic-gate 			bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
6930Sstevel@tonic-gate 		} else continue;
694*2139Sjp161948 		if (!bags) goto err;
6950Sstevel@tonic-gate 	    	if (!dump_certs_pkeys_bags (out, bags, pass, passlen,
6960Sstevel@tonic-gate 						 options, pempass)) {
6970Sstevel@tonic-gate 			sk_PKCS12_SAFEBAG_pop_free (bags, PKCS12_SAFEBAG_free);
698*2139Sjp161948 			goto err;
6990Sstevel@tonic-gate 		}
7000Sstevel@tonic-gate 		sk_PKCS12_SAFEBAG_pop_free (bags, PKCS12_SAFEBAG_free);
701*2139Sjp161948 		bags = NULL;
7020Sstevel@tonic-gate 	}
703*2139Sjp161948 	ret = 1;
704*2139Sjp161948 
705*2139Sjp161948 	err:
706*2139Sjp161948 
707*2139Sjp161948 	if (asafes)
708*2139Sjp161948 		sk_PKCS7_pop_free (asafes, PKCS7_free);
709*2139Sjp161948 	return ret;
7100Sstevel@tonic-gate }
7110Sstevel@tonic-gate 
dump_certs_pkeys_bags(BIO * out,STACK_OF (PKCS12_SAFEBAG)* bags,char * pass,int passlen,int options,char * pempass)7120Sstevel@tonic-gate int dump_certs_pkeys_bags (BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags,
7130Sstevel@tonic-gate 			   char *pass, int passlen, int options, char *pempass)
7140Sstevel@tonic-gate {
7150Sstevel@tonic-gate 	int i;
7160Sstevel@tonic-gate 	for (i = 0; i < sk_PKCS12_SAFEBAG_num (bags); i++) {
7170Sstevel@tonic-gate 		if (!dump_certs_pkeys_bag (out,
7180Sstevel@tonic-gate 					   sk_PKCS12_SAFEBAG_value (bags, i),
7190Sstevel@tonic-gate 					   pass, passlen,
7200Sstevel@tonic-gate 					   options, pempass))
7210Sstevel@tonic-gate 		    return 0;
7220Sstevel@tonic-gate 	}
7230Sstevel@tonic-gate 	return 1;
7240Sstevel@tonic-gate }
7250Sstevel@tonic-gate 
dump_certs_pkeys_bag(BIO * out,PKCS12_SAFEBAG * bag,char * pass,int passlen,int options,char * pempass)7260Sstevel@tonic-gate int dump_certs_pkeys_bag (BIO *out, PKCS12_SAFEBAG *bag, char *pass,
7270Sstevel@tonic-gate 	     int passlen, int options, char *pempass)
7280Sstevel@tonic-gate {
7290Sstevel@tonic-gate 	EVP_PKEY *pkey;
7300Sstevel@tonic-gate 	PKCS8_PRIV_KEY_INFO *p8;
7310Sstevel@tonic-gate 	X509 *x509;
7320Sstevel@tonic-gate 
7330Sstevel@tonic-gate 	switch (M_PKCS12_bag_type(bag))
7340Sstevel@tonic-gate 	{
7350Sstevel@tonic-gate 	case NID_keyBag:
7360Sstevel@tonic-gate 		if (options & INFO) BIO_printf (bio_err, "Key bag\n");
7370Sstevel@tonic-gate 		if (options & NOKEYS) return 1;
7380Sstevel@tonic-gate 		print_attribs (out, bag->attrib, "Bag Attributes");
7390Sstevel@tonic-gate 		p8 = bag->value.keybag;
7400Sstevel@tonic-gate 		if (!(pkey = EVP_PKCS82PKEY (p8))) return 0;
7410Sstevel@tonic-gate 		print_attribs (out, p8->attributes, "Key Attributes");
7420Sstevel@tonic-gate 		PEM_write_bio_PrivateKey (out, pkey, enc, NULL, 0, NULL, pempass);
7430Sstevel@tonic-gate 		EVP_PKEY_free(pkey);
7440Sstevel@tonic-gate 	break;
7450Sstevel@tonic-gate 
7460Sstevel@tonic-gate 	case NID_pkcs8ShroudedKeyBag:
7470Sstevel@tonic-gate 		if (options & INFO) {
7480Sstevel@tonic-gate 			BIO_printf (bio_err, "Shrouded Keybag: ");
7490Sstevel@tonic-gate 			alg_print (bio_err, bag->value.shkeybag->algor);
7500Sstevel@tonic-gate 		}
7510Sstevel@tonic-gate 		if (options & NOKEYS) return 1;
7520Sstevel@tonic-gate 		print_attribs (out, bag->attrib, "Bag Attributes");
7530Sstevel@tonic-gate 		if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen)))
7540Sstevel@tonic-gate 				return 0;
7550Sstevel@tonic-gate 		if (!(pkey = EVP_PKCS82PKEY (p8))) {
7560Sstevel@tonic-gate 			PKCS8_PRIV_KEY_INFO_free(p8);
7570Sstevel@tonic-gate 			return 0;
7580Sstevel@tonic-gate 		}
7590Sstevel@tonic-gate 		print_attribs (out, p8->attributes, "Key Attributes");
7600Sstevel@tonic-gate 		PKCS8_PRIV_KEY_INFO_free(p8);
7610Sstevel@tonic-gate 		PEM_write_bio_PrivateKey (out, pkey, enc, NULL, 0, NULL, pempass);
7620Sstevel@tonic-gate 		EVP_PKEY_free(pkey);
7630Sstevel@tonic-gate 	break;
7640Sstevel@tonic-gate 
7650Sstevel@tonic-gate 	case NID_certBag:
7660Sstevel@tonic-gate 		if (options & INFO) BIO_printf (bio_err, "Certificate bag\n");
7670Sstevel@tonic-gate 		if (options & NOCERTS) return 1;
7680Sstevel@tonic-gate                 if (PKCS12_get_attr(bag, NID_localKeyID)) {
7690Sstevel@tonic-gate 			if (options & CACERTS) return 1;
7700Sstevel@tonic-gate 		} else if (options & CLCERTS) return 1;
7710Sstevel@tonic-gate 		print_attribs (out, bag->attrib, "Bag Attributes");
7720Sstevel@tonic-gate 		if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate )
7730Sstevel@tonic-gate 								 return 1;
7740Sstevel@tonic-gate 		if (!(x509 = PKCS12_certbag2x509(bag))) return 0;
7750Sstevel@tonic-gate 		dump_cert_text (out, x509);
7760Sstevel@tonic-gate 		PEM_write_bio_X509 (out, x509);
7770Sstevel@tonic-gate 		X509_free(x509);
7780Sstevel@tonic-gate 	break;
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 	case NID_safeContentsBag:
7810Sstevel@tonic-gate 		if (options & INFO) BIO_printf (bio_err, "Safe Contents bag\n");
7820Sstevel@tonic-gate 		print_attribs (out, bag->attrib, "Bag Attributes");
7830Sstevel@tonic-gate 		return dump_certs_pkeys_bags (out, bag->value.safes, pass,
7840Sstevel@tonic-gate 							    passlen, options, pempass);
7850Sstevel@tonic-gate 
7860Sstevel@tonic-gate 	default:
7870Sstevel@tonic-gate 		BIO_printf (bio_err, "Warning unsupported bag type: ");
7880Sstevel@tonic-gate 		i2a_ASN1_OBJECT (bio_err, bag->type);
7890Sstevel@tonic-gate 		BIO_printf (bio_err, "\n");
7900Sstevel@tonic-gate 		return 1;
7910Sstevel@tonic-gate 	break;
7920Sstevel@tonic-gate 	}
7930Sstevel@tonic-gate 	return 1;
7940Sstevel@tonic-gate }
7950Sstevel@tonic-gate 
7960Sstevel@tonic-gate /* Given a single certificate return a verified chain or NULL if error */
7970Sstevel@tonic-gate 
7980Sstevel@tonic-gate /* Hope this is OK .... */
7990Sstevel@tonic-gate 
get_cert_chain(X509 * cert,X509_STORE * store,STACK_OF (X509)** chain)8000Sstevel@tonic-gate int get_cert_chain (X509 *cert, X509_STORE *store, STACK_OF(X509) **chain)
8010Sstevel@tonic-gate {
8020Sstevel@tonic-gate 	X509_STORE_CTX store_ctx;
8030Sstevel@tonic-gate 	STACK_OF(X509) *chn;
8040Sstevel@tonic-gate 	int i;
8050Sstevel@tonic-gate 
8060Sstevel@tonic-gate 	/* FIXME: Should really check the return status of X509_STORE_CTX_init
8070Sstevel@tonic-gate 	 * for an error, but how that fits into the return value of this
8080Sstevel@tonic-gate 	 * function is less obvious. */
8090Sstevel@tonic-gate 	X509_STORE_CTX_init(&store_ctx, store, cert, NULL);
8100Sstevel@tonic-gate 	if (X509_verify_cert(&store_ctx) <= 0) {
8110Sstevel@tonic-gate 		i = X509_STORE_CTX_get_error (&store_ctx);
8120Sstevel@tonic-gate 		goto err;
8130Sstevel@tonic-gate 	}
8140Sstevel@tonic-gate 	chn =  X509_STORE_CTX_get1_chain(&store_ctx);
8150Sstevel@tonic-gate 	i = 0;
8160Sstevel@tonic-gate 	*chain = chn;
8170Sstevel@tonic-gate err:
8180Sstevel@tonic-gate 	X509_STORE_CTX_cleanup(&store_ctx);
8190Sstevel@tonic-gate 
8200Sstevel@tonic-gate 	return i;
8210Sstevel@tonic-gate }
8220Sstevel@tonic-gate 
alg_print(BIO * x,X509_ALGOR * alg)8230Sstevel@tonic-gate int alg_print (BIO *x, X509_ALGOR *alg)
8240Sstevel@tonic-gate {
8250Sstevel@tonic-gate 	PBEPARAM *pbe;
826*2139Sjp161948 	const unsigned char *p;
8270Sstevel@tonic-gate 	p = alg->parameter->value.sequence->data;
8280Sstevel@tonic-gate 	pbe = d2i_PBEPARAM (NULL, &p, alg->parameter->value.sequence->length);
829*2139Sjp161948 	BIO_printf (bio_err, "%s, Iteration %ld\n",
830*2139Sjp161948 		OBJ_nid2ln(OBJ_obj2nid(alg->algorithm)),
831*2139Sjp161948 		ASN1_INTEGER_get(pbe->iter));
8320Sstevel@tonic-gate 	PBEPARAM_free (pbe);
8330Sstevel@tonic-gate 	return 0;
8340Sstevel@tonic-gate }
8350Sstevel@tonic-gate 
8360Sstevel@tonic-gate /* Load all certificates from a given file */
8370Sstevel@tonic-gate 
cert_load(BIO * in,STACK_OF (X509)* sk)8380Sstevel@tonic-gate int cert_load(BIO *in, STACK_OF(X509) *sk)
8390Sstevel@tonic-gate {
8400Sstevel@tonic-gate 	int ret;
8410Sstevel@tonic-gate 	X509 *cert;
8420Sstevel@tonic-gate 	ret = 0;
8430Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
8440Sstevel@tonic-gate 	CRYPTO_push_info("cert_load(): reading one cert");
8450Sstevel@tonic-gate #endif
8460Sstevel@tonic-gate 	while((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
8470Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
8480Sstevel@tonic-gate 		CRYPTO_pop_info();
8490Sstevel@tonic-gate #endif
8500Sstevel@tonic-gate 		ret = 1;
8510Sstevel@tonic-gate 		sk_X509_push(sk, cert);
8520Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
8530Sstevel@tonic-gate 		CRYPTO_push_info("cert_load(): reading one cert");
8540Sstevel@tonic-gate #endif
8550Sstevel@tonic-gate 	}
8560Sstevel@tonic-gate #ifdef CRYPTO_MDEBUG
8570Sstevel@tonic-gate 	CRYPTO_pop_info();
8580Sstevel@tonic-gate #endif
8590Sstevel@tonic-gate 	if(ret) ERR_clear_error();
8600Sstevel@tonic-gate 	return ret;
8610Sstevel@tonic-gate }
8620Sstevel@tonic-gate 
8630Sstevel@tonic-gate /* Generalised attribute print: handle PKCS#8 and bag attributes */
8640Sstevel@tonic-gate 
print_attribs(BIO * out,STACK_OF (X509_ATTRIBUTE)* attrlst,const char * name)865*2139Sjp161948 int print_attribs (BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst,const char *name)
8660Sstevel@tonic-gate {
8670Sstevel@tonic-gate 	X509_ATTRIBUTE *attr;
8680Sstevel@tonic-gate 	ASN1_TYPE *av;
8690Sstevel@tonic-gate 	char *value;
8700Sstevel@tonic-gate 	int i, attr_nid;
8710Sstevel@tonic-gate 	if(!attrlst) {
8720Sstevel@tonic-gate 		BIO_printf(out, "%s: <No Attributes>\n", name);
8730Sstevel@tonic-gate 		return 1;
8740Sstevel@tonic-gate 	}
8750Sstevel@tonic-gate 	if(!sk_X509_ATTRIBUTE_num(attrlst)) {
8760Sstevel@tonic-gate 		BIO_printf(out, "%s: <Empty Attributes>\n", name);
8770Sstevel@tonic-gate 		return 1;
8780Sstevel@tonic-gate 	}
8790Sstevel@tonic-gate 	BIO_printf(out, "%s\n", name);
8800Sstevel@tonic-gate 	for(i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) {
8810Sstevel@tonic-gate 		attr = sk_X509_ATTRIBUTE_value(attrlst, i);
8820Sstevel@tonic-gate 		attr_nid = OBJ_obj2nid(attr->object);
8830Sstevel@tonic-gate 		BIO_printf(out, "    ");
8840Sstevel@tonic-gate 		if(attr_nid == NID_undef) {
8850Sstevel@tonic-gate 			i2a_ASN1_OBJECT (out, attr->object);
8860Sstevel@tonic-gate 			BIO_printf(out, ": ");
8870Sstevel@tonic-gate 		} else BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid));
8880Sstevel@tonic-gate 
8890Sstevel@tonic-gate 		if(sk_ASN1_TYPE_num(attr->value.set)) {
8900Sstevel@tonic-gate 			av = sk_ASN1_TYPE_value(attr->value.set, 0);
8910Sstevel@tonic-gate 			switch(av->type) {
8920Sstevel@tonic-gate 				case V_ASN1_BMPSTRING:
8930Sstevel@tonic-gate         			value = uni2asc(av->value.bmpstring->data,
8940Sstevel@tonic-gate                                 	       av->value.bmpstring->length);
8950Sstevel@tonic-gate 				BIO_printf(out, "%s\n", value);
8960Sstevel@tonic-gate 				OPENSSL_free(value);
8970Sstevel@tonic-gate 				break;
8980Sstevel@tonic-gate 
8990Sstevel@tonic-gate 				case V_ASN1_OCTET_STRING:
9000Sstevel@tonic-gate 				hex_prin(out, av->value.octet_string->data,
9010Sstevel@tonic-gate 					av->value.octet_string->length);
9020Sstevel@tonic-gate 				BIO_printf(out, "\n");
9030Sstevel@tonic-gate 				break;
9040Sstevel@tonic-gate 
9050Sstevel@tonic-gate 				case V_ASN1_BIT_STRING:
9060Sstevel@tonic-gate 				hex_prin(out, av->value.bit_string->data,
9070Sstevel@tonic-gate 					av->value.bit_string->length);
9080Sstevel@tonic-gate 				BIO_printf(out, "\n");
9090Sstevel@tonic-gate 				break;
9100Sstevel@tonic-gate 
9110Sstevel@tonic-gate 				default:
9120Sstevel@tonic-gate 					BIO_printf(out, "<Unsupported tag %d>\n", av->type);
9130Sstevel@tonic-gate 				break;
9140Sstevel@tonic-gate 			}
9150Sstevel@tonic-gate 		} else BIO_printf(out, "<No Values>\n");
9160Sstevel@tonic-gate 	}
9170Sstevel@tonic-gate 	return 1;
9180Sstevel@tonic-gate }
9190Sstevel@tonic-gate 
hex_prin(BIO * out,unsigned char * buf,int len)9200Sstevel@tonic-gate void hex_prin(BIO *out, unsigned char *buf, int len)
9210Sstevel@tonic-gate {
9220Sstevel@tonic-gate 	int i;
9230Sstevel@tonic-gate 	for (i = 0; i < len; i++) BIO_printf (out, "%02X ", buf[i]);
9240Sstevel@tonic-gate }
9250Sstevel@tonic-gate 
9260Sstevel@tonic-gate #endif
927