155714Skris/* pkcs8.c */ 2280304Sjkim/* 3280304Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4280304Sjkim * 1999-2004. 555714Skris */ 655714Skris/* ==================================================================== 755714Skris * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 855714Skris * 955714Skris * Redistribution and use in source and binary forms, with or without 1055714Skris * modification, are permitted provided that the following conditions 1155714Skris * are met: 1255714Skris * 1355714Skris * 1. Redistributions of source code must retain the above copyright 14280304Sjkim * notice, this list of conditions and the following disclaimer. 1555714Skris * 1655714Skris * 2. Redistributions in binary form must reproduce the above copyright 1755714Skris * notice, this list of conditions and the following disclaimer in 1855714Skris * the documentation and/or other materials provided with the 1955714Skris * distribution. 2055714Skris * 2155714Skris * 3. All advertising materials mentioning features or use of this 2255714Skris * software must display the following acknowledgment: 2355714Skris * "This product includes software developed by the OpenSSL Project 2455714Skris * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2555714Skris * 2655714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2755714Skris * endorse or promote products derived from this software without 2855714Skris * prior written permission. For written permission, please contact 2955714Skris * licensing@OpenSSL.org. 3055714Skris * 3155714Skris * 5. Products derived from this software may not be called "OpenSSL" 3255714Skris * nor may "OpenSSL" appear in their names without prior written 3355714Skris * permission of the OpenSSL Project. 3455714Skris * 3555714Skris * 6. Redistributions of any form whatsoever must retain the following 3655714Skris * acknowledgment: 3755714Skris * "This product includes software developed by the OpenSSL Project 3855714Skris * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3955714Skris * 4055714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 4155714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4255714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4355714Skris * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4455714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4555714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4655714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4755714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4955714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 5055714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 5155714Skris * OF THE POSSIBILITY OF SUCH DAMAGE. 5255714Skris * ==================================================================== 5355714Skris * 5455714Skris * This product includes cryptographic software written by Eric Young 5555714Skris * (eay@cryptsoft.com). This product includes software written by Tim 5655714Skris * Hudson (tjh@cryptsoft.com). 5755714Skris * 5855714Skris */ 5955714Skris#include <stdio.h> 6055714Skris#include <string.h> 6159191Skris#include "apps.h" 6255714Skris#include <openssl/pem.h> 6355714Skris#include <openssl/err.h> 6455714Skris#include <openssl/evp.h> 6555714Skris#include <openssl/pkcs12.h> 6655714Skris 6755714Skris#define PROG pkcs8_main 6855714Skris 6959191Skrisint MAIN(int, char **); 7055714Skris 7155714Skrisint MAIN(int argc, char **argv) 72280304Sjkim{ 73280304Sjkim ENGINE *e = NULL; 74280304Sjkim char **args, *infile = NULL, *outfile = NULL; 75280304Sjkim char *passargin = NULL, *passargout = NULL; 76280304Sjkim BIO *in = NULL, *out = NULL; 77280304Sjkim int topk8 = 0; 78280304Sjkim int pbe_nid = -1; 79280304Sjkim const EVP_CIPHER *cipher = NULL; 80280304Sjkim int iter = PKCS12_DEFAULT_ITER; 81280304Sjkim int informat, outformat; 82280304Sjkim int p8_broken = PKCS8_OK; 83280304Sjkim int nocrypt = 0; 84280304Sjkim X509_SIG *p8 = NULL; 85280304Sjkim PKCS8_PRIV_KEY_INFO *p8inf = NULL; 86280304Sjkim EVP_PKEY *pkey = NULL; 87280304Sjkim char pass[50], *passin = NULL, *passout = NULL, *p8pass = NULL; 88280304Sjkim int badarg = 0; 89280304Sjkim int ret = 1; 90111147Snectar#ifndef OPENSSL_NO_ENGINE 91280304Sjkim char *engine = NULL; 92111147Snectar#endif 93109998Smarkm 94280304Sjkim if (bio_err == NULL) 95280304Sjkim bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); 96109998Smarkm 97280304Sjkim if (!load_config(bio_err, NULL)) 98280304Sjkim goto end; 99109998Smarkm 100280304Sjkim informat = FORMAT_PEM; 101280304Sjkim outformat = FORMAT_PEM; 102109998Smarkm 103280304Sjkim ERR_load_crypto_strings(); 104280304Sjkim OpenSSL_add_all_algorithms(); 105280304Sjkim args = argv + 1; 106280304Sjkim while (!badarg && *args && *args[0] == '-') { 107280304Sjkim if (!strcmp(*args, "-v2")) { 108280304Sjkim if (args[1]) { 109280304Sjkim args++; 110280304Sjkim cipher = EVP_get_cipherbyname(*args); 111280304Sjkim if (!cipher) { 112280304Sjkim BIO_printf(bio_err, "Unknown cipher %s\n", *args); 113280304Sjkim badarg = 1; 114280304Sjkim } 115280304Sjkim } else 116280304Sjkim badarg = 1; 117280304Sjkim } else if (!strcmp(*args, "-v1")) { 118280304Sjkim if (args[1]) { 119280304Sjkim args++; 120280304Sjkim pbe_nid = OBJ_txt2nid(*args); 121280304Sjkim if (pbe_nid == NID_undef) { 122280304Sjkim BIO_printf(bio_err, "Unknown PBE algorithm %s\n", *args); 123280304Sjkim badarg = 1; 124280304Sjkim } 125280304Sjkim } else 126280304Sjkim badarg = 1; 127280304Sjkim } else if (!strcmp(*args, "-inform")) { 128280304Sjkim if (args[1]) { 129280304Sjkim args++; 130280304Sjkim informat = str2fmt(*args); 131280304Sjkim } else 132280304Sjkim badarg = 1; 133280304Sjkim } else if (!strcmp(*args, "-outform")) { 134280304Sjkim if (args[1]) { 135280304Sjkim args++; 136280304Sjkim outformat = str2fmt(*args); 137280304Sjkim } else 138280304Sjkim badarg = 1; 139280304Sjkim } else if (!strcmp(*args, "-topk8")) 140280304Sjkim topk8 = 1; 141280304Sjkim else if (!strcmp(*args, "-noiter")) 142280304Sjkim iter = 1; 143280304Sjkim else if (!strcmp(*args, "-nocrypt")) 144280304Sjkim nocrypt = 1; 145280304Sjkim else if (!strcmp(*args, "-nooct")) 146280304Sjkim p8_broken = PKCS8_NO_OCTET; 147280304Sjkim else if (!strcmp(*args, "-nsdb")) 148280304Sjkim p8_broken = PKCS8_NS_DB; 149280304Sjkim else if (!strcmp(*args, "-embed")) 150280304Sjkim p8_broken = PKCS8_EMBEDDED_PARAM; 151280304Sjkim else if (!strcmp(*args, "-passin")) { 152280304Sjkim if (!args[1]) 153280304Sjkim goto bad; 154280304Sjkim passargin = *(++args); 155280304Sjkim } else if (!strcmp(*args, "-passout")) { 156280304Sjkim if (!args[1]) 157280304Sjkim goto bad; 158280304Sjkim passargout = *(++args); 159280304Sjkim } 160111147Snectar#ifndef OPENSSL_NO_ENGINE 161280304Sjkim else if (strcmp(*args, "-engine") == 0) { 162280304Sjkim if (!args[1]) 163280304Sjkim goto bad; 164280304Sjkim engine = *(++args); 165280304Sjkim } 166111147Snectar#endif 167280304Sjkim else if (!strcmp(*args, "-in")) { 168280304Sjkim if (args[1]) { 169280304Sjkim args++; 170280304Sjkim infile = *args; 171280304Sjkim } else 172280304Sjkim badarg = 1; 173280304Sjkim } else if (!strcmp(*args, "-out")) { 174280304Sjkim if (args[1]) { 175280304Sjkim args++; 176280304Sjkim outfile = *args; 177280304Sjkim } else 178280304Sjkim badarg = 1; 179280304Sjkim } else 180280304Sjkim badarg = 1; 181280304Sjkim args++; 182280304Sjkim } 18355714Skris 184280304Sjkim if (badarg) { 185280304Sjkim bad: 186280304Sjkim BIO_printf(bio_err, "Usage pkcs8 [options]\n"); 187280304Sjkim BIO_printf(bio_err, "where options are\n"); 188280304Sjkim BIO_printf(bio_err, "-in file input file\n"); 189280304Sjkim BIO_printf(bio_err, "-inform X input format (DER or PEM)\n"); 190280304Sjkim BIO_printf(bio_err, 191280304Sjkim "-passin arg input file pass phrase source\n"); 192280304Sjkim BIO_printf(bio_err, "-outform X output format (DER or PEM)\n"); 193280304Sjkim BIO_printf(bio_err, "-out file output file\n"); 194280304Sjkim BIO_printf(bio_err, 195280304Sjkim "-passout arg output file pass phrase source\n"); 196280304Sjkim BIO_printf(bio_err, "-topk8 output PKCS8 file\n"); 197280304Sjkim BIO_printf(bio_err, 198280304Sjkim "-nooct use (nonstandard) no octet format\n"); 199280304Sjkim BIO_printf(bio_err, 200280304Sjkim "-embed use (nonstandard) embedded DSA parameters format\n"); 201280304Sjkim BIO_printf(bio_err, 202280304Sjkim "-nsdb use (nonstandard) DSA Netscape DB format\n"); 203280304Sjkim BIO_printf(bio_err, "-noiter use 1 as iteration count\n"); 204280304Sjkim BIO_printf(bio_err, 205280304Sjkim "-nocrypt use or expect unencrypted private key\n"); 206280304Sjkim BIO_printf(bio_err, 207280304Sjkim "-v2 alg use PKCS#5 v2.0 and cipher \"alg\"\n"); 208280304Sjkim BIO_printf(bio_err, 209280304Sjkim "-v1 obj use PKCS#5 v1.5 and cipher \"alg\"\n"); 210111147Snectar#ifndef OPENSSL_NO_ENGINE 211280304Sjkim BIO_printf(bio_err, 212280304Sjkim " -engine e use engine e, possibly a hardware device.\n"); 213111147Snectar#endif 214280304Sjkim goto end; 215280304Sjkim } 216111147Snectar#ifndef OPENSSL_NO_ENGINE 217280304Sjkim e = setup_engine(bio_err, engine, 0); 218111147Snectar#endif 219109998Smarkm 220280304Sjkim if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { 221280304Sjkim BIO_printf(bio_err, "Error getting passwords\n"); 222280304Sjkim goto end; 223280304Sjkim } 22459191Skris 225280304Sjkim if ((pbe_nid == -1) && !cipher) 226280304Sjkim pbe_nid = NID_pbeWithMD5AndDES_CBC; 22755714Skris 228280304Sjkim if (infile) { 229280304Sjkim if (!(in = BIO_new_file(infile, "rb"))) { 230280304Sjkim BIO_printf(bio_err, "Can't open input file %s\n", infile); 231280304Sjkim goto end; 232280304Sjkim } 233280304Sjkim } else 234280304Sjkim in = BIO_new_fp(stdin, BIO_NOCLOSE); 23555714Skris 236280304Sjkim if (outfile) { 237280304Sjkim if (!(out = BIO_new_file(outfile, "wb"))) { 238280304Sjkim BIO_printf(bio_err, "Can't open output file %s\n", outfile); 239280304Sjkim goto end; 240280304Sjkim } 241280304Sjkim } else { 242280304Sjkim out = BIO_new_fp(stdout, BIO_NOCLOSE); 243109998Smarkm#ifdef OPENSSL_SYS_VMS 244280304Sjkim { 245280304Sjkim BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 246280304Sjkim out = BIO_push(tmpbio, out); 247280304Sjkim } 248142425Snectar#endif 249280304Sjkim } 250280304Sjkim if (topk8) { 251280304Sjkim pkey = load_key(bio_err, infile, informat, 1, passin, e, "key"); 252280304Sjkim if (!pkey) 253280304Sjkim goto end; 254280304Sjkim if (!(p8inf = EVP_PKEY2PKCS8_broken(pkey, p8_broken))) { 255280304Sjkim BIO_printf(bio_err, "Error converting key\n"); 256280304Sjkim ERR_print_errors(bio_err); 257280304Sjkim goto end; 258280304Sjkim } 259280304Sjkim if (nocrypt) { 260280304Sjkim if (outformat == FORMAT_PEM) 261280304Sjkim PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf); 262280304Sjkim else if (outformat == FORMAT_ASN1) 263280304Sjkim i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8inf); 264280304Sjkim else { 265280304Sjkim BIO_printf(bio_err, "Bad format specified for key\n"); 266280304Sjkim goto end; 267280304Sjkim } 268280304Sjkim } else { 269280304Sjkim if (passout) 270280304Sjkim p8pass = passout; 271280304Sjkim else { 272280304Sjkim p8pass = pass; 273280304Sjkim if (EVP_read_pw_string 274280304Sjkim (pass, sizeof pass, "Enter Encryption Password:", 1)) 275280304Sjkim goto end; 276280304Sjkim } 277280304Sjkim app_RAND_load_file(NULL, bio_err, 0); 278280304Sjkim if (!(p8 = PKCS8_encrypt(pbe_nid, cipher, 279280304Sjkim p8pass, strlen(p8pass), 280280304Sjkim NULL, 0, iter, p8inf))) { 281280304Sjkim BIO_printf(bio_err, "Error encrypting key\n"); 282280304Sjkim ERR_print_errors(bio_err); 283280304Sjkim goto end; 284280304Sjkim } 285280304Sjkim app_RAND_write_file(NULL, bio_err); 286280304Sjkim if (outformat == FORMAT_PEM) 287280304Sjkim PEM_write_bio_PKCS8(out, p8); 288280304Sjkim else if (outformat == FORMAT_ASN1) 289280304Sjkim i2d_PKCS8_bio(out, p8); 290280304Sjkim else { 291280304Sjkim BIO_printf(bio_err, "Bad format specified for key\n"); 292280304Sjkim goto end; 293280304Sjkim } 294280304Sjkim } 295142425Snectar 296280304Sjkim ret = 0; 297280304Sjkim goto end; 298280304Sjkim } 29955714Skris 300280304Sjkim if (nocrypt) { 301280304Sjkim if (informat == FORMAT_PEM) 302280304Sjkim p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in, NULL, NULL, NULL); 303280304Sjkim else if (informat == FORMAT_ASN1) 304280304Sjkim p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL); 305280304Sjkim else { 306280304Sjkim BIO_printf(bio_err, "Bad format specified for key\n"); 307280304Sjkim goto end; 308280304Sjkim } 309280304Sjkim } else { 310280304Sjkim if (informat == FORMAT_PEM) 311280304Sjkim p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL); 312280304Sjkim else if (informat == FORMAT_ASN1) 313280304Sjkim p8 = d2i_PKCS8_bio(in, NULL); 314280304Sjkim else { 315280304Sjkim BIO_printf(bio_err, "Bad format specified for key\n"); 316280304Sjkim goto end; 317280304Sjkim } 31855714Skris 319280304Sjkim if (!p8) { 320280304Sjkim BIO_printf(bio_err, "Error reading key\n"); 321280304Sjkim ERR_print_errors(bio_err); 322280304Sjkim goto end; 323280304Sjkim } 324280304Sjkim if (passin) 325280304Sjkim p8pass = passin; 326280304Sjkim else { 327280304Sjkim p8pass = pass; 328280304Sjkim EVP_read_pw_string(pass, sizeof pass, "Enter Password:", 0); 329280304Sjkim } 330280304Sjkim p8inf = PKCS8_decrypt(p8, p8pass, strlen(p8pass)); 331280304Sjkim } 33255714Skris 333280304Sjkim if (!p8inf) { 334280304Sjkim BIO_printf(bio_err, "Error decrypting key\n"); 335280304Sjkim ERR_print_errors(bio_err); 336280304Sjkim goto end; 337280304Sjkim } 33855714Skris 339280304Sjkim if (!(pkey = EVP_PKCS82PKEY(p8inf))) { 340280304Sjkim BIO_printf(bio_err, "Error converting key\n"); 341280304Sjkim ERR_print_errors(bio_err); 342280304Sjkim goto end; 343280304Sjkim } 34455714Skris 345280304Sjkim if (p8inf->broken) { 346280304Sjkim BIO_printf(bio_err, "Warning: broken key encoding: "); 347280304Sjkim switch (p8inf->broken) { 348280304Sjkim case PKCS8_NO_OCTET: 349280304Sjkim BIO_printf(bio_err, "No Octet String in PrivateKey\n"); 350280304Sjkim break; 35159191Skris 352280304Sjkim case PKCS8_EMBEDDED_PARAM: 353280304Sjkim BIO_printf(bio_err, "DSA parameters included in PrivateKey\n"); 354280304Sjkim break; 35559191Skris 356280304Sjkim case PKCS8_NS_DB: 357280304Sjkim BIO_printf(bio_err, "DSA public key include in PrivateKey\n"); 358280304Sjkim break; 359238405Sjkim 360280304Sjkim case PKCS8_NEG_PRIVKEY: 361280304Sjkim BIO_printf(bio_err, "DSA private key value is negative\n"); 362280304Sjkim break; 36355714Skris 364280304Sjkim default: 365280304Sjkim BIO_printf(bio_err, "Unknown broken type\n"); 366280304Sjkim break; 367280304Sjkim } 368280304Sjkim } 36955714Skris 370280304Sjkim if (outformat == FORMAT_PEM) 371280304Sjkim PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, passout); 372280304Sjkim else if (outformat == FORMAT_ASN1) 373280304Sjkim i2d_PrivateKey_bio(out, pkey); 374280304Sjkim else { 375280304Sjkim BIO_printf(bio_err, "Bad format specified for key\n"); 376280304Sjkim goto end; 377280304Sjkim } 378280304Sjkim ret = 0; 379280304Sjkim 380280304Sjkim end: 381280304Sjkim X509_SIG_free(p8); 382280304Sjkim PKCS8_PRIV_KEY_INFO_free(p8inf); 383280304Sjkim EVP_PKEY_free(pkey); 384280304Sjkim BIO_free_all(out); 385280304Sjkim BIO_free(in); 386280304Sjkim if (passin) 387280304Sjkim OPENSSL_free(passin); 388280304Sjkim if (passout) 389280304Sjkim OPENSSL_free(passout); 390280304Sjkim 391280304Sjkim return ret; 392280304Sjkim} 393