Main Page | Class List | Directories | File List | Class Members | File Members

dhparam.c

Go to the documentation of this file.
00001 /* apps/dhparam.c */
00002 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
00003  * All rights reserved.
00004  *
00005  * This package is an SSL implementation written
00006  * by Eric Young (eay@cryptsoft.com).
00007  * The implementation was written so as to conform with Netscapes SSL.
00008  * 
00009  * This library is free for commercial and non-commercial use as long as
00010  * the following conditions are aheared to.  The following conditions
00011  * apply to all code found in this distribution, be it the RC4, RSA,
00012  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
00013  * included with this distribution is covered by the same copyright terms
00014  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
00015  * 
00016  * Copyright remains Eric Young's, and as such any Copyright notices in
00017  * the code are not to be removed.
00018  * If this package is used in a product, Eric Young should be given attribution
00019  * as the author of the parts of the library used.
00020  * This can be in the form of a textual message at program startup or
00021  * in documentation (online or textual) provided with the package.
00022  * 
00023  * Redistribution and use in source and binary forms, with or without
00024  * modification, are permitted provided that the following conditions
00025  * are met:
00026  * 1. Redistributions of source code must retain the copyright
00027  *    notice, this list of conditions and the following disclaimer.
00028  * 2. Redistributions in binary form must reproduce the above copyright
00029  *    notice, this list of conditions and the following disclaimer in the
00030  *    documentation and/or other materials provided with the distribution.
00031  * 3. All advertising materials mentioning features or use of this software
00032  *    must display the following acknowledgement:
00033  *    "This product includes cryptographic software written by
00034  *     Eric Young (eay@cryptsoft.com)"
00035  *    The word 'cryptographic' can be left out if the rouines from the library
00036  *    being used are not cryptographic related :-).
00037  * 4. If you include any Windows specific code (or a derivative thereof) from 
00038  *    the apps directory (application code) you must include an acknowledgement:
00039  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
00040  * 
00041  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
00042  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00043  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00044  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
00045  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00046  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00047  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00048  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00049  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00050  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00051  * SUCH DAMAGE.
00052  * 
00053  * The licence and distribution terms for any publically available version or
00054  * derivative of this code cannot be changed.  i.e. this code cannot simply be
00055  * copied and put under another distribution licence
00056  * [including the GNU Public Licence.]
00057  */
00058 /* ====================================================================
00059  * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
00060  *
00061  * Redistribution and use in source and binary forms, with or without
00062  * modification, are permitted provided that the following conditions
00063  * are met:
00064  *
00065  * 1. Redistributions of source code must retain the above copyright
00066  *    notice, this list of conditions and the following disclaimer. 
00067  *
00068  * 2. Redistributions in binary form must reproduce the above copyright
00069  *    notice, this list of conditions and the following disclaimer in
00070  *    the documentation and/or other materials provided with the
00071  *    distribution.
00072  *
00073  * 3. All advertising materials mentioning features or use of this
00074  *    software must display the following acknowledgment:
00075  *    "This product includes software developed by the OpenSSL Project
00076  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
00077  *
00078  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
00079  *    endorse or promote products derived from this software without
00080  *    prior written permission. For written permission, please contact
00081  *    openssl-core@openssl.org.
00082  *
00083  * 5. Products derived from this software may not be called "OpenSSL"
00084  *    nor may "OpenSSL" appear in their names without prior written
00085  *    permission of the OpenSSL Project.
00086  *
00087  * 6. Redistributions of any form whatsoever must retain the following
00088  *    acknowledgment:
00089  *    "This product includes software developed by the OpenSSL Project
00090  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
00091  *
00092  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
00093  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00094  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00095  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
00096  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00097  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00098  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00099  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00100  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00101  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00102  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00103  * OF THE POSSIBILITY OF SUCH DAMAGE.
00104  * ====================================================================
00105  *
00106  * This product includes cryptographic software written by Eric Young
00107  * (eay@cryptsoft.com).  This product includes software written by Tim
00108  * Hudson (tjh@cryptsoft.com).
00109  *
00110  */
00111 
00112 #include <openssl/opensslconf.h>        /* for OPENSSL_NO_DH */
00113 #ifndef OPENSSL_NO_DH
00114 #include <stdio.h>
00115 #include <stdlib.h>
00116 #include <time.h>
00117 #include <string.h>
00118 #include "apps.h"
00119 #include <openssl/bio.h>
00120 #include <openssl/err.h>
00121 #include <openssl/bn.h>
00122 #include <openssl/dh.h>
00123 #include <openssl/x509.h>
00124 #include <openssl/pem.h>
00125 
00126 #ifndef OPENSSL_NO_DSA
00127 #include <openssl/dsa.h>
00128 #endif
00129 
00130 #undef PROG
00131 #define PROG    dhparam_main
00132 
00133 #define DEFBITS 512
00134 
00135 /* -inform arg  - input format - default PEM (DER or PEM)
00136  * -outform arg - output format - default PEM
00137  * -in arg      - input file - default stdin
00138  * -out arg     - output file - default stdout
00139  * -dsaparam  - read or generate DSA parameters, convert to DH
00140  * -check       - check the parameters are ok
00141  * -noout
00142  * -text
00143  * -C
00144  */
00145 
00146 static int MS_CALLBACK dh_cb(int p, int n, BN_GENCB *cb);
00147 
00148 int MAIN(int, char **);
00149 
00150 int MAIN(int argc, char **argv)
00151         {
00152 #ifndef OPENSSL_NO_ENGINE
00153         ENGINE *e = NULL;
00154 #endif
00155         DH *dh=NULL;
00156         int i,badops=0,text=0;
00157 #ifndef OPENSSL_NO_DSA
00158         int dsaparam=0;
00159 #endif
00160         BIO *in=NULL,*out=NULL;
00161         int informat,outformat,check=0,noout=0,C=0,ret=1;
00162         char *infile,*outfile,*prog;
00163         char *inrand=NULL;
00164 #ifndef OPENSSL_NO_ENGINE
00165         char *engine=NULL;
00166 #endif
00167         int num = 0, g = 0;
00168 
00169         apps_startup();
00170 
00171         if (bio_err == NULL)
00172                 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
00173                         BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
00174 
00175         if (!load_config(bio_err, NULL))
00176                 goto end;
00177 
00178         infile=NULL;
00179         outfile=NULL;
00180         informat=FORMAT_PEM;
00181         outformat=FORMAT_PEM;
00182 
00183         prog=argv[0];
00184         argc--;
00185         argv++;
00186         while (argc >= 1)
00187                 {
00188                 if      (strcmp(*argv,"-inform") == 0)
00189                         {
00190                         if (--argc < 1) goto bad;
00191                         informat=str2fmt(*(++argv));
00192                         }
00193                 else if (strcmp(*argv,"-outform") == 0)
00194                         {
00195                         if (--argc < 1) goto bad;
00196                         outformat=str2fmt(*(++argv));
00197                         }
00198                 else if (strcmp(*argv,"-in") == 0)
00199                         {
00200                         if (--argc < 1) goto bad;
00201                         infile= *(++argv);
00202                         }
00203                 else if (strcmp(*argv,"-out") == 0)
00204                         {
00205                         if (--argc < 1) goto bad;
00206                         outfile= *(++argv);
00207                         }
00208 #ifndef OPENSSL_NO_ENGINE
00209                 else if (strcmp(*argv,"-engine") == 0)
00210                         {
00211                         if (--argc < 1) goto bad;
00212                         engine= *(++argv);
00213                         }
00214 #endif
00215                 else if (strcmp(*argv,"-check") == 0)
00216                         check=1;
00217                 else if (strcmp(*argv,"-text") == 0)
00218                         text=1;
00219 #ifndef OPENSSL_NO_DSA
00220                 else if (strcmp(*argv,"-dsaparam") == 0)
00221                         dsaparam=1;
00222 #endif
00223                 else if (strcmp(*argv,"-C") == 0)
00224                         C=1;
00225                 else if (strcmp(*argv,"-noout") == 0)
00226                         noout=1;
00227                 else if (strcmp(*argv,"-2") == 0)
00228                         g=2;
00229                 else if (strcmp(*argv,"-5") == 0)
00230                         g=5;
00231                 else if (strcmp(*argv,"-rand") == 0)
00232                         {
00233                         if (--argc < 1) goto bad;
00234                         inrand= *(++argv);
00235                         }
00236                 else if (((sscanf(*argv,"%d",&num) == 0) || (num <= 0)))
00237                         goto bad;
00238                 argv++;
00239                 argc--;
00240                 }
00241 
00242         if (badops)
00243                 {
00244 bad:
00245                 BIO_printf(bio_err,"%s [options] [numbits]\n",prog);
00246                 BIO_printf(bio_err,"where options are\n");
00247                 BIO_printf(bio_err," -inform arg   input format - one of DER PEM\n");
00248                 BIO_printf(bio_err," -outform arg  output format - one of DER PEM\n");
00249                 BIO_printf(bio_err," -in arg       input file\n");
00250                 BIO_printf(bio_err," -out arg      output file\n");
00251 #ifndef OPENSSL_NO_DSA
00252                 BIO_printf(bio_err," -dsaparam     read or generate DSA parameters, convert to DH\n");
00253 #endif
00254                 BIO_printf(bio_err," -check        check the DH parameters\n");
00255                 BIO_printf(bio_err," -text         print a text form of the DH parameters\n");
00256                 BIO_printf(bio_err," -C            Output C code\n");
00257                 BIO_printf(bio_err," -2            generate parameters using  2 as the generator value\n");
00258                 BIO_printf(bio_err," -5            generate parameters using  5 as the generator value\n");
00259                 BIO_printf(bio_err," numbits       number of bits in to generate (default 512)\n");
00260 #ifndef OPENSSL_NO_ENGINE
00261                 BIO_printf(bio_err," -engine e     use engine e, possibly a hardware device.\n");
00262 #endif
00263                 BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
00264                 BIO_printf(bio_err,"               - load the file (or the files in the directory) into\n");
00265                 BIO_printf(bio_err,"               the random number generator\n");
00266                 BIO_printf(bio_err," -noout        no output\n");
00267                 goto end;
00268                 }
00269 
00270         ERR_load_crypto_strings();
00271 
00272 #ifndef OPENSSL_NO_ENGINE
00273         e = setup_engine(bio_err, engine, 0);
00274 #endif
00275 
00276         if (g && !num)
00277                 num = DEFBITS;
00278 
00279 #ifndef OPENSSL_NO_DSA
00280         if (dsaparam)
00281                 {
00282                 if (g)
00283                         {
00284                         BIO_printf(bio_err, "generator may not be chosen for DSA parameters\n");
00285                         goto end;
00286                         }
00287                 }
00288         else
00289 #endif
00290                 {
00291                 /* DH parameters */
00292                 if (num && !g)
00293                         g = 2;
00294                 }
00295 
00296         if(num) {
00297 
00298                 BN_GENCB cb;
00299                 BN_GENCB_set(&cb, dh_cb, bio_err);
00300                 if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL)
00301                         {
00302                         BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n");
00303                         }
00304                 if (inrand != NULL)
00305                         BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
00306                                 app_RAND_load_files(inrand));
00307 
00308 #ifndef OPENSSL_NO_DSA
00309                 if (dsaparam)
00310                         {
00311                         DSA *dsa = DSA_new();
00312                         
00313                         BIO_printf(bio_err,"Generating DSA parameters, %d bit long prime\n",num);
00314                         if(!dsa || !DSA_generate_parameters_ex(dsa, num,
00315                                                 NULL, 0, NULL, NULL, &cb))
00316                                 {
00317                                 if(dsa) DSA_free(dsa);
00318                                 ERR_print_errors(bio_err);
00319                                 goto end;
00320                                 }
00321 
00322                         dh = DSA_dup_DH(dsa);
00323                         DSA_free(dsa);
00324                         if (dh == NULL)
00325                                 {
00326                                 ERR_print_errors(bio_err);
00327                                 goto end;
00328                                 }
00329                         }
00330                 else
00331 #endif
00332                         {
00333                         dh = DH_new();
00334                         BIO_printf(bio_err,"Generating DH parameters, %d bit long safe prime, generator %d\n",num,g);
00335                         BIO_printf(bio_err,"This is going to take a long time\n");
00336                         if(!dh || !DH_generate_parameters_ex(dh, num, g, &cb))
00337                                 {
00338                                 if(dh) DH_free(dh);
00339                                 ERR_print_errors(bio_err);
00340                                 goto end;
00341                                 }
00342                         }
00343 
00344                 app_RAND_write_file(NULL, bio_err);
00345         } else {
00346 
00347                 in=BIO_new(BIO_s_file());
00348                 if (in == NULL)
00349                         {
00350                         ERR_print_errors(bio_err);
00351                         goto end;
00352                         }
00353                 if (infile == NULL)
00354                         BIO_set_fp(in,stdin,BIO_NOCLOSE);
00355                 else
00356                         {
00357                         if (BIO_read_filename(in,infile) <= 0)
00358                                 {
00359                                 perror(infile);
00360                                 goto end;
00361                                 }
00362                         }
00363 
00364                 if      (informat != FORMAT_ASN1 && informat != FORMAT_PEM)
00365                         {
00366                         BIO_printf(bio_err,"bad input format specified\n");
00367                         goto end;
00368                         }
00369 
00370 #ifndef OPENSSL_NO_DSA
00371                 if (dsaparam)
00372                         {
00373                         DSA *dsa;
00374                         
00375                         if (informat == FORMAT_ASN1)
00376                                 dsa=d2i_DSAparams_bio(in,NULL);
00377                         else /* informat == FORMAT_PEM */
00378                                 dsa=PEM_read_bio_DSAparams(in,NULL,NULL,NULL);
00379                         
00380                         if (dsa == NULL)
00381                                 {
00382                                 BIO_printf(bio_err,"unable to load DSA parameters\n");
00383                                 ERR_print_errors(bio_err);
00384                                 goto end;
00385                                 }
00386                         
00387                         dh = DSA_dup_DH(dsa);
00388                         DSA_free(dsa);
00389                         if (dh == NULL)
00390                                 {
00391                                 ERR_print_errors(bio_err);
00392                                 goto end;
00393                                 }
00394                         }
00395                 else
00396 #endif
00397                         {
00398                         if (informat == FORMAT_ASN1)
00399                                 dh=d2i_DHparams_bio(in,NULL);
00400                         else /* informat == FORMAT_PEM */
00401                                 dh=PEM_read_bio_DHparams(in,NULL,NULL,NULL);
00402                         
00403                         if (dh == NULL)
00404                                 {
00405                                 BIO_printf(bio_err,"unable to load DH parameters\n");
00406                                 ERR_print_errors(bio_err);
00407                                 goto end;
00408                                 }
00409                         }
00410                 
00411                 /* dh != NULL */
00412         }
00413         
00414         out=BIO_new(BIO_s_file());
00415         if (out == NULL)
00416                 {
00417                 ERR_print_errors(bio_err);
00418                 goto end;
00419                 }
00420         if (outfile == NULL)
00421                 {
00422                 BIO_set_fp(out,stdout,BIO_NOCLOSE);
00423 #ifdef OPENSSL_SYS_VMS
00424                 {
00425                 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
00426                 out = BIO_push(tmpbio, out);
00427                 }
00428 #endif
00429                 }
00430         else
00431                 {
00432                 if (BIO_write_filename(out,outfile) <= 0)
00433                         {
00434                         perror(outfile);
00435                         goto end;
00436                         }
00437                 }
00438 
00439 
00440         if (text)
00441                 {
00442                 DHparams_print(out,dh);
00443                 }
00444         
00445         if (check)
00446                 {
00447                 if (!DH_check(dh,&i))
00448                         {
00449                         ERR_print_errors(bio_err);
00450                         goto end;
00451                         }
00452                 if (i & DH_CHECK_P_NOT_PRIME)
00453                         printf("p value is not prime\n");
00454                 if (i & DH_CHECK_P_NOT_SAFE_PRIME)
00455                         printf("p value is not a safe prime\n");
00456                 if (i & DH_UNABLE_TO_CHECK_GENERATOR)
00457                         printf("unable to check the generator value\n");
00458                 if (i & DH_NOT_SUITABLE_GENERATOR)
00459                         printf("the g value is not a generator\n");
00460                 if (i == 0)
00461                         printf("DH parameters appear to be ok.\n");
00462                 }
00463         if (C)
00464                 {
00465                 unsigned char *data;
00466                 int len,l,bits;
00467 
00468                 len=BN_num_bytes(dh->p);
00469                 bits=BN_num_bits(dh->p);
00470                 data=(unsigned char *)OPENSSL_malloc(len);
00471                 if (data == NULL)
00472                         {
00473                         perror("OPENSSL_malloc");
00474                         goto end;
00475                         }
00476                 printf("#ifndef HEADER_DH_H\n"
00477                        "#include <openssl/dh.h>\n"
00478                        "#endif\n");
00479                 printf("DH *get_dh%d()\n\t{\n",bits);
00480 
00481                 l=BN_bn2bin(dh->p,data);
00482                 printf("\tstatic unsigned char dh%d_p[]={",bits);
00483                 for (i=0; i<l; i++)
00484                         {
00485                         if ((i%12) == 0) printf("\n\t\t");
00486                         printf("0x%02X,",data[i]);
00487                         }
00488                 printf("\n\t\t};\n");
00489 
00490                 l=BN_bn2bin(dh->g,data);
00491                 printf("\tstatic unsigned char dh%d_g[]={",bits);
00492                 for (i=0; i<l; i++)
00493                         {
00494                         if ((i%12) == 0) printf("\n\t\t");
00495                         printf("0x%02X,",data[i]);
00496                         }
00497                 printf("\n\t\t};\n");
00498 
00499                 printf("\tDH *dh;\n\n");
00500                 printf("\tif ((dh=DH_new()) == NULL) return(NULL);\n");
00501                 printf("\tdh->p=BN_bin2bn(dh%d_p,sizeof(dh%d_p),NULL);\n",
00502                         bits,bits);
00503                 printf("\tdh->g=BN_bin2bn(dh%d_g,sizeof(dh%d_g),NULL);\n",
00504                         bits,bits);
00505                 printf("\tif ((dh->p == NULL) || (dh->g == NULL))\n");
00506                 printf("\t\t{ DH_free(dh); return(NULL); }\n");
00507                 if (dh->length)
00508                         printf("\tdh->length = %ld;\n", dh->length);
00509                 printf("\treturn(dh);\n\t}\n");
00510                 OPENSSL_free(data);
00511                 }
00512 
00513 
00514         if (!noout)
00515                 {
00516                 if      (outformat == FORMAT_ASN1)
00517                         i=i2d_DHparams_bio(out,dh);
00518                 else if (outformat == FORMAT_PEM)
00519                         i=PEM_write_bio_DHparams(out,dh);
00520                 else    {
00521                         BIO_printf(bio_err,"bad output format specified for outfile\n");
00522                         goto end;
00523                         }
00524                 if (!i)
00525                         {
00526                         BIO_printf(bio_err,"unable to write DH parameters\n");
00527                         ERR_print_errors(bio_err);
00528                         goto end;
00529                         }
00530                 }
00531         ret=0;
00532 end:
00533         if (in != NULL) BIO_free(in);
00534         if (out != NULL) BIO_free_all(out);
00535         if (dh != NULL) DH_free(dh);
00536         apps_shutdown();
00537         OPENSSL_EXIT(ret);
00538         }
00539 
00540 /* dh_cb is identical to dsa_cb in apps/dsaparam.c */
00541 static int MS_CALLBACK dh_cb(int p, int n, BN_GENCB *cb)
00542         {
00543         char c='*';
00544 
00545         if (p == 0) c='.';
00546         if (p == 1) c='+';
00547         if (p == 2) c='*';
00548         if (p == 3) c='\n';
00549         BIO_write(cb->arg,&c,1);
00550         (void)BIO_flush(cb->arg);
00551 #ifdef LINT
00552         p=n;
00553 #endif
00554         return 1;
00555         }
00556 
00557 #endif

© sourcejam.com 2005-2008