10Sstevel@tonic-gate /* apps/dh.c */
20Sstevel@tonic-gate /* obsoleted by dhparam.c */
30Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
40Sstevel@tonic-gate * All rights reserved.
50Sstevel@tonic-gate *
60Sstevel@tonic-gate * This package is an SSL implementation written
70Sstevel@tonic-gate * by Eric Young (eay@cryptsoft.com).
80Sstevel@tonic-gate * The implementation was written so as to conform with Netscapes SSL.
90Sstevel@tonic-gate *
100Sstevel@tonic-gate * This library is free for commercial and non-commercial use as long as
110Sstevel@tonic-gate * the following conditions are aheared to. The following conditions
120Sstevel@tonic-gate * apply to all code found in this distribution, be it the RC4, RSA,
130Sstevel@tonic-gate * lhash, DES, etc., code; not just the SSL code. The SSL documentation
140Sstevel@tonic-gate * included with this distribution is covered by the same copyright terms
150Sstevel@tonic-gate * except that the holder is Tim Hudson (tjh@cryptsoft.com).
160Sstevel@tonic-gate *
170Sstevel@tonic-gate * Copyright remains Eric Young's, and as such any Copyright notices in
180Sstevel@tonic-gate * the code are not to be removed.
190Sstevel@tonic-gate * If this package is used in a product, Eric Young should be given attribution
200Sstevel@tonic-gate * as the author of the parts of the library used.
210Sstevel@tonic-gate * This can be in the form of a textual message at program startup or
220Sstevel@tonic-gate * in documentation (online or textual) provided with the package.
230Sstevel@tonic-gate *
240Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without
250Sstevel@tonic-gate * modification, are permitted provided that the following conditions
260Sstevel@tonic-gate * are met:
270Sstevel@tonic-gate * 1. Redistributions of source code must retain the copyright
280Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer.
290Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright
300Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the
310Sstevel@tonic-gate * documentation and/or other materials provided with the distribution.
320Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software
330Sstevel@tonic-gate * must display the following acknowledgement:
340Sstevel@tonic-gate * "This product includes cryptographic software written by
350Sstevel@tonic-gate * Eric Young (eay@cryptsoft.com)"
360Sstevel@tonic-gate * The word 'cryptographic' can be left out if the rouines from the library
370Sstevel@tonic-gate * being used are not cryptographic related :-).
380Sstevel@tonic-gate * 4. If you include any Windows specific code (or a derivative thereof) from
390Sstevel@tonic-gate * the apps directory (application code) you must include an acknowledgement:
400Sstevel@tonic-gate * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
410Sstevel@tonic-gate *
420Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
430Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
440Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
450Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
460Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
470Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
480Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
490Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
500Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
510Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
520Sstevel@tonic-gate * SUCH DAMAGE.
530Sstevel@tonic-gate *
540Sstevel@tonic-gate * The licence and distribution terms for any publically available version or
550Sstevel@tonic-gate * derivative of this code cannot be changed. i.e. this code cannot simply be
560Sstevel@tonic-gate * copied and put under another distribution licence
570Sstevel@tonic-gate * [including the GNU Public Licence.]
580Sstevel@tonic-gate */
590Sstevel@tonic-gate
60*2139Sjp161948 #include <openssl/opensslconf.h> /* for OPENSSL_NO_DH */
610Sstevel@tonic-gate #ifndef OPENSSL_NO_DH
620Sstevel@tonic-gate #include <stdio.h>
630Sstevel@tonic-gate #include <stdlib.h>
640Sstevel@tonic-gate #include <time.h>
650Sstevel@tonic-gate #include <string.h>
660Sstevel@tonic-gate #include "apps.h"
670Sstevel@tonic-gate #include <openssl/bio.h>
680Sstevel@tonic-gate #include <openssl/err.h>
690Sstevel@tonic-gate #include <openssl/bn.h>
700Sstevel@tonic-gate #include <openssl/dh.h>
710Sstevel@tonic-gate #include <openssl/x509.h>
720Sstevel@tonic-gate #include <openssl/pem.h>
730Sstevel@tonic-gate
740Sstevel@tonic-gate #undef PROG
750Sstevel@tonic-gate #define PROG dh_main
760Sstevel@tonic-gate
770Sstevel@tonic-gate /* -inform arg - input format - default PEM (DER or PEM)
780Sstevel@tonic-gate * -outform arg - output format - default PEM
790Sstevel@tonic-gate * -in arg - input file - default stdin
800Sstevel@tonic-gate * -out arg - output file - default stdout
810Sstevel@tonic-gate * -check - check the parameters are ok
820Sstevel@tonic-gate * -noout
830Sstevel@tonic-gate * -text
840Sstevel@tonic-gate * -C
850Sstevel@tonic-gate */
860Sstevel@tonic-gate
870Sstevel@tonic-gate int MAIN(int, char **);
880Sstevel@tonic-gate
MAIN(int argc,char ** argv)890Sstevel@tonic-gate int MAIN(int argc, char **argv)
900Sstevel@tonic-gate {
910Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
920Sstevel@tonic-gate ENGINE *e = NULL;
930Sstevel@tonic-gate #endif
940Sstevel@tonic-gate DH *dh=NULL;
950Sstevel@tonic-gate int i,badops=0,text=0;
960Sstevel@tonic-gate BIO *in=NULL,*out=NULL;
970Sstevel@tonic-gate int informat,outformat,check=0,noout=0,C=0,ret=1;
980Sstevel@tonic-gate char *infile,*outfile,*prog;
990Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
1000Sstevel@tonic-gate char *engine;
1010Sstevel@tonic-gate #endif
1020Sstevel@tonic-gate
1030Sstevel@tonic-gate apps_startup();
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate if (bio_err == NULL)
1060Sstevel@tonic-gate if ((bio_err=BIO_new(BIO_s_file())) != NULL)
1070Sstevel@tonic-gate BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate if (!load_config(bio_err, NULL))
1100Sstevel@tonic-gate goto end;
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
1130Sstevel@tonic-gate engine=NULL;
1140Sstevel@tonic-gate #endif
1150Sstevel@tonic-gate infile=NULL;
1160Sstevel@tonic-gate outfile=NULL;
1170Sstevel@tonic-gate informat=FORMAT_PEM;
1180Sstevel@tonic-gate outformat=FORMAT_PEM;
1190Sstevel@tonic-gate
1200Sstevel@tonic-gate prog=argv[0];
1210Sstevel@tonic-gate argc--;
1220Sstevel@tonic-gate argv++;
1230Sstevel@tonic-gate while (argc >= 1)
1240Sstevel@tonic-gate {
1250Sstevel@tonic-gate if (strcmp(*argv,"-inform") == 0)
1260Sstevel@tonic-gate {
1270Sstevel@tonic-gate if (--argc < 1) goto bad;
1280Sstevel@tonic-gate informat=str2fmt(*(++argv));
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate else if (strcmp(*argv,"-outform") == 0)
1310Sstevel@tonic-gate {
1320Sstevel@tonic-gate if (--argc < 1) goto bad;
1330Sstevel@tonic-gate outformat=str2fmt(*(++argv));
1340Sstevel@tonic-gate }
1350Sstevel@tonic-gate else if (strcmp(*argv,"-in") == 0)
1360Sstevel@tonic-gate {
1370Sstevel@tonic-gate if (--argc < 1) goto bad;
1380Sstevel@tonic-gate infile= *(++argv);
1390Sstevel@tonic-gate }
1400Sstevel@tonic-gate else if (strcmp(*argv,"-out") == 0)
1410Sstevel@tonic-gate {
1420Sstevel@tonic-gate if (--argc < 1) goto bad;
1430Sstevel@tonic-gate outfile= *(++argv);
1440Sstevel@tonic-gate }
1450Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
1460Sstevel@tonic-gate else if (strcmp(*argv,"-engine") == 0)
1470Sstevel@tonic-gate {
1480Sstevel@tonic-gate if (--argc < 1) goto bad;
1490Sstevel@tonic-gate engine= *(++argv);
1500Sstevel@tonic-gate }
1510Sstevel@tonic-gate #endif
1520Sstevel@tonic-gate else if (strcmp(*argv,"-check") == 0)
1530Sstevel@tonic-gate check=1;
1540Sstevel@tonic-gate else if (strcmp(*argv,"-text") == 0)
1550Sstevel@tonic-gate text=1;
1560Sstevel@tonic-gate else if (strcmp(*argv,"-C") == 0)
1570Sstevel@tonic-gate C=1;
1580Sstevel@tonic-gate else if (strcmp(*argv,"-noout") == 0)
1590Sstevel@tonic-gate noout=1;
1600Sstevel@tonic-gate else
1610Sstevel@tonic-gate {
1620Sstevel@tonic-gate BIO_printf(bio_err,"unknown option %s\n",*argv);
1630Sstevel@tonic-gate badops=1;
1640Sstevel@tonic-gate break;
1650Sstevel@tonic-gate }
1660Sstevel@tonic-gate argc--;
1670Sstevel@tonic-gate argv++;
1680Sstevel@tonic-gate }
1690Sstevel@tonic-gate
1700Sstevel@tonic-gate if (badops)
1710Sstevel@tonic-gate {
1720Sstevel@tonic-gate bad:
1730Sstevel@tonic-gate BIO_printf(bio_err,"%s [options] <infile >outfile\n",prog);
1740Sstevel@tonic-gate BIO_printf(bio_err,"where options are\n");
1750Sstevel@tonic-gate BIO_printf(bio_err," -inform arg input format - one of DER PEM\n");
1760Sstevel@tonic-gate BIO_printf(bio_err," -outform arg output format - one of DER PEM\n");
1770Sstevel@tonic-gate BIO_printf(bio_err," -in arg input file\n");
1780Sstevel@tonic-gate BIO_printf(bio_err," -out arg output file\n");
1790Sstevel@tonic-gate BIO_printf(bio_err," -check check the DH parameters\n");
1800Sstevel@tonic-gate BIO_printf(bio_err," -text print a text form of the DH parameters\n");
1810Sstevel@tonic-gate BIO_printf(bio_err," -C Output C code\n");
1820Sstevel@tonic-gate BIO_printf(bio_err," -noout no output\n");
1830Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
1840Sstevel@tonic-gate BIO_printf(bio_err," -engine e use engine e, possibly a hardware device.\n");
1850Sstevel@tonic-gate #endif
1860Sstevel@tonic-gate goto end;
1870Sstevel@tonic-gate }
1880Sstevel@tonic-gate
1890Sstevel@tonic-gate ERR_load_crypto_strings();
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
1920Sstevel@tonic-gate e = setup_engine(bio_err, engine, 0);
1930Sstevel@tonic-gate #endif
1940Sstevel@tonic-gate
1950Sstevel@tonic-gate in=BIO_new(BIO_s_file());
1960Sstevel@tonic-gate out=BIO_new(BIO_s_file());
1970Sstevel@tonic-gate if ((in == NULL) || (out == NULL))
1980Sstevel@tonic-gate {
1990Sstevel@tonic-gate ERR_print_errors(bio_err);
2000Sstevel@tonic-gate goto end;
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate if (infile == NULL)
2040Sstevel@tonic-gate BIO_set_fp(in,stdin,BIO_NOCLOSE);
2050Sstevel@tonic-gate else
2060Sstevel@tonic-gate {
2070Sstevel@tonic-gate if (BIO_read_filename(in,infile) <= 0)
2080Sstevel@tonic-gate {
2090Sstevel@tonic-gate perror(infile);
2100Sstevel@tonic-gate goto end;
2110Sstevel@tonic-gate }
2120Sstevel@tonic-gate }
2130Sstevel@tonic-gate if (outfile == NULL)
2140Sstevel@tonic-gate {
2150Sstevel@tonic-gate BIO_set_fp(out,stdout,BIO_NOCLOSE);
2160Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS
2170Sstevel@tonic-gate {
2180Sstevel@tonic-gate BIO *tmpbio = BIO_new(BIO_f_linebuffer());
2190Sstevel@tonic-gate out = BIO_push(tmpbio, out);
2200Sstevel@tonic-gate }
2210Sstevel@tonic-gate #endif
2220Sstevel@tonic-gate }
2230Sstevel@tonic-gate else
2240Sstevel@tonic-gate {
2250Sstevel@tonic-gate if (BIO_write_filename(out,outfile) <= 0)
2260Sstevel@tonic-gate {
2270Sstevel@tonic-gate perror(outfile);
2280Sstevel@tonic-gate goto end;
2290Sstevel@tonic-gate }
2300Sstevel@tonic-gate }
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate if (informat == FORMAT_ASN1)
2330Sstevel@tonic-gate dh=d2i_DHparams_bio(in,NULL);
2340Sstevel@tonic-gate else if (informat == FORMAT_PEM)
2350Sstevel@tonic-gate dh=PEM_read_bio_DHparams(in,NULL,NULL,NULL);
2360Sstevel@tonic-gate else
2370Sstevel@tonic-gate {
2380Sstevel@tonic-gate BIO_printf(bio_err,"bad input format specified\n");
2390Sstevel@tonic-gate goto end;
2400Sstevel@tonic-gate }
2410Sstevel@tonic-gate if (dh == NULL)
2420Sstevel@tonic-gate {
2430Sstevel@tonic-gate BIO_printf(bio_err,"unable to load DH parameters\n");
2440Sstevel@tonic-gate ERR_print_errors(bio_err);
2450Sstevel@tonic-gate goto end;
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate
2480Sstevel@tonic-gate
2490Sstevel@tonic-gate
2500Sstevel@tonic-gate if (text)
2510Sstevel@tonic-gate {
2520Sstevel@tonic-gate DHparams_print(out,dh);
2530Sstevel@tonic-gate #ifdef undef
2540Sstevel@tonic-gate printf("p=");
2550Sstevel@tonic-gate BN_print(stdout,dh->p);
2560Sstevel@tonic-gate printf("\ng=");
2570Sstevel@tonic-gate BN_print(stdout,dh->g);
2580Sstevel@tonic-gate printf("\n");
2590Sstevel@tonic-gate if (dh->length != 0)
2600Sstevel@tonic-gate printf("recommended private length=%ld\n",dh->length);
2610Sstevel@tonic-gate #endif
2620Sstevel@tonic-gate }
2630Sstevel@tonic-gate
2640Sstevel@tonic-gate if (check)
2650Sstevel@tonic-gate {
2660Sstevel@tonic-gate if (!DH_check(dh,&i))
2670Sstevel@tonic-gate {
2680Sstevel@tonic-gate ERR_print_errors(bio_err);
2690Sstevel@tonic-gate goto end;
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate if (i & DH_CHECK_P_NOT_PRIME)
2720Sstevel@tonic-gate printf("p value is not prime\n");
2730Sstevel@tonic-gate if (i & DH_CHECK_P_NOT_SAFE_PRIME)
2740Sstevel@tonic-gate printf("p value is not a safe prime\n");
2750Sstevel@tonic-gate if (i & DH_UNABLE_TO_CHECK_GENERATOR)
2760Sstevel@tonic-gate printf("unable to check the generator value\n");
2770Sstevel@tonic-gate if (i & DH_NOT_SUITABLE_GENERATOR)
2780Sstevel@tonic-gate printf("the g value is not a generator\n");
2790Sstevel@tonic-gate if (i == 0)
2800Sstevel@tonic-gate printf("DH parameters appear to be ok.\n");
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate if (C)
2830Sstevel@tonic-gate {
2840Sstevel@tonic-gate unsigned char *data;
2850Sstevel@tonic-gate int len,l,bits;
2860Sstevel@tonic-gate
2870Sstevel@tonic-gate len=BN_num_bytes(dh->p);
2880Sstevel@tonic-gate bits=BN_num_bits(dh->p);
2890Sstevel@tonic-gate data=(unsigned char *)OPENSSL_malloc(len);
2900Sstevel@tonic-gate if (data == NULL)
2910Sstevel@tonic-gate {
2920Sstevel@tonic-gate perror("OPENSSL_malloc");
2930Sstevel@tonic-gate goto end;
2940Sstevel@tonic-gate }
2950Sstevel@tonic-gate l=BN_bn2bin(dh->p,data);
2960Sstevel@tonic-gate printf("static unsigned char dh%d_p[]={",bits);
2970Sstevel@tonic-gate for (i=0; i<l; i++)
2980Sstevel@tonic-gate {
2990Sstevel@tonic-gate if ((i%12) == 0) printf("\n\t");
3000Sstevel@tonic-gate printf("0x%02X,",data[i]);
3010Sstevel@tonic-gate }
3020Sstevel@tonic-gate printf("\n\t};\n");
3030Sstevel@tonic-gate
3040Sstevel@tonic-gate l=BN_bn2bin(dh->g,data);
3050Sstevel@tonic-gate printf("static unsigned char dh%d_g[]={",bits);
3060Sstevel@tonic-gate for (i=0; i<l; i++)
3070Sstevel@tonic-gate {
3080Sstevel@tonic-gate if ((i%12) == 0) printf("\n\t");
3090Sstevel@tonic-gate printf("0x%02X,",data[i]);
3100Sstevel@tonic-gate }
3110Sstevel@tonic-gate printf("\n\t};\n\n");
3120Sstevel@tonic-gate
3130Sstevel@tonic-gate printf("DH *get_dh%d()\n\t{\n",bits);
3140Sstevel@tonic-gate printf("\tDH *dh;\n\n");
3150Sstevel@tonic-gate printf("\tif ((dh=DH_new()) == NULL) return(NULL);\n");
3160Sstevel@tonic-gate printf("\tdh->p=BN_bin2bn(dh%d_p,sizeof(dh%d_p),NULL);\n",
3170Sstevel@tonic-gate bits,bits);
3180Sstevel@tonic-gate printf("\tdh->g=BN_bin2bn(dh%d_g,sizeof(dh%d_g),NULL);\n",
3190Sstevel@tonic-gate bits,bits);
3200Sstevel@tonic-gate printf("\tif ((dh->p == NULL) || (dh->g == NULL))\n");
3210Sstevel@tonic-gate printf("\t\treturn(NULL);\n");
3220Sstevel@tonic-gate printf("\treturn(dh);\n\t}\n");
3230Sstevel@tonic-gate OPENSSL_free(data);
3240Sstevel@tonic-gate }
3250Sstevel@tonic-gate
3260Sstevel@tonic-gate
3270Sstevel@tonic-gate if (!noout)
3280Sstevel@tonic-gate {
3290Sstevel@tonic-gate if (outformat == FORMAT_ASN1)
3300Sstevel@tonic-gate i=i2d_DHparams_bio(out,dh);
3310Sstevel@tonic-gate else if (outformat == FORMAT_PEM)
3320Sstevel@tonic-gate i=PEM_write_bio_DHparams(out,dh);
3330Sstevel@tonic-gate else {
3340Sstevel@tonic-gate BIO_printf(bio_err,"bad output format specified for outfile\n");
3350Sstevel@tonic-gate goto end;
3360Sstevel@tonic-gate }
3370Sstevel@tonic-gate if (!i)
3380Sstevel@tonic-gate {
3390Sstevel@tonic-gate BIO_printf(bio_err,"unable to write DH parameters\n");
3400Sstevel@tonic-gate ERR_print_errors(bio_err);
3410Sstevel@tonic-gate goto end;
3420Sstevel@tonic-gate }
3430Sstevel@tonic-gate }
3440Sstevel@tonic-gate ret=0;
3450Sstevel@tonic-gate end:
3460Sstevel@tonic-gate if (in != NULL) BIO_free(in);
3470Sstevel@tonic-gate if (out != NULL) BIO_free_all(out);
3480Sstevel@tonic-gate if (dh != NULL) DH_free(dh);
3490Sstevel@tonic-gate apps_shutdown();
3500Sstevel@tonic-gate OPENSSL_EXIT(ret);
3510Sstevel@tonic-gate }
3520Sstevel@tonic-gate #endif
353