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