dh.c revision 109998
1263367Semaste/* apps/dh.c */
2254721Semaste/* obsoleted by dhparam.c */
3254721Semaste/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
4254721Semaste * All rights reserved.
5254721Semaste *
6254721Semaste * This package is an SSL implementation written
7254721Semaste * by Eric Young (eay@cryptsoft.com).
8254721Semaste * The implementation was written so as to conform with Netscapes SSL.
9254721Semaste *
10254721Semaste * This library is free for commercial and non-commercial use as long as
11254721Semaste * the following conditions are aheared to.  The following conditions
12254721Semaste * apply to all code found in this distribution, be it the RC4, RSA,
13254721Semaste * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
14254721Semaste * included with this distribution is covered by the same copyright terms
15254721Semaste * except that the holder is Tim Hudson (tjh@cryptsoft.com).
16269024Semaste *
17254721Semaste * Copyright remains Eric Young's, and as such any Copyright notices in
18254721Semaste * the code are not to be removed.
19263363Semaste * If this package is used in a product, Eric Young should be given attribution
20263363Semaste * as the author of the parts of the library used.
21269024Semaste * This can be in the form of a textual message at program startup or
22269024Semaste * in documentation (online or textual) provided with the package.
23263363Semaste *
24263363Semaste * Redistribution and use in source and binary forms, with or without
25254721Semaste * modification, are permitted provided that the following conditions
26254721Semaste * are met:
27254721Semaste * 1. Redistributions of source code must retain the copyright
28254721Semaste *    notice, this list of conditions and the following disclaimer.
29254721Semaste * 2. Redistributions in binary form must reproduce the above copyright
30254721Semaste *    notice, this list of conditions and the following disclaimer in the
31254721Semaste *    documentation and/or other materials provided with the distribution.
32254721Semaste * 3. All advertising materials mentioning features or use of this software
33254721Semaste *    must display the following acknowledgement:
34254721Semaste *    "This product includes cryptographic software written by
35254721Semaste *     Eric Young (eay@cryptsoft.com)"
36254721Semaste *    The word 'cryptographic' can be left out if the rouines from the library
37254721Semaste *    being used are not cryptographic related :-).
38254721Semaste * 4. If you include any Windows specific code (or a derivative thereof) from
39254721Semaste *    the apps directory (application code) you must include an acknowledgement:
40254721Semaste *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
41254721Semaste *
42254721Semaste * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
43254721Semaste * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44254721Semaste * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45254721Semaste * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
46254721Semaste * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47254721Semaste * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48254721Semaste * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49254721Semaste * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50254721Semaste * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51254721Semaste * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52254721Semaste * SUCH DAMAGE.
53254721Semaste *
54254721Semaste * The licence and distribution terms for any publically available version or
55254721Semaste * derivative of this code cannot be changed.  i.e. this code cannot simply be
56254721Semaste * copied and put under another distribution licence
57254721Semaste * [including the GNU Public Licence.]
58254721Semaste */
59254721Semaste
60254721Semaste#ifndef OPENSSL_NO_DH
61254721Semaste#include <stdio.h>
62254721Semaste#include <stdlib.h>
63254721Semaste#include <time.h>
64254721Semaste#include <string.h>
65254721Semaste#include "apps.h"
66254721Semaste#include <openssl/bio.h>
67254721Semaste#include <openssl/err.h>
68254721Semaste#include <openssl/bn.h>
69254721Semaste#include <openssl/dh.h>
70254721Semaste#include <openssl/x509.h>
71254721Semaste#include <openssl/pem.h>
72254721Semaste
73254721Semaste#undef PROG
74254721Semaste#define PROG	dh_main
75254721Semaste
76254721Semaste/* -inform arg	- input format - default PEM (DER or PEM)
77254721Semaste * -outform arg - output format - default PEM
78254721Semaste * -in arg	- input file - default stdin
79254721Semaste * -out arg	- output file - default stdout
80254721Semaste * -check	- check the parameters are ok
81254721Semaste * -noout
82269024Semaste * -text
83269024Semaste * -C
84269024Semaste */
85269024Semaste
86269024Semasteint MAIN(int, char **);
87254721Semaste
88254721Semasteint MAIN(int argc, char **argv)
89254721Semaste	{
90254721Semaste	ENGINE *e = NULL;
91263363Semaste	DH *dh=NULL;
92263363Semaste	int i,badops=0,text=0;
93263363Semaste	BIO *in=NULL,*out=NULL;
94263363Semaste	int informat,outformat,check=0,noout=0,C=0,ret=1;
95263363Semaste	char *infile,*outfile,*prog,*engine;
96263363Semaste
97269024Semaste	apps_startup();
98269024Semaste
99269024Semaste	if (bio_err == NULL)
100269024Semaste		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
101269024Semaste			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
102263363Semaste
103263363Semaste	if (!load_config(bio_err, NULL))
104263363Semaste		goto end;
105263363Semaste
106263363Semaste	engine=NULL;
107263363Semaste	infile=NULL;
108263363Semaste	outfile=NULL;
109254721Semaste	informat=FORMAT_PEM;
110254721Semaste	outformat=FORMAT_PEM;
111254721Semaste
112254721Semaste	prog=argv[0];
113269024Semaste	argc--;
114269024Semaste	argv++;
115269024Semaste	while (argc >= 1)
116269024Semaste		{
117254721Semaste		if 	(strcmp(*argv,"-inform") == 0)
118254721Semaste			{
119254721Semaste			if (--argc < 1) goto bad;
120254721Semaste			informat=str2fmt(*(++argv));
121254721Semaste			}
122254721Semaste		else if (strcmp(*argv,"-outform") == 0)
123254721Semaste			{
124254721Semaste			if (--argc < 1) goto bad;
125254721Semaste			outformat=str2fmt(*(++argv));
126254721Semaste			}
127254721Semaste		else if (strcmp(*argv,"-in") == 0)
128254721Semaste			{
129254721Semaste			if (--argc < 1) goto bad;
130254721Semaste			infile= *(++argv);
131254721Semaste			}
132254721Semaste		else if (strcmp(*argv,"-out") == 0)
133254721Semaste			{
134254721Semaste			if (--argc < 1) goto bad;
135254721Semaste			outfile= *(++argv);
136254721Semaste			}
137254721Semaste		else if (strcmp(*argv,"-engine") == 0)
138254721Semaste			{
139254721Semaste			if (--argc < 1) goto bad;
140254721Semaste			engine= *(++argv);
141254721Semaste			}
142254721Semaste		else if (strcmp(*argv,"-check") == 0)
143254721Semaste			check=1;
144254721Semaste		else if (strcmp(*argv,"-text") == 0)
145254721Semaste			text=1;
146254721Semaste		else if (strcmp(*argv,"-C") == 0)
147254721Semaste			C=1;
148254721Semaste		else if (strcmp(*argv,"-noout") == 0)
149254721Semaste			noout=1;
150254721Semaste		else
151254721Semaste			{
152254721Semaste			BIO_printf(bio_err,"unknown option %s\n",*argv);
153254721Semaste			badops=1;
154254721Semaste			break;
155254721Semaste			}
156254721Semaste		argc--;
157269024Semaste		argv++;
158254721Semaste		}
159254721Semaste
160254721Semaste	if (badops)
161254721Semaste		{
162254721Semastebad:
163254721Semaste		BIO_printf(bio_err,"%s [options] <infile >outfile\n",prog);
164254721Semaste		BIO_printf(bio_err,"where options are\n");
165254721Semaste		BIO_printf(bio_err," -inform arg   input format - one of DER PEM\n");
166254721Semaste		BIO_printf(bio_err," -outform arg  output format - one of DER PEM\n");
167254721Semaste		BIO_printf(bio_err," -in arg       input file\n");
168254721Semaste		BIO_printf(bio_err," -out arg      output file\n");
169254721Semaste		BIO_printf(bio_err," -check        check the DH parameters\n");
170254721Semaste		BIO_printf(bio_err," -text         print a text form of the DH parameters\n");
171269024Semaste		BIO_printf(bio_err," -C            Output C code\n");
172269024Semaste		BIO_printf(bio_err," -noout        no output\n");
173269024Semaste		BIO_printf(bio_err," -engine e     use engine e, possibly a hardware device.\n");
174269024Semaste		goto end;
175269024Semaste		}
176269024Semaste
177269024Semaste	ERR_load_crypto_strings();
178269024Semaste
179269024Semaste        e = setup_engine(bio_err, engine, 0);
180269024Semaste
181269024Semaste	in=BIO_new(BIO_s_file());
182269024Semaste	out=BIO_new(BIO_s_file());
183254721Semaste	if ((in == NULL) || (out == NULL))
184254721Semaste		{
185254721Semaste		ERR_print_errors(bio_err);
186254721Semaste		goto end;
187269024Semaste		}
188269024Semaste
189269024Semaste	if (infile == NULL)
190269024Semaste		BIO_set_fp(in,stdin,BIO_NOCLOSE);
191269024Semaste	else
192269024Semaste		{
193269024Semaste		if (BIO_read_filename(in,infile) <= 0)
194269024Semaste			{
195269024Semaste			perror(infile);
196254721Semaste			goto end;
197254721Semaste			}
198254721Semaste		}
199254721Semaste	if (outfile == NULL)
200254721Semaste		{
201254721Semaste		BIO_set_fp(out,stdout,BIO_NOCLOSE);
202254721Semaste#ifdef OPENSSL_SYS_VMS
203254721Semaste		{
204254721Semaste		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
205254721Semaste		out = BIO_push(tmpbio, out);
206254721Semaste		}
207254721Semaste#endif
208254721Semaste		}
209269024Semaste	else
210254721Semaste		{
211254721Semaste		if (BIO_write_filename(out,outfile) <= 0)
212254721Semaste			{
213254721Semaste			perror(outfile);
214254721Semaste			goto end;
215254721Semaste			}
216254721Semaste		}
217254721Semaste
218254721Semaste	if	(informat == FORMAT_ASN1)
219254721Semaste		dh=d2i_DHparams_bio(in,NULL);
220254721Semaste	else if (informat == FORMAT_PEM)
221263363Semaste		dh=PEM_read_bio_DHparams(in,NULL,NULL,NULL);
222263363Semaste	else
223263363Semaste		{
224254721Semaste		BIO_printf(bio_err,"bad input format specified\n");
225263363Semaste		goto end;
226254721Semaste		}
227254721Semaste	if (dh == NULL)
228254721Semaste		{
229254721Semaste		BIO_printf(bio_err,"unable to load DH parameters\n");
230254721Semaste		ERR_print_errors(bio_err);
231269024Semaste		goto end;
232254721Semaste		}
233254721Semaste
234254721Semaste
235254721Semaste
236254721Semaste	if (text)
237254721Semaste		{
238254721Semaste		DHparams_print(out,dh);
239254721Semaste#ifdef undef
240254721Semaste		printf("p=");
241254721Semaste		BN_print(stdout,dh->p);
242254721Semaste		printf("\ng=");
243254721Semaste		BN_print(stdout,dh->g);
244254721Semaste		printf("\n");
245254721Semaste		if (dh->length != 0)
246254721Semaste			printf("recommended private length=%ld\n",dh->length);
247254721Semaste#endif
248254721Semaste		}
249254721Semaste
250254721Semaste	if (check)
251254721Semaste		{
252254721Semaste		if (!DH_check(dh,&i))
253254721Semaste			{
254254721Semaste			ERR_print_errors(bio_err);
255254721Semaste			goto end;
256254721Semaste			}
257254721Semaste		if (i & DH_CHECK_P_NOT_PRIME)
258254721Semaste			printf("p value is not prime\n");
259254721Semaste		if (i & DH_CHECK_P_NOT_SAFE_PRIME)
260254721Semaste			printf("p value is not a safe prime\n");
261254721Semaste		if (i & DH_UNABLE_TO_CHECK_GENERATOR)
262254721Semaste			printf("unable to check the generator value\n");
263254721Semaste		if (i & DH_NOT_SUITABLE_GENERATOR)
264254721Semaste			printf("the g value is not a generator\n");
265254721Semaste		if (i == 0)
266254721Semaste			printf("DH parameters appear to be ok.\n");
267254721Semaste		}
268254721Semaste	if (C)
269254721Semaste		{
270254721Semaste		unsigned char *data;
271254721Semaste		int len,l,bits;
272254721Semaste
273263367Semaste		len=BN_num_bytes(dh->p);
274263367Semaste		bits=BN_num_bits(dh->p);
275263367Semaste		data=(unsigned char *)OPENSSL_malloc(len);
276263367Semaste		if (data == NULL)
277263367Semaste			{
278254721Semaste			perror("OPENSSL_malloc");
279254721Semaste			goto end;
280263363Semaste			}
281254721Semaste		l=BN_bn2bin(dh->p,data);
282254721Semaste		printf("static unsigned char dh%d_p[]={",bits);
283263363Semaste		for (i=0; i<l; i++)
284263363Semaste			{
285263363Semaste			if ((i%12) == 0) printf("\n\t");
286254721Semaste			printf("0x%02X,",data[i]);
287254721Semaste			}
288254721Semaste		printf("\n\t};\n");
289254721Semaste
290263367Semaste		l=BN_bn2bin(dh->g,data);
291263367Semaste		printf("static unsigned char dh%d_g[]={",bits);
292263367Semaste		for (i=0; i<l; i++)
293263367Semaste			{
294263367Semaste			if ((i%12) == 0) printf("\n\t");
295263367Semaste			printf("0x%02X,",data[i]);
296263367Semaste			}
297263367Semaste		printf("\n\t};\n\n");
298263367Semaste
299254721Semaste		printf("DH *get_dh%d()\n\t{\n",bits);
300254721Semaste		printf("\tDH *dh;\n\n");
301254721Semaste		printf("\tif ((dh=DH_new()) == NULL) return(NULL);\n");
302254721Semaste		printf("\tdh->p=BN_bin2bn(dh%d_p,sizeof(dh%d_p),NULL);\n",
303254721Semaste			bits,bits);
304254721Semaste		printf("\tdh->g=BN_bin2bn(dh%d_g,sizeof(dh%d_g),NULL);\n",
305254721Semaste			bits,bits);
306254721Semaste		printf("\tif ((dh->p == NULL) || (dh->g == NULL))\n");
307254721Semaste		printf("\t\treturn(NULL);\n");
308254721Semaste		printf("\treturn(dh);\n\t}\n");
309269024Semaste		OPENSSL_free(data);
310269024Semaste		}
311269024Semaste
312269024Semaste
313254721Semaste	if (!noout)
314254721Semaste		{
315254721Semaste		if 	(outformat == FORMAT_ASN1)
316254721Semaste			i=i2d_DHparams_bio(out,dh);
317263363Semaste		else if (outformat == FORMAT_PEM)
318263363Semaste			i=PEM_write_bio_DHparams(out,dh);
319263363Semaste		else	{
320263363Semaste			BIO_printf(bio_err,"bad output format specified for outfile\n");
321263363Semaste			goto end;
322263363Semaste			}
323263363Semaste		if (!i)
324263363Semaste			{
325263363Semaste			BIO_printf(bio_err,"unable to write DH parameters\n");
326263363Semaste			ERR_print_errors(bio_err);
327263363Semaste			goto end;
328263367Semaste			}
329263363Semaste		}
330263363Semaste	ret=0;
331263363Semasteend:
332263363Semaste	if (in != NULL) BIO_free(in);
333263363Semaste	if (out != NULL) BIO_free_all(out);
334263363Semaste	if (dh != NULL) DH_free(dh);
335263363Semaste	apps_shutdown();
336263363Semaste	OPENSSL_EXIT(ret);
337263363Semaste	}
338263363Semaste#endif
339263363Semaste