dsaparam.c revision 205128
155714Skris/* apps/dsaparam.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 855714Skris * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1555714Skris * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 2255714Skris * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4055714Skris * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 5255714Skris * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 59160814Ssimon#include <openssl/opensslconf.h> /* for OPENSSL_NO_DSA */ 60160814Ssimon/* Until the key-gen callbacks are modified to use newer prototypes, we allow 61160814Ssimon * deprecated functions for openssl-internal code */ 62160814Ssimon#ifdef OPENSSL_NO_DEPRECATED 63160814Ssimon#undef OPENSSL_NO_DEPRECATED 64160814Ssimon#endif 65160814Ssimon 66109998Smarkm#ifndef OPENSSL_NO_DSA 6759191Skris#include <assert.h> 6855714Skris#include <stdio.h> 6955714Skris#include <stdlib.h> 7055714Skris#include <time.h> 7155714Skris#include <string.h> 7255714Skris#include "apps.h" 7355714Skris#include <openssl/bio.h> 7455714Skris#include <openssl/err.h> 7555714Skris#include <openssl/bn.h> 7655714Skris#include <openssl/dsa.h> 7755714Skris#include <openssl/x509.h> 7855714Skris#include <openssl/pem.h> 7955714Skris 8055714Skris#undef PROG 8155714Skris#define PROG dsaparam_main 8255714Skris 8359191Skris/* -inform arg - input format - default PEM (DER or PEM) 8455714Skris * -outform arg - output format - default PEM 8555714Skris * -in arg - input file - default stdin 8655714Skris * -out arg - output file - default stdout 8755714Skris * -noout 8855714Skris * -text 8955714Skris * -C 9055714Skris * -noout 9155714Skris * -genkey 92160814Ssimon * #ifdef GENCB_TEST 93160814Ssimon * -timebomb n - interrupt keygen after <n> seconds 94160814Ssimon * #endif 9555714Skris */ 9655714Skris 97160814Ssimon#ifdef GENCB_TEST 9859191Skris 99160814Ssimonstatic int stop_keygen_flag = 0; 100160814Ssimon 101160814Ssimonstatic void timebomb_sigalarm(int foo) 102160814Ssimon { 103160814Ssimon stop_keygen_flag = 1; 104160814Ssimon } 105160814Ssimon 106160814Ssimon#endif 107160814Ssimon 108160814Ssimonstatic int MS_CALLBACK dsa_cb(int p, int n, BN_GENCB *cb); 109160814Ssimon 11059191Skrisint MAIN(int, char **); 11159191Skris 11255714Skrisint MAIN(int argc, char **argv) 11355714Skris { 114111147Snectar#ifndef OPENSSL_NO_ENGINE 115109998Smarkm ENGINE *e = NULL; 116111147Snectar#endif 11755714Skris DSA *dsa=NULL; 11855714Skris int i,badops=0,text=0; 11955714Skris BIO *in=NULL,*out=NULL; 12055714Skris int informat,outformat,noout=0,C=0,ret=1; 12155714Skris char *infile,*outfile,*prog,*inrand=NULL; 12255714Skris int numbits= -1,num,genkey=0; 12359191Skris int need_rand=0; 124111147Snectar#ifndef OPENSSL_NO_ENGINE 125109998Smarkm char *engine=NULL; 126111147Snectar#endif 127160814Ssimon#ifdef GENCB_TEST 128160814Ssimon int timebomb=0; 129160814Ssimon#endif 13055714Skris 13155714Skris apps_startup(); 13255714Skris 13355714Skris if (bio_err == NULL) 13455714Skris if ((bio_err=BIO_new(BIO_s_file())) != NULL) 13555714Skris BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); 13655714Skris 137109998Smarkm if (!load_config(bio_err, NULL)) 138109998Smarkm goto end; 139109998Smarkm 14055714Skris infile=NULL; 14155714Skris outfile=NULL; 14255714Skris informat=FORMAT_PEM; 14355714Skris outformat=FORMAT_PEM; 14455714Skris 14555714Skris prog=argv[0]; 14655714Skris argc--; 14755714Skris argv++; 14855714Skris while (argc >= 1) 14955714Skris { 15055714Skris if (strcmp(*argv,"-inform") == 0) 15155714Skris { 15255714Skris if (--argc < 1) goto bad; 15355714Skris informat=str2fmt(*(++argv)); 15455714Skris } 15555714Skris else if (strcmp(*argv,"-outform") == 0) 15655714Skris { 15755714Skris if (--argc < 1) goto bad; 15855714Skris outformat=str2fmt(*(++argv)); 15955714Skris } 16055714Skris else if (strcmp(*argv,"-in") == 0) 16155714Skris { 16255714Skris if (--argc < 1) goto bad; 16355714Skris infile= *(++argv); 16455714Skris } 16555714Skris else if (strcmp(*argv,"-out") == 0) 16655714Skris { 16755714Skris if (--argc < 1) goto bad; 16855714Skris outfile= *(++argv); 16955714Skris } 170111147Snectar#ifndef OPENSSL_NO_ENGINE 171109998Smarkm else if(strcmp(*argv, "-engine") == 0) 172109998Smarkm { 173109998Smarkm if (--argc < 1) goto bad; 174109998Smarkm engine = *(++argv); 175109998Smarkm } 176111147Snectar#endif 177160814Ssimon#ifdef GENCB_TEST 178160814Ssimon else if(strcmp(*argv, "-timebomb") == 0) 179160814Ssimon { 180160814Ssimon if (--argc < 1) goto bad; 181160814Ssimon timebomb = atoi(*(++argv)); 182160814Ssimon } 183160814Ssimon#endif 18455714Skris else if (strcmp(*argv,"-text") == 0) 18555714Skris text=1; 18655714Skris else if (strcmp(*argv,"-C") == 0) 18755714Skris C=1; 18855714Skris else if (strcmp(*argv,"-genkey") == 0) 18959191Skris { 19055714Skris genkey=1; 19159191Skris need_rand=1; 19259191Skris } 19355714Skris else if (strcmp(*argv,"-rand") == 0) 19455714Skris { 19555714Skris if (--argc < 1) goto bad; 19655714Skris inrand= *(++argv); 19759191Skris need_rand=1; 19855714Skris } 19955714Skris else if (strcmp(*argv,"-noout") == 0) 20055714Skris noout=1; 20155714Skris else if (sscanf(*argv,"%d",&num) == 1) 20255714Skris { 20355714Skris /* generate a key */ 20455714Skris numbits=num; 20559191Skris need_rand=1; 20655714Skris } 20755714Skris else 20855714Skris { 20955714Skris BIO_printf(bio_err,"unknown option %s\n",*argv); 21055714Skris badops=1; 21155714Skris break; 21255714Skris } 21355714Skris argc--; 21455714Skris argv++; 21555714Skris } 21655714Skris 21755714Skris if (badops) 21855714Skris { 21955714Skrisbad: 22055714Skris BIO_printf(bio_err,"%s [options] [bits] <infile >outfile\n",prog); 22155714Skris BIO_printf(bio_err,"where options are\n"); 22259191Skris BIO_printf(bio_err," -inform arg input format - DER or PEM\n"); 22359191Skris BIO_printf(bio_err," -outform arg output format - DER or PEM\n"); 22455714Skris BIO_printf(bio_err," -in arg input file\n"); 22555714Skris BIO_printf(bio_err," -out arg output file\n"); 226100928Snectar BIO_printf(bio_err," -text print as text\n"); 22755714Skris BIO_printf(bio_err," -C Output C code\n"); 22855714Skris BIO_printf(bio_err," -noout no output\n"); 229109998Smarkm BIO_printf(bio_err," -genkey generate a DSA key\n"); 23055714Skris BIO_printf(bio_err," -rand files to use for random number input\n"); 231111147Snectar#ifndef OPENSSL_NO_ENGINE 232109998Smarkm BIO_printf(bio_err," -engine e use engine e, possibly a hardware device.\n"); 233111147Snectar#endif 234160814Ssimon#ifdef GENCB_TEST 235160814Ssimon BIO_printf(bio_err," -timebomb n interrupt keygen after <n> seconds\n"); 236160814Ssimon#endif 23755714Skris BIO_printf(bio_err," number number of bits to use for generating private key\n"); 23855714Skris goto end; 23955714Skris } 24055714Skris 24155714Skris ERR_load_crypto_strings(); 24255714Skris 24355714Skris in=BIO_new(BIO_s_file()); 24455714Skris out=BIO_new(BIO_s_file()); 24555714Skris if ((in == NULL) || (out == NULL)) 24655714Skris { 24755714Skris ERR_print_errors(bio_err); 24855714Skris goto end; 24955714Skris } 25055714Skris 25155714Skris if (infile == NULL) 25255714Skris BIO_set_fp(in,stdin,BIO_NOCLOSE); 25355714Skris else 25455714Skris { 25555714Skris if (BIO_read_filename(in,infile) <= 0) 25655714Skris { 25755714Skris perror(infile); 25855714Skris goto end; 25955714Skris } 26055714Skris } 26155714Skris if (outfile == NULL) 26268651Skris { 26355714Skris BIO_set_fp(out,stdout,BIO_NOCLOSE); 264109998Smarkm#ifdef OPENSSL_SYS_VMS 26568651Skris { 26668651Skris BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 26768651Skris out = BIO_push(tmpbio, out); 26868651Skris } 26968651Skris#endif 27068651Skris } 27155714Skris else 27255714Skris { 27355714Skris if (BIO_write_filename(out,outfile) <= 0) 27455714Skris { 27555714Skris perror(outfile); 27655714Skris goto end; 27755714Skris } 27855714Skris } 27955714Skris 280111147Snectar#ifndef OPENSSL_NO_ENGINE 281109998Smarkm e = setup_engine(bio_err, engine, 0); 282111147Snectar#endif 283109998Smarkm 28459191Skris if (need_rand) 28559191Skris { 28659191Skris app_RAND_load_file(NULL, bio_err, (inrand != NULL)); 28759191Skris if (inrand != NULL) 28859191Skris BIO_printf(bio_err,"%ld semi-random bytes loaded\n", 28959191Skris app_RAND_load_files(inrand)); 29059191Skris } 29159191Skris 29255714Skris if (numbits > 0) 29355714Skris { 294160814Ssimon BN_GENCB cb; 295160814Ssimon BN_GENCB_set(&cb, dsa_cb, bio_err); 29659191Skris assert(need_rand); 297160814Ssimon dsa = DSA_new(); 298160814Ssimon if(!dsa) 299160814Ssimon { 300160814Ssimon BIO_printf(bio_err,"Error allocating DSA object\n"); 301160814Ssimon goto end; 302160814Ssimon } 30355714Skris BIO_printf(bio_err,"Generating DSA parameters, %d bit long prime\n",num); 30455714Skris BIO_printf(bio_err,"This could take some time\n"); 305160814Ssimon#ifdef GENCB_TEST 306160814Ssimon if(timebomb > 0) 307160814Ssimon { 308160814Ssimon struct sigaction act; 309160814Ssimon act.sa_handler = timebomb_sigalarm; 310160814Ssimon act.sa_flags = 0; 311160814Ssimon BIO_printf(bio_err,"(though I'll stop it if not done within %d secs)\n", 312160814Ssimon timebomb); 313160814Ssimon if(sigaction(SIGALRM, &act, NULL) != 0) 314160814Ssimon { 315160814Ssimon BIO_printf(bio_err,"Error, couldn't set SIGALRM handler\n"); 316160814Ssimon goto end; 317160814Ssimon } 318160814Ssimon alarm(timebomb); 319160814Ssimon } 320160814Ssimon#endif 321160814Ssimon if(!DSA_generate_parameters_ex(dsa,num,NULL,0,NULL,NULL, &cb)) 322160814Ssimon { 323160814Ssimon#ifdef GENCB_TEST 324160814Ssimon if(stop_keygen_flag) 325160814Ssimon { 326160814Ssimon BIO_printf(bio_err,"DSA key generation time-stopped\n"); 327160814Ssimon /* This is an asked-for behaviour! */ 328160814Ssimon ret = 0; 329160814Ssimon goto end; 330160814Ssimon } 331160814Ssimon#endif 332160814Ssimon BIO_printf(bio_err,"Error, DSA key generation failed\n"); 333160814Ssimon goto end; 334160814Ssimon } 33555714Skris } 33655714Skris else if (informat == FORMAT_ASN1) 33755714Skris dsa=d2i_DSAparams_bio(in,NULL); 33855714Skris else if (informat == FORMAT_PEM) 33955714Skris dsa=PEM_read_bio_DSAparams(in,NULL,NULL,NULL); 34055714Skris else 34155714Skris { 34255714Skris BIO_printf(bio_err,"bad input format specified\n"); 34355714Skris goto end; 34455714Skris } 34555714Skris if (dsa == NULL) 34655714Skris { 34755714Skris BIO_printf(bio_err,"unable to load DSA parameters\n"); 34855714Skris ERR_print_errors(bio_err); 34955714Skris goto end; 35055714Skris } 35155714Skris 35255714Skris if (text) 35355714Skris { 35455714Skris DSAparams_print(out,dsa); 35555714Skris } 35655714Skris 35755714Skris if (C) 35855714Skris { 35955714Skris unsigned char *data; 36055714Skris int l,len,bits_p,bits_q,bits_g; 36155714Skris 36255714Skris len=BN_num_bytes(dsa->p); 36355714Skris bits_p=BN_num_bits(dsa->p); 36455714Skris bits_q=BN_num_bits(dsa->q); 36555714Skris bits_g=BN_num_bits(dsa->g); 36668651Skris data=(unsigned char *)OPENSSL_malloc(len+20); 36755714Skris if (data == NULL) 36855714Skris { 36968651Skris perror("OPENSSL_malloc"); 37055714Skris goto end; 37155714Skris } 37255714Skris l=BN_bn2bin(dsa->p,data); 37355714Skris printf("static unsigned char dsa%d_p[]={",bits_p); 37455714Skris for (i=0; i<l; i++) 37555714Skris { 37655714Skris if ((i%12) == 0) printf("\n\t"); 37755714Skris printf("0x%02X,",data[i]); 37855714Skris } 37955714Skris printf("\n\t};\n"); 38055714Skris 38155714Skris l=BN_bn2bin(dsa->q,data); 38255714Skris printf("static unsigned char dsa%d_q[]={",bits_p); 38355714Skris for (i=0; i<l; i++) 38455714Skris { 38555714Skris if ((i%12) == 0) printf("\n\t"); 38655714Skris printf("0x%02X,",data[i]); 38755714Skris } 38855714Skris printf("\n\t};\n"); 38955714Skris 39055714Skris l=BN_bn2bin(dsa->g,data); 39155714Skris printf("static unsigned char dsa%d_g[]={",bits_p); 39255714Skris for (i=0; i<l; i++) 39355714Skris { 39455714Skris if ((i%12) == 0) printf("\n\t"); 39555714Skris printf("0x%02X,",data[i]); 39655714Skris } 39755714Skris printf("\n\t};\n\n"); 39855714Skris 39955714Skris printf("DSA *get_dsa%d()\n\t{\n",bits_p); 40055714Skris printf("\tDSA *dsa;\n\n"); 40155714Skris printf("\tif ((dsa=DSA_new()) == NULL) return(NULL);\n"); 40255714Skris printf("\tdsa->p=BN_bin2bn(dsa%d_p,sizeof(dsa%d_p),NULL);\n", 40355714Skris bits_p,bits_p); 40455714Skris printf("\tdsa->q=BN_bin2bn(dsa%d_q,sizeof(dsa%d_q),NULL);\n", 40555714Skris bits_p,bits_p); 40655714Skris printf("\tdsa->g=BN_bin2bn(dsa%d_g,sizeof(dsa%d_g),NULL);\n", 40755714Skris bits_p,bits_p); 40855714Skris printf("\tif ((dsa->p == NULL) || (dsa->q == NULL) || (dsa->g == NULL))\n"); 40972613Skris printf("\t\t{ DSA_free(dsa); return(NULL); }\n"); 41055714Skris printf("\treturn(dsa);\n\t}\n"); 41155714Skris } 41255714Skris 41355714Skris 41455714Skris if (!noout) 41555714Skris { 41655714Skris if (outformat == FORMAT_ASN1) 41755714Skris i=i2d_DSAparams_bio(out,dsa); 41855714Skris else if (outformat == FORMAT_PEM) 41955714Skris i=PEM_write_bio_DSAparams(out,dsa); 42055714Skris else { 42155714Skris BIO_printf(bio_err,"bad output format specified for outfile\n"); 42255714Skris goto end; 42355714Skris } 42455714Skris if (!i) 42555714Skris { 42659191Skris BIO_printf(bio_err,"unable to write DSA parameters\n"); 42755714Skris ERR_print_errors(bio_err); 42855714Skris goto end; 42955714Skris } 43055714Skris } 43155714Skris if (genkey) 43255714Skris { 43355714Skris DSA *dsakey; 43455714Skris 43559191Skris assert(need_rand); 43655714Skris if ((dsakey=DSAparams_dup(dsa)) == NULL) goto end; 43755714Skris if (!DSA_generate_key(dsakey)) goto end; 43855714Skris if (outformat == FORMAT_ASN1) 43955714Skris i=i2d_DSAPrivateKey_bio(out,dsakey); 44055714Skris else if (outformat == FORMAT_PEM) 44155714Skris i=PEM_write_bio_DSAPrivateKey(out,dsakey,NULL,NULL,0,NULL,NULL); 44255714Skris else { 44355714Skris BIO_printf(bio_err,"bad output format specified for outfile\n"); 44455714Skris goto end; 44555714Skris } 44655714Skris DSA_free(dsakey); 44755714Skris } 44859191Skris if (need_rand) 44959191Skris app_RAND_write_file(NULL, bio_err); 45055714Skris ret=0; 45155714Skrisend: 45255714Skris if (in != NULL) BIO_free(in); 45368651Skris if (out != NULL) BIO_free_all(out); 45455714Skris if (dsa != NULL) DSA_free(dsa); 455109998Smarkm apps_shutdown(); 456109998Smarkm OPENSSL_EXIT(ret); 45755714Skris } 45855714Skris 459160814Ssimonstatic int MS_CALLBACK dsa_cb(int p, int n, BN_GENCB *cb) 46055714Skris { 46155714Skris char c='*'; 46255714Skris 46355714Skris if (p == 0) c='.'; 46455714Skris if (p == 1) c='+'; 46555714Skris if (p == 2) c='*'; 46655714Skris if (p == 3) c='\n'; 467160814Ssimon BIO_write(cb->arg,&c,1); 468160814Ssimon (void)BIO_flush(cb->arg); 46955714Skris#ifdef LINT 47055714Skris p=n; 47155714Skris#endif 472160814Ssimon#ifdef GENCB_TEST 473160814Ssimon if(stop_keygen_flag) 474160814Ssimon return 0; 475160814Ssimon#endif 476160814Ssimon return 1; 47755714Skris } 478205128Ssimon#else /* !OPENSSL_NO_DSA */ 479205128Ssimon 480205128Ssimon# if PEDANTIC 481205128Ssimonstatic void *dummy=&dummy; 482205128Ssimon# endif 483205128Ssimon 48455714Skris#endif 485