dsaparam.c revision 109998
11553Srgrimes/* apps/dsaparam.c */
21553Srgrimes/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
31553Srgrimes * All rights reserved.
41553Srgrimes *
51553Srgrimes * This package is an SSL implementation written
61553Srgrimes * by Eric Young (eay@cryptsoft.com).
71553Srgrimes * The implementation was written so as to conform with Netscapes SSL.
81553Srgrimes *
91553Srgrimes * This library is free for commercial and non-commercial use as long as
101553Srgrimes * the following conditions are aheared to.  The following conditions
111553Srgrimes * apply to all code found in this distribution, be it the RC4, RSA,
121553Srgrimes * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
131553Srgrimes * included with this distribution is covered by the same copyright terms
141553Srgrimes * except that the holder is Tim Hudson (tjh@cryptsoft.com).
151553Srgrimes *
161553Srgrimes * Copyright remains Eric Young's, and as such any Copyright notices in
171553Srgrimes * the code are not to be removed.
181553Srgrimes * If this package is used in a product, Eric Young should be given attribution
191553Srgrimes * as the author of the parts of the library used.
201553Srgrimes * This can be in the form of a textual message at program startup or
211553Srgrimes * in documentation (online or textual) provided with the package.
221553Srgrimes *
231553Srgrimes * Redistribution and use in source and binary forms, with or without
241553Srgrimes * modification, are permitted provided that the following conditions
251553Srgrimes * are met:
261553Srgrimes * 1. Redistributions of source code must retain the copyright
271553Srgrimes *    notice, this list of conditions and the following disclaimer.
281553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
291553Srgrimes *    notice, this list of conditions and the following disclaimer in the
301553Srgrimes *    documentation and/or other materials provided with the distribution.
311553Srgrimes * 3. All advertising materials mentioning features or use of this software
321553Srgrimes *    must display the following acknowledgement:
331553Srgrimes *    "This product includes cryptographic software written by
341553Srgrimes *     Eric Young (eay@cryptsoft.com)"
351553Srgrimes *    The word 'cryptographic' can be left out if the rouines from the library
3631492Swollman *    being used are not cryptographic related :-).
371553Srgrimes * 4. If you include any Windows specific code (or a derivative thereof) from
381553Srgrimes *    the apps directory (application code) you must include an acknowledgement:
391553Srgrimes *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
401553Srgrimes *
411553Srgrimes * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4231492Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4315648Sjoerg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4431492Swollman * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4531492Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4650479Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
471553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
481553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
491553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
501553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
511553Srgrimes * SUCH DAMAGE.
521553Srgrimes *
531553Srgrimes * The licence and distribution terms for any publically available version or
541553Srgrimes * derivative of this code cannot be changed.  i.e. this code cannot simply be
551553Srgrimes * copied and put under another distribution licence
561553Srgrimes * [including the GNU Public Licence.]
571553Srgrimes */
581553Srgrimes
591553Srgrimes#ifndef OPENSSL_NO_DSA
601553Srgrimes#include <assert.h>
611553Srgrimes#include <stdio.h>
621553Srgrimes#include <stdlib.h>
631553Srgrimes#include <time.h>
641553Srgrimes#include <string.h>
651553Srgrimes#include "apps.h"
661553Srgrimes#include <openssl/bio.h>
671553Srgrimes#include <openssl/err.h>
681553Srgrimes#include <openssl/bn.h>
691553Srgrimes#include <openssl/dsa.h>
701553Srgrimes#include <openssl/x509.h>
711553Srgrimes#include <openssl/pem.h>
7215032Ssef
7315032Ssef#undef PROG
7415703Sjoerg#define PROG	dsaparam_main
751553Srgrimes
761553Srgrimes/* -inform arg	- input format - default PEM (DER or PEM)
771553Srgrimes * -outform arg - output format - default PEM
781553Srgrimes * -in arg	- input file - default stdin
791553Srgrimes * -out arg	- output file - default stdout
801553Srgrimes * -noout
811553Srgrimes * -text
821553Srgrimes * -C
831553Srgrimes * -noout
841553Srgrimes * -genkey
851553Srgrimes */
861553Srgrimes
871553Srgrimesstatic void MS_CALLBACK dsa_cb(int p, int n, void *arg);
881553Srgrimes
891553Srgrimesint MAIN(int, char **);
901553Srgrimes
911553Srgrimesint MAIN(int argc, char **argv)
921553Srgrimes	{
931553Srgrimes	ENGINE *e = NULL;
941553Srgrimes	DSA *dsa=NULL;
951553Srgrimes	int i,badops=0,text=0;
961553Srgrimes	BIO *in=NULL,*out=NULL;
971553Srgrimes	int informat,outformat,noout=0,C=0,ret=1;
9868253Sgad	char *infile,*outfile,*prog,*inrand=NULL;
991553Srgrimes	int numbits= -1,num,genkey=0;
1001553Srgrimes	int need_rand=0;
1011553Srgrimes	char *engine=NULL;
10224831Sbrian
1031553Srgrimes	apps_startup();
1041553Srgrimes
1051553Srgrimes	if (bio_err == NULL)
1061553Srgrimes		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
10753956Sache			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
1081553Srgrimes
1091553Srgrimes	if (!load_config(bio_err, NULL))
11078300Sgad		goto end;
1111553Srgrimes
1128857Srgrimes	infile=NULL;
1131553Srgrimes	outfile=NULL;
1141553Srgrimes	informat=FORMAT_PEM;
1151553Srgrimes	outformat=FORMAT_PEM;
1161553Srgrimes
1171553Srgrimes	prog=argv[0];
11868664Sgad	argc--;
11968664Sgad	argv++;
1201553Srgrimes	while (argc >= 1)
12124831Sbrian		{
12224831Sbrian		if 	(strcmp(*argv,"-inform") == 0)
1231553Srgrimes			{
12478146Sgad			if (--argc < 1) goto bad;
12578146Sgad			informat=str2fmt(*(++argv));
12678146Sgad			}
12778146Sgad		else if (strcmp(*argv,"-outform") == 0)
12878146Sgad			{
12978146Sgad			if (--argc < 1) goto bad;
13078146Sgad			outformat=str2fmt(*(++argv));
13178146Sgad			}
13278146Sgad		else if (strcmp(*argv,"-in") == 0)
13378146Sgad			{
13478146Sgad			if (--argc < 1) goto bad;
13578146Sgad			infile= *(++argv);
13678146Sgad			}
13778146Sgad		else if (strcmp(*argv,"-out") == 0)
13878146Sgad			{
13978146Sgad			if (--argc < 1) goto bad;
14078146Sgad			outfile= *(++argv);
14178146Sgad			}
14278146Sgad		else if(strcmp(*argv, "-engine") == 0)
14378146Sgad			{
14478146Sgad			if (--argc < 1) goto bad;
14578146Sgad			engine = *(++argv);
1461553Srgrimes			}
1471553Srgrimes		else if (strcmp(*argv,"-text") == 0)
14878146Sgad			text=1;
1491553Srgrimes		else if (strcmp(*argv,"-C") == 0)
1501553Srgrimes			C=1;
15168401Sgad		else if (strcmp(*argv,"-genkey") == 0)
15268401Sgad			{
1531553Srgrimes			genkey=1;
15468733Sgad			need_rand=1;
15568733Sgad			}
1561553Srgrimes		else if (strcmp(*argv,"-rand") == 0)
15768733Sgad			{
15831492Swollman			if (--argc < 1) goto bad;
15931492Swollman			inrand= *(++argv);
1601553Srgrimes			need_rand=1;
16131492Swollman			}
16231492Swollman		else if (strcmp(*argv,"-noout") == 0)
1631553Srgrimes			noout=1;
1641553Srgrimes		else if (sscanf(*argv,"%d",&num) == 1)
1651553Srgrimes			{
1661553Srgrimes			/* generate a key */
1671553Srgrimes			numbits=num;
16879735Sgad			need_rand=1;
16979735Sgad			}
17079735Sgad		else
17179735Sgad			{
17279735Sgad			BIO_printf(bio_err,"unknown option %s\n",*argv);
17379735Sgad			badops=1;
17479735Sgad			break;
17579735Sgad			}
1761553Srgrimes		argc--;
1771553Srgrimes		argv++;
1781553Srgrimes		}
1791553Srgrimes
1801553Srgrimes	if (badops)
1811553Srgrimes		{
1821553Srgrimesbad:
1831553Srgrimes		BIO_printf(bio_err,"%s [options] [bits] <infile >outfile\n",prog);
18431492Swollman		BIO_printf(bio_err,"where options are\n");
18531492Swollman		BIO_printf(bio_err," -inform arg   input format - DER or PEM\n");
1861553Srgrimes		BIO_printf(bio_err," -outform arg  output format - DER or PEM\n");
1871553Srgrimes		BIO_printf(bio_err," -in arg       input file\n");
18831492Swollman		BIO_printf(bio_err," -out arg      output file\n");
1891553Srgrimes		BIO_printf(bio_err," -text         print as text\n");
19031492Swollman		BIO_printf(bio_err," -C            Output C code\n");
19131492Swollman		BIO_printf(bio_err," -noout        no output\n");
1921553Srgrimes		BIO_printf(bio_err," -genkey       generate a DSA key\n");
19331492Swollman		BIO_printf(bio_err," -rand         files to use for random number input\n");
19431492Swollman		BIO_printf(bio_err," -engine e     use engine e, possibly a hardware device.\n");
19531492Swollman		BIO_printf(bio_err," number        number of bits to use for generating private key\n");
1961553Srgrimes		goto end;
1971553Srgrimes		}
19831492Swollman
19931492Swollman	ERR_load_crypto_strings();
20031492Swollman
2011553Srgrimes	in=BIO_new(BIO_s_file());
2021553Srgrimes	out=BIO_new(BIO_s_file());
2031553Srgrimes	if ((in == NULL) || (out == NULL))
2041553Srgrimes		{
2051553Srgrimes		ERR_print_errors(bio_err);
2061553Srgrimes		goto end;
2071553Srgrimes		}
2081553Srgrimes
2091553Srgrimes	if (infile == NULL)
21031492Swollman		BIO_set_fp(in,stdin,BIO_NOCLOSE);
2111553Srgrimes	else
2121553Srgrimes		{
2131553Srgrimes		if (BIO_read_filename(in,infile) <= 0)
2141553Srgrimes			{
2151553Srgrimes			perror(infile);
21631492Swollman			goto end;
21731492Swollman			}
21831492Swollman		}
2191553Srgrimes	if (outfile == NULL)
2201553Srgrimes		{
2211553Srgrimes		BIO_set_fp(out,stdout,BIO_NOCLOSE);
2221553Srgrimes#ifdef OPENSSL_SYS_VMS
22331492Swollman		{
22431492Swollman		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
22531492Swollman		out = BIO_push(tmpbio, out);
22631492Swollman		}
2271553Srgrimes#endif
22868664Sgad		}
22968664Sgad	else
23068664Sgad		{
23168664Sgad		if (BIO_write_filename(out,outfile) <= 0)
23268664Sgad			{
23368732Sgad			perror(outfile);
23468664Sgad			goto end;
23568664Sgad			}
23668664Sgad		}
23768664Sgad
23868732Sgad        e = setup_engine(bio_err, engine, 0);
23968664Sgad
24068664Sgad	if (need_rand)
24168664Sgad		{
24268664Sgad		app_RAND_load_file(NULL, bio_err, (inrand != NULL));
24331492Swollman		if (inrand != NULL)
2441553Srgrimes			BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
2451553Srgrimes				app_RAND_load_files(inrand));
2461553Srgrimes		}
2471553Srgrimes
2481553Srgrimes	if (numbits > 0)
2491553Srgrimes		{
2501553Srgrimes		assert(need_rand);
2511553Srgrimes		BIO_printf(bio_err,"Generating DSA parameters, %d bit long prime\n",num);
25268401Sgad	        BIO_printf(bio_err,"This could take some time\n");
2531553Srgrimes	        dsa=DSA_generate_parameters(num,NULL,0,NULL,NULL, dsa_cb,bio_err);
25415648Sjoerg		}
2551553Srgrimes	else if	(informat == FORMAT_ASN1)
25615648Sjoerg		dsa=d2i_DSAparams_bio(in,NULL);
25768401Sgad	else if (informat == FORMAT_PEM)
2581553Srgrimes		dsa=PEM_read_bio_DSAparams(in,NULL,NULL,NULL);
2591553Srgrimes	else
26031492Swollman		{
26131492Swollman		BIO_printf(bio_err,"bad input format specified\n");
26231492Swollman		goto end;
26368401Sgad		}
2641553Srgrimes	if (dsa == NULL)
26568401Sgad		{
2661553Srgrimes		BIO_printf(bio_err,"unable to load DSA parameters\n");
2671553Srgrimes		ERR_print_errors(bio_err);
2681553Srgrimes		goto end;
2691553Srgrimes		}
2701553Srgrimes
2711553Srgrimes	if (text)
27231492Swollman		{
2731553Srgrimes		DSAparams_print(out,dsa);
2741553Srgrimes		}
27531492Swollman
27631492Swollman	if (C)
2771553Srgrimes		{
27831492Swollman		unsigned char *data;
27931492Swollman		int l,len,bits_p,bits_q,bits_g;
2801553Srgrimes
28131492Swollman		len=BN_num_bytes(dsa->p);
2821553Srgrimes		bits_p=BN_num_bits(dsa->p);
2831553Srgrimes		bits_q=BN_num_bits(dsa->q);
2841553Srgrimes		bits_g=BN_num_bits(dsa->g);
28568733Sgad		data=(unsigned char *)OPENSSL_malloc(len+20);
28668733Sgad		if (data == NULL)
28715648Sjoerg			{
28815648Sjoerg			perror("OPENSSL_malloc");
28931492Swollman			goto end;
2901553Srgrimes			}
2911553Srgrimes		l=BN_bn2bin(dsa->p,data);
2921553Srgrimes		printf("static unsigned char dsa%d_p[]={",bits_p);
29315648Sjoerg		for (i=0; i<l; i++)
2941553Srgrimes			{
29579735Sgad			if ((i%12) == 0) printf("\n\t");
29679735Sgad			printf("0x%02X,",data[i]);
29779735Sgad			}
2981553Srgrimes		printf("\n\t};\n");
2991553Srgrimes
3001553Srgrimes		l=BN_bn2bin(dsa->q,data);
3011553Srgrimes		printf("static unsigned char dsa%d_q[]={",bits_p);
30231492Swollman		for (i=0; i<l; i++)
30331492Swollman			{
30431492Swollman			if ((i%12) == 0) printf("\n\t");
3051553Srgrimes			printf("0x%02X,",data[i]);
30615648Sjoerg			}
30731492Swollman		printf("\n\t};\n");
30831492Swollman
30931492Swollman		l=BN_bn2bin(dsa->g,data);
31068401Sgad		printf("static unsigned char dsa%d_g[]={",bits_p);
31115648Sjoerg		for (i=0; i<l; i++)
31227748Simp			{
31368401Sgad			if ((i%12) == 0) printf("\n\t");
31468401Sgad			printf("0x%02X,",data[i]);
31568401Sgad			}
31615648Sjoerg		printf("\n\t};\n\n");
31731492Swollman
31815648Sjoerg		printf("DSA *get_dsa%d()\n\t{\n",bits_p);
3191553Srgrimes		printf("\tDSA *dsa;\n\n");
3201553Srgrimes		printf("\tif ((dsa=DSA_new()) == NULL) return(NULL);\n");
32131492Swollman		printf("\tdsa->p=BN_bin2bn(dsa%d_p,sizeof(dsa%d_p),NULL);\n",
3221553Srgrimes			bits_p,bits_p);
3231553Srgrimes		printf("\tdsa->q=BN_bin2bn(dsa%d_q,sizeof(dsa%d_q),NULL);\n",
3241553Srgrimes			bits_p,bits_p);
32531492Swollman		printf("\tdsa->g=BN_bin2bn(dsa%d_g,sizeof(dsa%d_g),NULL);\n",
32631492Swollman			bits_p,bits_p);
32731492Swollman		printf("\tif ((dsa->p == NULL) || (dsa->q == NULL) || (dsa->g == NULL))\n");
3281553Srgrimes		printf("\t\t{ DSA_free(dsa); return(NULL); }\n");
3291553Srgrimes		printf("\treturn(dsa);\n\t}\n");
3301553Srgrimes		}
3311553Srgrimes
33268733Sgad
33331492Swollman	if (!noout)
33431492Swollman		{
33531492Swollman		if 	(outformat == FORMAT_ASN1)
33631492Swollman			i=i2d_DSAparams_bio(out,dsa);
33731492Swollman		else if (outformat == FORMAT_PEM)
33831492Swollman			i=PEM_write_bio_DSAparams(out,dsa);
3391553Srgrimes		else	{
34019202Simp			BIO_printf(bio_err,"bad output format specified for outfile\n");
34119202Simp			goto end;
34268664Sgad			}
3431553Srgrimes		if (!i)
3441553Srgrimes			{
3451553Srgrimes			BIO_printf(bio_err,"unable to write DSA parameters\n");
3461553Srgrimes			ERR_print_errors(bio_err);
3471553Srgrimes			goto end;
3481553Srgrimes			}
3491553Srgrimes		}
3501553Srgrimes	if (genkey)
3511553Srgrimes		{
3521553Srgrimes		DSA *dsakey;
3531553Srgrimes
3541553Srgrimes		assert(need_rand);
3551553Srgrimes		if ((dsakey=DSAparams_dup(dsa)) == NULL) goto end;
3561553Srgrimes		if (!DSA_generate_key(dsakey)) goto end;
3571553Srgrimes		if 	(outformat == FORMAT_ASN1)
3581553Srgrimes			i=i2d_DSAPrivateKey_bio(out,dsakey);
3591553Srgrimes		else if (outformat == FORMAT_PEM)
3601553Srgrimes			i=PEM_write_bio_DSAPrivateKey(out,dsakey,NULL,NULL,0,NULL,NULL);
3611553Srgrimes		else	{
36278146Sgad			BIO_printf(bio_err,"bad output format specified for outfile\n");
3631553Srgrimes			goto end;
3641553Srgrimes			}
36568734Sgad		DSA_free(dsakey);
36668734Sgad		}
3671553Srgrimes	if (need_rand)
36868734Sgad		app_RAND_write_file(NULL, bio_err);
36968734Sgad	ret=0;
3701553Srgrimesend:
3711553Srgrimes	if (in != NULL) BIO_free(in);
3721553Srgrimes	if (out != NULL) BIO_free_all(out);
3731553Srgrimes	if (dsa != NULL) DSA_free(dsa);
37431492Swollman	apps_shutdown();
3751553Srgrimes	OPENSSL_EXIT(ret);
3761553Srgrimes	}
3771553Srgrimes
3781553Srgrimesstatic void MS_CALLBACK dsa_cb(int p, int n, void *arg)
3791553Srgrimes	{
3801553Srgrimes	char c='*';
3811553Srgrimes
38231492Swollman	if (p == 0) c='.';
3831553Srgrimes	if (p == 1) c='+';
3841553Srgrimes	if (p == 2) c='*';
38568253Sgad	if (p == 3) c='\n';
38668253Sgad	BIO_write(arg,&c,1);
38768253Sgad	(void)BIO_flush(arg);
3881553Srgrimes#ifdef LINT
3891553Srgrimes	p=n;
3901553Srgrimes#endif
3911553Srgrimes	}
3921553Srgrimes#endif
3931553Srgrimes