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