159191Skris/* apps/dhparam.c */
259191Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
359191Skris * All rights reserved.
459191Skris *
559191Skris * This package is an SSL implementation written
659191Skris * by Eric Young (eay@cryptsoft.com).
759191Skris * The implementation was written so as to conform with Netscapes SSL.
8296465Sdelphij *
959191Skris * This library is free for commercial and non-commercial use as long as
1059191Skris * the following conditions are aheared to.  The following conditions
1159191Skris * apply to all code found in this distribution, be it the RC4, RSA,
1259191Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1359191Skris * included with this distribution is covered by the same copyright terms
1459191Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15296465Sdelphij *
1659191Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1759191Skris * the code are not to be removed.
1859191Skris * If this package is used in a product, Eric Young should be given attribution
1959191Skris * as the author of the parts of the library used.
2059191Skris * This can be in the form of a textual message at program startup or
2159191Skris * in documentation (online or textual) provided with the package.
22296465Sdelphij *
2359191Skris * Redistribution and use in source and binary forms, with or without
2459191Skris * modification, are permitted provided that the following conditions
2559191Skris * are met:
2659191Skris * 1. Redistributions of source code must retain the copyright
2759191Skris *    notice, this list of conditions and the following disclaimer.
2859191Skris * 2. Redistributions in binary form must reproduce the above copyright
2959191Skris *    notice, this list of conditions and the following disclaimer in the
3059191Skris *    documentation and/or other materials provided with the distribution.
3159191Skris * 3. All advertising materials mentioning features or use of this software
3259191Skris *    must display the following acknowledgement:
3359191Skris *    "This product includes cryptographic software written by
3459191Skris *     Eric Young (eay@cryptsoft.com)"
3559191Skris *    The word 'cryptographic' can be left out if the rouines from the library
3659191Skris *    being used are not cryptographic related :-).
37296465Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from
3859191Skris *    the apps directory (application code) you must include an acknowledgement:
3959191Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40296465Sdelphij *
4159191Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4259191Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4359191Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4459191Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4559191Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4659191Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4759191Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4859191Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4959191Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5059191Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5159191Skris * SUCH DAMAGE.
52296465Sdelphij *
5359191Skris * The licence and distribution terms for any publically available version or
5459191Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5559191Skris * copied and put under another distribution licence
5659191Skris * [including the GNU Public Licence.]
5759191Skris */
5859191Skris/* ====================================================================
5959191Skris * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
6059191Skris *
6159191Skris * Redistribution and use in source and binary forms, with or without
6259191Skris * modification, are permitted provided that the following conditions
6359191Skris * are met:
6459191Skris *
6559191Skris * 1. Redistributions of source code must retain the above copyright
66296465Sdelphij *    notice, this list of conditions and the following disclaimer.
6759191Skris *
6859191Skris * 2. Redistributions in binary form must reproduce the above copyright
6959191Skris *    notice, this list of conditions and the following disclaimer in
7059191Skris *    the documentation and/or other materials provided with the
7159191Skris *    distribution.
7259191Skris *
7359191Skris * 3. All advertising materials mentioning features or use of this
7459191Skris *    software must display the following acknowledgment:
7559191Skris *    "This product includes software developed by the OpenSSL Project
7659191Skris *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
7759191Skris *
7859191Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
7959191Skris *    endorse or promote products derived from this software without
8059191Skris *    prior written permission. For written permission, please contact
8159191Skris *    openssl-core@openssl.org.
8259191Skris *
8359191Skris * 5. Products derived from this software may not be called "OpenSSL"
8459191Skris *    nor may "OpenSSL" appear in their names without prior written
8559191Skris *    permission of the OpenSSL Project.
8659191Skris *
8759191Skris * 6. Redistributions of any form whatsoever must retain the following
8859191Skris *    acknowledgment:
8959191Skris *    "This product includes software developed by the OpenSSL Project
9059191Skris *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
9159191Skris *
9259191Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
9359191Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9459191Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
9559191Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
9659191Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9759191Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
9859191Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
9959191Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
10059191Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
10159191Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
10259191Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
10359191Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
10459191Skris * ====================================================================
10559191Skris *
10659191Skris * This product includes cryptographic software written by Eric Young
10759191Skris * (eay@cryptsoft.com).  This product includes software written by Tim
10859191Skris * Hudson (tjh@cryptsoft.com).
10959191Skris *
11059191Skris */
11159191Skris
112296465Sdelphij#include <openssl/opensslconf.h> /* for OPENSSL_NO_DH */
113109998Smarkm#ifndef OPENSSL_NO_DH
114296465Sdelphij# include <stdio.h>
115296465Sdelphij# include <stdlib.h>
116296465Sdelphij# include <time.h>
117296465Sdelphij# include <string.h>
118296465Sdelphij# include "apps.h"
119296465Sdelphij# include <openssl/bio.h>
120296465Sdelphij# include <openssl/err.h>
121296465Sdelphij# include <openssl/bn.h>
122296465Sdelphij# include <openssl/dh.h>
123296465Sdelphij# include <openssl/x509.h>
124296465Sdelphij# include <openssl/pem.h>
12559191Skris
126296465Sdelphij# ifndef OPENSSL_NO_DSA
127296465Sdelphij#  include <openssl/dsa.h>
128296465Sdelphij# endif
12959191Skris
130296465Sdelphij# undef PROG
131296465Sdelphij# define PROG    dhparam_main
13259191Skris
133296465Sdelphij# define DEFBITS 512
13459191Skris
135296465Sdelphij/*-
136296465Sdelphij * -inform arg  - input format - default PEM (DER or PEM)
13759191Skris * -outform arg - output format - default PEM
138296465Sdelphij * -in arg      - input file - default stdin
139296465Sdelphij * -out arg     - output file - default stdout
14059191Skris * -dsaparam  - read or generate DSA parameters, convert to DH
141296465Sdelphij * -check       - check the parameters are ok
14259191Skris * -noout
14359191Skris * -text
14459191Skris * -C
14559191Skris */
14659191Skris
147160814Ssimonstatic int MS_CALLBACK dh_cb(int p, int n, BN_GENCB *cb);
14859191Skris
14959191Skrisint MAIN(int, char **);
15059191Skris
15159191Skrisint MAIN(int argc, char **argv)
152296465Sdelphij{
153296465Sdelphij    DH *dh = NULL;
154296465Sdelphij    int i, badops = 0, text = 0;
155296465Sdelphij# ifndef OPENSSL_NO_DSA
156296465Sdelphij    int dsaparam = 0;
157296465Sdelphij# endif
158296465Sdelphij    BIO *in = NULL, *out = NULL;
159296465Sdelphij    int informat, outformat, check = 0, noout = 0, C = 0, ret = 1;
160296465Sdelphij    char *infile, *outfile, *prog;
161296465Sdelphij    char *inrand = NULL;
162296465Sdelphij# ifndef OPENSSL_NO_ENGINE
163296465Sdelphij    char *engine = NULL;
164296465Sdelphij# endif
165296465Sdelphij    int num = 0, g = 0;
16659191Skris
167296465Sdelphij    apps_startup();
16859191Skris
169296465Sdelphij    if (bio_err == NULL)
170296465Sdelphij        if ((bio_err = BIO_new(BIO_s_file())) != NULL)
171296465Sdelphij            BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
17259191Skris
173296465Sdelphij    if (!load_config(bio_err, NULL))
174296465Sdelphij        goto end;
175109998Smarkm
176296465Sdelphij    infile = NULL;
177296465Sdelphij    outfile = NULL;
178296465Sdelphij    informat = FORMAT_PEM;
179296465Sdelphij    outformat = FORMAT_PEM;
18059191Skris
181296465Sdelphij    prog = argv[0];
182296465Sdelphij    argc--;
183296465Sdelphij    argv++;
184296465Sdelphij    while (argc >= 1) {
185296465Sdelphij        if (strcmp(*argv, "-inform") == 0) {
186296465Sdelphij            if (--argc < 1)
187296465Sdelphij                goto bad;
188296465Sdelphij            informat = str2fmt(*(++argv));
189296465Sdelphij        } else if (strcmp(*argv, "-outform") == 0) {
190296465Sdelphij            if (--argc < 1)
191296465Sdelphij                goto bad;
192296465Sdelphij            outformat = str2fmt(*(++argv));
193296465Sdelphij        } else if (strcmp(*argv, "-in") == 0) {
194296465Sdelphij            if (--argc < 1)
195296465Sdelphij                goto bad;
196296465Sdelphij            infile = *(++argv);
197296465Sdelphij        } else if (strcmp(*argv, "-out") == 0) {
198296465Sdelphij            if (--argc < 1)
199296465Sdelphij                goto bad;
200296465Sdelphij            outfile = *(++argv);
201296465Sdelphij        }
202296465Sdelphij# ifndef OPENSSL_NO_ENGINE
203296465Sdelphij        else if (strcmp(*argv, "-engine") == 0) {
204296465Sdelphij            if (--argc < 1)
205296465Sdelphij                goto bad;
206296465Sdelphij            engine = *(++argv);
207296465Sdelphij        }
208296465Sdelphij# endif
209296465Sdelphij        else if (strcmp(*argv, "-check") == 0)
210296465Sdelphij            check = 1;
211296465Sdelphij        else if (strcmp(*argv, "-text") == 0)
212296465Sdelphij            text = 1;
213296465Sdelphij# ifndef OPENSSL_NO_DSA
214296465Sdelphij        else if (strcmp(*argv, "-dsaparam") == 0)
215296465Sdelphij            dsaparam = 1;
216296465Sdelphij# endif
217296465Sdelphij        else if (strcmp(*argv, "-C") == 0)
218296465Sdelphij            C = 1;
219296465Sdelphij        else if (strcmp(*argv, "-noout") == 0)
220296465Sdelphij            noout = 1;
221296465Sdelphij        else if (strcmp(*argv, "-2") == 0)
222296465Sdelphij            g = 2;
223296465Sdelphij        else if (strcmp(*argv, "-5") == 0)
224296465Sdelphij            g = 5;
225296465Sdelphij        else if (strcmp(*argv, "-rand") == 0) {
226296465Sdelphij            if (--argc < 1)
227296465Sdelphij                goto bad;
228296465Sdelphij            inrand = *(++argv);
229296465Sdelphij        } else if (((sscanf(*argv, "%d", &num) == 0) || (num <= 0)))
230296465Sdelphij            goto bad;
231296465Sdelphij        argv++;
232296465Sdelphij        argc--;
233296465Sdelphij    }
23459191Skris
235296465Sdelphij    if (badops) {
236296465Sdelphij bad:
237296465Sdelphij        BIO_printf(bio_err, "%s [options] [numbits]\n", prog);
238296465Sdelphij        BIO_printf(bio_err, "where options are\n");
239296465Sdelphij        BIO_printf(bio_err, " -inform arg   input format - one of DER PEM\n");
240296465Sdelphij        BIO_printf(bio_err,
241296465Sdelphij                   " -outform arg  output format - one of DER PEM\n");
242296465Sdelphij        BIO_printf(bio_err, " -in arg       input file\n");
243296465Sdelphij        BIO_printf(bio_err, " -out arg      output file\n");
244296465Sdelphij# ifndef OPENSSL_NO_DSA
245296465Sdelphij        BIO_printf(bio_err,
246296465Sdelphij                   " -dsaparam     read or generate DSA parameters, convert to DH\n");
247296465Sdelphij# endif
248296465Sdelphij        BIO_printf(bio_err, " -check        check the DH parameters\n");
249296465Sdelphij        BIO_printf(bio_err,
250296465Sdelphij                   " -text         print a text form of the DH parameters\n");
251296465Sdelphij        BIO_printf(bio_err, " -C            Output C code\n");
252296465Sdelphij        BIO_printf(bio_err,
253296465Sdelphij                   " -2            generate parameters using  2 as the generator value\n");
254296465Sdelphij        BIO_printf(bio_err,
255296465Sdelphij                   " -5            generate parameters using  5 as the generator value\n");
256296465Sdelphij        BIO_printf(bio_err,
257296465Sdelphij                   " numbits       number of bits in to generate (default 512)\n");
258296465Sdelphij# ifndef OPENSSL_NO_ENGINE
259296465Sdelphij        BIO_printf(bio_err,
260296465Sdelphij                   " -engine e     use engine e, possibly a hardware device.\n");
261296465Sdelphij# endif
262296465Sdelphij        BIO_printf(bio_err, " -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR,
263296465Sdelphij                   LIST_SEPARATOR_CHAR);
264296465Sdelphij        BIO_printf(bio_err,
265296465Sdelphij                   "               - load the file (or the files in the directory) into\n");
266296465Sdelphij        BIO_printf(bio_err, "               the random number generator\n");
267296465Sdelphij        BIO_printf(bio_err, " -noout        no output\n");
268296465Sdelphij        goto end;
269296465Sdelphij    }
27059191Skris
271296465Sdelphij    ERR_load_crypto_strings();
27259191Skris
273296465Sdelphij# ifndef OPENSSL_NO_ENGINE
274296465Sdelphij    setup_engine(bio_err, engine, 0);
275296465Sdelphij# endif
276109998Smarkm
277296465Sdelphij    if (g && !num)
278296465Sdelphij        num = DEFBITS;
27959191Skris
280296465Sdelphij# ifndef OPENSSL_NO_DSA
281296465Sdelphij    if (dsaparam) {
282296465Sdelphij        if (g) {
283296465Sdelphij            BIO_printf(bio_err,
284296465Sdelphij                       "generator may not be chosen for DSA parameters\n");
285296465Sdelphij            goto end;
286296465Sdelphij        }
287296465Sdelphij    } else
288296465Sdelphij# endif
289296465Sdelphij    {
290296465Sdelphij        /* DH parameters */
291296465Sdelphij        if (num && !g)
292296465Sdelphij            g = 2;
293296465Sdelphij    }
29459191Skris
295296465Sdelphij    if (num) {
29659191Skris
297296465Sdelphij        BN_GENCB cb;
298296465Sdelphij        BN_GENCB_set(&cb, dh_cb, bio_err);
299296465Sdelphij        if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL) {
300296465Sdelphij            BIO_printf(bio_err,
301296465Sdelphij                       "warning, not much extra random data, consider using the -rand option\n");
302296465Sdelphij        }
303296465Sdelphij        if (inrand != NULL)
304296465Sdelphij            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
305296465Sdelphij                       app_RAND_load_files(inrand));
30659191Skris
307296465Sdelphij# ifndef OPENSSL_NO_DSA
308296465Sdelphij        if (dsaparam) {
309296465Sdelphij            DSA *dsa = DSA_new();
31059191Skris
311296465Sdelphij            BIO_printf(bio_err,
312296465Sdelphij                       "Generating DSA parameters, %d bit long prime\n", num);
313296465Sdelphij            if (!dsa
314296465Sdelphij                || !DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL,
315296465Sdelphij                                               &cb)) {
316296465Sdelphij                if (dsa)
317296465Sdelphij                    DSA_free(dsa);
318296465Sdelphij                ERR_print_errors(bio_err);
319296465Sdelphij                goto end;
320296465Sdelphij            }
32159191Skris
322296465Sdelphij            dh = DSA_dup_DH(dsa);
323296465Sdelphij            DSA_free(dsa);
324296465Sdelphij            if (dh == NULL) {
325296465Sdelphij                ERR_print_errors(bio_err);
326296465Sdelphij                goto end;
327296465Sdelphij            }
328296465Sdelphij        } else
329296465Sdelphij# endif
330296465Sdelphij        {
331296465Sdelphij            dh = DH_new();
332296465Sdelphij            BIO_printf(bio_err,
333296465Sdelphij                       "Generating DH parameters, %d bit long safe prime, generator %d\n",
334296465Sdelphij                       num, g);
335296465Sdelphij            BIO_printf(bio_err, "This is going to take a long time\n");
336296465Sdelphij            if (!dh || !DH_generate_parameters_ex(dh, num, g, &cb)) {
337296465Sdelphij                ERR_print_errors(bio_err);
338296465Sdelphij                goto end;
339296465Sdelphij            }
340296465Sdelphij        }
34159191Skris
342296465Sdelphij        app_RAND_write_file(NULL, bio_err);
343296465Sdelphij    } else {
34459191Skris
345296465Sdelphij        in = BIO_new(BIO_s_file());
346296465Sdelphij        if (in == NULL) {
347296465Sdelphij            ERR_print_errors(bio_err);
348296465Sdelphij            goto end;
349296465Sdelphij        }
350296465Sdelphij        if (infile == NULL)
351296465Sdelphij            BIO_set_fp(in, stdin, BIO_NOCLOSE);
352296465Sdelphij        else {
353296465Sdelphij            if (BIO_read_filename(in, infile) <= 0) {
354296465Sdelphij                perror(infile);
355296465Sdelphij                goto end;
356296465Sdelphij            }
357296465Sdelphij        }
35859191Skris
359296465Sdelphij        if (informat != FORMAT_ASN1 && informat != FORMAT_PEM) {
360296465Sdelphij            BIO_printf(bio_err, "bad input format specified\n");
361296465Sdelphij            goto end;
362296465Sdelphij        }
363296465Sdelphij# ifndef OPENSSL_NO_DSA
364296465Sdelphij        if (dsaparam) {
365296465Sdelphij            DSA *dsa;
36659191Skris
367296465Sdelphij            if (informat == FORMAT_ASN1)
368296465Sdelphij                dsa = d2i_DSAparams_bio(in, NULL);
369296465Sdelphij            else                /* informat == FORMAT_PEM */
370296465Sdelphij                dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL);
37159191Skris
372296465Sdelphij            if (dsa == NULL) {
373296465Sdelphij                BIO_printf(bio_err, "unable to load DSA parameters\n");
374296465Sdelphij                ERR_print_errors(bio_err);
375296465Sdelphij                goto end;
376296465Sdelphij            }
37759191Skris
378296465Sdelphij            dh = DSA_dup_DH(dsa);
379296465Sdelphij            DSA_free(dsa);
380296465Sdelphij            if (dh == NULL) {
381296465Sdelphij                ERR_print_errors(bio_err);
382296465Sdelphij                goto end;
383296465Sdelphij            }
384296465Sdelphij        } else
385296465Sdelphij# endif
386296465Sdelphij        {
387296465Sdelphij            if (informat == FORMAT_ASN1)
388296465Sdelphij                dh = d2i_DHparams_bio(in, NULL);
389296465Sdelphij            else                /* informat == FORMAT_PEM */
390296465Sdelphij                dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
39159191Skris
392296465Sdelphij            if (dh == NULL) {
393296465Sdelphij                BIO_printf(bio_err, "unable to load DH parameters\n");
394296465Sdelphij                ERR_print_errors(bio_err);
395296465Sdelphij                goto end;
396296465Sdelphij            }
397296465Sdelphij        }
39859191Skris
399296465Sdelphij        /* dh != NULL */
400296465Sdelphij    }
40159191Skris
402296465Sdelphij    out = BIO_new(BIO_s_file());
403296465Sdelphij    if (out == NULL) {
404296465Sdelphij        ERR_print_errors(bio_err);
405296465Sdelphij        goto end;
406296465Sdelphij    }
407296465Sdelphij    if (outfile == NULL) {
408296465Sdelphij        BIO_set_fp(out, stdout, BIO_NOCLOSE);
409296465Sdelphij# ifdef OPENSSL_SYS_VMS
410296465Sdelphij        {
411296465Sdelphij            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
412296465Sdelphij            out = BIO_push(tmpbio, out);
413296465Sdelphij        }
414296465Sdelphij# endif
415296465Sdelphij    } else {
416296465Sdelphij        if (BIO_write_filename(out, outfile) <= 0) {
417296465Sdelphij            perror(outfile);
418296465Sdelphij            goto end;
419296465Sdelphij        }
420296465Sdelphij    }
42159191Skris
422296465Sdelphij    if (text) {
423296465Sdelphij        DHparams_print(out, dh);
424296465Sdelphij    }
42559191Skris
426296465Sdelphij    if (check) {
427296465Sdelphij        if (!DH_check(dh, &i)) {
428296465Sdelphij            ERR_print_errors(bio_err);
429296465Sdelphij            goto end;
430296465Sdelphij        }
431296465Sdelphij        if (i & DH_CHECK_P_NOT_PRIME)
432296465Sdelphij            printf("p value is not prime\n");
433296465Sdelphij        if (i & DH_CHECK_P_NOT_SAFE_PRIME)
434296465Sdelphij            printf("p value is not a safe prime\n");
435296465Sdelphij        if (i & DH_UNABLE_TO_CHECK_GENERATOR)
436296465Sdelphij            printf("unable to check the generator value\n");
437296465Sdelphij        if (i & DH_NOT_SUITABLE_GENERATOR)
438296465Sdelphij            printf("the g value is not a generator\n");
439296465Sdelphij        if (i == 0)
440296465Sdelphij            printf("DH parameters appear to be ok.\n");
441296465Sdelphij    }
442296465Sdelphij    if (C) {
443296465Sdelphij        unsigned char *data;
444296465Sdelphij        int len, l, bits;
44559191Skris
446296465Sdelphij        len = BN_num_bytes(dh->p);
447296465Sdelphij        bits = BN_num_bits(dh->p);
448296465Sdelphij        data = (unsigned char *)OPENSSL_malloc(len);
449296465Sdelphij        if (data == NULL) {
450296465Sdelphij            perror("OPENSSL_malloc");
451296465Sdelphij            goto end;
452296465Sdelphij        }
453296465Sdelphij        printf("#ifndef HEADER_DH_H\n"
454296465Sdelphij               "#include <openssl/dh.h>\n" "#endif\n");
455296465Sdelphij        printf("DH *get_dh%d()\n\t{\n", bits);
456296465Sdelphij
457296465Sdelphij        l = BN_bn2bin(dh->p, data);
458296465Sdelphij        printf("\tstatic unsigned char dh%d_p[]={", bits);
459296465Sdelphij        for (i = 0; i < l; i++) {
460296465Sdelphij            if ((i % 12) == 0)
461296465Sdelphij                printf("\n\t\t");
462296465Sdelphij            printf("0x%02X,", data[i]);
463296465Sdelphij        }
464296465Sdelphij        printf("\n\t\t};\n");
465296465Sdelphij
466296465Sdelphij        l = BN_bn2bin(dh->g, data);
467296465Sdelphij        printf("\tstatic unsigned char dh%d_g[]={", bits);
468296465Sdelphij        for (i = 0; i < l; i++) {
469296465Sdelphij            if ((i % 12) == 0)
470296465Sdelphij                printf("\n\t\t");
471296465Sdelphij            printf("0x%02X,", data[i]);
472296465Sdelphij        }
473296465Sdelphij        printf("\n\t\t};\n");
474296465Sdelphij
475296465Sdelphij        printf("\tDH *dh;\n\n");
476296465Sdelphij        printf("\tif ((dh=DH_new()) == NULL) return(NULL);\n");
477296465Sdelphij        printf("\tdh->p=BN_bin2bn(dh%d_p,sizeof(dh%d_p),NULL);\n",
478296465Sdelphij               bits, bits);
479296465Sdelphij        printf("\tdh->g=BN_bin2bn(dh%d_g,sizeof(dh%d_g),NULL);\n",
480296465Sdelphij               bits, bits);
481296465Sdelphij        printf("\tif ((dh->p == NULL) || (dh->g == NULL))\n");
482296465Sdelphij        printf("\t\t{ DH_free(dh); return(NULL); }\n");
483296465Sdelphij        if (dh->length)
484296465Sdelphij            printf("\tdh->length = %ld;\n", dh->length);
485296465Sdelphij        printf("\treturn(dh);\n\t}\n");
486296465Sdelphij        OPENSSL_free(data);
487296465Sdelphij    }
488296465Sdelphij
489296465Sdelphij    if (!noout) {
490296465Sdelphij        if (outformat == FORMAT_ASN1)
491296465Sdelphij            i = i2d_DHparams_bio(out, dh);
492296465Sdelphij        else if (outformat == FORMAT_PEM)
493296465Sdelphij            i = PEM_write_bio_DHparams(out, dh);
494296465Sdelphij        else {
495296465Sdelphij            BIO_printf(bio_err, "bad output format specified for outfile\n");
496296465Sdelphij            goto end;
497296465Sdelphij        }
498296465Sdelphij        if (!i) {
499296465Sdelphij            BIO_printf(bio_err, "unable to write DH parameters\n");
500296465Sdelphij            ERR_print_errors(bio_err);
501296465Sdelphij            goto end;
502296465Sdelphij        }
503296465Sdelphij    }
504296465Sdelphij    ret = 0;
505296465Sdelphij end:
506296465Sdelphij    if (in != NULL)
507296465Sdelphij        BIO_free(in);
508296465Sdelphij    if (out != NULL)
509296465Sdelphij        BIO_free_all(out);
510296465Sdelphij    if (dh != NULL)
511296465Sdelphij        DH_free(dh);
512296465Sdelphij    apps_shutdown();
513296465Sdelphij    OPENSSL_EXIT(ret);
514296465Sdelphij}
515296465Sdelphij
51659191Skris/* dh_cb is identical to dsa_cb in apps/dsaparam.c */
517160814Ssimonstatic int MS_CALLBACK dh_cb(int p, int n, BN_GENCB *cb)
518296465Sdelphij{
519296465Sdelphij    char c = '*';
52059191Skris
521296465Sdelphij    if (p == 0)
522296465Sdelphij        c = '.';
523296465Sdelphij    if (p == 1)
524296465Sdelphij        c = '+';
525296465Sdelphij    if (p == 2)
526296465Sdelphij        c = '*';
527296465Sdelphij    if (p == 3)
528296465Sdelphij        c = '\n';
529296465Sdelphij    BIO_write(cb->arg, &c, 1);
530296465Sdelphij    (void)BIO_flush(cb->arg);
531296465Sdelphij# ifdef LINT
532296465Sdelphij    p = n;
533296465Sdelphij# endif
534296465Sdelphij    return 1;
535296465Sdelphij}
53659191Skris
53759191Skris#endif
538