155714Skris/* pkcs8.c */ 2296465Sdelphij/* 3296465Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4296465Sdelphij * 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 14296465Sdelphij * 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) 72296465Sdelphij{ 73296465Sdelphij ENGINE *e = NULL; 74296465Sdelphij char **args, *infile = NULL, *outfile = NULL; 75296465Sdelphij char *passargin = NULL, *passargout = NULL; 76296465Sdelphij BIO *in = NULL, *out = NULL; 77296465Sdelphij int topk8 = 0; 78296465Sdelphij int pbe_nid = -1; 79296465Sdelphij const EVP_CIPHER *cipher = NULL; 80296465Sdelphij int iter = PKCS12_DEFAULT_ITER; 81296465Sdelphij int informat, outformat; 82296465Sdelphij int p8_broken = PKCS8_OK; 83296465Sdelphij int nocrypt = 0; 84296465Sdelphij X509_SIG *p8; 85296465Sdelphij PKCS8_PRIV_KEY_INFO *p8inf; 86296465Sdelphij EVP_PKEY *pkey = NULL; 87296465Sdelphij char pass[50], *passin = NULL, *passout = NULL, *p8pass = NULL; 88296465Sdelphij int badarg = 0; 89111147Snectar#ifndef OPENSSL_NO_ENGINE 90296465Sdelphij char *engine = NULL; 91111147Snectar#endif 92109998Smarkm 93296465Sdelphij if (bio_err == NULL) 94296465Sdelphij bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); 95109998Smarkm 96296465Sdelphij if (!load_config(bio_err, NULL)) 97296465Sdelphij goto end; 98109998Smarkm 99296465Sdelphij informat = FORMAT_PEM; 100296465Sdelphij outformat = FORMAT_PEM; 101109998Smarkm 102296465Sdelphij ERR_load_crypto_strings(); 103296465Sdelphij OpenSSL_add_all_algorithms(); 104296465Sdelphij args = argv + 1; 105296465Sdelphij while (!badarg && *args && *args[0] == '-') { 106296465Sdelphij if (!strcmp(*args, "-v2")) { 107296465Sdelphij if (args[1]) { 108296465Sdelphij args++; 109296465Sdelphij cipher = EVP_get_cipherbyname(*args); 110296465Sdelphij if (!cipher) { 111296465Sdelphij BIO_printf(bio_err, "Unknown cipher %s\n", *args); 112296465Sdelphij badarg = 1; 113296465Sdelphij } 114296465Sdelphij } else 115296465Sdelphij badarg = 1; 116296465Sdelphij } else if (!strcmp(*args, "-v1")) { 117296465Sdelphij if (args[1]) { 118296465Sdelphij args++; 119296465Sdelphij pbe_nid = OBJ_txt2nid(*args); 120296465Sdelphij if (pbe_nid == NID_undef) { 121296465Sdelphij BIO_printf(bio_err, "Unknown PBE algorithm %s\n", *args); 122296465Sdelphij badarg = 1; 123296465Sdelphij } 124296465Sdelphij } else 125296465Sdelphij badarg = 1; 126296465Sdelphij } else if (!strcmp(*args, "-inform")) { 127296465Sdelphij if (args[1]) { 128296465Sdelphij args++; 129296465Sdelphij informat = str2fmt(*args); 130296465Sdelphij } else 131296465Sdelphij badarg = 1; 132296465Sdelphij } else if (!strcmp(*args, "-outform")) { 133296465Sdelphij if (args[1]) { 134296465Sdelphij args++; 135296465Sdelphij outformat = str2fmt(*args); 136296465Sdelphij } else 137296465Sdelphij badarg = 1; 138296465Sdelphij } else if (!strcmp(*args, "-topk8")) 139296465Sdelphij topk8 = 1; 140296465Sdelphij else if (!strcmp(*args, "-noiter")) 141296465Sdelphij iter = 1; 142296465Sdelphij else if (!strcmp(*args, "-nocrypt")) 143296465Sdelphij nocrypt = 1; 144296465Sdelphij else if (!strcmp(*args, "-nooct")) 145296465Sdelphij p8_broken = PKCS8_NO_OCTET; 146296465Sdelphij else if (!strcmp(*args, "-nsdb")) 147296465Sdelphij p8_broken = PKCS8_NS_DB; 148296465Sdelphij else if (!strcmp(*args, "-embed")) 149296465Sdelphij p8_broken = PKCS8_EMBEDDED_PARAM; 150296465Sdelphij else if (!strcmp(*args, "-passin")) { 151296465Sdelphij if (!args[1]) 152296465Sdelphij goto bad; 153296465Sdelphij passargin = *(++args); 154296465Sdelphij } else if (!strcmp(*args, "-passout")) { 155296465Sdelphij if (!args[1]) 156296465Sdelphij goto bad; 157296465Sdelphij passargout = *(++args); 158296465Sdelphij } 159111147Snectar#ifndef OPENSSL_NO_ENGINE 160296465Sdelphij else if (strcmp(*args, "-engine") == 0) { 161296465Sdelphij if (!args[1]) 162296465Sdelphij goto bad; 163296465Sdelphij engine = *(++args); 164296465Sdelphij } 165111147Snectar#endif 166296465Sdelphij else if (!strcmp(*args, "-in")) { 167296465Sdelphij if (args[1]) { 168296465Sdelphij args++; 169296465Sdelphij infile = *args; 170296465Sdelphij } else 171296465Sdelphij badarg = 1; 172296465Sdelphij } else if (!strcmp(*args, "-out")) { 173296465Sdelphij if (args[1]) { 174296465Sdelphij args++; 175296465Sdelphij outfile = *args; 176296465Sdelphij } else 177296465Sdelphij badarg = 1; 178296465Sdelphij } else 179296465Sdelphij badarg = 1; 180296465Sdelphij args++; 181296465Sdelphij } 18255714Skris 183296465Sdelphij if (badarg) { 184296465Sdelphij bad: 185296465Sdelphij BIO_printf(bio_err, "Usage pkcs8 [options]\n"); 186296465Sdelphij BIO_printf(bio_err, "where options are\n"); 187296465Sdelphij BIO_printf(bio_err, "-in file input file\n"); 188296465Sdelphij BIO_printf(bio_err, "-inform X input format (DER or PEM)\n"); 189296465Sdelphij BIO_printf(bio_err, 190296465Sdelphij "-passin arg input file pass phrase source\n"); 191296465Sdelphij BIO_printf(bio_err, "-outform X output format (DER or PEM)\n"); 192296465Sdelphij BIO_printf(bio_err, "-out file output file\n"); 193296465Sdelphij BIO_printf(bio_err, 194296465Sdelphij "-passout arg output file pass phrase source\n"); 195296465Sdelphij BIO_printf(bio_err, "-topk8 output PKCS8 file\n"); 196296465Sdelphij BIO_printf(bio_err, 197296465Sdelphij "-nooct use (nonstandard) no octet format\n"); 198296465Sdelphij BIO_printf(bio_err, 199296465Sdelphij "-embed use (nonstandard) embedded DSA parameters format\n"); 200296465Sdelphij BIO_printf(bio_err, 201296465Sdelphij "-nsdb use (nonstandard) DSA Netscape DB format\n"); 202296465Sdelphij BIO_printf(bio_err, "-noiter use 1 as iteration count\n"); 203296465Sdelphij BIO_printf(bio_err, 204296465Sdelphij "-nocrypt use or expect unencrypted private key\n"); 205296465Sdelphij BIO_printf(bio_err, 206296465Sdelphij "-v2 alg use PKCS#5 v2.0 and cipher \"alg\"\n"); 207296465Sdelphij BIO_printf(bio_err, 208296465Sdelphij "-v1 obj use PKCS#5 v1.5 and cipher \"alg\"\n"); 209111147Snectar#ifndef OPENSSL_NO_ENGINE 210296465Sdelphij BIO_printf(bio_err, 211296465Sdelphij " -engine e use engine e, possibly a hardware device.\n"); 212111147Snectar#endif 213296465Sdelphij return 1; 214296465Sdelphij } 215111147Snectar#ifndef OPENSSL_NO_ENGINE 216296465Sdelphij e = setup_engine(bio_err, engine, 0); 217111147Snectar#endif 218109998Smarkm 219296465Sdelphij if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { 220296465Sdelphij BIO_printf(bio_err, "Error getting passwords\n"); 221296465Sdelphij return 1; 222296465Sdelphij } 22359191Skris 224296465Sdelphij if ((pbe_nid == -1) && !cipher) 225296465Sdelphij pbe_nid = NID_pbeWithMD5AndDES_CBC; 22655714Skris 227296465Sdelphij if (infile) { 228296465Sdelphij if (!(in = BIO_new_file(infile, "rb"))) { 229296465Sdelphij BIO_printf(bio_err, "Can't open input file %s\n", infile); 230296465Sdelphij return (1); 231296465Sdelphij } 232296465Sdelphij } else 233296465Sdelphij in = BIO_new_fp(stdin, BIO_NOCLOSE); 23455714Skris 235296465Sdelphij if (outfile) { 236296465Sdelphij if (!(out = BIO_new_file(outfile, "wb"))) { 237296465Sdelphij BIO_printf(bio_err, "Can't open output file %s\n", outfile); 238296465Sdelphij return (1); 239296465Sdelphij } 240296465Sdelphij } else { 241296465Sdelphij out = BIO_new_fp(stdout, BIO_NOCLOSE); 242109998Smarkm#ifdef OPENSSL_SYS_VMS 243296465Sdelphij { 244296465Sdelphij BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 245296465Sdelphij out = BIO_push(tmpbio, out); 246296465Sdelphij } 247142425Snectar#endif 248296465Sdelphij } 249296465Sdelphij if (topk8) { 250296465Sdelphij BIO_free(in); /* Not needed in this section */ 251296465Sdelphij pkey = load_key(bio_err, infile, informat, 1, passin, e, "key"); 252296465Sdelphij if (!pkey) { 253296465Sdelphij BIO_free_all(out); 254296465Sdelphij return 1; 255296465Sdelphij } 256296465Sdelphij if (!(p8inf = EVP_PKEY2PKCS8_broken(pkey, p8_broken))) { 257296465Sdelphij BIO_printf(bio_err, "Error converting key\n"); 258296465Sdelphij ERR_print_errors(bio_err); 259296465Sdelphij EVP_PKEY_free(pkey); 260296465Sdelphij BIO_free_all(out); 261296465Sdelphij return 1; 262296465Sdelphij } 263296465Sdelphij if (nocrypt) { 264296465Sdelphij if (outformat == FORMAT_PEM) 265296465Sdelphij PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf); 266296465Sdelphij else if (outformat == FORMAT_ASN1) 267296465Sdelphij i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8inf); 268296465Sdelphij else { 269296465Sdelphij BIO_printf(bio_err, "Bad format specified for key\n"); 270296465Sdelphij PKCS8_PRIV_KEY_INFO_free(p8inf); 271296465Sdelphij EVP_PKEY_free(pkey); 272296465Sdelphij BIO_free_all(out); 273296465Sdelphij return (1); 274296465Sdelphij } 275296465Sdelphij } else { 276296465Sdelphij if (passout) 277296465Sdelphij p8pass = passout; 278296465Sdelphij else { 279296465Sdelphij p8pass = pass; 280296465Sdelphij if (EVP_read_pw_string 281296465Sdelphij (pass, sizeof pass, "Enter Encryption Password:", 1)) { 282296465Sdelphij PKCS8_PRIV_KEY_INFO_free(p8inf); 283296465Sdelphij EVP_PKEY_free(pkey); 284296465Sdelphij BIO_free_all(out); 285296465Sdelphij return (1); 286296465Sdelphij } 287296465Sdelphij } 288296465Sdelphij app_RAND_load_file(NULL, bio_err, 0); 289296465Sdelphij if (!(p8 = PKCS8_encrypt(pbe_nid, cipher, 290296465Sdelphij p8pass, strlen(p8pass), 291296465Sdelphij NULL, 0, iter, p8inf))) { 292296465Sdelphij BIO_printf(bio_err, "Error encrypting key\n"); 293296465Sdelphij ERR_print_errors(bio_err); 294296465Sdelphij PKCS8_PRIV_KEY_INFO_free(p8inf); 295296465Sdelphij EVP_PKEY_free(pkey); 296296465Sdelphij BIO_free_all(out); 297296465Sdelphij return (1); 298296465Sdelphij } 299296465Sdelphij app_RAND_write_file(NULL, bio_err); 300296465Sdelphij if (outformat == FORMAT_PEM) 301296465Sdelphij PEM_write_bio_PKCS8(out, p8); 302296465Sdelphij else if (outformat == FORMAT_ASN1) 303296465Sdelphij i2d_PKCS8_bio(out, p8); 304296465Sdelphij else { 305296465Sdelphij BIO_printf(bio_err, "Bad format specified for key\n"); 306296465Sdelphij PKCS8_PRIV_KEY_INFO_free(p8inf); 307296465Sdelphij EVP_PKEY_free(pkey); 308296465Sdelphij BIO_free_all(out); 309296465Sdelphij return (1); 310296465Sdelphij } 311296465Sdelphij X509_SIG_free(p8); 312296465Sdelphij } 313142425Snectar 314296465Sdelphij PKCS8_PRIV_KEY_INFO_free(p8inf); 315296465Sdelphij EVP_PKEY_free(pkey); 316296465Sdelphij BIO_free_all(out); 317296465Sdelphij if (passin) 318296465Sdelphij OPENSSL_free(passin); 319296465Sdelphij if (passout) 320296465Sdelphij OPENSSL_free(passout); 321296465Sdelphij return (0); 322296465Sdelphij } 32355714Skris 324296465Sdelphij if (nocrypt) { 325296465Sdelphij if (informat == FORMAT_PEM) 326296465Sdelphij p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in, NULL, NULL, NULL); 327296465Sdelphij else if (informat == FORMAT_ASN1) 328296465Sdelphij p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL); 329296465Sdelphij else { 330296465Sdelphij BIO_printf(bio_err, "Bad format specified for key\n"); 331296465Sdelphij return (1); 332296465Sdelphij } 333296465Sdelphij } else { 334296465Sdelphij if (informat == FORMAT_PEM) 335296465Sdelphij p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL); 336296465Sdelphij else if (informat == FORMAT_ASN1) 337296465Sdelphij p8 = d2i_PKCS8_bio(in, NULL); 338296465Sdelphij else { 339296465Sdelphij BIO_printf(bio_err, "Bad format specified for key\n"); 340296465Sdelphij return (1); 341296465Sdelphij } 34255714Skris 343296465Sdelphij if (!p8) { 344296465Sdelphij BIO_printf(bio_err, "Error reading key\n"); 345296465Sdelphij ERR_print_errors(bio_err); 346296465Sdelphij return (1); 347296465Sdelphij } 348296465Sdelphij if (passin) 349296465Sdelphij p8pass = passin; 350296465Sdelphij else { 351296465Sdelphij p8pass = pass; 352296465Sdelphij EVP_read_pw_string(pass, sizeof pass, "Enter Password:", 0); 353296465Sdelphij } 354296465Sdelphij p8inf = PKCS8_decrypt(p8, p8pass, strlen(p8pass)); 355296465Sdelphij X509_SIG_free(p8); 356296465Sdelphij } 35755714Skris 358296465Sdelphij if (!p8inf) { 359296465Sdelphij BIO_printf(bio_err, "Error decrypting key\n"); 360296465Sdelphij ERR_print_errors(bio_err); 361296465Sdelphij return (1); 362296465Sdelphij } 36355714Skris 364296465Sdelphij if (!(pkey = EVP_PKCS82PKEY(p8inf))) { 365296465Sdelphij BIO_printf(bio_err, "Error converting key\n"); 366296465Sdelphij ERR_print_errors(bio_err); 367296465Sdelphij return (1); 368296465Sdelphij } 36955714Skris 370296465Sdelphij if (p8inf->broken) { 371296465Sdelphij BIO_printf(bio_err, "Warning: broken key encoding: "); 372296465Sdelphij switch (p8inf->broken) { 373296465Sdelphij case PKCS8_NO_OCTET: 374296465Sdelphij BIO_printf(bio_err, "No Octet String in PrivateKey\n"); 375296465Sdelphij break; 37659191Skris 377296465Sdelphij case PKCS8_EMBEDDED_PARAM: 378296465Sdelphij BIO_printf(bio_err, "DSA parameters included in PrivateKey\n"); 379296465Sdelphij break; 38059191Skris 381296465Sdelphij case PKCS8_NS_DB: 382296465Sdelphij BIO_printf(bio_err, "DSA public key include in PrivateKey\n"); 383296465Sdelphij break; 38455714Skris 385296465Sdelphij default: 386296465Sdelphij BIO_printf(bio_err, "Unknown broken type\n"); 387296465Sdelphij break; 388296465Sdelphij } 389296465Sdelphij } 39055714Skris 391296465Sdelphij PKCS8_PRIV_KEY_INFO_free(p8inf); 392296465Sdelphij if (outformat == FORMAT_PEM) 393296465Sdelphij PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, passout); 394296465Sdelphij else if (outformat == FORMAT_ASN1) 395296465Sdelphij i2d_PrivateKey_bio(out, pkey); 396296465Sdelphij else { 397296465Sdelphij BIO_printf(bio_err, "Bad format specified for key\n"); 398296465Sdelphij return (1); 399296465Sdelphij } 400296465Sdelphij 401296465Sdelphij end: 402296465Sdelphij EVP_PKEY_free(pkey); 403296465Sdelphij BIO_free_all(out); 404296465Sdelphij BIO_free(in); 405296465Sdelphij if (passin) 406296465Sdelphij OPENSSL_free(passin); 407296465Sdelphij if (passout) 408296465Sdelphij OPENSSL_free(passout); 409296465Sdelphij 410296465Sdelphij return (0); 411296465Sdelphij} 412