155714Skris/* pkcs12.c */
2296341Sdelphij/*
3296341Sdelphij * 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
14296341Sdelphij *    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
63296341Sdelphij# include <stdio.h>
64296341Sdelphij# include <stdlib.h>
65296341Sdelphij# include <string.h>
66296341Sdelphij# include "apps.h"
67296341Sdelphij# include <openssl/crypto.h>
68296341Sdelphij# include <openssl/err.h>
69296341Sdelphij# include <openssl/pem.h>
70296341Sdelphij# include <openssl/pkcs12.h>
7155714Skris
72296341Sdelphij# define PROG pkcs12_main
7355714Skris
74109998Smarkmconst EVP_CIPHER *enc;
7555714Skris
76296341Sdelphij# define NOKEYS          0x1
77296341Sdelphij# define NOCERTS         0x2
78296341Sdelphij# define INFO            0x4
79296341Sdelphij# define CLCERTS         0x8
80296341Sdelphij# define CACERTS         0x10
8155714Skris
82296341Sdelphijint get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **chain);
83296341Sdelphijint dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen,
84296341Sdelphij                        int options, char *pempass);
85296341Sdelphijint dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags,
86296341Sdelphij                          char *pass, int passlen, int options,
87296341Sdelphij                          char *pempass);
88296341Sdelphijint dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bags, char *pass,
89296341Sdelphij                         int passlen, int options, char *pempass);
90296341Sdelphijint print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst,
91296341Sdelphij                  const char *name);
9255714Skrisvoid hex_prin(BIO *out, unsigned char *buf, int len);
9355714Skrisint alg_print(BIO *x, X509_ALGOR *alg);
9455714Skrisint cert_load(BIO *in, STACK_OF(X509) *sk);
95238405Sjkimstatic int set_pbe(BIO *err, int *ppbe, const char *str);
9659191Skris
9759191Skrisint MAIN(int, char **);
9859191Skris
9955714Skrisint MAIN(int argc, char **argv)
10055714Skris{
101109998Smarkm    ENGINE *e = NULL;
102296341Sdelphij    char *infile = NULL, *outfile = NULL, *keyname = NULL;
103296341Sdelphij    char *certfile = NULL;
104296341Sdelphij    BIO *in = NULL, *out = NULL;
10555714Skris    char **args;
10655714Skris    char *name = NULL;
107109998Smarkm    char *csp_name = NULL;
108194206Ssimon    int add_lmk = 0;
10955714Skris    PKCS12 *p12 = NULL;
11055714Skris    char pass[50], macpass[50];
11155714Skris    int export_cert = 0;
11255714Skris    int options = 0;
11355714Skris    int chain = 0;
11455714Skris    int badarg = 0;
11555714Skris    int iter = PKCS12_DEFAULT_ITER;
11659191Skris    int maciter = PKCS12_DEFAULT_ITER;
11755714Skris    int twopass = 0;
11855714Skris    int keytype = 0;
119264331Sjkim    int cert_pbe;
12059191Skris    int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
12155714Skris    int ret = 1;
12255714Skris    int macver = 1;
12355714Skris    int noprompt = 0;
124238405Sjkim    STACK_OF(OPENSSL_STRING) *canames = NULL;
12555714Skris    char *cpass = NULL, *mpass = NULL;
12659191Skris    char *passargin = NULL, *passargout = NULL, *passarg = NULL;
12759191Skris    char *passin = NULL, *passout = NULL;
12859191Skris    char *inrand = NULL;
129238405Sjkim    char *macalg = NULL;
13068651Skris    char *CApath = NULL, *CAfile = NULL;
131296341Sdelphij# ifndef OPENSSL_NO_ENGINE
132296341Sdelphij    char *engine = NULL;
133296341Sdelphij# endif
13455714Skris
13555714Skris    apps_startup();
13655714Skris
137296341Sdelphij# ifdef OPENSSL_FIPS
138264331Sjkim    if (FIPS_mode())
139296341Sdelphij        cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
140264331Sjkim    else
141296341Sdelphij# endif
142296341Sdelphij        cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
143264331Sjkim
14455714Skris    enc = EVP_des_ede3_cbc();
145296341Sdelphij    if (bio_err == NULL)
146296341Sdelphij        bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
14755714Skris
148296341Sdelphij    if (!load_config(bio_err, NULL))
149296341Sdelphij        goto end;
150109998Smarkm
15155714Skris    args = argv + 1;
15255714Skris
15355714Skris    while (*args) {
154296341Sdelphij        if (*args[0] == '-') {
155296341Sdelphij            if (!strcmp(*args, "-nokeys"))
156296341Sdelphij                options |= NOKEYS;
157296341Sdelphij            else if (!strcmp(*args, "-keyex"))
158296341Sdelphij                keytype = KEY_EX;
159296341Sdelphij            else if (!strcmp(*args, "-keysig"))
160296341Sdelphij                keytype = KEY_SIG;
161296341Sdelphij            else if (!strcmp(*args, "-nocerts"))
162296341Sdelphij                options |= NOCERTS;
163296341Sdelphij            else if (!strcmp(*args, "-clcerts"))
164296341Sdelphij                options |= CLCERTS;
165296341Sdelphij            else if (!strcmp(*args, "-cacerts"))
166296341Sdelphij                options |= CACERTS;
167296341Sdelphij            else if (!strcmp(*args, "-noout"))
168296341Sdelphij                options |= (NOKEYS | NOCERTS);
169296341Sdelphij            else if (!strcmp(*args, "-info"))
170296341Sdelphij                options |= INFO;
171296341Sdelphij            else if (!strcmp(*args, "-chain"))
172296341Sdelphij                chain = 1;
173296341Sdelphij            else if (!strcmp(*args, "-twopass"))
174296341Sdelphij                twopass = 1;
175296341Sdelphij            else if (!strcmp(*args, "-nomacver"))
176296341Sdelphij                macver = 0;
177296341Sdelphij            else if (!strcmp(*args, "-descert"))
178296341Sdelphij                cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
179296341Sdelphij            else if (!strcmp(*args, "-export"))
180296341Sdelphij                export_cert = 1;
181296341Sdelphij            else if (!strcmp(*args, "-des"))
182296341Sdelphij                enc = EVP_des_cbc();
183296341Sdelphij            else if (!strcmp(*args, "-des3"))
184296341Sdelphij                enc = EVP_des_ede3_cbc();
185296341Sdelphij# ifndef OPENSSL_NO_IDEA
186296341Sdelphij            else if (!strcmp(*args, "-idea"))
187296341Sdelphij                enc = EVP_idea_cbc();
188296341Sdelphij# endif
189296341Sdelphij# ifndef OPENSSL_NO_SEED
190296341Sdelphij            else if (!strcmp(*args, "-seed"))
191296341Sdelphij                enc = EVP_seed_cbc();
192296341Sdelphij# endif
193296341Sdelphij# ifndef OPENSSL_NO_AES
194296341Sdelphij            else if (!strcmp(*args, "-aes128"))
195296341Sdelphij                enc = EVP_aes_128_cbc();
196296341Sdelphij            else if (!strcmp(*args, "-aes192"))
197296341Sdelphij                enc = EVP_aes_192_cbc();
198296341Sdelphij            else if (!strcmp(*args, "-aes256"))
199296341Sdelphij                enc = EVP_aes_256_cbc();
200296341Sdelphij# endif
201296341Sdelphij# ifndef OPENSSL_NO_CAMELLIA
202296341Sdelphij            else if (!strcmp(*args, "-camellia128"))
203296341Sdelphij                enc = EVP_camellia_128_cbc();
204296341Sdelphij            else if (!strcmp(*args, "-camellia192"))
205296341Sdelphij                enc = EVP_camellia_192_cbc();
206296341Sdelphij            else if (!strcmp(*args, "-camellia256"))
207296341Sdelphij                enc = EVP_camellia_256_cbc();
208296341Sdelphij# endif
209296341Sdelphij            else if (!strcmp(*args, "-noiter"))
210296341Sdelphij                iter = 1;
211296341Sdelphij            else if (!strcmp(*args, "-maciter"))
212296341Sdelphij                maciter = PKCS12_DEFAULT_ITER;
213296341Sdelphij            else if (!strcmp(*args, "-nomaciter"))
214296341Sdelphij                maciter = 1;
215296341Sdelphij            else if (!strcmp(*args, "-nomac"))
216296341Sdelphij                maciter = -1;
217296341Sdelphij            else if (!strcmp(*args, "-macalg"))
218296341Sdelphij                if (args[1]) {
219296341Sdelphij                    args++;
220296341Sdelphij                    macalg = *args;
221296341Sdelphij                } else
222296341Sdelphij                    badarg = 1;
223296341Sdelphij            else if (!strcmp(*args, "-nodes"))
224296341Sdelphij                enc = NULL;
225296341Sdelphij            else if (!strcmp(*args, "-certpbe")) {
226296341Sdelphij                if (!set_pbe(bio_err, &cert_pbe, *++args))
227296341Sdelphij                    badarg = 1;
228296341Sdelphij            } else if (!strcmp(*args, "-keypbe")) {
229296341Sdelphij                if (!set_pbe(bio_err, &key_pbe, *++args))
230296341Sdelphij                    badarg = 1;
231296341Sdelphij            } else if (!strcmp(*args, "-rand")) {
232296341Sdelphij                if (args[1]) {
233296341Sdelphij                    args++;
234296341Sdelphij                    inrand = *args;
235296341Sdelphij                } else
236296341Sdelphij                    badarg = 1;
237296341Sdelphij            } else if (!strcmp(*args, "-inkey")) {
238296341Sdelphij                if (args[1]) {
239296341Sdelphij                    args++;
240296341Sdelphij                    keyname = *args;
241296341Sdelphij                } else
242296341Sdelphij                    badarg = 1;
243296341Sdelphij            } else if (!strcmp(*args, "-certfile")) {
244296341Sdelphij                if (args[1]) {
245296341Sdelphij                    args++;
246296341Sdelphij                    certfile = *args;
247296341Sdelphij                } else
248296341Sdelphij                    badarg = 1;
249296341Sdelphij            } else if (!strcmp(*args, "-name")) {
250296341Sdelphij                if (args[1]) {
251296341Sdelphij                    args++;
252296341Sdelphij                    name = *args;
253296341Sdelphij                } else
254296341Sdelphij                    badarg = 1;
255296341Sdelphij            } else if (!strcmp(*args, "-LMK"))
256296341Sdelphij                add_lmk = 1;
257296341Sdelphij            else if (!strcmp(*args, "-CSP")) {
258296341Sdelphij                if (args[1]) {
259296341Sdelphij                    args++;
260296341Sdelphij                    csp_name = *args;
261296341Sdelphij                } else
262296341Sdelphij                    badarg = 1;
263296341Sdelphij            } else if (!strcmp(*args, "-caname")) {
264296341Sdelphij                if (args[1]) {
265296341Sdelphij                    args++;
266296341Sdelphij                    if (!canames)
267296341Sdelphij                        canames = sk_OPENSSL_STRING_new_null();
268296341Sdelphij                    sk_OPENSSL_STRING_push(canames, *args);
269296341Sdelphij                } else
270296341Sdelphij                    badarg = 1;
271296341Sdelphij            } else if (!strcmp(*args, "-in")) {
272296341Sdelphij                if (args[1]) {
273296341Sdelphij                    args++;
274296341Sdelphij                    infile = *args;
275296341Sdelphij                } else
276296341Sdelphij                    badarg = 1;
277296341Sdelphij            } else if (!strcmp(*args, "-out")) {
278296341Sdelphij                if (args[1]) {
279296341Sdelphij                    args++;
280296341Sdelphij                    outfile = *args;
281296341Sdelphij                } else
282296341Sdelphij                    badarg = 1;
283296341Sdelphij            } else if (!strcmp(*args, "-passin")) {
284296341Sdelphij                if (args[1]) {
285296341Sdelphij                    args++;
286296341Sdelphij                    passargin = *args;
287296341Sdelphij                } else
288296341Sdelphij                    badarg = 1;
289296341Sdelphij            } else if (!strcmp(*args, "-passout")) {
290296341Sdelphij                if (args[1]) {
291296341Sdelphij                    args++;
292296341Sdelphij                    passargout = *args;
293296341Sdelphij                } else
294296341Sdelphij                    badarg = 1;
295296341Sdelphij            } else if (!strcmp(*args, "-password")) {
296296341Sdelphij                if (args[1]) {
297296341Sdelphij                    args++;
298296341Sdelphij                    passarg = *args;
299296341Sdelphij                    noprompt = 1;
300296341Sdelphij                } else
301296341Sdelphij                    badarg = 1;
302296341Sdelphij            } else if (!strcmp(*args, "-CApath")) {
303296341Sdelphij                if (args[1]) {
304296341Sdelphij                    args++;
305296341Sdelphij                    CApath = *args;
306296341Sdelphij                } else
307296341Sdelphij                    badarg = 1;
308296341Sdelphij            } else if (!strcmp(*args, "-CAfile")) {
309296341Sdelphij                if (args[1]) {
310296341Sdelphij                    args++;
311296341Sdelphij                    CAfile = *args;
312296341Sdelphij                } else
313296341Sdelphij                    badarg = 1;
314296341Sdelphij# ifndef OPENSSL_NO_ENGINE
315296341Sdelphij            } else if (!strcmp(*args, "-engine")) {
316296341Sdelphij                if (args[1]) {
317296341Sdelphij                    args++;
318296341Sdelphij                    engine = *args;
319296341Sdelphij                } else
320296341Sdelphij                    badarg = 1;
321296341Sdelphij# endif
322296341Sdelphij            } else
323296341Sdelphij                badarg = 1;
32455714Skris
325296341Sdelphij        } else
326296341Sdelphij            badarg = 1;
327296341Sdelphij        args++;
32855714Skris    }
32955714Skris
33055714Skris    if (badarg) {
331296341Sdelphij        BIO_printf(bio_err, "Usage: pkcs12 [options]\n");
332296341Sdelphij        BIO_printf(bio_err, "where options are\n");
333296341Sdelphij        BIO_printf(bio_err, "-export       output PKCS12 file\n");
334296341Sdelphij        BIO_printf(bio_err, "-chain        add certificate chain\n");
335296341Sdelphij        BIO_printf(bio_err, "-inkey file   private key if not infile\n");
336296341Sdelphij        BIO_printf(bio_err, "-certfile f   add all certs in f\n");
337296341Sdelphij        BIO_printf(bio_err, "-CApath arg   - PEM format directory of CA's\n");
338296341Sdelphij        BIO_printf(bio_err, "-CAfile arg   - PEM format file of CA's\n");
339296341Sdelphij        BIO_printf(bio_err, "-name \"name\"  use name as friendly name\n");
340296341Sdelphij        BIO_printf(bio_err,
341296341Sdelphij                   "-caname \"nm\"  use nm as CA friendly name (can be used more than once).\n");
342296341Sdelphij        BIO_printf(bio_err, "-in  infile   input filename\n");
343296341Sdelphij        BIO_printf(bio_err, "-out outfile  output filename\n");
344296341Sdelphij        BIO_printf(bio_err,
345296341Sdelphij                   "-noout        don't output anything, just verify.\n");
346296341Sdelphij        BIO_printf(bio_err, "-nomacver     don't verify MAC.\n");
347296341Sdelphij        BIO_printf(bio_err, "-nocerts      don't output certificates.\n");
348296341Sdelphij        BIO_printf(bio_err,
349296341Sdelphij                   "-clcerts      only output client certificates.\n");
350296341Sdelphij        BIO_printf(bio_err, "-cacerts      only output CA certificates.\n");
351296341Sdelphij        BIO_printf(bio_err, "-nokeys       don't output private keys.\n");
352296341Sdelphij        BIO_printf(bio_err,
353296341Sdelphij                   "-info         give info about PKCS#12 structure.\n");
354296341Sdelphij        BIO_printf(bio_err, "-des          encrypt private keys with DES\n");
355296341Sdelphij        BIO_printf(bio_err,
356296341Sdelphij                   "-des3         encrypt private keys with triple DES (default)\n");
357296341Sdelphij# ifndef OPENSSL_NO_IDEA
358296341Sdelphij        BIO_printf(bio_err, "-idea         encrypt private keys with idea\n");
359296341Sdelphij# endif
360296341Sdelphij# ifndef OPENSSL_NO_SEED
361296341Sdelphij        BIO_printf(bio_err, "-seed         encrypt private keys with seed\n");
362296341Sdelphij# endif
363296341Sdelphij# ifndef OPENSSL_NO_AES
364296341Sdelphij        BIO_printf(bio_err, "-aes128, -aes192, -aes256\n");
365296341Sdelphij        BIO_printf(bio_err,
366296341Sdelphij                   "              encrypt PEM output with cbc aes\n");
367296341Sdelphij# endif
368296341Sdelphij# ifndef OPENSSL_NO_CAMELLIA
369296341Sdelphij        BIO_printf(bio_err, "-camellia128, -camellia192, -camellia256\n");
370296341Sdelphij        BIO_printf(bio_err,
371296341Sdelphij                   "              encrypt PEM output with cbc camellia\n");
372296341Sdelphij# endif
373296341Sdelphij        BIO_printf(bio_err, "-nodes        don't encrypt private keys\n");
374296341Sdelphij        BIO_printf(bio_err, "-noiter       don't use encryption iteration\n");
375296341Sdelphij        BIO_printf(bio_err, "-nomaciter    don't use MAC iteration\n");
376296341Sdelphij        BIO_printf(bio_err, "-maciter      use MAC iteration\n");
377296341Sdelphij        BIO_printf(bio_err, "-nomac        don't generate MAC\n");
378296341Sdelphij        BIO_printf(bio_err,
379296341Sdelphij                   "-twopass      separate MAC, encryption passwords\n");
380296341Sdelphij        BIO_printf(bio_err,
381296341Sdelphij                   "-descert      encrypt PKCS#12 certificates with triple DES (default RC2-40)\n");
382296341Sdelphij        BIO_printf(bio_err,
383296341Sdelphij                   "-certpbe alg  specify certificate PBE algorithm (default RC2-40)\n");
384296341Sdelphij        BIO_printf(bio_err,
385296341Sdelphij                   "-keypbe alg   specify private key PBE algorithm (default 3DES)\n");
386296341Sdelphij        BIO_printf(bio_err,
387296341Sdelphij                   "-macalg alg   digest algorithm used in MAC (default SHA1)\n");
388296341Sdelphij        BIO_printf(bio_err, "-keyex        set MS key exchange type\n");
389296341Sdelphij        BIO_printf(bio_err, "-keysig       set MS key signature type\n");
390296341Sdelphij        BIO_printf(bio_err,
391296341Sdelphij                   "-password p   set import/export password source\n");
392296341Sdelphij        BIO_printf(bio_err, "-passin p     input file pass phrase source\n");
393296341Sdelphij        BIO_printf(bio_err, "-passout p    output file pass phrase source\n");
394296341Sdelphij# ifndef OPENSSL_NO_ENGINE
395296341Sdelphij        BIO_printf(bio_err,
396296341Sdelphij                   "-engine e     use engine e, possibly a hardware device.\n");
397296341Sdelphij# endif
398296341Sdelphij        BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR,
399296341Sdelphij                   LIST_SEPARATOR_CHAR);
400296341Sdelphij        BIO_printf(bio_err,
401296341Sdelphij                   "              load the file (or the files in the directory) into\n");
402296341Sdelphij        BIO_printf(bio_err, "              the random number generator\n");
403296341Sdelphij        BIO_printf(bio_err, "-CSP name     Microsoft CSP name\n");
404296341Sdelphij        BIO_printf(bio_err,
405296341Sdelphij                   "-LMK          Add local machine keyset attribute to private key\n");
406296341Sdelphij        goto end;
40755714Skris    }
408296341Sdelphij# ifndef OPENSSL_NO_ENGINE
409109998Smarkm    e = setup_engine(bio_err, engine, 0);
410296341Sdelphij# endif
411109998Smarkm
412296341Sdelphij    if (passarg) {
413296341Sdelphij        if (export_cert)
414296341Sdelphij            passargout = passarg;
415296341Sdelphij        else
416296341Sdelphij            passargin = passarg;
41759191Skris    }
41859191Skris
419296341Sdelphij    if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
420296341Sdelphij        BIO_printf(bio_err, "Error getting passwords\n");
421296341Sdelphij        goto end;
42259191Skris    }
42359191Skris
424296341Sdelphij    if (!cpass) {
425296341Sdelphij        if (export_cert)
426296341Sdelphij            cpass = passout;
427296341Sdelphij        else
428296341Sdelphij            cpass = passin;
42959191Skris    }
43059191Skris
431296341Sdelphij    if (cpass) {
432296341Sdelphij        mpass = cpass;
433296341Sdelphij        noprompt = 1;
43459191Skris    } else {
435296341Sdelphij        cpass = pass;
436296341Sdelphij        mpass = macpass;
43755714Skris    }
43855714Skris
439296341Sdelphij    if (export_cert || inrand) {
440296341Sdelphij        app_RAND_load_file(NULL, bio_err, (inrand != NULL));
44159191Skris        if (inrand != NULL)
442296341Sdelphij            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
443296341Sdelphij                       app_RAND_load_files(inrand));
44459191Skris    }
44555714Skris    ERR_load_crypto_strings();
44655714Skris
447296341Sdelphij# ifdef CRYPTO_MDEBUG
44859191Skris    CRYPTO_push_info("read files");
449296341Sdelphij# endif
45059191Skris
451296341Sdelphij    if (!infile)
452296341Sdelphij        in = BIO_new_fp(stdin, BIO_NOCLOSE);
453296341Sdelphij    else
454296341Sdelphij        in = BIO_new_file(infile, "rb");
45555714Skris    if (!in) {
456296341Sdelphij        BIO_printf(bio_err, "Error opening input file %s\n",
457296341Sdelphij                   infile ? infile : "<stdin>");
458296341Sdelphij        perror(infile);
459296341Sdelphij        goto end;
460296341Sdelphij    }
461296341Sdelphij# ifdef CRYPTO_MDEBUG
46259191Skris    CRYPTO_pop_info();
46359191Skris    CRYPTO_push_info("write files");
464296341Sdelphij# endif
46559191Skris
46668651Skris    if (!outfile) {
467296341Sdelphij        out = BIO_new_fp(stdout, BIO_NOCLOSE);
468296341Sdelphij# ifdef OPENSSL_SYS_VMS
469296341Sdelphij        {
470296341Sdelphij            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
471296341Sdelphij            out = BIO_push(tmpbio, out);
472296341Sdelphij        }
473296341Sdelphij# endif
474296341Sdelphij    } else
475296341Sdelphij        out = BIO_new_file(outfile, "wb");
47655714Skris    if (!out) {
477296341Sdelphij        BIO_printf(bio_err, "Error opening output file %s\n",
478296341Sdelphij                   outfile ? outfile : "<stdout>");
479296341Sdelphij        perror(outfile);
480296341Sdelphij        goto end;
48155714Skris    }
48255714Skris    if (twopass) {
483296341Sdelphij# ifdef CRYPTO_MDEBUG
484296341Sdelphij        CRYPTO_push_info("read MAC password");
485296341Sdelphij# endif
486296341Sdelphij        if (EVP_read_pw_string
487296341Sdelphij            (macpass, sizeof macpass, "Enter MAC Password:", export_cert)) {
488296341Sdelphij            BIO_printf(bio_err, "Can't read Password\n");
489296341Sdelphij            goto end;
490296341Sdelphij        }
491296341Sdelphij# ifdef CRYPTO_MDEBUG
492296341Sdelphij        CRYPTO_pop_info();
493296341Sdelphij# endif
49455714Skris    }
49555714Skris
49659191Skris    if (export_cert) {
497296341Sdelphij        EVP_PKEY *key = NULL;
498296341Sdelphij        X509 *ucert = NULL, *x = NULL;
499296341Sdelphij        STACK_OF(X509) *certs = NULL;
500296341Sdelphij        const EVP_MD *macmd = NULL;
501296341Sdelphij        unsigned char *catmp = NULL;
502296341Sdelphij        int i;
50359191Skris
504296341Sdelphij        if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) {
505296341Sdelphij            BIO_printf(bio_err, "Nothing to do!\n");
506296341Sdelphij            goto export_end;
507296341Sdelphij        }
508160814Ssimon
509296341Sdelphij        if (options & NOCERTS)
510296341Sdelphij            chain = 0;
511160814Ssimon
512296341Sdelphij# ifdef CRYPTO_MDEBUG
513296341Sdelphij        CRYPTO_push_info("process -export_cert");
514296341Sdelphij        CRYPTO_push_info("reading private key");
515296341Sdelphij# endif
516296341Sdelphij        if (!(options & NOKEYS)) {
517296341Sdelphij            key = load_key(bio_err, keyname ? keyname : infile,
518296341Sdelphij                           FORMAT_PEM, 1, passin, e, "private key");
519296341Sdelphij            if (!key)
520296341Sdelphij                goto export_end;
521296341Sdelphij        }
522296341Sdelphij# ifdef CRYPTO_MDEBUG
523296341Sdelphij        CRYPTO_pop_info();
524296341Sdelphij        CRYPTO_push_info("reading certs from input");
525296341Sdelphij# endif
52655714Skris
527296341Sdelphij        /* Load in all certs in input file */
528296341Sdelphij        if (!(options & NOCERTS)) {
529296341Sdelphij            certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e,
530296341Sdelphij                               "certificates");
531296341Sdelphij            if (!certs)
532296341Sdelphij                goto export_end;
53355714Skris
534296341Sdelphij            if (key) {
535296341Sdelphij                /* Look for matching private key */
536296341Sdelphij                for (i = 0; i < sk_X509_num(certs); i++) {
537296341Sdelphij                    x = sk_X509_value(certs, i);
538296341Sdelphij                    if (X509_check_private_key(x, key)) {
539296341Sdelphij                        ucert = x;
540296341Sdelphij                        /* Zero keyid and alias */
541296341Sdelphij                        X509_keyid_set1(ucert, NULL, 0);
542296341Sdelphij                        X509_alias_set1(ucert, NULL, 0);
543296341Sdelphij                        /* Remove from list */
544296341Sdelphij                        (void)sk_X509_delete(certs, i);
545296341Sdelphij                        break;
546296341Sdelphij                    }
547296341Sdelphij                }
548296341Sdelphij                if (!ucert) {
549296341Sdelphij                    BIO_printf(bio_err,
550296341Sdelphij                               "No certificate matches private key\n");
551296341Sdelphij                    goto export_end;
552296341Sdelphij                }
553296341Sdelphij            }
55455714Skris
555296341Sdelphij        }
556296341Sdelphij# ifdef CRYPTO_MDEBUG
557296341Sdelphij        CRYPTO_pop_info();
558296341Sdelphij        CRYPTO_push_info("reading certs from input 2");
559296341Sdelphij# endif
56068651Skris
561296341Sdelphij        /* Add any more certificates asked for */
562296341Sdelphij        if (certfile) {
563296341Sdelphij            STACK_OF(X509) *morecerts = NULL;
564296341Sdelphij            if (!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM,
565296341Sdelphij                                         NULL, e,
566296341Sdelphij                                         "certificates from certfile")))
567296341Sdelphij                goto export_end;
568296341Sdelphij            while (sk_X509_num(morecerts) > 0)
569296341Sdelphij                sk_X509_push(certs, sk_X509_shift(morecerts));
570296341Sdelphij            sk_X509_free(morecerts);
571296341Sdelphij        }
572296341Sdelphij# ifdef CRYPTO_MDEBUG
573296341Sdelphij        CRYPTO_pop_info();
574296341Sdelphij        CRYPTO_push_info("reading certs from certfile");
575296341Sdelphij# endif
576160814Ssimon
577296341Sdelphij# ifdef CRYPTO_MDEBUG
578296341Sdelphij        CRYPTO_pop_info();
579296341Sdelphij        CRYPTO_push_info("building chain");
580296341Sdelphij# endif
58155714Skris
582296341Sdelphij        /* If chaining get chain from user cert */
583296341Sdelphij        if (chain) {
584296341Sdelphij            int vret;
585296341Sdelphij            STACK_OF(X509) *chain2;
586296341Sdelphij            X509_STORE *store = X509_STORE_new();
587296341Sdelphij            if (!store) {
588296341Sdelphij                BIO_printf(bio_err, "Memory allocation error\n");
589296341Sdelphij                goto export_end;
590296341Sdelphij            }
591296341Sdelphij            if (!X509_STORE_load_locations(store, CAfile, CApath))
592296341Sdelphij                X509_STORE_set_default_paths(store);
59355714Skris
594296341Sdelphij            vret = get_cert_chain(ucert, store, &chain2);
595296341Sdelphij            X509_STORE_free(store);
596160814Ssimon
597296341Sdelphij            if (!vret) {
598296341Sdelphij                /* Exclude verified certificate */
599296341Sdelphij                for (i = 1; i < sk_X509_num(chain2); i++)
600296341Sdelphij                    sk_X509_push(certs, sk_X509_value(chain2, i));
601296341Sdelphij                /* Free first certificate */
602296341Sdelphij                X509_free(sk_X509_value(chain2, 0));
603296341Sdelphij                sk_X509_free(chain2);
604296341Sdelphij            } else {
605296341Sdelphij                if (vret >= 0)
606296341Sdelphij                    BIO_printf(bio_err, "Error %s getting chain.\n",
607296341Sdelphij                               X509_verify_cert_error_string(vret));
608296341Sdelphij                else
609296341Sdelphij                    ERR_print_errors(bio_err);
610296341Sdelphij                goto export_end;
611296341Sdelphij            }
612296341Sdelphij        }
61368651Skris
614296341Sdelphij        /* Add any CA names */
61568651Skris
616296341Sdelphij        for (i = 0; i < sk_OPENSSL_STRING_num(canames); i++) {
617296341Sdelphij            catmp = (unsigned char *)sk_OPENSSL_STRING_value(canames, i);
618296341Sdelphij            X509_alias_set1(sk_X509_value(certs, i), catmp, -1);
619296341Sdelphij        }
62068651Skris
621296341Sdelphij        if (csp_name && key)
622296341Sdelphij            EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name,
623296341Sdelphij                                      MBSTRING_ASC, (unsigned char *)csp_name,
624296341Sdelphij                                      -1);
62555714Skris
626296341Sdelphij        if (add_lmk && key)
627296341Sdelphij            EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1);
62868651Skris
629296341Sdelphij# ifdef CRYPTO_MDEBUG
630296341Sdelphij        CRYPTO_pop_info();
631296341Sdelphij        CRYPTO_push_info("reading password");
632296341Sdelphij# endif
63355714Skris
634296341Sdelphij        if (!noprompt &&
635296341Sdelphij            EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:",
636296341Sdelphij                               1)) {
637296341Sdelphij            BIO_printf(bio_err, "Can't read Password\n");
638296341Sdelphij            goto export_end;
639296341Sdelphij        }
640296341Sdelphij        if (!twopass)
641296341Sdelphij            BUF_strlcpy(macpass, pass, sizeof macpass);
642160814Ssimon
643296341Sdelphij# ifdef CRYPTO_MDEBUG
644296341Sdelphij        CRYPTO_pop_info();
645296341Sdelphij        CRYPTO_push_info("creating PKCS#12 structure");
646296341Sdelphij# endif
647194206Ssimon
648296341Sdelphij        p12 = PKCS12_create(cpass, name, key, ucert, certs,
649296341Sdelphij                            key_pbe, cert_pbe, iter, -1, keytype);
65068651Skris
651296341Sdelphij        if (!p12) {
652296341Sdelphij            ERR_print_errors(bio_err);
653296341Sdelphij            goto export_end;
654296341Sdelphij        }
65555714Skris
656296341Sdelphij        if (macalg) {
657296341Sdelphij            macmd = EVP_get_digestbyname(macalg);
658296341Sdelphij            if (!macmd) {
659296341Sdelphij                BIO_printf(bio_err, "Unknown digest algorithm %s\n", macalg);
660296341Sdelphij            }
661296341Sdelphij        }
66268651Skris
663296341Sdelphij        if (maciter != -1)
664296341Sdelphij            PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd);
66568651Skris
666296341Sdelphij# ifdef CRYPTO_MDEBUG
667296341Sdelphij        CRYPTO_pop_info();
668296341Sdelphij        CRYPTO_push_info("writing pkcs12");
669296341Sdelphij# endif
67068651Skris
671296341Sdelphij        i2d_PKCS12_bio(out, p12);
672238405Sjkim
673296341Sdelphij        ret = 0;
67455714Skris
675296341Sdelphij export_end:
676296341Sdelphij# ifdef CRYPTO_MDEBUG
677296341Sdelphij        CRYPTO_pop_info();
678296341Sdelphij        CRYPTO_pop_info();
679296341Sdelphij        CRYPTO_push_info("process -export_cert: freeing");
680296341Sdelphij# endif
68168651Skris
682296341Sdelphij        if (key)
683296341Sdelphij            EVP_PKEY_free(key);
684296341Sdelphij        if (certs)
685296341Sdelphij            sk_X509_pop_free(certs, X509_free);
686296341Sdelphij        if (ucert)
687296341Sdelphij            X509_free(ucert);
68855714Skris
689296341Sdelphij# ifdef CRYPTO_MDEBUG
690296341Sdelphij        CRYPTO_pop_info();
691296341Sdelphij# endif
692296341Sdelphij        goto end;
69359191Skris
69455714Skris    }
69555714Skris
696296341Sdelphij    if (!(p12 = d2i_PKCS12_bio(in, NULL))) {
697296341Sdelphij        ERR_print_errors(bio_err);
698296341Sdelphij        goto end;
69955714Skris    }
700296341Sdelphij# ifdef CRYPTO_MDEBUG
70159191Skris    CRYPTO_push_info("read import password");
702296341Sdelphij# endif
703296341Sdelphij    if (!noprompt
704296341Sdelphij        && EVP_read_pw_string(pass, sizeof pass, "Enter Import Password:",
705296341Sdelphij                              0)) {
706296341Sdelphij        BIO_printf(bio_err, "Can't read Password\n");
707296341Sdelphij        goto end;
70855714Skris    }
709296341Sdelphij# ifdef CRYPTO_MDEBUG
71059191Skris    CRYPTO_pop_info();
711296341Sdelphij# endif
71255714Skris
713296341Sdelphij    if (!twopass)
714296341Sdelphij        BUF_strlcpy(macpass, pass, sizeof macpass);
71555714Skris
716296341Sdelphij    if ((options & INFO) && p12->mac)
717296341Sdelphij        BIO_printf(bio_err, "MAC Iteration %ld\n",
718296341Sdelphij                   p12->mac->iter ? ASN1_INTEGER_get(p12->mac->iter) : 1);
719296341Sdelphij    if (macver) {
720296341Sdelphij# ifdef CRYPTO_MDEBUG
721296341Sdelphij        CRYPTO_push_info("verify MAC");
722296341Sdelphij# endif
723296341Sdelphij        /* If we enter empty password try no password first */
724296341Sdelphij        if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) {
725296341Sdelphij            /* If mac and crypto pass the same set it to NULL too */
726296341Sdelphij            if (!twopass)
727296341Sdelphij                cpass = NULL;
728296341Sdelphij        } else if (!PKCS12_verify_mac(p12, mpass, -1)) {
729296341Sdelphij            BIO_printf(bio_err, "Mac verify error: invalid password?\n");
730296341Sdelphij            ERR_print_errors(bio_err);
731296341Sdelphij            goto end;
732296341Sdelphij        }
733296341Sdelphij        BIO_printf(bio_err, "MAC verified OK\n");
734296341Sdelphij# ifdef CRYPTO_MDEBUG
735296341Sdelphij        CRYPTO_pop_info();
736296341Sdelphij# endif
73755714Skris    }
738296341Sdelphij# ifdef CRYPTO_MDEBUG
73959191Skris    CRYPTO_push_info("output keys and certificates");
740296341Sdelphij# endif
741296341Sdelphij    if (!dump_certs_keys_p12(out, p12, cpass, -1, options, passout)) {
742296341Sdelphij        BIO_printf(bio_err, "Error outputting keys and certificates\n");
743296341Sdelphij        ERR_print_errors(bio_err);
744296341Sdelphij        goto end;
74555714Skris    }
746296341Sdelphij# ifdef CRYPTO_MDEBUG
74759191Skris    CRYPTO_pop_info();
748296341Sdelphij# endif
74955714Skris    ret = 0;
75068651Skris end:
751296341Sdelphij    if (p12)
752296341Sdelphij        PKCS12_free(p12);
753296341Sdelphij    if (export_cert || inrand)
754296341Sdelphij        app_RAND_write_file(NULL, bio_err);
755296341Sdelphij# ifdef CRYPTO_MDEBUG
75659191Skris    CRYPTO_remove_all_info();
757296341Sdelphij# endif
75859191Skris    BIO_free(in);
75968651Skris    BIO_free_all(out);
760296341Sdelphij    if (canames)
761296341Sdelphij        sk_OPENSSL_STRING_free(canames);
762296341Sdelphij    if (passin)
763296341Sdelphij        OPENSSL_free(passin);
764296341Sdelphij    if (passout)
765296341Sdelphij        OPENSSL_free(passout);
766109998Smarkm    apps_shutdown();
767109998Smarkm    OPENSSL_EXIT(ret);
76855714Skris}
76955714Skris
770296341Sdelphijint dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass,
771296341Sdelphij                        int passlen, int options, char *pempass)
77255714Skris{
773296341Sdelphij    STACK_OF(PKCS7) *asafes = NULL;
774296341Sdelphij    STACK_OF(PKCS12_SAFEBAG) *bags;
775296341Sdelphij    int i, bagnid;
776296341Sdelphij    int ret = 0;
777296341Sdelphij    PKCS7 *p7;
77868651Skris
779296341Sdelphij    if (!(asafes = PKCS12_unpack_authsafes(p12)))
780296341Sdelphij        return 0;
781296341Sdelphij    for (i = 0; i < sk_PKCS7_num(asafes); i++) {
782296341Sdelphij        p7 = sk_PKCS7_value(asafes, i);
783296341Sdelphij        bagnid = OBJ_obj2nid(p7->type);
784296341Sdelphij        if (bagnid == NID_pkcs7_data) {
785296341Sdelphij            bags = PKCS12_unpack_p7data(p7);
786296341Sdelphij            if (options & INFO)
787296341Sdelphij                BIO_printf(bio_err, "PKCS7 Data\n");
788296341Sdelphij        } else if (bagnid == NID_pkcs7_encrypted) {
789296341Sdelphij            if (options & INFO) {
790296341Sdelphij                BIO_printf(bio_err, "PKCS7 Encrypted data: ");
791296341Sdelphij                alg_print(bio_err, p7->d.encrypted->enc_data->algorithm);
792296341Sdelphij            }
793296341Sdelphij            bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
794296341Sdelphij        } else
795296341Sdelphij            continue;
796296341Sdelphij        if (!bags)
797296341Sdelphij            goto err;
798296341Sdelphij        if (!dump_certs_pkeys_bags(out, bags, pass, passlen,
799296341Sdelphij                                   options, pempass)) {
800296341Sdelphij            sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
801296341Sdelphij            goto err;
802296341Sdelphij        }
803296341Sdelphij        sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
804296341Sdelphij        bags = NULL;
805296341Sdelphij    }
806296341Sdelphij    ret = 1;
807160814Ssimon
808296341Sdelphij err:
809160814Ssimon
810296341Sdelphij    if (asafes)
811296341Sdelphij        sk_PKCS7_pop_free(asafes, PKCS7_free);
812296341Sdelphij    return ret;
81355714Skris}
81455714Skris
815296341Sdelphijint dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags,
816296341Sdelphij                          char *pass, int passlen, int options, char *pempass)
81755714Skris{
818296341Sdelphij    int i;
819296341Sdelphij    for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
820296341Sdelphij        if (!dump_certs_pkeys_bag(out,
821296341Sdelphij                                  sk_PKCS12_SAFEBAG_value(bags, i),
822296341Sdelphij                                  pass, passlen, options, pempass))
823296341Sdelphij            return 0;
824296341Sdelphij    }
825296341Sdelphij    return 1;
82655714Skris}
82755714Skris
828296341Sdelphijint dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bag, char *pass,
829296341Sdelphij                         int passlen, int options, char *pempass)
83055714Skris{
831296341Sdelphij    EVP_PKEY *pkey;
832296341Sdelphij    PKCS8_PRIV_KEY_INFO *p8;
833296341Sdelphij    X509 *x509;
83455714Skris
835296341Sdelphij    switch (M_PKCS12_bag_type(bag)) {
836296341Sdelphij    case NID_keyBag:
837296341Sdelphij        if (options & INFO)
838296341Sdelphij            BIO_printf(bio_err, "Key bag\n");
839296341Sdelphij        if (options & NOKEYS)
840296341Sdelphij            return 1;
841296341Sdelphij        print_attribs(out, bag->attrib, "Bag Attributes");
842296341Sdelphij        p8 = bag->value.keybag;
843296341Sdelphij        if (!(pkey = EVP_PKCS82PKEY(p8)))
844296341Sdelphij            return 0;
845296341Sdelphij        print_attribs(out, p8->attributes, "Key Attributes");
846296341Sdelphij        PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass);
847296341Sdelphij        EVP_PKEY_free(pkey);
848296341Sdelphij        break;
84955714Skris
850296341Sdelphij    case NID_pkcs8ShroudedKeyBag:
851296341Sdelphij        if (options & INFO) {
852296341Sdelphij            BIO_printf(bio_err, "Shrouded Keybag: ");
853296341Sdelphij            alg_print(bio_err, bag->value.shkeybag->algor);
854296341Sdelphij        }
855296341Sdelphij        if (options & NOKEYS)
856296341Sdelphij            return 1;
857296341Sdelphij        print_attribs(out, bag->attrib, "Bag Attributes");
858296341Sdelphij        if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen)))
859296341Sdelphij            return 0;
860296341Sdelphij        if (!(pkey = EVP_PKCS82PKEY(p8))) {
861296341Sdelphij            PKCS8_PRIV_KEY_INFO_free(p8);
862296341Sdelphij            return 0;
863296341Sdelphij        }
864296341Sdelphij        print_attribs(out, p8->attributes, "Key Attributes");
865296341Sdelphij        PKCS8_PRIV_KEY_INFO_free(p8);
866296341Sdelphij        PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass);
867296341Sdelphij        EVP_PKEY_free(pkey);
868296341Sdelphij        break;
86955714Skris
870296341Sdelphij    case NID_certBag:
871296341Sdelphij        if (options & INFO)
872296341Sdelphij            BIO_printf(bio_err, "Certificate bag\n");
873296341Sdelphij        if (options & NOCERTS)
874296341Sdelphij            return 1;
875296341Sdelphij        if (PKCS12_get_attr(bag, NID_localKeyID)) {
876296341Sdelphij            if (options & CACERTS)
877296341Sdelphij                return 1;
878296341Sdelphij        } else if (options & CLCERTS)
879296341Sdelphij            return 1;
880296341Sdelphij        print_attribs(out, bag->attrib, "Bag Attributes");
881296341Sdelphij        if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate)
882296341Sdelphij            return 1;
883296341Sdelphij        if (!(x509 = PKCS12_certbag2x509(bag)))
884296341Sdelphij            return 0;
885296341Sdelphij        dump_cert_text(out, x509);
886296341Sdelphij        PEM_write_bio_X509(out, x509);
887296341Sdelphij        X509_free(x509);
888296341Sdelphij        break;
889296341Sdelphij
890296341Sdelphij    case NID_safeContentsBag:
891296341Sdelphij        if (options & INFO)
892296341Sdelphij            BIO_printf(bio_err, "Safe Contents bag\n");
893296341Sdelphij        print_attribs(out, bag->attrib, "Bag Attributes");
894296341Sdelphij        return dump_certs_pkeys_bags(out, bag->value.safes, pass,
895296341Sdelphij                                     passlen, options, pempass);
896296341Sdelphij
897296341Sdelphij    default:
898296341Sdelphij        BIO_printf(bio_err, "Warning unsupported bag type: ");
899296341Sdelphij        i2a_ASN1_OBJECT(bio_err, bag->type);
900296341Sdelphij        BIO_printf(bio_err, "\n");
901296341Sdelphij        return 1;
902296341Sdelphij        break;
903296341Sdelphij    }
904296341Sdelphij    return 1;
90555714Skris}
90655714Skris
90755714Skris/* Given a single certificate return a verified chain or NULL if error */
90855714Skris
90955714Skris/* Hope this is OK .... */
91055714Skris
911296341Sdelphijint get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **chain)
91255714Skris{
913296341Sdelphij    X509_STORE_CTX store_ctx;
914296341Sdelphij    STACK_OF(X509) *chn;
915296341Sdelphij    int i = 0;
91659191Skris
917296341Sdelphij    /*
918296341Sdelphij     * FIXME: Should really check the return status of X509_STORE_CTX_init
919296341Sdelphij     * for an error, but how that fits into the return value of this function
920296341Sdelphij     * is less obvious.
921296341Sdelphij     */
922296341Sdelphij    X509_STORE_CTX_init(&store_ctx, store, cert, NULL);
923296341Sdelphij    if (X509_verify_cert(&store_ctx) <= 0) {
924296341Sdelphij        i = X509_STORE_CTX_get_error(&store_ctx);
925296341Sdelphij        if (i == 0)
926296341Sdelphij            /*
927296341Sdelphij             * avoid returning 0 if X509_verify_cert() did not set an
928296341Sdelphij             * appropriate error value in the context
929296341Sdelphij             */
930296341Sdelphij            i = -1;
931296341Sdelphij        chn = NULL;
932296341Sdelphij        goto err;
933296341Sdelphij    } else
934296341Sdelphij        chn = X509_STORE_CTX_get1_chain(&store_ctx);
935296341Sdelphij err:
936296341Sdelphij    X509_STORE_CTX_cleanup(&store_ctx);
937296341Sdelphij    *chain = chn;
93855714Skris
939296341Sdelphij    return i;
940296341Sdelphij}
941296341Sdelphij
942296341Sdelphijint alg_print(BIO *x, X509_ALGOR *alg)
94355714Skris{
944296341Sdelphij    PBEPARAM *pbe;
945296341Sdelphij    const unsigned char *p;
946296341Sdelphij    p = alg->parameter->value.sequence->data;
947296341Sdelphij    pbe = d2i_PBEPARAM(NULL, &p, alg->parameter->value.sequence->length);
948296341Sdelphij    if (!pbe)
949296341Sdelphij        return 1;
950296341Sdelphij    BIO_printf(bio_err, "%s, Iteration %ld\n",
951296341Sdelphij               OBJ_nid2ln(OBJ_obj2nid(alg->algorithm)),
952296341Sdelphij               ASN1_INTEGER_get(pbe->iter));
953296341Sdelphij    PBEPARAM_free(pbe);
954296341Sdelphij    return 1;
95555714Skris}
95655714Skris
95755714Skris/* Load all certificates from a given file */
95855714Skris
95955714Skrisint cert_load(BIO *in, STACK_OF(X509) *sk)
96055714Skris{
961296341Sdelphij    int ret;
962296341Sdelphij    X509 *cert;
963296341Sdelphij    ret = 0;
964296341Sdelphij# ifdef CRYPTO_MDEBUG
965296341Sdelphij    CRYPTO_push_info("cert_load(): reading one cert");
966296341Sdelphij# endif
967296341Sdelphij    while ((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
968296341Sdelphij# ifdef CRYPTO_MDEBUG
969296341Sdelphij        CRYPTO_pop_info();
970296341Sdelphij# endif
971296341Sdelphij        ret = 1;
972296341Sdelphij        sk_X509_push(sk, cert);
973296341Sdelphij# ifdef CRYPTO_MDEBUG
974296341Sdelphij        CRYPTO_push_info("cert_load(): reading one cert");
975296341Sdelphij# endif
976296341Sdelphij    }
977296341Sdelphij# ifdef CRYPTO_MDEBUG
978296341Sdelphij    CRYPTO_pop_info();
979296341Sdelphij# endif
980296341Sdelphij    if (ret)
981296341Sdelphij        ERR_clear_error();
982296341Sdelphij    return ret;
98355714Skris}
98455714Skris
98555714Skris/* Generalised attribute print: handle PKCS#8 and bag attributes */
98655714Skris
987296341Sdelphijint print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst,
988296341Sdelphij                  const char *name)
98955714Skris{
990296341Sdelphij    X509_ATTRIBUTE *attr;
991296341Sdelphij    ASN1_TYPE *av;
992296341Sdelphij    char *value;
993296341Sdelphij    int i, attr_nid;
994296341Sdelphij    if (!attrlst) {
995296341Sdelphij        BIO_printf(out, "%s: <No Attributes>\n", name);
996296341Sdelphij        return 1;
997296341Sdelphij    }
998296341Sdelphij    if (!sk_X509_ATTRIBUTE_num(attrlst)) {
999296341Sdelphij        BIO_printf(out, "%s: <Empty Attributes>\n", name);
1000296341Sdelphij        return 1;
1001296341Sdelphij    }
1002296341Sdelphij    BIO_printf(out, "%s\n", name);
1003296341Sdelphij    for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) {
1004296341Sdelphij        attr = sk_X509_ATTRIBUTE_value(attrlst, i);
1005296341Sdelphij        attr_nid = OBJ_obj2nid(attr->object);
1006296341Sdelphij        BIO_printf(out, "    ");
1007296341Sdelphij        if (attr_nid == NID_undef) {
1008296341Sdelphij            i2a_ASN1_OBJECT(out, attr->object);
1009296341Sdelphij            BIO_printf(out, ": ");
1010296341Sdelphij        } else
1011296341Sdelphij            BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid));
101255714Skris
1013296341Sdelphij        if (sk_ASN1_TYPE_num(attr->value.set)) {
1014296341Sdelphij            av = sk_ASN1_TYPE_value(attr->value.set, 0);
1015296341Sdelphij            switch (av->type) {
1016296341Sdelphij            case V_ASN1_BMPSTRING:
1017296341Sdelphij                value = OPENSSL_uni2asc(av->value.bmpstring->data,
1018296341Sdelphij                                        av->value.bmpstring->length);
1019296341Sdelphij                BIO_printf(out, "%s\n", value);
1020296341Sdelphij                OPENSSL_free(value);
1021296341Sdelphij                break;
102255714Skris
1023296341Sdelphij            case V_ASN1_OCTET_STRING:
1024296341Sdelphij                hex_prin(out, av->value.octet_string->data,
1025296341Sdelphij                         av->value.octet_string->length);
1026296341Sdelphij                BIO_printf(out, "\n");
1027296341Sdelphij                break;
102855714Skris
1029296341Sdelphij            case V_ASN1_BIT_STRING:
1030296341Sdelphij                hex_prin(out, av->value.bit_string->data,
1031296341Sdelphij                         av->value.bit_string->length);
1032296341Sdelphij                BIO_printf(out, "\n");
1033296341Sdelphij                break;
103455714Skris
1035296341Sdelphij            default:
1036296341Sdelphij                BIO_printf(out, "<Unsupported tag %d>\n", av->type);
1037296341Sdelphij                break;
1038296341Sdelphij            }
1039296341Sdelphij        } else
1040296341Sdelphij            BIO_printf(out, "<No Values>\n");
1041296341Sdelphij    }
1042296341Sdelphij    return 1;
104355714Skris}
104455714Skris
104555714Skrisvoid hex_prin(BIO *out, unsigned char *buf, int len)
104655714Skris{
1047296341Sdelphij    int i;
1048296341Sdelphij    for (i = 0; i < len; i++)
1049296341Sdelphij        BIO_printf(out, "%02X ", buf[i]);
105055714Skris}
105155714Skris
1052238405Sjkimstatic int set_pbe(BIO *err, int *ppbe, const char *str)
1053296341Sdelphij{
1054296341Sdelphij    if (!str)
1055296341Sdelphij        return 0;
1056296341Sdelphij    if (!strcmp(str, "NONE")) {
1057296341Sdelphij        *ppbe = -1;
1058296341Sdelphij        return 1;
1059296341Sdelphij    }
1060296341Sdelphij    *ppbe = OBJ_txt2nid(str);
1061296341Sdelphij    if (*ppbe == NID_undef) {
1062296341Sdelphij        BIO_printf(bio_err, "Unknown PBE algorithm %s\n", str);
1063296341Sdelphij        return 0;
1064296341Sdelphij    }
1065296341Sdelphij    return 1;
1066296341Sdelphij}
1067296341Sdelphij
106855714Skris#endif
1069