pkcs8.c revision 109998
155714Skris/* pkcs8.c */ 255714Skris/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL 355714Skris * project 1999. 455714Skris */ 555714Skris/* ==================================================================== 655714Skris * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 755714Skris * 855714Skris * Redistribution and use in source and binary forms, with or without 955714Skris * modification, are permitted provided that the following conditions 1055714Skris * are met: 1155714Skris * 1255714Skris * 1. Redistributions of source code must retain the above copyright 1355714Skris * notice, this list of conditions and the following disclaimer. 1455714Skris * 1555714Skris * 2. Redistributions in binary form must reproduce the above copyright 1655714Skris * notice, this list of conditions and the following disclaimer in 1755714Skris * the documentation and/or other materials provided with the 1855714Skris * distribution. 1955714Skris * 2055714Skris * 3. All advertising materials mentioning features or use of this 2155714Skris * software must display the following acknowledgment: 2255714Skris * "This product includes software developed by the OpenSSL Project 2355714Skris * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2455714Skris * 2555714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2655714Skris * endorse or promote products derived from this software without 2755714Skris * prior written permission. For written permission, please contact 2855714Skris * licensing@OpenSSL.org. 2955714Skris * 3055714Skris * 5. Products derived from this software may not be called "OpenSSL" 3155714Skris * nor may "OpenSSL" appear in their names without prior written 3255714Skris * permission of the OpenSSL Project. 3355714Skris * 3455714Skris * 6. Redistributions of any form whatsoever must retain the following 3555714Skris * acknowledgment: 3655714Skris * "This product includes software developed by the OpenSSL Project 3755714Skris * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3855714Skris * 3955714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 4055714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4155714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4255714Skris * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4355714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4455714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4555714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4655714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4755714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4855714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 4955714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 5055714Skris * OF THE POSSIBILITY OF SUCH DAMAGE. 5155714Skris * ==================================================================== 5255714Skris * 5355714Skris * This product includes cryptographic software written by Eric Young 5455714Skris * (eay@cryptsoft.com). This product includes software written by Tim 5555714Skris * Hudson (tjh@cryptsoft.com). 5655714Skris * 5755714Skris */ 5855714Skris#include <stdio.h> 5955714Skris#include <string.h> 6059191Skris#include "apps.h" 6155714Skris#include <openssl/pem.h> 6255714Skris#include <openssl/err.h> 6355714Skris#include <openssl/evp.h> 6455714Skris#include <openssl/pkcs12.h> 6555714Skris 6655714Skris#define PROG pkcs8_main 6755714Skris 6859191Skrisint MAIN(int, char **); 6955714Skris 7055714Skrisint MAIN(int argc, char **argv) 7155714Skris{ 72109998Smarkm ENGINE *e = NULL; 7355714Skris char **args, *infile = NULL, *outfile = NULL; 7459191Skris char *passargin = NULL, *passargout = NULL; 7555714Skris BIO *in = NULL, *out = NULL; 7655714Skris int topk8 = 0; 7755714Skris int pbe_nid = -1; 7855714Skris const EVP_CIPHER *cipher = NULL; 7955714Skris int iter = PKCS12_DEFAULT_ITER; 8055714Skris int informat, outformat; 8155714Skris int p8_broken = PKCS8_OK; 8255714Skris int nocrypt = 0; 8355714Skris X509_SIG *p8; 8455714Skris PKCS8_PRIV_KEY_INFO *p8inf; 85109998Smarkm EVP_PKEY *pkey=NULL; 8659191Skris char pass[50], *passin = NULL, *passout = NULL, *p8pass = NULL; 8755714Skris int badarg = 0; 88109998Smarkm char *engine=NULL; 89109998Smarkm 9055714Skris if (bio_err == NULL) bio_err = BIO_new_fp (stderr, BIO_NOCLOSE); 91109998Smarkm 92109998Smarkm if (!load_config(bio_err, NULL)) 93109998Smarkm goto end; 94109998Smarkm 9555714Skris informat=FORMAT_PEM; 9655714Skris outformat=FORMAT_PEM; 97109998Smarkm 9855714Skris ERR_load_crypto_strings(); 9959191Skris OpenSSL_add_all_algorithms(); 10055714Skris args = argv + 1; 10155714Skris while (!badarg && *args && *args[0] == '-') { 10255714Skris if (!strcmp(*args,"-v2")) { 10355714Skris if (args[1]) { 10455714Skris args++; 10555714Skris cipher=EVP_get_cipherbyname(*args); 10655714Skris if(!cipher) { 10755714Skris BIO_printf(bio_err, 10855714Skris "Unknown cipher %s\n", *args); 10955714Skris badarg = 1; 11055714Skris } 11155714Skris } else badarg = 1; 11259191Skris } else if (!strcmp(*args,"-v1")) { 11359191Skris if (args[1]) { 11459191Skris args++; 11559191Skris pbe_nid=OBJ_txt2nid(*args); 11659191Skris if(pbe_nid == NID_undef) { 11759191Skris BIO_printf(bio_err, 11859191Skris "Unknown PBE algorithm %s\n", *args); 11959191Skris badarg = 1; 12059191Skris } 12159191Skris } else badarg = 1; 12255714Skris } else if (!strcmp(*args,"-inform")) { 12355714Skris if (args[1]) { 12455714Skris args++; 12555714Skris informat=str2fmt(*args); 12655714Skris } else badarg = 1; 12755714Skris } else if (!strcmp(*args,"-outform")) { 12855714Skris if (args[1]) { 12955714Skris args++; 13055714Skris outformat=str2fmt(*args); 13155714Skris } else badarg = 1; 13255714Skris } else if (!strcmp (*args, "-topk8")) topk8 = 1; 13355714Skris else if (!strcmp (*args, "-noiter")) iter = 1; 13455714Skris else if (!strcmp (*args, "-nocrypt")) nocrypt = 1; 13555714Skris else if (!strcmp (*args, "-nooct")) p8_broken = PKCS8_NO_OCTET; 13659191Skris else if (!strcmp (*args, "-nsdb")) p8_broken = PKCS8_NS_DB; 13759191Skris else if (!strcmp (*args, "-embed")) p8_broken = PKCS8_EMBEDDED_PARAM; 13859191Skris else if (!strcmp(*args,"-passin")) 13959191Skris { 14059191Skris if (!args[1]) goto bad; 14159191Skris passargin= *(++args); 14259191Skris } 14359191Skris else if (!strcmp(*args,"-passout")) 14459191Skris { 14559191Skris if (!args[1]) goto bad; 14659191Skris passargout= *(++args); 14759191Skris } 148109998Smarkm else if (strcmp(*args,"-engine") == 0) 149109998Smarkm { 150109998Smarkm if (!args[1]) goto bad; 151109998Smarkm engine= *(++args); 152109998Smarkm } 15355714Skris else if (!strcmp (*args, "-in")) { 15455714Skris if (args[1]) { 15555714Skris args++; 15655714Skris infile = *args; 15755714Skris } else badarg = 1; 15855714Skris } else if (!strcmp (*args, "-out")) { 15955714Skris if (args[1]) { 16055714Skris args++; 16155714Skris outfile = *args; 16255714Skris } else badarg = 1; 16355714Skris } else badarg = 1; 16455714Skris args++; 16555714Skris } 16655714Skris 16755714Skris if (badarg) { 16859191Skris bad: 16959191Skris BIO_printf(bio_err, "Usage pkcs8 [options]\n"); 17059191Skris BIO_printf(bio_err, "where options are\n"); 17159191Skris BIO_printf(bio_err, "-in file input file\n"); 17259191Skris BIO_printf(bio_err, "-inform X input format (DER or PEM)\n"); 17359191Skris BIO_printf(bio_err, "-passin arg input file pass phrase source\n"); 17459191Skris BIO_printf(bio_err, "-outform X output format (DER or PEM)\n"); 17559191Skris BIO_printf(bio_err, "-out file output file\n"); 17659191Skris BIO_printf(bio_err, "-passout arg output file pass phrase source\n"); 17759191Skris BIO_printf(bio_err, "-topk8 output PKCS8 file\n"); 17859191Skris BIO_printf(bio_err, "-nooct use (nonstandard) no octet format\n"); 17959191Skris BIO_printf(bio_err, "-embed use (nonstandard) embedded DSA parameters format\n"); 18059191Skris BIO_printf(bio_err, "-nsdb use (nonstandard) DSA Netscape DB format\n"); 18159191Skris BIO_printf(bio_err, "-noiter use 1 as iteration count\n"); 18259191Skris BIO_printf(bio_err, "-nocrypt use or expect unencrypted private key\n"); 18359191Skris BIO_printf(bio_err, "-v2 alg use PKCS#5 v2.0 and cipher \"alg\"\n"); 18459191Skris BIO_printf(bio_err, "-v1 obj use PKCS#5 v1.5 and cipher \"alg\"\n"); 185109998Smarkm BIO_printf(bio_err," -engine e use engine e, possibly a hardware device.\n"); 18655714Skris return (1); 18755714Skris } 18855714Skris 189109998Smarkm e = setup_engine(bio_err, engine, 0); 190109998Smarkm 19159191Skris if(!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { 19259191Skris BIO_printf(bio_err, "Error getting passwords\n"); 19359191Skris return (1); 19459191Skris } 19559191Skris 19655714Skris if ((pbe_nid == -1) && !cipher) pbe_nid = NID_pbeWithMD5AndDES_CBC; 19755714Skris 19855714Skris if (infile) { 19959191Skris if (!(in = BIO_new_file(infile, "rb"))) { 20059191Skris BIO_printf(bio_err, 20155714Skris "Can't open input file %s\n", infile); 20255714Skris return (1); 20355714Skris } 20455714Skris } else in = BIO_new_fp (stdin, BIO_NOCLOSE); 20555714Skris 20655714Skris if (outfile) { 20755714Skris if (!(out = BIO_new_file (outfile, "wb"))) { 20859191Skris BIO_printf(bio_err, 20955714Skris "Can't open output file %s\n", outfile); 21055714Skris return (1); 21155714Skris } 21268651Skris } else { 21368651Skris out = BIO_new_fp (stdout, BIO_NOCLOSE); 214109998Smarkm#ifdef OPENSSL_SYS_VMS 21568651Skris { 21668651Skris BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 21768651Skris out = BIO_push(tmpbio, out); 21868651Skris } 21968651Skris#endif 22068651Skris } 221109998Smarkm if (topk8) 222109998Smarkm { 223109998Smarkm BIO_free(in); /* Not needed in this section */ 224109998Smarkm pkey = load_key(bio_err, infile, informat, 1, 225109998Smarkm passin, e, "key"); 22659191Skris if (!pkey) { 22755714Skris return (1); 22855714Skris } 22959191Skris if (!(p8inf = EVP_PKEY2PKCS8_broken(pkey, p8_broken))) { 23059191Skris BIO_printf(bio_err, "Error converting key\n", outfile); 23155714Skris ERR_print_errors(bio_err); 23255714Skris return (1); 23355714Skris } 23455714Skris if(nocrypt) { 23555714Skris if(outformat == FORMAT_PEM) 23655714Skris PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf); 23755714Skris else if(outformat == FORMAT_ASN1) 23855714Skris i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8inf); 23955714Skris else { 24055714Skris BIO_printf(bio_err, "Bad format specified for key\n"); 24155714Skris return (1); 24255714Skris } 24355714Skris } else { 24459191Skris if(passout) p8pass = passout; 24559191Skris else { 24659191Skris p8pass = pass; 247109998Smarkm if (EVP_read_pw_string(pass, sizeof pass, "Enter Encryption Password:", 1)) 248109998Smarkm return (1); 24959191Skris } 25059191Skris app_RAND_load_file(NULL, bio_err, 0); 25155714Skris if (!(p8 = PKCS8_encrypt(pbe_nid, cipher, 25259191Skris p8pass, strlen(p8pass), 25355714Skris NULL, 0, iter, p8inf))) { 25459191Skris BIO_printf(bio_err, "Error encrypting key\n", 25555714Skris outfile); 25655714Skris ERR_print_errors(bio_err); 25755714Skris return (1); 25855714Skris } 25959191Skris app_RAND_write_file(NULL, bio_err); 26055714Skris if(outformat == FORMAT_PEM) 26159191Skris PEM_write_bio_PKCS8(out, p8); 26255714Skris else if(outformat == FORMAT_ASN1) 26355714Skris i2d_PKCS8_bio(out, p8); 26455714Skris else { 26555714Skris BIO_printf(bio_err, "Bad format specified for key\n"); 26655714Skris return (1); 26755714Skris } 26855714Skris X509_SIG_free(p8); 26955714Skris } 27055714Skris PKCS8_PRIV_KEY_INFO_free (p8inf); 27155714Skris EVP_PKEY_free(pkey); 27268651Skris BIO_free_all(out); 27368651Skris if(passin) OPENSSL_free(passin); 27468651Skris if(passout) OPENSSL_free(passout); 27555714Skris return (0); 27655714Skris } 27755714Skris 27855714Skris if(nocrypt) { 27955714Skris if(informat == FORMAT_PEM) 28055714Skris p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in,NULL,NULL, NULL); 28155714Skris else if(informat == FORMAT_ASN1) 28255714Skris p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL); 28355714Skris else { 28455714Skris BIO_printf(bio_err, "Bad format specified for key\n"); 28555714Skris return (1); 28655714Skris } 28755714Skris } else { 28855714Skris if(informat == FORMAT_PEM) 28955714Skris p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL); 29055714Skris else if(informat == FORMAT_ASN1) 29155714Skris p8 = d2i_PKCS8_bio(in, NULL); 29255714Skris else { 29355714Skris BIO_printf(bio_err, "Bad format specified for key\n"); 29455714Skris return (1); 29555714Skris } 29655714Skris 29755714Skris if (!p8) { 29855714Skris BIO_printf (bio_err, "Error reading key\n", outfile); 29955714Skris ERR_print_errors(bio_err); 30055714Skris return (1); 30155714Skris } 30259191Skris if(passin) p8pass = passin; 30359191Skris else { 30459191Skris p8pass = pass; 305109998Smarkm EVP_read_pw_string(pass, sizeof pass, "Enter Password:", 0); 30659191Skris } 307109998Smarkm p8inf = PKCS8_decrypt(p8, p8pass, strlen(p8pass)); 30855714Skris X509_SIG_free(p8); 30955714Skris } 31055714Skris 31155714Skris if (!p8inf) { 31255714Skris BIO_printf(bio_err, "Error decrypting key\n", outfile); 31355714Skris ERR_print_errors(bio_err); 31455714Skris return (1); 31555714Skris } 31655714Skris 31755714Skris if (!(pkey = EVP_PKCS82PKEY(p8inf))) { 31855714Skris BIO_printf(bio_err, "Error converting key\n", outfile); 31955714Skris ERR_print_errors(bio_err); 32055714Skris return (1); 32155714Skris } 32255714Skris 32355714Skris if (p8inf->broken) { 32455714Skris BIO_printf(bio_err, "Warning: broken key encoding: "); 32555714Skris switch (p8inf->broken) { 32655714Skris case PKCS8_NO_OCTET: 32759191Skris BIO_printf(bio_err, "No Octet String in PrivateKey\n"); 32855714Skris break; 32955714Skris 33059191Skris case PKCS8_EMBEDDED_PARAM: 33159191Skris BIO_printf(bio_err, "DSA parameters included in PrivateKey\n"); 33259191Skris break; 33359191Skris 33459191Skris case PKCS8_NS_DB: 33559191Skris BIO_printf(bio_err, "DSA public key include in PrivateKey\n"); 33659191Skris break; 33759191Skris 33855714Skris default: 33955714Skris BIO_printf(bio_err, "Unknown broken type\n"); 34055714Skris break; 34155714Skris } 34255714Skris } 34355714Skris 34455714Skris PKCS8_PRIV_KEY_INFO_free(p8inf); 34559191Skris if(outformat == FORMAT_PEM) 34659191Skris PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, passout); 34759191Skris else if(outformat == FORMAT_ASN1) 34859191Skris i2d_PrivateKey_bio(out, pkey); 34959191Skris else { 35059191Skris BIO_printf(bio_err, "Bad format specified for key\n"); 35159191Skris return (1); 35259191Skris } 35355714Skris 354109998Smarkm end: 35555714Skris EVP_PKEY_free(pkey); 35668651Skris BIO_free_all(out); 35755714Skris BIO_free(in); 35868651Skris if(passin) OPENSSL_free(passin); 35968651Skris if(passout) OPENSSL_free(passout); 36055714Skris 36155714Skris return (0); 36255714Skris} 363