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

pkcs8.c

Go to the documentation of this file.
00001 /* pkcs8.c */
00002 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
00003  * project 1999-2004.
00004  */
00005 /* ====================================================================
00006  * Copyright (c) 1999 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 #include <stdio.h>
00059 #include <string.h>
00060 #include "apps.h"
00061 #include <openssl/pem.h>
00062 #include <openssl/err.h>
00063 #include <openssl/evp.h>
00064 #include <openssl/pkcs12.h>
00065 
00066 #define PROG pkcs8_main
00067 
00068 int MAIN(int, char **);
00069 
00070 int MAIN(int argc, char **argv)
00071         {
00072         ENGINE *e = NULL;
00073         char **args, *infile = NULL, *outfile = NULL;
00074         char *passargin = NULL, *passargout = NULL;
00075         BIO *in = NULL, *out = NULL;
00076         int topk8 = 0;
00077         int pbe_nid = -1;
00078         const EVP_CIPHER *cipher = NULL;
00079         int iter = PKCS12_DEFAULT_ITER;
00080         int informat, outformat;
00081         int p8_broken = PKCS8_OK;
00082         int nocrypt = 0;
00083         X509_SIG *p8;
00084         PKCS8_PRIV_KEY_INFO *p8inf;
00085         EVP_PKEY *pkey=NULL;
00086         char pass[50], *passin = NULL, *passout = NULL, *p8pass = NULL;
00087         int badarg = 0;
00088 #ifndef OPENSSL_NO_ENGINE
00089         char *engine=NULL;
00090 #endif
00091 
00092         if (bio_err == NULL) bio_err = BIO_new_fp (stderr, BIO_NOCLOSE);
00093 
00094         if (!load_config(bio_err, NULL))
00095                 goto end;
00096 
00097         informat=FORMAT_PEM;
00098         outformat=FORMAT_PEM;
00099 
00100         ERR_load_crypto_strings();
00101         OpenSSL_add_all_algorithms();
00102         args = argv + 1;
00103         while (!badarg && *args && *args[0] == '-')
00104                 {
00105                 if (!strcmp(*args,"-v2"))
00106                         {
00107                         if (args[1])
00108                                 {
00109                                 args++;
00110                                 cipher=EVP_get_cipherbyname(*args);
00111                                 if (!cipher)
00112                                         {
00113                                         BIO_printf(bio_err,
00114                                                  "Unknown cipher %s\n", *args);
00115                                         badarg = 1;
00116                                         }
00117                                 }
00118                         else
00119                                 badarg = 1;
00120                         }
00121                 else if (!strcmp(*args,"-v1"))
00122                         {
00123                         if (args[1])
00124                                 {
00125                                 args++;
00126                                 pbe_nid=OBJ_txt2nid(*args);
00127                                 if (pbe_nid == NID_undef)
00128                                         {
00129                                         BIO_printf(bio_err,
00130                                                  "Unknown PBE algorithm %s\n", *args);
00131                                         badarg = 1;
00132                                         }
00133                                 }
00134                         else
00135                                 badarg = 1;
00136                         }
00137                 else if (!strcmp(*args,"-inform"))
00138                         {
00139                         if (args[1])
00140                                 {
00141                                 args++;
00142                                 informat=str2fmt(*args);
00143                                 }
00144                         else badarg = 1;
00145                         }
00146                 else if (!strcmp(*args,"-outform"))
00147                         {
00148                         if (args[1])
00149                                 {
00150                                 args++;
00151                                 outformat=str2fmt(*args);
00152                                 }
00153                         else badarg = 1;
00154                         }
00155                 else if (!strcmp (*args, "-topk8"))
00156                         topk8 = 1;
00157                 else if (!strcmp (*args, "-noiter"))
00158                         iter = 1;
00159                 else if (!strcmp (*args, "-nocrypt"))
00160                         nocrypt = 1;
00161                 else if (!strcmp (*args, "-nooct"))
00162                         p8_broken = PKCS8_NO_OCTET;
00163                 else if (!strcmp (*args, "-nsdb"))
00164                         p8_broken = PKCS8_NS_DB;
00165                 else if (!strcmp (*args, "-embed"))
00166                         p8_broken = PKCS8_EMBEDDED_PARAM;
00167                 else if (!strcmp(*args,"-passin"))
00168                         {
00169                         if (!args[1]) goto bad;
00170                         passargin= *(++args);
00171                         }
00172                 else if (!strcmp(*args,"-passout"))
00173                         {
00174                         if (!args[1]) goto bad;
00175                         passargout= *(++args);
00176                         }
00177 #ifndef OPENSSL_NO_ENGINE
00178                 else if (strcmp(*args,"-engine") == 0)
00179                         {
00180                         if (!args[1]) goto bad;
00181                         engine= *(++args);
00182                         }
00183 #endif
00184                 else if (!strcmp (*args, "-in"))
00185                         {
00186                         if (args[1])
00187                                 {
00188                                 args++;
00189                                 infile = *args;
00190                                 }
00191                         else badarg = 1;
00192                         }
00193                 else if (!strcmp (*args, "-out"))
00194                         {
00195                         if (args[1])
00196                                 {
00197                                 args++;
00198                                 outfile = *args;
00199                                 }
00200                         else badarg = 1;
00201                         }
00202                 else badarg = 1;
00203                 args++;
00204                 }
00205 
00206         if (badarg)
00207                 {
00208                 bad:
00209                 BIO_printf(bio_err, "Usage pkcs8 [options]\n");
00210                 BIO_printf(bio_err, "where options are\n");
00211                 BIO_printf(bio_err, "-in file        input file\n");
00212                 BIO_printf(bio_err, "-inform X       input format (DER or PEM)\n");
00213                 BIO_printf(bio_err, "-passin arg     input file pass phrase source\n");
00214                 BIO_printf(bio_err, "-outform X      output format (DER or PEM)\n");
00215                 BIO_printf(bio_err, "-out file       output file\n");
00216                 BIO_printf(bio_err, "-passout arg    output file pass phrase source\n");
00217                 BIO_printf(bio_err, "-topk8          output PKCS8 file\n");
00218                 BIO_printf(bio_err, "-nooct          use (nonstandard) no octet format\n");
00219                 BIO_printf(bio_err, "-embed          use (nonstandard) embedded DSA parameters format\n");
00220                 BIO_printf(bio_err, "-nsdb           use (nonstandard) DSA Netscape DB format\n");
00221                 BIO_printf(bio_err, "-noiter         use 1 as iteration count\n");
00222                 BIO_printf(bio_err, "-nocrypt        use or expect unencrypted private key\n");
00223                 BIO_printf(bio_err, "-v2 alg         use PKCS#5 v2.0 and cipher \"alg\"\n");
00224                 BIO_printf(bio_err, "-v1 obj         use PKCS#5 v1.5 and cipher \"alg\"\n");
00225 #ifndef OPENSSL_NO_ENGINE
00226                 BIO_printf(bio_err," -engine e       use engine e, possibly a hardware device.\n");
00227 #endif
00228                 return 1;
00229                 }
00230 
00231 #ifndef OPENSSL_NO_ENGINE
00232         e = setup_engine(bio_err, engine, 0);
00233 #endif
00234 
00235         if (!app_passwd(bio_err, passargin, passargout, &passin, &passout))
00236                 {
00237                 BIO_printf(bio_err, "Error getting passwords\n");
00238                 return 1;
00239                 }
00240 
00241         if ((pbe_nid == -1) && !cipher)
00242                 pbe_nid = NID_pbeWithMD5AndDES_CBC;
00243 
00244         if (infile)
00245                 {
00246                 if (!(in = BIO_new_file(infile, "rb")))
00247                         {
00248                         BIO_printf(bio_err,
00249                                  "Can't open input file %s\n", infile);
00250                         return (1);
00251                         }
00252                 }
00253         else
00254                 in = BIO_new_fp (stdin, BIO_NOCLOSE);
00255 
00256         if (outfile)
00257                 {
00258                 if (!(out = BIO_new_file (outfile, "wb")))
00259                         {
00260                         BIO_printf(bio_err,
00261                                  "Can't open output file %s\n", outfile);
00262                         return (1);
00263                         }
00264                 }
00265         else
00266                 {
00267                 out = BIO_new_fp (stdout, BIO_NOCLOSE);
00268 #ifdef OPENSSL_SYS_VMS
00269                         {
00270                         BIO *tmpbio = BIO_new(BIO_f_linebuffer());
00271                         out = BIO_push(tmpbio, out);
00272                         }
00273 #endif
00274                 }
00275         if (topk8)
00276                 {
00277                 BIO_free(in); /* Not needed in this section */
00278                 pkey = load_key(bio_err, infile, informat, 1,
00279                         passin, e, "key");
00280                 if (!pkey)
00281                         {
00282                         BIO_free_all(out);
00283                         return 1;
00284                         }
00285                 if (!(p8inf = EVP_PKEY2PKCS8_broken(pkey, p8_broken)))
00286                         {
00287                         BIO_printf(bio_err, "Error converting key\n");
00288                         ERR_print_errors(bio_err);
00289                         EVP_PKEY_free(pkey);
00290                         BIO_free_all(out);
00291                         return 1;
00292                         }
00293                 if (nocrypt)
00294                         {
00295                         if (outformat == FORMAT_PEM) 
00296                                 PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf);
00297                         else if (outformat == FORMAT_ASN1)
00298                                 i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8inf);
00299                         else
00300                                 {
00301                                 BIO_printf(bio_err, "Bad format specified for key\n");
00302                                 PKCS8_PRIV_KEY_INFO_free(p8inf);
00303                                 EVP_PKEY_free(pkey);
00304                                 BIO_free_all(out);
00305                                 return (1);
00306                                 }
00307                         }
00308                 else
00309                         {
00310                         if (passout)
00311                                 p8pass = passout;
00312                         else
00313                                 {
00314                                 p8pass = pass;
00315                                 if (EVP_read_pw_string(pass, sizeof pass, "Enter Encryption Password:", 1))
00316                                         {
00317                                         PKCS8_PRIV_KEY_INFO_free(p8inf);
00318                                         EVP_PKEY_free(pkey);
00319                                         BIO_free_all(out);
00320                                         return (1);
00321                                         }
00322                                 }
00323                         app_RAND_load_file(NULL, bio_err, 0);
00324                         if (!(p8 = PKCS8_encrypt(pbe_nid, cipher,
00325                                         p8pass, strlen(p8pass),
00326                                         NULL, 0, iter, p8inf)))
00327                                 {
00328                                 BIO_printf(bio_err, "Error encrypting key\n");
00329                                 ERR_print_errors(bio_err);
00330                                 PKCS8_PRIV_KEY_INFO_free(p8inf);
00331                                 EVP_PKEY_free(pkey);
00332                                 BIO_free_all(out);
00333                                 return (1);
00334                                 }
00335                         app_RAND_write_file(NULL, bio_err);
00336                         if (outformat == FORMAT_PEM) 
00337                                 PEM_write_bio_PKCS8(out, p8);
00338                         else if (outformat == FORMAT_ASN1)
00339                                 i2d_PKCS8_bio(out, p8);
00340                         else
00341                                 {
00342                                 BIO_printf(bio_err, "Bad format specified for key\n");
00343                                 PKCS8_PRIV_KEY_INFO_free(p8inf);
00344                                 EVP_PKEY_free(pkey);
00345                                 BIO_free_all(out);
00346                                 return (1);
00347                                 }
00348                         X509_SIG_free(p8);
00349                         }
00350 
00351                 PKCS8_PRIV_KEY_INFO_free (p8inf);
00352                 EVP_PKEY_free(pkey);
00353                 BIO_free_all(out);
00354                 if (passin)
00355                         OPENSSL_free(passin);
00356                 if (passout)
00357                         OPENSSL_free(passout);
00358                 return (0);
00359                 }
00360 
00361         if (nocrypt)
00362                 {
00363                 if (informat == FORMAT_PEM) 
00364                         p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in,NULL,NULL, NULL);
00365                 else if (informat == FORMAT_ASN1)
00366                         p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL);
00367                 else
00368                         {
00369                         BIO_printf(bio_err, "Bad format specified for key\n");
00370                         return (1);
00371                         }
00372                 }
00373         else
00374                 {
00375                 if (informat == FORMAT_PEM) 
00376                         p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL);
00377                 else if (informat == FORMAT_ASN1)
00378                         p8 = d2i_PKCS8_bio(in, NULL);
00379                 else
00380                         {
00381                         BIO_printf(bio_err, "Bad format specified for key\n");
00382                         return (1);
00383                         }
00384 
00385                 if (!p8)
00386                         {
00387                         BIO_printf (bio_err, "Error reading key\n");
00388                         ERR_print_errors(bio_err);
00389                         return (1);
00390                         }
00391                 if (passin)
00392                         p8pass = passin;
00393                 else
00394                         {
00395                         p8pass = pass;
00396                         EVP_read_pw_string(pass, sizeof pass, "Enter Password:", 0);
00397                         }
00398                 p8inf = PKCS8_decrypt(p8, p8pass, strlen(p8pass));
00399                 X509_SIG_free(p8);
00400                 }
00401 
00402         if (!p8inf)
00403                 {
00404                 BIO_printf(bio_err, "Error decrypting key\n");
00405                 ERR_print_errors(bio_err);
00406                 return (1);
00407                 }
00408 
00409         if (!(pkey = EVP_PKCS82PKEY(p8inf)))
00410                 {
00411                 BIO_printf(bio_err, "Error converting key\n");
00412                 ERR_print_errors(bio_err);
00413                 return (1);
00414                 }
00415         
00416         if (p8inf->broken)
00417                 {
00418                 BIO_printf(bio_err, "Warning: broken key encoding: ");
00419                 switch (p8inf->broken)
00420                         {
00421                         case PKCS8_NO_OCTET:
00422                         BIO_printf(bio_err, "No Octet String in PrivateKey\n");
00423                         break;
00424 
00425                         case PKCS8_EMBEDDED_PARAM:
00426                         BIO_printf(bio_err, "DSA parameters included in PrivateKey\n");
00427                         break;
00428 
00429                         case PKCS8_NS_DB:
00430                         BIO_printf(bio_err, "DSA public key include in PrivateKey\n");
00431                         break;
00432 
00433                         default:
00434                         BIO_printf(bio_err, "Unknown broken type\n");
00435                         break;
00436                 }
00437         }
00438         
00439         PKCS8_PRIV_KEY_INFO_free(p8inf);
00440         if (outformat == FORMAT_PEM) 
00441                 PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, passout);
00442         else if (outformat == FORMAT_ASN1)
00443                 i2d_PrivateKey_bio(out, pkey);
00444         else
00445                 {
00446                 BIO_printf(bio_err, "Bad format specified for key\n");
00447                         return (1);
00448                 }
00449 
00450         end:
00451         EVP_PKEY_free(pkey);
00452         BIO_free_all(out);
00453         BIO_free(in);
00454         if (passin)
00455                 OPENSSL_free(passin);
00456         if (passout)
00457                 OPENSSL_free(passout);
00458 
00459         return (0);
00460         }

© sourcejam.com 2005-2008