00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 #include <openssl/opensslconf.h>
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
00136
00137
00138
00139
00140
00141
00142
00143
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
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
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
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
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
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