Annotation of src/usr.bin/openssl/dsa.c, Revision 1.8
1.8 ! doug 1: /* $OpenBSD: dsa.c,v 1.7 2015/10/17 07:51:10 semarie Exp $ */
1.1 jsing 2: /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3: * All rights reserved.
4: *
5: * This package is an SSL implementation written
6: * by Eric Young (eay@cryptsoft.com).
7: * The implementation was written so as to conform with Netscapes SSL.
8: *
9: * This library is free for commercial and non-commercial use as long as
10: * the following conditions are aheared to. The following conditions
11: * apply to all code found in this distribution, be it the RC4, RSA,
12: * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13: * included with this distribution is covered by the same copyright terms
14: * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15: *
16: * Copyright remains Eric Young's, and as such any Copyright notices in
17: * the code are not to be removed.
18: * If this package is used in a product, Eric Young should be given attribution
19: * as the author of the parts of the library used.
20: * This can be in the form of a textual message at program startup or
21: * in documentation (online or textual) provided with the package.
22: *
23: * Redistribution and use in source and binary forms, with or without
24: * modification, are permitted provided that the following conditions
25: * are met:
26: * 1. Redistributions of source code must retain the copyright
27: * notice, this list of conditions and the following disclaimer.
28: * 2. Redistributions in binary form must reproduce the above copyright
29: * notice, this list of conditions and the following disclaimer in the
30: * documentation and/or other materials provided with the distribution.
31: * 3. All advertising materials mentioning features or use of this software
32: * must display the following acknowledgement:
33: * "This product includes cryptographic software written by
34: * Eric Young (eay@cryptsoft.com)"
35: * The word 'cryptographic' can be left out if the rouines from the library
36: * being used are not cryptographic related :-).
37: * 4. If you include any Windows specific code (or a derivative thereof) from
38: * the apps directory (application code) you must include an acknowledgement:
39: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40: *
41: * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51: * SUCH DAMAGE.
52: *
53: * The licence and distribution terms for any publically available version or
54: * derivative of this code cannot be changed. i.e. this code cannot simply be
55: * copied and put under another distribution licence
56: * [including the GNU Public Licence.]
57: */
58:
59: #include <openssl/opensslconf.h> /* for OPENSSL_NO_DSA */
60:
1.3 doug 61: #include <ctype.h>
1.1 jsing 62: #include <stdio.h>
63: #include <stdlib.h>
64: #include <time.h>
65: #include <string.h>
66:
67: #include "apps.h"
68:
69: #include <openssl/bio.h>
70: #include <openssl/bn.h>
71: #include <openssl/dsa.h>
72: #include <openssl/err.h>
73: #include <openssl/evp.h>
74: #include <openssl/pem.h>
75: #include <openssl/x509.h>
76:
1.3 doug 77: static struct {
78: const EVP_CIPHER *enc;
79: char *infile;
80: int informat;
81: int modulus;
82: int noout;
83: char *outfile;
84: int outformat;
85: char *passargin;
86: char *passargout;
87: int pubin;
88: int pubout;
89: int pvk_encr;
90: int text;
91: } dsa_config;
92:
93: static int
94: dsa_opt_enc(int argc, char **argv, int *argsused)
95: {
96: char *name = argv[0];
97:
98: if (*name++ != '-')
99: return (1);
100:
101: if ((dsa_config.enc = EVP_get_cipherbyname(name)) != NULL) {
102: *argsused = 1;
103: return (0);
104: }
105:
106: return (1);
107: }
108:
109: static struct option dsa_options[] = {
110: {
111: .name = "in",
112: .argname = "file",
113: .desc = "Input file (default stdin)",
114: .type = OPTION_ARG,
115: .opt.arg = &dsa_config.infile,
116: },
117: {
118: .name = "inform",
119: .argname = "format",
120: .desc = "Input format (PEM (default) or any other supported"
121: " format)",
122: .type = OPTION_ARG_FORMAT,
123: .opt.value = &dsa_config.informat,
124: },
125: {
126: .name = "noout",
127: .desc = "No output",
128: .type = OPTION_FLAG,
129: .opt.flag = &dsa_config.noout,
130: },
131: {
132: .name = "out",
133: .argname = "file",
134: .desc = "Output file (default stdout)",
135: .type = OPTION_ARG,
136: .opt.arg = &dsa_config.outfile,
137: },
138: {
139: .name = "outform",
140: .argname = "format",
141: .desc = "Output format (DER, MSBLOB, PEM (default) or PVK)",
142: .type = OPTION_ARG_FORMAT,
143: .opt.value = &dsa_config.outformat,
144: },
145: {
146: .name = "passin",
147: .argname = "source",
148: .desc = "Input file passphrase source",
149: .type = OPTION_ARG,
150: .opt.arg = &dsa_config.passargin,
151: },
152: {
153: .name = "passout",
154: .argname = "source",
155: .desc = "Output file passphrase source",
156: .type = OPTION_ARG,
157: .opt.arg = &dsa_config.passargout,
158: },
159: {
160: .name = "pubin",
161: .desc = "Read a public key from the input file instead of"
162: " private key",
163: .type = OPTION_FLAG,
164: .opt.flag = &dsa_config.pubin,
165: },
166: {
167: .name = "pubout",
168: .desc = "Output a public key instead of private key",
169: .type = OPTION_FLAG,
170: .opt.flag = &dsa_config.pubout,
171: },
172: {
173: .name = "pvk-none",
174: .desc = "PVK encryption level",
175: .type = OPTION_VALUE,
176: .value = 0,
177: .opt.value = &dsa_config.pvk_encr,
178: },
179: {
180: .name = "pvk-strong",
181: .desc = "PVK encryption level (default)",
182: .type = OPTION_VALUE,
183: .value = 2,
184: .opt.value = &dsa_config.pvk_encr,
185: },
186: {
187: .name = "pvk-weak",
188: .desc = "PVK encryption level",
189: .type = OPTION_VALUE,
190: .value = 1,
191: .opt.value = &dsa_config.pvk_encr,
192: },
193: {
194: .name = "text",
195: .desc = "Print the key in text form",
196: .type = OPTION_FLAG,
197: .opt.flag = &dsa_config.text,
198: },
199: {
200: .name = NULL,
201: .type = OPTION_ARGV_FUNC,
202: .opt.argvfunc = dsa_opt_enc,
203: },
204: { NULL },
205: };
206:
207: static void
208: show_ciphers(const OBJ_NAME *name, void *arg)
209: {
210: static int n;
211:
212: if (!islower((unsigned char)*name->name))
213: return;
214:
215: fprintf(stderr, " -%-24s%s", name->name, (++n % 3 ? "" : "\n"));
216: }
217:
218: static void
219: dsa_usage(void)
220: {
221: fprintf(stderr,
1.5 bcook 222: "usage: dsa [-in file] [-inform format] [-noout]\n"
1.3 doug 223: " [-out file] [-outform format] [-passin src] [-passout src]\n"
224: " [-pubin] [-pubout] [-pvk-none | -pvk-strong | -pvk-weak]\n"
225: " [-text] [-ciphername]\n\n");
226: options_usage(dsa_options);
227: fprintf(stderr, "\n");
228:
229: fprintf(stderr, "Valid ciphername values:\n\n");
230: OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, show_ciphers, NULL);
231: fprintf(stderr, "\n");
232: }
1.1 jsing 233:
234: int
235: dsa_main(int argc, char **argv)
236: {
237: int ret = 1;
238: DSA *dsa = NULL;
1.3 doug 239: int i;
1.1 jsing 240: BIO *in = NULL, *out = NULL;
241: char *passin = NULL, *passout = NULL;
1.6 doug 242:
243: if (single_execution) {
1.8 ! doug 244: if (pledge("stdio rpath wpath cpath tty", NULL) == -1) {
1.6 doug 245: perror("pledge");
1.8 ! doug 246: exit(1);
! 247: }
1.6 doug 248: }
1.1 jsing 249:
1.3 doug 250: memset(&dsa_config, 0, sizeof(dsa_config));
1.1 jsing 251:
1.3 doug 252: dsa_config.pvk_encr = 2;
253: dsa_config.informat = FORMAT_PEM;
254: dsa_config.outformat = FORMAT_PEM;
1.1 jsing 255:
1.3 doug 256: if (options_parse(argc, argv, dsa_options, NULL, NULL) != 0) {
257: dsa_usage();
1.1 jsing 258: goto end;
259: }
260:
1.3 doug 261: if (!app_passwd(bio_err, dsa_config.passargin, dsa_config.passargout,
262: &passin, &passout)) {
1.1 jsing 263: BIO_printf(bio_err, "Error getting passwords\n");
264: goto end;
265: }
1.3 doug 266:
1.1 jsing 267: in = BIO_new(BIO_s_file());
268: out = BIO_new(BIO_s_file());
1.3 doug 269: if (in == NULL || out == NULL) {
1.1 jsing 270: ERR_print_errors(bio_err);
271: goto end;
272: }
1.3 doug 273: if (dsa_config.infile == NULL)
1.1 jsing 274: BIO_set_fp(in, stdin, BIO_NOCLOSE);
275: else {
1.3 doug 276: if (BIO_read_filename(in, dsa_config.infile) <= 0) {
277: perror(dsa_config.infile);
1.1 jsing 278: goto end;
279: }
280: }
281:
282: BIO_printf(bio_err, "read DSA key\n");
283:
284: {
285: EVP_PKEY *pkey;
286:
1.3 doug 287: if (dsa_config.pubin)
288: pkey = load_pubkey(bio_err, dsa_config.infile,
1.5 bcook 289: dsa_config.informat, 1, passin, "Public Key");
1.1 jsing 290: else
1.3 doug 291: pkey = load_key(bio_err, dsa_config.infile,
1.5 bcook 292: dsa_config.informat, 1, passin, "Private Key");
1.1 jsing 293:
294: if (pkey) {
295: dsa = EVP_PKEY_get1_DSA(pkey);
296: EVP_PKEY_free(pkey);
297: }
298: }
299: if (dsa == NULL) {
300: BIO_printf(bio_err, "unable to load Key\n");
301: ERR_print_errors(bio_err);
302: goto end;
303: }
1.3 doug 304: if (dsa_config.outfile == NULL) {
1.1 jsing 305: BIO_set_fp(out, stdout, BIO_NOCLOSE);
306: } else {
1.3 doug 307: if (BIO_write_filename(out, dsa_config.outfile) <= 0) {
308: perror(dsa_config.outfile);
1.1 jsing 309: goto end;
310: }
311: }
312:
1.3 doug 313: if (dsa_config.text) {
1.1 jsing 314: if (!DSA_print(out, dsa, 0)) {
1.3 doug 315: perror(dsa_config.outfile);
1.1 jsing 316: ERR_print_errors(bio_err);
317: goto end;
318: }
319: }
1.3 doug 320: if (dsa_config.modulus) {
1.1 jsing 321: fprintf(stdout, "Public Key=");
322: BN_print(out, dsa->pub_key);
323: fprintf(stdout, "\n");
324: }
1.3 doug 325: if (dsa_config.noout)
1.1 jsing 326: goto end;
327: BIO_printf(bio_err, "writing DSA key\n");
1.3 doug 328: if (dsa_config.outformat == FORMAT_ASN1) {
329: if (dsa_config.pubin || dsa_config.pubout)
1.1 jsing 330: i = i2d_DSA_PUBKEY_bio(out, dsa);
331: else
332: i = i2d_DSAPrivateKey_bio(out, dsa);
1.3 doug 333: } else if (dsa_config.outformat == FORMAT_PEM) {
334: if (dsa_config.pubin || dsa_config.pubout)
1.1 jsing 335: i = PEM_write_bio_DSA_PUBKEY(out, dsa);
336: else
1.3 doug 337: i = PEM_write_bio_DSAPrivateKey(out, dsa, dsa_config.enc,
1.1 jsing 338: NULL, 0, NULL, passout);
339: #if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_RC4)
1.3 doug 340: } else if (dsa_config.outformat == FORMAT_MSBLOB ||
341: dsa_config.outformat == FORMAT_PVK) {
1.1 jsing 342: EVP_PKEY *pk;
343: pk = EVP_PKEY_new();
344: EVP_PKEY_set1_DSA(pk, dsa);
1.3 doug 345: if (dsa_config.outformat == FORMAT_PVK)
346: i = i2b_PVK_bio(out, pk, dsa_config.pvk_encr, 0,
347: passout);
348: else if (dsa_config.pubin || dsa_config.pubout)
1.1 jsing 349: i = i2b_PublicKey_bio(out, pk);
350: else
351: i = i2b_PrivateKey_bio(out, pk);
352: EVP_PKEY_free(pk);
353: #endif
354: } else {
355: BIO_printf(bio_err, "bad output format specified for outfile\n");
356: goto end;
357: }
358: if (i <= 0) {
359: BIO_printf(bio_err, "unable to write private key\n");
360: ERR_print_errors(bio_err);
361: } else
362: ret = 0;
363: end:
364: BIO_free(in);
365: if (out != NULL)
366: BIO_free_all(out);
367: if (dsa != NULL)
368: DSA_free(dsa);
369: free(passin);
370: free(passout);
371:
372: return (ret);
373: }