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