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