xref: /openbsd-src/usr.bin/openssl/dhparam.c (revision a9d90585ca40c280201dda70d6b331b26701653a)
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