1 /* 2 * Copyright 1995-2020 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 <openssl/opensslconf.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <time.h> 15 #include "apps.h" 16 #include "progs.h" 17 #include <openssl/bio.h> 18 #include <openssl/err.h> 19 #include <openssl/rsa.h> 20 #include <openssl/evp.h> 21 #include <openssl/x509.h> 22 #include <openssl/pem.h> 23 #include <openssl/bn.h> 24 25 typedef enum OPTION_choice { 26 OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, 27 OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT, 28 OPT_PUBIN, OPT_PUBOUT, OPT_PASSOUT, OPT_PASSIN, 29 OPT_RSAPUBKEY_IN, OPT_RSAPUBKEY_OUT, 30 /* Do not change the order here; see case statements below */ 31 OPT_PVK_NONE, OPT_PVK_WEAK, OPT_PVK_STRONG, 32 OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_CHECK, OPT_CIPHER 33 } OPTION_CHOICE; 34 35 const OPTIONS rsa_options[] = { 36 {"help", OPT_HELP, '-', "Display this summary"}, 37 {"inform", OPT_INFORM, 'f', "Input format, one of DER PEM"}, 38 {"outform", OPT_OUTFORM, 'f', "Output format, one of DER PEM PVK"}, 39 {"in", OPT_IN, 's', "Input file"}, 40 {"out", OPT_OUT, '>', "Output file"}, 41 {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"}, 42 {"pubout", OPT_PUBOUT, '-', "Output a public key"}, 43 {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, 44 {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, 45 {"RSAPublicKey_in", OPT_RSAPUBKEY_IN, '-', "Input is an RSAPublicKey"}, 46 {"RSAPublicKey_out", OPT_RSAPUBKEY_OUT, '-', "Output is an RSAPublicKey"}, 47 {"noout", OPT_NOOUT, '-', "Don't print key out"}, 48 {"text", OPT_TEXT, '-', "Print the key in text"}, 49 {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"}, 50 {"check", OPT_CHECK, '-', "Verify key consistency"}, 51 {"", OPT_CIPHER, '-', "Any supported cipher"}, 52 #if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) 53 {"pvk-strong", OPT_PVK_STRONG, '-', "Enable 'Strong' PVK encoding level (default)"}, 54 {"pvk-weak", OPT_PVK_WEAK, '-', "Enable 'Weak' PVK encoding level"}, 55 {"pvk-none", OPT_PVK_NONE, '-', "Don't enforce PVK encoding"}, 56 #endif 57 #ifndef OPENSSL_NO_ENGINE 58 {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 59 #endif 60 {NULL} 61 }; 62 63 int rsa_main(int argc, char **argv) 64 { 65 ENGINE *e = NULL; 66 BIO *out = NULL; 67 RSA *rsa = NULL; 68 const EVP_CIPHER *enc = NULL; 69 char *infile = NULL, *outfile = NULL, *prog; 70 char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL; 71 int i, private = 0; 72 int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, check = 0; 73 int noout = 0, modulus = 0, pubin = 0, pubout = 0, ret = 1; 74 #if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) 75 int pvk_encr = 2; 76 #endif 77 OPTION_CHOICE o; 78 79 prog = opt_init(argc, argv, rsa_options); 80 while ((o = opt_next()) != OPT_EOF) { 81 switch (o) { 82 case OPT_EOF: 83 case OPT_ERR: 84 opthelp: 85 BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 86 goto end; 87 case OPT_HELP: 88 opt_help(rsa_options); 89 ret = 0; 90 goto end; 91 case OPT_INFORM: 92 if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat)) 93 goto opthelp; 94 break; 95 case OPT_IN: 96 infile = opt_arg(); 97 break; 98 case OPT_OUTFORM: 99 if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat)) 100 goto opthelp; 101 break; 102 case OPT_OUT: 103 outfile = opt_arg(); 104 break; 105 case OPT_PASSIN: 106 passinarg = opt_arg(); 107 break; 108 case OPT_PASSOUT: 109 passoutarg = opt_arg(); 110 break; 111 case OPT_ENGINE: 112 e = setup_engine(opt_arg(), 0); 113 break; 114 case OPT_PUBIN: 115 pubin = 1; 116 break; 117 case OPT_PUBOUT: 118 pubout = 1; 119 break; 120 case OPT_RSAPUBKEY_IN: 121 pubin = 2; 122 break; 123 case OPT_RSAPUBKEY_OUT: 124 pubout = 2; 125 break; 126 case OPT_PVK_STRONG: /* pvk_encr:= 2 */ 127 case OPT_PVK_WEAK: /* pvk_encr:= 1 */ 128 case OPT_PVK_NONE: /* pvk_encr:= 0 */ 129 #if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) 130 pvk_encr = (o - OPT_PVK_NONE); 131 #endif 132 break; 133 case OPT_NOOUT: 134 noout = 1; 135 break; 136 case OPT_TEXT: 137 text = 1; 138 break; 139 case OPT_MODULUS: 140 modulus = 1; 141 break; 142 case OPT_CHECK: 143 check = 1; 144 break; 145 case OPT_CIPHER: 146 if (!opt_cipher(opt_unknown(), &enc)) 147 goto opthelp; 148 break; 149 } 150 } 151 argc = opt_num_rest(); 152 if (argc != 0) 153 goto opthelp; 154 155 private = (text && !pubin) || (!pubout && !noout) ? 1 : 0; 156 157 if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { 158 BIO_printf(bio_err, "Error getting passwords\n"); 159 goto end; 160 } 161 if (check && pubin) { 162 BIO_printf(bio_err, "Only private keys can be checked\n"); 163 goto end; 164 } 165 166 { 167 EVP_PKEY *pkey; 168 169 if (pubin) { 170 int tmpformat = -1; 171 if (pubin == 2) { 172 if (informat == FORMAT_PEM) 173 tmpformat = FORMAT_PEMRSA; 174 else if (informat == FORMAT_ASN1) 175 tmpformat = FORMAT_ASN1RSA; 176 } else { 177 tmpformat = informat; 178 } 179 180 pkey = load_pubkey(infile, tmpformat, 1, passin, e, "Public Key"); 181 } else { 182 pkey = load_key(infile, informat, 1, passin, e, "Private Key"); 183 } 184 185 if (pkey != NULL) 186 rsa = EVP_PKEY_get1_RSA(pkey); 187 EVP_PKEY_free(pkey); 188 } 189 190 if (rsa == NULL) { 191 ERR_print_errors(bio_err); 192 goto end; 193 } 194 195 out = bio_open_owner(outfile, outformat, private); 196 if (out == NULL) 197 goto end; 198 199 if (text) { 200 assert(pubin || private); 201 if (!RSA_print(out, rsa, 0)) { 202 perror(outfile); 203 ERR_print_errors(bio_err); 204 goto end; 205 } 206 } 207 208 if (modulus) { 209 const BIGNUM *n; 210 RSA_get0_key(rsa, &n, NULL, NULL); 211 BIO_printf(out, "Modulus="); 212 BN_print(out, n); 213 BIO_printf(out, "\n"); 214 } 215 216 if (check) { 217 int r = RSA_check_key_ex(rsa, NULL); 218 219 if (r == 1) { 220 BIO_printf(out, "RSA key ok\n"); 221 } else if (r == 0) { 222 unsigned long err; 223 224 while ((err = ERR_peek_error()) != 0 && 225 ERR_GET_LIB(err) == ERR_LIB_RSA && 226 ERR_GET_FUNC(err) == RSA_F_RSA_CHECK_KEY_EX && 227 ERR_GET_REASON(err) != ERR_R_MALLOC_FAILURE) { 228 BIO_printf(out, "RSA key error: %s\n", 229 ERR_reason_error_string(err)); 230 ERR_get_error(); /* remove err from error stack */ 231 } 232 } else if (r == -1) { 233 ERR_print_errors(bio_err); 234 goto end; 235 } 236 } 237 238 if (noout) { 239 ret = 0; 240 goto end; 241 } 242 BIO_printf(bio_err, "writing RSA key\n"); 243 if (outformat == FORMAT_ASN1) { 244 if (pubout || pubin) { 245 if (pubout == 2) 246 i = i2d_RSAPublicKey_bio(out, rsa); 247 else 248 i = i2d_RSA_PUBKEY_bio(out, rsa); 249 } else { 250 assert(private); 251 i = i2d_RSAPrivateKey_bio(out, rsa); 252 } 253 } else if (outformat == FORMAT_PEM) { 254 if (pubout || pubin) { 255 if (pubout == 2) 256 i = PEM_write_bio_RSAPublicKey(out, rsa); 257 else 258 i = PEM_write_bio_RSA_PUBKEY(out, rsa); 259 } else { 260 assert(private); 261 i = PEM_write_bio_RSAPrivateKey(out, rsa, 262 enc, NULL, 0, NULL, passout); 263 } 264 #ifndef OPENSSL_NO_DSA 265 } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) { 266 EVP_PKEY *pk; 267 pk = EVP_PKEY_new(); 268 if (pk == NULL) 269 goto end; 270 271 EVP_PKEY_set1_RSA(pk, rsa); 272 if (outformat == FORMAT_PVK) { 273 if (pubin) { 274 BIO_printf(bio_err, "PVK form impossible with public key input\n"); 275 EVP_PKEY_free(pk); 276 goto end; 277 } 278 assert(private); 279 # ifdef OPENSSL_NO_RC4 280 BIO_printf(bio_err, "PVK format not supported\n"); 281 EVP_PKEY_free(pk); 282 goto end; 283 # else 284 i = i2b_PVK_bio(out, pk, pvk_encr, 0, passout); 285 # endif 286 } else if (pubin || pubout) { 287 i = i2b_PublicKey_bio(out, pk); 288 } else { 289 assert(private); 290 i = i2b_PrivateKey_bio(out, pk); 291 } 292 EVP_PKEY_free(pk); 293 #endif 294 } else { 295 BIO_printf(bio_err, "bad output format specified for outfile\n"); 296 goto end; 297 } 298 if (i <= 0) { 299 BIO_printf(bio_err, "unable to write key\n"); 300 ERR_print_errors(bio_err); 301 } else { 302 ret = 0; 303 } 304 end: 305 release_engine(e); 306 BIO_free_all(out); 307 RSA_free(rsa); 308 OPENSSL_free(passin); 309 OPENSSL_free(passout); 310 return ret; 311 } 312