xref: /netbsd-src/crypto/external/bsd/openssl.old/dist/apps/dsa.c (revision 4724848cf0da353df257f730694b7882798e5daf)
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