1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <openssl/opensslconf.h> 11e1051a39Sopenharmony_ci 12e1051a39Sopenharmony_ci#include <stdio.h> 13e1051a39Sopenharmony_ci#include <string.h> 14e1051a39Sopenharmony_ci#include <sys/types.h> 15e1051a39Sopenharmony_ci#include <sys/stat.h> 16e1051a39Sopenharmony_ci#include "apps.h" 17e1051a39Sopenharmony_ci#include "progs.h" 18e1051a39Sopenharmony_ci#include <openssl/bio.h> 19e1051a39Sopenharmony_ci#include <openssl/err.h> 20e1051a39Sopenharmony_ci#include <openssl/bn.h> 21e1051a39Sopenharmony_ci#include <openssl/rsa.h> 22e1051a39Sopenharmony_ci#include <openssl/evp.h> 23e1051a39Sopenharmony_ci#include <openssl/x509.h> 24e1051a39Sopenharmony_ci#include <openssl/pem.h> 25e1051a39Sopenharmony_ci#include <openssl/rand.h> 26e1051a39Sopenharmony_ci 27e1051a39Sopenharmony_ci#define DEFBITS 2048 28e1051a39Sopenharmony_ci#define DEFPRIMES 2 29e1051a39Sopenharmony_ci 30e1051a39Sopenharmony_cistatic int verbose = 0; 31e1051a39Sopenharmony_ci 32e1051a39Sopenharmony_cistatic int genrsa_cb(EVP_PKEY_CTX *ctx); 33e1051a39Sopenharmony_ci 34e1051a39Sopenharmony_citypedef enum OPTION_choice { 35e1051a39Sopenharmony_ci OPT_COMMON, 36e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 37e1051a39Sopenharmony_ci OPT_3, 38e1051a39Sopenharmony_ci#endif 39e1051a39Sopenharmony_ci OPT_F4, OPT_ENGINE, 40e1051a39Sopenharmony_ci OPT_OUT, OPT_PASSOUT, OPT_CIPHER, OPT_PRIMES, OPT_VERBOSE, 41e1051a39Sopenharmony_ci OPT_R_ENUM, OPT_PROV_ENUM, OPT_TRADITIONAL 42e1051a39Sopenharmony_ci} OPTION_CHOICE; 43e1051a39Sopenharmony_ci 44e1051a39Sopenharmony_ciconst OPTIONS genrsa_options[] = { 45e1051a39Sopenharmony_ci {OPT_HELP_STR, 1, '-', "Usage: %s [options] numbits\n"}, 46e1051a39Sopenharmony_ci 47e1051a39Sopenharmony_ci OPT_SECTION("General"), 48e1051a39Sopenharmony_ci {"help", OPT_HELP, '-', "Display this summary"}, 49e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE 50e1051a39Sopenharmony_ci {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 51e1051a39Sopenharmony_ci#endif 52e1051a39Sopenharmony_ci 53e1051a39Sopenharmony_ci OPT_SECTION("Input"), 54e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 55e1051a39Sopenharmony_ci {"3", OPT_3, '-', "(deprecated) Use 3 for the E value"}, 56e1051a39Sopenharmony_ci#endif 57e1051a39Sopenharmony_ci {"F4", OPT_F4, '-', "Use the Fermat number F4 (0x10001) for the E value"}, 58e1051a39Sopenharmony_ci {"f4", OPT_F4, '-', "Use the Fermat number F4 (0x10001) for the E value"}, 59e1051a39Sopenharmony_ci 60e1051a39Sopenharmony_ci OPT_SECTION("Output"), 61e1051a39Sopenharmony_ci {"out", OPT_OUT, '>', "Output the key to specified file"}, 62e1051a39Sopenharmony_ci {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, 63e1051a39Sopenharmony_ci {"primes", OPT_PRIMES, 'p', "Specify number of primes"}, 64e1051a39Sopenharmony_ci {"verbose", OPT_VERBOSE, '-', "Verbose output"}, 65e1051a39Sopenharmony_ci {"traditional", OPT_TRADITIONAL, '-', 66e1051a39Sopenharmony_ci "Use traditional format for private keys"}, 67e1051a39Sopenharmony_ci {"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"}, 68e1051a39Sopenharmony_ci 69e1051a39Sopenharmony_ci OPT_R_OPTIONS, 70e1051a39Sopenharmony_ci OPT_PROV_OPTIONS, 71e1051a39Sopenharmony_ci 72e1051a39Sopenharmony_ci OPT_PARAMETERS(), 73e1051a39Sopenharmony_ci {"numbits", 0, 0, "Size of key in bits"}, 74e1051a39Sopenharmony_ci {NULL} 75e1051a39Sopenharmony_ci}; 76e1051a39Sopenharmony_ci 77e1051a39Sopenharmony_ciint genrsa_main(int argc, char **argv) 78e1051a39Sopenharmony_ci{ 79e1051a39Sopenharmony_ci BN_GENCB *cb = BN_GENCB_new(); 80e1051a39Sopenharmony_ci ENGINE *eng = NULL; 81e1051a39Sopenharmony_ci BIGNUM *bn = BN_new(); 82e1051a39Sopenharmony_ci BIO *out = NULL; 83e1051a39Sopenharmony_ci EVP_PKEY *pkey = NULL; 84e1051a39Sopenharmony_ci EVP_PKEY_CTX *ctx = NULL; 85e1051a39Sopenharmony_ci EVP_CIPHER *enc = NULL; 86e1051a39Sopenharmony_ci int ret = 1, num = DEFBITS, private = 0, primes = DEFPRIMES; 87e1051a39Sopenharmony_ci unsigned long f4 = RSA_F4; 88e1051a39Sopenharmony_ci char *outfile = NULL, *passoutarg = NULL, *passout = NULL; 89e1051a39Sopenharmony_ci char *prog, *hexe, *dece, *ciphername = NULL; 90e1051a39Sopenharmony_ci OPTION_CHOICE o; 91e1051a39Sopenharmony_ci int traditional = 0; 92e1051a39Sopenharmony_ci 93e1051a39Sopenharmony_ci if (bn == NULL || cb == NULL) 94e1051a39Sopenharmony_ci goto end; 95e1051a39Sopenharmony_ci 96e1051a39Sopenharmony_ci prog = opt_init(argc, argv, genrsa_options); 97e1051a39Sopenharmony_ci while ((o = opt_next()) != OPT_EOF) { 98e1051a39Sopenharmony_ci switch (o) { 99e1051a39Sopenharmony_ci case OPT_EOF: 100e1051a39Sopenharmony_ci case OPT_ERR: 101e1051a39Sopenharmony_ciopthelp: 102e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 103e1051a39Sopenharmony_ci goto end; 104e1051a39Sopenharmony_ci case OPT_HELP: 105e1051a39Sopenharmony_ci ret = 0; 106e1051a39Sopenharmony_ci opt_help(genrsa_options); 107e1051a39Sopenharmony_ci goto end; 108e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 109e1051a39Sopenharmony_ci case OPT_3: 110e1051a39Sopenharmony_ci f4 = RSA_3; 111e1051a39Sopenharmony_ci break; 112e1051a39Sopenharmony_ci#endif 113e1051a39Sopenharmony_ci case OPT_F4: 114e1051a39Sopenharmony_ci f4 = RSA_F4; 115e1051a39Sopenharmony_ci break; 116e1051a39Sopenharmony_ci case OPT_OUT: 117e1051a39Sopenharmony_ci outfile = opt_arg(); 118e1051a39Sopenharmony_ci break; 119e1051a39Sopenharmony_ci case OPT_ENGINE: 120e1051a39Sopenharmony_ci eng = setup_engine(opt_arg(), 0); 121e1051a39Sopenharmony_ci break; 122e1051a39Sopenharmony_ci case OPT_R_CASES: 123e1051a39Sopenharmony_ci if (!opt_rand(o)) 124e1051a39Sopenharmony_ci goto end; 125e1051a39Sopenharmony_ci break; 126e1051a39Sopenharmony_ci case OPT_PROV_CASES: 127e1051a39Sopenharmony_ci if (!opt_provider(o)) 128e1051a39Sopenharmony_ci goto end; 129e1051a39Sopenharmony_ci break; 130e1051a39Sopenharmony_ci case OPT_PASSOUT: 131e1051a39Sopenharmony_ci passoutarg = opt_arg(); 132e1051a39Sopenharmony_ci break; 133e1051a39Sopenharmony_ci case OPT_CIPHER: 134e1051a39Sopenharmony_ci ciphername = opt_unknown(); 135e1051a39Sopenharmony_ci break; 136e1051a39Sopenharmony_ci case OPT_PRIMES: 137e1051a39Sopenharmony_ci primes = opt_int_arg(); 138e1051a39Sopenharmony_ci break; 139e1051a39Sopenharmony_ci case OPT_VERBOSE: 140e1051a39Sopenharmony_ci verbose = 1; 141e1051a39Sopenharmony_ci break; 142e1051a39Sopenharmony_ci case OPT_TRADITIONAL: 143e1051a39Sopenharmony_ci traditional = 1; 144e1051a39Sopenharmony_ci break; 145e1051a39Sopenharmony_ci } 146e1051a39Sopenharmony_ci } 147e1051a39Sopenharmony_ci 148e1051a39Sopenharmony_ci /* One optional argument, the bitsize. */ 149e1051a39Sopenharmony_ci argc = opt_num_rest(); 150e1051a39Sopenharmony_ci argv = opt_rest(); 151e1051a39Sopenharmony_ci 152e1051a39Sopenharmony_ci if (argc == 1) { 153e1051a39Sopenharmony_ci if (!opt_int(argv[0], &num) || num <= 0) 154e1051a39Sopenharmony_ci goto end; 155e1051a39Sopenharmony_ci if (num > OPENSSL_RSA_MAX_MODULUS_BITS) 156e1051a39Sopenharmony_ci BIO_printf(bio_err, 157e1051a39Sopenharmony_ci "Warning: It is not recommended to use more than %d bit for RSA keys.\n" 158e1051a39Sopenharmony_ci " Your key size is %d! Larger key size may behave not as expected.\n", 159e1051a39Sopenharmony_ci OPENSSL_RSA_MAX_MODULUS_BITS, num); 160e1051a39Sopenharmony_ci } else if (argc > 0) { 161e1051a39Sopenharmony_ci BIO_printf(bio_err, "Extra arguments given.\n"); 162e1051a39Sopenharmony_ci goto opthelp; 163e1051a39Sopenharmony_ci } 164e1051a39Sopenharmony_ci 165e1051a39Sopenharmony_ci if (!app_RAND_load()) 166e1051a39Sopenharmony_ci goto end; 167e1051a39Sopenharmony_ci 168e1051a39Sopenharmony_ci private = 1; 169e1051a39Sopenharmony_ci if (ciphername != NULL) { 170e1051a39Sopenharmony_ci if (!opt_cipher(ciphername, &enc)) 171e1051a39Sopenharmony_ci goto end; 172e1051a39Sopenharmony_ci } 173e1051a39Sopenharmony_ci if (!app_passwd(NULL, passoutarg, NULL, &passout)) { 174e1051a39Sopenharmony_ci BIO_printf(bio_err, "Error getting password\n"); 175e1051a39Sopenharmony_ci goto end; 176e1051a39Sopenharmony_ci } 177e1051a39Sopenharmony_ci 178e1051a39Sopenharmony_ci out = bio_open_owner(outfile, FORMAT_PEM, private); 179e1051a39Sopenharmony_ci if (out == NULL) 180e1051a39Sopenharmony_ci goto end; 181e1051a39Sopenharmony_ci 182e1051a39Sopenharmony_ci if (!init_gen_str(&ctx, "RSA", eng, 0, app_get0_libctx(), 183e1051a39Sopenharmony_ci app_get0_propq())) 184e1051a39Sopenharmony_ci goto end; 185e1051a39Sopenharmony_ci 186e1051a39Sopenharmony_ci EVP_PKEY_CTX_set_cb(ctx, genrsa_cb); 187e1051a39Sopenharmony_ci EVP_PKEY_CTX_set_app_data(ctx, bio_err); 188e1051a39Sopenharmony_ci 189e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, num) <= 0) { 190e1051a39Sopenharmony_ci BIO_printf(bio_err, "Error setting RSA length\n"); 191e1051a39Sopenharmony_ci goto end; 192e1051a39Sopenharmony_ci } 193e1051a39Sopenharmony_ci if (!BN_set_word(bn, f4)) { 194e1051a39Sopenharmony_ci BIO_printf(bio_err, "Error allocating RSA public exponent\n"); 195e1051a39Sopenharmony_ci goto end; 196e1051a39Sopenharmony_ci } 197e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, bn) <= 0) { 198e1051a39Sopenharmony_ci BIO_printf(bio_err, "Error setting RSA public exponent\n"); 199e1051a39Sopenharmony_ci goto end; 200e1051a39Sopenharmony_ci } 201e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, primes) <= 0) { 202e1051a39Sopenharmony_ci BIO_printf(bio_err, "Error setting number of primes\n"); 203e1051a39Sopenharmony_ci goto end; 204e1051a39Sopenharmony_ci } 205e1051a39Sopenharmony_ci pkey = app_keygen(ctx, "RSA", num, verbose); 206e1051a39Sopenharmony_ci if (pkey == NULL) 207e1051a39Sopenharmony_ci goto end; 208e1051a39Sopenharmony_ci 209e1051a39Sopenharmony_ci if (verbose) { 210e1051a39Sopenharmony_ci BIGNUM *e = NULL; 211e1051a39Sopenharmony_ci 212e1051a39Sopenharmony_ci /* Every RSA key has an 'e' */ 213e1051a39Sopenharmony_ci EVP_PKEY_get_bn_param(pkey, "e", &e); 214e1051a39Sopenharmony_ci if (e == NULL) { 215e1051a39Sopenharmony_ci BIO_printf(bio_err, "Error cannot access RSA e\n"); 216e1051a39Sopenharmony_ci goto end; 217e1051a39Sopenharmony_ci } 218e1051a39Sopenharmony_ci hexe = BN_bn2hex(e); 219e1051a39Sopenharmony_ci dece = BN_bn2dec(e); 220e1051a39Sopenharmony_ci if (hexe && dece) { 221e1051a39Sopenharmony_ci BIO_printf(bio_err, "e is %s (0x%s)\n", dece, hexe); 222e1051a39Sopenharmony_ci } 223e1051a39Sopenharmony_ci OPENSSL_free(hexe); 224e1051a39Sopenharmony_ci OPENSSL_free(dece); 225e1051a39Sopenharmony_ci BN_free(e); 226e1051a39Sopenharmony_ci } 227e1051a39Sopenharmony_ci if (traditional) { 228e1051a39Sopenharmony_ci if (!PEM_write_bio_PrivateKey_traditional(out, pkey, enc, NULL, 0, 229e1051a39Sopenharmony_ci NULL, passout)) 230e1051a39Sopenharmony_ci goto end; 231e1051a39Sopenharmony_ci } else { 232e1051a39Sopenharmony_ci if (!PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, passout)) 233e1051a39Sopenharmony_ci goto end; 234e1051a39Sopenharmony_ci } 235e1051a39Sopenharmony_ci 236e1051a39Sopenharmony_ci ret = 0; 237e1051a39Sopenharmony_ci end: 238e1051a39Sopenharmony_ci BN_free(bn); 239e1051a39Sopenharmony_ci BN_GENCB_free(cb); 240e1051a39Sopenharmony_ci EVP_PKEY_CTX_free(ctx); 241e1051a39Sopenharmony_ci EVP_PKEY_free(pkey); 242e1051a39Sopenharmony_ci EVP_CIPHER_free(enc); 243e1051a39Sopenharmony_ci BIO_free_all(out); 244e1051a39Sopenharmony_ci release_engine(eng); 245e1051a39Sopenharmony_ci OPENSSL_free(passout); 246e1051a39Sopenharmony_ci if (ret != 0) 247e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 248e1051a39Sopenharmony_ci return ret; 249e1051a39Sopenharmony_ci} 250e1051a39Sopenharmony_ci 251e1051a39Sopenharmony_cistatic int genrsa_cb(EVP_PKEY_CTX *ctx) 252e1051a39Sopenharmony_ci{ 253e1051a39Sopenharmony_ci char c = '*'; 254e1051a39Sopenharmony_ci BIO *b = EVP_PKEY_CTX_get_app_data(ctx); 255e1051a39Sopenharmony_ci int p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); 256e1051a39Sopenharmony_ci 257e1051a39Sopenharmony_ci if (!verbose) 258e1051a39Sopenharmony_ci return 1; 259e1051a39Sopenharmony_ci 260e1051a39Sopenharmony_ci if (p == 0) 261e1051a39Sopenharmony_ci c = '.'; 262e1051a39Sopenharmony_ci if (p == 1) 263e1051a39Sopenharmony_ci c = '+'; 264e1051a39Sopenharmony_ci if (p == 2) 265e1051a39Sopenharmony_ci c = '*'; 266e1051a39Sopenharmony_ci if (p == 3) 267e1051a39Sopenharmony_ci c = '\n'; 268e1051a39Sopenharmony_ci BIO_write(b, &c, 1); 269e1051a39Sopenharmony_ci (void)BIO_flush(b); 270e1051a39Sopenharmony_ci return 1; 271e1051a39Sopenharmony_ci} 272