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/dh.h> 21 #include <openssl/x509.h> 22 #include <openssl/pem.h> 23 24 #ifndef OPENSSL_NO_DSA 25 # include <openssl/dsa.h> 26 #endif 27 28 #define DEFBITS 2048 29 30 static int dh_cb(int p, int n, BN_GENCB *cb); 31 32 typedef enum OPTION_choice { 33 OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, 34 OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, 35 OPT_ENGINE, OPT_CHECK, OPT_TEXT, OPT_NOOUT, 36 OPT_DSAPARAM, OPT_C, OPT_2, OPT_5, 37 OPT_R_ENUM 38 } OPTION_CHOICE; 39 40 const OPTIONS dhparam_options[] = { 41 {OPT_HELP_STR, 1, '-', "Usage: %s [flags] [numbits]\n"}, 42 {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, 43 {"help", OPT_HELP, '-', "Display this summary"}, 44 {"in", OPT_IN, '<', "Input file"}, 45 {"inform", OPT_INFORM, 'F', "Input format, DER or PEM"}, 46 {"outform", OPT_OUTFORM, 'F', "Output format, DER or PEM"}, 47 {"out", OPT_OUT, '>', "Output file"}, 48 {"check", OPT_CHECK, '-', "Check the DH parameters"}, 49 {"text", OPT_TEXT, '-', "Print a text form of the DH parameters"}, 50 {"noout", OPT_NOOUT, '-', "Don't output any DH parameters"}, 51 OPT_R_OPTIONS, 52 {"C", OPT_C, '-', "Print C code"}, 53 {"2", OPT_2, '-', "Generate parameters using 2 as the generator value"}, 54 {"5", OPT_5, '-', "Generate parameters using 5 as the generator value"}, 55 #ifndef OPENSSL_NO_DSA 56 {"dsaparam", OPT_DSAPARAM, '-', 57 "Read or generate DSA parameters, convert to DH"}, 58 #endif 59 #ifndef OPENSSL_NO_ENGINE 60 {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, 61 #endif 62 {NULL} 63 }; 64 65 int dhparam_main(int argc, char **argv) 66 { 67 BIO *in = NULL, *out = NULL; 68 DH *dh = NULL; 69 char *infile = NULL, *outfile = NULL, *prog; 70 ENGINE *e = NULL; 71 #ifndef OPENSSL_NO_DSA 72 int dsaparam = 0; 73 #endif 74 int i, text = 0, C = 0, ret = 1, num = 0, g = 0; 75 int informat = FORMAT_PEM, outformat = FORMAT_PEM, check = 0, noout = 0; 76 OPTION_CHOICE o; 77 78 prog = opt_init(argc, argv, dhparam_options); 79 while ((o = opt_next()) != OPT_EOF) { 80 switch (o) { 81 case OPT_EOF: 82 case OPT_ERR: 83 opthelp: 84 BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 85 goto end; 86 case OPT_HELP: 87 opt_help(dhparam_options); 88 ret = 0; 89 goto end; 90 case OPT_INFORM: 91 if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) 92 goto opthelp; 93 break; 94 case OPT_OUTFORM: 95 if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) 96 goto opthelp; 97 break; 98 case OPT_IN: 99 infile = opt_arg(); 100 break; 101 case OPT_OUT: 102 outfile = opt_arg(); 103 break; 104 case OPT_ENGINE: 105 e = setup_engine(opt_arg(), 0); 106 break; 107 case OPT_CHECK: 108 check = 1; 109 break; 110 case OPT_TEXT: 111 text = 1; 112 break; 113 case OPT_DSAPARAM: 114 #ifndef OPENSSL_NO_DSA 115 dsaparam = 1; 116 #endif 117 break; 118 case OPT_C: 119 C = 1; 120 break; 121 case OPT_2: 122 g = 2; 123 break; 124 case OPT_5: 125 g = 5; 126 break; 127 case OPT_NOOUT: 128 noout = 1; 129 break; 130 case OPT_R_CASES: 131 if (!opt_rand(o)) 132 goto end; 133 break; 134 } 135 } 136 argc = opt_num_rest(); 137 argv = opt_rest(); 138 139 if (argv[0] != NULL && (!opt_int(argv[0], &num) || num <= 0)) 140 goto end; 141 142 if (g && !num) 143 num = DEFBITS; 144 145 #ifndef OPENSSL_NO_DSA 146 if (dsaparam && g) { 147 BIO_printf(bio_err, 148 "generator may not be chosen for DSA parameters\n"); 149 goto end; 150 } 151 #endif 152 153 out = bio_open_default(outfile, 'w', outformat); 154 if (out == NULL) 155 goto end; 156 157 /* DH parameters */ 158 if (num && !g) 159 g = 2; 160 161 if (num) { 162 163 BN_GENCB *cb; 164 cb = BN_GENCB_new(); 165 if (cb == NULL) { 166 ERR_print_errors(bio_err); 167 goto end; 168 } 169 170 BN_GENCB_set(cb, dh_cb, bio_err); 171 172 #ifndef OPENSSL_NO_DSA 173 if (dsaparam) { 174 DSA *dsa = DSA_new(); 175 176 BIO_printf(bio_err, 177 "Generating DSA parameters, %d bit long prime\n", num); 178 if (dsa == NULL 179 || !DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL, 180 cb)) { 181 DSA_free(dsa); 182 BN_GENCB_free(cb); 183 ERR_print_errors(bio_err); 184 goto end; 185 } 186 187 dh = DSA_dup_DH(dsa); 188 DSA_free(dsa); 189 if (dh == NULL) { 190 BN_GENCB_free(cb); 191 ERR_print_errors(bio_err); 192 goto end; 193 } 194 } else 195 #endif 196 { 197 dh = DH_new(); 198 BIO_printf(bio_err, 199 "Generating DH parameters, %d bit long safe prime, generator %d\n", 200 num, g); 201 BIO_printf(bio_err, "This is going to take a long time\n"); 202 if (dh == NULL || !DH_generate_parameters_ex(dh, num, g, cb)) { 203 BN_GENCB_free(cb); 204 ERR_print_errors(bio_err); 205 goto end; 206 } 207 } 208 209 BN_GENCB_free(cb); 210 } else { 211 212 in = bio_open_default(infile, 'r', informat); 213 if (in == NULL) 214 goto end; 215 216 #ifndef OPENSSL_NO_DSA 217 if (dsaparam) { 218 DSA *dsa; 219 220 if (informat == FORMAT_ASN1) 221 dsa = d2i_DSAparams_bio(in, NULL); 222 else /* informat == FORMAT_PEM */ 223 dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL); 224 225 if (dsa == NULL) { 226 BIO_printf(bio_err, "unable to load DSA parameters\n"); 227 ERR_print_errors(bio_err); 228 goto end; 229 } 230 231 dh = DSA_dup_DH(dsa); 232 DSA_free(dsa); 233 if (dh == NULL) { 234 ERR_print_errors(bio_err); 235 goto end; 236 } 237 } else 238 #endif 239 { 240 if (informat == FORMAT_ASN1) { 241 /* 242 * We have no PEM header to determine what type of DH params it 243 * is. We'll just try both. 244 */ 245 dh = d2i_DHparams_bio(in, NULL); 246 /* BIO_reset() returns 0 for success for file BIOs only!!! */ 247 if (dh == NULL && BIO_reset(in) == 0) 248 dh = d2i_DHxparams_bio(in, NULL); 249 } else { 250 /* informat == FORMAT_PEM */ 251 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); 252 } 253 254 if (dh == NULL) { 255 BIO_printf(bio_err, "unable to load DH parameters\n"); 256 ERR_print_errors(bio_err); 257 goto end; 258 } 259 } 260 261 /* dh != NULL */ 262 } 263 264 if (text) { 265 DHparams_print(out, dh); 266 } 267 268 if (check) { 269 if (!DH_check(dh, &i)) { 270 ERR_print_errors(bio_err); 271 goto end; 272 } 273 if (i & DH_CHECK_P_NOT_PRIME) 274 BIO_printf(bio_err, "WARNING: p value is not prime\n"); 275 if (i & DH_CHECK_P_NOT_SAFE_PRIME) 276 BIO_printf(bio_err, "WARNING: p value is not a safe prime\n"); 277 if (i & DH_CHECK_Q_NOT_PRIME) 278 BIO_printf(bio_err, "WARNING: q value is not a prime\n"); 279 if (i & DH_CHECK_INVALID_Q_VALUE) 280 BIO_printf(bio_err, "WARNING: q value is invalid\n"); 281 if (i & DH_CHECK_INVALID_J_VALUE) 282 BIO_printf(bio_err, "WARNING: j value is invalid\n"); 283 if (i & DH_UNABLE_TO_CHECK_GENERATOR) 284 BIO_printf(bio_err, 285 "WARNING: unable to check the generator value\n"); 286 if (i & DH_NOT_SUITABLE_GENERATOR) 287 BIO_printf(bio_err, "WARNING: the g value is not a generator\n"); 288 if (i == 0) 289 BIO_printf(bio_err, "DH parameters appear to be ok.\n"); 290 if (num != 0 && i != 0) { 291 /* 292 * We have generated parameters but DH_check() indicates they are 293 * invalid! This should never happen! 294 */ 295 BIO_printf(bio_err, "ERROR: Invalid parameters generated\n"); 296 goto end; 297 } 298 } 299 if (C) { 300 unsigned char *data; 301 int len, bits; 302 const BIGNUM *pbn, *gbn; 303 304 len = DH_size(dh); 305 bits = DH_bits(dh); 306 DH_get0_pqg(dh, &pbn, NULL, &gbn); 307 data = app_malloc(len, "print a BN"); 308 309 BIO_printf(out, "static DH *get_dh%d(void)\n{\n", bits); 310 print_bignum_var(out, pbn, "dhp", bits, data); 311 print_bignum_var(out, gbn, "dhg", bits, data); 312 BIO_printf(out, " DH *dh = DH_new();\n" 313 " BIGNUM *p, *g;\n" 314 "\n" 315 " if (dh == NULL)\n" 316 " return NULL;\n"); 317 BIO_printf(out, " p = BN_bin2bn(dhp_%d, sizeof(dhp_%d), NULL);\n", 318 bits, bits); 319 BIO_printf(out, " g = BN_bin2bn(dhg_%d, sizeof(dhg_%d), NULL);\n", 320 bits, bits); 321 BIO_printf(out, " if (p == NULL || g == NULL\n" 322 " || !DH_set0_pqg(dh, p, NULL, g)) {\n" 323 " DH_free(dh);\n" 324 " BN_free(p);\n" 325 " BN_free(g);\n" 326 " return NULL;\n" 327 " }\n"); 328 if (DH_get_length(dh) > 0) 329 BIO_printf(out, 330 " if (!DH_set_length(dh, %ld)) {\n" 331 " DH_free(dh);\n" 332 " return NULL;\n" 333 " }\n", DH_get_length(dh)); 334 BIO_printf(out, " return dh;\n}\n"); 335 OPENSSL_free(data); 336 } 337 338 if (!noout) { 339 const BIGNUM *q; 340 DH_get0_pqg(dh, NULL, &q, NULL); 341 if (outformat == FORMAT_ASN1) { 342 if (q != NULL) 343 i = i2d_DHxparams_bio(out, dh); 344 else 345 i = i2d_DHparams_bio(out, dh); 346 } else if (q != NULL) { 347 i = PEM_write_bio_DHxparams(out, dh); 348 } else { 349 i = PEM_write_bio_DHparams(out, dh); 350 } 351 if (!i) { 352 BIO_printf(bio_err, "unable to write DH parameters\n"); 353 ERR_print_errors(bio_err); 354 goto end; 355 } 356 } 357 ret = 0; 358 end: 359 BIO_free(in); 360 BIO_free_all(out); 361 DH_free(dh); 362 release_engine(e); 363 return ret; 364 } 365 366 static int dh_cb(int p, int n, BN_GENCB *cb) 367 { 368 static const char symbols[] = ".+*\n"; 369 char c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?'; 370 371 BIO_write(BN_GENCB_get_arg(cb), &c, 1); 372 (void)BIO_flush(BN_GENCB_get_arg(cb)); 373 return 1; 374 } 375