155714Skris/* pkcs12.c */
2296465Sdelphij/*
3296465Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4160814Ssimon * project.
555714Skris */
655714Skris/* ====================================================================
7162911Ssimon * Copyright (c) 1999-2006 The OpenSSL Project.  All rights reserved.
855714Skris *
955714Skris * Redistribution and use in source and binary forms, with or without
1055714Skris * modification, are permitted provided that the following conditions
1155714Skris * are met:
1255714Skris *
1355714Skris * 1. Redistributions of source code must retain the above copyright
14296465Sdelphij *    notice, this list of conditions and the following disclaimer.
1555714Skris *
1655714Skris * 2. Redistributions in binary form must reproduce the above copyright
1755714Skris *    notice, this list of conditions and the following disclaimer in
1855714Skris *    the documentation and/or other materials provided with the
1955714Skris *    distribution.
2055714Skris *
2155714Skris * 3. All advertising materials mentioning features or use of this
2255714Skris *    software must display the following acknowledgment:
2355714Skris *    "This product includes software developed by the OpenSSL Project
2455714Skris *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2555714Skris *
2655714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2755714Skris *    endorse or promote products derived from this software without
2855714Skris *    prior written permission. For written permission, please contact
2955714Skris *    licensing@OpenSSL.org.
3055714Skris *
3155714Skris * 5. Products derived from this software may not be called "OpenSSL"
3255714Skris *    nor may "OpenSSL" appear in their names without prior written
3355714Skris *    permission of the OpenSSL Project.
3455714Skris *
3555714Skris * 6. Redistributions of any form whatsoever must retain the following
3655714Skris *    acknowledgment:
3755714Skris *    "This product includes software developed by the OpenSSL Project
3855714Skris *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3955714Skris *
4055714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4155714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4255714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4355714Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4455714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4555714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4655714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4755714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4955714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
5055714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
5155714Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
5255714Skris * ====================================================================
5355714Skris *
5455714Skris * This product includes cryptographic software written by Eric Young
5555714Skris * (eay@cryptsoft.com).  This product includes software written by Tim
5655714Skris * Hudson (tjh@cryptsoft.com).
5755714Skris *
5855714Skris */
5955714Skris
60160814Ssimon#include <openssl/opensslconf.h>
61160814Ssimon#if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_SHA1)
62160814Ssimon
63296465Sdelphij# include <stdio.h>
64296465Sdelphij# include <stdlib.h>
65296465Sdelphij# include <string.h>
66296465Sdelphij# include "apps.h"
67296465Sdelphij# include <openssl/crypto.h>
68296465Sdelphij# include <openssl/err.h>
69296465Sdelphij# include <openssl/pem.h>
70296465Sdelphij# include <openssl/pkcs12.h>
7155714Skris
72296465Sdelphij# ifdef OPENSSL_SYS_NETWARE
73205128Ssimon/* Rename these functions to avoid name clashes on NetWare OS */
74296465Sdelphij#  define uni2asc OPENSSL_uni2asc
75296465Sdelphij#  define asc2uni OPENSSL_asc2uni
76296465Sdelphij# endif
77205128Ssimon
78296465Sdelphij# define PROG pkcs12_main
7955714Skris
80109998Smarkmconst EVP_CIPHER *enc;
8155714Skris
82296465Sdelphij# define NOKEYS          0x1
83296465Sdelphij# define NOCERTS         0x2
84296465Sdelphij# define INFO            0x4
85296465Sdelphij# define CLCERTS         0x8
86296465Sdelphij# define CACERTS         0x10
8755714Skris
88296465Sdelphijint get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **chain);
89296465Sdelphijint dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen,
90296465Sdelphij                        int options, char *pempass);
91296465Sdelphijint dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags,
92296465Sdelphij                          char *pass, int passlen, int options,
93296465Sdelphij                          char *pempass);
94296465Sdelphijint dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bags, char *pass,
95296465Sdelphij                         int passlen, int options, char *pempass);
96296465Sdelphijint print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst,
97296465Sdelphij                  const char *name);
9855714Skrisvoid hex_prin(BIO *out, unsigned char *buf, int len);
9955714Skrisint alg_print(BIO *x, X509_ALGOR *alg);
10055714Skrisint cert_load(BIO *in, STACK_OF(X509) *sk);
10159191Skris
10259191Skrisint MAIN(int, char **);
10359191Skris
10455714Skrisint MAIN(int argc, char **argv)
10555714Skris{
106109998Smarkm    ENGINE *e = NULL;
107296465Sdelphij    char *infile = NULL, *outfile = NULL, *keyname = NULL;
108296465Sdelphij    char *certfile = NULL;
109296465Sdelphij    BIO *in = NULL, *out = NULL;
11055714Skris    char **args;
11155714Skris    char *name = NULL;
112109998Smarkm    char *csp_name = NULL;
113194206Ssimon    int add_lmk = 0;
11455714Skris    PKCS12 *p12 = NULL;
11555714Skris    char pass[50], macpass[50];
11655714Skris    int export_cert = 0;
11755714Skris    int options = 0;
11855714Skris    int chain = 0;
11955714Skris    int badarg = 0;
12055714Skris    int iter = PKCS12_DEFAULT_ITER;
12159191Skris    int maciter = PKCS12_DEFAULT_ITER;
12255714Skris    int twopass = 0;
12355714Skris    int keytype = 0;
124194206Ssimon    int cert_pbe;
12559191Skris    int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
12655714Skris    int ret = 1;
12755714Skris    int macver = 1;
12855714Skris    int noprompt = 0;
12955714Skris    STACK *canames = NULL;
13055714Skris    char *cpass = NULL, *mpass = NULL;
13159191Skris    char *passargin = NULL, *passargout = NULL, *passarg = NULL;
13259191Skris    char *passin = NULL, *passout = NULL;
13359191Skris    char *inrand = NULL;
13468651Skris    char *CApath = NULL, *CAfile = NULL;
135296465Sdelphij# ifndef OPENSSL_NO_ENGINE
136296465Sdelphij    char *engine = NULL;
137296465Sdelphij# endif
13855714Skris
13955714Skris    apps_startup();
14055714Skris
141296465Sdelphij# ifdef OPENSSL_FIPS
142194206Ssimon    if (FIPS_mode())
143296465Sdelphij        cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
144194206Ssimon    else
145296465Sdelphij# endif
146296465Sdelphij        cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
147194206Ssimon
14855714Skris    enc = EVP_des_ede3_cbc();
149296465Sdelphij    if (bio_err == NULL)
150296465Sdelphij        bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
15155714Skris
152296465Sdelphij    if (!load_config(bio_err, NULL))
153296465Sdelphij        goto end;
154109998Smarkm
15555714Skris    args = argv + 1;
15655714Skris
15755714Skris    while (*args) {
158296465Sdelphij        if (*args[0] == '-') {
159296465Sdelphij            if (!strcmp(*args, "-nokeys"))
160296465Sdelphij                options |= NOKEYS;
161296465Sdelphij            else if (!strcmp(*args, "-keyex"))
162296465Sdelphij                keytype = KEY_EX;
163296465Sdelphij            else if (!strcmp(*args, "-keysig"))
164296465Sdelphij                keytype = KEY_SIG;
165296465Sdelphij            else if (!strcmp(*args, "-nocerts"))
166296465Sdelphij                options |= NOCERTS;
167296465Sdelphij            else if (!strcmp(*args, "-clcerts"))
168296465Sdelphij                options |= CLCERTS;
169296465Sdelphij            else if (!strcmp(*args, "-cacerts"))
170296465Sdelphij                options |= CACERTS;
171296465Sdelphij            else if (!strcmp(*args, "-noout"))
172296465Sdelphij                options |= (NOKEYS | NOCERTS);
173296465Sdelphij            else if (!strcmp(*args, "-info"))
174296465Sdelphij                options |= INFO;
175296465Sdelphij            else if (!strcmp(*args, "-chain"))
176296465Sdelphij                chain = 1;
177296465Sdelphij            else if (!strcmp(*args, "-twopass"))
178296465Sdelphij                twopass = 1;
179296465Sdelphij            else if (!strcmp(*args, "-nomacver"))
180296465Sdelphij                macver = 0;
181296465Sdelphij            else if (!strcmp(*args, "-descert"))
182296465Sdelphij                cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
183296465Sdelphij            else if (!strcmp(*args, "-export"))
184296465Sdelphij                export_cert = 1;
185296465Sdelphij            else if (!strcmp(*args, "-des"))
186296465Sdelphij                enc = EVP_des_cbc();
187296465Sdelphij            else if (!strcmp(*args, "-des3"))
188296465Sdelphij                enc = EVP_des_ede3_cbc();
189296465Sdelphij# ifndef OPENSSL_NO_IDEA
190296465Sdelphij            else if (!strcmp(*args, "-idea"))
191296465Sdelphij                enc = EVP_idea_cbc();
192296465Sdelphij# endif
193296465Sdelphij# ifndef OPENSSL_NO_SEED
194296465Sdelphij            else if (!strcmp(*args, "-seed"))
195296465Sdelphij                enc = EVP_seed_cbc();
196296465Sdelphij# endif
197296465Sdelphij# ifndef OPENSSL_NO_AES
198296465Sdelphij            else if (!strcmp(*args, "-aes128"))
199296465Sdelphij                enc = EVP_aes_128_cbc();
200296465Sdelphij            else if (!strcmp(*args, "-aes192"))
201296465Sdelphij                enc = EVP_aes_192_cbc();
202296465Sdelphij            else if (!strcmp(*args, "-aes256"))
203296465Sdelphij                enc = EVP_aes_256_cbc();
204296465Sdelphij# endif
205296465Sdelphij# ifndef OPENSSL_NO_CAMELLIA
206296465Sdelphij            else if (!strcmp(*args, "-camellia128"))
207296465Sdelphij                enc = EVP_camellia_128_cbc();
208296465Sdelphij            else if (!strcmp(*args, "-camellia192"))
209296465Sdelphij                enc = EVP_camellia_192_cbc();
210296465Sdelphij            else if (!strcmp(*args, "-camellia256"))
211296465Sdelphij                enc = EVP_camellia_256_cbc();
212296465Sdelphij# endif
213296465Sdelphij            else if (!strcmp(*args, "-noiter"))
214296465Sdelphij                iter = 1;
215296465Sdelphij            else if (!strcmp(*args, "-maciter"))
216296465Sdelphij                maciter = PKCS12_DEFAULT_ITER;
217296465Sdelphij            else if (!strcmp(*args, "-nomaciter"))
218296465Sdelphij                maciter = 1;
219296465Sdelphij            else if (!strcmp(*args, "-nomac"))
220296465Sdelphij                maciter = -1;
221296465Sdelphij            else if (!strcmp(*args, "-nodes"))
222296465Sdelphij                enc = NULL;
223296465Sdelphij            else if (!strcmp(*args, "-certpbe")) {
224296465Sdelphij                if (args[1]) {
225296465Sdelphij                    args++;
226296465Sdelphij                    if (!strcmp(*args, "NONE"))
227296465Sdelphij                        cert_pbe = -1;
228296465Sdelphij                    else
229296465Sdelphij                        cert_pbe = OBJ_txt2nid(*args);
230296465Sdelphij                    if (cert_pbe == NID_undef) {
231296465Sdelphij                        BIO_printf(bio_err,
232296465Sdelphij                                   "Unknown PBE algorithm %s\n", *args);
233296465Sdelphij                        badarg = 1;
234296465Sdelphij                    }
235296465Sdelphij                } else
236296465Sdelphij                    badarg = 1;
237296465Sdelphij            } else if (!strcmp(*args, "-keypbe")) {
238296465Sdelphij                if (args[1]) {
239296465Sdelphij                    args++;
240296465Sdelphij                    if (!strcmp(*args, "NONE"))
241296465Sdelphij                        key_pbe = -1;
242296465Sdelphij                    else
243296465Sdelphij                        key_pbe = OBJ_txt2nid(*args);
244296465Sdelphij                    if (key_pbe == NID_undef) {
245296465Sdelphij                        BIO_printf(bio_err,
246296465Sdelphij                                   "Unknown PBE algorithm %s\n", *args);
247296465Sdelphij                        badarg = 1;
248296465Sdelphij                    }
249296465Sdelphij                } else
250296465Sdelphij                    badarg = 1;
251296465Sdelphij            } else if (!strcmp(*args, "-rand")) {
252296465Sdelphij                if (args[1]) {
253296465Sdelphij                    args++;
254296465Sdelphij                    inrand = *args;
255296465Sdelphij                } else
256296465Sdelphij                    badarg = 1;
257296465Sdelphij            } else if (!strcmp(*args, "-inkey")) {
258296465Sdelphij                if (args[1]) {
259296465Sdelphij                    args++;
260296465Sdelphij                    keyname = *args;
261296465Sdelphij                } else
262296465Sdelphij                    badarg = 1;
263296465Sdelphij            } else if (!strcmp(*args, "-certfile")) {
264296465Sdelphij                if (args[1]) {
265296465Sdelphij                    args++;
266296465Sdelphij                    certfile = *args;
267296465Sdelphij                } else
268296465Sdelphij                    badarg = 1;
269296465Sdelphij            } else if (!strcmp(*args, "-name")) {
270296465Sdelphij                if (args[1]) {
271296465Sdelphij                    args++;
272296465Sdelphij                    name = *args;
273296465Sdelphij                } else
274296465Sdelphij                    badarg = 1;
275296465Sdelphij            } else if (!strcmp(*args, "-LMK"))
276296465Sdelphij                add_lmk = 1;
277296465Sdelphij            else if (!strcmp(*args, "-CSP")) {
278296465Sdelphij                if (args[1]) {
279296465Sdelphij                    args++;
280296465Sdelphij                    csp_name = *args;
281296465Sdelphij                } else
282296465Sdelphij                    badarg = 1;
283296465Sdelphij            } else if (!strcmp(*args, "-caname")) {
284296465Sdelphij                if (args[1]) {
285296465Sdelphij                    args++;
286296465Sdelphij                    if (!canames)
287296465Sdelphij                        canames = sk_new_null();
288296465Sdelphij                    sk_push(canames, *args);
289296465Sdelphij                } else
290296465Sdelphij                    badarg = 1;
291296465Sdelphij            } else if (!strcmp(*args, "-in")) {
292296465Sdelphij                if (args[1]) {
293296465Sdelphij                    args++;
294296465Sdelphij                    infile = *args;
295296465Sdelphij                } else
296296465Sdelphij                    badarg = 1;
297296465Sdelphij            } else if (!strcmp(*args, "-out")) {
298296465Sdelphij                if (args[1]) {
299296465Sdelphij                    args++;
300296465Sdelphij                    outfile = *args;
301296465Sdelphij                } else
302296465Sdelphij                    badarg = 1;
303296465Sdelphij            } else if (!strcmp(*args, "-passin")) {
304296465Sdelphij                if (args[1]) {
305296465Sdelphij                    args++;
306296465Sdelphij                    passargin = *args;
307296465Sdelphij                } else
308296465Sdelphij                    badarg = 1;
309296465Sdelphij            } else if (!strcmp(*args, "-passout")) {
310296465Sdelphij                if (args[1]) {
311296465Sdelphij                    args++;
312296465Sdelphij                    passargout = *args;
313296465Sdelphij                } else
314296465Sdelphij                    badarg = 1;
315296465Sdelphij            } else if (!strcmp(*args, "-password")) {
316296465Sdelphij                if (args[1]) {
317296465Sdelphij                    args++;
318296465Sdelphij                    passarg = *args;
319296465Sdelphij                    noprompt = 1;
320296465Sdelphij                } else
321296465Sdelphij                    badarg = 1;
322296465Sdelphij            } else if (!strcmp(*args, "-CApath")) {
323296465Sdelphij                if (args[1]) {
324296465Sdelphij                    args++;
325296465Sdelphij                    CApath = *args;
326296465Sdelphij                } else
327296465Sdelphij                    badarg = 1;
328296465Sdelphij            } else if (!strcmp(*args, "-CAfile")) {
329296465Sdelphij                if (args[1]) {
330296465Sdelphij                    args++;
331296465Sdelphij                    CAfile = *args;
332296465Sdelphij                } else
333296465Sdelphij                    badarg = 1;
334296465Sdelphij# ifndef OPENSSL_NO_ENGINE
335296465Sdelphij            } else if (!strcmp(*args, "-engine")) {
336296465Sdelphij                if (args[1]) {
337296465Sdelphij                    args++;
338296465Sdelphij                    engine = *args;
339296465Sdelphij                } else
340296465Sdelphij                    badarg = 1;
341296465Sdelphij# endif
342296465Sdelphij            } else
343296465Sdelphij                badarg = 1;
34455714Skris
345296465Sdelphij        } else
346296465Sdelphij            badarg = 1;
347296465Sdelphij        args++;
34855714Skris    }
34955714Skris
35055714Skris    if (badarg) {
351296465Sdelphij        BIO_printf(bio_err, "Usage: pkcs12 [options]\n");
352296465Sdelphij        BIO_printf(bio_err, "where options are\n");
353296465Sdelphij        BIO_printf(bio_err, "-export       output PKCS12 file\n");
354296465Sdelphij        BIO_printf(bio_err, "-chain        add certificate chain\n");
355296465Sdelphij        BIO_printf(bio_err, "-inkey file   private key if not infile\n");
356296465Sdelphij        BIO_printf(bio_err, "-certfile f   add all certs in f\n");
357296465Sdelphij        BIO_printf(bio_err, "-CApath arg   - PEM format directory of CA's\n");
358296465Sdelphij        BIO_printf(bio_err, "-CAfile arg   - PEM format file of CA's\n");
359296465Sdelphij        BIO_printf(bio_err, "-name \"name\"  use name as friendly name\n");
360296465Sdelphij        BIO_printf(bio_err,
361296465Sdelphij                   "-caname \"nm\"  use nm as CA friendly name (can be used more than once).\n");
362296465Sdelphij        BIO_printf(bio_err, "-in  infile   input filename\n");
363296465Sdelphij        BIO_printf(bio_err, "-out outfile  output filename\n");
364296465Sdelphij        BIO_printf(bio_err,
365296465Sdelphij                   "-noout        don't output anything, just verify.\n");
366296465Sdelphij        BIO_printf(bio_err, "-nomacver     don't verify MAC.\n");
367296465Sdelphij        BIO_printf(bio_err, "-nocerts      don't output certificates.\n");
368296465Sdelphij        BIO_printf(bio_err,
369296465Sdelphij                   "-clcerts      only output client certificates.\n");
370296465Sdelphij        BIO_printf(bio_err, "-cacerts      only output CA certificates.\n");
371296465Sdelphij        BIO_printf(bio_err, "-nokeys       don't output private keys.\n");
372296465Sdelphij        BIO_printf(bio_err,
373296465Sdelphij                   "-info         give info about PKCS#12 structure.\n");
374296465Sdelphij        BIO_printf(bio_err, "-des          encrypt private keys with DES\n");
375296465Sdelphij        BIO_printf(bio_err,
376296465Sdelphij                   "-des3         encrypt private keys with triple DES (default)\n");
377296465Sdelphij# ifndef OPENSSL_NO_IDEA
378296465Sdelphij        BIO_printf(bio_err, "-idea         encrypt private keys with idea\n");
379296465Sdelphij# endif
380296465Sdelphij# ifndef OPENSSL_NO_SEED
381296465Sdelphij        BIO_printf(bio_err, "-seed         encrypt private keys with seed\n");
382296465Sdelphij# endif
383296465Sdelphij# ifndef OPENSSL_NO_AES
384296465Sdelphij        BIO_printf(bio_err, "-aes128, -aes192, -aes256\n");
385296465Sdelphij        BIO_printf(bio_err,
386296465Sdelphij                   "              encrypt PEM output with cbc aes\n");
387296465Sdelphij# endif
388296465Sdelphij# ifndef OPENSSL_NO_CAMELLIA
389296465Sdelphij        BIO_printf(bio_err, "-camellia128, -camellia192, -camellia256\n");
390296465Sdelphij        BIO_printf(bio_err,
391296465Sdelphij                   "              encrypt PEM output with cbc camellia\n");
392296465Sdelphij# endif
393296465Sdelphij        BIO_printf(bio_err, "-nodes        don't encrypt private keys\n");
394296465Sdelphij        BIO_printf(bio_err, "-noiter       don't use encryption iteration\n");
395296465Sdelphij        BIO_printf(bio_err, "-maciter      use MAC iteration\n");
396296465Sdelphij        BIO_printf(bio_err,
397296465Sdelphij                   "-twopass      separate MAC, encryption passwords\n");
398296465Sdelphij        BIO_printf(bio_err,
399296465Sdelphij                   "-descert      encrypt PKCS#12 certificates with triple DES (default RC2-40)\n");
400296465Sdelphij        BIO_printf(bio_err,
401296465Sdelphij                   "-certpbe alg  specify certificate PBE algorithm (default RC2-40)\n");
402296465Sdelphij        BIO_printf(bio_err,
403296465Sdelphij                   "-keypbe alg   specify private key PBE algorithm (default 3DES)\n");
404296465Sdelphij        BIO_printf(bio_err, "-keyex        set MS key exchange type\n");
405296465Sdelphij        BIO_printf(bio_err, "-keysig       set MS key signature type\n");
406296465Sdelphij        BIO_printf(bio_err,
407296465Sdelphij                   "-password p   set import/export password source\n");
408296465Sdelphij        BIO_printf(bio_err, "-passin p     input file pass phrase source\n");
409296465Sdelphij        BIO_printf(bio_err, "-passout p    output file pass phrase source\n");
410296465Sdelphij# ifndef OPENSSL_NO_ENGINE
411296465Sdelphij        BIO_printf(bio_err,
412296465Sdelphij                   "-engine e     use engine e, possibly a hardware device.\n");
413296465Sdelphij# endif
414296465Sdelphij        BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR,
415296465Sdelphij                   LIST_SEPARATOR_CHAR);
416296465Sdelphij        BIO_printf(bio_err,
417296465Sdelphij                   "              load the file (or the files in the directory) into\n");
418296465Sdelphij        BIO_printf(bio_err, "              the random number generator\n");
419296465Sdelphij        BIO_printf(bio_err, "-CSP name     Microsoft CSP name\n");
420296465Sdelphij        BIO_printf(bio_err,
421296465Sdelphij                   "-LMK          Add local machine keyset attribute to private key\n");
422296465Sdelphij        goto end;
42355714Skris    }
424296465Sdelphij# ifndef OPENSSL_NO_ENGINE
425109998Smarkm    e = setup_engine(bio_err, engine, 0);
426296465Sdelphij# endif
427109998Smarkm
428296465Sdelphij    if (passarg) {
429296465Sdelphij        if (export_cert)
430296465Sdelphij            passargout = passarg;
431296465Sdelphij        else
432296465Sdelphij            passargin = passarg;
43359191Skris    }
43459191Skris
435296465Sdelphij    if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
436296465Sdelphij        BIO_printf(bio_err, "Error getting passwords\n");
437296465Sdelphij        goto end;
43859191Skris    }
43959191Skris
440296465Sdelphij    if (!cpass) {
441296465Sdelphij        if (export_cert)
442296465Sdelphij            cpass = passout;
443296465Sdelphij        else
444296465Sdelphij            cpass = passin;
44559191Skris    }
44659191Skris
447296465Sdelphij    if (cpass) {
448296465Sdelphij        mpass = cpass;
449296465Sdelphij        noprompt = 1;
45059191Skris    } else {
451296465Sdelphij        cpass = pass;
452296465Sdelphij        mpass = macpass;
45355714Skris    }
45455714Skris
455296465Sdelphij    if (export_cert || inrand) {
456296465Sdelphij        app_RAND_load_file(NULL, bio_err, (inrand != NULL));
45759191Skris        if (inrand != NULL)
458296465Sdelphij            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
459296465Sdelphij                       app_RAND_load_files(inrand));
46059191Skris    }
46155714Skris    ERR_load_crypto_strings();
46255714Skris
463296465Sdelphij# ifdef CRYPTO_MDEBUG
46459191Skris    CRYPTO_push_info("read files");
465296465Sdelphij# endif
46659191Skris
467296465Sdelphij    if (!infile)
468296465Sdelphij        in = BIO_new_fp(stdin, BIO_NOCLOSE);
469296465Sdelphij    else
470296465Sdelphij        in = BIO_new_file(infile, "rb");
47155714Skris    if (!in) {
472296465Sdelphij        BIO_printf(bio_err, "Error opening input file %s\n",
473296465Sdelphij                   infile ? infile : "<stdin>");
474296465Sdelphij        perror(infile);
475296465Sdelphij        goto end;
476296465Sdelphij    }
477296465Sdelphij# ifdef CRYPTO_MDEBUG
47859191Skris    CRYPTO_pop_info();
47959191Skris    CRYPTO_push_info("write files");
480296465Sdelphij# endif
48159191Skris
48268651Skris    if (!outfile) {
483296465Sdelphij        out = BIO_new_fp(stdout, BIO_NOCLOSE);
484296465Sdelphij# ifdef OPENSSL_SYS_VMS
485296465Sdelphij        {
486296465Sdelphij            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
487296465Sdelphij            out = BIO_push(tmpbio, out);
488296465Sdelphij        }
489296465Sdelphij# endif
490296465Sdelphij    } else
491296465Sdelphij        out = BIO_new_file(outfile, "wb");
49255714Skris    if (!out) {
493296465Sdelphij        BIO_printf(bio_err, "Error opening output file %s\n",
494296465Sdelphij                   outfile ? outfile : "<stdout>");
495296465Sdelphij        perror(outfile);
496296465Sdelphij        goto end;
49755714Skris    }
49855714Skris    if (twopass) {
499296465Sdelphij# ifdef CRYPTO_MDEBUG
500296465Sdelphij        CRYPTO_push_info("read MAC password");
501296465Sdelphij# endif
502296465Sdelphij        if (EVP_read_pw_string
503296465Sdelphij            (macpass, sizeof macpass, "Enter MAC Password:", export_cert)) {
504296465Sdelphij            BIO_printf(bio_err, "Can't read Password\n");
505296465Sdelphij            goto end;
506296465Sdelphij        }
507296465Sdelphij# ifdef CRYPTO_MDEBUG
508296465Sdelphij        CRYPTO_pop_info();
509296465Sdelphij# endif
51055714Skris    }
51155714Skris
51259191Skris    if (export_cert) {
513296465Sdelphij        EVP_PKEY *key = NULL;
514296465Sdelphij        X509 *ucert = NULL, *x = NULL;
515296465Sdelphij        STACK_OF(X509) *certs = NULL;
516296465Sdelphij        unsigned char *catmp = NULL;
517296465Sdelphij        int i;
51859191Skris
519296465Sdelphij        if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) {
520296465Sdelphij            BIO_printf(bio_err, "Nothing to do!\n");
521296465Sdelphij            goto export_end;
522296465Sdelphij        }
523160814Ssimon
524296465Sdelphij        if (options & NOCERTS)
525296465Sdelphij            chain = 0;
526160814Ssimon
527296465Sdelphij# ifdef CRYPTO_MDEBUG
528296465Sdelphij        CRYPTO_push_info("process -export_cert");
529296465Sdelphij        CRYPTO_push_info("reading private key");
530296465Sdelphij# endif
531296465Sdelphij        if (!(options & NOKEYS)) {
532296465Sdelphij            key = load_key(bio_err, keyname ? keyname : infile,
533296465Sdelphij                           FORMAT_PEM, 1, passin, e, "private key");
534296465Sdelphij            if (!key)
535296465Sdelphij                goto export_end;
536296465Sdelphij        }
537296465Sdelphij# ifdef CRYPTO_MDEBUG
538296465Sdelphij        CRYPTO_pop_info();
539296465Sdelphij        CRYPTO_push_info("reading certs from input");
540296465Sdelphij# endif
54155714Skris
542296465Sdelphij        /* Load in all certs in input file */
543296465Sdelphij        if (!(options & NOCERTS)) {
544296465Sdelphij            certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e,
545296465Sdelphij                               "certificates");
546296465Sdelphij            if (!certs)
547296465Sdelphij                goto export_end;
54855714Skris
549296465Sdelphij            if (key) {
550296465Sdelphij                /* Look for matching private key */
551296465Sdelphij                for (i = 0; i < sk_X509_num(certs); i++) {
552296465Sdelphij                    x = sk_X509_value(certs, i);
553296465Sdelphij                    if (X509_check_private_key(x, key)) {
554296465Sdelphij                        ucert = x;
555296465Sdelphij                        /* Zero keyid and alias */
556296465Sdelphij                        X509_keyid_set1(ucert, NULL, 0);
557296465Sdelphij                        X509_alias_set1(ucert, NULL, 0);
558296465Sdelphij                        /* Remove from list */
559296465Sdelphij                        (void)sk_X509_delete(certs, i);
560296465Sdelphij                        break;
561296465Sdelphij                    }
562296465Sdelphij                }
563296465Sdelphij                if (!ucert) {
564296465Sdelphij                    BIO_printf(bio_err,
565296465Sdelphij                               "No certificate matches private key\n");
566296465Sdelphij                    goto export_end;
567296465Sdelphij                }
568296465Sdelphij            }
56955714Skris
570296465Sdelphij        }
571296465Sdelphij# ifdef CRYPTO_MDEBUG
572296465Sdelphij        CRYPTO_pop_info();
573296465Sdelphij        CRYPTO_push_info("reading certs from input 2");
574296465Sdelphij# endif
57568651Skris
576296465Sdelphij        /* Add any more certificates asked for */
577296465Sdelphij        if (certfile) {
578296465Sdelphij            STACK_OF(X509) *morecerts = NULL;
579296465Sdelphij            if (!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM,
580296465Sdelphij                                         NULL, e,
581296465Sdelphij                                         "certificates from certfile")))
582296465Sdelphij                goto export_end;
583296465Sdelphij            while (sk_X509_num(morecerts) > 0)
584296465Sdelphij                sk_X509_push(certs, sk_X509_shift(morecerts));
585296465Sdelphij            sk_X509_free(morecerts);
586296465Sdelphij        }
587296465Sdelphij# ifdef CRYPTO_MDEBUG
588296465Sdelphij        CRYPTO_pop_info();
589296465Sdelphij        CRYPTO_push_info("reading certs from certfile");
590296465Sdelphij# endif
591160814Ssimon
592296465Sdelphij# ifdef CRYPTO_MDEBUG
593296465Sdelphij        CRYPTO_pop_info();
594296465Sdelphij        CRYPTO_push_info("building chain");
595296465Sdelphij# endif
59655714Skris
597296465Sdelphij        /* If chaining get chain from user cert */
598296465Sdelphij        if (chain) {
599296465Sdelphij            int vret;
600296465Sdelphij            STACK_OF(X509) *chain2;
601296465Sdelphij            X509_STORE *store = X509_STORE_new();
602296465Sdelphij            if (!store) {
603296465Sdelphij                BIO_printf(bio_err, "Memory allocation error\n");
604296465Sdelphij                goto export_end;
605296465Sdelphij            }
606296465Sdelphij            if (!X509_STORE_load_locations(store, CAfile, CApath))
607296465Sdelphij                X509_STORE_set_default_paths(store);
60855714Skris
609296465Sdelphij            vret = get_cert_chain(ucert, store, &chain2);
610296465Sdelphij            X509_STORE_free(store);
611160814Ssimon
612296465Sdelphij            if (!vret) {
613296465Sdelphij                /* Exclude verified certificate */
614296465Sdelphij                for (i = 1; i < sk_X509_num(chain2); i++)
615296465Sdelphij                    sk_X509_push(certs, sk_X509_value(chain2, i));
616296465Sdelphij                /* Free first certificate */
617296465Sdelphij                X509_free(sk_X509_value(chain2, 0));
618296465Sdelphij                sk_X509_free(chain2);
619296465Sdelphij            } else {
620296465Sdelphij                if (vret >= 0)
621296465Sdelphij                    BIO_printf(bio_err, "Error %s getting chain.\n",
622296465Sdelphij                               X509_verify_cert_error_string(vret));
623296465Sdelphij                else
624296465Sdelphij                    ERR_print_errors(bio_err);
625296465Sdelphij                goto export_end;
626296465Sdelphij            }
627296465Sdelphij        }
62868651Skris
629296465Sdelphij        /* Add any CA names */
63068651Skris
631296465Sdelphij        for (i = 0; i < sk_num(canames); i++) {
632296465Sdelphij            catmp = (unsigned char *)sk_value(canames, i);
633296465Sdelphij            X509_alias_set1(sk_X509_value(certs, i), catmp, -1);
634296465Sdelphij        }
63568651Skris
636296465Sdelphij        if (csp_name && key)
637296465Sdelphij            EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name,
638296465Sdelphij                                      MBSTRING_ASC, (unsigned char *)csp_name,
639296465Sdelphij                                      -1);
64055714Skris
641296465Sdelphij        if (add_lmk && key)
642296465Sdelphij            EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1);
64368651Skris
644296465Sdelphij# ifdef CRYPTO_MDEBUG
645296465Sdelphij        CRYPTO_pop_info();
646296465Sdelphij        CRYPTO_push_info("reading password");
647296465Sdelphij# endif
64855714Skris
649296465Sdelphij        if (!noprompt &&
650296465Sdelphij            EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:",
651296465Sdelphij                               1)) {
652296465Sdelphij            BIO_printf(bio_err, "Can't read Password\n");
653296465Sdelphij            goto export_end;
654296465Sdelphij        }
655296465Sdelphij        if (!twopass)
656296465Sdelphij            BUF_strlcpy(macpass, pass, sizeof macpass);
657160814Ssimon
658296465Sdelphij# ifdef CRYPTO_MDEBUG
659296465Sdelphij        CRYPTO_pop_info();
660296465Sdelphij        CRYPTO_push_info("creating PKCS#12 structure");
661296465Sdelphij# endif
662194206Ssimon
663296465Sdelphij        p12 = PKCS12_create(cpass, name, key, ucert, certs,
664296465Sdelphij                            key_pbe, cert_pbe, iter, -1, keytype);
66568651Skris
666296465Sdelphij        if (!p12) {
667296465Sdelphij            ERR_print_errors(bio_err);
668296465Sdelphij            goto export_end;
669296465Sdelphij        }
67055714Skris
671296465Sdelphij        if (maciter != -1)
672296465Sdelphij            PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, NULL);
67368651Skris
674296465Sdelphij# ifdef CRYPTO_MDEBUG
675296465Sdelphij        CRYPTO_pop_info();
676296465Sdelphij        CRYPTO_push_info("writing pkcs12");
677296465Sdelphij# endif
67868651Skris
679296465Sdelphij        i2d_PKCS12_bio(out, p12);
68068651Skris
681296465Sdelphij        ret = 0;
68255714Skris
683296465Sdelphij export_end:
684296465Sdelphij# ifdef CRYPTO_MDEBUG
685296465Sdelphij        CRYPTO_pop_info();
686296465Sdelphij        CRYPTO_pop_info();
687296465Sdelphij        CRYPTO_push_info("process -export_cert: freeing");
688296465Sdelphij# endif
68968651Skris
690296465Sdelphij        if (key)
691296465Sdelphij            EVP_PKEY_free(key);
692296465Sdelphij        if (certs)
693296465Sdelphij            sk_X509_pop_free(certs, X509_free);
694296465Sdelphij        if (ucert)
695296465Sdelphij            X509_free(ucert);
69655714Skris
697296465Sdelphij# ifdef CRYPTO_MDEBUG
698296465Sdelphij        CRYPTO_pop_info();
699296465Sdelphij# endif
700296465Sdelphij        goto end;
70159191Skris
70255714Skris    }
70355714Skris
704296465Sdelphij    if (!(p12 = d2i_PKCS12_bio(in, NULL))) {
705296465Sdelphij        ERR_print_errors(bio_err);
706296465Sdelphij        goto end;
70755714Skris    }
708296465Sdelphij# ifdef CRYPTO_MDEBUG
70959191Skris    CRYPTO_push_info("read import password");
710296465Sdelphij# endif
711296465Sdelphij    if (!noprompt
712296465Sdelphij        && EVP_read_pw_string(pass, sizeof pass, "Enter Import Password:",
713296465Sdelphij                              0)) {
714296465Sdelphij        BIO_printf(bio_err, "Can't read Password\n");
715296465Sdelphij        goto end;
71655714Skris    }
717296465Sdelphij# ifdef CRYPTO_MDEBUG
71859191Skris    CRYPTO_pop_info();
719296465Sdelphij# endif
72055714Skris
721296465Sdelphij    if (!twopass)
722296465Sdelphij        BUF_strlcpy(macpass, pass, sizeof macpass);
72355714Skris
724296465Sdelphij    if ((options & INFO) && p12->mac)
725296465Sdelphij        BIO_printf(bio_err, "MAC Iteration %ld\n",
726296465Sdelphij                   p12->mac->iter ? ASN1_INTEGER_get(p12->mac->iter) : 1);
727296465Sdelphij    if (macver) {
728296465Sdelphij# ifdef CRYPTO_MDEBUG
729296465Sdelphij        CRYPTO_push_info("verify MAC");
730296465Sdelphij# endif
731296465Sdelphij        /* If we enter empty password try no password first */
732296465Sdelphij        if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) {
733296465Sdelphij            /* If mac and crypto pass the same set it to NULL too */
734296465Sdelphij            if (!twopass)
735296465Sdelphij                cpass = NULL;
736296465Sdelphij        } else if (!PKCS12_verify_mac(p12, mpass, -1)) {
737296465Sdelphij            BIO_printf(bio_err, "Mac verify error: invalid password?\n");
738296465Sdelphij            ERR_print_errors(bio_err);
739296465Sdelphij            goto end;
740296465Sdelphij        }
741296465Sdelphij        BIO_printf(bio_err, "MAC verified OK\n");
742296465Sdelphij# ifdef CRYPTO_MDEBUG
743296465Sdelphij        CRYPTO_pop_info();
744296465Sdelphij# endif
74555714Skris    }
746296465Sdelphij# ifdef CRYPTO_MDEBUG
74759191Skris    CRYPTO_push_info("output keys and certificates");
748296465Sdelphij# endif
749296465Sdelphij    if (!dump_certs_keys_p12(out, p12, cpass, -1, options, passout)) {
750296465Sdelphij        BIO_printf(bio_err, "Error outputting keys and certificates\n");
751296465Sdelphij        ERR_print_errors(bio_err);
752296465Sdelphij        goto end;
75355714Skris    }
754296465Sdelphij# ifdef CRYPTO_MDEBUG
75559191Skris    CRYPTO_pop_info();
756296465Sdelphij# endif
75755714Skris    ret = 0;
75868651Skris end:
759296465Sdelphij    if (p12)
760296465Sdelphij        PKCS12_free(p12);
761296465Sdelphij    if (export_cert || inrand)
762296465Sdelphij        app_RAND_write_file(NULL, bio_err);
763296465Sdelphij# ifdef CRYPTO_MDEBUG
76459191Skris    CRYPTO_remove_all_info();
765296465Sdelphij# endif
76659191Skris    BIO_free(in);
76768651Skris    BIO_free_all(out);
768296465Sdelphij    if (canames)
769296465Sdelphij        sk_free(canames);
770296465Sdelphij    if (passin)
771296465Sdelphij        OPENSSL_free(passin);
772296465Sdelphij    if (passout)
773296465Sdelphij        OPENSSL_free(passout);
774109998Smarkm    apps_shutdown();
775109998Smarkm    OPENSSL_EXIT(ret);
77655714Skris}
77755714Skris
778296465Sdelphijint dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass,
779296465Sdelphij                        int passlen, int options, char *pempass)
78055714Skris{
781296465Sdelphij    STACK_OF(PKCS7) *asafes = NULL;
782296465Sdelphij    STACK_OF(PKCS12_SAFEBAG) *bags;
783296465Sdelphij    int i, bagnid;
784296465Sdelphij    int ret = 0;
785296465Sdelphij    PKCS7 *p7;
78668651Skris
787296465Sdelphij    if (!(asafes = PKCS12_unpack_authsafes(p12)))
788296465Sdelphij        return 0;
789296465Sdelphij    for (i = 0; i < sk_PKCS7_num(asafes); i++) {
790296465Sdelphij        p7 = sk_PKCS7_value(asafes, i);
791296465Sdelphij        bagnid = OBJ_obj2nid(p7->type);
792296465Sdelphij        if (bagnid == NID_pkcs7_data) {
793296465Sdelphij            bags = PKCS12_unpack_p7data(p7);
794296465Sdelphij            if (options & INFO)
795296465Sdelphij                BIO_printf(bio_err, "PKCS7 Data\n");
796296465Sdelphij        } else if (bagnid == NID_pkcs7_encrypted) {
797296465Sdelphij            if (options & INFO) {
798296465Sdelphij                BIO_printf(bio_err, "PKCS7 Encrypted data: ");
799296465Sdelphij                alg_print(bio_err, p7->d.encrypted->enc_data->algorithm);
800296465Sdelphij            }
801296465Sdelphij            bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
802296465Sdelphij        } else
803296465Sdelphij            continue;
804296465Sdelphij        if (!bags)
805296465Sdelphij            goto err;
806296465Sdelphij        if (!dump_certs_pkeys_bags(out, bags, pass, passlen,
807296465Sdelphij                                   options, pempass)) {
808296465Sdelphij            sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
809296465Sdelphij            goto err;
810296465Sdelphij        }
811296465Sdelphij        sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
812296465Sdelphij        bags = NULL;
813296465Sdelphij    }
814296465Sdelphij    ret = 1;
815160814Ssimon
816296465Sdelphij err:
817160814Ssimon
818296465Sdelphij    if (asafes)
819296465Sdelphij        sk_PKCS7_pop_free(asafes, PKCS7_free);
820296465Sdelphij    return ret;
82155714Skris}
82255714Skris
823296465Sdelphijint dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags,
824296465Sdelphij                          char *pass, int passlen, int options, char *pempass)
82555714Skris{
826296465Sdelphij    int i;
827296465Sdelphij    for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
828296465Sdelphij        if (!dump_certs_pkeys_bag(out,
829296465Sdelphij                                  sk_PKCS12_SAFEBAG_value(bags, i),
830296465Sdelphij                                  pass, passlen, options, pempass))
831296465Sdelphij            return 0;
832296465Sdelphij    }
833296465Sdelphij    return 1;
83455714Skris}
83555714Skris
836296465Sdelphijint dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bag, char *pass,
837296465Sdelphij                         int passlen, int options, char *pempass)
83855714Skris{
839296465Sdelphij    EVP_PKEY *pkey;
840296465Sdelphij    PKCS8_PRIV_KEY_INFO *p8;
841296465Sdelphij    X509 *x509;
84255714Skris
843296465Sdelphij    switch (M_PKCS12_bag_type(bag)) {
844296465Sdelphij    case NID_keyBag:
845296465Sdelphij        if (options & INFO)
846296465Sdelphij            BIO_printf(bio_err, "Key bag\n");
847296465Sdelphij        if (options & NOKEYS)
848296465Sdelphij            return 1;
849296465Sdelphij        print_attribs(out, bag->attrib, "Bag Attributes");
850296465Sdelphij        p8 = bag->value.keybag;
851296465Sdelphij        if (!(pkey = EVP_PKCS82PKEY(p8)))
852296465Sdelphij            return 0;
853296465Sdelphij        print_attribs(out, p8->attributes, "Key Attributes");
854296465Sdelphij        PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass);
855296465Sdelphij        EVP_PKEY_free(pkey);
856296465Sdelphij        break;
85755714Skris
858296465Sdelphij    case NID_pkcs8ShroudedKeyBag:
859296465Sdelphij        if (options & INFO) {
860296465Sdelphij            BIO_printf(bio_err, "Shrouded Keybag: ");
861296465Sdelphij            alg_print(bio_err, bag->value.shkeybag->algor);
862296465Sdelphij        }
863296465Sdelphij        if (options & NOKEYS)
864296465Sdelphij            return 1;
865296465Sdelphij        print_attribs(out, bag->attrib, "Bag Attributes");
866296465Sdelphij        if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen)))
867296465Sdelphij            return 0;
868296465Sdelphij        if (!(pkey = EVP_PKCS82PKEY(p8))) {
869296465Sdelphij            PKCS8_PRIV_KEY_INFO_free(p8);
870296465Sdelphij            return 0;
871296465Sdelphij        }
872296465Sdelphij        print_attribs(out, p8->attributes, "Key Attributes");
873296465Sdelphij        PKCS8_PRIV_KEY_INFO_free(p8);
874296465Sdelphij        PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass);
875296465Sdelphij        EVP_PKEY_free(pkey);
876296465Sdelphij        break;
87755714Skris
878296465Sdelphij    case NID_certBag:
879296465Sdelphij        if (options & INFO)
880296465Sdelphij            BIO_printf(bio_err, "Certificate bag\n");
881296465Sdelphij        if (options & NOCERTS)
882296465Sdelphij            return 1;
883296465Sdelphij        if (PKCS12_get_attr(bag, NID_localKeyID)) {
884296465Sdelphij            if (options & CACERTS)
885296465Sdelphij                return 1;
886296465Sdelphij        } else if (options & CLCERTS)
887296465Sdelphij            return 1;
888296465Sdelphij        print_attribs(out, bag->attrib, "Bag Attributes");
889296465Sdelphij        if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate)
890296465Sdelphij            return 1;
891296465Sdelphij        if (!(x509 = PKCS12_certbag2x509(bag)))
892296465Sdelphij            return 0;
893296465Sdelphij        dump_cert_text(out, x509);
894296465Sdelphij        PEM_write_bio_X509(out, x509);
895296465Sdelphij        X509_free(x509);
896296465Sdelphij        break;
897296465Sdelphij
898296465Sdelphij    case NID_safeContentsBag:
899296465Sdelphij        if (options & INFO)
900296465Sdelphij            BIO_printf(bio_err, "Safe Contents bag\n");
901296465Sdelphij        print_attribs(out, bag->attrib, "Bag Attributes");
902296465Sdelphij        return dump_certs_pkeys_bags(out, bag->value.safes, pass,
903296465Sdelphij                                     passlen, options, pempass);
904296465Sdelphij
905296465Sdelphij    default:
906296465Sdelphij        BIO_printf(bio_err, "Warning unsupported bag type: ");
907296465Sdelphij        i2a_ASN1_OBJECT(bio_err, bag->type);
908296465Sdelphij        BIO_printf(bio_err, "\n");
909296465Sdelphij        return 1;
910296465Sdelphij        break;
911296465Sdelphij    }
912296465Sdelphij    return 1;
91355714Skris}
91455714Skris
91555714Skris/* Given a single certificate return a verified chain or NULL if error */
91655714Skris
91755714Skris/* Hope this is OK .... */
91855714Skris
919296465Sdelphijint get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **chain)
92055714Skris{
921296465Sdelphij    X509_STORE_CTX store_ctx;
922296465Sdelphij    STACK_OF(X509) *chn;
923296465Sdelphij    int i = 0;
92459191Skris
925296465Sdelphij    /*
926296465Sdelphij     * FIXME: Should really check the return status of X509_STORE_CTX_init
927296465Sdelphij     * for an error, but how that fits into the return value of this function
928296465Sdelphij     * is less obvious.
929296465Sdelphij     */
930296465Sdelphij    X509_STORE_CTX_init(&store_ctx, store, cert, NULL);
931296465Sdelphij    if (X509_verify_cert(&store_ctx) <= 0) {
932296465Sdelphij        i = X509_STORE_CTX_get_error(&store_ctx);
933296465Sdelphij        if (i == 0)
934296465Sdelphij            /*
935296465Sdelphij             * avoid returning 0 if X509_verify_cert() did not set an
936296465Sdelphij             * appropriate error value in the context
937296465Sdelphij             */
938296465Sdelphij            i = -1;
939296465Sdelphij        chn = NULL;
940296465Sdelphij        goto err;
941296465Sdelphij    } else
942296465Sdelphij        chn = X509_STORE_CTX_get1_chain(&store_ctx);
943296465Sdelphij err:
944296465Sdelphij    X509_STORE_CTX_cleanup(&store_ctx);
945296465Sdelphij    *chain = chn;
94655714Skris
947296465Sdelphij    return i;
948296465Sdelphij}
949296465Sdelphij
950296465Sdelphijint alg_print(BIO *x, X509_ALGOR *alg)
95155714Skris{
952296465Sdelphij    PBEPARAM *pbe;
953296465Sdelphij    const unsigned char *p;
954296465Sdelphij    p = alg->parameter->value.sequence->data;
955296465Sdelphij    pbe = d2i_PBEPARAM(NULL, &p, alg->parameter->value.sequence->length);
956296465Sdelphij    if (!pbe)
957296465Sdelphij        return 1;
958296465Sdelphij    BIO_printf(bio_err, "%s, Iteration %ld\n",
959296465Sdelphij               OBJ_nid2ln(OBJ_obj2nid(alg->algorithm)),
960296465Sdelphij               ASN1_INTEGER_get(pbe->iter));
961296465Sdelphij    PBEPARAM_free(pbe);
962296465Sdelphij    return 1;
96355714Skris}
96455714Skris
96555714Skris/* Load all certificates from a given file */
96655714Skris
96755714Skrisint cert_load(BIO *in, STACK_OF(X509) *sk)
96855714Skris{
969296465Sdelphij    int ret;
970296465Sdelphij    X509 *cert;
971296465Sdelphij    ret = 0;
972296465Sdelphij# ifdef CRYPTO_MDEBUG
973296465Sdelphij    CRYPTO_push_info("cert_load(): reading one cert");
974296465Sdelphij# endif
975296465Sdelphij    while ((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
976296465Sdelphij# ifdef CRYPTO_MDEBUG
977296465Sdelphij        CRYPTO_pop_info();
978296465Sdelphij# endif
979296465Sdelphij        ret = 1;
980296465Sdelphij        sk_X509_push(sk, cert);
981296465Sdelphij# ifdef CRYPTO_MDEBUG
982296465Sdelphij        CRYPTO_push_info("cert_load(): reading one cert");
983296465Sdelphij# endif
984296465Sdelphij    }
985296465Sdelphij# ifdef CRYPTO_MDEBUG
986296465Sdelphij    CRYPTO_pop_info();
987296465Sdelphij# endif
988296465Sdelphij    if (ret)
989296465Sdelphij        ERR_clear_error();
990296465Sdelphij    return ret;
99155714Skris}
99255714Skris
99355714Skris/* Generalised attribute print: handle PKCS#8 and bag attributes */
99455714Skris
995296465Sdelphijint print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst,
996296465Sdelphij                  const char *name)
99755714Skris{
998296465Sdelphij    X509_ATTRIBUTE *attr;
999296465Sdelphij    ASN1_TYPE *av;
1000296465Sdelphij    char *value;
1001296465Sdelphij    int i, attr_nid;
1002296465Sdelphij    if (!attrlst) {
1003296465Sdelphij        BIO_printf(out, "%s: <No Attributes>\n", name);
1004296465Sdelphij        return 1;
1005296465Sdelphij    }
1006296465Sdelphij    if (!sk_X509_ATTRIBUTE_num(attrlst)) {
1007296465Sdelphij        BIO_printf(out, "%s: <Empty Attributes>\n", name);
1008296465Sdelphij        return 1;
1009296465Sdelphij    }
1010296465Sdelphij    BIO_printf(out, "%s\n", name);
1011296465Sdelphij    for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) {
1012296465Sdelphij        attr = sk_X509_ATTRIBUTE_value(attrlst, i);
1013296465Sdelphij        attr_nid = OBJ_obj2nid(attr->object);
1014296465Sdelphij        BIO_printf(out, "    ");
1015296465Sdelphij        if (attr_nid == NID_undef) {
1016296465Sdelphij            i2a_ASN1_OBJECT(out, attr->object);
1017296465Sdelphij            BIO_printf(out, ": ");
1018296465Sdelphij        } else
1019296465Sdelphij            BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid));
102055714Skris
1021296465Sdelphij        if (sk_ASN1_TYPE_num(attr->value.set)) {
1022296465Sdelphij            av = sk_ASN1_TYPE_value(attr->value.set, 0);
1023296465Sdelphij            switch (av->type) {
1024296465Sdelphij            case V_ASN1_BMPSTRING:
1025296465Sdelphij                value = uni2asc(av->value.bmpstring->data,
1026296465Sdelphij                                av->value.bmpstring->length);
1027296465Sdelphij                BIO_printf(out, "%s\n", value);
1028296465Sdelphij                OPENSSL_free(value);
1029296465Sdelphij                break;
103055714Skris
1031296465Sdelphij            case V_ASN1_OCTET_STRING:
1032296465Sdelphij                hex_prin(out, av->value.octet_string->data,
1033296465Sdelphij                         av->value.octet_string->length);
1034296465Sdelphij                BIO_printf(out, "\n");
1035296465Sdelphij                break;
103655714Skris
1037296465Sdelphij            case V_ASN1_BIT_STRING:
1038296465Sdelphij                hex_prin(out, av->value.bit_string->data,
1039296465Sdelphij                         av->value.bit_string->length);
1040296465Sdelphij                BIO_printf(out, "\n");
1041296465Sdelphij                break;
104255714Skris
1043296465Sdelphij            default:
1044296465Sdelphij                BIO_printf(out, "<Unsupported tag %d>\n", av->type);
1045296465Sdelphij                break;
1046296465Sdelphij            }
1047296465Sdelphij        } else
1048296465Sdelphij            BIO_printf(out, "<No Values>\n");
1049296465Sdelphij    }
1050296465Sdelphij    return 1;
105155714Skris}
105255714Skris
105355714Skrisvoid hex_prin(BIO *out, unsigned char *buf, int len)
105455714Skris{
1055296465Sdelphij    int i;
1056296465Sdelphij    for (i = 0; i < len; i++)
1057296465Sdelphij        BIO_printf(out, "%02X ", buf[i]);
105855714Skris}
105955714Skris
106055714Skris#endif
1061