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