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