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 <stdlib.h> 13 #include <time.h> 14 #include <string.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/dsa.h> 21 #include <openssl/x509.h> 22 #include <openssl/pem.h> 23 24 static int dsa_cb(int p, int n, BN_GENCB *cb); 25 26 typedef enum OPTION_choice { 27 OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, 28 OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, OPT_C, 29 OPT_NOOUT, OPT_GENKEY, OPT_ENGINE, OPT_R_ENUM 30 } OPTION_CHOICE; 31 32 const OPTIONS dsaparam_options[] = { 33 {"help", OPT_HELP, '-', "Display this summary"}, 34 {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"}, 35 {"in", OPT_IN, '<', "Input file"}, 36 {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, 37 {"out", OPT_OUT, '>', "Output file"}, 38 {"text", OPT_TEXT, '-', "Print as text"}, 39 {"C", OPT_C, '-', "Output C code"}, 40 {"noout", OPT_NOOUT, '-', "No output"}, 41 {"genkey", OPT_GENKEY, '-', "Generate a DSA key"}, 42 OPT_R_OPTIONS, 43 #ifndef OPENSSL_NO_ENGINE 44 {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, 45 #endif 46 {NULL} 47 }; 48 49 int dsaparam_main(int argc, char **argv) 50 { 51 ENGINE *e = NULL; 52 DSA *dsa = NULL; 53 BIO *in = NULL, *out = NULL; 54 BN_GENCB *cb = NULL; 55 int numbits = -1, num = 0, genkey = 0; 56 int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0; 57 int ret = 1, i, text = 0, private = 0; 58 char *infile = NULL, *outfile = NULL, *prog; 59 OPTION_CHOICE o; 60 61 prog = opt_init(argc, argv, dsaparam_options); 62 while ((o = opt_next()) != OPT_EOF) { 63 switch (o) { 64 case OPT_EOF: 65 case OPT_ERR: 66 opthelp: 67 BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 68 goto end; 69 case OPT_HELP: 70 opt_help(dsaparam_options); 71 ret = 0; 72 goto end; 73 case OPT_INFORM: 74 if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) 75 goto opthelp; 76 break; 77 case OPT_IN: 78 infile = opt_arg(); 79 break; 80 case OPT_OUTFORM: 81 if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) 82 goto opthelp; 83 break; 84 case OPT_OUT: 85 outfile = opt_arg(); 86 break; 87 case OPT_ENGINE: 88 e = setup_engine(opt_arg(), 0); 89 break; 90 case OPT_TEXT: 91 text = 1; 92 break; 93 case OPT_C: 94 C = 1; 95 break; 96 case OPT_GENKEY: 97 genkey = 1; 98 break; 99 case OPT_R_CASES: 100 if (!opt_rand(o)) 101 goto end; 102 break; 103 case OPT_NOOUT: 104 noout = 1; 105 break; 106 } 107 } 108 argc = opt_num_rest(); 109 argv = opt_rest(); 110 111 if (argc == 1) { 112 if (!opt_int(argv[0], &num) || num < 0) 113 goto end; 114 /* generate a key */ 115 numbits = num; 116 } 117 private = genkey ? 1 : 0; 118 119 in = bio_open_default(infile, 'r', informat); 120 if (in == NULL) 121 goto end; 122 out = bio_open_owner(outfile, outformat, private); 123 if (out == NULL) 124 goto end; 125 126 if (numbits > 0) { 127 if (numbits > OPENSSL_DSA_MAX_MODULUS_BITS) 128 BIO_printf(bio_err, 129 "Warning: It is not recommended to use more than %d bit for DSA keys.\n" 130 " Your key size is %d! Larger key size may behave not as expected.\n", 131 OPENSSL_DSA_MAX_MODULUS_BITS, numbits); 132 133 cb = BN_GENCB_new(); 134 if (cb == NULL) { 135 BIO_printf(bio_err, "Error allocating BN_GENCB object\n"); 136 goto end; 137 } 138 BN_GENCB_set(cb, dsa_cb, bio_err); 139 dsa = DSA_new(); 140 if (dsa == NULL) { 141 BIO_printf(bio_err, "Error allocating DSA object\n"); 142 goto end; 143 } 144 BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n", 145 num); 146 BIO_printf(bio_err, "This could take some time\n"); 147 if (!DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL, cb)) { 148 ERR_print_errors(bio_err); 149 BIO_printf(bio_err, "Error, DSA key generation failed\n"); 150 goto end; 151 } 152 } else if (informat == FORMAT_ASN1) { 153 dsa = d2i_DSAparams_bio(in, NULL); 154 } else { 155 dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL); 156 } 157 if (dsa == NULL) { 158 BIO_printf(bio_err, "unable to load DSA parameters\n"); 159 ERR_print_errors(bio_err); 160 goto end; 161 } 162 163 if (text) { 164 DSAparams_print(out, dsa); 165 } 166 167 if (C) { 168 const BIGNUM *p = NULL, *q = NULL, *g = NULL; 169 unsigned char *data; 170 int len, bits_p; 171 172 DSA_get0_pqg(dsa, &p, &q, &g); 173 len = BN_num_bytes(p); 174 bits_p = BN_num_bits(p); 175 176 data = app_malloc(len + 20, "BN space"); 177 178 BIO_printf(bio_out, "static DSA *get_dsa%d(void)\n{\n", bits_p); 179 print_bignum_var(bio_out, p, "dsap", bits_p, data); 180 print_bignum_var(bio_out, q, "dsaq", bits_p, data); 181 print_bignum_var(bio_out, g, "dsag", bits_p, data); 182 BIO_printf(bio_out, " DSA *dsa = DSA_new();\n" 183 " BIGNUM *p, *q, *g;\n" 184 "\n"); 185 BIO_printf(bio_out, " if (dsa == NULL)\n" 186 " return NULL;\n"); 187 BIO_printf(bio_out, " if (!DSA_set0_pqg(dsa, p = BN_bin2bn(dsap_%d, sizeof(dsap_%d), NULL),\n", 188 bits_p, bits_p); 189 BIO_printf(bio_out, " q = BN_bin2bn(dsaq_%d, sizeof(dsaq_%d), NULL),\n", 190 bits_p, bits_p); 191 BIO_printf(bio_out, " g = BN_bin2bn(dsag_%d, sizeof(dsag_%d), NULL))) {\n", 192 bits_p, bits_p); 193 BIO_printf(bio_out, " DSA_free(dsa);\n" 194 " BN_free(p);\n" 195 " BN_free(q);\n" 196 " BN_free(g);\n" 197 " return NULL;\n" 198 " }\n" 199 " return dsa;\n}\n"); 200 OPENSSL_free(data); 201 } 202 203 if (outformat == FORMAT_ASN1 && genkey) 204 noout = 1; 205 206 if (!noout) { 207 if (outformat == FORMAT_ASN1) 208 i = i2d_DSAparams_bio(out, dsa); 209 else 210 i = PEM_write_bio_DSAparams(out, dsa); 211 if (!i) { 212 BIO_printf(bio_err, "unable to write DSA parameters\n"); 213 ERR_print_errors(bio_err); 214 goto end; 215 } 216 } 217 if (genkey) { 218 DSA *dsakey; 219 220 if ((dsakey = DSAparams_dup(dsa)) == NULL) 221 goto end; 222 if (!DSA_generate_key(dsakey)) { 223 ERR_print_errors(bio_err); 224 DSA_free(dsakey); 225 goto end; 226 } 227 assert(private); 228 if (outformat == FORMAT_ASN1) 229 i = i2d_DSAPrivateKey_bio(out, dsakey); 230 else 231 i = PEM_write_bio_DSAPrivateKey(out, dsakey, NULL, NULL, 0, NULL, 232 NULL); 233 DSA_free(dsakey); 234 } 235 ret = 0; 236 end: 237 BN_GENCB_free(cb); 238 BIO_free(in); 239 BIO_free_all(out); 240 DSA_free(dsa); 241 release_engine(e); 242 return ret; 243 } 244 245 static int dsa_cb(int p, int n, BN_GENCB *cb) 246 { 247 static const char symbols[] = ".+*\n"; 248 char c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?'; 249 250 BIO_write(BN_GENCB_get_arg(cb), &c, 1); 251 (void)BIO_flush(BN_GENCB_get_arg(cb)); 252 return 1; 253 } 254