1e71b7053SJung-uk Kim /* 2*b077aed3SPierre Pronchery * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. 3f579bf8eSKris Kennaway * 4*b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use 5e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 6e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at 7e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html 8f579bf8eSKris Kennaway */ 9f579bf8eSKris Kennaway 10e71b7053SJung-uk Kim #include <openssl/opensslconf.h> 11*b077aed3SPierre Pronchery 12f579bf8eSKris Kennaway #include <stdio.h> 13f579bf8eSKris Kennaway #include <stdlib.h> 14f579bf8eSKris Kennaway #include <time.h> 15f579bf8eSKris Kennaway #include <string.h> 16f579bf8eSKris Kennaway #include "apps.h" 17e71b7053SJung-uk Kim #include "progs.h" 18f579bf8eSKris Kennaway #include <openssl/bio.h> 19f579bf8eSKris Kennaway #include <openssl/err.h> 20f579bf8eSKris Kennaway #include <openssl/bn.h> 21*b077aed3SPierre Pronchery #include <openssl/dsa.h> 22f579bf8eSKris Kennaway #include <openssl/dh.h> 23f579bf8eSKris Kennaway #include <openssl/x509.h> 24f579bf8eSKris Kennaway #include <openssl/pem.h> 25*b077aed3SPierre Pronchery #include <openssl/core_names.h> 26*b077aed3SPierre Pronchery #include <openssl/core_dispatch.h> 27*b077aed3SPierre Pronchery #include <openssl/param_build.h> 28*b077aed3SPierre Pronchery #include <openssl/encoder.h> 29*b077aed3SPierre Pronchery #include <openssl/decoder.h> 30f579bf8eSKris Kennaway 31ed6b93beSJung-uk Kim #define DEFBITS 2048 32f579bf8eSKris Kennaway 33*b077aed3SPierre Pronchery static EVP_PKEY *dsa_to_dh(EVP_PKEY *dh); 34*b077aed3SPierre Pronchery static int gendh_cb(EVP_PKEY_CTX *ctx); 35f579bf8eSKris Kennaway 36e71b7053SJung-uk Kim typedef enum OPTION_choice { 37*b077aed3SPierre Pronchery OPT_COMMON, 38e71b7053SJung-uk Kim OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, 39e71b7053SJung-uk Kim OPT_ENGINE, OPT_CHECK, OPT_TEXT, OPT_NOOUT, 40*b077aed3SPierre Pronchery OPT_DSAPARAM, OPT_2, OPT_3, OPT_5, 41*b077aed3SPierre Pronchery OPT_R_ENUM, OPT_PROV_ENUM 42e71b7053SJung-uk Kim } OPTION_CHOICE; 43f579bf8eSKris Kennaway 44e71b7053SJung-uk Kim const OPTIONS dhparam_options[] = { 45*b077aed3SPierre Pronchery {OPT_HELP_STR, 1, '-', "Usage: %s [options] [numbits]\n"}, 46*b077aed3SPierre Pronchery 47*b077aed3SPierre Pronchery OPT_SECTION("General"), 48e71b7053SJung-uk Kim {"help", OPT_HELP, '-', "Display this summary"}, 49e71b7053SJung-uk Kim {"check", OPT_CHECK, '-', "Check the DH parameters"}, 50*b077aed3SPierre Pronchery #if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_DEPRECATED_3_0) 51e71b7053SJung-uk Kim {"dsaparam", OPT_DSAPARAM, '-', 52e71b7053SJung-uk Kim "Read or generate DSA parameters, convert to DH"}, 53e71b7053SJung-uk Kim #endif 54e71b7053SJung-uk Kim #ifndef OPENSSL_NO_ENGINE 55e71b7053SJung-uk Kim {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, 56e71b7053SJung-uk Kim #endif 57*b077aed3SPierre Pronchery 58*b077aed3SPierre Pronchery OPT_SECTION("Input"), 59*b077aed3SPierre Pronchery {"in", OPT_IN, '<', "Input file"}, 60*b077aed3SPierre Pronchery {"inform", OPT_INFORM, 'F', "Input format, DER or PEM"}, 61*b077aed3SPierre Pronchery 62*b077aed3SPierre Pronchery OPT_SECTION("Output"), 63*b077aed3SPierre Pronchery {"out", OPT_OUT, '>', "Output file"}, 64*b077aed3SPierre Pronchery {"outform", OPT_OUTFORM, 'F', "Output format, DER or PEM"}, 65*b077aed3SPierre Pronchery {"text", OPT_TEXT, '-', "Print a text form of the DH parameters"}, 66*b077aed3SPierre Pronchery {"noout", OPT_NOOUT, '-', "Don't output any DH parameters"}, 67*b077aed3SPierre Pronchery {"2", OPT_2, '-', "Generate parameters using 2 as the generator value"}, 68*b077aed3SPierre Pronchery {"3", OPT_3, '-', "Generate parameters using 3 as the generator value"}, 69*b077aed3SPierre Pronchery {"5", OPT_5, '-', "Generate parameters using 5 as the generator value"}, 70*b077aed3SPierre Pronchery 71*b077aed3SPierre Pronchery OPT_R_OPTIONS, 72*b077aed3SPierre Pronchery OPT_PROV_OPTIONS, 73*b077aed3SPierre Pronchery 74*b077aed3SPierre Pronchery OPT_PARAMETERS(), 75*b077aed3SPierre Pronchery {"numbits", 0, 0, "Number of bits if generating parameters (optional)"}, 76e71b7053SJung-uk Kim {NULL} 77e71b7053SJung-uk Kim }; 78f579bf8eSKris Kennaway 79e71b7053SJung-uk Kim int dhparam_main(int argc, char **argv) 80f579bf8eSKris Kennaway { 81e71b7053SJung-uk Kim BIO *in = NULL, *out = NULL; 82*b077aed3SPierre Pronchery EVP_PKEY *pkey = NULL, *tmppkey = NULL; 83*b077aed3SPierre Pronchery EVP_PKEY_CTX *ctx = NULL; 84e71b7053SJung-uk Kim char *infile = NULL, *outfile = NULL, *prog; 85e71b7053SJung-uk Kim ENGINE *e = NULL; 86f579bf8eSKris Kennaway int dsaparam = 0; 87*b077aed3SPierre Pronchery int text = 0, ret = 1, num = 0, g = 0; 88e71b7053SJung-uk Kim int informat = FORMAT_PEM, outformat = FORMAT_PEM, check = 0, noout = 0; 89e71b7053SJung-uk Kim OPTION_CHOICE o; 90f579bf8eSKris Kennaway 91e71b7053SJung-uk Kim prog = opt_init(argc, argv, dhparam_options); 92e71b7053SJung-uk Kim while ((o = opt_next()) != OPT_EOF) { 93e71b7053SJung-uk Kim switch (o) { 94e71b7053SJung-uk Kim case OPT_EOF: 95e71b7053SJung-uk Kim case OPT_ERR: 96e71b7053SJung-uk Kim opthelp: 97e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 985c87c606SMark Murray goto end; 99e71b7053SJung-uk Kim case OPT_HELP: 100e71b7053SJung-uk Kim opt_help(dhparam_options); 101e71b7053SJung-uk Kim ret = 0; 102e71b7053SJung-uk Kim goto end; 103e71b7053SJung-uk Kim case OPT_INFORM: 104e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) 105e71b7053SJung-uk Kim goto opthelp; 106e71b7053SJung-uk Kim break; 107e71b7053SJung-uk Kim case OPT_OUTFORM: 108e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) 109e71b7053SJung-uk Kim goto opthelp; 110e71b7053SJung-uk Kim break; 111e71b7053SJung-uk Kim case OPT_IN: 112e71b7053SJung-uk Kim infile = opt_arg(); 113e71b7053SJung-uk Kim break; 114e71b7053SJung-uk Kim case OPT_OUT: 115e71b7053SJung-uk Kim outfile = opt_arg(); 116e71b7053SJung-uk Kim break; 117e71b7053SJung-uk Kim case OPT_ENGINE: 118e71b7053SJung-uk Kim e = setup_engine(opt_arg(), 0); 119e71b7053SJung-uk Kim break; 120e71b7053SJung-uk Kim case OPT_CHECK: 121f579bf8eSKris Kennaway check = 1; 122e71b7053SJung-uk Kim break; 123e71b7053SJung-uk Kim case OPT_TEXT: 124f579bf8eSKris Kennaway text = 1; 125e71b7053SJung-uk Kim break; 126e71b7053SJung-uk Kim case OPT_DSAPARAM: 127f579bf8eSKris Kennaway dsaparam = 1; 128e71b7053SJung-uk Kim break; 129e71b7053SJung-uk Kim case OPT_2: 130f579bf8eSKris Kennaway g = 2; 131e71b7053SJung-uk Kim break; 132*b077aed3SPierre Pronchery case OPT_3: 133*b077aed3SPierre Pronchery g = 3; 134*b077aed3SPierre Pronchery break; 135e71b7053SJung-uk Kim case OPT_5: 136f579bf8eSKris Kennaway g = 5; 137e71b7053SJung-uk Kim break; 138e71b7053SJung-uk Kim case OPT_NOOUT: 139e71b7053SJung-uk Kim noout = 1; 140e71b7053SJung-uk Kim break; 141e71b7053SJung-uk Kim case OPT_R_CASES: 142e71b7053SJung-uk Kim if (!opt_rand(o)) 143f579bf8eSKris Kennaway goto end; 144e71b7053SJung-uk Kim break; 145*b077aed3SPierre Pronchery case OPT_PROV_CASES: 146*b077aed3SPierre Pronchery if (!opt_provider(o)) 147*b077aed3SPierre Pronchery goto end; 148*b077aed3SPierre Pronchery break; 149f579bf8eSKris Kennaway } 150e71b7053SJung-uk Kim } 151*b077aed3SPierre Pronchery 152*b077aed3SPierre Pronchery /* One optional argument, bitsize to generate. */ 153e71b7053SJung-uk Kim argc = opt_num_rest(); 154e71b7053SJung-uk Kim argv = opt_rest(); 155*b077aed3SPierre Pronchery if (argc == 1) { 156*b077aed3SPierre Pronchery if (!opt_int(argv[0], &num) || num <= 0) 157*b077aed3SPierre Pronchery goto opthelp; 158*b077aed3SPierre Pronchery } else if (argc != 0) { 159*b077aed3SPierre Pronchery goto opthelp; 160*b077aed3SPierre Pronchery } 161*b077aed3SPierre Pronchery if (!app_RAND_load()) 162e71b7053SJung-uk Kim goto end; 1635c87c606SMark Murray 164f579bf8eSKris Kennaway if (g && !num) 165f579bf8eSKris Kennaway num = DEFBITS; 166f579bf8eSKris Kennaway 167e71b7053SJung-uk Kim if (dsaparam && g) { 1686f9291ceSJung-uk Kim BIO_printf(bio_err, 169*b077aed3SPierre Pronchery "Error, generator may not be chosen for DSA parameters\n"); 170f579bf8eSKris Kennaway goto end; 171f579bf8eSKris Kennaway } 172e71b7053SJung-uk Kim 173e71b7053SJung-uk Kim out = bio_open_default(outfile, 'w', outformat); 174e71b7053SJung-uk Kim if (out == NULL) 175e71b7053SJung-uk Kim goto end; 176e71b7053SJung-uk Kim 177f579bf8eSKris Kennaway /* DH parameters */ 178f579bf8eSKris Kennaway if (num && !g) 179f579bf8eSKris Kennaway g = 2; 180f579bf8eSKris Kennaway 181f579bf8eSKris Kennaway if (num) { 182*b077aed3SPierre Pronchery const char *alg = dsaparam ? "DSA" : "DH"; 183f579bf8eSKris Kennaway 184*b077aed3SPierre Pronchery if (infile != NULL) { 185*b077aed3SPierre Pronchery BIO_printf(bio_err, "Warning, input file %s ignored\n", infile); 186*b077aed3SPierre Pronchery } 187*b077aed3SPierre Pronchery 188*b077aed3SPierre Pronchery ctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), alg, app_get0_propq()); 189*b077aed3SPierre Pronchery if (ctx == NULL) { 190*b077aed3SPierre Pronchery BIO_printf(bio_err, 191*b077aed3SPierre Pronchery "Error, %s param generation context allocation failed\n", 192*b077aed3SPierre Pronchery alg); 193*b077aed3SPierre Pronchery goto end; 194*b077aed3SPierre Pronchery } 195*b077aed3SPierre Pronchery EVP_PKEY_CTX_set_cb(ctx, gendh_cb); 196*b077aed3SPierre Pronchery EVP_PKEY_CTX_set_app_data(ctx, bio_err); 197*b077aed3SPierre Pronchery BIO_printf(bio_err, 198*b077aed3SPierre Pronchery "Generating %s parameters, %d bit long %sprime\n", 199*b077aed3SPierre Pronchery alg, num, dsaparam ? "" : "safe "); 200*b077aed3SPierre Pronchery 201*b077aed3SPierre Pronchery if (EVP_PKEY_paramgen_init(ctx) <= 0) { 202*b077aed3SPierre Pronchery BIO_printf(bio_err, 203*b077aed3SPierre Pronchery "Error, unable to initialise %s parameters\n", 204*b077aed3SPierre Pronchery alg); 205e71b7053SJung-uk Kim goto end; 206f579bf8eSKris Kennaway } 207e71b7053SJung-uk Kim 2086f9291ceSJung-uk Kim if (dsaparam) { 209*b077aed3SPierre Pronchery if (EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, num) <= 0) { 210*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error, unable to set DSA prime length\n"); 211f579bf8eSKris Kennaway goto end; 212f579bf8eSKris Kennaway } 213f579bf8eSKris Kennaway } else { 214*b077aed3SPierre Pronchery if (EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, num) <= 0) { 215*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error, unable to set DH prime length\n"); 216*b077aed3SPierre Pronchery goto end; 217*b077aed3SPierre Pronchery } 218*b077aed3SPierre Pronchery if (EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, g) <= 0) { 219*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error, unable to set generator\n"); 220*b077aed3SPierre Pronchery goto end; 221*b077aed3SPierre Pronchery } 222*b077aed3SPierre Pronchery } 223*b077aed3SPierre Pronchery 224*b077aed3SPierre Pronchery tmppkey = app_paramgen(ctx, alg); 225*b077aed3SPierre Pronchery EVP_PKEY_CTX_free(ctx); 226*b077aed3SPierre Pronchery ctx = NULL; 227*b077aed3SPierre Pronchery if (dsaparam) { 228*b077aed3SPierre Pronchery pkey = dsa_to_dh(tmppkey); 229*b077aed3SPierre Pronchery if (pkey == NULL) 230*b077aed3SPierre Pronchery goto end; 231*b077aed3SPierre Pronchery EVP_PKEY_free(tmppkey); 232*b077aed3SPierre Pronchery } else { 233*b077aed3SPierre Pronchery pkey = tmppkey; 234*b077aed3SPierre Pronchery } 235*b077aed3SPierre Pronchery tmppkey = NULL; 236*b077aed3SPierre Pronchery } else { 237*b077aed3SPierre Pronchery OSSL_DECODER_CTX *decoderctx = NULL; 238*b077aed3SPierre Pronchery const char *keytype = "DH"; 239*b077aed3SPierre Pronchery int done; 240f579bf8eSKris Kennaway 241e71b7053SJung-uk Kim in = bio_open_default(infile, 'r', informat); 242e71b7053SJung-uk Kim if (in == NULL) 243f579bf8eSKris Kennaway goto end; 244f579bf8eSKris Kennaway 245*b077aed3SPierre Pronchery do { 246ed7112f0SJung-uk Kim /* 247*b077aed3SPierre Pronchery * We assume we're done unless we explicitly want to retry and set 248*b077aed3SPierre Pronchery * this to 0 below. 249ed7112f0SJung-uk Kim */ 250*b077aed3SPierre Pronchery done = 1; 251*b077aed3SPierre Pronchery /* 252*b077aed3SPierre Pronchery * We set NULL for the keytype to allow any key type. We don't know 253*b077aed3SPierre Pronchery * if we're going to get DH or DHX (or DSA in the event of dsaparam). 254*b077aed3SPierre Pronchery * We check that we got one of those key types afterwards. 255*b077aed3SPierre Pronchery */ 256*b077aed3SPierre Pronchery decoderctx 257*b077aed3SPierre Pronchery = OSSL_DECODER_CTX_new_for_pkey(&tmppkey, 258*b077aed3SPierre Pronchery (informat == FORMAT_ASN1) 259*b077aed3SPierre Pronchery ? "DER" : "PEM", 260*b077aed3SPierre Pronchery NULL, 261*b077aed3SPierre Pronchery (informat == FORMAT_ASN1) 262*b077aed3SPierre Pronchery ? keytype : NULL, 263*b077aed3SPierre Pronchery OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, 264*b077aed3SPierre Pronchery NULL, NULL); 265f579bf8eSKris Kennaway 266*b077aed3SPierre Pronchery if (decoderctx != NULL 267*b077aed3SPierre Pronchery && !OSSL_DECODER_from_bio(decoderctx, in) 268*b077aed3SPierre Pronchery && informat == FORMAT_ASN1 269*b077aed3SPierre Pronchery && strcmp(keytype, "DH") == 0) { 270*b077aed3SPierre Pronchery /* 271*b077aed3SPierre Pronchery * When reading DER we explicitly state the expected keytype 272*b077aed3SPierre Pronchery * because, unlike PEM, there is no header to declare what 273*b077aed3SPierre Pronchery * the contents of the DER file are. The decoders just try 274*b077aed3SPierre Pronchery * and guess. Unfortunately with DHX key types they may guess 275*b077aed3SPierre Pronchery * wrong and think we have a DSA keytype. Therefore we try 276*b077aed3SPierre Pronchery * both DH and DHX sequentially. 277*b077aed3SPierre Pronchery */ 278*b077aed3SPierre Pronchery keytype = "DHX"; 279*b077aed3SPierre Pronchery /* 280*b077aed3SPierre Pronchery * BIO_reset() returns 0 for success for file BIOs only!!! 281*b077aed3SPierre Pronchery * This won't work for stdin (and never has done) 282*b077aed3SPierre Pronchery */ 283*b077aed3SPierre Pronchery if (BIO_reset(in) == 0) 284*b077aed3SPierre Pronchery done = 0; 285*b077aed3SPierre Pronchery } 286*b077aed3SPierre Pronchery OSSL_DECODER_CTX_free(decoderctx); 287*b077aed3SPierre Pronchery } while (!done); 288*b077aed3SPierre Pronchery if (tmppkey == NULL) { 289*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error, unable to load parameters\n"); 290f579bf8eSKris Kennaway goto end; 291f579bf8eSKris Kennaway } 292*b077aed3SPierre Pronchery 293*b077aed3SPierre Pronchery if (dsaparam) { 294*b077aed3SPierre Pronchery if (!EVP_PKEY_is_a(tmppkey, "DSA")) { 295*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error, unable to load DSA parameters\n"); 296*b077aed3SPierre Pronchery goto end; 297*b077aed3SPierre Pronchery } 298*b077aed3SPierre Pronchery pkey = dsa_to_dh(tmppkey); 299*b077aed3SPierre Pronchery if (pkey == NULL) 300*b077aed3SPierre Pronchery goto end; 301*b077aed3SPierre Pronchery } else { 302*b077aed3SPierre Pronchery if (!EVP_PKEY_is_a(tmppkey, "DH") 303*b077aed3SPierre Pronchery && !EVP_PKEY_is_a(tmppkey, "DHX")) { 304*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error, unable to load DH parameters\n"); 305*b077aed3SPierre Pronchery goto end; 306*b077aed3SPierre Pronchery } 307*b077aed3SPierre Pronchery pkey = tmppkey; 308*b077aed3SPierre Pronchery tmppkey = NULL; 309*b077aed3SPierre Pronchery } 310f579bf8eSKris Kennaway } 311f579bf8eSKris Kennaway 312*b077aed3SPierre Pronchery if (text) 313*b077aed3SPierre Pronchery EVP_PKEY_print_params(out, pkey, 4, NULL); 314f579bf8eSKris Kennaway 3156f9291ceSJung-uk Kim if (check) { 316*b077aed3SPierre Pronchery ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), pkey, app_get0_propq()); 317*b077aed3SPierre Pronchery if (ctx == NULL) { 318*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error, failed to check DH parameters\n"); 319f579bf8eSKris Kennaway goto end; 320f579bf8eSKris Kennaway } 321*b077aed3SPierre Pronchery if (EVP_PKEY_param_check(ctx) <= 0) { 322*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error, invalid parameters generated\n"); 323*b077aed3SPierre Pronchery goto end; 324*b077aed3SPierre Pronchery } 325e71b7053SJung-uk Kim BIO_printf(bio_err, "DH parameters appear to be ok.\n"); 326f579bf8eSKris Kennaway } 327f579bf8eSKris Kennaway 3286f9291ceSJung-uk Kim if (!noout) { 329*b077aed3SPierre Pronchery OSSL_ENCODER_CTX *ectx = 330*b077aed3SPierre Pronchery OSSL_ENCODER_CTX_new_for_pkey(pkey, 331*b077aed3SPierre Pronchery OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, 332*b077aed3SPierre Pronchery outformat == FORMAT_ASN1 333*b077aed3SPierre Pronchery ? "DER" : "PEM", 334*b077aed3SPierre Pronchery NULL, NULL); 335*b077aed3SPierre Pronchery 336*b077aed3SPierre Pronchery if (ectx == NULL || !OSSL_ENCODER_to_bio(ectx, out)) { 337*b077aed3SPierre Pronchery OSSL_ENCODER_CTX_free(ectx); 338*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error, unable to write DH parameters\n"); 339f579bf8eSKris Kennaway goto end; 340f579bf8eSKris Kennaway } 341*b077aed3SPierre Pronchery OSSL_ENCODER_CTX_free(ectx); 342f579bf8eSKris Kennaway } 343f579bf8eSKris Kennaway ret = 0; 344f579bf8eSKris Kennaway end: 345*b077aed3SPierre Pronchery if (ret != 0) 346*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 3476f9291ceSJung-uk Kim BIO_free(in); 3486f9291ceSJung-uk Kim BIO_free_all(out); 349*b077aed3SPierre Pronchery EVP_PKEY_free(pkey); 350*b077aed3SPierre Pronchery EVP_PKEY_free(tmppkey); 351*b077aed3SPierre Pronchery EVP_PKEY_CTX_free(ctx); 3526cf8931aSJung-uk Kim release_engine(e); 353e71b7053SJung-uk Kim return ret; 354f579bf8eSKris Kennaway } 355f579bf8eSKris Kennaway 356*b077aed3SPierre Pronchery /* 357*b077aed3SPierre Pronchery * Historically we had the low level call DSA_dup_DH() to do this. 358*b077aed3SPierre Pronchery * That is now deprecated with no replacement. Since we still need to do this 359*b077aed3SPierre Pronchery * for backwards compatibility reasons, we do it "manually". 360*b077aed3SPierre Pronchery */ 361*b077aed3SPierre Pronchery static EVP_PKEY *dsa_to_dh(EVP_PKEY *dh) 362f579bf8eSKris Kennaway { 363*b077aed3SPierre Pronchery OSSL_PARAM_BLD *tmpl = NULL; 364*b077aed3SPierre Pronchery OSSL_PARAM *params = NULL; 365*b077aed3SPierre Pronchery BIGNUM *bn_p = NULL, *bn_q = NULL, *bn_g = NULL; 366*b077aed3SPierre Pronchery EVP_PKEY_CTX *ctx = NULL; 367*b077aed3SPierre Pronchery EVP_PKEY *pkey = NULL; 368*b077aed3SPierre Pronchery 369*b077aed3SPierre Pronchery if (!EVP_PKEY_get_bn_param(dh, OSSL_PKEY_PARAM_FFC_P, &bn_p) 370*b077aed3SPierre Pronchery || !EVP_PKEY_get_bn_param(dh, OSSL_PKEY_PARAM_FFC_Q, &bn_q) 371*b077aed3SPierre Pronchery || !EVP_PKEY_get_bn_param(dh, OSSL_PKEY_PARAM_FFC_G, &bn_g)) { 372*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error, failed to set DH parameters\n"); 373*b077aed3SPierre Pronchery goto err; 374*b077aed3SPierre Pronchery } 375*b077aed3SPierre Pronchery 376*b077aed3SPierre Pronchery if ((tmpl = OSSL_PARAM_BLD_new()) == NULL 377*b077aed3SPierre Pronchery || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, 378*b077aed3SPierre Pronchery bn_p) 379*b077aed3SPierre Pronchery || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q, 380*b077aed3SPierre Pronchery bn_q) 381*b077aed3SPierre Pronchery || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, 382*b077aed3SPierre Pronchery bn_g) 383*b077aed3SPierre Pronchery || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) { 384*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error, failed to set DH parameters\n"); 385*b077aed3SPierre Pronchery goto err; 386*b077aed3SPierre Pronchery } 387*b077aed3SPierre Pronchery 388*b077aed3SPierre Pronchery ctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), "DHX", app_get0_propq()); 389*b077aed3SPierre Pronchery if (ctx == NULL 390*b077aed3SPierre Pronchery || EVP_PKEY_fromdata_init(ctx) <= 0 391*b077aed3SPierre Pronchery || EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEY_PARAMETERS, params) <= 0) { 392*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error, failed to set DH parameters\n"); 393*b077aed3SPierre Pronchery goto err; 394*b077aed3SPierre Pronchery } 395*b077aed3SPierre Pronchery 396*b077aed3SPierre Pronchery err: 397*b077aed3SPierre Pronchery EVP_PKEY_CTX_free(ctx); 398*b077aed3SPierre Pronchery OSSL_PARAM_free(params); 399*b077aed3SPierre Pronchery OSSL_PARAM_BLD_free(tmpl); 400*b077aed3SPierre Pronchery BN_free(bn_p); 401*b077aed3SPierre Pronchery BN_free(bn_q); 402*b077aed3SPierre Pronchery BN_free(bn_g); 403*b077aed3SPierre Pronchery return pkey; 404*b077aed3SPierre Pronchery } 405*b077aed3SPierre Pronchery 406*b077aed3SPierre Pronchery static int gendh_cb(EVP_PKEY_CTX *ctx) 407*b077aed3SPierre Pronchery { 408*b077aed3SPierre Pronchery int p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); 409*b077aed3SPierre Pronchery BIO *b = EVP_PKEY_CTX_get_app_data(ctx); 410e71b7053SJung-uk Kim static const char symbols[] = ".+*\n"; 411e71b7053SJung-uk Kim char c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?'; 412f579bf8eSKris Kennaway 413*b077aed3SPierre Pronchery BIO_write(b, &c, 1); 414*b077aed3SPierre Pronchery (void)BIO_flush(b); 4153b4e3dcbSSimon L. B. Nielsen return 1; 416f579bf8eSKris Kennaway } 417