Home | History | Annotate | Line # | Download | only in apps
      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