#include <openssl/opensslconf.h>
#ifndef OPENSSL_NO_DH
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "apps.h"
#include <openssl/bio.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/dh.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
static struct {
int C;
int check;
char *infile;
int informat;
int noout;
char *outfile;
int outformat;
int text;
} dh_config;
static const struct option dh_options[] = {
{
.name = "C",
.desc = "Convert DH parameters into C code",
.type = OPTION_FLAG,
.opt.flag = &dh_config.C,
},
{
.name = "check",
.desc = "Check the DH parameters",
.type = OPTION_FLAG,
.opt.flag = &dh_config.check,
},
{
.name = "in",
.argname = "file",
.desc = "Input file (default stdin)",
.type = OPTION_ARG,
.opt.arg = &dh_config.infile,
},
{
.name = "inform",
.argname = "format",
.desc = "Input format (DER or PEM (default))",
.type = OPTION_ARG_FORMAT,
.opt.value = &dh_config.informat,
},
{
.name = "noout",
.desc = "No output",
.type = OPTION_FLAG,
.opt.flag = &dh_config.noout,
},
{
.name = "out",
.argname = "file",
.desc = "Output file (default stdout)",
.type = OPTION_ARG,
.opt.arg = &dh_config.outfile,
},
{
.name = "outform",
.argname = "format",
.desc = "Output format (DER or PEM (default))",
.type = OPTION_ARG_FORMAT,
.opt.value = &dh_config.outformat,
},
{
.name = "text",
.desc = "Print a text form of the DH parameters",
.type = OPTION_FLAG,
.opt.flag = &dh_config.text,
},
{ NULL },
};
static void
dh_usage(void)
{
fprintf(stderr,
"usage: dh [-C] [-check] [-in file] [-inform format]\n"
" [-noout] [-out file] [-outform format] [-text]\n\n");
options_usage(dh_options);
}
int
dh_main(int argc, char **argv)
{
DH *dh = NULL;
int i;
BIO *in = NULL, *out = NULL;
int ret = 1;
if (single_execution) {
if (pledge("stdio cpath wpath rpath", NULL) == -1) {
perror("pledge");
exit(1);
}
}
memset(&dh_config, 0, sizeof(dh_config));
dh_config.informat = FORMAT_PEM;
dh_config.outformat = FORMAT_PEM;
if (options_parse(argc, argv, dh_options, NULL, NULL) != 0) {
dh_usage();
goto end;
}
in = BIO_new(BIO_s_file());
out = BIO_new(BIO_s_file());
if (in == NULL || out == NULL) {
ERR_print_errors(bio_err);
goto end;
}
if (dh_config.infile == NULL)
BIO_set_fp(in, stdin, BIO_NOCLOSE);
else {
if (BIO_read_filename(in, dh_config.infile) <= 0) {
perror(dh_config.infile);
goto end;
}
}
if (dh_config.outfile == NULL) {
BIO_set_fp(out, stdout, BIO_NOCLOSE);
} else {
if (BIO_write_filename(out, dh_config.outfile) <= 0) {
perror(dh_config.outfile);
goto end;
}
}
if (dh_config.informat == FORMAT_ASN1)
dh = d2i_DHparams_bio(in, NULL);
else if (dh_config.informat == FORMAT_PEM)
dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
else {
BIO_printf(bio_err, "bad input format specified\n");
goto end;
}
if (dh == NULL) {
BIO_printf(bio_err, "unable to load DH parameters\n");
ERR_print_errors(bio_err);
goto end;
}
if (dh_config.text) {
DHparams_print(out, dh);
}
if (dh_config.check) {
if (!DH_check(dh, &i)) {
ERR_print_errors(bio_err);
goto end;
}
if (i & DH_CHECK_P_NOT_PRIME)
printf("p value is not prime\n");
if (i & DH_CHECK_P_NOT_SAFE_PRIME)
printf("p value is not a safe prime\n");
if (i & DH_UNABLE_TO_CHECK_GENERATOR)
printf("unable to check the generator value\n");
if (i & DH_NOT_SUITABLE_GENERATOR)
printf("the g value is not a generator\n");
if (i == 0)
printf("DH parameters appear to be ok.\n");
}
if (dh_config.C) {
unsigned char *data;
int len, l, bits;
len = BN_num_bytes(DH_get0_p(dh));
bits = BN_num_bits(DH_get0_p(dh));
data = malloc(len);
if (data == NULL) {
perror("malloc");
goto end;
}
l = BN_bn2bin(DH_get0_p(dh), data);
printf("static unsigned char dh%d_p[] = {", bits);
for (i = 0; i < l; i++) {
if ((i % 12) == 0)
printf("\n\t");
printf("0x%02X, ", data[i]);
}
printf("\n\t};\n");
l = BN_bn2bin(DH_get0_g(dh), data);
printf("static unsigned char dh%d_g[] = {", bits);
for (i = 0; i < l; i++) {
if ((i % 12) == 0)
printf("\n\t");
printf("0x%02X, ", data[i]);
}
printf("\n\t};\n\n");
printf("DH *get_dh%d()\n\t{\n", bits);
printf("\tDH *dh;\n");
printf("\tBIGNUM *p = NULL, *g = NULL;\n\n");
printf("\tif ((dh = DH_new()) == NULL) return(NULL);\n");
printf("\tp = BN_bin2bn(dh%d_p, sizeof(dh%d_p), NULL);\n",
bits, bits);
printf("\tg = BN_bin2bn(dh%d_g, sizeof(dh%d_g), NULL);\n",
bits, bits);
printf("\tif (p == NULL || g == NULL)\n");
printf("\t\t{ BN_free(p); BN_free(q); DH_free(dh); return(NULL); }\n");
printf("\tDH_set0_pqg(dh, p, NULL, g);\n");
printf("\treturn(dh);\n\t}\n");
free(data);
}
if (!dh_config.noout) {
if (dh_config.outformat == FORMAT_ASN1)
i = i2d_DHparams_bio(out, dh);
else if (dh_config.outformat == FORMAT_PEM)
i = PEM_write_bio_DHparams(out, dh);
else {
BIO_printf(bio_err, "bad output format specified for outfile\n");
goto end;
}
if (!i) {
BIO_printf(bio_err, "unable to write DH parameters\n");
ERR_print_errors(bio_err);
goto end;
}
}
ret = 0;
end:
BIO_free(in);
BIO_free_all(out);
DH_free(dh);
return (ret);
}
#endif