1*a9d90585Stb /* $OpenBSD: dhparam.c,v 1.19 2025/01/19 10:24:17 tb Exp $ */ 2dab3f910Sjsing /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3dab3f910Sjsing * All rights reserved. 4dab3f910Sjsing * 5dab3f910Sjsing * This package is an SSL implementation written 6dab3f910Sjsing * by Eric Young (eay@cryptsoft.com). 7dab3f910Sjsing * The implementation was written so as to conform with Netscapes SSL. 8dab3f910Sjsing * 9dab3f910Sjsing * This library is free for commercial and non-commercial use as long as 10dab3f910Sjsing * the following conditions are aheared to. The following conditions 11dab3f910Sjsing * apply to all code found in this distribution, be it the RC4, RSA, 12dab3f910Sjsing * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13dab3f910Sjsing * included with this distribution is covered by the same copyright terms 14dab3f910Sjsing * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15dab3f910Sjsing * 16dab3f910Sjsing * Copyright remains Eric Young's, and as such any Copyright notices in 17dab3f910Sjsing * the code are not to be removed. 18dab3f910Sjsing * If this package is used in a product, Eric Young should be given attribution 19dab3f910Sjsing * as the author of the parts of the library used. 20dab3f910Sjsing * This can be in the form of a textual message at program startup or 21dab3f910Sjsing * in documentation (online or textual) provided with the package. 22dab3f910Sjsing * 23dab3f910Sjsing * Redistribution and use in source and binary forms, with or without 24dab3f910Sjsing * modification, are permitted provided that the following conditions 25dab3f910Sjsing * are met: 26dab3f910Sjsing * 1. Redistributions of source code must retain the copyright 27dab3f910Sjsing * notice, this list of conditions and the following disclaimer. 28dab3f910Sjsing * 2. Redistributions in binary form must reproduce the above copyright 29dab3f910Sjsing * notice, this list of conditions and the following disclaimer in the 30dab3f910Sjsing * documentation and/or other materials provided with the distribution. 31dab3f910Sjsing * 3. All advertising materials mentioning features or use of this software 32dab3f910Sjsing * must display the following acknowledgement: 33dab3f910Sjsing * "This product includes cryptographic software written by 34dab3f910Sjsing * Eric Young (eay@cryptsoft.com)" 35dab3f910Sjsing * The word 'cryptographic' can be left out if the rouines from the library 36dab3f910Sjsing * being used are not cryptographic related :-). 37dab3f910Sjsing * 4. If you include any Windows specific code (or a derivative thereof) from 38dab3f910Sjsing * the apps directory (application code) you must include an acknowledgement: 39dab3f910Sjsing * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40dab3f910Sjsing * 41dab3f910Sjsing * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42dab3f910Sjsing * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43dab3f910Sjsing * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44dab3f910Sjsing * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45dab3f910Sjsing * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46dab3f910Sjsing * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47dab3f910Sjsing * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48dab3f910Sjsing * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49dab3f910Sjsing * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50dab3f910Sjsing * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51dab3f910Sjsing * SUCH DAMAGE. 52dab3f910Sjsing * 53dab3f910Sjsing * The licence and distribution terms for any publically available version or 54dab3f910Sjsing * derivative of this code cannot be changed. i.e. this code cannot simply be 55dab3f910Sjsing * copied and put under another distribution licence 56dab3f910Sjsing * [including the GNU Public Licence.] 57dab3f910Sjsing */ 58dab3f910Sjsing /* ==================================================================== 59dab3f910Sjsing * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. 60dab3f910Sjsing * 61dab3f910Sjsing * Redistribution and use in source and binary forms, with or without 62dab3f910Sjsing * modification, are permitted provided that the following conditions 63dab3f910Sjsing * are met: 64dab3f910Sjsing * 65dab3f910Sjsing * 1. Redistributions of source code must retain the above copyright 66dab3f910Sjsing * notice, this list of conditions and the following disclaimer. 67dab3f910Sjsing * 68dab3f910Sjsing * 2. Redistributions in binary form must reproduce the above copyright 69dab3f910Sjsing * notice, this list of conditions and the following disclaimer in 70dab3f910Sjsing * the documentation and/or other materials provided with the 71dab3f910Sjsing * distribution. 72dab3f910Sjsing * 73dab3f910Sjsing * 3. All advertising materials mentioning features or use of this 74dab3f910Sjsing * software must display the following acknowledgment: 75dab3f910Sjsing * "This product includes software developed by the OpenSSL Project 76dab3f910Sjsing * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 77dab3f910Sjsing * 78dab3f910Sjsing * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 79dab3f910Sjsing * endorse or promote products derived from this software without 80dab3f910Sjsing * prior written permission. For written permission, please contact 81dab3f910Sjsing * openssl-core@openssl.org. 82dab3f910Sjsing * 83dab3f910Sjsing * 5. Products derived from this software may not be called "OpenSSL" 84dab3f910Sjsing * nor may "OpenSSL" appear in their names without prior written 85dab3f910Sjsing * permission of the OpenSSL Project. 86dab3f910Sjsing * 87dab3f910Sjsing * 6. Redistributions of any form whatsoever must retain the following 88dab3f910Sjsing * acknowledgment: 89dab3f910Sjsing * "This product includes software developed by the OpenSSL Project 90dab3f910Sjsing * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 91dab3f910Sjsing * 92dab3f910Sjsing * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 93dab3f910Sjsing * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 94dab3f910Sjsing * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 95dab3f910Sjsing * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 96dab3f910Sjsing * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 97dab3f910Sjsing * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 98dab3f910Sjsing * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 99dab3f910Sjsing * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 100dab3f910Sjsing * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 101dab3f910Sjsing * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 102dab3f910Sjsing * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 103dab3f910Sjsing * OF THE POSSIBILITY OF SUCH DAMAGE. 104dab3f910Sjsing * ==================================================================== 105dab3f910Sjsing * 106dab3f910Sjsing * This product includes cryptographic software written by Eric Young 107dab3f910Sjsing * (eay@cryptsoft.com). This product includes software written by Tim 108dab3f910Sjsing * Hudson (tjh@cryptsoft.com). 109dab3f910Sjsing * 110dab3f910Sjsing */ 111dab3f910Sjsing 112dab3f910Sjsing #include <openssl/opensslconf.h> /* for OPENSSL_NO_DH */ 113dab3f910Sjsing 114dab3f910Sjsing #ifndef OPENSSL_NO_DH 115dab3f910Sjsing 116dab3f910Sjsing #include <stdio.h> 117dab3f910Sjsing #include <stdlib.h> 118dab3f910Sjsing #include <string.h> 119dab3f910Sjsing #include <time.h> 120dab3f910Sjsing 121dab3f910Sjsing #include "apps.h" 122dab3f910Sjsing 123dab3f910Sjsing #include <openssl/bio.h> 124dab3f910Sjsing #include <openssl/bn.h> 125dab3f910Sjsing #include <openssl/err.h> 126dab3f910Sjsing #include <openssl/dh.h> 127dab3f910Sjsing #include <openssl/pem.h> 128dab3f910Sjsing #include <openssl/x509.h> 129dab3f910Sjsing 130dab3f910Sjsing #include <openssl/dsa.h> 131dab3f910Sjsing 132a2c01ee8Ssthen #define DEFBITS 2048 133dab3f910Sjsing 134efc7e65fStb static struct { 135f7ecdafcSjsing int check; 136f7ecdafcSjsing int dsaparam; 137f7ecdafcSjsing int g; 138f7ecdafcSjsing char *infile; 139f7ecdafcSjsing int informat; 140f7ecdafcSjsing int noout; 141f7ecdafcSjsing char *outfile; 142f7ecdafcSjsing int outformat; 143f7ecdafcSjsing int text; 144e7718adaStb } cfg; 145f7ecdafcSjsing 146ea149709Sguenther static const struct option dhparam_options[] = { 147f7ecdafcSjsing { 148f7ecdafcSjsing .name = "2", 149f7ecdafcSjsing .desc = "Generate DH parameters with a generator value of 2 " 150f7ecdafcSjsing "(default)", 151f7ecdafcSjsing .type = OPTION_VALUE, 152e7718adaStb .opt.value = &cfg.g, 153f7ecdafcSjsing .value = 2, 154f7ecdafcSjsing }, 155f7ecdafcSjsing { 156f7ecdafcSjsing .name = "5", 157f7ecdafcSjsing .desc = "Generate DH parameters with a generator value of 5", 158f7ecdafcSjsing .type = OPTION_VALUE, 159e7718adaStb .opt.value = &cfg.g, 160f7ecdafcSjsing .value = 5, 161f7ecdafcSjsing }, 162f7ecdafcSjsing { 163f7ecdafcSjsing .name = "check", 164f7ecdafcSjsing .desc = "Check the DH parameters", 165f7ecdafcSjsing .type = OPTION_FLAG, 166e7718adaStb .opt.flag = &cfg.check, 167f7ecdafcSjsing }, 168f7ecdafcSjsing { 169f7ecdafcSjsing .name = "dsaparam", 170f7ecdafcSjsing .desc = "Read or generate DSA parameters and convert to DH", 171f7ecdafcSjsing .type = OPTION_FLAG, 172e7718adaStb .opt.flag = &cfg.dsaparam, 173f7ecdafcSjsing }, 174f7ecdafcSjsing { 175f7ecdafcSjsing .name = "in", 176f7ecdafcSjsing .argname = "file", 177f7ecdafcSjsing .desc = "Input file (default stdin)", 178f7ecdafcSjsing .type = OPTION_ARG, 179e7718adaStb .opt.arg = &cfg.infile, 180f7ecdafcSjsing }, 181f7ecdafcSjsing { 182f7ecdafcSjsing .name = "inform", 183f7ecdafcSjsing .argname = "format", 184f7ecdafcSjsing .desc = "Input format (DER or PEM (default))", 185f7ecdafcSjsing .type = OPTION_ARG_FORMAT, 186e7718adaStb .opt.value = &cfg.informat, 187f7ecdafcSjsing }, 188f7ecdafcSjsing { 189f7ecdafcSjsing .name = "noout", 190f7ecdafcSjsing .desc = "Do not output encoded version of DH parameters", 191f7ecdafcSjsing .type = OPTION_FLAG, 192e7718adaStb .opt.flag = &cfg.noout, 193f7ecdafcSjsing }, 194f7ecdafcSjsing { 195f7ecdafcSjsing .name = "out", 196f7ecdafcSjsing .argname = "file", 197f7ecdafcSjsing .desc = "Output file (default stdout)", 198f7ecdafcSjsing .type = OPTION_ARG, 199e7718adaStb .opt.arg = &cfg.outfile, 200f7ecdafcSjsing }, 201f7ecdafcSjsing { 202f7ecdafcSjsing .name = "outform", 203f7ecdafcSjsing .argname = "format", 204f7ecdafcSjsing .desc = "Output format (DER or PEM (default))", 205f7ecdafcSjsing .type = OPTION_ARG_FORMAT, 206e7718adaStb .opt.value = &cfg.outformat, 207f7ecdafcSjsing }, 208f7ecdafcSjsing { 209f7ecdafcSjsing .name = "text", 210f7ecdafcSjsing .desc = "Print DH parameters in plain text", 211f7ecdafcSjsing .type = OPTION_FLAG, 212e7718adaStb .opt.flag = &cfg.text, 213f7ecdafcSjsing }, 214f7ecdafcSjsing { NULL }, 215f7ecdafcSjsing }; 216f7ecdafcSjsing 217f7ecdafcSjsing static void 218440d1414Stb dhparam_usage(void) 219f7ecdafcSjsing { 220f7ecdafcSjsing fprintf(stderr, 221*a9d90585Stb "usage: dhparam [-2 | -5] [-check] [-dsaparam]\n" 222f7ecdafcSjsing " [-in file] [-inform DER | PEM] [-noout] [-out file]\n" 223f7ecdafcSjsing " [-outform DER | PEM] [-text] [numbits]\n\n"); 224f7ecdafcSjsing options_usage(dhparam_options); 225f7ecdafcSjsing } 226dab3f910Sjsing 227dab3f910Sjsing static int dh_cb(int p, int n, BN_GENCB *cb); 228dab3f910Sjsing 229dab3f910Sjsing int 230dab3f910Sjsing dhparam_main(int argc, char **argv) 231dab3f910Sjsing { 232dab3f910Sjsing BIO *in = NULL, *out = NULL; 233e0a955c7Stb BN_GENCB *cb = NULL; 234f7ecdafcSjsing char *num_bits = NULL; 235f7ecdafcSjsing DH *dh = NULL; 236f7ecdafcSjsing int num = 0; 237f7ecdafcSjsing int ret = 1; 238f7ecdafcSjsing int i; 239dab3f910Sjsing 24051811eadSderaadt if (pledge("stdio cpath wpath rpath", NULL) == -1) { 2419bc487adSdoug perror("pledge"); 242e370f0eeSdoug exit(1); 243e370f0eeSdoug } 2449bc487adSdoug 245e7718adaStb memset(&cfg, 0, sizeof(cfg)); 246dab3f910Sjsing 247e7718adaStb cfg.informat = FORMAT_PEM; 248e7718adaStb cfg.outformat = FORMAT_PEM; 249f7ecdafcSjsing 250f7ecdafcSjsing if (options_parse(argc, argv, dhparam_options, &num_bits, NULL) != 0) { 251f7ecdafcSjsing dhparam_usage(); 252f7ecdafcSjsing return (1); 253dab3f910Sjsing } 254dab3f910Sjsing 255f7ecdafcSjsing if (num_bits != NULL) { 256f7ecdafcSjsing if(sscanf(num_bits, "%d", &num) == 0 || num <= 0) { 257f7ecdafcSjsing BIO_printf(bio_err, "invalid number of bits: %s\n", 258f7ecdafcSjsing num_bits); 259f7ecdafcSjsing return (1); 260f7ecdafcSjsing } 261dab3f910Sjsing } 262dab3f910Sjsing 263e7718adaStb if (cfg.g && !num) 264dab3f910Sjsing num = DEFBITS; 265dab3f910Sjsing 266e7718adaStb if (cfg.dsaparam) { 267e7718adaStb if (cfg.g) { 268dab3f910Sjsing BIO_printf(bio_err, "generator may not be chosen for DSA parameters\n"); 269dab3f910Sjsing goto end; 270dab3f910Sjsing } 271f7ecdafcSjsing } else { 272dab3f910Sjsing /* DH parameters */ 273e7718adaStb if (num && !cfg.g) 274e7718adaStb cfg.g = 2; 275dab3f910Sjsing } 276dab3f910Sjsing 277dab3f910Sjsing if (num) { 278e0a955c7Stb if ((cb = BN_GENCB_new()) == NULL) { 279e0a955c7Stb BIO_printf(bio_err, 280e0a955c7Stb "Error allocating BN_GENCB object\n"); 281e0a955c7Stb goto end; 282e0a955c7Stb } 283dab3f910Sjsing 284e0a955c7Stb BN_GENCB_set(cb, dh_cb, bio_err); 285e7718adaStb if (cfg.dsaparam) { 286dab3f910Sjsing DSA *dsa = DSA_new(); 287dab3f910Sjsing 288dab3f910Sjsing BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n", num); 289dab3f910Sjsing if (!dsa || !DSA_generate_parameters_ex(dsa, num, 290e0a955c7Stb NULL, 0, NULL, NULL, cb)) { 291dab3f910Sjsing DSA_free(dsa); 292dab3f910Sjsing ERR_print_errors(bio_err); 293dab3f910Sjsing goto end; 294dab3f910Sjsing } 295dab3f910Sjsing dh = DSA_dup_DH(dsa); 296dab3f910Sjsing DSA_free(dsa); 297dab3f910Sjsing if (dh == NULL) { 298dab3f910Sjsing ERR_print_errors(bio_err); 299dab3f910Sjsing goto end; 300dab3f910Sjsing } 301f7ecdafcSjsing } else { 302dab3f910Sjsing dh = DH_new(); 303e7718adaStb BIO_printf(bio_err, "Generating DH parameters, %d bit long safe prime, generator %d\n", num, cfg.g); 304dab3f910Sjsing BIO_printf(bio_err, "This is going to take a long time\n"); 305e7718adaStb if (!dh || !DH_generate_parameters_ex(dh, num, cfg.g, cb)) { 306dab3f910Sjsing ERR_print_errors(bio_err); 307dab3f910Sjsing goto end; 308dab3f910Sjsing } 309dab3f910Sjsing } 310dab3f910Sjsing } else { 311dab3f910Sjsing 312dab3f910Sjsing in = BIO_new(BIO_s_file()); 313dab3f910Sjsing if (in == NULL) { 314dab3f910Sjsing ERR_print_errors(bio_err); 315dab3f910Sjsing goto end; 316dab3f910Sjsing } 317e7718adaStb if (cfg.infile == NULL) 318dab3f910Sjsing BIO_set_fp(in, stdin, BIO_NOCLOSE); 319dab3f910Sjsing else { 320e7718adaStb if (BIO_read_filename(in, cfg.infile) <= 0) { 321e7718adaStb perror(cfg.infile); 322dab3f910Sjsing goto end; 323dab3f910Sjsing } 324dab3f910Sjsing } 325dab3f910Sjsing 326e7718adaStb if (cfg.informat != FORMAT_ASN1 && 327e7718adaStb cfg.informat != FORMAT_PEM) { 328dab3f910Sjsing BIO_printf(bio_err, "bad input format specified\n"); 329dab3f910Sjsing goto end; 330dab3f910Sjsing } 331e7718adaStb if (cfg.dsaparam) { 332dab3f910Sjsing DSA *dsa; 333dab3f910Sjsing 334e7718adaStb if (cfg.informat == FORMAT_ASN1) 335dab3f910Sjsing dsa = d2i_DSAparams_bio(in, NULL); 336dab3f910Sjsing else /* informat == FORMAT_PEM */ 337dab3f910Sjsing dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL); 338dab3f910Sjsing 339dab3f910Sjsing if (dsa == NULL) { 340dab3f910Sjsing BIO_printf(bio_err, "unable to load DSA parameters\n"); 341dab3f910Sjsing ERR_print_errors(bio_err); 342dab3f910Sjsing goto end; 343dab3f910Sjsing } 344dab3f910Sjsing dh = DSA_dup_DH(dsa); 345dab3f910Sjsing DSA_free(dsa); 346dab3f910Sjsing if (dh == NULL) { 347dab3f910Sjsing ERR_print_errors(bio_err); 348dab3f910Sjsing goto end; 349dab3f910Sjsing } 350dab3f910Sjsing } else 351dab3f910Sjsing { 352e7718adaStb if (cfg.informat == FORMAT_ASN1) 353dab3f910Sjsing dh = d2i_DHparams_bio(in, NULL); 354dab3f910Sjsing else /* informat == FORMAT_PEM */ 355dab3f910Sjsing dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); 356dab3f910Sjsing 357dab3f910Sjsing if (dh == NULL) { 358dab3f910Sjsing BIO_printf(bio_err, "unable to load DH parameters\n"); 359dab3f910Sjsing ERR_print_errors(bio_err); 360dab3f910Sjsing goto end; 361dab3f910Sjsing } 362dab3f910Sjsing } 363dab3f910Sjsing 364dab3f910Sjsing /* dh != NULL */ 365dab3f910Sjsing } 366dab3f910Sjsing 367dab3f910Sjsing out = BIO_new(BIO_s_file()); 368dab3f910Sjsing if (out == NULL) { 369dab3f910Sjsing ERR_print_errors(bio_err); 370dab3f910Sjsing goto end; 371dab3f910Sjsing } 372e7718adaStb if (cfg.outfile == NULL) { 373dab3f910Sjsing BIO_set_fp(out, stdout, BIO_NOCLOSE); 374dab3f910Sjsing } else { 375e7718adaStb if (BIO_write_filename(out, cfg.outfile) <= 0) { 376e7718adaStb perror(cfg.outfile); 377dab3f910Sjsing goto end; 378dab3f910Sjsing } 379dab3f910Sjsing } 380dab3f910Sjsing 381dab3f910Sjsing 382e7718adaStb if (cfg.text) { 383dab3f910Sjsing DHparams_print(out, dh); 384dab3f910Sjsing } 385e7718adaStb if (cfg.check) { 386dab3f910Sjsing if (!DH_check(dh, &i)) { 387dab3f910Sjsing ERR_print_errors(bio_err); 388dab3f910Sjsing goto end; 389dab3f910Sjsing } 390dab3f910Sjsing if (i & DH_CHECK_P_NOT_PRIME) 391dab3f910Sjsing printf("p value is not prime\n"); 392dab3f910Sjsing if (i & DH_CHECK_P_NOT_SAFE_PRIME) 393dab3f910Sjsing printf("p value is not a safe prime\n"); 394dab3f910Sjsing if (i & DH_UNABLE_TO_CHECK_GENERATOR) 395dab3f910Sjsing printf("unable to check the generator value\n"); 396dab3f910Sjsing if (i & DH_NOT_SUITABLE_GENERATOR) 397dab3f910Sjsing printf("the g value is not a generator\n"); 398dab3f910Sjsing if (i == 0) 399dab3f910Sjsing printf("DH parameters appear to be ok.\n"); 400dab3f910Sjsing } 401e7718adaStb if (!cfg.noout) { 402e7718adaStb if (cfg.outformat == FORMAT_ASN1) 403dab3f910Sjsing i = i2d_DHparams_bio(out, dh); 404e7718adaStb else if (cfg.outformat == FORMAT_PEM) 405dab3f910Sjsing i = PEM_write_bio_DHparams(out, dh); 406dab3f910Sjsing else { 407dab3f910Sjsing BIO_printf(bio_err, "bad output format specified for outfile\n"); 408dab3f910Sjsing goto end; 409dab3f910Sjsing } 410dab3f910Sjsing if (!i) { 411dab3f910Sjsing BIO_printf(bio_err, "unable to write DH parameters\n"); 412dab3f910Sjsing ERR_print_errors(bio_err); 413dab3f910Sjsing goto end; 414dab3f910Sjsing } 415dab3f910Sjsing } 416dab3f910Sjsing ret = 0; 417dab3f910Sjsing 418dab3f910Sjsing end: 419dab3f910Sjsing BIO_free(in); 420dab3f910Sjsing BIO_free_all(out); 421e0a955c7Stb BN_GENCB_free(cb); 422dab3f910Sjsing DH_free(dh); 423dab3f910Sjsing 424dab3f910Sjsing return (ret); 425dab3f910Sjsing } 426dab3f910Sjsing 427dab3f910Sjsing /* dh_cb is identical to dsa_cb in apps/dsaparam.c */ 428dab3f910Sjsing static int 429dab3f910Sjsing dh_cb(int p, int n, BN_GENCB *cb) 430dab3f910Sjsing { 431dab3f910Sjsing char c = '*'; 432dab3f910Sjsing 433dab3f910Sjsing if (p == 0) 434dab3f910Sjsing c = '.'; 435dab3f910Sjsing if (p == 1) 436dab3f910Sjsing c = '+'; 437dab3f910Sjsing if (p == 2) 438dab3f910Sjsing c = '*'; 439dab3f910Sjsing if (p == 3) 440dab3f910Sjsing c = '\n'; 441e0a955c7Stb BIO_write(BN_GENCB_get_arg(cb), &c, 1); 442e0a955c7Stb (void) BIO_flush(BN_GENCB_get_arg(cb)); 443dab3f910Sjsing return 1; 444dab3f910Sjsing } 445dab3f910Sjsing 446dab3f910Sjsing #endif 447