1*4724848cSchristos /*
2*4724848cSchristos * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
3c9496f6bSchristos *
4*4724848cSchristos * Licensed under the OpenSSL license (the "License"). You may not use
5*4724848cSchristos * this file except in compliance with the License. You can obtain a copy
6*4724848cSchristos * in the file LICENSE in the source distribution or at
7*4724848cSchristos * https://www.openssl.org/source/license.html
8c9496f6bSchristos */
9c9496f6bSchristos
10*4724848cSchristos #include <openssl/opensslconf.h>
11c9496f6bSchristos #include <stdio.h>
12c9496f6bSchristos #include <stdlib.h>
13c9496f6bSchristos #include <string.h>
14c9496f6bSchristos #include <time.h>
15c9496f6bSchristos #include "apps.h"
16*4724848cSchristos #include "progs.h"
17c9496f6bSchristos #include <openssl/bio.h>
18c9496f6bSchristos #include <openssl/err.h>
19c9496f6bSchristos #include <openssl/dsa.h>
20c9496f6bSchristos #include <openssl/evp.h>
21c9496f6bSchristos #include <openssl/x509.h>
22c9496f6bSchristos #include <openssl/pem.h>
23c9496f6bSchristos #include <openssl/bn.h>
24c9496f6bSchristos
25*4724848cSchristos typedef enum OPTION_choice {
26*4724848cSchristos OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
27*4724848cSchristos OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENGINE,
28*4724848cSchristos /* Do not change the order here; see case statements below */
29*4724848cSchristos OPT_PVK_NONE, OPT_PVK_WEAK, OPT_PVK_STRONG,
30*4724848cSchristos OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_PUBIN,
31*4724848cSchristos OPT_PUBOUT, OPT_CIPHER, OPT_PASSIN, OPT_PASSOUT
32*4724848cSchristos } OPTION_CHOICE;
33c9496f6bSchristos
34*4724848cSchristos const OPTIONS dsa_options[] = {
35*4724848cSchristos {"help", OPT_HELP, '-', "Display this summary"},
36*4724848cSchristos {"inform", OPT_INFORM, 'f', "Input format, DER PEM PVK"},
37*4724848cSchristos {"outform", OPT_OUTFORM, 'f', "Output format, DER PEM PVK"},
38*4724848cSchristos {"in", OPT_IN, 's', "Input key"},
39*4724848cSchristos {"out", OPT_OUT, '>', "Output file"},
40*4724848cSchristos {"noout", OPT_NOOUT, '-', "Don't print key out"},
41*4724848cSchristos {"text", OPT_TEXT, '-', "Print the key in text"},
42*4724848cSchristos {"modulus", OPT_MODULUS, '-', "Print the DSA public value"},
43*4724848cSchristos {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"},
44*4724848cSchristos {"pubout", OPT_PUBOUT, '-', "Output public key, not private"},
45*4724848cSchristos {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
46*4724848cSchristos {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
47*4724848cSchristos {"", OPT_CIPHER, '-', "Any supported cipher"},
48*4724848cSchristos #ifndef OPENSSL_NO_RC4
49*4724848cSchristos {"pvk-strong", OPT_PVK_STRONG, '-', "Enable 'Strong' PVK encoding level (default)"},
50*4724848cSchristos {"pvk-weak", OPT_PVK_WEAK, '-', "Enable 'Weak' PVK encoding level"},
51*4724848cSchristos {"pvk-none", OPT_PVK_NONE, '-', "Don't enforce PVK encoding"},
52c9496f6bSchristos #endif
53*4724848cSchristos #ifndef OPENSSL_NO_ENGINE
54*4724848cSchristos {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
55*4724848cSchristos #endif
56*4724848cSchristos {NULL}
57*4724848cSchristos };
58*4724848cSchristos
dsa_main(int argc,char ** argv)59*4724848cSchristos int dsa_main(int argc, char **argv)
60*4724848cSchristos {
61*4724848cSchristos BIO *out = NULL;
62*4724848cSchristos DSA *dsa = NULL;
63*4724848cSchristos ENGINE *e = NULL;
64*4724848cSchristos const EVP_CIPHER *enc = NULL;
65*4724848cSchristos char *infile = NULL, *outfile = NULL, *prog;
66*4724848cSchristos char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL;
67*4724848cSchristos OPTION_CHOICE o;
68*4724848cSchristos int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, noout = 0;
69*4724848cSchristos int i, modulus = 0, pubin = 0, pubout = 0, ret = 1;
70*4724848cSchristos #ifndef OPENSSL_NO_RC4
71*4724848cSchristos int pvk_encr = 2;
72*4724848cSchristos #endif
73*4724848cSchristos int private = 0;
74*4724848cSchristos
75*4724848cSchristos prog = opt_init(argc, argv, dsa_options);
76*4724848cSchristos while ((o = opt_next()) != OPT_EOF) {
77*4724848cSchristos switch (o) {
78*4724848cSchristos case OPT_EOF:
79*4724848cSchristos case OPT_ERR:
80*4724848cSchristos opthelp:
81*4724848cSchristos ret = 0;
82*4724848cSchristos BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
83*4724848cSchristos goto end;
84*4724848cSchristos case OPT_HELP:
85*4724848cSchristos opt_help(dsa_options);
86*4724848cSchristos ret = 0;
87*4724848cSchristos goto end;
88*4724848cSchristos case OPT_INFORM:
89*4724848cSchristos if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat))
90*4724848cSchristos goto opthelp;
91*4724848cSchristos break;
92*4724848cSchristos case OPT_IN:
93*4724848cSchristos infile = opt_arg();
94*4724848cSchristos break;
95*4724848cSchristos case OPT_OUTFORM:
96*4724848cSchristos if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat))
97*4724848cSchristos goto opthelp;
98*4724848cSchristos break;
99*4724848cSchristos case OPT_OUT:
100*4724848cSchristos outfile = opt_arg();
101*4724848cSchristos break;
102*4724848cSchristos case OPT_ENGINE:
103*4724848cSchristos e = setup_engine(opt_arg(), 0);
104*4724848cSchristos break;
105*4724848cSchristos case OPT_PASSIN:
106*4724848cSchristos passinarg = opt_arg();
107*4724848cSchristos break;
108*4724848cSchristos case OPT_PASSOUT:
109*4724848cSchristos passoutarg = opt_arg();
110*4724848cSchristos break;
111*4724848cSchristos case OPT_PVK_STRONG: /* pvk_encr:= 2 */
112*4724848cSchristos case OPT_PVK_WEAK: /* pvk_encr:= 1 */
113*4724848cSchristos case OPT_PVK_NONE: /* pvk_encr:= 0 */
114*4724848cSchristos #ifndef OPENSSL_NO_RC4
115*4724848cSchristos pvk_encr = (o - OPT_PVK_NONE);
116*4724848cSchristos #endif
117*4724848cSchristos break;
118*4724848cSchristos case OPT_NOOUT:
119c9496f6bSchristos noout = 1;
120*4724848cSchristos break;
121*4724848cSchristos case OPT_TEXT:
122c9496f6bSchristos text = 1;
123*4724848cSchristos break;
124*4724848cSchristos case OPT_MODULUS:
125c9496f6bSchristos modulus = 1;
126*4724848cSchristos break;
127*4724848cSchristos case OPT_PUBIN:
128c9496f6bSchristos pubin = 1;
129*4724848cSchristos break;
130*4724848cSchristos case OPT_PUBOUT:
131c9496f6bSchristos pubout = 1;
132*4724848cSchristos break;
133*4724848cSchristos case OPT_CIPHER:
134*4724848cSchristos if (!opt_cipher(opt_unknown(), &enc))
135*4724848cSchristos goto end;
136c9496f6bSchristos break;
137c9496f6bSchristos }
138c9496f6bSchristos }
139*4724848cSchristos argc = opt_num_rest();
140*4724848cSchristos if (argc != 0)
141*4724848cSchristos goto opthelp;
142c9496f6bSchristos
143*4724848cSchristos private = pubin || pubout ? 0 : 1;
144*4724848cSchristos if (text && !pubin)
145*4724848cSchristos private = 1;
146c9496f6bSchristos
147*4724848cSchristos if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
148c9496f6bSchristos BIO_printf(bio_err, "Error getting passwords\n");
149c9496f6bSchristos goto end;
150c9496f6bSchristos }
151c9496f6bSchristos
152c9496f6bSchristos BIO_printf(bio_err, "read DSA key\n");
153c9496f6bSchristos {
154c9496f6bSchristos EVP_PKEY *pkey;
155c9496f6bSchristos
156c9496f6bSchristos if (pubin)
157*4724848cSchristos pkey = load_pubkey(infile, informat, 1, passin, e, "Public Key");
158c9496f6bSchristos else
159*4724848cSchristos pkey = load_key(infile, informat, 1, passin, e, "Private Key");
160c9496f6bSchristos
161*4724848cSchristos if (pkey != NULL) {
162c9496f6bSchristos dsa = EVP_PKEY_get1_DSA(pkey);
163c9496f6bSchristos EVP_PKEY_free(pkey);
164c9496f6bSchristos }
165c9496f6bSchristos }
166c9496f6bSchristos if (dsa == NULL) {
167c9496f6bSchristos BIO_printf(bio_err, "unable to load Key\n");
168c9496f6bSchristos ERR_print_errors(bio_err);
169c9496f6bSchristos goto end;
170c9496f6bSchristos }
171c9496f6bSchristos
172*4724848cSchristos out = bio_open_owner(outfile, outformat, private);
173*4724848cSchristos if (out == NULL)
174c9496f6bSchristos goto end;
175c9496f6bSchristos
176*4724848cSchristos if (text) {
177*4724848cSchristos assert(pubin || private);
178c9496f6bSchristos if (!DSA_print(out, dsa, 0)) {
179c9496f6bSchristos perror(outfile);
180c9496f6bSchristos ERR_print_errors(bio_err);
181c9496f6bSchristos goto end;
182c9496f6bSchristos }
183c9496f6bSchristos }
184c9496f6bSchristos
185*4724848cSchristos if (modulus) {
186*4724848cSchristos const BIGNUM *pub_key = NULL;
187*4724848cSchristos DSA_get0_key(dsa, &pub_key, NULL);
188*4724848cSchristos BIO_printf(out, "Public Key=");
189*4724848cSchristos BN_print(out, pub_key);
190*4724848cSchristos BIO_printf(out, "\n");
191*4724848cSchristos }
192*4724848cSchristos
193*4724848cSchristos if (noout) {
194*4724848cSchristos ret = 0;
195c9496f6bSchristos goto end;
196*4724848cSchristos }
197c9496f6bSchristos BIO_printf(bio_err, "writing DSA key\n");
198c9496f6bSchristos if (outformat == FORMAT_ASN1) {
199*4724848cSchristos if (pubin || pubout) {
200c9496f6bSchristos i = i2d_DSA_PUBKEY_bio(out, dsa);
201*4724848cSchristos } else {
202*4724848cSchristos assert(private);
203c9496f6bSchristos i = i2d_DSAPrivateKey_bio(out, dsa);
204*4724848cSchristos }
205c9496f6bSchristos } else if (outformat == FORMAT_PEM) {
206*4724848cSchristos if (pubin || pubout) {
207c9496f6bSchristos i = PEM_write_bio_DSA_PUBKEY(out, dsa);
208*4724848cSchristos } else {
209*4724848cSchristos assert(private);
210c9496f6bSchristos i = PEM_write_bio_DSAPrivateKey(out, dsa, enc,
211c9496f6bSchristos NULL, 0, NULL, passout);
212*4724848cSchristos }
213*4724848cSchristos #ifndef OPENSSL_NO_RSA
214c9496f6bSchristos } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) {
215c9496f6bSchristos EVP_PKEY *pk;
216c9496f6bSchristos pk = EVP_PKEY_new();
217*4724848cSchristos if (pk == NULL)
218*4724848cSchristos goto end;
219*4724848cSchristos
220c9496f6bSchristos EVP_PKEY_set1_DSA(pk, dsa);
221*4724848cSchristos if (outformat == FORMAT_PVK) {
222*4724848cSchristos if (pubin) {
223*4724848cSchristos BIO_printf(bio_err, "PVK form impossible with public key input\n");
224*4724848cSchristos EVP_PKEY_free(pk);
225*4724848cSchristos goto end;
226*4724848cSchristos }
227*4724848cSchristos assert(private);
228*4724848cSchristos # ifdef OPENSSL_NO_RC4
229*4724848cSchristos BIO_printf(bio_err, "PVK format not supported\n");
230*4724848cSchristos EVP_PKEY_free(pk);
231*4724848cSchristos goto end;
232*4724848cSchristos # else
233c9496f6bSchristos i = i2b_PVK_bio(out, pk, pvk_encr, 0, passout);
234*4724848cSchristos # endif
235*4724848cSchristos } else if (pubin || pubout) {
236c9496f6bSchristos i = i2b_PublicKey_bio(out, pk);
237*4724848cSchristos } else {
238*4724848cSchristos assert(private);
239c9496f6bSchristos i = i2b_PrivateKey_bio(out, pk);
240*4724848cSchristos }
241c9496f6bSchristos EVP_PKEY_free(pk);
242c9496f6bSchristos #endif
243c9496f6bSchristos } else {
244c9496f6bSchristos BIO_printf(bio_err, "bad output format specified for outfile\n");
245c9496f6bSchristos goto end;
246c9496f6bSchristos }
247c9496f6bSchristos if (i <= 0) {
248c9496f6bSchristos BIO_printf(bio_err, "unable to write private key\n");
249c9496f6bSchristos ERR_print_errors(bio_err);
250*4724848cSchristos goto end;
251*4724848cSchristos }
252c9496f6bSchristos ret = 0;
253c9496f6bSchristos end:
254c9496f6bSchristos BIO_free_all(out);
255c9496f6bSchristos DSA_free(dsa);
256c9496f6bSchristos release_engine(e);
257c9496f6bSchristos OPENSSL_free(passin);
258c9496f6bSchristos OPENSSL_free(passout);
259*4724848cSchristos return ret;
260c9496f6bSchristos }
261