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