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