1*e71b7053SJung-uk Kim /* 2*e71b7053SJung-uk Kim * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. 374664626SKris Kennaway * 4*e71b7053SJung-uk Kim * Licensed under the OpenSSL license (the "License"). You may not use 5*e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 6*e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at 7*e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html 874664626SKris Kennaway */ 974664626SKris Kennaway 10*e71b7053SJung-uk Kim #include <openssl/opensslconf.h> 11*e71b7053SJung-uk Kim #ifdef OPENSSL_NO_DSA 12*e71b7053SJung-uk Kim NON_EMPTY_TRANSLATION_UNIT 13*e71b7053SJung-uk Kim #else 14*e71b7053SJung-uk Kim 1574664626SKris Kennaway # include <stdio.h> 1674664626SKris Kennaway # include <stdlib.h> 1774664626SKris Kennaway # include <string.h> 1874664626SKris Kennaway # include <time.h> 1974664626SKris Kennaway # include "apps.h" 20*e71b7053SJung-uk Kim # include "progs.h" 2174664626SKris Kennaway # include <openssl/bio.h> 2274664626SKris Kennaway # include <openssl/err.h> 231f13597dSJung-uk Kim # include <openssl/dsa.h> 2474664626SKris Kennaway # include <openssl/evp.h> 2574664626SKris Kennaway # include <openssl/x509.h> 2674664626SKris Kennaway # include <openssl/pem.h> 273b4e3dcbSSimon L. B. Nielsen # include <openssl/bn.h> 2874664626SKris Kennaway 29*e71b7053SJung-uk Kim typedef enum OPTION_choice { 30*e71b7053SJung-uk Kim OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, 31*e71b7053SJung-uk Kim OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENGINE, 32*e71b7053SJung-uk Kim /* Do not change the order here; see case statements below */ 33*e71b7053SJung-uk Kim OPT_PVK_NONE, OPT_PVK_WEAK, OPT_PVK_STRONG, 34*e71b7053SJung-uk Kim OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_PUBIN, 35*e71b7053SJung-uk Kim OPT_PUBOUT, OPT_CIPHER, OPT_PASSIN, OPT_PASSOUT 36*e71b7053SJung-uk Kim } OPTION_CHOICE; 3774664626SKris Kennaway 38*e71b7053SJung-uk Kim const OPTIONS dsa_options[] = { 39*e71b7053SJung-uk Kim {"help", OPT_HELP, '-', "Display this summary"}, 40*e71b7053SJung-uk Kim {"inform", OPT_INFORM, 'f', "Input format, DER PEM PVK"}, 41*e71b7053SJung-uk Kim {"outform", OPT_OUTFORM, 'f', "Output format, DER PEM PVK"}, 42*e71b7053SJung-uk Kim {"in", OPT_IN, 's', "Input key"}, 43*e71b7053SJung-uk Kim {"out", OPT_OUT, '>', "Output file"}, 44*e71b7053SJung-uk Kim {"noout", OPT_NOOUT, '-', "Don't print key out"}, 45*e71b7053SJung-uk Kim {"text", OPT_TEXT, '-', "Print the key in text"}, 46*e71b7053SJung-uk Kim {"modulus", OPT_MODULUS, '-', "Print the DSA public value"}, 47*e71b7053SJung-uk Kim {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"}, 48*e71b7053SJung-uk Kim {"pubout", OPT_PUBOUT, '-', "Output public key, not private"}, 49*e71b7053SJung-uk Kim {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, 50*e71b7053SJung-uk Kim {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, 51*e71b7053SJung-uk Kim {"", OPT_CIPHER, '-', "Any supported cipher"}, 52*e71b7053SJung-uk Kim # ifndef OPENSSL_NO_RC4 53*e71b7053SJung-uk Kim {"pvk-strong", OPT_PVK_STRONG, '-', "Enable 'Strong' PVK encoding level (default)"}, 54*e71b7053SJung-uk Kim {"pvk-weak", OPT_PVK_WEAK, '-', "Enable 'Weak' PVK encoding level"}, 55*e71b7053SJung-uk Kim {"pvk-none", OPT_PVK_NONE, '-', "Don't enforce PVK encoding"}, 56fceca8a3SJacques Vidrine # endif 57*e71b7053SJung-uk Kim # ifndef OPENSSL_NO_ENGINE 58*e71b7053SJung-uk Kim {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, 59*e71b7053SJung-uk Kim # endif 60*e71b7053SJung-uk Kim {NULL} 61*e71b7053SJung-uk Kim }; 62*e71b7053SJung-uk Kim 63*e71b7053SJung-uk Kim int dsa_main(int argc, char **argv) 64*e71b7053SJung-uk Kim { 65*e71b7053SJung-uk Kim BIO *out = NULL; 66*e71b7053SJung-uk Kim DSA *dsa = NULL; 67*e71b7053SJung-uk Kim ENGINE *e = NULL; 68*e71b7053SJung-uk Kim const EVP_CIPHER *enc = NULL; 69*e71b7053SJung-uk Kim char *infile = NULL, *outfile = NULL, *prog; 70*e71b7053SJung-uk Kim char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL; 71*e71b7053SJung-uk Kim OPTION_CHOICE o; 72*e71b7053SJung-uk Kim int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, noout = 0; 73*e71b7053SJung-uk Kim int i, modulus = 0, pubin = 0, pubout = 0, ret = 1; 74*e71b7053SJung-uk Kim # ifndef OPENSSL_NO_RC4 75*e71b7053SJung-uk Kim int pvk_encr = 2; 76*e71b7053SJung-uk Kim # endif 77*e71b7053SJung-uk Kim int private = 0; 78*e71b7053SJung-uk Kim 79*e71b7053SJung-uk Kim prog = opt_init(argc, argv, dsa_options); 80*e71b7053SJung-uk Kim while ((o = opt_next()) != OPT_EOF) { 81*e71b7053SJung-uk Kim switch (o) { 82*e71b7053SJung-uk Kim case OPT_EOF: 83*e71b7053SJung-uk Kim case OPT_ERR: 84*e71b7053SJung-uk Kim opthelp: 85*e71b7053SJung-uk Kim ret = 0; 86*e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 87*e71b7053SJung-uk Kim goto end; 88*e71b7053SJung-uk Kim case OPT_HELP: 89*e71b7053SJung-uk Kim opt_help(dsa_options); 90*e71b7053SJung-uk Kim ret = 0; 91*e71b7053SJung-uk Kim goto end; 92*e71b7053SJung-uk Kim case OPT_INFORM: 93*e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat)) 94*e71b7053SJung-uk Kim goto opthelp; 95*e71b7053SJung-uk Kim break; 96*e71b7053SJung-uk Kim case OPT_IN: 97*e71b7053SJung-uk Kim infile = opt_arg(); 98*e71b7053SJung-uk Kim break; 99*e71b7053SJung-uk Kim case OPT_OUTFORM: 100*e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat)) 101*e71b7053SJung-uk Kim goto opthelp; 102*e71b7053SJung-uk Kim break; 103*e71b7053SJung-uk Kim case OPT_OUT: 104*e71b7053SJung-uk Kim outfile = opt_arg(); 105*e71b7053SJung-uk Kim break; 106*e71b7053SJung-uk Kim case OPT_ENGINE: 107*e71b7053SJung-uk Kim e = setup_engine(opt_arg(), 0); 108*e71b7053SJung-uk Kim break; 109*e71b7053SJung-uk Kim case OPT_PASSIN: 110*e71b7053SJung-uk Kim passinarg = opt_arg(); 111*e71b7053SJung-uk Kim break; 112*e71b7053SJung-uk Kim case OPT_PASSOUT: 113*e71b7053SJung-uk Kim passoutarg = opt_arg(); 114*e71b7053SJung-uk Kim break; 115*e71b7053SJung-uk Kim case OPT_PVK_STRONG: /* pvk_encr:= 2 */ 116*e71b7053SJung-uk Kim case OPT_PVK_WEAK: /* pvk_encr:= 1 */ 117*e71b7053SJung-uk Kim case OPT_PVK_NONE: /* pvk_encr:= 0 */ 118*e71b7053SJung-uk Kim #ifndef OPENSSL_NO_RC4 119*e71b7053SJung-uk Kim pvk_encr = (o - OPT_PVK_NONE); 120*e71b7053SJung-uk Kim #endif 121*e71b7053SJung-uk Kim break; 122*e71b7053SJung-uk Kim case OPT_NOOUT: 12374664626SKris Kennaway noout = 1; 124*e71b7053SJung-uk Kim break; 125*e71b7053SJung-uk Kim case OPT_TEXT: 12674664626SKris Kennaway text = 1; 127*e71b7053SJung-uk Kim break; 128*e71b7053SJung-uk Kim case OPT_MODULUS: 12974664626SKris Kennaway modulus = 1; 130*e71b7053SJung-uk Kim break; 131*e71b7053SJung-uk Kim case OPT_PUBIN: 132f579bf8eSKris Kennaway pubin = 1; 133*e71b7053SJung-uk Kim break; 134*e71b7053SJung-uk Kim case OPT_PUBOUT: 135f579bf8eSKris Kennaway pubout = 1; 136*e71b7053SJung-uk Kim break; 137*e71b7053SJung-uk Kim case OPT_CIPHER: 138*e71b7053SJung-uk Kim if (!opt_cipher(opt_unknown(), &enc)) 139*e71b7053SJung-uk Kim goto end; 14074664626SKris Kennaway break; 14174664626SKris Kennaway } 14274664626SKris Kennaway } 143*e71b7053SJung-uk Kim argc = opt_num_rest(); 144*e71b7053SJung-uk Kim if (argc != 0) 145*e71b7053SJung-uk Kim goto opthelp; 14674664626SKris Kennaway 147*e71b7053SJung-uk Kim private = pubin || pubout ? 0 : 1; 148*e71b7053SJung-uk Kim if (text && !pubin) 149*e71b7053SJung-uk Kim private = 1; 15074664626SKris Kennaway 151*e71b7053SJung-uk Kim if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { 152f579bf8eSKris Kennaway BIO_printf(bio_err, "Error getting passwords\n"); 153f579bf8eSKris Kennaway goto end; 154f579bf8eSKris Kennaway } 155f579bf8eSKris Kennaway 156f579bf8eSKris Kennaway BIO_printf(bio_err, "read DSA key\n"); 15774664626SKris Kennaway { 158db522d3aSSimon L. B. Nielsen EVP_PKEY *pkey; 1591f13597dSJung-uk Kim 160db522d3aSSimon L. B. Nielsen if (pubin) 161*e71b7053SJung-uk Kim pkey = load_pubkey(infile, informat, 1, passin, e, "Public Key"); 162db522d3aSSimon L. B. Nielsen else 163*e71b7053SJung-uk Kim pkey = load_key(infile, informat, 1, passin, e, "Private Key"); 164db522d3aSSimon L. B. Nielsen 165*e71b7053SJung-uk Kim if (pkey != NULL) { 1661f13597dSJung-uk Kim dsa = EVP_PKEY_get1_DSA(pkey); 167db522d3aSSimon L. B. Nielsen EVP_PKEY_free(pkey); 16874664626SKris Kennaway } 1691f13597dSJung-uk Kim } 1706f9291ceSJung-uk Kim if (dsa == NULL) { 171f579bf8eSKris Kennaway BIO_printf(bio_err, "unable to load Key\n"); 17274664626SKris Kennaway ERR_print_errors(bio_err); 17374664626SKris Kennaway goto end; 17474664626SKris Kennaway } 17574664626SKris Kennaway 176*e71b7053SJung-uk Kim out = bio_open_owner(outfile, outformat, private); 177*e71b7053SJung-uk Kim if (out == NULL) 17874664626SKris Kennaway goto end; 17974664626SKris Kennaway 180*e71b7053SJung-uk Kim if (text) { 181*e71b7053SJung-uk Kim assert(pubin || private); 1826f9291ceSJung-uk Kim if (!DSA_print(out, dsa, 0)) { 18374664626SKris Kennaway perror(outfile); 18474664626SKris Kennaway ERR_print_errors(bio_err); 18574664626SKris Kennaway goto end; 18674664626SKris Kennaway } 18774664626SKris Kennaway } 18874664626SKris Kennaway 189*e71b7053SJung-uk Kim if (modulus) { 190*e71b7053SJung-uk Kim const BIGNUM *pub_key = NULL; 191*e71b7053SJung-uk Kim DSA_get0_key(dsa, &pub_key, NULL); 192*e71b7053SJung-uk Kim BIO_printf(out, "Public Key="); 193*e71b7053SJung-uk Kim BN_print(out, pub_key); 194*e71b7053SJung-uk Kim BIO_printf(out, "\n"); 195*e71b7053SJung-uk Kim } 196*e71b7053SJung-uk Kim 197*e71b7053SJung-uk Kim if (noout) { 198*e71b7053SJung-uk Kim ret = 0; 1996f9291ceSJung-uk Kim goto end; 200*e71b7053SJung-uk Kim } 201f579bf8eSKris Kennaway BIO_printf(bio_err, "writing DSA key\n"); 202f579bf8eSKris Kennaway if (outformat == FORMAT_ASN1) { 203*e71b7053SJung-uk Kim if (pubin || pubout) { 2046f9291ceSJung-uk Kim i = i2d_DSA_PUBKEY_bio(out, dsa); 205*e71b7053SJung-uk Kim } else { 206*e71b7053SJung-uk Kim assert(private); 2076f9291ceSJung-uk Kim i = i2d_DSAPrivateKey_bio(out, dsa); 208*e71b7053SJung-uk Kim } 209f579bf8eSKris Kennaway } else if (outformat == FORMAT_PEM) { 210*e71b7053SJung-uk Kim if (pubin || pubout) { 211f579bf8eSKris Kennaway i = PEM_write_bio_DSA_PUBKEY(out, dsa); 212*e71b7053SJung-uk Kim } else { 213*e71b7053SJung-uk Kim assert(private); 2146f9291ceSJung-uk Kim i = PEM_write_bio_DSAPrivateKey(out, dsa, enc, 215f579bf8eSKris Kennaway NULL, 0, NULL, passout); 216*e71b7053SJung-uk Kim } 217*e71b7053SJung-uk Kim # ifndef OPENSSL_NO_RSA 2181f13597dSJung-uk Kim } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) { 2191f13597dSJung-uk Kim EVP_PKEY *pk; 2201f13597dSJung-uk Kim pk = EVP_PKEY_new(); 221c4ad4dffSJung-uk Kim if (pk == NULL) 222c4ad4dffSJung-uk Kim goto end; 223c4ad4dffSJung-uk Kim 2241f13597dSJung-uk Kim EVP_PKEY_set1_DSA(pk, dsa); 225*e71b7053SJung-uk Kim if (outformat == FORMAT_PVK) { 226*e71b7053SJung-uk Kim if (pubin) { 227*e71b7053SJung-uk Kim BIO_printf(bio_err, "PVK form impossible with public key input\n"); 228*e71b7053SJung-uk Kim EVP_PKEY_free(pk); 229*e71b7053SJung-uk Kim goto end; 230*e71b7053SJung-uk Kim } 231*e71b7053SJung-uk Kim assert(private); 232*e71b7053SJung-uk Kim # ifdef OPENSSL_NO_RC4 233*e71b7053SJung-uk Kim BIO_printf(bio_err, "PVK format not supported\n"); 234*e71b7053SJung-uk Kim EVP_PKEY_free(pk); 235*e71b7053SJung-uk Kim goto end; 236*e71b7053SJung-uk Kim # else 2371f13597dSJung-uk Kim i = i2b_PVK_bio(out, pk, pvk_encr, 0, passout); 238*e71b7053SJung-uk Kim # endif 239*e71b7053SJung-uk Kim } else if (pubin || pubout) { 2401f13597dSJung-uk Kim i = i2b_PublicKey_bio(out, pk); 241*e71b7053SJung-uk Kim } else { 242*e71b7053SJung-uk Kim assert(private); 2431f13597dSJung-uk Kim i = i2b_PrivateKey_bio(out, pk); 244*e71b7053SJung-uk Kim } 2451f13597dSJung-uk Kim EVP_PKEY_free(pk); 2461f13597dSJung-uk Kim # endif 247f579bf8eSKris Kennaway } else { 24874664626SKris Kennaway BIO_printf(bio_err, "bad output format specified for outfile\n"); 24974664626SKris Kennaway goto end; 25074664626SKris Kennaway } 2516f9291ceSJung-uk Kim if (i <= 0) { 25274664626SKris Kennaway BIO_printf(bio_err, "unable to write private key\n"); 25374664626SKris Kennaway ERR_print_errors(bio_err); 254*e71b7053SJung-uk Kim goto end; 255*e71b7053SJung-uk Kim } 25674664626SKris Kennaway ret = 0; 25774664626SKris Kennaway end: 2586f9291ceSJung-uk Kim BIO_free_all(out); 2596f9291ceSJung-uk Kim DSA_free(dsa); 2606cf8931aSJung-uk Kim release_engine(e); 2616f9291ceSJung-uk Kim OPENSSL_free(passin); 2626f9291ceSJung-uk Kim OPENSSL_free(passout); 263*e71b7053SJung-uk Kim return ret; 26474664626SKris Kennaway } 26574664626SKris Kennaway #endif 266