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 <string.h> 13 #include <sys/types.h> 14 #include <sys/stat.h> 15 #include "apps.h" 16 #include "progs.h" 17 #include <openssl/bio.h> 18 #include <openssl/err.h> 19 #include <openssl/bn.h> 20 #include <openssl/rsa.h> 21 #include <openssl/evp.h> 22 #include <openssl/x509.h> 23 #include <openssl/pem.h> 24 #include <openssl/rand.h> 25 26 #define DEFBITS 2048 27 #define DEFPRIMES 2 28 29 static int genrsa_cb(int p, int n, BN_GENCB *cb); 30 31 typedef enum OPTION_choice { 32 OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, 33 OPT_3, OPT_F4, OPT_ENGINE, 34 OPT_OUT, OPT_PASSOUT, OPT_CIPHER, OPT_PRIMES, 35 OPT_R_ENUM 36 } OPTION_CHOICE; 37 38 const OPTIONS genrsa_options[] = { 39 {"help", OPT_HELP, '-', "Display this summary"}, 40 {"3", OPT_3, '-', "Use 3 for the E value"}, 41 {"F4", OPT_F4, '-', "Use F4 (0x10001) for the E value"}, 42 {"f4", OPT_F4, '-', "Use F4 (0x10001) for the E value"}, 43 {"out", OPT_OUT, '>', "Output the key to specified file"}, 44 OPT_R_OPTIONS, 45 {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, 46 {"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"}, 47 #ifndef OPENSSL_NO_ENGINE 48 {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 49 #endif 50 {"primes", OPT_PRIMES, 'p', "Specify number of primes"}, 51 {NULL} 52 }; 53 54 int genrsa_main(int argc, char **argv) 55 { 56 BN_GENCB *cb = BN_GENCB_new(); 57 PW_CB_DATA cb_data; 58 ENGINE *eng = NULL; 59 BIGNUM *bn = BN_new(); 60 BIO *out = NULL; 61 const BIGNUM *e; 62 RSA *rsa = NULL; 63 const EVP_CIPHER *enc = NULL; 64 int ret = 1, num = DEFBITS, private = 0, primes = DEFPRIMES; 65 unsigned long f4 = RSA_F4; 66 char *outfile = NULL, *passoutarg = NULL, *passout = NULL; 67 char *prog, *hexe, *dece; 68 OPTION_CHOICE o; 69 70 if (bn == NULL || cb == NULL) 71 goto end; 72 73 BN_GENCB_set(cb, genrsa_cb, bio_err); 74 75 prog = opt_init(argc, argv, genrsa_options); 76 while ((o = opt_next()) != OPT_EOF) { 77 switch (o) { 78 case OPT_EOF: 79 case OPT_ERR: 80 opthelp: 81 BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 82 goto end; 83 case OPT_HELP: 84 ret = 0; 85 opt_help(genrsa_options); 86 goto end; 87 case OPT_3: 88 f4 = 3; 89 break; 90 case OPT_F4: 91 f4 = RSA_F4; 92 break; 93 case OPT_OUT: 94 outfile = opt_arg(); 95 break; 96 case OPT_ENGINE: 97 eng = setup_engine(opt_arg(), 0); 98 break; 99 case OPT_R_CASES: 100 if (!opt_rand(o)) 101 goto end; 102 break; 103 case OPT_PASSOUT: 104 passoutarg = opt_arg(); 105 break; 106 case OPT_CIPHER: 107 if (!opt_cipher(opt_unknown(), &enc)) 108 goto end; 109 break; 110 case OPT_PRIMES: 111 if (!opt_int(opt_arg(), &primes)) 112 goto end; 113 break; 114 } 115 } 116 argc = opt_num_rest(); 117 argv = opt_rest(); 118 119 if (argc == 1) { 120 if (!opt_int(argv[0], &num) || num <= 0) 121 goto end; 122 if (num > OPENSSL_RSA_MAX_MODULUS_BITS) 123 BIO_printf(bio_err, 124 "Warning: It is not recommended to use more than %d bit for RSA keys.\n" 125 " Your key size is %d! Larger key size may behave not as expected.\n", 126 OPENSSL_RSA_MAX_MODULUS_BITS, num); 127 } else if (argc > 0) { 128 BIO_printf(bio_err, "Extra arguments given.\n"); 129 goto opthelp; 130 } 131 132 private = 1; 133 if (!app_passwd(NULL, passoutarg, NULL, &passout)) { 134 BIO_printf(bio_err, "Error getting password\n"); 135 goto end; 136 } 137 138 out = bio_open_owner(outfile, FORMAT_PEM, private); 139 if (out == NULL) 140 goto end; 141 142 BIO_printf(bio_err, "Generating RSA private key, %d bit long modulus (%d primes)\n", 143 num, primes); 144 rsa = eng ? RSA_new_method(eng) : RSA_new(); 145 if (rsa == NULL) 146 goto end; 147 148 if (!BN_set_word(bn, f4) 149 || !RSA_generate_multi_prime_key(rsa, num, primes, bn, cb)) 150 goto end; 151 152 RSA_get0_key(rsa, NULL, &e, NULL); 153 hexe = BN_bn2hex(e); 154 dece = BN_bn2dec(e); 155 if (hexe && dece) { 156 BIO_printf(bio_err, "e is %s (0x%s)\n", dece, hexe); 157 } 158 OPENSSL_free(hexe); 159 OPENSSL_free(dece); 160 cb_data.password = passout; 161 cb_data.prompt_info = outfile; 162 assert(private); 163 if (!PEM_write_bio_RSAPrivateKey(out, rsa, enc, NULL, 0, 164 (pem_password_cb *)password_callback, 165 &cb_data)) 166 goto end; 167 168 ret = 0; 169 end: 170 BN_free(bn); 171 BN_GENCB_free(cb); 172 RSA_free(rsa); 173 BIO_free_all(out); 174 release_engine(eng); 175 OPENSSL_free(passout); 176 if (ret != 0) 177 ERR_print_errors(bio_err); 178 return ret; 179 } 180 181 static int genrsa_cb(int p, int n, BN_GENCB *cb) 182 { 183 char c = '*'; 184 185 if (p == 0) 186 c = '.'; 187 if (p == 1) 188 c = '+'; 189 if (p == 2) 190 c = '*'; 191 if (p == 3) 192 c = '\n'; 193 BIO_write(BN_GENCB_get_arg(cb), &c, 1); 194 (void)BIO_flush(BN_GENCB_get_arg(cb)); 195 return 1; 196 } 197