1 /* 2 * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (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 12 #include <stdio.h> 13 #include <string.h> 14 #include <sys/types.h> 15 #include <sys/stat.h> 16 #include "apps.h" 17 #include "progs.h" 18 #include <openssl/bio.h> 19 #include <openssl/err.h> 20 #include <openssl/bn.h> 21 #include <openssl/dsa.h> 22 #include <openssl/x509.h> 23 #include <openssl/pem.h> 24 25 typedef enum OPTION_choice { 26 OPT_COMMON, 27 OPT_OUT, 28 OPT_PASSOUT, 29 OPT_ENGINE, 30 OPT_CIPHER, 31 OPT_VERBOSE, 32 OPT_QUIET, 33 OPT_R_ENUM, 34 OPT_PROV_ENUM 35 } OPTION_CHOICE; 36 37 const OPTIONS gendsa_options[] = { 38 { OPT_HELP_STR, 1, '-', "Usage: %s [options] dsaparam-file\n" }, 39 40 OPT_SECTION("General"), 41 { "help", OPT_HELP, '-', "Display this summary" }, 42 #ifndef OPENSSL_NO_ENGINE 43 { "engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device" }, 44 #endif 45 46 OPT_SECTION("Output"), 47 { "out", OPT_OUT, '>', "Output the key to the specified file" }, 48 { "passout", OPT_PASSOUT, 's', "Output file pass phrase source" }, 49 OPT_R_OPTIONS, 50 OPT_PROV_OPTIONS, 51 { "", OPT_CIPHER, '-', "Encrypt the output with any supported cipher" }, 52 { "verbose", OPT_VERBOSE, '-', "Verbose output" }, 53 { "quiet", OPT_QUIET, '-', "Terse output" }, 54 55 OPT_PARAMETERS(), 56 { "dsaparam-file", 0, 0, "File containing DSA parameters" }, 57 { NULL } 58 }; 59 60 int gendsa_main(int argc, char **argv) 61 { 62 ENGINE *e = NULL; 63 BIO *out = NULL, *in = NULL; 64 EVP_PKEY *pkey = NULL; 65 EVP_PKEY_CTX *ctx = NULL; 66 EVP_CIPHER *enc = NULL; 67 char *dsaparams = NULL, *ciphername = NULL; 68 char *outfile = NULL, *passoutarg = NULL, *passout = NULL, *prog; 69 OPTION_CHOICE o; 70 int ret = 1, private = 0, verbose = 0, nbits; 71 72 opt_set_unknown_name("cipher"); 73 prog = opt_init(argc, argv, gendsa_options); 74 while ((o = opt_next()) != OPT_EOF) { 75 switch (o) { 76 case OPT_EOF: 77 case OPT_ERR: 78 opthelp: 79 BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 80 goto end; 81 case OPT_HELP: 82 ret = 0; 83 opt_help(gendsa_options); 84 goto end; 85 case OPT_OUT: 86 outfile = opt_arg(); 87 break; 88 case OPT_PASSOUT: 89 passoutarg = opt_arg(); 90 break; 91 case OPT_ENGINE: 92 e = setup_engine(opt_arg(), 0); 93 break; 94 case OPT_R_CASES: 95 if (!opt_rand(o)) 96 goto end; 97 break; 98 case OPT_PROV_CASES: 99 if (!opt_provider(o)) 100 goto end; 101 break; 102 case OPT_CIPHER: 103 ciphername = opt_unknown(); 104 break; 105 case OPT_VERBOSE: 106 verbose = 1; 107 break; 108 case OPT_QUIET: 109 verbose = 0; 110 break; 111 } 112 } 113 114 /* One argument, the params file. */ 115 if (!opt_check_rest_arg("params file")) 116 goto opthelp; 117 argv = opt_rest(); 118 dsaparams = argv[0]; 119 120 if (!app_RAND_load()) 121 goto end; 122 123 if (!opt_cipher(ciphername, &enc)) 124 goto end; 125 private = 1; 126 127 if (!app_passwd(NULL, passoutarg, NULL, &passout)) { 128 BIO_printf(bio_err, "Error getting password\n"); 129 goto end; 130 } 131 132 pkey = load_keyparams(dsaparams, FORMAT_UNDEF, 1, "DSA", "DSA parameters"); 133 134 out = bio_open_owner(outfile, FORMAT_PEM, private); 135 if (out == NULL) 136 goto end2; 137 138 nbits = EVP_PKEY_get_bits(pkey); 139 if (nbits > OPENSSL_DSA_MAX_MODULUS_BITS) 140 BIO_printf(bio_err, 141 "Warning: It is not recommended to use more than %d bit for DSA keys.\n" 142 " Your key size is %d! Larger key size may behave not as expected.\n", 143 OPENSSL_DSA_MAX_MODULUS_BITS, EVP_PKEY_get_bits(pkey)); 144 145 ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), pkey, app_get0_propq()); 146 if (ctx == NULL) { 147 BIO_printf(bio_err, "unable to create PKEY context\n"); 148 goto end; 149 } 150 EVP_PKEY_free(pkey); 151 pkey = NULL; 152 if (EVP_PKEY_keygen_init(ctx) <= 0) { 153 BIO_printf(bio_err, "unable to set up for key generation\n"); 154 goto end; 155 } 156 pkey = app_keygen(ctx, "DSA", nbits, verbose); 157 if (pkey == NULL) 158 goto end; 159 160 assert(private); 161 if (!PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, passout)) { 162 BIO_printf(bio_err, "unable to output generated key\n"); 163 goto end; 164 } 165 ret = 0; 166 end: 167 if (ret != 0) 168 ERR_print_errors(bio_err); 169 end2: 170 BIO_free(in); 171 BIO_free_all(out); 172 EVP_PKEY_free(pkey); 173 EVP_PKEY_CTX_free(ctx); 174 EVP_CIPHER_free(enc); 175 release_engine(e); 176 OPENSSL_free(passout); 177 return ret; 178 } 179