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
13296465Sdelphij *    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
61296465Sdelphij# include <stdio.h>
62296465Sdelphij# include <stdlib.h>
63296465Sdelphij# include <string.h>
64296465Sdelphij# include "apps.h"
65296465Sdelphij# include <openssl/bio.h>
66296465Sdelphij# include <openssl/err.h>
67296465Sdelphij# include <openssl/evp.h>
68296465Sdelphij# include <openssl/pem.h>
69160814Ssimon
70296465Sdelphij# undef PROG
71296465Sdelphij# define PROG    ec_main
72160814Ssimon
73296465Sdelphij/*-
74296465Sdelphij * -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{
89296465Sdelphij    int ret = 1;
90296465Sdelphij    EC_KEY *eckey = NULL;
91296465Sdelphij    const EC_GROUP *group;
92296465Sdelphij    int i, badops = 0;
93296465Sdelphij    const EVP_CIPHER *enc = NULL;
94296465Sdelphij    BIO *in = NULL, *out = NULL;
95296465Sdelphij    int informat, outformat, text = 0, noout = 0;
96296465Sdelphij    int pubin = 0, pubout = 0, param_out = 0;
97296465Sdelphij    char *infile, *outfile, *prog, *engine;
98296465Sdelphij    char *passargin = NULL, *passargout = NULL;
99296465Sdelphij    char *passin = NULL, *passout = NULL;
100296465Sdelphij    point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
101296465Sdelphij    int new_form = 0;
102296465Sdelphij    int asn1_flag = OPENSSL_EC_NAMED_CURVE;
103296465Sdelphij    int new_asn1_flag = 0;
104160814Ssimon
105296465Sdelphij    apps_startup();
106160814Ssimon
107296465Sdelphij    if (bio_err == NULL)
108296465Sdelphij        if ((bio_err = BIO_new(BIO_s_file())) != NULL)
109296465Sdelphij            BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
110160814Ssimon
111296465Sdelphij    if (!load_config(bio_err, NULL))
112296465Sdelphij        goto end;
113160814Ssimon
114296465Sdelphij    engine = NULL;
115296465Sdelphij    infile = NULL;
116296465Sdelphij    outfile = NULL;
117296465Sdelphij    informat = FORMAT_PEM;
118296465Sdelphij    outformat = FORMAT_PEM;
119160814Ssimon
120296465Sdelphij    prog = argv[0];
121296465Sdelphij    argc--;
122296465Sdelphij    argv++;
123296465Sdelphij    while (argc >= 1) {
124296465Sdelphij        if (strcmp(*argv, "-inform") == 0) {
125296465Sdelphij            if (--argc < 1)
126296465Sdelphij                goto bad;
127296465Sdelphij            informat = str2fmt(*(++argv));
128296465Sdelphij        } else if (strcmp(*argv, "-outform") == 0) {
129296465Sdelphij            if (--argc < 1)
130296465Sdelphij                goto bad;
131296465Sdelphij            outformat = str2fmt(*(++argv));
132296465Sdelphij        } else if (strcmp(*argv, "-in") == 0) {
133296465Sdelphij            if (--argc < 1)
134296465Sdelphij                goto bad;
135296465Sdelphij            infile = *(++argv);
136296465Sdelphij        } else if (strcmp(*argv, "-out") == 0) {
137296465Sdelphij            if (--argc < 1)
138296465Sdelphij                goto bad;
139296465Sdelphij            outfile = *(++argv);
140296465Sdelphij        } else if (strcmp(*argv, "-passin") == 0) {
141296465Sdelphij            if (--argc < 1)
142296465Sdelphij                goto bad;
143296465Sdelphij            passargin = *(++argv);
144296465Sdelphij        } else if (strcmp(*argv, "-passout") == 0) {
145296465Sdelphij            if (--argc < 1)
146296465Sdelphij                goto bad;
147296465Sdelphij            passargout = *(++argv);
148296465Sdelphij        } else if (strcmp(*argv, "-engine") == 0) {
149296465Sdelphij            if (--argc < 1)
150296465Sdelphij                goto bad;
151296465Sdelphij            engine = *(++argv);
152296465Sdelphij        } else if (strcmp(*argv, "-noout") == 0)
153296465Sdelphij            noout = 1;
154296465Sdelphij        else if (strcmp(*argv, "-text") == 0)
155296465Sdelphij            text = 1;
156296465Sdelphij        else if (strcmp(*argv, "-conv_form") == 0) {
157296465Sdelphij            if (--argc < 1)
158296465Sdelphij                goto bad;
159296465Sdelphij            ++argv;
160296465Sdelphij            new_form = 1;
161296465Sdelphij            if (strcmp(*argv, "compressed") == 0)
162296465Sdelphij                form = POINT_CONVERSION_COMPRESSED;
163296465Sdelphij            else if (strcmp(*argv, "uncompressed") == 0)
164296465Sdelphij                form = POINT_CONVERSION_UNCOMPRESSED;
165296465Sdelphij            else if (strcmp(*argv, "hybrid") == 0)
166296465Sdelphij                form = POINT_CONVERSION_HYBRID;
167296465Sdelphij            else
168296465Sdelphij                goto bad;
169296465Sdelphij        } else if (strcmp(*argv, "-param_enc") == 0) {
170296465Sdelphij            if (--argc < 1)
171296465Sdelphij                goto bad;
172296465Sdelphij            ++argv;
173296465Sdelphij            new_asn1_flag = 1;
174296465Sdelphij            if (strcmp(*argv, "named_curve") == 0)
175296465Sdelphij                asn1_flag = OPENSSL_EC_NAMED_CURVE;
176296465Sdelphij            else if (strcmp(*argv, "explicit") == 0)
177296465Sdelphij                asn1_flag = 0;
178296465Sdelphij            else
179296465Sdelphij                goto bad;
180296465Sdelphij        } else if (strcmp(*argv, "-param_out") == 0)
181296465Sdelphij            param_out = 1;
182296465Sdelphij        else if (strcmp(*argv, "-pubin") == 0)
183296465Sdelphij            pubin = 1;
184296465Sdelphij        else if (strcmp(*argv, "-pubout") == 0)
185296465Sdelphij            pubout = 1;
186296465Sdelphij        else if ((enc = EVP_get_cipherbyname(&(argv[0][1]))) == NULL) {
187296465Sdelphij            BIO_printf(bio_err, "unknown option %s\n", *argv);
188296465Sdelphij            badops = 1;
189296465Sdelphij            break;
190296465Sdelphij        }
191296465Sdelphij        argc--;
192296465Sdelphij        argv++;
193296465Sdelphij    }
194160814Ssimon
195296465Sdelphij    if (badops) {
196296465Sdelphij bad:
197296465Sdelphij        BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog);
198296465Sdelphij        BIO_printf(bio_err, "where options are\n");
199296465Sdelphij        BIO_printf(bio_err, " -inform arg     input format - "
200296465Sdelphij                   "DER or PEM\n");
201296465Sdelphij        BIO_printf(bio_err, " -outform arg    output format - "
202296465Sdelphij                   "DER or PEM\n");
203296465Sdelphij        BIO_printf(bio_err, " -in arg         input file\n");
204296465Sdelphij        BIO_printf(bio_err, " -passin arg     input file pass "
205296465Sdelphij                   "phrase source\n");
206296465Sdelphij        BIO_printf(bio_err, " -out arg        output file\n");
207296465Sdelphij        BIO_printf(bio_err, " -passout arg    output file pass "
208296465Sdelphij                   "phrase source\n");
209296465Sdelphij        BIO_printf(bio_err, " -engine e       use engine e, "
210296465Sdelphij                   "possibly a hardware device.\n");
211296465Sdelphij        BIO_printf(bio_err, " -des            encrypt PEM output, "
212296465Sdelphij                   "instead of 'des' every other \n"
213296465Sdelphij                   "                 cipher "
214296465Sdelphij                   "supported by OpenSSL can be used\n");
215296465Sdelphij        BIO_printf(bio_err, " -text           print the key\n");
216296465Sdelphij        BIO_printf(bio_err, " -noout          don't print key out\n");
217296465Sdelphij        BIO_printf(bio_err, " -param_out      print the elliptic "
218296465Sdelphij                   "curve parameters\n");
219296465Sdelphij        BIO_printf(bio_err, " -conv_form arg  specifies the "
220296465Sdelphij                   "point conversion form \n");
221296465Sdelphij        BIO_printf(bio_err, "                 possible values:"
222296465Sdelphij                   " compressed\n");
223296465Sdelphij        BIO_printf(bio_err, "                                 "
224296465Sdelphij                   " uncompressed (default)\n");
225296465Sdelphij        BIO_printf(bio_err, "                                  " " hybrid\n");
226296465Sdelphij        BIO_printf(bio_err, " -param_enc arg  specifies the way"
227296465Sdelphij                   " the ec parameters are encoded\n");
228296465Sdelphij        BIO_printf(bio_err, "                 in the asn1 der " "encoding\n");
229296465Sdelphij        BIO_printf(bio_err, "                 possible values:"
230296465Sdelphij                   " named_curve (default)\n");
231296465Sdelphij        BIO_printf(bio_err, "                                  "
232296465Sdelphij                   "explicit\n");
233296465Sdelphij        goto end;
234296465Sdelphij    }
235160814Ssimon
236296465Sdelphij    ERR_load_crypto_strings();
237160814Ssimon
238296465Sdelphij# ifndef OPENSSL_NO_ENGINE
239296465Sdelphij    setup_engine(bio_err, engine, 0);
240296465Sdelphij# endif
241160814Ssimon
242296465Sdelphij    if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
243296465Sdelphij        BIO_printf(bio_err, "Error getting passwords\n");
244296465Sdelphij        goto end;
245296465Sdelphij    }
246160814Ssimon
247296465Sdelphij    in = BIO_new(BIO_s_file());
248296465Sdelphij    out = BIO_new(BIO_s_file());
249296465Sdelphij    if ((in == NULL) || (out == NULL)) {
250296465Sdelphij        ERR_print_errors(bio_err);
251296465Sdelphij        goto end;
252296465Sdelphij    }
253160814Ssimon
254296465Sdelphij    if (infile == NULL)
255296465Sdelphij        BIO_set_fp(in, stdin, BIO_NOCLOSE);
256296465Sdelphij    else {
257296465Sdelphij        if (BIO_read_filename(in, infile) <= 0) {
258296465Sdelphij            perror(infile);
259296465Sdelphij            goto end;
260296465Sdelphij        }
261296465Sdelphij    }
262160814Ssimon
263296465Sdelphij    BIO_printf(bio_err, "read EC key\n");
264296465Sdelphij    if (informat == FORMAT_ASN1) {
265296465Sdelphij        if (pubin)
266296465Sdelphij            eckey = d2i_EC_PUBKEY_bio(in, NULL);
267296465Sdelphij        else
268296465Sdelphij            eckey = d2i_ECPrivateKey_bio(in, NULL);
269296465Sdelphij    } else if (informat == FORMAT_PEM) {
270296465Sdelphij        if (pubin)
271296465Sdelphij            eckey = PEM_read_bio_EC_PUBKEY(in, NULL, NULL, NULL);
272296465Sdelphij        else
273296465Sdelphij            eckey = PEM_read_bio_ECPrivateKey(in, NULL, NULL, passin);
274296465Sdelphij    } else {
275296465Sdelphij        BIO_printf(bio_err, "bad input format specified for key\n");
276296465Sdelphij        goto end;
277296465Sdelphij    }
278296465Sdelphij    if (eckey == NULL) {
279296465Sdelphij        BIO_printf(bio_err, "unable to load Key\n");
280296465Sdelphij        ERR_print_errors(bio_err);
281296465Sdelphij        goto end;
282296465Sdelphij    }
283160814Ssimon
284296465Sdelphij    if (outfile == NULL) {
285296465Sdelphij        BIO_set_fp(out, stdout, BIO_NOCLOSE);
286296465Sdelphij# ifdef OPENSSL_SYS_VMS
287296465Sdelphij        {
288296465Sdelphij            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
289296465Sdelphij            out = BIO_push(tmpbio, out);
290296465Sdelphij        }
291296465Sdelphij# endif
292296465Sdelphij    } else {
293296465Sdelphij        if (BIO_write_filename(out, outfile) <= 0) {
294296465Sdelphij            perror(outfile);
295296465Sdelphij            goto end;
296296465Sdelphij        }
297296465Sdelphij    }
298160814Ssimon
299296465Sdelphij    group = EC_KEY_get0_group(eckey);
300160814Ssimon
301296465Sdelphij    if (new_form)
302296465Sdelphij        EC_KEY_set_conv_form(eckey, form);
303160814Ssimon
304296465Sdelphij    if (new_asn1_flag)
305296465Sdelphij        EC_KEY_set_asn1_flag(eckey, asn1_flag);
306160814Ssimon
307296465Sdelphij    if (text)
308296465Sdelphij        if (!EC_KEY_print(out, eckey, 0)) {
309296465Sdelphij            perror(outfile);
310296465Sdelphij            ERR_print_errors(bio_err);
311296465Sdelphij            goto end;
312296465Sdelphij        }
313160814Ssimon
314296465Sdelphij    if (noout) {
315296465Sdelphij        ret = 0;
316296465Sdelphij        goto end;
317296465Sdelphij    }
318160814Ssimon
319296465Sdelphij    BIO_printf(bio_err, "writing EC key\n");
320296465Sdelphij    if (outformat == FORMAT_ASN1) {
321296465Sdelphij        if (param_out)
322296465Sdelphij            i = i2d_ECPKParameters_bio(out, group);
323296465Sdelphij        else if (pubin || pubout)
324296465Sdelphij            i = i2d_EC_PUBKEY_bio(out, eckey);
325296465Sdelphij        else
326296465Sdelphij            i = i2d_ECPrivateKey_bio(out, eckey);
327296465Sdelphij    } else if (outformat == FORMAT_PEM) {
328296465Sdelphij        if (param_out)
329296465Sdelphij            i = PEM_write_bio_ECPKParameters(out, group);
330296465Sdelphij        else if (pubin || pubout)
331296465Sdelphij            i = PEM_write_bio_EC_PUBKEY(out, eckey);
332296465Sdelphij        else
333296465Sdelphij            i = PEM_write_bio_ECPrivateKey(out, eckey, enc,
334296465Sdelphij                                           NULL, 0, NULL, passout);
335296465Sdelphij    } else {
336296465Sdelphij        BIO_printf(bio_err, "bad output format specified for " "outfile\n");
337296465Sdelphij        goto end;
338296465Sdelphij    }
339160814Ssimon
340296465Sdelphij    if (!i) {
341296465Sdelphij        BIO_printf(bio_err, "unable to write private key\n");
342296465Sdelphij        ERR_print_errors(bio_err);
343296465Sdelphij    } else
344296465Sdelphij        ret = 0;
345296465Sdelphij end:
346296465Sdelphij    if (in)
347296465Sdelphij        BIO_free(in);
348296465Sdelphij    if (out)
349296465Sdelphij        BIO_free_all(out);
350296465Sdelphij    if (eckey)
351296465Sdelphij        EC_KEY_free(eckey);
352296465Sdelphij    if (passin)
353296465Sdelphij        OPENSSL_free(passin);
354296465Sdelphij    if (passout)
355296465Sdelphij        OPENSSL_free(passout);
356296465Sdelphij    apps_shutdown();
357296465Sdelphij    OPENSSL_EXIT(ret);
358160814Ssimon}
359160814Ssimon#endif
360