1 /* apps/dh.c */ 2 /* obsoleted by dhparam.c */ 3 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 4 * All rights reserved. 5 * 6 * This package is an SSL implementation written 7 * by Eric Young (eay@cryptsoft.com). 8 * The implementation was written so as to conform with Netscapes SSL. 9 * 10 * This library is free for commercial and non-commercial use as long as 11 * the following conditions are aheared to. The following conditions 12 * apply to all code found in this distribution, be it the RC4, RSA, 13 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 14 * included with this distribution is covered by the same copyright terms 15 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 16 * 17 * Copyright remains Eric Young's, and as such any Copyright notices in 18 * the code are not to be removed. 19 * If this package is used in a product, Eric Young should be given attribution 20 * as the author of the parts of the library used. 21 * This can be in the form of a textual message at program startup or 22 * in documentation (online or textual) provided with the package. 23 * 24 * Redistribution and use in source and binary forms, with or without 25 * modification, are permitted provided that the following conditions 26 * are met: 27 * 1. Redistributions of source code must retain the copyright 28 * notice, this list of conditions and the following disclaimer. 29 * 2. Redistributions in binary form must reproduce the above copyright 30 * notice, this list of conditions and the following disclaimer in the 31 * documentation and/or other materials provided with the distribution. 32 * 3. All advertising materials mentioning features or use of this software 33 * must display the following acknowledgement: 34 * "This product includes cryptographic software written by 35 * Eric Young (eay@cryptsoft.com)" 36 * The word 'cryptographic' can be left out if the rouines from the library 37 * being used are not cryptographic related :-). 38 * 4. If you include any Windows specific code (or a derivative thereof) from 39 * the apps directory (application code) you must include an acknowledgement: 40 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 41 * 42 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 45 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 52 * SUCH DAMAGE. 53 * 54 * The licence and distribution terms for any publically available version or 55 * derivative of this code cannot be changed. i.e. this code cannot simply be 56 * copied and put under another distribution licence 57 * [including the GNU Public Licence.] 58 */ 59 60 #include <openssl/opensslconf.h> /* for OPENSSL_NO_DH */ 61 #ifndef OPENSSL_NO_DH 62 # include <stdio.h> 63 # include <stdlib.h> 64 # include <time.h> 65 # include <string.h> 66 # include "apps.h" 67 # include <openssl/bio.h> 68 # include <openssl/err.h> 69 # include <openssl/bn.h> 70 # include <openssl/dh.h> 71 # include <openssl/x509.h> 72 # include <openssl/pem.h> 73 74 # undef PROG 75 # define PROG dh_main 76 77 /*- 78 * -inform arg - input format - default PEM (DER or PEM) 79 * -outform arg - output format - default PEM 80 * -in arg - input file - default stdin 81 * -out arg - output file - default stdout 82 * -check - check the parameters are ok 83 * -noout 84 * -text 85 * -C 86 */ 87 88 int MAIN(int, char **); 89 90 int MAIN(int argc, char **argv) 91 { 92 DH *dh = NULL; 93 int i, badops = 0, text = 0; 94 BIO *in = NULL, *out = NULL; 95 int informat, outformat, check = 0, noout = 0, C = 0, ret = 1; 96 char *infile, *outfile, *prog; 97 # ifndef OPENSSL_NO_ENGINE 98 char *engine; 99 # endif 100 101 apps_startup(); 102 103 if (bio_err == NULL) 104 if ((bio_err = BIO_new(BIO_s_file())) != NULL) 105 BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); 106 107 if (!load_config(bio_err, NULL)) 108 goto end; 109 110 # ifndef OPENSSL_NO_ENGINE 111 engine = NULL; 112 # endif 113 infile = NULL; 114 outfile = NULL; 115 informat = FORMAT_PEM; 116 outformat = FORMAT_PEM; 117 118 prog = argv[0]; 119 argc--; 120 argv++; 121 while (argc >= 1) { 122 if (strcmp(*argv, "-inform") == 0) { 123 if (--argc < 1) 124 goto bad; 125 informat = str2fmt(*(++argv)); 126 } else if (strcmp(*argv, "-outform") == 0) { 127 if (--argc < 1) 128 goto bad; 129 outformat = str2fmt(*(++argv)); 130 } else if (strcmp(*argv, "-in") == 0) { 131 if (--argc < 1) 132 goto bad; 133 infile = *(++argv); 134 } else if (strcmp(*argv, "-out") == 0) { 135 if (--argc < 1) 136 goto bad; 137 outfile = *(++argv); 138 } 139 # ifndef OPENSSL_NO_ENGINE 140 else if (strcmp(*argv, "-engine") == 0) { 141 if (--argc < 1) 142 goto bad; 143 engine = *(++argv); 144 } 145 # endif 146 else if (strcmp(*argv, "-check") == 0) 147 check = 1; 148 else if (strcmp(*argv, "-text") == 0) 149 text = 1; 150 else if (strcmp(*argv, "-C") == 0) 151 C = 1; 152 else if (strcmp(*argv, "-noout") == 0) 153 noout = 1; 154 else { 155 BIO_printf(bio_err, "unknown option %s\n", *argv); 156 badops = 1; 157 break; 158 } 159 argc--; 160 argv++; 161 } 162 163 if (badops) { 164 bad: 165 BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog); 166 BIO_printf(bio_err, "where options are\n"); 167 BIO_printf(bio_err, " -inform arg input format - one of DER PEM\n"); 168 BIO_printf(bio_err, 169 " -outform arg output format - one of DER PEM\n"); 170 BIO_printf(bio_err, " -in arg input file\n"); 171 BIO_printf(bio_err, " -out arg output file\n"); 172 BIO_printf(bio_err, " -check check the DH parameters\n"); 173 BIO_printf(bio_err, 174 " -text print a text form of the DH parameters\n"); 175 BIO_printf(bio_err, " -C Output C code\n"); 176 BIO_printf(bio_err, " -noout no output\n"); 177 # ifndef OPENSSL_NO_ENGINE 178 BIO_printf(bio_err, 179 " -engine e use engine e, possibly a hardware device.\n"); 180 # endif 181 goto end; 182 } 183 184 ERR_load_crypto_strings(); 185 186 # ifndef OPENSSL_NO_ENGINE 187 setup_engine(bio_err, engine, 0); 188 # endif 189 190 in = BIO_new(BIO_s_file()); 191 out = BIO_new(BIO_s_file()); 192 if ((in == NULL) || (out == NULL)) { 193 ERR_print_errors(bio_err); 194 goto end; 195 } 196 197 if (infile == NULL) 198 BIO_set_fp(in, stdin, BIO_NOCLOSE); 199 else { 200 if (BIO_read_filename(in, infile) <= 0) { 201 perror(infile); 202 goto end; 203 } 204 } 205 if (outfile == NULL) { 206 BIO_set_fp(out, stdout, BIO_NOCLOSE); 207 # ifdef OPENSSL_SYS_VMS 208 { 209 BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 210 out = BIO_push(tmpbio, out); 211 } 212 # endif 213 } else { 214 if (BIO_write_filename(out, outfile) <= 0) { 215 perror(outfile); 216 goto end; 217 } 218 } 219 220 if (informat == FORMAT_ASN1) 221 dh = d2i_DHparams_bio(in, NULL); 222 else if (informat == FORMAT_PEM) 223 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); 224 else { 225 BIO_printf(bio_err, "bad input format specified\n"); 226 goto end; 227 } 228 if (dh == NULL) { 229 BIO_printf(bio_err, "unable to load DH parameters\n"); 230 ERR_print_errors(bio_err); 231 goto end; 232 } 233 234 if (text) { 235 DHparams_print(out, dh); 236 # ifdef undef 237 printf("p="); 238 BN_print(stdout, dh->p); 239 printf("\ng="); 240 BN_print(stdout, dh->g); 241 printf("\n"); 242 if (dh->length != 0) 243 printf("recommended private length=%ld\n", dh->length); 244 # endif 245 } 246 247 if (check) { 248 if (!DH_check(dh, &i)) { 249 ERR_print_errors(bio_err); 250 goto end; 251 } 252 if (i & DH_CHECK_P_NOT_PRIME) 253 printf("p value is not prime\n"); 254 if (i & DH_CHECK_P_NOT_SAFE_PRIME) 255 printf("p value is not a safe prime\n"); 256 if (i & DH_UNABLE_TO_CHECK_GENERATOR) 257 printf("unable to check the generator value\n"); 258 if (i & DH_NOT_SUITABLE_GENERATOR) 259 printf("the g value is not a generator\n"); 260 if (i == 0) 261 printf("DH parameters appear to be ok.\n"); 262 } 263 if (C) { 264 unsigned char *data; 265 int len, l, bits; 266 267 len = BN_num_bytes(dh->p); 268 bits = BN_num_bits(dh->p); 269 data = (unsigned char *)OPENSSL_malloc(len); 270 if (data == NULL) { 271 perror("OPENSSL_malloc"); 272 goto end; 273 } 274 l = BN_bn2bin(dh->p, data); 275 printf("static unsigned char dh%d_p[]={", bits); 276 for (i = 0; i < l; i++) { 277 if ((i % 12) == 0) 278 printf("\n\t"); 279 printf("0x%02X,", data[i]); 280 } 281 printf("\n\t};\n"); 282 283 l = BN_bn2bin(dh->g, data); 284 printf("static unsigned char dh%d_g[]={", bits); 285 for (i = 0; i < l; i++) { 286 if ((i % 12) == 0) 287 printf("\n\t"); 288 printf("0x%02X,", data[i]); 289 } 290 printf("\n\t};\n\n"); 291 292 printf("DH *get_dh%d()\n\t{\n", bits); 293 printf("\tDH *dh;\n\n"); 294 printf("\tif ((dh=DH_new()) == NULL) return(NULL);\n"); 295 printf("\tdh->p=BN_bin2bn(dh%d_p,sizeof(dh%d_p),NULL);\n", 296 bits, bits); 297 printf("\tdh->g=BN_bin2bn(dh%d_g,sizeof(dh%d_g),NULL);\n", 298 bits, bits); 299 printf("\tif ((dh->p == NULL) || (dh->g == NULL))\n"); 300 printf("\t\treturn(NULL);\n"); 301 printf("\treturn(dh);\n\t}\n"); 302 OPENSSL_free(data); 303 } 304 305 if (!noout) { 306 if (outformat == FORMAT_ASN1) 307 i = i2d_DHparams_bio(out, dh); 308 else if (outformat == FORMAT_PEM) 309 i = PEM_write_bio_DHparams(out, dh); 310 else { 311 BIO_printf(bio_err, "bad output format specified for outfile\n"); 312 goto end; 313 } 314 if (!i) { 315 BIO_printf(bio_err, "unable to write DH parameters\n"); 316 ERR_print_errors(bio_err); 317 goto end; 318 } 319 } 320 ret = 0; 321 end: 322 if (in != NULL) 323 BIO_free(in); 324 if (out != NULL) 325 BIO_free_all(out); 326 if (dh != NULL) 327 DH_free(dh); 328 apps_shutdown(); 329 OPENSSL_EXIT(ret); 330 } 331 #else /* !OPENSSL_NO_DH */ 332 333 # if PEDANTIC 334 static void *dummy = &dummy; 335 # endif 336 337 #endif 338