1160814Ssimon/* apps/ec.c */
2160814Ssimon/*
3160814Ssimon * Written by Nils Larsch for the OpenSSL project.
4160814Ssimon */
5160814Ssimon/* ====================================================================
6160814Ssimon * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
7160814Ssimon *
8160814Ssimon * Redistribution and use in source and binary forms, with or without
9160814Ssimon * modification, are permitted provided that the following conditions
10160814Ssimon * are met:
11160814Ssimon *
12160814Ssimon * 1. Redistributions of source code must retain the above copyright
13280304Sjkim *    notice, this list of conditions and the following disclaimer.
14160814Ssimon *
15160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright
16160814Ssimon *    notice, this list of conditions and the following disclaimer in
17160814Ssimon *    the documentation and/or other materials provided with the
18160814Ssimon *    distribution.
19160814Ssimon *
20160814Ssimon * 3. All advertising materials mentioning features or use of this
21160814Ssimon *    software must display the following acknowledgment:
22160814Ssimon *    "This product includes software developed by the OpenSSL Project
23160814Ssimon *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24160814Ssimon *
25160814Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26160814Ssimon *    endorse or promote products derived from this software without
27160814Ssimon *    prior written permission. For written permission, please contact
28160814Ssimon *    openssl-core@openssl.org.
29160814Ssimon *
30160814Ssimon * 5. Products derived from this software may not be called "OpenSSL"
31160814Ssimon *    nor may "OpenSSL" appear in their names without prior written
32160814Ssimon *    permission of the OpenSSL Project.
33160814Ssimon *
34160814Ssimon * 6. Redistributions of any form whatsoever must retain the following
35160814Ssimon *    acknowledgment:
36160814Ssimon *    "This product includes software developed by the OpenSSL Project
37160814Ssimon *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38160814Ssimon *
39160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40160814Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42160814Ssimon * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43160814Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44160814Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45160814Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46160814Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48160814Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49160814Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50160814Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE.
51160814Ssimon * ====================================================================
52160814Ssimon *
53160814Ssimon * This product includes cryptographic software written by Eric Young
54160814Ssimon * (eay@cryptsoft.com).  This product includes software written by Tim
55160814Ssimon * Hudson (tjh@cryptsoft.com).
56160814Ssimon *
57160814Ssimon */
58160814Ssimon
59160814Ssimon#include <openssl/opensslconf.h>
60160814Ssimon#ifndef OPENSSL_NO_EC
61280304Sjkim# include <stdio.h>
62280304Sjkim# include <stdlib.h>
63280304Sjkim# include <string.h>
64280304Sjkim# include "apps.h"
65280304Sjkim# include <openssl/bio.h>
66280304Sjkim# include <openssl/err.h>
67280304Sjkim# include <openssl/evp.h>
68280304Sjkim# include <openssl/pem.h>
69160814Ssimon
70280304Sjkim# undef PROG
71280304Sjkim# define PROG    ec_main
72160814Ssimon
73280304Sjkim/*-
74280304Sjkim * -inform arg    - input format - default PEM (one of DER, NET or PEM)
75160814Ssimon * -outform arg   - output format - default PEM
76160814Ssimon * -in arg        - input file - default stdin
77160814Ssimon * -out arg       - output file - default stdout
78160814Ssimon * -des           - encrypt output if PEM format with DES in cbc mode
79160814Ssimon * -text          - print a text version
80160814Ssimon * -param_out     - print the elliptic curve parameters
81160814Ssimon * -conv_form arg - specifies the point encoding form
82160814Ssimon * -param_enc arg - specifies the parameter encoding
83160814Ssimon */
84160814Ssimon
85160814Ssimonint MAIN(int, char **);
86160814Ssimon
87160814Ssimonint MAIN(int argc, char **argv)
88160814Ssimon{
89280304Sjkim    int ret = 1;
90280304Sjkim    EC_KEY *eckey = NULL;
91280304Sjkim    const EC_GROUP *group;
92280304Sjkim    int i, badops = 0;
93280304Sjkim    const EVP_CIPHER *enc = NULL;
94280304Sjkim    BIO *in = NULL, *out = NULL;
95280304Sjkim    int informat, outformat, text = 0, noout = 0;
96280304Sjkim    int pubin = 0, pubout = 0, param_out = 0;
97280304Sjkim    char *infile, *outfile, *prog, *engine;
98280304Sjkim    char *passargin = NULL, *passargout = NULL;
99280304Sjkim    char *passin = NULL, *passout = NULL;
100280304Sjkim    point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
101280304Sjkim    int new_form = 0;
102280304Sjkim    int asn1_flag = OPENSSL_EC_NAMED_CURVE;
103280304Sjkim    int new_asn1_flag = 0;
104160814Ssimon
105280304Sjkim    apps_startup();
106160814Ssimon
107280304Sjkim    if (bio_err == NULL)
108280304Sjkim        if ((bio_err = BIO_new(BIO_s_file())) != NULL)
109280304Sjkim            BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
110160814Ssimon
111280304Sjkim    if (!load_config(bio_err, NULL))
112280304Sjkim        goto end;
113160814Ssimon
114280304Sjkim    engine = NULL;
115280304Sjkim    infile = NULL;
116280304Sjkim    outfile = NULL;
117280304Sjkim    informat = FORMAT_PEM;
118280304Sjkim    outformat = FORMAT_PEM;
119160814Ssimon
120280304Sjkim    prog = argv[0];
121280304Sjkim    argc--;
122280304Sjkim    argv++;
123280304Sjkim    while (argc >= 1) {
124280304Sjkim        if (strcmp(*argv, "-inform") == 0) {
125280304Sjkim            if (--argc < 1)
126280304Sjkim                goto bad;
127280304Sjkim            informat = str2fmt(*(++argv));
128280304Sjkim        } else if (strcmp(*argv, "-outform") == 0) {
129280304Sjkim            if (--argc < 1)
130280304Sjkim                goto bad;
131280304Sjkim            outformat = str2fmt(*(++argv));
132280304Sjkim        } else if (strcmp(*argv, "-in") == 0) {
133280304Sjkim            if (--argc < 1)
134280304Sjkim                goto bad;
135280304Sjkim            infile = *(++argv);
136280304Sjkim        } else if (strcmp(*argv, "-out") == 0) {
137280304Sjkim            if (--argc < 1)
138280304Sjkim                goto bad;
139280304Sjkim            outfile = *(++argv);
140280304Sjkim        } else if (strcmp(*argv, "-passin") == 0) {
141280304Sjkim            if (--argc < 1)
142280304Sjkim                goto bad;
143280304Sjkim            passargin = *(++argv);
144280304Sjkim        } else if (strcmp(*argv, "-passout") == 0) {
145280304Sjkim            if (--argc < 1)
146280304Sjkim                goto bad;
147280304Sjkim            passargout = *(++argv);
148280304Sjkim        } else if (strcmp(*argv, "-engine") == 0) {
149280304Sjkim            if (--argc < 1)
150280304Sjkim                goto bad;
151280304Sjkim            engine = *(++argv);
152280304Sjkim        } else if (strcmp(*argv, "-noout") == 0)
153280304Sjkim            noout = 1;
154280304Sjkim        else if (strcmp(*argv, "-text") == 0)
155280304Sjkim            text = 1;
156280304Sjkim        else if (strcmp(*argv, "-conv_form") == 0) {
157280304Sjkim            if (--argc < 1)
158280304Sjkim                goto bad;
159280304Sjkim            ++argv;
160280304Sjkim            new_form = 1;
161280304Sjkim            if (strcmp(*argv, "compressed") == 0)
162280304Sjkim                form = POINT_CONVERSION_COMPRESSED;
163280304Sjkim            else if (strcmp(*argv, "uncompressed") == 0)
164280304Sjkim                form = POINT_CONVERSION_UNCOMPRESSED;
165280304Sjkim            else if (strcmp(*argv, "hybrid") == 0)
166280304Sjkim                form = POINT_CONVERSION_HYBRID;
167280304Sjkim            else
168280304Sjkim                goto bad;
169280304Sjkim        } else if (strcmp(*argv, "-param_enc") == 0) {
170280304Sjkim            if (--argc < 1)
171280304Sjkim                goto bad;
172280304Sjkim            ++argv;
173280304Sjkim            new_asn1_flag = 1;
174280304Sjkim            if (strcmp(*argv, "named_curve") == 0)
175280304Sjkim                asn1_flag = OPENSSL_EC_NAMED_CURVE;
176280304Sjkim            else if (strcmp(*argv, "explicit") == 0)
177280304Sjkim                asn1_flag = 0;
178280304Sjkim            else
179280304Sjkim                goto bad;
180280304Sjkim        } else if (strcmp(*argv, "-param_out") == 0)
181280304Sjkim            param_out = 1;
182280304Sjkim        else if (strcmp(*argv, "-pubin") == 0)
183280304Sjkim            pubin = 1;
184280304Sjkim        else if (strcmp(*argv, "-pubout") == 0)
185280304Sjkim            pubout = 1;
186280304Sjkim        else if ((enc = EVP_get_cipherbyname(&(argv[0][1]))) == NULL) {
187280304Sjkim            BIO_printf(bio_err, "unknown option %s\n", *argv);
188280304Sjkim            badops = 1;
189280304Sjkim            break;
190280304Sjkim        }
191280304Sjkim        argc--;
192280304Sjkim        argv++;
193280304Sjkim    }
194160814Ssimon
195280304Sjkim    if (badops) {
196280304Sjkim bad:
197280304Sjkim        BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog);
198280304Sjkim        BIO_printf(bio_err, "where options are\n");
199280304Sjkim        BIO_printf(bio_err, " -inform arg     input format - "
200280304Sjkim                   "DER or PEM\n");
201280304Sjkim        BIO_printf(bio_err, " -outform arg    output format - "
202280304Sjkim                   "DER or PEM\n");
203280304Sjkim        BIO_printf(bio_err, " -in arg         input file\n");
204280304Sjkim        BIO_printf(bio_err, " -passin arg     input file pass "
205280304Sjkim                   "phrase source\n");
206280304Sjkim        BIO_printf(bio_err, " -out arg        output file\n");
207280304Sjkim        BIO_printf(bio_err, " -passout arg    output file pass "
208280304Sjkim                   "phrase source\n");
209280304Sjkim        BIO_printf(bio_err, " -engine e       use engine e, "
210280304Sjkim                   "possibly a hardware device.\n");
211280304Sjkim        BIO_printf(bio_err, " -des            encrypt PEM output, "
212280304Sjkim                   "instead of 'des' every other \n"
213280304Sjkim                   "                 cipher "
214280304Sjkim                   "supported by OpenSSL can be used\n");
215280304Sjkim        BIO_printf(bio_err, " -text           print the key\n");
216280304Sjkim        BIO_printf(bio_err, " -noout          don't print key out\n");
217280304Sjkim        BIO_printf(bio_err, " -param_out      print the elliptic "
218280304Sjkim                   "curve parameters\n");
219280304Sjkim        BIO_printf(bio_err, " -conv_form arg  specifies the "
220280304Sjkim                   "point conversion form \n");
221280304Sjkim        BIO_printf(bio_err, "                 possible values:"
222280304Sjkim                   " compressed\n");
223280304Sjkim        BIO_printf(bio_err, "                                 "
224280304Sjkim                   " uncompressed (default)\n");
225280304Sjkim        BIO_printf(bio_err, "                                  " " hybrid\n");
226280304Sjkim        BIO_printf(bio_err, " -param_enc arg  specifies the way"
227280304Sjkim                   " the ec parameters are encoded\n");
228280304Sjkim        BIO_printf(bio_err, "                 in the asn1 der " "encoding\n");
229280304Sjkim        BIO_printf(bio_err, "                 possible values:"
230280304Sjkim                   " named_curve (default)\n");
231280304Sjkim        BIO_printf(bio_err, "                                  "
232280304Sjkim                   "explicit\n");
233280304Sjkim        goto end;
234280304Sjkim    }
235160814Ssimon
236280304Sjkim    ERR_load_crypto_strings();
237160814Ssimon
238280304Sjkim# ifndef OPENSSL_NO_ENGINE
239280304Sjkim    setup_engine(bio_err, engine, 0);
240280304Sjkim# endif
241160814Ssimon
242280304Sjkim    if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
243280304Sjkim        BIO_printf(bio_err, "Error getting passwords\n");
244280304Sjkim        goto end;
245280304Sjkim    }
246160814Ssimon
247280304Sjkim    in = BIO_new(BIO_s_file());
248280304Sjkim    out = BIO_new(BIO_s_file());
249280304Sjkim    if ((in == NULL) || (out == NULL)) {
250280304Sjkim        ERR_print_errors(bio_err);
251280304Sjkim        goto end;
252280304Sjkim    }
253160814Ssimon
254280304Sjkim    if (infile == NULL)
255280304Sjkim        BIO_set_fp(in, stdin, BIO_NOCLOSE);
256280304Sjkim    else {
257280304Sjkim        if (BIO_read_filename(in, infile) <= 0) {
258280304Sjkim            perror(infile);
259280304Sjkim            goto end;
260280304Sjkim        }
261280304Sjkim    }
262160814Ssimon
263280304Sjkim    BIO_printf(bio_err, "read EC key\n");
264280304Sjkim    if (informat == FORMAT_ASN1) {
265280304Sjkim        if (pubin)
266280304Sjkim            eckey = d2i_EC_PUBKEY_bio(in, NULL);
267280304Sjkim        else
268280304Sjkim            eckey = d2i_ECPrivateKey_bio(in, NULL);
269280304Sjkim    } else if (informat == FORMAT_PEM) {
270280304Sjkim        if (pubin)
271280304Sjkim            eckey = PEM_read_bio_EC_PUBKEY(in, NULL, NULL, NULL);
272280304Sjkim        else
273280304Sjkim            eckey = PEM_read_bio_ECPrivateKey(in, NULL, NULL, passin);
274280304Sjkim    } else {
275280304Sjkim        BIO_printf(bio_err, "bad input format specified for key\n");
276280304Sjkim        goto end;
277280304Sjkim    }
278280304Sjkim    if (eckey == NULL) {
279280304Sjkim        BIO_printf(bio_err, "unable to load Key\n");
280280304Sjkim        ERR_print_errors(bio_err);
281280304Sjkim        goto end;
282280304Sjkim    }
283160814Ssimon
284280304Sjkim    if (outfile == NULL) {
285280304Sjkim        BIO_set_fp(out, stdout, BIO_NOCLOSE);
286280304Sjkim# ifdef OPENSSL_SYS_VMS
287280304Sjkim        {
288280304Sjkim            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
289280304Sjkim            out = BIO_push(tmpbio, out);
290280304Sjkim        }
291280304Sjkim# endif
292280304Sjkim    } else {
293280304Sjkim        if (BIO_write_filename(out, outfile) <= 0) {
294280304Sjkim            perror(outfile);
295280304Sjkim            goto end;
296280304Sjkim        }
297280304Sjkim    }
298160814Ssimon
299280304Sjkim    group = EC_KEY_get0_group(eckey);
300160814Ssimon
301280304Sjkim    if (new_form)
302280304Sjkim        EC_KEY_set_conv_form(eckey, form);
303160814Ssimon
304280304Sjkim    if (new_asn1_flag)
305280304Sjkim        EC_KEY_set_asn1_flag(eckey, asn1_flag);
306160814Ssimon
307280304Sjkim    if (text)
308280304Sjkim        if (!EC_KEY_print(out, eckey, 0)) {
309280304Sjkim            perror(outfile);
310280304Sjkim            ERR_print_errors(bio_err);
311280304Sjkim            goto end;
312280304Sjkim        }
313160814Ssimon
314280304Sjkim    if (noout) {
315280304Sjkim        ret = 0;
316280304Sjkim        goto end;
317280304Sjkim    }
318160814Ssimon
319280304Sjkim    BIO_printf(bio_err, "writing EC key\n");
320280304Sjkim    if (outformat == FORMAT_ASN1) {
321280304Sjkim        if (param_out)
322280304Sjkim            i = i2d_ECPKParameters_bio(out, group);
323280304Sjkim        else if (pubin || pubout)
324280304Sjkim            i = i2d_EC_PUBKEY_bio(out, eckey);
325280304Sjkim        else
326280304Sjkim            i = i2d_ECPrivateKey_bio(out, eckey);
327280304Sjkim    } else if (outformat == FORMAT_PEM) {
328280304Sjkim        if (param_out)
329280304Sjkim            i = PEM_write_bio_ECPKParameters(out, group);
330280304Sjkim        else if (pubin || pubout)
331280304Sjkim            i = PEM_write_bio_EC_PUBKEY(out, eckey);
332280304Sjkim        else
333280304Sjkim            i = PEM_write_bio_ECPrivateKey(out, eckey, enc,
334280304Sjkim                                           NULL, 0, NULL, passout);
335280304Sjkim    } else {
336280304Sjkim        BIO_printf(bio_err, "bad output format specified for " "outfile\n");
337280304Sjkim        goto end;
338280304Sjkim    }
339160814Ssimon
340280304Sjkim    if (!i) {
341280304Sjkim        BIO_printf(bio_err, "unable to write private key\n");
342280304Sjkim        ERR_print_errors(bio_err);
343280304Sjkim    } else
344280304Sjkim        ret = 0;
345280304Sjkim end:
346280304Sjkim    if (in)
347280304Sjkim        BIO_free(in);
348280304Sjkim    if (out)
349280304Sjkim        BIO_free_all(out);
350280304Sjkim    if (eckey)
351280304Sjkim        EC_KEY_free(eckey);
352280304Sjkim    if (passin)
353280304Sjkim        OPENSSL_free(passin);
354280304Sjkim    if (passout)
355280304Sjkim        OPENSSL_free(passout);
356280304Sjkim    apps_shutdown();
357280304Sjkim    OPENSSL_EXIT(ret);
358160814Ssimon}
359280304Sjkim#else                           /* !OPENSSL_NO_EC */
360238405Sjkim
361238405Sjkim# if PEDANTIC
362280304Sjkimstatic void *dummy = &dummy;
363238405Sjkim# endif
364238405Sjkim
365160814Ssimon#endif
366