1 /* 2 * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include "apps.h" 14 #include <openssl/pem.h> 15 #include <openssl/err.h> 16 #include <openssl/evp.h> 17 #include <openssl/pkcs12.h> 18 19 typedef enum OPTION_choice { 20 OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, 21 OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT, 22 OPT_TOPK8, OPT_NOITER, OPT_NOCRYPT, 23 #ifndef OPENSSL_NO_SCRYPT 24 OPT_SCRYPT, OPT_SCRYPT_N, OPT_SCRYPT_R, OPT_SCRYPT_P, 25 #endif 26 OPT_V2, OPT_V1, OPT_V2PRF, OPT_ITER, OPT_PASSIN, OPT_PASSOUT, 27 OPT_TRADITIONAL 28 } OPTION_CHOICE; 29 30 OPTIONS pkcs8_options[] = { 31 {"help", OPT_HELP, '-', "Display this summary"}, 32 {"inform", OPT_INFORM, 'F', "Input format (DER or PEM)"}, 33 {"outform", OPT_OUTFORM, 'F', "Output format (DER or PEM)"}, 34 {"in", OPT_IN, '<', "Input file"}, 35 {"out", OPT_OUT, '>', "Output file"}, 36 {"topk8", OPT_TOPK8, '-', "Output PKCS8 file"}, 37 {"noiter", OPT_NOITER, '-', "Use 1 as iteration count"}, 38 {"nocrypt", OPT_NOCRYPT, '-', "Use or expect unencrypted private key"}, 39 {"v2", OPT_V2, 's', "Use PKCS#5 v2.0 and cipher"}, 40 {"v1", OPT_V1, 's', "Use PKCS#5 v1.5 and cipher"}, 41 {"v2prf", OPT_V2PRF, 's', "Set the PRF algorithm to use with PKCS#5 v2.0"}, 42 {"iter", OPT_ITER, 'p', "Specify the iteration count"}, 43 {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, 44 {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, 45 {"traditional", OPT_TRADITIONAL, '-', "use traditional format private key"}, 46 #ifndef OPENSSL_NO_ENGINE 47 {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 48 #endif 49 #ifndef OPENSSL_NO_SCRYPT 50 {"scrypt", OPT_SCRYPT, '-', "Use scrypt algorithm"}, 51 {"scrypt_N", OPT_SCRYPT_N, 's', "Set scrypt N parameter"}, 52 {"scrypt_r", OPT_SCRYPT_R, 's', "Set scrypt r parameter"}, 53 {"scrypt_p", OPT_SCRYPT_P, 's', "Set scrypt p parameter"}, 54 #endif 55 {NULL} 56 }; 57 58 int pkcs8_main(int argc, char **argv) 59 { 60 BIO *in = NULL, *out = NULL; 61 ENGINE *e = NULL; 62 EVP_PKEY *pkey = NULL; 63 PKCS8_PRIV_KEY_INFO *p8inf = NULL; 64 X509_SIG *p8 = NULL; 65 const EVP_CIPHER *cipher = NULL; 66 char *infile = NULL, *outfile = NULL; 67 char *passinarg = NULL, *passoutarg = NULL, *prog; 68 #ifndef OPENSSL_NO_UI 69 char pass[APP_PASS_LEN]; 70 #endif 71 char *passin = NULL, *passout = NULL, *p8pass = NULL; 72 OPTION_CHOICE o; 73 int nocrypt = 0, ret = 1, iter = PKCS12_DEFAULT_ITER; 74 int informat = FORMAT_PEM, outformat = FORMAT_PEM, topk8 = 0, pbe_nid = -1; 75 int private = 0, traditional = 0; 76 #ifndef OPENSSL_NO_SCRYPT 77 long scrypt_N = 0, scrypt_r = 0, scrypt_p = 0; 78 #endif 79 80 prog = opt_init(argc, argv, pkcs8_options); 81 while ((o = opt_next()) != OPT_EOF) { 82 switch (o) { 83 case OPT_EOF: 84 case OPT_ERR: 85 opthelp: 86 BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 87 goto end; 88 case OPT_HELP: 89 opt_help(pkcs8_options); 90 ret = 0; 91 goto end; 92 case OPT_INFORM: 93 if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) 94 goto opthelp; 95 break; 96 case OPT_IN: 97 infile = opt_arg(); 98 break; 99 case OPT_OUTFORM: 100 if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) 101 goto opthelp; 102 break; 103 case OPT_OUT: 104 outfile = opt_arg(); 105 break; 106 case OPT_TOPK8: 107 topk8 = 1; 108 break; 109 case OPT_NOITER: 110 iter = 1; 111 break; 112 case OPT_NOCRYPT: 113 nocrypt = 1; 114 break; 115 case OPT_TRADITIONAL: 116 traditional = 1; 117 break; 118 case OPT_V2: 119 if (!opt_cipher(opt_arg(), &cipher)) 120 goto opthelp; 121 break; 122 case OPT_V1: 123 pbe_nid = OBJ_txt2nid(opt_arg()); 124 if (pbe_nid == NID_undef) { 125 BIO_printf(bio_err, 126 "%s: Unknown PBE algorithm %s\n", prog, opt_arg()); 127 goto opthelp; 128 } 129 break; 130 case OPT_V2PRF: 131 pbe_nid = OBJ_txt2nid(opt_arg()); 132 if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, pbe_nid, NULL, NULL, 0)) { 133 BIO_printf(bio_err, 134 "%s: Unknown PRF algorithm %s\n", prog, opt_arg()); 135 goto opthelp; 136 } 137 if (cipher == NULL) 138 cipher = EVP_aes_256_cbc(); 139 break; 140 case OPT_ITER: 141 if (!opt_int(opt_arg(), &iter)) 142 goto opthelp; 143 break; 144 case OPT_PASSIN: 145 passinarg = opt_arg(); 146 break; 147 case OPT_PASSOUT: 148 passoutarg = opt_arg(); 149 break; 150 case OPT_ENGINE: 151 e = setup_engine(opt_arg(), 0); 152 break; 153 #ifndef OPENSSL_NO_SCRYPT 154 case OPT_SCRYPT: 155 scrypt_N = 16384; 156 scrypt_r = 8; 157 scrypt_p = 1; 158 if (cipher == NULL) 159 cipher = EVP_aes_256_cbc(); 160 break; 161 case OPT_SCRYPT_N: 162 if (!opt_long(opt_arg(), &scrypt_N) || scrypt_N <= 0) 163 goto opthelp; 164 break; 165 case OPT_SCRYPT_R: 166 if (!opt_long(opt_arg(), &scrypt_r) || scrypt_r <= 0) 167 goto opthelp; 168 break; 169 case OPT_SCRYPT_P: 170 if (!opt_long(opt_arg(), &scrypt_p) || scrypt_p <= 0) 171 goto opthelp; 172 break; 173 #endif 174 } 175 } 176 argc = opt_num_rest(); 177 if (argc != 0) 178 goto opthelp; 179 180 private = 1; 181 182 if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { 183 BIO_printf(bio_err, "Error getting passwords\n"); 184 goto end; 185 } 186 187 if ((pbe_nid == -1) && cipher == NULL) 188 cipher = EVP_aes_256_cbc(); 189 190 in = bio_open_default(infile, 'r', informat); 191 if (in == NULL) 192 goto end; 193 out = bio_open_owner(outfile, outformat, private); 194 if (out == NULL) 195 goto end; 196 197 if (topk8) { 198 pkey = load_key(infile, informat, 1, passin, e, "key"); 199 if (!pkey) 200 goto end; 201 if ((p8inf = EVP_PKEY2PKCS8(pkey)) == NULL) { 202 BIO_printf(bio_err, "Error converting key\n"); 203 ERR_print_errors(bio_err); 204 goto end; 205 } 206 if (nocrypt) { 207 assert(private); 208 if (outformat == FORMAT_PEM) 209 PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf); 210 else if (outformat == FORMAT_ASN1) 211 i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8inf); 212 else { 213 BIO_printf(bio_err, "Bad format specified for key\n"); 214 goto end; 215 } 216 } else { 217 X509_ALGOR *pbe; 218 if (cipher) { 219 #ifndef OPENSSL_NO_SCRYPT 220 if (scrypt_N && scrypt_r && scrypt_p) 221 pbe = PKCS5_pbe2_set_scrypt(cipher, NULL, 0, NULL, 222 scrypt_N, scrypt_r, scrypt_p); 223 else 224 #endif 225 pbe = PKCS5_pbe2_set_iv(cipher, iter, NULL, 0, NULL, 226 pbe_nid); 227 } else { 228 pbe = PKCS5_pbe_set(pbe_nid, iter, NULL, 0); 229 } 230 if (pbe == NULL) { 231 BIO_printf(bio_err, "Error setting PBE algorithm\n"); 232 ERR_print_errors(bio_err); 233 goto end; 234 } 235 if (passout) 236 p8pass = passout; 237 else if (1) { 238 #ifndef OPENSSL_NO_UI 239 p8pass = pass; 240 if (EVP_read_pw_string 241 (pass, sizeof(pass), "Enter Encryption Password:", 1)) { 242 X509_ALGOR_free(pbe); 243 goto end; 244 } 245 } else { 246 #endif 247 BIO_printf(bio_err, "Password required\n"); 248 goto end; 249 } 250 app_RAND_load_file(NULL, 0); 251 p8 = PKCS8_set0_pbe(p8pass, strlen(p8pass), p8inf, pbe); 252 if (p8 == NULL) { 253 X509_ALGOR_free(pbe); 254 BIO_printf(bio_err, "Error encrypting key\n"); 255 ERR_print_errors(bio_err); 256 goto end; 257 } 258 app_RAND_write_file(NULL); 259 assert(private); 260 if (outformat == FORMAT_PEM) 261 PEM_write_bio_PKCS8(out, p8); 262 else if (outformat == FORMAT_ASN1) 263 i2d_PKCS8_bio(out, p8); 264 else { 265 BIO_printf(bio_err, "Bad format specified for key\n"); 266 goto end; 267 } 268 } 269 270 ret = 0; 271 goto end; 272 } 273 274 if (nocrypt) { 275 if (informat == FORMAT_PEM) 276 p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in, NULL, NULL, NULL); 277 else if (informat == FORMAT_ASN1) 278 p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL); 279 else { 280 BIO_printf(bio_err, "Bad format specified for key\n"); 281 goto end; 282 } 283 } else { 284 if (informat == FORMAT_PEM) 285 p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL); 286 else if (informat == FORMAT_ASN1) 287 p8 = d2i_PKCS8_bio(in, NULL); 288 else { 289 BIO_printf(bio_err, "Bad format specified for key\n"); 290 goto end; 291 } 292 293 if (!p8) { 294 BIO_printf(bio_err, "Error reading key\n"); 295 ERR_print_errors(bio_err); 296 goto end; 297 } 298 if (passin) 299 p8pass = passin; 300 else if (1) { 301 #ifndef OPENSSL_NO_UI 302 p8pass = pass; 303 if (EVP_read_pw_string(pass, sizeof(pass), "Enter Password:", 0)) { 304 BIO_printf(bio_err, "Can't read Password\n"); 305 goto end; 306 } 307 } else { 308 #endif 309 BIO_printf(bio_err, "Password required\n"); 310 goto end; 311 } 312 p8inf = PKCS8_decrypt(p8, p8pass, strlen(p8pass)); 313 } 314 315 if (!p8inf) { 316 BIO_printf(bio_err, "Error decrypting key\n"); 317 ERR_print_errors(bio_err); 318 goto end; 319 } 320 321 if ((pkey = EVP_PKCS82PKEY(p8inf)) == NULL) { 322 BIO_printf(bio_err, "Error converting key\n"); 323 ERR_print_errors(bio_err); 324 goto end; 325 } 326 327 assert(private); 328 if (outformat == FORMAT_PEM) { 329 if (traditional) 330 PEM_write_bio_PrivateKey_traditional(out, pkey, NULL, NULL, 0, 331 NULL, passout); 332 else 333 PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, passout); 334 } else if (outformat == FORMAT_ASN1) { 335 i2d_PrivateKey_bio(out, pkey); 336 } else { 337 BIO_printf(bio_err, "Bad format specified for key\n"); 338 goto end; 339 } 340 ret = 0; 341 342 end: 343 X509_SIG_free(p8); 344 PKCS8_PRIV_KEY_INFO_free(p8inf); 345 EVP_PKEY_free(pkey); 346 release_engine(e); 347 BIO_free_all(out); 348 BIO_free(in); 349 OPENSSL_free(passin); 350 OPENSSL_free(passout); 351 352 return ret; 353 } 354