1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/* Necessary for legacy RSA public key export */ 11e1051a39Sopenharmony_ci#define OPENSSL_SUPPRESS_DEPRECATED 12e1051a39Sopenharmony_ci 13e1051a39Sopenharmony_ci#include <openssl/opensslconf.h> 14e1051a39Sopenharmony_ci 15e1051a39Sopenharmony_ci#include <stdio.h> 16e1051a39Sopenharmony_ci#include <stdlib.h> 17e1051a39Sopenharmony_ci#include <string.h> 18e1051a39Sopenharmony_ci#include <time.h> 19e1051a39Sopenharmony_ci#include "apps.h" 20e1051a39Sopenharmony_ci#include "progs.h" 21e1051a39Sopenharmony_ci#include <openssl/bio.h> 22e1051a39Sopenharmony_ci#include <openssl/err.h> 23e1051a39Sopenharmony_ci#include <openssl/rsa.h> 24e1051a39Sopenharmony_ci#include <openssl/evp.h> 25e1051a39Sopenharmony_ci#include <openssl/x509.h> 26e1051a39Sopenharmony_ci#include <openssl/pem.h> 27e1051a39Sopenharmony_ci#include <openssl/bn.h> 28e1051a39Sopenharmony_ci#include <openssl/encoder.h> 29e1051a39Sopenharmony_ci 30e1051a39Sopenharmony_ci/* 31e1051a39Sopenharmony_ci * This include is to get OSSL_KEYMGMT_SELECT_*, which feels a bit 32e1051a39Sopenharmony_ci * much just for those macros... they might serve better as EVP macros. 33e1051a39Sopenharmony_ci */ 34e1051a39Sopenharmony_ci#include <openssl/core_dispatch.h> 35e1051a39Sopenharmony_ci 36e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_RC4 37e1051a39Sopenharmony_ci# define DEFAULT_PVK_ENCR_STRENGTH 2 38e1051a39Sopenharmony_ci#else 39e1051a39Sopenharmony_ci# define DEFAULT_PVK_ENCR_STRENGTH 0 40e1051a39Sopenharmony_ci#endif 41e1051a39Sopenharmony_ci 42e1051a39Sopenharmony_citypedef enum OPTION_choice { 43e1051a39Sopenharmony_ci OPT_COMMON, 44e1051a39Sopenharmony_ci OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT, 45e1051a39Sopenharmony_ci OPT_PUBIN, OPT_PUBOUT, OPT_PASSOUT, OPT_PASSIN, 46e1051a39Sopenharmony_ci OPT_RSAPUBKEY_IN, OPT_RSAPUBKEY_OUT, 47e1051a39Sopenharmony_ci /* Do not change the order here; see case statements below */ 48e1051a39Sopenharmony_ci OPT_PVK_NONE, OPT_PVK_WEAK, OPT_PVK_STRONG, 49e1051a39Sopenharmony_ci OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_CHECK, OPT_CIPHER, 50e1051a39Sopenharmony_ci OPT_PROV_ENUM, OPT_TRADITIONAL 51e1051a39Sopenharmony_ci} OPTION_CHOICE; 52e1051a39Sopenharmony_ci 53e1051a39Sopenharmony_ciconst OPTIONS rsa_options[] = { 54e1051a39Sopenharmony_ci OPT_SECTION("General"), 55e1051a39Sopenharmony_ci {"help", OPT_HELP, '-', "Display this summary"}, 56e1051a39Sopenharmony_ci {"check", OPT_CHECK, '-', "Verify key consistency"}, 57e1051a39Sopenharmony_ci {"", OPT_CIPHER, '-', "Any supported cipher"}, 58e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE 59e1051a39Sopenharmony_ci {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 60e1051a39Sopenharmony_ci#endif 61e1051a39Sopenharmony_ci 62e1051a39Sopenharmony_ci OPT_SECTION("Input"), 63e1051a39Sopenharmony_ci {"in", OPT_IN, 's', "Input file"}, 64e1051a39Sopenharmony_ci {"inform", OPT_INFORM, 'f', "Input format (DER/PEM/P12/ENGINE)"}, 65e1051a39Sopenharmony_ci {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"}, 66e1051a39Sopenharmony_ci {"RSAPublicKey_in", OPT_RSAPUBKEY_IN, '-', "Input is an RSAPublicKey"}, 67e1051a39Sopenharmony_ci {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, 68e1051a39Sopenharmony_ci 69e1051a39Sopenharmony_ci OPT_SECTION("Output"), 70e1051a39Sopenharmony_ci {"out", OPT_OUT, '>', "Output file"}, 71e1051a39Sopenharmony_ci {"outform", OPT_OUTFORM, 'f', "Output format, one of DER PEM PVK"}, 72e1051a39Sopenharmony_ci {"pubout", OPT_PUBOUT, '-', "Output a public key"}, 73e1051a39Sopenharmony_ci {"RSAPublicKey_out", OPT_RSAPUBKEY_OUT, '-', "Output is an RSAPublicKey"}, 74e1051a39Sopenharmony_ci {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, 75e1051a39Sopenharmony_ci {"noout", OPT_NOOUT, '-', "Don't print key out"}, 76e1051a39Sopenharmony_ci {"text", OPT_TEXT, '-', "Print the key in text"}, 77e1051a39Sopenharmony_ci {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"}, 78e1051a39Sopenharmony_ci {"traditional", OPT_TRADITIONAL, '-', 79e1051a39Sopenharmony_ci "Use traditional format for private keys"}, 80e1051a39Sopenharmony_ci 81e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_RC4 82e1051a39Sopenharmony_ci OPT_SECTION("PVK"), 83e1051a39Sopenharmony_ci {"pvk-strong", OPT_PVK_STRONG, '-', "Enable 'Strong' PVK encoding level (default)"}, 84e1051a39Sopenharmony_ci {"pvk-weak", OPT_PVK_WEAK, '-', "Enable 'Weak' PVK encoding level"}, 85e1051a39Sopenharmony_ci {"pvk-none", OPT_PVK_NONE, '-', "Don't enforce PVK encoding"}, 86e1051a39Sopenharmony_ci#endif 87e1051a39Sopenharmony_ci 88e1051a39Sopenharmony_ci OPT_PROV_OPTIONS, 89e1051a39Sopenharmony_ci {NULL} 90e1051a39Sopenharmony_ci}; 91e1051a39Sopenharmony_ci 92e1051a39Sopenharmony_cistatic int try_legacy_encoding(EVP_PKEY *pkey, int outformat, int pubout, 93e1051a39Sopenharmony_ci BIO *out) 94e1051a39Sopenharmony_ci{ 95e1051a39Sopenharmony_ci int ret = 0; 96e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 97e1051a39Sopenharmony_ci const RSA *rsa = EVP_PKEY_get0_RSA(pkey); 98e1051a39Sopenharmony_ci 99e1051a39Sopenharmony_ci if (rsa == NULL) 100e1051a39Sopenharmony_ci return 0; 101e1051a39Sopenharmony_ci 102e1051a39Sopenharmony_ci if (outformat == FORMAT_ASN1) { 103e1051a39Sopenharmony_ci if (pubout == 2) 104e1051a39Sopenharmony_ci ret = i2d_RSAPublicKey_bio(out, rsa) > 0; 105e1051a39Sopenharmony_ci else 106e1051a39Sopenharmony_ci ret = i2d_RSA_PUBKEY_bio(out, rsa) > 0; 107e1051a39Sopenharmony_ci } else if (outformat == FORMAT_PEM) { 108e1051a39Sopenharmony_ci if (pubout == 2) 109e1051a39Sopenharmony_ci ret = PEM_write_bio_RSAPublicKey(out, rsa) > 0; 110e1051a39Sopenharmony_ci else 111e1051a39Sopenharmony_ci ret = PEM_write_bio_RSA_PUBKEY(out, rsa) > 0; 112e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_DSA 113e1051a39Sopenharmony_ci } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) { 114e1051a39Sopenharmony_ci ret = i2b_PublicKey_bio(out, pkey) > 0; 115e1051a39Sopenharmony_ci# endif 116e1051a39Sopenharmony_ci } 117e1051a39Sopenharmony_ci#endif 118e1051a39Sopenharmony_ci 119e1051a39Sopenharmony_ci return ret; 120e1051a39Sopenharmony_ci} 121e1051a39Sopenharmony_ci 122e1051a39Sopenharmony_ciint rsa_main(int argc, char **argv) 123e1051a39Sopenharmony_ci{ 124e1051a39Sopenharmony_ci ENGINE *e = NULL; 125e1051a39Sopenharmony_ci BIO *out = NULL; 126e1051a39Sopenharmony_ci EVP_PKEY *pkey = NULL; 127e1051a39Sopenharmony_ci EVP_PKEY_CTX *pctx; 128e1051a39Sopenharmony_ci EVP_CIPHER *enc = NULL; 129e1051a39Sopenharmony_ci char *infile = NULL, *outfile = NULL, *ciphername = NULL, *prog; 130e1051a39Sopenharmony_ci char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL; 131e1051a39Sopenharmony_ci int private = 0; 132e1051a39Sopenharmony_ci int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, text = 0, check = 0; 133e1051a39Sopenharmony_ci int noout = 0, modulus = 0, pubin = 0, pubout = 0, ret = 1; 134e1051a39Sopenharmony_ci int pvk_encr = DEFAULT_PVK_ENCR_STRENGTH; 135e1051a39Sopenharmony_ci OPTION_CHOICE o; 136e1051a39Sopenharmony_ci int traditional = 0; 137e1051a39Sopenharmony_ci const char *output_type = NULL; 138e1051a39Sopenharmony_ci const char *output_structure = NULL; 139e1051a39Sopenharmony_ci int selection = 0; 140e1051a39Sopenharmony_ci OSSL_ENCODER_CTX *ectx = NULL; 141e1051a39Sopenharmony_ci 142e1051a39Sopenharmony_ci prog = opt_init(argc, argv, rsa_options); 143e1051a39Sopenharmony_ci while ((o = opt_next()) != OPT_EOF) { 144e1051a39Sopenharmony_ci switch (o) { 145e1051a39Sopenharmony_ci case OPT_EOF: 146e1051a39Sopenharmony_ci case OPT_ERR: 147e1051a39Sopenharmony_ci opthelp: 148e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 149e1051a39Sopenharmony_ci goto end; 150e1051a39Sopenharmony_ci case OPT_HELP: 151e1051a39Sopenharmony_ci opt_help(rsa_options); 152e1051a39Sopenharmony_ci ret = 0; 153e1051a39Sopenharmony_ci goto end; 154e1051a39Sopenharmony_ci case OPT_INFORM: 155e1051a39Sopenharmony_ci if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat)) 156e1051a39Sopenharmony_ci goto opthelp; 157e1051a39Sopenharmony_ci break; 158e1051a39Sopenharmony_ci case OPT_IN: 159e1051a39Sopenharmony_ci infile = opt_arg(); 160e1051a39Sopenharmony_ci break; 161e1051a39Sopenharmony_ci case OPT_OUTFORM: 162e1051a39Sopenharmony_ci if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat)) 163e1051a39Sopenharmony_ci goto opthelp; 164e1051a39Sopenharmony_ci break; 165e1051a39Sopenharmony_ci case OPT_OUT: 166e1051a39Sopenharmony_ci outfile = opt_arg(); 167e1051a39Sopenharmony_ci break; 168e1051a39Sopenharmony_ci case OPT_PASSIN: 169e1051a39Sopenharmony_ci passinarg = opt_arg(); 170e1051a39Sopenharmony_ci break; 171e1051a39Sopenharmony_ci case OPT_PASSOUT: 172e1051a39Sopenharmony_ci passoutarg = opt_arg(); 173e1051a39Sopenharmony_ci break; 174e1051a39Sopenharmony_ci case OPT_ENGINE: 175e1051a39Sopenharmony_ci e = setup_engine(opt_arg(), 0); 176e1051a39Sopenharmony_ci break; 177e1051a39Sopenharmony_ci case OPT_PUBIN: 178e1051a39Sopenharmony_ci pubin = 1; 179e1051a39Sopenharmony_ci break; 180e1051a39Sopenharmony_ci case OPT_PUBOUT: 181e1051a39Sopenharmony_ci pubout = 1; 182e1051a39Sopenharmony_ci break; 183e1051a39Sopenharmony_ci case OPT_RSAPUBKEY_IN: 184e1051a39Sopenharmony_ci pubin = 2; 185e1051a39Sopenharmony_ci break; 186e1051a39Sopenharmony_ci case OPT_RSAPUBKEY_OUT: 187e1051a39Sopenharmony_ci pubout = 2; 188e1051a39Sopenharmony_ci break; 189e1051a39Sopenharmony_ci case OPT_PVK_STRONG: /* pvk_encr:= 2 */ 190e1051a39Sopenharmony_ci case OPT_PVK_WEAK: /* pvk_encr:= 1 */ 191e1051a39Sopenharmony_ci case OPT_PVK_NONE: /* pvk_encr:= 0 */ 192e1051a39Sopenharmony_ci pvk_encr = (o - OPT_PVK_NONE); 193e1051a39Sopenharmony_ci break; 194e1051a39Sopenharmony_ci case OPT_NOOUT: 195e1051a39Sopenharmony_ci noout = 1; 196e1051a39Sopenharmony_ci break; 197e1051a39Sopenharmony_ci case OPT_TEXT: 198e1051a39Sopenharmony_ci text = 1; 199e1051a39Sopenharmony_ci break; 200e1051a39Sopenharmony_ci case OPT_MODULUS: 201e1051a39Sopenharmony_ci modulus = 1; 202e1051a39Sopenharmony_ci break; 203e1051a39Sopenharmony_ci case OPT_CHECK: 204e1051a39Sopenharmony_ci check = 1; 205e1051a39Sopenharmony_ci break; 206e1051a39Sopenharmony_ci case OPT_CIPHER: 207e1051a39Sopenharmony_ci ciphername = opt_unknown(); 208e1051a39Sopenharmony_ci break; 209e1051a39Sopenharmony_ci case OPT_PROV_CASES: 210e1051a39Sopenharmony_ci if (!opt_provider(o)) 211e1051a39Sopenharmony_ci goto end; 212e1051a39Sopenharmony_ci break; 213e1051a39Sopenharmony_ci case OPT_TRADITIONAL: 214e1051a39Sopenharmony_ci traditional = 1; 215e1051a39Sopenharmony_ci break; 216e1051a39Sopenharmony_ci } 217e1051a39Sopenharmony_ci } 218e1051a39Sopenharmony_ci 219e1051a39Sopenharmony_ci /* No extra arguments. */ 220e1051a39Sopenharmony_ci argc = opt_num_rest(); 221e1051a39Sopenharmony_ci if (argc != 0) 222e1051a39Sopenharmony_ci goto opthelp; 223e1051a39Sopenharmony_ci 224e1051a39Sopenharmony_ci if (ciphername != NULL) { 225e1051a39Sopenharmony_ci if (!opt_cipher(ciphername, &enc)) 226e1051a39Sopenharmony_ci goto opthelp; 227e1051a39Sopenharmony_ci } 228e1051a39Sopenharmony_ci private = (text && !pubin) || (!pubout && !noout) ? 1 : 0; 229e1051a39Sopenharmony_ci 230e1051a39Sopenharmony_ci if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { 231e1051a39Sopenharmony_ci BIO_printf(bio_err, "Error getting passwords\n"); 232e1051a39Sopenharmony_ci goto end; 233e1051a39Sopenharmony_ci } 234e1051a39Sopenharmony_ci if (check && pubin) { 235e1051a39Sopenharmony_ci BIO_printf(bio_err, "Only private keys can be checked\n"); 236e1051a39Sopenharmony_ci goto end; 237e1051a39Sopenharmony_ci } 238e1051a39Sopenharmony_ci 239e1051a39Sopenharmony_ci if (pubin) { 240e1051a39Sopenharmony_ci int tmpformat = FORMAT_UNDEF; 241e1051a39Sopenharmony_ci 242e1051a39Sopenharmony_ci if (pubin == 2) { 243e1051a39Sopenharmony_ci if (informat == FORMAT_PEM) 244e1051a39Sopenharmony_ci tmpformat = FORMAT_PEMRSA; 245e1051a39Sopenharmony_ci else if (informat == FORMAT_ASN1) 246e1051a39Sopenharmony_ci tmpformat = FORMAT_ASN1RSA; 247e1051a39Sopenharmony_ci } else { 248e1051a39Sopenharmony_ci tmpformat = informat; 249e1051a39Sopenharmony_ci } 250e1051a39Sopenharmony_ci 251e1051a39Sopenharmony_ci pkey = load_pubkey(infile, tmpformat, 1, passin, e, "public key"); 252e1051a39Sopenharmony_ci } else { 253e1051a39Sopenharmony_ci pkey = load_key(infile, informat, 1, passin, e, "private key"); 254e1051a39Sopenharmony_ci } 255e1051a39Sopenharmony_ci 256e1051a39Sopenharmony_ci if (pkey == NULL) { 257e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 258e1051a39Sopenharmony_ci goto end; 259e1051a39Sopenharmony_ci } 260e1051a39Sopenharmony_ci if (!EVP_PKEY_is_a(pkey, "RSA") && !EVP_PKEY_is_a(pkey, "RSA-PSS")) { 261e1051a39Sopenharmony_ci BIO_printf(bio_err, "Not an RSA key\n"); 262e1051a39Sopenharmony_ci goto end; 263e1051a39Sopenharmony_ci } 264e1051a39Sopenharmony_ci 265e1051a39Sopenharmony_ci out = bio_open_owner(outfile, outformat, private); 266e1051a39Sopenharmony_ci if (out == NULL) 267e1051a39Sopenharmony_ci goto end; 268e1051a39Sopenharmony_ci 269e1051a39Sopenharmony_ci if (text) { 270e1051a39Sopenharmony_ci assert(pubin || private); 271e1051a39Sopenharmony_ci if ((pubin && EVP_PKEY_print_public(out, pkey, 0, NULL) <= 0) 272e1051a39Sopenharmony_ci || (!pubin && EVP_PKEY_print_private(out, pkey, 0, NULL) <= 0)) { 273e1051a39Sopenharmony_ci perror(outfile); 274e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 275e1051a39Sopenharmony_ci goto end; 276e1051a39Sopenharmony_ci } 277e1051a39Sopenharmony_ci } 278e1051a39Sopenharmony_ci 279e1051a39Sopenharmony_ci if (modulus) { 280e1051a39Sopenharmony_ci BIGNUM *n = NULL; 281e1051a39Sopenharmony_ci 282e1051a39Sopenharmony_ci /* Every RSA key has an 'n' */ 283e1051a39Sopenharmony_ci EVP_PKEY_get_bn_param(pkey, "n", &n); 284e1051a39Sopenharmony_ci BIO_printf(out, "Modulus="); 285e1051a39Sopenharmony_ci BN_print(out, n); 286e1051a39Sopenharmony_ci BIO_printf(out, "\n"); 287e1051a39Sopenharmony_ci BN_free(n); 288e1051a39Sopenharmony_ci } 289e1051a39Sopenharmony_ci 290e1051a39Sopenharmony_ci if (check) { 291e1051a39Sopenharmony_ci int r; 292e1051a39Sopenharmony_ci 293e1051a39Sopenharmony_ci pctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL); 294e1051a39Sopenharmony_ci if (pctx == NULL) { 295e1051a39Sopenharmony_ci BIO_printf(bio_err, "RSA unable to create PKEY context\n"); 296e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 297e1051a39Sopenharmony_ci goto end; 298e1051a39Sopenharmony_ci } 299e1051a39Sopenharmony_ci r = EVP_PKEY_check(pctx); 300e1051a39Sopenharmony_ci EVP_PKEY_CTX_free(pctx); 301e1051a39Sopenharmony_ci 302e1051a39Sopenharmony_ci if (r == 1) { 303e1051a39Sopenharmony_ci BIO_printf(out, "RSA key ok\n"); 304e1051a39Sopenharmony_ci } else if (r == 0) { 305e1051a39Sopenharmony_ci BIO_printf(bio_err, "RSA key not ok\n"); 306e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 307e1051a39Sopenharmony_ci } else if (r < 0) { 308e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 309e1051a39Sopenharmony_ci goto end; 310e1051a39Sopenharmony_ci } 311e1051a39Sopenharmony_ci } 312e1051a39Sopenharmony_ci 313e1051a39Sopenharmony_ci if (noout) { 314e1051a39Sopenharmony_ci ret = 0; 315e1051a39Sopenharmony_ci goto end; 316e1051a39Sopenharmony_ci } 317e1051a39Sopenharmony_ci BIO_printf(bio_err, "writing RSA key\n"); 318e1051a39Sopenharmony_ci 319e1051a39Sopenharmony_ci /* Choose output type for the format */ 320e1051a39Sopenharmony_ci if (outformat == FORMAT_ASN1) { 321e1051a39Sopenharmony_ci output_type = "DER"; 322e1051a39Sopenharmony_ci } else if (outformat == FORMAT_PEM) { 323e1051a39Sopenharmony_ci output_type = "PEM"; 324e1051a39Sopenharmony_ci } else if (outformat == FORMAT_MSBLOB) { 325e1051a39Sopenharmony_ci output_type = "MSBLOB"; 326e1051a39Sopenharmony_ci } else if (outformat == FORMAT_PVK) { 327e1051a39Sopenharmony_ci if (pubin) { 328e1051a39Sopenharmony_ci BIO_printf(bio_err, "PVK form impossible with public key input\n"); 329e1051a39Sopenharmony_ci goto end; 330e1051a39Sopenharmony_ci } 331e1051a39Sopenharmony_ci output_type = "PVK"; 332e1051a39Sopenharmony_ci } else { 333e1051a39Sopenharmony_ci BIO_printf(bio_err, "bad output format specified for outfile\n"); 334e1051a39Sopenharmony_ci goto end; 335e1051a39Sopenharmony_ci } 336e1051a39Sopenharmony_ci 337e1051a39Sopenharmony_ci /* Select what you want in the output */ 338e1051a39Sopenharmony_ci if (pubout || pubin) { 339e1051a39Sopenharmony_ci selection = OSSL_KEYMGMT_SELECT_PUBLIC_KEY; 340e1051a39Sopenharmony_ci } else { 341e1051a39Sopenharmony_ci assert(private); 342e1051a39Sopenharmony_ci selection = (OSSL_KEYMGMT_SELECT_KEYPAIR 343e1051a39Sopenharmony_ci | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS); 344e1051a39Sopenharmony_ci } 345e1051a39Sopenharmony_ci 346e1051a39Sopenharmony_ci /* For DER based output, select the desired output structure */ 347e1051a39Sopenharmony_ci if (outformat == FORMAT_ASN1 || outformat == FORMAT_PEM) { 348e1051a39Sopenharmony_ci if (pubout || pubin) { 349e1051a39Sopenharmony_ci if (pubout == 2) 350e1051a39Sopenharmony_ci output_structure = "pkcs1"; /* "type-specific" would work too */ 351e1051a39Sopenharmony_ci else 352e1051a39Sopenharmony_ci output_structure = "SubjectPublicKeyInfo"; 353e1051a39Sopenharmony_ci } else { 354e1051a39Sopenharmony_ci assert(private); 355e1051a39Sopenharmony_ci if (traditional) 356e1051a39Sopenharmony_ci output_structure = "pkcs1"; /* "type-specific" would work too */ 357e1051a39Sopenharmony_ci else 358e1051a39Sopenharmony_ci output_structure = "PrivateKeyInfo"; 359e1051a39Sopenharmony_ci } 360e1051a39Sopenharmony_ci } 361e1051a39Sopenharmony_ci 362e1051a39Sopenharmony_ci /* Now, perform the encoding */ 363e1051a39Sopenharmony_ci ectx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, 364e1051a39Sopenharmony_ci output_type, output_structure, 365e1051a39Sopenharmony_ci NULL); 366e1051a39Sopenharmony_ci if (OSSL_ENCODER_CTX_get_num_encoders(ectx) == 0) { 367e1051a39Sopenharmony_ci if ((!pubout && !pubin) 368e1051a39Sopenharmony_ci || !try_legacy_encoding(pkey, outformat, pubout, out)) 369e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s format not supported\n", output_type); 370e1051a39Sopenharmony_ci else 371e1051a39Sopenharmony_ci ret = 0; 372e1051a39Sopenharmony_ci goto end; 373e1051a39Sopenharmony_ci } 374e1051a39Sopenharmony_ci 375e1051a39Sopenharmony_ci /* Passphrase setup */ 376e1051a39Sopenharmony_ci if (enc != NULL) 377e1051a39Sopenharmony_ci OSSL_ENCODER_CTX_set_cipher(ectx, EVP_CIPHER_get0_name(enc), NULL); 378e1051a39Sopenharmony_ci 379e1051a39Sopenharmony_ci /* Default passphrase prompter */ 380e1051a39Sopenharmony_ci if (enc != NULL || outformat == FORMAT_PVK) { 381e1051a39Sopenharmony_ci OSSL_ENCODER_CTX_set_passphrase_ui(ectx, get_ui_method(), NULL); 382e1051a39Sopenharmony_ci if (passout != NULL) 383e1051a39Sopenharmony_ci /* When passout given, override the passphrase prompter */ 384e1051a39Sopenharmony_ci OSSL_ENCODER_CTX_set_passphrase(ectx, 385e1051a39Sopenharmony_ci (const unsigned char *)passout, 386e1051a39Sopenharmony_ci strlen(passout)); 387e1051a39Sopenharmony_ci } 388e1051a39Sopenharmony_ci 389e1051a39Sopenharmony_ci /* PVK is a bit special... */ 390e1051a39Sopenharmony_ci if (outformat == FORMAT_PVK) { 391e1051a39Sopenharmony_ci OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; 392e1051a39Sopenharmony_ci 393e1051a39Sopenharmony_ci params[0] = OSSL_PARAM_construct_int("encrypt-level", &pvk_encr); 394e1051a39Sopenharmony_ci if (!OSSL_ENCODER_CTX_set_params(ectx, params)) { 395e1051a39Sopenharmony_ci BIO_printf(bio_err, "invalid PVK encryption level\n"); 396e1051a39Sopenharmony_ci goto end; 397e1051a39Sopenharmony_ci } 398e1051a39Sopenharmony_ci } 399e1051a39Sopenharmony_ci 400e1051a39Sopenharmony_ci if (!OSSL_ENCODER_to_bio(ectx, out)) { 401e1051a39Sopenharmony_ci BIO_printf(bio_err, "unable to write key\n"); 402e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 403e1051a39Sopenharmony_ci goto end; 404e1051a39Sopenharmony_ci } 405e1051a39Sopenharmony_ci ret = 0; 406e1051a39Sopenharmony_ci end: 407e1051a39Sopenharmony_ci OSSL_ENCODER_CTX_free(ectx); 408e1051a39Sopenharmony_ci release_engine(e); 409e1051a39Sopenharmony_ci BIO_free_all(out); 410e1051a39Sopenharmony_ci EVP_PKEY_free(pkey); 411e1051a39Sopenharmony_ci EVP_CIPHER_free(enc); 412e1051a39Sopenharmony_ci OPENSSL_free(passin); 413e1051a39Sopenharmony_ci OPENSSL_free(passout); 414e1051a39Sopenharmony_ci return ret; 415e1051a39Sopenharmony_ci} 416