11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. 31cb0ef41Sopenharmony_ci * 41cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 51cb0ef41Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 61cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at 71cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html 81cb0ef41Sopenharmony_ci */ 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci/* Necessary for legacy RSA public key export */ 111cb0ef41Sopenharmony_ci#define OPENSSL_SUPPRESS_DEPRECATED 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ci#include <openssl/opensslconf.h> 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ci#include <stdio.h> 161cb0ef41Sopenharmony_ci#include <stdlib.h> 171cb0ef41Sopenharmony_ci#include <string.h> 181cb0ef41Sopenharmony_ci#include <time.h> 191cb0ef41Sopenharmony_ci#include "apps.h" 201cb0ef41Sopenharmony_ci#include "progs.h" 211cb0ef41Sopenharmony_ci#include <openssl/bio.h> 221cb0ef41Sopenharmony_ci#include <openssl/err.h> 231cb0ef41Sopenharmony_ci#include <openssl/rsa.h> 241cb0ef41Sopenharmony_ci#include <openssl/evp.h> 251cb0ef41Sopenharmony_ci#include <openssl/x509.h> 261cb0ef41Sopenharmony_ci#include <openssl/pem.h> 271cb0ef41Sopenharmony_ci#include <openssl/bn.h> 281cb0ef41Sopenharmony_ci#include <openssl/encoder.h> 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci/* 311cb0ef41Sopenharmony_ci * This include is to get OSSL_KEYMGMT_SELECT_*, which feels a bit 321cb0ef41Sopenharmony_ci * much just for those macros... they might serve better as EVP macros. 331cb0ef41Sopenharmony_ci */ 341cb0ef41Sopenharmony_ci#include <openssl/core_dispatch.h> 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_ci#ifndef OPENSSL_NO_RC4 371cb0ef41Sopenharmony_ci# define DEFAULT_PVK_ENCR_STRENGTH 2 381cb0ef41Sopenharmony_ci#else 391cb0ef41Sopenharmony_ci# define DEFAULT_PVK_ENCR_STRENGTH 0 401cb0ef41Sopenharmony_ci#endif 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_citypedef enum OPTION_choice { 431cb0ef41Sopenharmony_ci OPT_COMMON, 441cb0ef41Sopenharmony_ci OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT, 451cb0ef41Sopenharmony_ci OPT_PUBIN, OPT_PUBOUT, OPT_PASSOUT, OPT_PASSIN, 461cb0ef41Sopenharmony_ci OPT_RSAPUBKEY_IN, OPT_RSAPUBKEY_OUT, 471cb0ef41Sopenharmony_ci /* Do not change the order here; see case statements below */ 481cb0ef41Sopenharmony_ci OPT_PVK_NONE, OPT_PVK_WEAK, OPT_PVK_STRONG, 491cb0ef41Sopenharmony_ci OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_CHECK, OPT_CIPHER, 501cb0ef41Sopenharmony_ci OPT_PROV_ENUM, OPT_TRADITIONAL 511cb0ef41Sopenharmony_ci} OPTION_CHOICE; 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ciconst OPTIONS rsa_options[] = { 541cb0ef41Sopenharmony_ci OPT_SECTION("General"), 551cb0ef41Sopenharmony_ci {"help", OPT_HELP, '-', "Display this summary"}, 561cb0ef41Sopenharmony_ci {"check", OPT_CHECK, '-', "Verify key consistency"}, 571cb0ef41Sopenharmony_ci {"", OPT_CIPHER, '-', "Any supported cipher"}, 581cb0ef41Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE 591cb0ef41Sopenharmony_ci {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 601cb0ef41Sopenharmony_ci#endif 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci OPT_SECTION("Input"), 631cb0ef41Sopenharmony_ci {"in", OPT_IN, 's', "Input file"}, 641cb0ef41Sopenharmony_ci {"inform", OPT_INFORM, 'f', "Input format (DER/PEM/P12/ENGINE)"}, 651cb0ef41Sopenharmony_ci {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"}, 661cb0ef41Sopenharmony_ci {"RSAPublicKey_in", OPT_RSAPUBKEY_IN, '-', "Input is an RSAPublicKey"}, 671cb0ef41Sopenharmony_ci {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci OPT_SECTION("Output"), 701cb0ef41Sopenharmony_ci {"out", OPT_OUT, '>', "Output file"}, 711cb0ef41Sopenharmony_ci {"outform", OPT_OUTFORM, 'f', "Output format, one of DER PEM PVK"}, 721cb0ef41Sopenharmony_ci {"pubout", OPT_PUBOUT, '-', "Output a public key"}, 731cb0ef41Sopenharmony_ci {"RSAPublicKey_out", OPT_RSAPUBKEY_OUT, '-', "Output is an RSAPublicKey"}, 741cb0ef41Sopenharmony_ci {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, 751cb0ef41Sopenharmony_ci {"noout", OPT_NOOUT, '-', "Don't print key out"}, 761cb0ef41Sopenharmony_ci {"text", OPT_TEXT, '-', "Print the key in text"}, 771cb0ef41Sopenharmony_ci {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"}, 781cb0ef41Sopenharmony_ci {"traditional", OPT_TRADITIONAL, '-', 791cb0ef41Sopenharmony_ci "Use traditional format for private keys"}, 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci#ifndef OPENSSL_NO_RC4 821cb0ef41Sopenharmony_ci OPT_SECTION("PVK"), 831cb0ef41Sopenharmony_ci {"pvk-strong", OPT_PVK_STRONG, '-', "Enable 'Strong' PVK encoding level (default)"}, 841cb0ef41Sopenharmony_ci {"pvk-weak", OPT_PVK_WEAK, '-', "Enable 'Weak' PVK encoding level"}, 851cb0ef41Sopenharmony_ci {"pvk-none", OPT_PVK_NONE, '-', "Don't enforce PVK encoding"}, 861cb0ef41Sopenharmony_ci#endif 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci OPT_PROV_OPTIONS, 891cb0ef41Sopenharmony_ci {NULL} 901cb0ef41Sopenharmony_ci}; 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_cistatic int try_legacy_encoding(EVP_PKEY *pkey, int outformat, int pubout, 931cb0ef41Sopenharmony_ci BIO *out) 941cb0ef41Sopenharmony_ci{ 951cb0ef41Sopenharmony_ci int ret = 0; 961cb0ef41Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 971cb0ef41Sopenharmony_ci const RSA *rsa = EVP_PKEY_get0_RSA(pkey); 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci if (rsa == NULL) 1001cb0ef41Sopenharmony_ci return 0; 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci if (outformat == FORMAT_ASN1) { 1031cb0ef41Sopenharmony_ci if (pubout == 2) 1041cb0ef41Sopenharmony_ci ret = i2d_RSAPublicKey_bio(out, rsa) > 0; 1051cb0ef41Sopenharmony_ci else 1061cb0ef41Sopenharmony_ci ret = i2d_RSA_PUBKEY_bio(out, rsa) > 0; 1071cb0ef41Sopenharmony_ci } else if (outformat == FORMAT_PEM) { 1081cb0ef41Sopenharmony_ci if (pubout == 2) 1091cb0ef41Sopenharmony_ci ret = PEM_write_bio_RSAPublicKey(out, rsa) > 0; 1101cb0ef41Sopenharmony_ci else 1111cb0ef41Sopenharmony_ci ret = PEM_write_bio_RSA_PUBKEY(out, rsa) > 0; 1121cb0ef41Sopenharmony_ci# ifndef OPENSSL_NO_DSA 1131cb0ef41Sopenharmony_ci } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) { 1141cb0ef41Sopenharmony_ci ret = i2b_PublicKey_bio(out, pkey) > 0; 1151cb0ef41Sopenharmony_ci# endif 1161cb0ef41Sopenharmony_ci } 1171cb0ef41Sopenharmony_ci#endif 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_ci return ret; 1201cb0ef41Sopenharmony_ci} 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ciint rsa_main(int argc, char **argv) 1231cb0ef41Sopenharmony_ci{ 1241cb0ef41Sopenharmony_ci ENGINE *e = NULL; 1251cb0ef41Sopenharmony_ci BIO *out = NULL; 1261cb0ef41Sopenharmony_ci EVP_PKEY *pkey = NULL; 1271cb0ef41Sopenharmony_ci EVP_PKEY_CTX *pctx; 1281cb0ef41Sopenharmony_ci EVP_CIPHER *enc = NULL; 1291cb0ef41Sopenharmony_ci char *infile = NULL, *outfile = NULL, *ciphername = NULL, *prog; 1301cb0ef41Sopenharmony_ci char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL; 1311cb0ef41Sopenharmony_ci int private = 0; 1321cb0ef41Sopenharmony_ci int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, text = 0, check = 0; 1331cb0ef41Sopenharmony_ci int noout = 0, modulus = 0, pubin = 0, pubout = 0, ret = 1; 1341cb0ef41Sopenharmony_ci int pvk_encr = DEFAULT_PVK_ENCR_STRENGTH; 1351cb0ef41Sopenharmony_ci OPTION_CHOICE o; 1361cb0ef41Sopenharmony_ci int traditional = 0; 1371cb0ef41Sopenharmony_ci const char *output_type = NULL; 1381cb0ef41Sopenharmony_ci const char *output_structure = NULL; 1391cb0ef41Sopenharmony_ci int selection = 0; 1401cb0ef41Sopenharmony_ci OSSL_ENCODER_CTX *ectx = NULL; 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ci prog = opt_init(argc, argv, rsa_options); 1431cb0ef41Sopenharmony_ci while ((o = opt_next()) != OPT_EOF) { 1441cb0ef41Sopenharmony_ci switch (o) { 1451cb0ef41Sopenharmony_ci case OPT_EOF: 1461cb0ef41Sopenharmony_ci case OPT_ERR: 1471cb0ef41Sopenharmony_ci opthelp: 1481cb0ef41Sopenharmony_ci BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 1491cb0ef41Sopenharmony_ci goto end; 1501cb0ef41Sopenharmony_ci case OPT_HELP: 1511cb0ef41Sopenharmony_ci opt_help(rsa_options); 1521cb0ef41Sopenharmony_ci ret = 0; 1531cb0ef41Sopenharmony_ci goto end; 1541cb0ef41Sopenharmony_ci case OPT_INFORM: 1551cb0ef41Sopenharmony_ci if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat)) 1561cb0ef41Sopenharmony_ci goto opthelp; 1571cb0ef41Sopenharmony_ci break; 1581cb0ef41Sopenharmony_ci case OPT_IN: 1591cb0ef41Sopenharmony_ci infile = opt_arg(); 1601cb0ef41Sopenharmony_ci break; 1611cb0ef41Sopenharmony_ci case OPT_OUTFORM: 1621cb0ef41Sopenharmony_ci if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat)) 1631cb0ef41Sopenharmony_ci goto opthelp; 1641cb0ef41Sopenharmony_ci break; 1651cb0ef41Sopenharmony_ci case OPT_OUT: 1661cb0ef41Sopenharmony_ci outfile = opt_arg(); 1671cb0ef41Sopenharmony_ci break; 1681cb0ef41Sopenharmony_ci case OPT_PASSIN: 1691cb0ef41Sopenharmony_ci passinarg = opt_arg(); 1701cb0ef41Sopenharmony_ci break; 1711cb0ef41Sopenharmony_ci case OPT_PASSOUT: 1721cb0ef41Sopenharmony_ci passoutarg = opt_arg(); 1731cb0ef41Sopenharmony_ci break; 1741cb0ef41Sopenharmony_ci case OPT_ENGINE: 1751cb0ef41Sopenharmony_ci e = setup_engine(opt_arg(), 0); 1761cb0ef41Sopenharmony_ci break; 1771cb0ef41Sopenharmony_ci case OPT_PUBIN: 1781cb0ef41Sopenharmony_ci pubin = 1; 1791cb0ef41Sopenharmony_ci break; 1801cb0ef41Sopenharmony_ci case OPT_PUBOUT: 1811cb0ef41Sopenharmony_ci pubout = 1; 1821cb0ef41Sopenharmony_ci break; 1831cb0ef41Sopenharmony_ci case OPT_RSAPUBKEY_IN: 1841cb0ef41Sopenharmony_ci pubin = 2; 1851cb0ef41Sopenharmony_ci break; 1861cb0ef41Sopenharmony_ci case OPT_RSAPUBKEY_OUT: 1871cb0ef41Sopenharmony_ci pubout = 2; 1881cb0ef41Sopenharmony_ci break; 1891cb0ef41Sopenharmony_ci case OPT_PVK_STRONG: /* pvk_encr:= 2 */ 1901cb0ef41Sopenharmony_ci case OPT_PVK_WEAK: /* pvk_encr:= 1 */ 1911cb0ef41Sopenharmony_ci case OPT_PVK_NONE: /* pvk_encr:= 0 */ 1921cb0ef41Sopenharmony_ci pvk_encr = (o - OPT_PVK_NONE); 1931cb0ef41Sopenharmony_ci break; 1941cb0ef41Sopenharmony_ci case OPT_NOOUT: 1951cb0ef41Sopenharmony_ci noout = 1; 1961cb0ef41Sopenharmony_ci break; 1971cb0ef41Sopenharmony_ci case OPT_TEXT: 1981cb0ef41Sopenharmony_ci text = 1; 1991cb0ef41Sopenharmony_ci break; 2001cb0ef41Sopenharmony_ci case OPT_MODULUS: 2011cb0ef41Sopenharmony_ci modulus = 1; 2021cb0ef41Sopenharmony_ci break; 2031cb0ef41Sopenharmony_ci case OPT_CHECK: 2041cb0ef41Sopenharmony_ci check = 1; 2051cb0ef41Sopenharmony_ci break; 2061cb0ef41Sopenharmony_ci case OPT_CIPHER: 2071cb0ef41Sopenharmony_ci ciphername = opt_unknown(); 2081cb0ef41Sopenharmony_ci break; 2091cb0ef41Sopenharmony_ci case OPT_PROV_CASES: 2101cb0ef41Sopenharmony_ci if (!opt_provider(o)) 2111cb0ef41Sopenharmony_ci goto end; 2121cb0ef41Sopenharmony_ci break; 2131cb0ef41Sopenharmony_ci case OPT_TRADITIONAL: 2141cb0ef41Sopenharmony_ci traditional = 1; 2151cb0ef41Sopenharmony_ci break; 2161cb0ef41Sopenharmony_ci } 2171cb0ef41Sopenharmony_ci } 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ci /* No extra arguments. */ 2201cb0ef41Sopenharmony_ci argc = opt_num_rest(); 2211cb0ef41Sopenharmony_ci if (argc != 0) 2221cb0ef41Sopenharmony_ci goto opthelp; 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_ci if (ciphername != NULL) { 2251cb0ef41Sopenharmony_ci if (!opt_cipher(ciphername, &enc)) 2261cb0ef41Sopenharmony_ci goto opthelp; 2271cb0ef41Sopenharmony_ci } 2281cb0ef41Sopenharmony_ci private = (text && !pubin) || (!pubout && !noout) ? 1 : 0; 2291cb0ef41Sopenharmony_ci 2301cb0ef41Sopenharmony_ci if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { 2311cb0ef41Sopenharmony_ci BIO_printf(bio_err, "Error getting passwords\n"); 2321cb0ef41Sopenharmony_ci goto end; 2331cb0ef41Sopenharmony_ci } 2341cb0ef41Sopenharmony_ci if (check && pubin) { 2351cb0ef41Sopenharmony_ci BIO_printf(bio_err, "Only private keys can be checked\n"); 2361cb0ef41Sopenharmony_ci goto end; 2371cb0ef41Sopenharmony_ci } 2381cb0ef41Sopenharmony_ci 2391cb0ef41Sopenharmony_ci if (pubin) { 2401cb0ef41Sopenharmony_ci int tmpformat = FORMAT_UNDEF; 2411cb0ef41Sopenharmony_ci 2421cb0ef41Sopenharmony_ci if (pubin == 2) { 2431cb0ef41Sopenharmony_ci if (informat == FORMAT_PEM) 2441cb0ef41Sopenharmony_ci tmpformat = FORMAT_PEMRSA; 2451cb0ef41Sopenharmony_ci else if (informat == FORMAT_ASN1) 2461cb0ef41Sopenharmony_ci tmpformat = FORMAT_ASN1RSA; 2471cb0ef41Sopenharmony_ci } else { 2481cb0ef41Sopenharmony_ci tmpformat = informat; 2491cb0ef41Sopenharmony_ci } 2501cb0ef41Sopenharmony_ci 2511cb0ef41Sopenharmony_ci pkey = load_pubkey(infile, tmpformat, 1, passin, e, "public key"); 2521cb0ef41Sopenharmony_ci } else { 2531cb0ef41Sopenharmony_ci pkey = load_key(infile, informat, 1, passin, e, "private key"); 2541cb0ef41Sopenharmony_ci } 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_ci if (pkey == NULL) { 2571cb0ef41Sopenharmony_ci ERR_print_errors(bio_err); 2581cb0ef41Sopenharmony_ci goto end; 2591cb0ef41Sopenharmony_ci } 2601cb0ef41Sopenharmony_ci if (!EVP_PKEY_is_a(pkey, "RSA") && !EVP_PKEY_is_a(pkey, "RSA-PSS")) { 2611cb0ef41Sopenharmony_ci BIO_printf(bio_err, "Not an RSA key\n"); 2621cb0ef41Sopenharmony_ci goto end; 2631cb0ef41Sopenharmony_ci } 2641cb0ef41Sopenharmony_ci 2651cb0ef41Sopenharmony_ci out = bio_open_owner(outfile, outformat, private); 2661cb0ef41Sopenharmony_ci if (out == NULL) 2671cb0ef41Sopenharmony_ci goto end; 2681cb0ef41Sopenharmony_ci 2691cb0ef41Sopenharmony_ci if (text) { 2701cb0ef41Sopenharmony_ci assert(pubin || private); 2711cb0ef41Sopenharmony_ci if ((pubin && EVP_PKEY_print_public(out, pkey, 0, NULL) <= 0) 2721cb0ef41Sopenharmony_ci || (!pubin && EVP_PKEY_print_private(out, pkey, 0, NULL) <= 0)) { 2731cb0ef41Sopenharmony_ci perror(outfile); 2741cb0ef41Sopenharmony_ci ERR_print_errors(bio_err); 2751cb0ef41Sopenharmony_ci goto end; 2761cb0ef41Sopenharmony_ci } 2771cb0ef41Sopenharmony_ci } 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ci if (modulus) { 2801cb0ef41Sopenharmony_ci BIGNUM *n = NULL; 2811cb0ef41Sopenharmony_ci 2821cb0ef41Sopenharmony_ci /* Every RSA key has an 'n' */ 2831cb0ef41Sopenharmony_ci EVP_PKEY_get_bn_param(pkey, "n", &n); 2841cb0ef41Sopenharmony_ci BIO_printf(out, "Modulus="); 2851cb0ef41Sopenharmony_ci BN_print(out, n); 2861cb0ef41Sopenharmony_ci BIO_printf(out, "\n"); 2871cb0ef41Sopenharmony_ci BN_free(n); 2881cb0ef41Sopenharmony_ci } 2891cb0ef41Sopenharmony_ci 2901cb0ef41Sopenharmony_ci if (check) { 2911cb0ef41Sopenharmony_ci int r; 2921cb0ef41Sopenharmony_ci 2931cb0ef41Sopenharmony_ci pctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL); 2941cb0ef41Sopenharmony_ci if (pctx == NULL) { 2951cb0ef41Sopenharmony_ci BIO_printf(bio_err, "RSA unable to create PKEY context\n"); 2961cb0ef41Sopenharmony_ci ERR_print_errors(bio_err); 2971cb0ef41Sopenharmony_ci goto end; 2981cb0ef41Sopenharmony_ci } 2991cb0ef41Sopenharmony_ci r = EVP_PKEY_check(pctx); 3001cb0ef41Sopenharmony_ci EVP_PKEY_CTX_free(pctx); 3011cb0ef41Sopenharmony_ci 3021cb0ef41Sopenharmony_ci if (r == 1) { 3031cb0ef41Sopenharmony_ci BIO_printf(out, "RSA key ok\n"); 3041cb0ef41Sopenharmony_ci } else if (r == 0) { 3051cb0ef41Sopenharmony_ci BIO_printf(bio_err, "RSA key not ok\n"); 3061cb0ef41Sopenharmony_ci ERR_print_errors(bio_err); 3071cb0ef41Sopenharmony_ci } else if (r < 0) { 3081cb0ef41Sopenharmony_ci ERR_print_errors(bio_err); 3091cb0ef41Sopenharmony_ci goto end; 3101cb0ef41Sopenharmony_ci } 3111cb0ef41Sopenharmony_ci } 3121cb0ef41Sopenharmony_ci 3131cb0ef41Sopenharmony_ci if (noout) { 3141cb0ef41Sopenharmony_ci ret = 0; 3151cb0ef41Sopenharmony_ci goto end; 3161cb0ef41Sopenharmony_ci } 3171cb0ef41Sopenharmony_ci BIO_printf(bio_err, "writing RSA key\n"); 3181cb0ef41Sopenharmony_ci 3191cb0ef41Sopenharmony_ci /* Choose output type for the format */ 3201cb0ef41Sopenharmony_ci if (outformat == FORMAT_ASN1) { 3211cb0ef41Sopenharmony_ci output_type = "DER"; 3221cb0ef41Sopenharmony_ci } else if (outformat == FORMAT_PEM) { 3231cb0ef41Sopenharmony_ci output_type = "PEM"; 3241cb0ef41Sopenharmony_ci } else if (outformat == FORMAT_MSBLOB) { 3251cb0ef41Sopenharmony_ci output_type = "MSBLOB"; 3261cb0ef41Sopenharmony_ci } else if (outformat == FORMAT_PVK) { 3271cb0ef41Sopenharmony_ci if (pubin) { 3281cb0ef41Sopenharmony_ci BIO_printf(bio_err, "PVK form impossible with public key input\n"); 3291cb0ef41Sopenharmony_ci goto end; 3301cb0ef41Sopenharmony_ci } 3311cb0ef41Sopenharmony_ci output_type = "PVK"; 3321cb0ef41Sopenharmony_ci } else { 3331cb0ef41Sopenharmony_ci BIO_printf(bio_err, "bad output format specified for outfile\n"); 3341cb0ef41Sopenharmony_ci goto end; 3351cb0ef41Sopenharmony_ci } 3361cb0ef41Sopenharmony_ci 3371cb0ef41Sopenharmony_ci /* Select what you want in the output */ 3381cb0ef41Sopenharmony_ci if (pubout || pubin) { 3391cb0ef41Sopenharmony_ci selection = OSSL_KEYMGMT_SELECT_PUBLIC_KEY; 3401cb0ef41Sopenharmony_ci } else { 3411cb0ef41Sopenharmony_ci assert(private); 3421cb0ef41Sopenharmony_ci selection = (OSSL_KEYMGMT_SELECT_KEYPAIR 3431cb0ef41Sopenharmony_ci | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS); 3441cb0ef41Sopenharmony_ci } 3451cb0ef41Sopenharmony_ci 3461cb0ef41Sopenharmony_ci /* For DER based output, select the desired output structure */ 3471cb0ef41Sopenharmony_ci if (outformat == FORMAT_ASN1 || outformat == FORMAT_PEM) { 3481cb0ef41Sopenharmony_ci if (pubout || pubin) { 3491cb0ef41Sopenharmony_ci if (pubout == 2) 3501cb0ef41Sopenharmony_ci output_structure = "pkcs1"; /* "type-specific" would work too */ 3511cb0ef41Sopenharmony_ci else 3521cb0ef41Sopenharmony_ci output_structure = "SubjectPublicKeyInfo"; 3531cb0ef41Sopenharmony_ci } else { 3541cb0ef41Sopenharmony_ci assert(private); 3551cb0ef41Sopenharmony_ci if (traditional) 3561cb0ef41Sopenharmony_ci output_structure = "pkcs1"; /* "type-specific" would work too */ 3571cb0ef41Sopenharmony_ci else 3581cb0ef41Sopenharmony_ci output_structure = "PrivateKeyInfo"; 3591cb0ef41Sopenharmony_ci } 3601cb0ef41Sopenharmony_ci } 3611cb0ef41Sopenharmony_ci 3621cb0ef41Sopenharmony_ci /* Now, perform the encoding */ 3631cb0ef41Sopenharmony_ci ectx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, 3641cb0ef41Sopenharmony_ci output_type, output_structure, 3651cb0ef41Sopenharmony_ci NULL); 3661cb0ef41Sopenharmony_ci if (OSSL_ENCODER_CTX_get_num_encoders(ectx) == 0) { 3671cb0ef41Sopenharmony_ci if ((!pubout && !pubin) 3681cb0ef41Sopenharmony_ci || !try_legacy_encoding(pkey, outformat, pubout, out)) 3691cb0ef41Sopenharmony_ci BIO_printf(bio_err, "%s format not supported\n", output_type); 3701cb0ef41Sopenharmony_ci else 3711cb0ef41Sopenharmony_ci ret = 0; 3721cb0ef41Sopenharmony_ci goto end; 3731cb0ef41Sopenharmony_ci } 3741cb0ef41Sopenharmony_ci 3751cb0ef41Sopenharmony_ci /* Passphrase setup */ 3761cb0ef41Sopenharmony_ci if (enc != NULL) 3771cb0ef41Sopenharmony_ci OSSL_ENCODER_CTX_set_cipher(ectx, EVP_CIPHER_get0_name(enc), NULL); 3781cb0ef41Sopenharmony_ci 3791cb0ef41Sopenharmony_ci /* Default passphrase prompter */ 3801cb0ef41Sopenharmony_ci if (enc != NULL || outformat == FORMAT_PVK) { 3811cb0ef41Sopenharmony_ci OSSL_ENCODER_CTX_set_passphrase_ui(ectx, get_ui_method(), NULL); 3821cb0ef41Sopenharmony_ci if (passout != NULL) 3831cb0ef41Sopenharmony_ci /* When passout given, override the passphrase prompter */ 3841cb0ef41Sopenharmony_ci OSSL_ENCODER_CTX_set_passphrase(ectx, 3851cb0ef41Sopenharmony_ci (const unsigned char *)passout, 3861cb0ef41Sopenharmony_ci strlen(passout)); 3871cb0ef41Sopenharmony_ci } 3881cb0ef41Sopenharmony_ci 3891cb0ef41Sopenharmony_ci /* PVK is a bit special... */ 3901cb0ef41Sopenharmony_ci if (outformat == FORMAT_PVK) { 3911cb0ef41Sopenharmony_ci OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; 3921cb0ef41Sopenharmony_ci 3931cb0ef41Sopenharmony_ci params[0] = OSSL_PARAM_construct_int("encrypt-level", &pvk_encr); 3941cb0ef41Sopenharmony_ci if (!OSSL_ENCODER_CTX_set_params(ectx, params)) { 3951cb0ef41Sopenharmony_ci BIO_printf(bio_err, "invalid PVK encryption level\n"); 3961cb0ef41Sopenharmony_ci goto end; 3971cb0ef41Sopenharmony_ci } 3981cb0ef41Sopenharmony_ci } 3991cb0ef41Sopenharmony_ci 4001cb0ef41Sopenharmony_ci if (!OSSL_ENCODER_to_bio(ectx, out)) { 4011cb0ef41Sopenharmony_ci BIO_printf(bio_err, "unable to write key\n"); 4021cb0ef41Sopenharmony_ci ERR_print_errors(bio_err); 4031cb0ef41Sopenharmony_ci goto end; 4041cb0ef41Sopenharmony_ci } 4051cb0ef41Sopenharmony_ci ret = 0; 4061cb0ef41Sopenharmony_ci end: 4071cb0ef41Sopenharmony_ci OSSL_ENCODER_CTX_free(ectx); 4081cb0ef41Sopenharmony_ci release_engine(e); 4091cb0ef41Sopenharmony_ci BIO_free_all(out); 4101cb0ef41Sopenharmony_ci EVP_PKEY_free(pkey); 4111cb0ef41Sopenharmony_ci EVP_CIPHER_free(enc); 4121cb0ef41Sopenharmony_ci OPENSSL_free(passin); 4131cb0ef41Sopenharmony_ci OPENSSL_free(passout); 4141cb0ef41Sopenharmony_ci return ret; 4151cb0ef41Sopenharmony_ci} 416