Main Page | Class List | Directories | File List | Class Members | File Members

pkcs12.c

Go to the documentation of this file.
00001 /* pkcs12.c */
00002 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
00003  * project.
00004  */
00005 /* ====================================================================
00006  * Copyright (c) 1999-2002 The OpenSSL Project.  All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions
00010  * are met:
00011  *
00012  * 1. Redistributions of source code must retain the above copyright
00013  *    notice, this list of conditions and the following disclaimer. 
00014  *
00015  * 2. Redistributions in binary form must reproduce the above copyright
00016  *    notice, this list of conditions and the following disclaimer in
00017  *    the documentation and/or other materials provided with the
00018  *    distribution.
00019  *
00020  * 3. All advertising materials mentioning features or use of this
00021  *    software must display the following acknowledgment:
00022  *    "This product includes software developed by the OpenSSL Project
00023  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
00024  *
00025  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
00026  *    endorse or promote products derived from this software without
00027  *    prior written permission. For written permission, please contact
00028  *    licensing@OpenSSL.org.
00029  *
00030  * 5. Products derived from this software may not be called "OpenSSL"
00031  *    nor may "OpenSSL" appear in their names without prior written
00032  *    permission of the OpenSSL Project.
00033  *
00034  * 6. Redistributions of any form whatsoever must retain the following
00035  *    acknowledgment:
00036  *    "This product includes software developed by the OpenSSL Project
00037  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
00038  *
00039  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
00040  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00041  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00042  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
00043  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00044  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00045  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00046  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00047  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00048  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00049  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00050  * OF THE POSSIBILITY OF SUCH DAMAGE.
00051  * ====================================================================
00052  *
00053  * This product includes cryptographic software written by Eric Young
00054  * (eay@cryptsoft.com).  This product includes software written by Tim
00055  * Hudson (tjh@cryptsoft.com).
00056  *
00057  */
00058 
00059 #include <openssl/opensslconf.h>
00060 #if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_SHA1)
00061 
00062 #include <stdio.h>
00063 #include <stdlib.h>
00064 #include <string.h>
00065 #include "apps.h"
00066 #include <openssl/crypto.h>
00067 #include <openssl/err.h>
00068 #include <openssl/pem.h>
00069 #include <openssl/pkcs12.h>
00070 
00071 #define PROG pkcs12_main
00072 
00073 const EVP_CIPHER *enc;
00074 
00075 
00076 #define NOKEYS          0x1
00077 #define NOCERTS         0x2
00078 #define INFO            0x4
00079 #define CLCERTS         0x8
00080 #define CACERTS         0x10
00081 
00082 int get_cert_chain (X509 *cert, X509_STORE *store, STACK_OF(X509) **chain);
00083 int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen, int options, char *pempass);
00084 int dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags, char *pass,
00085                           int passlen, int options, char *pempass);
00086 int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bags, char *pass, int passlen, int options, char *pempass);
00087 int print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst,const char *name);
00088 void hex_prin(BIO *out, unsigned char *buf, int len);
00089 int alg_print(BIO *x, X509_ALGOR *alg);
00090 int cert_load(BIO *in, STACK_OF(X509) *sk);
00091 
00092 int MAIN(int, char **);
00093 
00094 int MAIN(int argc, char **argv)
00095 {
00096     ENGINE *e = NULL;
00097     char *infile=NULL, *outfile=NULL, *keyname = NULL;  
00098     char *certfile=NULL;
00099     BIO *in=NULL, *out = NULL;
00100     char **args;
00101     char *name = NULL;
00102     char *csp_name = NULL;
00103     PKCS12 *p12 = NULL;
00104     char pass[50], macpass[50];
00105     int export_cert = 0;
00106     int options = 0;
00107     int chain = 0;
00108     int badarg = 0;
00109     int iter = PKCS12_DEFAULT_ITER;
00110     int maciter = PKCS12_DEFAULT_ITER;
00111     int twopass = 0;
00112     int keytype = 0;
00113     int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
00114     int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
00115     int ret = 1;
00116     int macver = 1;
00117     int noprompt = 0;
00118     STACK *canames = NULL;
00119     char *cpass = NULL, *mpass = NULL;
00120     char *passargin = NULL, *passargout = NULL, *passarg = NULL;
00121     char *passin = NULL, *passout = NULL;
00122     char *inrand = NULL;
00123     char *CApath = NULL, *CAfile = NULL;
00124 #ifndef OPENSSL_NO_ENGINE
00125     char *engine=NULL;
00126 #endif
00127 
00128     apps_startup();
00129 
00130     enc = EVP_des_ede3_cbc();
00131     if (bio_err == NULL ) bio_err = BIO_new_fp (stderr, BIO_NOCLOSE);
00132 
00133         if (!load_config(bio_err, NULL))
00134                 goto end;
00135 
00136     args = argv + 1;
00137 
00138 
00139     while (*args) {
00140         if (*args[0] == '-') {
00141                 if (!strcmp (*args, "-nokeys")) options |= NOKEYS;
00142                 else if (!strcmp (*args, "-keyex")) keytype = KEY_EX;
00143                 else if (!strcmp (*args, "-keysig")) keytype = KEY_SIG;
00144                 else if (!strcmp (*args, "-nocerts")) options |= NOCERTS;
00145                 else if (!strcmp (*args, "-clcerts")) options |= CLCERTS;
00146                 else if (!strcmp (*args, "-cacerts")) options |= CACERTS;
00147                 else if (!strcmp (*args, "-noout")) options |= (NOKEYS|NOCERTS);
00148                 else if (!strcmp (*args, "-info")) options |= INFO;
00149                 else if (!strcmp (*args, "-chain")) chain = 1;
00150                 else if (!strcmp (*args, "-twopass")) twopass = 1;
00151                 else if (!strcmp (*args, "-nomacver")) macver = 0;
00152                 else if (!strcmp (*args, "-descert"))
00153                         cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
00154                 else if (!strcmp (*args, "-export")) export_cert = 1;
00155                 else if (!strcmp (*args, "-des")) enc=EVP_des_cbc();
00156 #ifndef OPENSSL_NO_IDEA
00157                 else if (!strcmp (*args, "-idea")) enc=EVP_idea_cbc();
00158 #endif
00159                 else if (!strcmp (*args, "-des3")) enc = EVP_des_ede3_cbc();
00160 #ifndef OPENSSL_NO_AES
00161                 else if (!strcmp(*args,"-aes128")) enc=EVP_aes_128_cbc();
00162                 else if (!strcmp(*args,"-aes192")) enc=EVP_aes_192_cbc();
00163                 else if (!strcmp(*args,"-aes256")) enc=EVP_aes_256_cbc();
00164 #endif
00165                 else if (!strcmp (*args, "-noiter")) iter = 1;
00166                 else if (!strcmp (*args, "-maciter"))
00167                                          maciter = PKCS12_DEFAULT_ITER;
00168                 else if (!strcmp (*args, "-nomaciter"))
00169                                          maciter = 1;
00170                 else if (!strcmp (*args, "-nomac"))
00171                                          maciter = -1;
00172                 else if (!strcmp (*args, "-nodes")) enc=NULL;
00173                 else if (!strcmp (*args, "-certpbe")) {
00174                         if (args[1]) {
00175                                 args++;
00176                                 if (!strcmp(*args, "NONE"))
00177                                         cert_pbe = -1;
00178                                 cert_pbe=OBJ_txt2nid(*args);
00179                                 if(cert_pbe == NID_undef) {
00180                                         BIO_printf(bio_err,
00181                                                  "Unknown PBE algorithm %s\n", *args);
00182                                         badarg = 1;
00183                                 }
00184                         } else badarg = 1;
00185                 } else if (!strcmp (*args, "-keypbe")) {
00186                         if (args[1]) {
00187                                 args++;
00188                                 if (!strcmp(*args, "NONE"))
00189                                         key_pbe = -1;
00190                                 else
00191                                         key_pbe=OBJ_txt2nid(*args);
00192                                 if(key_pbe == NID_undef) {
00193                                         BIO_printf(bio_err,
00194                                                  "Unknown PBE algorithm %s\n", *args);
00195                                         badarg = 1;
00196                                 }
00197                         } else badarg = 1;
00198                 } else if (!strcmp (*args, "-rand")) {
00199                     if (args[1]) {
00200                         args++; 
00201                         inrand = *args;
00202                     } else badarg = 1;
00203                 } else if (!strcmp (*args, "-inkey")) {
00204                     if (args[1]) {
00205                         args++; 
00206                         keyname = *args;
00207                     } else badarg = 1;
00208                 } else if (!strcmp (*args, "-certfile")) {
00209                     if (args[1]) {
00210                         args++; 
00211                         certfile = *args;
00212                     } else badarg = 1;
00213                 } else if (!strcmp (*args, "-name")) {
00214                     if (args[1]) {
00215                         args++; 
00216                         name = *args;
00217                     } else badarg = 1;
00218                 } else if (!strcmp (*args, "-CSP")) {
00219                     if (args[1]) {
00220                         args++; 
00221                         csp_name = *args;
00222                     } else badarg = 1;
00223                 } else if (!strcmp (*args, "-caname")) {
00224                     if (args[1]) {
00225                         args++; 
00226                         if (!canames) canames = sk_new_null();
00227                         sk_push(canames, *args);
00228                     } else badarg = 1;
00229                 } else if (!strcmp (*args, "-in")) {
00230                     if (args[1]) {
00231                         args++; 
00232                         infile = *args;
00233                     } else badarg = 1;
00234                 } else if (!strcmp (*args, "-out")) {
00235                     if (args[1]) {
00236                         args++; 
00237                         outfile = *args;
00238                     } else badarg = 1;
00239                 } else if (!strcmp(*args,"-passin")) {
00240                     if (args[1]) {
00241                         args++; 
00242                         passargin = *args;
00243                     } else badarg = 1;
00244                 } else if (!strcmp(*args,"-passout")) {
00245                     if (args[1]) {
00246                         args++; 
00247                         passargout = *args;
00248                     } else badarg = 1;
00249                 } else if (!strcmp (*args, "-password")) {
00250                     if (args[1]) {
00251                         args++; 
00252                         passarg = *args;
00253                         noprompt = 1;
00254                     } else badarg = 1;
00255                 } else if (!strcmp(*args,"-CApath")) {
00256                     if (args[1]) {
00257                         args++; 
00258                         CApath = *args;
00259                     } else badarg = 1;
00260                 } else if (!strcmp(*args,"-CAfile")) {
00261                     if (args[1]) {
00262                         args++; 
00263                         CAfile = *args;
00264                     } else badarg = 1;
00265 #ifndef OPENSSL_NO_ENGINE
00266                 } else if (!strcmp(*args,"-engine")) {
00267                     if (args[1]) {
00268                         args++; 
00269                         engine = *args;
00270                     } else badarg = 1;
00271 #endif
00272                 } else badarg = 1;
00273 
00274         } else badarg = 1;
00275         args++;
00276     }
00277 
00278     if (badarg) {
00279         BIO_printf (bio_err, "Usage: pkcs12 [options]\n");
00280         BIO_printf (bio_err, "where options are\n");
00281         BIO_printf (bio_err, "-export       output PKCS12 file\n");
00282         BIO_printf (bio_err, "-chain        add certificate chain\n");
00283         BIO_printf (bio_err, "-inkey file   private key if not infile\n");
00284         BIO_printf (bio_err, "-certfile f   add all certs in f\n");
00285         BIO_printf (bio_err, "-CApath arg   - PEM format directory of CA's\n");
00286         BIO_printf (bio_err, "-CAfile arg   - PEM format file of CA's\n");
00287         BIO_printf (bio_err, "-name \"name\"  use name as friendly name\n");
00288         BIO_printf (bio_err, "-caname \"nm\"  use nm as CA friendly name (can be used more than once).\n");
00289         BIO_printf (bio_err, "-in  infile   input filename\n");
00290         BIO_printf (bio_err, "-out outfile  output filename\n");
00291         BIO_printf (bio_err, "-noout        don't output anything, just verify.\n");
00292         BIO_printf (bio_err, "-nomacver     don't verify MAC.\n");
00293         BIO_printf (bio_err, "-nocerts      don't output certificates.\n");
00294         BIO_printf (bio_err, "-clcerts      only output client certificates.\n");
00295         BIO_printf (bio_err, "-cacerts      only output CA certificates.\n");
00296         BIO_printf (bio_err, "-nokeys       don't output private keys.\n");
00297         BIO_printf (bio_err, "-info         give info about PKCS#12 structure.\n");
00298         BIO_printf (bio_err, "-des          encrypt private keys with DES\n");
00299         BIO_printf (bio_err, "-des3         encrypt private keys with triple DES (default)\n");
00300 #ifndef OPENSSL_NO_IDEA
00301         BIO_printf (bio_err, "-idea         encrypt private keys with idea\n");
00302 #endif
00303 #ifndef OPENSSL_NO_AES
00304         BIO_printf (bio_err, "-aes128, -aes192, -aes256\n");
00305         BIO_printf (bio_err, "              encrypt PEM output with cbc aes\n");
00306 #endif
00307         BIO_printf (bio_err, "-nodes        don't encrypt private keys\n");
00308         BIO_printf (bio_err, "-noiter       don't use encryption iteration\n");
00309         BIO_printf (bio_err, "-maciter      use MAC iteration\n");
00310         BIO_printf (bio_err, "-twopass      separate MAC, encryption passwords\n");
00311         BIO_printf (bio_err, "-descert      encrypt PKCS#12 certificates with triple DES (default RC2-40)\n");
00312         BIO_printf (bio_err, "-certpbe alg  specify certificate PBE algorithm (default RC2-40)\n");
00313         BIO_printf (bio_err, "-keypbe alg   specify private key PBE algorithm (default 3DES)\n");
00314         BIO_printf (bio_err, "-keyex        set MS key exchange type\n");
00315         BIO_printf (bio_err, "-keysig       set MS key signature type\n");
00316         BIO_printf (bio_err, "-password p   set import/export password source\n");
00317         BIO_printf (bio_err, "-passin p     input file pass phrase source\n");
00318         BIO_printf (bio_err, "-passout p    output file pass phrase source\n");
00319 #ifndef OPENSSL_NO_ENGINE
00320         BIO_printf (bio_err, "-engine e     use engine e, possibly a hardware device.\n");
00321 #endif
00322         BIO_printf(bio_err,  "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
00323         BIO_printf(bio_err,  "              load the file (or the files in the directory) into\n");
00324         BIO_printf(bio_err,  "              the random number generator\n");
00325         goto end;
00326     }
00327 
00328 #ifndef OPENSSL_NO_ENGINE
00329     e = setup_engine(bio_err, engine, 0);
00330 #endif
00331 
00332     if(passarg) {
00333         if(export_cert) passargout = passarg;
00334         else passargin = passarg;
00335     }
00336 
00337     if(!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
00338         BIO_printf(bio_err, "Error getting passwords\n");
00339         goto end;
00340     }
00341 
00342     if(!cpass) {
00343         if(export_cert) cpass = passout;
00344         else cpass = passin;
00345     }
00346 
00347     if(cpass) {
00348         mpass = cpass;
00349         noprompt = 1;
00350     } else {
00351         cpass = pass;
00352         mpass = macpass;
00353     }
00354 
00355     if(export_cert || inrand) {
00356         app_RAND_load_file(NULL, bio_err, (inrand != NULL));
00357         if (inrand != NULL)
00358                 BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
00359                         app_RAND_load_files(inrand));
00360     }
00361     ERR_load_crypto_strings();
00362 
00363 #ifdef CRYPTO_MDEBUG
00364     CRYPTO_push_info("read files");
00365 #endif
00366 
00367     if (!infile) in = BIO_new_fp(stdin, BIO_NOCLOSE);
00368     else in = BIO_new_file(infile, "rb");
00369     if (!in) {
00370             BIO_printf(bio_err, "Error opening input file %s\n",
00371                                                 infile ? infile : "<stdin>");
00372             perror (infile);
00373             goto end;
00374    }
00375 
00376 #ifdef CRYPTO_MDEBUG
00377     CRYPTO_pop_info();
00378     CRYPTO_push_info("write files");
00379 #endif
00380 
00381     if (!outfile) {
00382         out = BIO_new_fp(stdout, BIO_NOCLOSE);
00383 #ifdef OPENSSL_SYS_VMS
00384         {
00385             BIO *tmpbio = BIO_new(BIO_f_linebuffer());
00386             out = BIO_push(tmpbio, out);
00387         }
00388 #endif
00389     } else out = BIO_new_file(outfile, "wb");
00390     if (!out) {
00391         BIO_printf(bio_err, "Error opening output file %s\n",
00392                                                 outfile ? outfile : "<stdout>");
00393         perror (outfile);
00394         goto end;
00395     }
00396     if (twopass) {
00397 #ifdef CRYPTO_MDEBUG
00398     CRYPTO_push_info("read MAC password");
00399 #endif
00400         if(EVP_read_pw_string (macpass, sizeof macpass, "Enter MAC Password:", export_cert))
00401         {
00402             BIO_printf (bio_err, "Can't read Password\n");
00403             goto end;
00404         }
00405 #ifdef CRYPTO_MDEBUG
00406     CRYPTO_pop_info();
00407 #endif
00408     }
00409 
00410     if (export_cert) {
00411         EVP_PKEY *key = NULL;
00412         X509 *ucert = NULL, *x = NULL;
00413         STACK_OF(X509) *certs=NULL;
00414         unsigned char *catmp = NULL;
00415         int i;
00416 
00417         if ((options & (NOCERTS|NOKEYS)) == (NOCERTS|NOKEYS))
00418                 {       
00419                 BIO_printf(bio_err, "Nothing to do!\n");
00420                 goto export_end;
00421                 }
00422 
00423         if (options & NOCERTS)
00424                 chain = 0;
00425 
00426 #ifdef CRYPTO_MDEBUG
00427         CRYPTO_push_info("process -export_cert");
00428         CRYPTO_push_info("reading private key");
00429 #endif
00430         if (!(options & NOKEYS))
00431                 {
00432                 key = load_key(bio_err, keyname ? keyname : infile,
00433                                 FORMAT_PEM, 1, passin, e, "private key");
00434                 if (!key)
00435                         goto export_end;
00436                 }
00437 
00438 #ifdef CRYPTO_MDEBUG
00439         CRYPTO_pop_info();
00440         CRYPTO_push_info("reading certs from input");
00441 #endif
00442 
00443         /* Load in all certs in input file */
00444         if(!(options & NOCERTS))
00445                 {
00446                 certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e,
00447                                                         "certificates");
00448                 if (!certs)
00449                         goto export_end;
00450 
00451                 if (key)
00452                         {
00453                         /* Look for matching private key */
00454                         for(i = 0; i < sk_X509_num(certs); i++)
00455                                 {
00456                                 x = sk_X509_value(certs, i);
00457                                 if(X509_check_private_key(x, key))
00458                                         {
00459                                         ucert = x;
00460                                         /* Zero keyid and alias */
00461                                         X509_keyid_set1(ucert, NULL, 0);
00462                                         X509_alias_set1(ucert, NULL, 0);
00463                                         /* Remove from list */
00464                                         sk_X509_delete(certs, i);
00465                                         break;
00466                                         }
00467                                 }
00468                         if (!ucert)
00469                                 {
00470                                 BIO_printf(bio_err, "No certificate matches private key\n");
00471                                 goto export_end;
00472                                 }
00473                         }
00474 
00475                 }
00476 
00477 #ifdef CRYPTO_MDEBUG
00478         CRYPTO_pop_info();
00479         CRYPTO_push_info("reading certs from input 2");
00480 #endif
00481 
00482         /* Add any more certificates asked for */
00483         if(certfile)
00484                 {
00485                 STACK_OF(X509) *morecerts=NULL;
00486                 if(!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM,
00487                                             NULL, e,
00488                                             "certificates from certfile")))
00489                         goto export_end;
00490                 while(sk_X509_num(morecerts) > 0)
00491                         sk_X509_push(certs, sk_X509_shift(morecerts));
00492                 sk_X509_free(morecerts);
00493                 }
00494 
00495 #ifdef CRYPTO_MDEBUG
00496         CRYPTO_pop_info();
00497         CRYPTO_push_info("reading certs from certfile");
00498 #endif
00499 
00500 #ifdef CRYPTO_MDEBUG
00501         CRYPTO_pop_info();
00502         CRYPTO_push_info("building chain");
00503 #endif
00504 
00505         /* If chaining get chain from user cert */
00506         if (chain) {
00507                 int vret;
00508                 STACK_OF(X509) *chain2;
00509                 X509_STORE *store = X509_STORE_new();
00510                 if (!store)
00511                         {
00512                         BIO_printf (bio_err, "Memory allocation error\n");
00513                         goto export_end;
00514                         }
00515                 if (!X509_STORE_load_locations(store, CAfile, CApath))
00516                         X509_STORE_set_default_paths (store);
00517 
00518                 vret = get_cert_chain (ucert, store, &chain2);
00519                 X509_STORE_free(store);
00520 
00521                 if (!vret) {
00522                     /* Exclude verified certificate */
00523                     for (i = 1; i < sk_X509_num (chain2) ; i++) 
00524                         sk_X509_push(certs, sk_X509_value (chain2, i));
00525                     /* Free first certificate */
00526                     X509_free(sk_X509_value(chain2, 0));
00527                     sk_X509_free(chain2);
00528                 } else {
00529                         BIO_printf (bio_err, "Error %s getting chain.\n",
00530                                         X509_verify_cert_error_string(vret));
00531                         goto export_end;
00532                 }                       
00533         }
00534 
00535         /* Add any CA names */
00536 
00537         for (i = 0; i < sk_num(canames); i++)
00538                 {
00539                 catmp = (unsigned char *)sk_value(canames, i);
00540                 X509_alias_set1(sk_X509_value(certs, i), catmp, -1);
00541                 }
00542 
00543         if (csp_name && key)
00544                 EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name,
00545                                 MBSTRING_ASC, (unsigned char *)csp_name, -1);
00546                 
00547 
00548 #ifdef CRYPTO_MDEBUG
00549         CRYPTO_pop_info();
00550         CRYPTO_push_info("reading password");
00551 #endif
00552 
00553         if(!noprompt &&
00554                 EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:", 1))
00555                 {
00556                 BIO_printf (bio_err, "Can't read Password\n");
00557                 goto export_end;
00558                 }
00559         if (!twopass) BUF_strlcpy(macpass, pass, sizeof macpass);
00560 
00561 #ifdef CRYPTO_MDEBUG
00562         CRYPTO_pop_info();
00563         CRYPTO_push_info("creating PKCS#12 structure");
00564 #endif
00565 
00566         p12 = PKCS12_create(cpass, name, key, ucert, certs,
00567                                 key_pbe, cert_pbe, iter, -1, keytype);
00568 
00569         if (!p12)
00570                 {
00571                 ERR_print_errors (bio_err);
00572                 goto export_end;
00573                 }
00574 
00575         if (maciter != -1)
00576                 PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, NULL);
00577 
00578 #ifdef CRYPTO_MDEBUG
00579         CRYPTO_pop_info();
00580         CRYPTO_push_info("writing pkcs12");
00581 #endif
00582 
00583         i2d_PKCS12_bio(out, p12);
00584 
00585         ret = 0;
00586 
00587     export_end:
00588 #ifdef CRYPTO_MDEBUG
00589         CRYPTO_pop_info();
00590         CRYPTO_pop_info();
00591         CRYPTO_push_info("process -export_cert: freeing");
00592 #endif
00593 
00594         if (key) EVP_PKEY_free(key);
00595         if (certs) sk_X509_pop_free(certs, X509_free);
00596         if (ucert) X509_free(ucert);
00597 
00598 #ifdef CRYPTO_MDEBUG
00599         CRYPTO_pop_info();
00600 #endif
00601         goto end;
00602         
00603     }
00604 
00605     if (!(p12 = d2i_PKCS12_bio (in, NULL))) {
00606         ERR_print_errors(bio_err);
00607         goto end;
00608     }
00609 
00610 #ifdef CRYPTO_MDEBUG
00611     CRYPTO_push_info("read import password");
00612 #endif
00613     if(!noprompt && EVP_read_pw_string(pass, sizeof pass, "Enter Import Password:", 0)) {
00614         BIO_printf (bio_err, "Can't read Password\n");
00615         goto end;
00616     }
00617 #ifdef CRYPTO_MDEBUG
00618     CRYPTO_pop_info();
00619 #endif
00620 
00621     if (!twopass) BUF_strlcpy(macpass, pass, sizeof macpass);
00622 
00623     if (options & INFO) BIO_printf (bio_err, "MAC Iteration %ld\n", p12->mac->iter ? ASN1_INTEGER_get (p12->mac->iter) : 1);
00624     if(macver) {
00625 #ifdef CRYPTO_MDEBUG
00626     CRYPTO_push_info("verify MAC");
00627 #endif
00628         /* If we enter empty password try no password first */
00629         if(!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) {
00630                 /* If mac and crypto pass the same set it to NULL too */
00631                 if(!twopass) cpass = NULL;
00632         } else if (!PKCS12_verify_mac(p12, mpass, -1)) {
00633             BIO_printf (bio_err, "Mac verify error: invalid password?\n");
00634             ERR_print_errors (bio_err);
00635             goto end;
00636         }
00637         BIO_printf (bio_err, "MAC verified OK\n");
00638 #ifdef CRYPTO_MDEBUG
00639     CRYPTO_pop_info();
00640 #endif
00641     }
00642 
00643 #ifdef CRYPTO_MDEBUG
00644     CRYPTO_push_info("output keys and certificates");
00645 #endif
00646     if (!dump_certs_keys_p12 (out, p12, cpass, -1, options, passout)) {
00647         BIO_printf(bio_err, "Error outputting keys and certificates\n");
00648         ERR_print_errors (bio_err);
00649         goto end;
00650     }
00651 #ifdef CRYPTO_MDEBUG
00652     CRYPTO_pop_info();
00653 #endif
00654     ret = 0;
00655  end:
00656     if (p12) PKCS12_free(p12);
00657     if(export_cert || inrand) app_RAND_write_file(NULL, bio_err);
00658 #ifdef CRYPTO_MDEBUG
00659     CRYPTO_remove_all_info();
00660 #endif
00661     BIO_free(in);
00662     BIO_free_all(out);
00663     if (canames) sk_free(canames);
00664     if(passin) OPENSSL_free(passin);
00665     if(passout) OPENSSL_free(passout);
00666     apps_shutdown();
00667     OPENSSL_EXIT(ret);
00668 }
00669 
00670 int dump_certs_keys_p12 (BIO *out, PKCS12 *p12, char *pass,
00671              int passlen, int options, char *pempass)
00672 {
00673         STACK_OF(PKCS7) *asafes = NULL;
00674         STACK_OF(PKCS12_SAFEBAG) *bags;
00675         int i, bagnid;
00676         int ret = 0;
00677         PKCS7 *p7;
00678 
00679         if (!( asafes = PKCS12_unpack_authsafes(p12))) return 0;
00680         for (i = 0; i < sk_PKCS7_num (asafes); i++) {
00681                 p7 = sk_PKCS7_value (asafes, i);
00682                 bagnid = OBJ_obj2nid (p7->type);
00683                 if (bagnid == NID_pkcs7_data) {
00684                         bags = PKCS12_unpack_p7data(p7);
00685                         if (options & INFO) BIO_printf (bio_err, "PKCS7 Data\n");
00686                 } else if (bagnid == NID_pkcs7_encrypted) {
00687                         if (options & INFO) {
00688                                 BIO_printf(bio_err, "PKCS7 Encrypted data: ");
00689                                 alg_print(bio_err, 
00690                                         p7->d.encrypted->enc_data->algorithm);
00691                         }
00692                         bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
00693                 } else continue;
00694                 if (!bags) goto err;
00695                 if (!dump_certs_pkeys_bags (out, bags, pass, passlen, 
00696                                                  options, pempass)) {
00697                         sk_PKCS12_SAFEBAG_pop_free (bags, PKCS12_SAFEBAG_free);
00698                         goto err;
00699                 }
00700                 sk_PKCS12_SAFEBAG_pop_free (bags, PKCS12_SAFEBAG_free);
00701                 bags = NULL;
00702         }
00703         ret = 1;
00704 
00705         err:
00706 
00707         if (asafes)
00708                 sk_PKCS7_pop_free (asafes, PKCS7_free);
00709         return ret;
00710 }
00711 
00712 int dump_certs_pkeys_bags (BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags,
00713                            char *pass, int passlen, int options, char *pempass)
00714 {
00715         int i;
00716         for (i = 0; i < sk_PKCS12_SAFEBAG_num (bags); i++) {
00717                 if (!dump_certs_pkeys_bag (out,
00718                                            sk_PKCS12_SAFEBAG_value (bags, i),
00719                                            pass, passlen,
00720                                            options, pempass))
00721                     return 0;
00722         }
00723         return 1;
00724 }
00725 
00726 int dump_certs_pkeys_bag (BIO *out, PKCS12_SAFEBAG *bag, char *pass,
00727              int passlen, int options, char *pempass)
00728 {
00729         EVP_PKEY *pkey;
00730         PKCS8_PRIV_KEY_INFO *p8;
00731         X509 *x509;
00732         
00733         switch (M_PKCS12_bag_type(bag))
00734         {
00735         case NID_keyBag:
00736                 if (options & INFO) BIO_printf (bio_err, "Key bag\n");
00737                 if (options & NOKEYS) return 1;
00738                 print_attribs (out, bag->attrib, "Bag Attributes");
00739                 p8 = bag->value.keybag;
00740                 if (!(pkey = EVP_PKCS82PKEY (p8))) return 0;
00741                 print_attribs (out, p8->attributes, "Key Attributes");
00742                 PEM_write_bio_PrivateKey (out, pkey, enc, NULL, 0, NULL, pempass);
00743                 EVP_PKEY_free(pkey);
00744         break;
00745 
00746         case NID_pkcs8ShroudedKeyBag:
00747                 if (options & INFO) {
00748                         BIO_printf (bio_err, "Shrouded Keybag: ");
00749                         alg_print (bio_err, bag->value.shkeybag->algor);
00750                 }
00751                 if (options & NOKEYS) return 1;
00752                 print_attribs (out, bag->attrib, "Bag Attributes");
00753                 if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen)))
00754                                 return 0;
00755                 if (!(pkey = EVP_PKCS82PKEY (p8))) {
00756                         PKCS8_PRIV_KEY_INFO_free(p8);
00757                         return 0;
00758                 }
00759                 print_attribs (out, p8->attributes, "Key Attributes");
00760                 PKCS8_PRIV_KEY_INFO_free(p8);
00761                 PEM_write_bio_PrivateKey (out, pkey, enc, NULL, 0, NULL, pempass);
00762                 EVP_PKEY_free(pkey);
00763         break;
00764 
00765         case NID_certBag:
00766                 if (options & INFO) BIO_printf (bio_err, "Certificate bag\n");
00767                 if (options & NOCERTS) return 1;
00768                 if (PKCS12_get_attr(bag, NID_localKeyID)) {
00769                         if (options & CACERTS) return 1;
00770                 } else if (options & CLCERTS) return 1;
00771                 print_attribs (out, bag->attrib, "Bag Attributes");
00772                 if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate )
00773                                                                  return 1;
00774                 if (!(x509 = PKCS12_certbag2x509(bag))) return 0;
00775                 dump_cert_text (out, x509);
00776                 PEM_write_bio_X509 (out, x509);
00777                 X509_free(x509);
00778         break;
00779 
00780         case NID_safeContentsBag:
00781                 if (options & INFO) BIO_printf (bio_err, "Safe Contents bag\n");
00782                 print_attribs (out, bag->attrib, "Bag Attributes");
00783                 return dump_certs_pkeys_bags (out, bag->value.safes, pass,
00784                                                             passlen, options, pempass);
00785                                         
00786         default:
00787                 BIO_printf (bio_err, "Warning unsupported bag type: ");
00788                 i2a_ASN1_OBJECT (bio_err, bag->type);
00789                 BIO_printf (bio_err, "\n");
00790                 return 1;
00791         break;
00792         }
00793         return 1;
00794 }
00795 
00796 /* Given a single certificate return a verified chain or NULL if error */
00797 
00798 /* Hope this is OK .... */
00799 
00800 int get_cert_chain (X509 *cert, X509_STORE *store, STACK_OF(X509) **chain)
00801 {
00802         X509_STORE_CTX store_ctx;
00803         STACK_OF(X509) *chn;
00804         int i;
00805 
00806         /* FIXME: Should really check the return status of X509_STORE_CTX_init
00807          * for an error, but how that fits into the return value of this
00808          * function is less obvious. */
00809         X509_STORE_CTX_init(&store_ctx, store, cert, NULL);
00810         if (X509_verify_cert(&store_ctx) <= 0) {
00811                 i = X509_STORE_CTX_get_error (&store_ctx);
00812                 goto err;
00813         }
00814         chn =  X509_STORE_CTX_get1_chain(&store_ctx);
00815         i = 0;
00816         *chain = chn;
00817 err:
00818         X509_STORE_CTX_cleanup(&store_ctx);
00819         
00820         return i;
00821 }       
00822 
00823 int alg_print (BIO *x, X509_ALGOR *alg)
00824 {
00825         PBEPARAM *pbe;
00826         const unsigned char *p;
00827         p = alg->parameter->value.sequence->data;
00828         pbe = d2i_PBEPARAM (NULL, &p, alg->parameter->value.sequence->length);
00829         BIO_printf (bio_err, "%s, Iteration %ld\n", 
00830                 OBJ_nid2ln(OBJ_obj2nid(alg->algorithm)),
00831                 ASN1_INTEGER_get(pbe->iter));
00832         PBEPARAM_free (pbe);
00833         return 0;
00834 }
00835 
00836 /* Load all certificates from a given file */
00837 
00838 int cert_load(BIO *in, STACK_OF(X509) *sk)
00839 {
00840         int ret;
00841         X509 *cert;
00842         ret = 0;
00843 #ifdef CRYPTO_MDEBUG
00844         CRYPTO_push_info("cert_load(): reading one cert");
00845 #endif
00846         while((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
00847 #ifdef CRYPTO_MDEBUG
00848                 CRYPTO_pop_info();
00849 #endif
00850                 ret = 1;
00851                 sk_X509_push(sk, cert);
00852 #ifdef CRYPTO_MDEBUG
00853                 CRYPTO_push_info("cert_load(): reading one cert");
00854 #endif
00855         }
00856 #ifdef CRYPTO_MDEBUG
00857         CRYPTO_pop_info();
00858 #endif
00859         if(ret) ERR_clear_error();
00860         return ret;
00861 }
00862 
00863 /* Generalised attribute print: handle PKCS#8 and bag attributes */
00864 
00865 int print_attribs (BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst,const char *name)
00866 {
00867         X509_ATTRIBUTE *attr;
00868         ASN1_TYPE *av;
00869         char *value;
00870         int i, attr_nid;
00871         if(!attrlst) {
00872                 BIO_printf(out, "%s: <No Attributes>\n", name);
00873                 return 1;
00874         }
00875         if(!sk_X509_ATTRIBUTE_num(attrlst)) {
00876                 BIO_printf(out, "%s: <Empty Attributes>\n", name);
00877                 return 1;
00878         }
00879         BIO_printf(out, "%s\n", name);
00880         for(i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) {
00881                 attr = sk_X509_ATTRIBUTE_value(attrlst, i);
00882                 attr_nid = OBJ_obj2nid(attr->object);
00883                 BIO_printf(out, "    ");
00884                 if(attr_nid == NID_undef) {
00885                         i2a_ASN1_OBJECT (out, attr->object);
00886                         BIO_printf(out, ": ");
00887                 } else BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid));
00888 
00889                 if(sk_ASN1_TYPE_num(attr->value.set)) {
00890                         av = sk_ASN1_TYPE_value(attr->value.set, 0);
00891                         switch(av->type) {
00892                                 case V_ASN1_BMPSTRING:
00893                                 value = uni2asc(av->value.bmpstring->data,
00894                                                av->value.bmpstring->length);
00895                                 BIO_printf(out, "%s\n", value);
00896                                 OPENSSL_free(value);
00897                                 break;
00898 
00899                                 case V_ASN1_OCTET_STRING:
00900                                 hex_prin(out, av->value.octet_string->data,
00901                                         av->value.octet_string->length);
00902                                 BIO_printf(out, "\n");  
00903                                 break;
00904 
00905                                 case V_ASN1_BIT_STRING:
00906                                 hex_prin(out, av->value.bit_string->data,
00907                                         av->value.bit_string->length);
00908                                 BIO_printf(out, "\n");  
00909                                 break;
00910 
00911                                 default:
00912                                         BIO_printf(out, "<Unsupported tag %d>\n", av->type);
00913                                 break;
00914                         }
00915                 } else BIO_printf(out, "<No Values>\n");
00916         }
00917         return 1;
00918 }
00919 
00920 void hex_prin(BIO *out, unsigned char *buf, int len)
00921 {
00922         int i;
00923         for (i = 0; i < len; i++) BIO_printf (out, "%02X ", buf[i]);
00924 }
00925 
00926 #endif

© sourcejam.com 2005-2008