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