dsaparam.c revision 59191
1139823Simp/* apps/dsaparam.c */
21541Srgrimes/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
31541Srgrimes * All rights reserved.
41541Srgrimes *
51541Srgrimes * This package is an SSL implementation written
61541Srgrimes * by Eric Young (eay@cryptsoft.com).
71541Srgrimes * The implementation was written so as to conform with Netscapes SSL.
81541Srgrimes *
91541Srgrimes * This library is free for commercial and non-commercial use as long as
101541Srgrimes * the following conditions are aheared to.  The following conditions
111541Srgrimes * apply to all code found in this distribution, be it the RC4, RSA,
121541Srgrimes * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
131541Srgrimes * included with this distribution is covered by the same copyright terms
141541Srgrimes * except that the holder is Tim Hudson (tjh@cryptsoft.com).
151541Srgrimes *
161541Srgrimes * Copyright remains Eric Young's, and as such any Copyright notices in
171541Srgrimes * the code are not to be removed.
181541Srgrimes * If this package is used in a product, Eric Young should be given attribution
191541Srgrimes * as the author of the parts of the library used.
201541Srgrimes * This can be in the form of a textual message at program startup or
211541Srgrimes * in documentation (online or textual) provided with the package.
221541Srgrimes *
231541Srgrimes * Redistribution and use in source and binary forms, with or without
241541Srgrimes * modification, are permitted provided that the following conditions
251541Srgrimes * are met:
261541Srgrimes * 1. Redistributions of source code must retain the copyright
271541Srgrimes *    notice, this list of conditions and the following disclaimer.
281541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
291541Srgrimes *    notice, this list of conditions and the following disclaimer in the
301541Srgrimes *    documentation and/or other materials provided with the distribution.
311541Srgrimes * 3. All advertising materials mentioning features or use of this software
321541Srgrimes *    must display the following acknowledgement:
331541Srgrimes *    "This product includes cryptographic software written by
341541Srgrimes *     Eric Young (eay@cryptsoft.com)"
3517679Spst *    The word 'cryptographic' can be left out if the rouines from the library
361541Srgrimes *    being used are not cryptographic related :-).
3750477Speter * 4. If you include any Windows specific code (or a derivative thereof) from
381541Srgrimes *    the apps directory (application code) you must include an acknowledgement:
391541Srgrimes *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
402168Spaul *
412168Spaul * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
422168Spaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4317679Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4417679Spst * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4517679Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4617679Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4717679Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4817679Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
491541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
508876Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
518876Srgrimes * SUCH DAMAGE.
521541Srgrimes *
5339963Salex * The licence and distribution terms for any publically available version or
541541Srgrimes * derivative of this code cannot be changed.  i.e. this code cannot simply be
551541Srgrimes * copied and put under another distribution licence
561541Srgrimes * [including the GNU Public Licence.]
5756057Sphk */
581541Srgrimes
591541Srgrimes#ifndef NO_DSA
601541Srgrimes#include <assert.h>
611541Srgrimes#include <stdio.h>
621541Srgrimes#include <stdlib.h>
631541Srgrimes#include <time.h>
641541Srgrimes#include <string.h>
651541Srgrimes#include "apps.h"
661541Srgrimes#include <openssl/bio.h>
678876Srgrimes#include <openssl/err.h>
681541Srgrimes#include <openssl/bn.h>
691541Srgrimes#include <openssl/dsa.h>
701541Srgrimes#include <openssl/x509.h>
711541Srgrimes#include <openssl/pem.h>
721541Srgrimes
731541Srgrimes#undef PROG
741541Srgrimes#define PROG	dsaparam_main
751541Srgrimes
761541Srgrimes/* -inform arg	- input format - default PEM (DER or PEM)
778876Srgrimes * -outform arg - output format - default PEM
781541Srgrimes * -in arg	- input file - default stdin
791541Srgrimes * -out arg	- output file - default stdout
801541Srgrimes * -noout
811541Srgrimes * -text
821541Srgrimes * -C
831541Srgrimes * -noout
841541Srgrimes * -genkey
851541Srgrimes */
861541Srgrimes
871541Srgrimesstatic void MS_CALLBACK dsa_cb(int p, int n, void *arg);
881541Srgrimes
891541Srgrimesint MAIN(int, char **);
901541Srgrimes
9117679Spstint MAIN(int argc, char **argv)
921541Srgrimes	{
931541Srgrimes	DSA *dsa=NULL;
941541Srgrimes	int i,badops=0,text=0;
951541Srgrimes	BIO *in=NULL,*out=NULL;
961541Srgrimes	int informat,outformat,noout=0,C=0,ret=1;
971541Srgrimes	char *infile,*outfile,*prog,*inrand=NULL;
981541Srgrimes	int numbits= -1,num,genkey=0;
991541Srgrimes	int need_rand=0;
1001541Srgrimes
1011541Srgrimes	apps_startup();
1021541Srgrimes
1031541Srgrimes	if (bio_err == NULL)
1041541Srgrimes		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
1051541Srgrimes			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
1061541Srgrimes
1071541Srgrimes	infile=NULL;
1089235Spst	outfile=NULL;
1099235Spst	informat=FORMAT_PEM;
11052248Smsmith	outformat=FORMAT_PEM;
11152248Smsmith
11258192Srwatson	prog=argv[0];
11358192Srwatson	argc--;
114109580Ssam	argv++;
115109580Ssam	while (argc >= 1)
1161541Srgrimes		{
1171541Srgrimes		if 	(strcmp(*argv,"-inform") == 0)
1181541Srgrimes			{
1191541Srgrimes			if (--argc < 1) goto bad;
1201541Srgrimes			informat=str2fmt(*(++argv));
1211541Srgrimes			}
12217679Spst		else if (strcmp(*argv,"-outform") == 0)
12317679Spst			{
1241541Srgrimes			if (--argc < 1) goto bad;
1251541Srgrimes			outformat=str2fmt(*(++argv));
1261541Srgrimes			}
1271541Srgrimes		else if (strcmp(*argv,"-in") == 0)
1281541Srgrimes			{
1291541Srgrimes			if (--argc < 1) goto bad;
1301541Srgrimes			infile= *(++argv);
1311541Srgrimes			}
13255205Speter		else if (strcmp(*argv,"-out") == 0)
13337619Sbde			{
13437619Sbde			if (--argc < 1) goto bad;
1351541Srgrimes			outfile= *(++argv);
1361541Srgrimes			}
1371541Srgrimes		else if (strcmp(*argv,"-text") == 0)
1381541Srgrimes			text=1;
1391541Srgrimes		else if (strcmp(*argv,"-C") == 0)
140129874Sdwmalone			C=1;
1411541Srgrimes		else if (strcmp(*argv,"-genkey") == 0)
1421541Srgrimes			{
1431541Srgrimes			genkey=1;
1441541Srgrimes			need_rand=1;
1451541Srgrimes			}
1461541Srgrimes		else if (strcmp(*argv,"-rand") == 0)
1471541Srgrimes			{
1481541Srgrimes			if (--argc < 1) goto bad;
1491541Srgrimes			inrand= *(++argv);
1501541Srgrimes			need_rand=1;
15117679Spst			}
15238423Sache		else if (strcmp(*argv,"-noout") == 0)
1531541Srgrimes			noout=1;
1541541Srgrimes		else if (sscanf(*argv,"%d",&num) == 1)
15580767Sfenner			{
15680767Sfenner			/* generate a key */
15780767Sfenner			numbits=num;
15880767Sfenner			need_rand=1;
15980767Sfenner			}
16080767Sfenner		else
16180767Sfenner			{
16280767Sfenner			BIO_printf(bio_err,"unknown option %s\n",*argv);
16380767Sfenner			badops=1;
16480767Sfenner			break;
16580767Sfenner			}
16680767Sfenner		argc--;
16780767Sfenner		argv++;
16880767Sfenner		}
16980767Sfenner
17080767Sfenner	if (badops)
17180767Sfenner		{
17280767Sfennerbad:
17398540Sfenner		BIO_printf(bio_err,"%s [options] [bits] <infile >outfile\n",prog);
17498540Sfenner		BIO_printf(bio_err,"where options are\n");
17598540Sfenner		BIO_printf(bio_err," -inform arg   input format - DER or PEM\n");
17680767Sfenner		BIO_printf(bio_err," -outform arg  output format - DER or PEM\n");
17780767Sfenner		BIO_printf(bio_err," -in arg       input file\n");
17898540Sfenner		BIO_printf(bio_err," -out arg      output file\n");
17980767Sfenner		BIO_printf(bio_err," -text         print the key in text\n");
18080767Sfenner		BIO_printf(bio_err," -C            Output C code\n");
181127674Sbms		BIO_printf(bio_err," -noout        no output\n");
182127674Sbms		BIO_printf(bio_err," -rand         files to use for random number input\n");
183127674Sbms		BIO_printf(bio_err," number        number of bits to use for generating private key\n");
184127674Sbms		goto end;
185127674Sbms		}
186127674Sbms
18780767Sfenner	ERR_load_crypto_strings();
18880767Sfenner
18980767Sfenner	in=BIO_new(BIO_s_file());
19080767Sfenner	out=BIO_new(BIO_s_file());
19180767Sfenner	if ((in == NULL) || (out == NULL))
19280767Sfenner		{
19380767Sfenner		ERR_print_errors(bio_err);
19480767Sfenner		goto end;
19580767Sfenner		}
19680767Sfenner
19780767Sfenner	if (infile == NULL)
19880767Sfenner		BIO_set_fp(in,stdin,BIO_NOCLOSE);
19980767Sfenner	else
20080767Sfenner		{
20180767Sfenner		if (BIO_read_filename(in,infile) <= 0)
20280767Sfenner			{
20380767Sfenner			perror(infile);
20480767Sfenner			goto end;
20580767Sfenner			}
20680767Sfenner		}
20780767Sfenner	if (outfile == NULL)
20880767Sfenner		BIO_set_fp(out,stdout,BIO_NOCLOSE);
20980767Sfenner	else
21080767Sfenner		{
21180767Sfenner		if (BIO_write_filename(out,outfile) <= 0)
212127673Sbms			{
213127673Sbms			perror(outfile);
214127673Sbms			goto end;
215127673Sbms			}
216127673Sbms		}
217127673Sbms
218127673Sbms	if (need_rand)
219127673Sbms		{
22080767Sfenner		app_RAND_load_file(NULL, bio_err, (inrand != NULL));
22180767Sfenner		if (inrand != NULL)
22280767Sfenner			BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
22380767Sfenner				app_RAND_load_files(inrand));
22480767Sfenner		}
22580767Sfenner
22698540Sfenner	if (numbits > 0)
22780767Sfenner		{
22880767Sfenner		assert(need_rand);
22980767Sfenner		BIO_printf(bio_err,"Generating DSA parameters, %d bit long prime\n",num);
23080767Sfenner	        BIO_printf(bio_err,"This could take some time\n");
23180767Sfenner	        dsa=DSA_generate_parameters(num,NULL,0,NULL,NULL, dsa_cb,bio_err);
23280767Sfenner		}
23380767Sfenner	else if	(informat == FORMAT_ASN1)
23480767Sfenner		dsa=d2i_DSAparams_bio(in,NULL);
23580767Sfenner	else if (informat == FORMAT_PEM)
23680767Sfenner		dsa=PEM_read_bio_DSAparams(in,NULL,NULL,NULL);
237127673Sbms	else
238127673Sbms		{
239127673Sbms		BIO_printf(bio_err,"bad input format specified\n");
240127673Sbms		goto end;
241127673Sbms		}
242127673Sbms	if (dsa == NULL)
243127673Sbms		{
24480767Sfenner		BIO_printf(bio_err,"unable to load DSA parameters\n");
24580767Sfenner		ERR_print_errors(bio_err);
24680767Sfenner		goto end;
24780767Sfenner		}
24880767Sfenner
24998540Sfenner	if (text)
25098540Sfenner		{
25198540Sfenner		DSAparams_print(out,dsa);
25298540Sfenner		}
25398540Sfenner
25498540Sfenner	if (C)
25598540Sfenner		{
25698540Sfenner		unsigned char *data;
25798540Sfenner		int l,len,bits_p,bits_q,bits_g;
25898540Sfenner
25998540Sfenner		len=BN_num_bytes(dsa->p);
26098540Sfenner		bits_p=BN_num_bits(dsa->p);
26198540Sfenner		bits_q=BN_num_bits(dsa->q);
26298540Sfenner		bits_g=BN_num_bits(dsa->g);
26398540Sfenner		data=(unsigned char *)Malloc(len+20);
26498540Sfenner		if (data == NULL)
26598540Sfenner			{
26698540Sfenner			perror("Malloc");
26798540Sfenner			goto end;
26898540Sfenner			}
26998540Sfenner		l=BN_bn2bin(dsa->p,data);
27098540Sfenner		printf("static unsigned char dsa%d_p[]={",bits_p);
27198540Sfenner		for (i=0; i<l; i++)
27298540Sfenner			{
27398540Sfenner			if ((i%12) == 0) printf("\n\t");
27498540Sfenner			printf("0x%02X,",data[i]);
27598540Sfenner			}
27698540Sfenner		printf("\n\t};\n");
27798540Sfenner
27898540Sfenner		l=BN_bn2bin(dsa->q,data);
27998540Sfenner		printf("static unsigned char dsa%d_q[]={",bits_p);
28098540Sfenner		for (i=0; i<l; i++)
28198540Sfenner			{
28298540Sfenner			if ((i%12) == 0) printf("\n\t");
28398540Sfenner			printf("0x%02X,",data[i]);
28498540Sfenner			}
28598540Sfenner		printf("\n\t};\n");
28698540Sfenner
28798540Sfenner		l=BN_bn2bin(dsa->g,data);
28898540Sfenner		printf("static unsigned char dsa%d_g[]={",bits_p);
28998540Sfenner		for (i=0; i<l; i++)
290127673Sbms			{
291127673Sbms			if ((i%12) == 0) printf("\n\t");
292127673Sbms			printf("0x%02X,",data[i]);
293127673Sbms			}
294127673Sbms		printf("\n\t};\n\n");
295127674Sbms
296127674Sbms		printf("DSA *get_dsa%d()\n\t{\n",bits_p);
297127674Sbms		printf("\tDSA *dsa;\n\n");
298127674Sbms		printf("\tif ((dsa=DSA_new()) == NULL) return(NULL);\n");
299127674Sbms		printf("\tdsa->p=BN_bin2bn(dsa%d_p,sizeof(dsa%d_p),NULL);\n",
300127673Sbms			bits_p,bits_p);
301127673Sbms		printf("\tdsa->q=BN_bin2bn(dsa%d_q,sizeof(dsa%d_q),NULL);\n",
302127673Sbms			bits_p,bits_p);
303127673Sbms		printf("\tdsa->g=BN_bin2bn(dsa%d_g,sizeof(dsa%d_g),NULL);\n",
304127673Sbms			bits_p,bits_p);
305127673Sbms		printf("\tif ((dsa->p == NULL) || (dsa->q == NULL) || (dsa->g == NULL))\n");
306127673Sbms		printf("\t\treturn(NULL);\n");
307127673Sbms		printf("\treturn(dsa);\n\t}\n");
308127673Sbms		}
309127673Sbms
310127674Sbms
311127674Sbms	if (!noout)
312127674Sbms		{
313127674Sbms		if 	(outformat == FORMAT_ASN1)
314127674Sbms			i=i2d_DSAparams_bio(out,dsa);
315127674Sbms		else if (outformat == FORMAT_PEM)
316127674Sbms			i=PEM_write_bio_DSAparams(out,dsa);
317127674Sbms		else	{
318127673Sbms			BIO_printf(bio_err,"bad output format specified for outfile\n");
319127673Sbms			goto end;
320127673Sbms			}
321127673Sbms		if (!i)
322127673Sbms			{
323127673Sbms			BIO_printf(bio_err,"unable to write DSA parameters\n");
324127673Sbms			ERR_print_errors(bio_err);
325127673Sbms			goto end;
326127674Sbms			}
327127674Sbms		}
328127674Sbms	if (genkey)
329127674Sbms		{
330127674Sbms		DSA *dsakey;
331127673Sbms
332127673Sbms		assert(need_rand);
333127673Sbms		if ((dsakey=DSAparams_dup(dsa)) == NULL) goto end;
334127673Sbms		if (!DSA_generate_key(dsakey)) goto end;
335127673Sbms		if 	(outformat == FORMAT_ASN1)
336127674Sbms			i=i2d_DSAPrivateKey_bio(out,dsakey);
337127674Sbms		else if (outformat == FORMAT_PEM)
338127674Sbms			i=PEM_write_bio_DSAPrivateKey(out,dsakey,NULL,NULL,0,NULL,NULL);
339127674Sbms		else	{
340127674Sbms			BIO_printf(bio_err,"bad output format specified for outfile\n");
341127674Sbms			goto end;
342127674Sbms			}
343127674Sbms		DSA_free(dsakey);
344127674Sbms		}
345127674Sbms	if (need_rand)
346127674Sbms		app_RAND_write_file(NULL, bio_err);
347127674Sbms	ret=0;
348146729Ssamend:
349146729Ssam	if (in != NULL) BIO_free(in);
350146729Ssam	if (out != NULL) BIO_free(out);
351146729Ssam	if (dsa != NULL) DSA_free(dsa);
352146729Ssam	EXIT(ret);
353146729Ssam	}
354146729Ssam
355146729Ssamstatic void MS_CALLBACK dsa_cb(int p, int n, void *arg)
356146729Ssam	{
357146729Ssam	char c='*';
358146729Ssam
359146729Ssam	if (p == 0) c='.';
360146729Ssam	if (p == 1) c='+';
361127673Sbms	if (p == 2) c='*';
362127673Sbms	if (p == 3) c='\n';
363127673Sbms	BIO_write(arg,&c,1);
364127673Sbms	(void)BIO_flush(arg);
365147893Ssam#ifdef LINT
366147893Ssam	p=n;
367146729Ssam#endif
368147893Ssam	}
369147893Ssam#endif
370147893Ssam