source: trunk/third/openssl/apps/pkcs12.c @ 18442

Revision 18442, 27.4 KB checked in by zacheiss, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18441, which included commits to RCS files with non-trunk default branches.
Line 
1/* pkcs12.c */
2#if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_SHA1)
3
4/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
5 * project 1999.
6 */
7/* ====================================================================
8 * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 *
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in
19 *    the documentation and/or other materials provided with the
20 *    distribution.
21 *
22 * 3. All advertising materials mentioning features or use of this
23 *    software must display the following acknowledgment:
24 *    "This product includes software developed by the OpenSSL Project
25 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
26 *
27 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
28 *    endorse or promote products derived from this software without
29 *    prior written permission. For written permission, please contact
30 *    licensing@OpenSSL.org.
31 *
32 * 5. Products derived from this software may not be called "OpenSSL"
33 *    nor may "OpenSSL" appear in their names without prior written
34 *    permission of the OpenSSL Project.
35 *
36 * 6. Redistributions of any form whatsoever must retain the following
37 *    acknowledgment:
38 *    "This product includes software developed by the OpenSSL Project
39 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
42 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
44 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
45 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
48 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
50 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
52 * OF THE POSSIBILITY OF SUCH DAMAGE.
53 * ====================================================================
54 *
55 * This product includes cryptographic software written by Eric Young
56 * (eay@cryptsoft.com).  This product includes software written by Tim
57 * Hudson (tjh@cryptsoft.com).
58 *
59 */
60
61#include <stdio.h>
62#include <stdlib.h>
63#include <string.h>
64#include "apps.h"
65#include <openssl/crypto.h>
66#include <openssl/err.h>
67#include <openssl/pem.h>
68#include <openssl/pkcs12.h>
69
70#define PROG pkcs12_main
71
72const EVP_CIPHER *enc;
73
74
75#define NOKEYS          0x1
76#define NOCERTS         0x2
77#define INFO            0x4
78#define CLCERTS         0x8
79#define CACERTS         0x10
80
81int get_cert_chain (X509 *cert, X509_STORE *store, STACK_OF(X509) **chain);
82int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen, int options, char *pempass);
83int dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags, char *pass,
84                          int passlen, int options, char *pempass);
85int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bags, char *pass, int passlen, int options, char *pempass);
86int print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst, char *name);
87void hex_prin(BIO *out, unsigned char *buf, int len);
88int alg_print(BIO *x, X509_ALGOR *alg);
89int cert_load(BIO *in, STACK_OF(X509) *sk);
90
91int MAIN(int, char **);
92
93int MAIN(int argc, char **argv)
94{
95    ENGINE *e = NULL;
96    char *infile=NULL, *outfile=NULL, *keyname = NULL; 
97    char *certfile=NULL;
98    BIO *in=NULL, *out = NULL;
99    char **args;
100    char *name = NULL;
101    char *csp_name = NULL;
102    PKCS12 *p12 = NULL;
103    char pass[50], macpass[50];
104    int export_cert = 0;
105    int options = 0;
106    int chain = 0;
107    int badarg = 0;
108    int iter = PKCS12_DEFAULT_ITER;
109    int maciter = PKCS12_DEFAULT_ITER;
110    int twopass = 0;
111    int keytype = 0;
112    int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
113    int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
114    int ret = 1;
115    int macver = 1;
116    int noprompt = 0;
117    STACK *canames = NULL;
118    char *cpass = NULL, *mpass = NULL;
119    char *passargin = NULL, *passargout = NULL, *passarg = NULL;
120    char *passin = NULL, *passout = NULL;
121    char *inrand = NULL;
122    char *CApath = NULL, *CAfile = NULL;
123    char *engine=NULL;
124
125    apps_startup();
126
127    enc = EVP_des_ede3_cbc();
128    if (bio_err == NULL ) bio_err = BIO_new_fp (stderr, BIO_NOCLOSE);
129
130        if (!load_config(bio_err, NULL))
131                goto end;
132
133    args = argv + 1;
134
135
136    while (*args) {
137        if (*args[0] == '-') {
138                if (!strcmp (*args, "-nokeys")) options |= NOKEYS;
139                else if (!strcmp (*args, "-keyex")) keytype = KEY_EX;
140                else if (!strcmp (*args, "-keysig")) keytype = KEY_SIG;
141                else if (!strcmp (*args, "-nocerts")) options |= NOCERTS;
142                else if (!strcmp (*args, "-clcerts")) options |= CLCERTS;
143                else if (!strcmp (*args, "-cacerts")) options |= CACERTS;
144                else if (!strcmp (*args, "-noout")) options |= (NOKEYS|NOCERTS);
145                else if (!strcmp (*args, "-info")) options |= INFO;
146                else if (!strcmp (*args, "-chain")) chain = 1;
147                else if (!strcmp (*args, "-twopass")) twopass = 1;
148                else if (!strcmp (*args, "-nomacver")) macver = 0;
149                else if (!strcmp (*args, "-descert"))
150                        cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
151                else if (!strcmp (*args, "-export")) export_cert = 1;
152                else if (!strcmp (*args, "-des")) enc=EVP_des_cbc();
153#ifndef OPENSSL_NO_IDEA
154                else if (!strcmp (*args, "-idea")) enc=EVP_idea_cbc();
155#endif
156                else if (!strcmp (*args, "-des3")) enc = EVP_des_ede3_cbc();
157#ifndef OPENSSL_NO_AES
158                else if (!strcmp(*args,"-aes128")) enc=EVP_aes_128_cbc();
159                else if (!strcmp(*args,"-aes192")) enc=EVP_aes_192_cbc();
160                else if (!strcmp(*args,"-aes256")) enc=EVP_aes_256_cbc();
161#endif
162                else if (!strcmp (*args, "-noiter")) iter = 1;
163                else if (!strcmp (*args, "-maciter"))
164                                         maciter = PKCS12_DEFAULT_ITER;
165                else if (!strcmp (*args, "-nomaciter"))
166                                         maciter = 1;
167                else if (!strcmp (*args, "-nodes")) enc=NULL;
168                else if (!strcmp (*args, "-certpbe")) {
169                        if (args[1]) {
170                                args++;
171                                cert_pbe=OBJ_txt2nid(*args);
172                                if(cert_pbe == NID_undef) {
173                                        BIO_printf(bio_err,
174                                                 "Unknown PBE algorithm %s\n", *args);
175                                        badarg = 1;
176                                }
177                        } else badarg = 1;
178                } else if (!strcmp (*args, "-keypbe")) {
179                        if (args[1]) {
180                                args++;
181                                key_pbe=OBJ_txt2nid(*args);
182                                if(key_pbe == NID_undef) {
183                                        BIO_printf(bio_err,
184                                                 "Unknown PBE algorithm %s\n", *args);
185                                        badarg = 1;
186                                }
187                        } else badarg = 1;
188                } else if (!strcmp (*args, "-rand")) {
189                    if (args[1]) {
190                        args++;
191                        inrand = *args;
192                    } else badarg = 1;
193                } else if (!strcmp (*args, "-inkey")) {
194                    if (args[1]) {
195                        args++;
196                        keyname = *args;
197                    } else badarg = 1;
198                } else if (!strcmp (*args, "-certfile")) {
199                    if (args[1]) {
200                        args++;
201                        certfile = *args;
202                    } else badarg = 1;
203                } else if (!strcmp (*args, "-name")) {
204                    if (args[1]) {
205                        args++;
206                        name = *args;
207                    } else badarg = 1;
208                } else if (!strcmp (*args, "-CSP")) {
209                    if (args[1]) {
210                        args++;
211                        csp_name = *args;
212                    } else badarg = 1;
213                } else if (!strcmp (*args, "-caname")) {
214                    if (args[1]) {
215                        args++;
216                        if (!canames) canames = sk_new_null();
217                        sk_push(canames, *args);
218                    } else badarg = 1;
219                } else if (!strcmp (*args, "-in")) {
220                    if (args[1]) {
221                        args++;
222                        infile = *args;
223                    } else badarg = 1;
224                } else if (!strcmp (*args, "-out")) {
225                    if (args[1]) {
226                        args++;
227                        outfile = *args;
228                    } else badarg = 1;
229                } else if (!strcmp(*args,"-passin")) {
230                    if (args[1]) {
231                        args++;
232                        passargin = *args;
233                    } else badarg = 1;
234                } else if (!strcmp(*args,"-passout")) {
235                    if (args[1]) {
236                        args++;
237                        passargout = *args;
238                    } else badarg = 1;
239                } else if (!strcmp (*args, "-password")) {
240                    if (args[1]) {
241                        args++;
242                        passarg = *args;
243                        noprompt = 1;
244                    } else badarg = 1;
245                } else if (!strcmp(*args,"-CApath")) {
246                    if (args[1]) {
247                        args++;
248                        CApath = *args;
249                    } else badarg = 1;
250                } else if (!strcmp(*args,"-CAfile")) {
251                    if (args[1]) {
252                        args++;
253                        CAfile = *args;
254                    } else badarg = 1;
255                } else if (!strcmp(*args,"-engine")) {
256                    if (args[1]) {
257                        args++;
258                        engine = *args;
259                    } else badarg = 1;
260                } else badarg = 1;
261
262        } else badarg = 1;
263        args++;
264    }
265
266    if (badarg) {
267        BIO_printf (bio_err, "Usage: pkcs12 [options]\n");
268        BIO_printf (bio_err, "where options are\n");
269        BIO_printf (bio_err, "-export       output PKCS12 file\n");
270        BIO_printf (bio_err, "-chain        add certificate chain\n");
271        BIO_printf (bio_err, "-inkey file   private key if not infile\n");
272        BIO_printf (bio_err, "-certfile f   add all certs in f\n");
273        BIO_printf (bio_err, "-CApath arg   - PEM format directory of CA's\n");
274        BIO_printf (bio_err, "-CAfile arg   - PEM format file of CA's\n");
275        BIO_printf (bio_err, "-name \"name\"  use name as friendly name\n");
276        BIO_printf (bio_err, "-caname \"nm\"  use nm as CA friendly name (can be used more than once).\n");
277        BIO_printf (bio_err, "-in  infile   input filename\n");
278        BIO_printf (bio_err, "-out outfile  output filename\n");
279        BIO_printf (bio_err, "-noout        don't output anything, just verify.\n");
280        BIO_printf (bio_err, "-nomacver     don't verify MAC.\n");
281        BIO_printf (bio_err, "-nocerts      don't output certificates.\n");
282        BIO_printf (bio_err, "-clcerts      only output client certificates.\n");
283        BIO_printf (bio_err, "-cacerts      only output CA certificates.\n");
284        BIO_printf (bio_err, "-nokeys       don't output private keys.\n");
285        BIO_printf (bio_err, "-info         give info about PKCS#12 structure.\n");
286        BIO_printf (bio_err, "-des          encrypt private keys with DES\n");
287        BIO_printf (bio_err, "-des3         encrypt private keys with triple DES (default)\n");
288#ifndef OPENSSL_NO_IDEA
289        BIO_printf (bio_err, "-idea         encrypt private keys with idea\n");
290#endif
291#ifndef OPENSSL_NO_AES
292        BIO_printf (bio_err, "-aes128, -aes192, -aes256\n");
293        BIO_printf (bio_err, "              encrypt PEM output with cbc aes\n");
294#endif
295        BIO_printf (bio_err, "-nodes        don't encrypt private keys\n");
296        BIO_printf (bio_err, "-noiter       don't use encryption iteration\n");
297        BIO_printf (bio_err, "-maciter      use MAC iteration\n");
298        BIO_printf (bio_err, "-twopass      separate MAC, encryption passwords\n");
299        BIO_printf (bio_err, "-descert      encrypt PKCS#12 certificates with triple DES (default RC2-40)\n");
300        BIO_printf (bio_err, "-certpbe alg  specify certificate PBE algorithm (default RC2-40)\n");
301        BIO_printf (bio_err, "-keypbe alg   specify private key PBE algorithm (default 3DES)\n");
302        BIO_printf (bio_err, "-keyex        set MS key exchange type\n");
303        BIO_printf (bio_err, "-keysig       set MS key signature type\n");
304        BIO_printf (bio_err, "-password p   set import/export password source\n");
305        BIO_printf (bio_err, "-passin p     input file pass phrase source\n");
306        BIO_printf (bio_err, "-passout p    output file pass phrase source\n");
307        BIO_printf (bio_err, "-engine e     use engine e, possibly a hardware device.\n");
308        BIO_printf(bio_err,  "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
309        BIO_printf(bio_err,  "              load the file (or the files in the directory) into\n");
310        BIO_printf(bio_err,  "              the random number generator\n");
311        goto end;
312    }
313
314    e = setup_engine(bio_err, engine, 0);
315
316    if(passarg) {
317        if(export_cert) passargout = passarg;
318        else passargin = passarg;
319    }
320
321    if(!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
322        BIO_printf(bio_err, "Error getting passwords\n");
323        goto end;
324    }
325
326    if(!cpass) {
327        if(export_cert) cpass = passout;
328        else cpass = passin;
329    }
330
331    if(cpass) {
332        mpass = cpass;
333        noprompt = 1;
334    } else {
335        cpass = pass;
336        mpass = macpass;
337    }
338
339    if(export_cert || inrand) {
340        app_RAND_load_file(NULL, bio_err, (inrand != NULL));
341        if (inrand != NULL)
342                BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
343                        app_RAND_load_files(inrand));
344    }
345    ERR_load_crypto_strings();
346
347#ifdef CRYPTO_MDEBUG
348    CRYPTO_push_info("read files");
349#endif
350
351    if (!infile) in = BIO_new_fp(stdin, BIO_NOCLOSE);
352    else in = BIO_new_file(infile, "rb");
353    if (!in) {
354            BIO_printf(bio_err, "Error opening input file %s\n",
355                                                infile ? infile : "<stdin>");
356            perror (infile);
357            goto end;
358   }
359
360#if 0
361   if (certfile) {
362        if(!(certsin = BIO_new_file(certfile, "r"))) {
363            BIO_printf(bio_err, "Can't open certificate file %s\n", certfile);
364            perror (certfile);
365            goto end;
366        }
367    }
368
369    if (keyname) {
370        if(!(inkey = BIO_new_file(keyname, "r"))) {
371            BIO_printf(bio_err, "Can't key certificate file %s\n", keyname);
372            perror (keyname);
373            goto end;
374        }
375     }
376#endif
377
378#ifdef CRYPTO_MDEBUG
379    CRYPTO_pop_info();
380    CRYPTO_push_info("write files");
381#endif
382
383    if (!outfile) {
384        out = BIO_new_fp(stdout, BIO_NOCLOSE);
385#ifdef OPENSSL_SYS_VMS
386        {
387            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
388            out = BIO_push(tmpbio, out);
389        }
390#endif
391    } else out = BIO_new_file(outfile, "wb");
392    if (!out) {
393        BIO_printf(bio_err, "Error opening output file %s\n",
394                                                outfile ? outfile : "<stdout>");
395        perror (outfile);
396        goto end;
397    }
398    if (twopass) {
399#ifdef CRYPTO_MDEBUG
400    CRYPTO_push_info("read MAC password");
401#endif
402        if(EVP_read_pw_string (macpass, sizeof macpass, "Enter MAC Password:", export_cert))
403        {
404            BIO_printf (bio_err, "Can't read Password\n");
405            goto end;
406        }
407#ifdef CRYPTO_MDEBUG
408    CRYPTO_pop_info();
409#endif
410    }
411
412    if (export_cert) {
413        EVP_PKEY *key = NULL;
414        STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
415        STACK_OF(PKCS7) *safes = NULL;
416        PKCS12_SAFEBAG *bag = NULL;
417        PKCS8_PRIV_KEY_INFO *p8 = NULL;
418        PKCS7 *authsafe = NULL;
419        X509 *ucert = NULL;
420        STACK_OF(X509) *certs=NULL;
421        char *catmp = NULL;
422        int i;
423        unsigned char keyid[EVP_MAX_MD_SIZE];
424        unsigned int keyidlen = 0;
425
426#ifdef CRYPTO_MDEBUG
427        CRYPTO_push_info("process -export_cert");
428        CRYPTO_push_info("reading private key");
429#endif
430        key = load_key(bio_err, keyname ? keyname : infile, FORMAT_PEM, 1,
431                passin, e, "private key");
432        if (!key) {
433                goto export_end;
434        }
435
436#ifdef CRYPTO_MDEBUG
437        CRYPTO_pop_info();
438        CRYPTO_push_info("reading certs from input");
439#endif
440
441        /* Load in all certs in input file */
442        if(!(certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e,
443                "certificates"))) {
444                goto export_end;
445        }
446
447#ifdef CRYPTO_MDEBUG
448        CRYPTO_pop_info();
449        CRYPTO_push_info("reading certs from input 2");
450#endif
451
452        for(i = 0; i < sk_X509_num(certs); i++) {
453                ucert = sk_X509_value(certs, i);
454                if(X509_check_private_key(ucert, key)) {
455                        X509_digest(ucert, EVP_sha1(), keyid, &keyidlen);
456                        break;
457                }
458        }
459        if(!keyidlen) {
460                ucert = NULL;
461                BIO_printf(bio_err, "No certificate matches private key\n");
462                goto export_end;
463        }
464       
465#ifdef CRYPTO_MDEBUG
466        CRYPTO_pop_info();
467        CRYPTO_push_info("reading certs from certfile");
468#endif
469
470        bags = sk_PKCS12_SAFEBAG_new_null ();
471
472        /* Add any more certificates asked for */
473        if (certfile) {
474                STACK_OF(X509) *morecerts=NULL;
475                if(!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM,
476                                            NULL, e,
477                                            "certificates from certfile"))) {
478                        goto export_end;
479                }
480                while(sk_X509_num(morecerts) > 0) {
481                        sk_X509_push(certs, sk_X509_shift(morecerts));
482                }
483                sk_X509_free(morecerts);
484        }
485
486#ifdef CRYPTO_MDEBUG
487        CRYPTO_pop_info();
488        CRYPTO_push_info("building chain");
489#endif
490
491        /* If chaining get chain from user cert */
492        if (chain) {
493                int vret;
494                STACK_OF(X509) *chain2;
495                X509_STORE *store = X509_STORE_new();
496                if (!store)
497                        {
498                        BIO_printf (bio_err, "Memory allocation error\n");
499                        goto export_end;
500                        }
501                if (!X509_STORE_load_locations(store, CAfile, CApath))
502                        X509_STORE_set_default_paths (store);
503
504                vret = get_cert_chain (ucert, store, &chain2);
505                X509_STORE_free(store);
506
507                if (!vret) {
508                    /* Exclude verified certificate */
509                    for (i = 1; i < sk_X509_num (chain2) ; i++)
510                        sk_X509_push(certs, sk_X509_value (chain2, i));
511                    /* Free first certificate */
512                    X509_free(sk_X509_value(chain2, 0));
513                    sk_X509_free(chain2);
514                } else {
515                        BIO_printf (bio_err, "Error %s getting chain.\n",
516                                        X509_verify_cert_error_string(vret));
517                        goto export_end;
518                }                       
519        }
520
521#ifdef CRYPTO_MDEBUG
522        CRYPTO_pop_info();
523        CRYPTO_push_info("building bags");
524#endif
525
526        /* We now have loads of certificates: include them all */
527        for(i = 0; i < sk_X509_num(certs); i++) {
528                X509 *cert = NULL;
529                cert = sk_X509_value(certs, i);
530                bag = PKCS12_x5092certbag(cert);
531                /* If it matches private key set id */
532                if(cert == ucert) {
533                        if(name) PKCS12_add_friendlyname(bag, name, -1);
534                        PKCS12_add_localkeyid(bag, keyid, keyidlen);
535                } else if((catmp = sk_shift(canames)))
536                                PKCS12_add_friendlyname(bag, catmp, -1);
537                sk_PKCS12_SAFEBAG_push(bags, bag);
538        }
539        sk_X509_pop_free(certs, X509_free);
540        certs = NULL;
541
542#ifdef CRYPTO_MDEBUG
543        CRYPTO_pop_info();
544        CRYPTO_push_info("encrypting bags");
545#endif
546
547        if(!noprompt &&
548                EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:", 1)) {
549            BIO_printf (bio_err, "Can't read Password\n");
550            goto export_end;
551        }
552        if (!twopass) strcpy(macpass, pass);
553        /* Turn certbags into encrypted authsafe */
554        authsafe = PKCS12_pack_p7encdata(cert_pbe, cpass, -1, NULL, 0,
555                                                                 iter, bags);
556        sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
557        bags = NULL;
558
559        if (!authsafe) {
560                ERR_print_errors (bio_err);
561                goto export_end;
562        }
563
564        safes = sk_PKCS7_new_null ();
565        sk_PKCS7_push (safes, authsafe);
566
567#ifdef CRYPTO_MDEBUG
568        CRYPTO_pop_info();
569        CRYPTO_push_info("building shrouded key bag");
570#endif
571
572        /* Make a shrouded key bag */
573        p8 = EVP_PKEY2PKCS8 (key);
574        if(keytype) PKCS8_add_keyusage(p8, keytype);
575        bag = PKCS12_MAKE_SHKEYBAG(key_pbe, cpass, -1, NULL, 0, iter, p8);
576        PKCS8_PRIV_KEY_INFO_free(p8);
577        p8 = NULL;
578        if (name) PKCS12_add_friendlyname (bag, name, -1);
579        if(csp_name) PKCS12_add_CSPName_asc(bag, csp_name, -1);
580        PKCS12_add_localkeyid (bag, keyid, keyidlen);
581        bags = sk_PKCS12_SAFEBAG_new_null();
582        sk_PKCS12_SAFEBAG_push (bags, bag);
583
584#ifdef CRYPTO_MDEBUG
585        CRYPTO_pop_info();
586        CRYPTO_push_info("encrypting shrouded key bag");
587#endif
588
589        /* Turn it into unencrypted safe bag */
590        authsafe = PKCS12_pack_p7data (bags);
591        sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
592        bags = NULL;
593        sk_PKCS7_push (safes, authsafe);
594
595#ifdef CRYPTO_MDEBUG
596        CRYPTO_pop_info();
597        CRYPTO_push_info("building pkcs12");
598#endif
599
600        p12 = PKCS12_init(NID_pkcs7_data);
601
602        PKCS12_pack_authsafes(p12, safes);
603
604        sk_PKCS7_pop_free(safes, PKCS7_free);
605        safes = NULL;
606
607        PKCS12_set_mac (p12, mpass, -1, NULL, 0, maciter, NULL);
608
609#ifdef CRYPTO_MDEBUG
610        CRYPTO_pop_info();
611        CRYPTO_push_info("writing pkcs12");
612#endif
613
614        i2d_PKCS12_bio (out, p12);
615
616        ret = 0;
617
618    export_end:
619#ifdef CRYPTO_MDEBUG
620        CRYPTO_pop_info();
621        CRYPTO_pop_info();
622        CRYPTO_push_info("process -export_cert: freeing");
623#endif
624
625        if (key) EVP_PKEY_free(key);
626        if (certs) sk_X509_pop_free(certs, X509_free);
627        if (safes) sk_PKCS7_pop_free(safes, PKCS7_free);
628        if (bags) sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
629
630#ifdef CRYPTO_MDEBUG
631        CRYPTO_pop_info();
632#endif
633        goto end;
634       
635    }
636
637    if (!(p12 = d2i_PKCS12_bio (in, NULL))) {
638        ERR_print_errors(bio_err);
639        goto end;
640    }
641
642#ifdef CRYPTO_MDEBUG
643    CRYPTO_push_info("read import password");
644#endif
645    if(!noprompt && EVP_read_pw_string(pass, sizeof pass, "Enter Import Password:", 0)) {
646        BIO_printf (bio_err, "Can't read Password\n");
647        goto end;
648    }
649#ifdef CRYPTO_MDEBUG
650    CRYPTO_pop_info();
651#endif
652
653    if (!twopass) strcpy(macpass, pass);
654
655    if (options & INFO) BIO_printf (bio_err, "MAC Iteration %ld\n", p12->mac->iter ? ASN1_INTEGER_get (p12->mac->iter) : 1);
656    if(macver) {
657#ifdef CRYPTO_MDEBUG
658    CRYPTO_push_info("verify MAC");
659#endif
660        /* If we enter empty password try no password first */
661        if(!macpass[0] && PKCS12_verify_mac(p12, NULL, 0)) {
662                /* If mac and crypto pass the same set it to NULL too */
663                if(!twopass) cpass = NULL;
664        } else if (!PKCS12_verify_mac(p12, mpass, -1)) {
665            BIO_printf (bio_err, "Mac verify error: invalid password?\n");
666            ERR_print_errors (bio_err);
667            goto end;
668        }
669        BIO_printf (bio_err, "MAC verified OK\n");
670#ifdef CRYPTO_MDEBUG
671    CRYPTO_pop_info();
672#endif
673    }
674
675#ifdef CRYPTO_MDEBUG
676    CRYPTO_push_info("output keys and certificates");
677#endif
678    if (!dump_certs_keys_p12 (out, p12, cpass, -1, options, passout)) {
679        BIO_printf(bio_err, "Error outputting keys and certificates\n");
680        ERR_print_errors (bio_err);
681        goto end;
682    }
683#ifdef CRYPTO_MDEBUG
684    CRYPTO_pop_info();
685#endif
686    ret = 0;
687 end:
688    if (p12) PKCS12_free(p12);
689    if(export_cert || inrand) app_RAND_write_file(NULL, bio_err);
690#ifdef CRYPTO_MDEBUG
691    CRYPTO_remove_all_info();
692#endif
693    BIO_free(in);
694    BIO_free_all(out);
695    if (canames) sk_free(canames);
696    if(passin) OPENSSL_free(passin);
697    if(passout) OPENSSL_free(passout);
698    apps_shutdown();
699    OPENSSL_EXIT(ret);
700}
701
702int dump_certs_keys_p12 (BIO *out, PKCS12 *p12, char *pass,
703             int passlen, int options, char *pempass)
704{
705        STACK_OF(PKCS7) *asafes;
706        STACK_OF(PKCS12_SAFEBAG) *bags;
707        int i, bagnid;
708        PKCS7 *p7;
709
710        if (!( asafes = PKCS12_unpack_authsafes(p12))) return 0;
711        for (i = 0; i < sk_PKCS7_num (asafes); i++) {
712                p7 = sk_PKCS7_value (asafes, i);
713                bagnid = OBJ_obj2nid (p7->type);
714                if (bagnid == NID_pkcs7_data) {
715                        bags = PKCS12_unpack_p7data(p7);
716                        if (options & INFO) BIO_printf (bio_err, "PKCS7 Data\n");
717                } else if (bagnid == NID_pkcs7_encrypted) {
718                        if (options & INFO) {
719                                BIO_printf(bio_err, "PKCS7 Encrypted data: ");
720                                alg_print(bio_err,
721                                        p7->d.encrypted->enc_data->algorithm);
722                        }
723                        bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
724                } else continue;
725                if (!bags) return 0;
726                if (!dump_certs_pkeys_bags (out, bags, pass, passlen,
727                                                 options, pempass)) {
728                        sk_PKCS12_SAFEBAG_pop_free (bags, PKCS12_SAFEBAG_free);
729                        return 0;
730                }
731                sk_PKCS12_SAFEBAG_pop_free (bags, PKCS12_SAFEBAG_free);
732        }
733        sk_PKCS7_pop_free (asafes, PKCS7_free);
734        return 1;
735}
736
737int dump_certs_pkeys_bags (BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags,
738                           char *pass, int passlen, int options, char *pempass)
739{
740        int i;
741        for (i = 0; i < sk_PKCS12_SAFEBAG_num (bags); i++) {
742                if (!dump_certs_pkeys_bag (out,
743                                           sk_PKCS12_SAFEBAG_value (bags, i),
744                                           pass, passlen,
745                                           options, pempass))
746                    return 0;
747        }
748        return 1;
749}
750
751int dump_certs_pkeys_bag (BIO *out, PKCS12_SAFEBAG *bag, char *pass,
752             int passlen, int options, char *pempass)
753{
754        EVP_PKEY *pkey;
755        PKCS8_PRIV_KEY_INFO *p8;
756        X509 *x509;
757       
758        switch (M_PKCS12_bag_type(bag))
759        {
760        case NID_keyBag:
761                if (options & INFO) BIO_printf (bio_err, "Key bag\n");
762                if (options & NOKEYS) return 1;
763                print_attribs (out, bag->attrib, "Bag Attributes");
764                p8 = bag->value.keybag;
765                if (!(pkey = EVP_PKCS82PKEY (p8))) return 0;
766                print_attribs (out, p8->attributes, "Key Attributes");
767                PEM_write_bio_PrivateKey (out, pkey, enc, NULL, 0, NULL, pempass);
768                EVP_PKEY_free(pkey);
769        break;
770
771        case NID_pkcs8ShroudedKeyBag:
772                if (options & INFO) {
773                        BIO_printf (bio_err, "Shrouded Keybag: ");
774                        alg_print (bio_err, bag->value.shkeybag->algor);
775                }
776                if (options & NOKEYS) return 1;
777                print_attribs (out, bag->attrib, "Bag Attributes");
778                if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen)))
779                                return 0;
780                if (!(pkey = EVP_PKCS82PKEY (p8))) {
781                        PKCS8_PRIV_KEY_INFO_free(p8);
782                        return 0;
783                }
784                print_attribs (out, p8->attributes, "Key Attributes");
785                PKCS8_PRIV_KEY_INFO_free(p8);
786                PEM_write_bio_PrivateKey (out, pkey, enc, NULL, 0, NULL, pempass);
787                EVP_PKEY_free(pkey);
788        break;
789
790        case NID_certBag:
791                if (options & INFO) BIO_printf (bio_err, "Certificate bag\n");
792                if (options & NOCERTS) return 1;
793                if (PKCS12_get_attr(bag, NID_localKeyID)) {
794                        if (options & CACERTS) return 1;
795                } else if (options & CLCERTS) return 1;
796                print_attribs (out, bag->attrib, "Bag Attributes");
797                if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate )
798                                                                 return 1;
799                if (!(x509 = PKCS12_certbag2x509(bag))) return 0;
800                dump_cert_text (out, x509);
801                PEM_write_bio_X509 (out, x509);
802                X509_free(x509);
803        break;
804
805        case NID_safeContentsBag:
806                if (options & INFO) BIO_printf (bio_err, "Safe Contents bag\n");
807                print_attribs (out, bag->attrib, "Bag Attributes");
808                return dump_certs_pkeys_bags (out, bag->value.safes, pass,
809                                                            passlen, options, pempass);
810                                       
811        default:
812                BIO_printf (bio_err, "Warning unsupported bag type: ");
813                i2a_ASN1_OBJECT (bio_err, bag->type);
814                BIO_printf (bio_err, "\n");
815                return 1;
816        break;
817        }
818        return 1;
819}
820
821/* Given a single certificate return a verified chain or NULL if error */
822
823/* Hope this is OK .... */
824
825int get_cert_chain (X509 *cert, X509_STORE *store, STACK_OF(X509) **chain)
826{
827        X509_STORE_CTX store_ctx;
828        STACK_OF(X509) *chn;
829        int i;
830
831        /* FIXME: Should really check the return status of X509_STORE_CTX_init
832         * for an error, but how that fits into the return value of this
833         * function is less obvious. */
834        X509_STORE_CTX_init(&store_ctx, store, cert, NULL);
835        if (X509_verify_cert(&store_ctx) <= 0) {
836                i = X509_STORE_CTX_get_error (&store_ctx);
837                goto err;
838        }
839        chn =  X509_STORE_CTX_get1_chain(&store_ctx);
840        i = 0;
841        *chain = chn;
842err:
843        X509_STORE_CTX_cleanup(&store_ctx);
844       
845        return i;
846}       
847
848int alg_print (BIO *x, X509_ALGOR *alg)
849{
850        PBEPARAM *pbe;
851        unsigned char *p;
852        p = alg->parameter->value.sequence->data;
853        pbe = d2i_PBEPARAM (NULL, &p, alg->parameter->value.sequence->length);
854        BIO_printf (bio_err, "%s, Iteration %d\n",
855        OBJ_nid2ln(OBJ_obj2nid(alg->algorithm)), ASN1_INTEGER_get(pbe->iter));
856        PBEPARAM_free (pbe);
857        return 0;
858}
859
860/* Load all certificates from a given file */
861
862int cert_load(BIO *in, STACK_OF(X509) *sk)
863{
864        int ret;
865        X509 *cert;
866        ret = 0;
867#ifdef CRYPTO_MDEBUG
868        CRYPTO_push_info("cert_load(): reading one cert");
869#endif
870        while((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
871#ifdef CRYPTO_MDEBUG
872                CRYPTO_pop_info();
873#endif
874                ret = 1;
875                sk_X509_push(sk, cert);
876#ifdef CRYPTO_MDEBUG
877                CRYPTO_push_info("cert_load(): reading one cert");
878#endif
879        }
880#ifdef CRYPTO_MDEBUG
881        CRYPTO_pop_info();
882#endif
883        if(ret) ERR_clear_error();
884        return ret;
885}
886
887/* Generalised attribute print: handle PKCS#8 and bag attributes */
888
889int print_attribs (BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst, char *name)
890{
891        X509_ATTRIBUTE *attr;
892        ASN1_TYPE *av;
893        char *value;
894        int i, attr_nid;
895        if(!attrlst) {
896                BIO_printf(out, "%s: <No Attributes>\n", name);
897                return 1;
898        }
899        if(!sk_X509_ATTRIBUTE_num(attrlst)) {
900                BIO_printf(out, "%s: <Empty Attributes>\n", name);
901                return 1;
902        }
903        BIO_printf(out, "%s\n", name);
904        for(i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) {
905                attr = sk_X509_ATTRIBUTE_value(attrlst, i);
906                attr_nid = OBJ_obj2nid(attr->object);
907                BIO_printf(out, "    ");
908                if(attr_nid == NID_undef) {
909                        i2a_ASN1_OBJECT (out, attr->object);
910                        BIO_printf(out, ": ");
911                } else BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid));
912
913                if(sk_ASN1_TYPE_num(attr->value.set)) {
914                        av = sk_ASN1_TYPE_value(attr->value.set, 0);
915                        switch(av->type) {
916                                case V_ASN1_BMPSTRING:
917                                value = uni2asc(av->value.bmpstring->data,
918                                               av->value.bmpstring->length);
919                                BIO_printf(out, "%s\n", value);
920                                OPENSSL_free(value);
921                                break;
922
923                                case V_ASN1_OCTET_STRING:
924                                hex_prin(out, av->value.octet_string->data,
925                                        av->value.octet_string->length);
926                                BIO_printf(out, "\n"); 
927                                break;
928
929                                case V_ASN1_BIT_STRING:
930                                hex_prin(out, av->value.bit_string->data,
931                                        av->value.bit_string->length);
932                                BIO_printf(out, "\n"); 
933                                break;
934
935                                default:
936                                        BIO_printf(out, "<Unsupported tag %d>\n", av->type);
937                                break;
938                        }
939                } else BIO_printf(out, "<No Values>\n");
940        }
941        return 1;
942}
943
944void hex_prin(BIO *out, unsigned char *buf, int len)
945{
946        int i;
947        for (i = 0; i < len; i++) BIO_printf (out, "%02X ", buf[i]);
948}
949
950#endif
Note: See TracBrowser for help on using the repository browser.