1*a9d90585Stb /* $OpenBSD: dsaparam.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_DSA */ 60dab3f910Sjsing 61dab3f910Sjsing /* Until the key-gen callbacks are modified to use newer prototypes, we allow 62dab3f910Sjsing * deprecated functions for openssl-internal code */ 63dab3f910Sjsing #ifdef OPENSSL_NO_DEPRECATED 64dab3f910Sjsing #undef OPENSSL_NO_DEPRECATED 65dab3f910Sjsing #endif 66dab3f910Sjsing 67fbd5d489Sdoug #include <limits.h> 68dab3f910Sjsing #include <stdio.h> 69dab3f910Sjsing #include <stdlib.h> 70dab3f910Sjsing #include <string.h> 71dab3f910Sjsing #include <time.h> 72dab3f910Sjsing 73dab3f910Sjsing #include "apps.h" 74dab3f910Sjsing 75dab3f910Sjsing #include <openssl/bio.h> 76dab3f910Sjsing #include <openssl/bn.h> 77dab3f910Sjsing #include <openssl/err.h> 78dab3f910Sjsing #include <openssl/dsa.h> 79dab3f910Sjsing #include <openssl/pem.h> 80dab3f910Sjsing #include <openssl/x509.h> 81dab3f910Sjsing 82fbd5d489Sdoug static struct { 83fbd5d489Sdoug int genkey; 84fbd5d489Sdoug char *infile; 85fbd5d489Sdoug int informat; 86fbd5d489Sdoug int noout; 87fbd5d489Sdoug char *outfile; 88fbd5d489Sdoug int outformat; 89fbd5d489Sdoug int text; 90e7718adaStb } cfg; 91dab3f910Sjsing 92ea149709Sguenther static const struct option dsaparam_options[] = { 93fbd5d489Sdoug { 94fbd5d489Sdoug .name = "genkey", 95fbd5d489Sdoug .desc = "Generate a DSA key", 96fbd5d489Sdoug .type = OPTION_FLAG, 97e7718adaStb .opt.flag = &cfg.genkey, 98fbd5d489Sdoug }, 99fbd5d489Sdoug { 100fbd5d489Sdoug .name = "in", 101fbd5d489Sdoug .argname = "file", 102fbd5d489Sdoug .desc = "Input file (default stdin)", 103fbd5d489Sdoug .type = OPTION_ARG, 104e7718adaStb .opt.arg = &cfg.infile, 105fbd5d489Sdoug }, 106fbd5d489Sdoug { 107fbd5d489Sdoug .name = "inform", 108fbd5d489Sdoug .argname = "format", 109fbd5d489Sdoug .desc = "Input format (DER or PEM (default))", 110fbd5d489Sdoug .type = OPTION_ARG_FORMAT, 111e7718adaStb .opt.value = &cfg.informat, 112fbd5d489Sdoug }, 113fbd5d489Sdoug { 114fbd5d489Sdoug .name = "noout", 115fbd5d489Sdoug .desc = "No output", 116fbd5d489Sdoug .type = OPTION_FLAG, 117e7718adaStb .opt.flag = &cfg.noout, 118fbd5d489Sdoug }, 119fbd5d489Sdoug { 120fbd5d489Sdoug .name = "out", 121fbd5d489Sdoug .argname = "file", 122fbd5d489Sdoug .desc = "Output file (default stdout)", 123fbd5d489Sdoug .type = OPTION_ARG, 124e7718adaStb .opt.arg = &cfg.outfile, 125fbd5d489Sdoug }, 126fbd5d489Sdoug { 127fbd5d489Sdoug .name = "outform", 128fbd5d489Sdoug .argname = "format", 129fbd5d489Sdoug .desc = "Output format (DER or PEM (default))", 130fbd5d489Sdoug .type = OPTION_ARG_FORMAT, 131e7718adaStb .opt.value = &cfg.outformat, 132fbd5d489Sdoug }, 133fbd5d489Sdoug { 134fbd5d489Sdoug .name = "text", 135fbd5d489Sdoug .desc = "Print as text", 136fbd5d489Sdoug .type = OPTION_FLAG, 137e7718adaStb .opt.flag = &cfg.text, 138fbd5d489Sdoug }, 139fbd5d489Sdoug { NULL }, 140fbd5d489Sdoug }; 141dab3f910Sjsing 142dab3f910Sjsing static void 143fbd5d489Sdoug dsaparam_usage(void) 144dab3f910Sjsing { 145fbd5d489Sdoug fprintf(stderr, 146*a9d90585Stb "usage: dsaparam [-genkey] [-in file]\n" 147fbd5d489Sdoug " [-inform format] [-noout] [-out file] [-outform format]\n" 148fbd5d489Sdoug " [-text] [numbits]\n\n"); 149fbd5d489Sdoug options_usage(dsaparam_options); 150dab3f910Sjsing } 151dab3f910Sjsing 152dab3f910Sjsing static int dsa_cb(int p, int n, BN_GENCB *cb); 153dab3f910Sjsing 154dab3f910Sjsing int 155dab3f910Sjsing dsaparam_main(int argc, char **argv) 156dab3f910Sjsing { 157dab3f910Sjsing DSA *dsa = NULL; 158fbd5d489Sdoug int i; 159dab3f910Sjsing BIO *in = NULL, *out = NULL; 160e0a955c7Stb BN_GENCB *cb = NULL; 161fbd5d489Sdoug int ret = 1; 162fbd5d489Sdoug int numbits = -1; 163fbd5d489Sdoug char *strbits = NULL; 164dab3f910Sjsing 16551811eadSderaadt if (pledge("stdio cpath wpath rpath", NULL) == -1) { 1669bc487adSdoug perror("pledge"); 167e370f0eeSdoug exit(1); 168e370f0eeSdoug } 1699bc487adSdoug 170e7718adaStb memset(&cfg, 0, sizeof(cfg)); 171dab3f910Sjsing 172e7718adaStb cfg.informat = FORMAT_PEM; 173e7718adaStb cfg.outformat = FORMAT_PEM; 174dab3f910Sjsing 175fbd5d489Sdoug if (options_parse(argc, argv, dsaparam_options, &strbits, NULL) != 0) { 176fbd5d489Sdoug dsaparam_usage(); 177dab3f910Sjsing goto end; 178dab3f910Sjsing } 179dab3f910Sjsing 180fbd5d489Sdoug if (strbits != NULL) { 181fbd5d489Sdoug const char *errstr; 182fbd5d489Sdoug numbits = strtonum(strbits, 0, INT_MAX, &errstr); 183fbd5d489Sdoug if (errstr) { 184fbd5d489Sdoug fprintf(stderr, "Invalid number of bits: %s", errstr); 185fbd5d489Sdoug goto end; 186fbd5d489Sdoug } 187fbd5d489Sdoug } 188fbd5d489Sdoug 189dab3f910Sjsing in = BIO_new(BIO_s_file()); 190dab3f910Sjsing out = BIO_new(BIO_s_file()); 191fbd5d489Sdoug if (in == NULL || out == NULL) { 192dab3f910Sjsing ERR_print_errors(bio_err); 193dab3f910Sjsing goto end; 194dab3f910Sjsing } 195e7718adaStb if (cfg.infile == NULL) 196dab3f910Sjsing BIO_set_fp(in, stdin, BIO_NOCLOSE); 197dab3f910Sjsing else { 198e7718adaStb if (BIO_read_filename(in, cfg.infile) <= 0) { 199e7718adaStb perror(cfg.infile); 200dab3f910Sjsing goto end; 201dab3f910Sjsing } 202dab3f910Sjsing } 203e7718adaStb if (cfg.outfile == NULL) { 204dab3f910Sjsing BIO_set_fp(out, stdout, BIO_NOCLOSE); 205dab3f910Sjsing } else { 206e7718adaStb if (BIO_write_filename(out, cfg.outfile) <= 0) { 207e7718adaStb perror(cfg.outfile); 208dab3f910Sjsing goto end; 209dab3f910Sjsing } 210dab3f910Sjsing } 211dab3f910Sjsing 212dab3f910Sjsing if (numbits > 0) { 213e0a955c7Stb if ((cb = BN_GENCB_new()) == NULL) { 214e0a955c7Stb BIO_printf(bio_err, 215e0a955c7Stb "Error allocating BN_GENCB object\n"); 216e0a955c7Stb goto end; 217e0a955c7Stb } 218e0a955c7Stb 219e0a955c7Stb BN_GENCB_set(cb, dsa_cb, bio_err); 220e0a955c7Stb 221dab3f910Sjsing dsa = DSA_new(); 222dab3f910Sjsing if (!dsa) { 223dab3f910Sjsing BIO_printf(bio_err, "Error allocating DSA object\n"); 224dab3f910Sjsing goto end; 225dab3f910Sjsing } 226fbd5d489Sdoug BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n", numbits); 227dab3f910Sjsing BIO_printf(bio_err, "This could take some time\n"); 228e0a955c7Stb if (!DSA_generate_parameters_ex(dsa, numbits, NULL, 0, NULL, NULL, cb)) { 229dab3f910Sjsing ERR_print_errors(bio_err); 230dab3f910Sjsing BIO_printf(bio_err, "Error, DSA key generation failed\n"); 231dab3f910Sjsing goto end; 232dab3f910Sjsing } 233e7718adaStb } else if (cfg.informat == FORMAT_ASN1) 234dab3f910Sjsing dsa = d2i_DSAparams_bio(in, NULL); 235e7718adaStb else if (cfg.informat == FORMAT_PEM) 236dab3f910Sjsing dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL); 237dab3f910Sjsing else { 238dab3f910Sjsing BIO_printf(bio_err, "bad input format specified\n"); 239dab3f910Sjsing goto end; 240dab3f910Sjsing } 241dab3f910Sjsing if (dsa == NULL) { 242dab3f910Sjsing BIO_printf(bio_err, "unable to load DSA parameters\n"); 243dab3f910Sjsing ERR_print_errors(bio_err); 244dab3f910Sjsing goto end; 245dab3f910Sjsing } 246e7718adaStb if (cfg.text) { 247dab3f910Sjsing DSAparams_print(out, dsa); 248dab3f910Sjsing } 249e7718adaStb if (!cfg.noout) { 250e7718adaStb if (cfg.outformat == FORMAT_ASN1) 251dab3f910Sjsing i = i2d_DSAparams_bio(out, dsa); 252e7718adaStb else if (cfg.outformat == FORMAT_PEM) 253dab3f910Sjsing i = PEM_write_bio_DSAparams(out, dsa); 254dab3f910Sjsing else { 255dab3f910Sjsing BIO_printf(bio_err, "bad output format specified for outfile\n"); 256dab3f910Sjsing goto end; 257dab3f910Sjsing } 258dab3f910Sjsing if (!i) { 259dab3f910Sjsing BIO_printf(bio_err, "unable to write DSA parameters\n"); 260dab3f910Sjsing ERR_print_errors(bio_err); 261dab3f910Sjsing goto end; 262dab3f910Sjsing } 263dab3f910Sjsing } 264e7718adaStb if (cfg.genkey) { 265dab3f910Sjsing DSA *dsakey; 266dab3f910Sjsing 267dab3f910Sjsing if ((dsakey = DSAparams_dup(dsa)) == NULL) 268dab3f910Sjsing goto end; 269dab3f910Sjsing if (!DSA_generate_key(dsakey)) { 270dab3f910Sjsing ERR_print_errors(bio_err); 271dab3f910Sjsing DSA_free(dsakey); 272dab3f910Sjsing goto end; 273dab3f910Sjsing } 274e7718adaStb if (cfg.outformat == FORMAT_ASN1) 275dab3f910Sjsing i = i2d_DSAPrivateKey_bio(out, dsakey); 276e7718adaStb else if (cfg.outformat == FORMAT_PEM) 277dab3f910Sjsing i = PEM_write_bio_DSAPrivateKey(out, dsakey, NULL, NULL, 0, NULL, NULL); 278dab3f910Sjsing else { 279dab3f910Sjsing BIO_printf(bio_err, "bad output format specified for outfile\n"); 280dab3f910Sjsing DSA_free(dsakey); 281dab3f910Sjsing goto end; 282dab3f910Sjsing } 283dab3f910Sjsing DSA_free(dsakey); 284dab3f910Sjsing } 285dab3f910Sjsing ret = 0; 286dab3f910Sjsing 287dab3f910Sjsing end: 288dab3f910Sjsing BIO_free(in); 289dab3f910Sjsing BIO_free_all(out); 290e0a955c7Stb BN_GENCB_free(cb); 291dab3f910Sjsing DSA_free(dsa); 292dab3f910Sjsing 293dab3f910Sjsing return (ret); 294dab3f910Sjsing } 295dab3f910Sjsing 296dab3f910Sjsing static int 297dab3f910Sjsing dsa_cb(int p, int n, BN_GENCB *cb) 298dab3f910Sjsing { 299dab3f910Sjsing char c = '*'; 300dab3f910Sjsing 301dab3f910Sjsing if (p == 0) 302dab3f910Sjsing c = '.'; 303dab3f910Sjsing if (p == 1) 304dab3f910Sjsing c = '+'; 305dab3f910Sjsing if (p == 2) 306dab3f910Sjsing c = '*'; 307dab3f910Sjsing if (p == 3) 308dab3f910Sjsing c = '\n'; 309e0a955c7Stb BIO_write(BN_GENCB_get_arg(cb), &c, 1); 310e0a955c7Stb (void) BIO_flush(BN_GENCB_get_arg(cb)); 311dab3f910Sjsing #ifdef GENCB_TEST 312dab3f910Sjsing if (stop_keygen_flag) 313dab3f910Sjsing return 0; 314dab3f910Sjsing #endif 315dab3f910Sjsing return 1; 316dab3f910Sjsing } 317