ec.c revision 167613
1/* apps/ec.c */
2/*
3 * Written by Nils Larsch for the OpenSSL project.
4 */
5/* ====================================================================
6 * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in
17 *    the documentation and/or other materials provided with the
18 *    distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 *    software must display the following acknowledgment:
22 *    "This product includes software developed by the OpenSSL Project
23 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 *    endorse or promote products derived from this software without
27 *    prior written permission. For written permission, please contact
28 *    openssl-core@openssl.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 *    nor may "OpenSSL" appear in their names without prior written
32 *    permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 *    acknowledgment:
36 *    "This product includes software developed by the OpenSSL Project
37 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com).  This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59#include <openssl/opensslconf.h>
60#ifndef OPENSSL_NO_EC
61#include <stdio.h>
62#include <stdlib.h>
63#include <string.h>
64#include "apps.h"
65#include <openssl/bio.h>
66#include <openssl/err.h>
67#include <openssl/evp.h>
68#include <openssl/pem.h>
69
70#undef PROG
71#define PROG	ec_main
72
73/* -inform arg    - input format - default PEM (one of DER, NET or PEM)
74 * -outform arg   - output format - default PEM
75 * -in arg        - input file - default stdin
76 * -out arg       - output file - default stdout
77 * -des           - encrypt output if PEM format with DES in cbc mode
78 * -text          - print a text version
79 * -param_out     - print the elliptic curve parameters
80 * -conv_form arg - specifies the point encoding form
81 * -param_enc arg - specifies the parameter encoding
82 */
83
84int MAIN(int, char **);
85
86int MAIN(int argc, char **argv)
87{
88#ifndef OPENSSL_NO_ENGINE
89	ENGINE 	*e = NULL;
90#endif
91	int 	ret = 1;
92	EC_KEY 	*eckey = NULL;
93	const EC_GROUP *group;
94	int 	i, badops = 0;
95	const EVP_CIPHER *enc = NULL;
96	BIO 	*in = NULL, *out = NULL;
97	int 	informat, outformat, text=0, noout=0;
98	int  	pubin = 0, pubout = 0, param_out = 0;
99	char 	*infile, *outfile, *prog, *engine;
100	char 	*passargin = NULL, *passargout = NULL;
101	char 	*passin = NULL, *passout = NULL;
102	point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
103	int	new_form = 0;
104	int	asn1_flag = OPENSSL_EC_NAMED_CURVE;
105	int 	new_asn1_flag = 0;
106
107	apps_startup();
108
109	if (bio_err == NULL)
110		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
111			BIO_set_fp(bio_err, stderr, BIO_NOCLOSE|BIO_FP_TEXT);
112
113	if (!load_config(bio_err, NULL))
114		goto end;
115
116	engine = NULL;
117	infile = NULL;
118	outfile = NULL;
119	informat = FORMAT_PEM;
120	outformat = FORMAT_PEM;
121
122	prog = argv[0];
123	argc--;
124	argv++;
125	while (argc >= 1)
126		{
127		if (strcmp(*argv,"-inform") == 0)
128			{
129			if (--argc < 1) goto bad;
130			informat=str2fmt(*(++argv));
131			}
132		else if (strcmp(*argv,"-outform") == 0)
133			{
134			if (--argc < 1) goto bad;
135			outformat=str2fmt(*(++argv));
136			}
137		else if (strcmp(*argv,"-in") == 0)
138			{
139			if (--argc < 1) goto bad;
140			infile= *(++argv);
141			}
142		else if (strcmp(*argv,"-out") == 0)
143			{
144			if (--argc < 1) goto bad;
145			outfile= *(++argv);
146			}
147		else if (strcmp(*argv,"-passin") == 0)
148			{
149			if (--argc < 1) goto bad;
150			passargin= *(++argv);
151			}
152		else if (strcmp(*argv,"-passout") == 0)
153			{
154			if (--argc < 1) goto bad;
155			passargout= *(++argv);
156			}
157		else if (strcmp(*argv, "-engine") == 0)
158			{
159			if (--argc < 1) goto bad;
160			engine= *(++argv);
161			}
162		else if (strcmp(*argv, "-noout") == 0)
163			noout = 1;
164		else if (strcmp(*argv, "-text") == 0)
165			text = 1;
166		else if (strcmp(*argv, "-conv_form") == 0)
167			{
168			if (--argc < 1)
169				goto bad;
170			++argv;
171			new_form = 1;
172			if (strcmp(*argv, "compressed") == 0)
173				form = POINT_CONVERSION_COMPRESSED;
174			else if (strcmp(*argv, "uncompressed") == 0)
175				form = POINT_CONVERSION_UNCOMPRESSED;
176			else if (strcmp(*argv, "hybrid") == 0)
177				form = POINT_CONVERSION_HYBRID;
178			else
179				goto bad;
180			}
181		else if (strcmp(*argv, "-param_enc") == 0)
182			{
183			if (--argc < 1)
184				goto bad;
185			++argv;
186			new_asn1_flag = 1;
187			if (strcmp(*argv, "named_curve") == 0)
188				asn1_flag = OPENSSL_EC_NAMED_CURVE;
189			else if (strcmp(*argv, "explicit") == 0)
190				asn1_flag = 0;
191			else
192				goto bad;
193			}
194		else if (strcmp(*argv, "-param_out") == 0)
195			param_out = 1;
196		else if (strcmp(*argv, "-pubin") == 0)
197			pubin=1;
198		else if (strcmp(*argv, "-pubout") == 0)
199			pubout=1;
200		else if ((enc=EVP_get_cipherbyname(&(argv[0][1]))) == NULL)
201			{
202			BIO_printf(bio_err, "unknown option %s\n", *argv);
203			badops=1;
204			break;
205			}
206		argc--;
207		argv++;
208		}
209
210	if (badops)
211		{
212bad:
213		BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog);
214		BIO_printf(bio_err, "where options are\n");
215		BIO_printf(bio_err, " -inform arg     input format - "
216				"DER or PEM\n");
217		BIO_printf(bio_err, " -outform arg    output format - "
218				"DER or PEM\n");
219		BIO_printf(bio_err, " -in arg         input file\n");
220		BIO_printf(bio_err, " -passin arg     input file pass "
221				"phrase source\n");
222		BIO_printf(bio_err, " -out arg        output file\n");
223		BIO_printf(bio_err, " -passout arg    output file pass "
224				"phrase source\n");
225		BIO_printf(bio_err, " -engine e       use engine e, "
226				"possibly a hardware device.\n");
227		BIO_printf(bio_err, " -des            encrypt PEM output, "
228				"instead of 'des' every other \n"
229				"                 cipher "
230				"supported by OpenSSL can be used\n");
231		BIO_printf(bio_err, " -text           print the key\n");
232		BIO_printf(bio_err, " -noout          don't print key out\n");
233		BIO_printf(bio_err, " -param_out      print the elliptic "
234				"curve parameters\n");
235		BIO_printf(bio_err, " -conv_form arg  specifies the "
236				"point conversion form \n");
237		BIO_printf(bio_err, "                 possible values:"
238				" compressed\n");
239		BIO_printf(bio_err, "                                 "
240				" uncompressed (default)\n");
241		BIO_printf(bio_err, "                                  "
242				" hybrid\n");
243		BIO_printf(bio_err, " -param_enc arg  specifies the way"
244				" the ec parameters are encoded\n");
245		BIO_printf(bio_err, "                 in the asn1 der "
246				"encoding\n");
247		BIO_printf(bio_err, "                 possilbe values:"
248				" named_curve (default)\n");
249		BIO_printf(bio_err,"                                  "
250				"explicit\n");
251		goto end;
252		}
253
254	ERR_load_crypto_strings();
255
256#ifndef OPENSSL_NO_ENGINE
257        e = setup_engine(bio_err, engine, 0);
258#endif
259
260	if(!app_passwd(bio_err, passargin, passargout, &passin, &passout))
261		{
262		BIO_printf(bio_err, "Error getting passwords\n");
263		goto end;
264		}
265
266	in = BIO_new(BIO_s_file());
267	out = BIO_new(BIO_s_file());
268	if ((in == NULL) || (out == NULL))
269		{
270		ERR_print_errors(bio_err);
271		goto end;
272		}
273
274	if (infile == NULL)
275		BIO_set_fp(in, stdin, BIO_NOCLOSE);
276	else
277		{
278		if (BIO_read_filename(in, infile) <= 0)
279			{
280			perror(infile);
281			goto end;
282			}
283		}
284
285	BIO_printf(bio_err, "read EC key\n");
286	if (informat == FORMAT_ASN1)
287		{
288		if (pubin)
289			eckey = d2i_EC_PUBKEY_bio(in, NULL);
290		else
291			eckey = d2i_ECPrivateKey_bio(in, NULL);
292		}
293	else if (informat == FORMAT_PEM)
294		{
295		if (pubin)
296			eckey = PEM_read_bio_EC_PUBKEY(in, NULL, NULL,
297				NULL);
298		else
299			eckey = PEM_read_bio_ECPrivateKey(in, NULL, NULL,
300				passin);
301		}
302	else
303		{
304		BIO_printf(bio_err, "bad input format specified for key\n");
305		goto end;
306		}
307	if (eckey == NULL)
308		{
309		BIO_printf(bio_err,"unable to load Key\n");
310		ERR_print_errors(bio_err);
311		goto end;
312		}
313
314	if (outfile == NULL)
315		{
316		BIO_set_fp(out, stdout, BIO_NOCLOSE);
317#ifdef OPENSSL_SYS_VMS
318			{
319			BIO *tmpbio = BIO_new(BIO_f_linebuffer());
320			out = BIO_push(tmpbio, out);
321			}
322#endif
323		}
324	else
325		{
326		if (BIO_write_filename(out, outfile) <= 0)
327			{
328			perror(outfile);
329			goto end;
330			}
331		}
332
333	group = EC_KEY_get0_group(eckey);
334
335	if (new_form)
336		EC_KEY_set_conv_form(eckey, form);
337
338	if (new_asn1_flag)
339		EC_KEY_set_asn1_flag(eckey, asn1_flag);
340
341	if (text)
342		if (!EC_KEY_print(out, eckey, 0))
343			{
344			perror(outfile);
345			ERR_print_errors(bio_err);
346			goto end;
347			}
348
349	if (noout)
350		{
351		ret = 0;
352		goto end;
353		}
354
355	BIO_printf(bio_err, "writing EC key\n");
356	if (outformat == FORMAT_ASN1)
357		{
358		if (param_out)
359			i = i2d_ECPKParameters_bio(out, group);
360		else if (pubin || pubout)
361			i = i2d_EC_PUBKEY_bio(out, eckey);
362		else
363			i = i2d_ECPrivateKey_bio(out, eckey);
364		}
365	else if (outformat == FORMAT_PEM)
366		{
367		if (param_out)
368			i = PEM_write_bio_ECPKParameters(out, group);
369		else if (pubin || pubout)
370			i = PEM_write_bio_EC_PUBKEY(out, eckey);
371		else
372			i = PEM_write_bio_ECPrivateKey(out, eckey, enc,
373						NULL, 0, NULL, passout);
374		}
375	else
376		{
377		BIO_printf(bio_err, "bad output format specified for "
378			"outfile\n");
379		goto end;
380		}
381
382	if (!i)
383		{
384		BIO_printf(bio_err, "unable to write private key\n");
385		ERR_print_errors(bio_err);
386		}
387	else
388		ret=0;
389end:
390	if (in)
391		BIO_free(in);
392	if (out)
393		BIO_free_all(out);
394	if (eckey)
395		EC_KEY_free(eckey);
396	if (passin)
397		OPENSSL_free(passin);
398	if (passout)
399		OPENSSL_free(passout);
400	apps_shutdown();
401	OPENSSL_EXIT(ret);
402}
403#endif
404