xref: /freebsd/crypto/openssl/apps/ec.c (revision 1669d8afc64812c8d2d1d147ae1fd42ff441e1b1)
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 
84 int MAIN(int, char **);
85 
86 int 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 		{
212 bad:
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;
389 end:
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