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