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