Home | History | Annotate | Line # | Download | only in apps
ec.c revision 1.1.1.4
      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 (at) 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 (at) cryptsoft.com).  This product includes software written by Tim
     55  * Hudson (tjh (at) 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 /*-
     74  * -inform arg    - input format - default PEM (one of DER, NET or PEM)
     75  * -outform arg   - output format - default PEM
     76  * -in arg        - input file - default stdin
     77  * -out arg       - output file - default stdout
     78  * -des           - encrypt output if PEM format with DES in cbc mode
     79  * -text          - print a text version
     80  * -param_out     - print the elliptic curve parameters
     81  * -conv_form arg - specifies the point encoding form
     82  * -param_enc arg - specifies the parameter encoding
     83  */
     84 
     85 int MAIN(int, char **);
     86 
     87 int MAIN(int argc, char **argv)
     88 {
     89     int ret = 1;
     90     EC_KEY *eckey = NULL;
     91     const EC_GROUP *group;
     92     int i, badops = 0;
     93     const EVP_CIPHER *enc = NULL;
     94     BIO *in = NULL, *out = NULL;
     95     int informat, outformat, text = 0, noout = 0;
     96     int pubin = 0, pubout = 0, param_out = 0;
     97     char *infile, *outfile, *prog, *engine;
     98     ENGINE *e = NULL;
     99     char *passargin = NULL, *passargout = NULL;
    100     char *passin = NULL, *passout = NULL;
    101     point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
    102     int new_form = 0;
    103     int asn1_flag = OPENSSL_EC_NAMED_CURVE;
    104     int new_asn1_flag = 0;
    105 
    106     apps_startup();
    107 
    108     if (bio_err == NULL)
    109         if ((bio_err = BIO_new(BIO_s_file())) != NULL)
    110             BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
    111 
    112     if (!load_config(bio_err, NULL))
    113         goto end;
    114 
    115     engine = NULL;
    116     infile = NULL;
    117     outfile = NULL;
    118     informat = FORMAT_PEM;
    119     outformat = FORMAT_PEM;
    120 
    121     prog = argv[0];
    122     argc--;
    123     argv++;
    124     while (argc >= 1) {
    125         if (strcmp(*argv, "-inform") == 0) {
    126             if (--argc < 1)
    127                 goto bad;
    128             informat = str2fmt(*(++argv));
    129         } else if (strcmp(*argv, "-outform") == 0) {
    130             if (--argc < 1)
    131                 goto bad;
    132             outformat = str2fmt(*(++argv));
    133         } else if (strcmp(*argv, "-in") == 0) {
    134             if (--argc < 1)
    135                 goto bad;
    136             infile = *(++argv);
    137         } else if (strcmp(*argv, "-out") == 0) {
    138             if (--argc < 1)
    139                 goto bad;
    140             outfile = *(++argv);
    141         } else if (strcmp(*argv, "-passin") == 0) {
    142             if (--argc < 1)
    143                 goto bad;
    144             passargin = *(++argv);
    145         } else if (strcmp(*argv, "-passout") == 0) {
    146             if (--argc < 1)
    147                 goto bad;
    148             passargout = *(++argv);
    149         } else if (strcmp(*argv, "-engine") == 0) {
    150             if (--argc < 1)
    151                 goto bad;
    152             engine = *(++argv);
    153         } else if (strcmp(*argv, "-noout") == 0)
    154             noout = 1;
    155         else if (strcmp(*argv, "-text") == 0)
    156             text = 1;
    157         else if (strcmp(*argv, "-conv_form") == 0) {
    158             if (--argc < 1)
    159                 goto bad;
    160             ++argv;
    161             new_form = 1;
    162             if (strcmp(*argv, "compressed") == 0)
    163                 form = POINT_CONVERSION_COMPRESSED;
    164             else if (strcmp(*argv, "uncompressed") == 0)
    165                 form = POINT_CONVERSION_UNCOMPRESSED;
    166             else if (strcmp(*argv, "hybrid") == 0)
    167                 form = POINT_CONVERSION_HYBRID;
    168             else
    169                 goto bad;
    170         } else if (strcmp(*argv, "-param_enc") == 0) {
    171             if (--argc < 1)
    172                 goto bad;
    173             ++argv;
    174             new_asn1_flag = 1;
    175             if (strcmp(*argv, "named_curve") == 0)
    176                 asn1_flag = OPENSSL_EC_NAMED_CURVE;
    177             else if (strcmp(*argv, "explicit") == 0)
    178                 asn1_flag = 0;
    179             else
    180                 goto bad;
    181         } else if (strcmp(*argv, "-param_out") == 0)
    182             param_out = 1;
    183         else if (strcmp(*argv, "-pubin") == 0)
    184             pubin = 1;
    185         else if (strcmp(*argv, "-pubout") == 0)
    186             pubout = 1;
    187         else if ((enc = EVP_get_cipherbyname(&(argv[0][1]))) == NULL) {
    188             BIO_printf(bio_err, "unknown option %s\n", *argv);
    189             badops = 1;
    190             break;
    191         }
    192         argc--;
    193         argv++;
    194     }
    195 
    196     if (badops) {
    197  bad:
    198         BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog);
    199         BIO_printf(bio_err, "where options are\n");
    200         BIO_printf(bio_err, " -inform arg     input format - "
    201                    "DER or PEM\n");
    202         BIO_printf(bio_err, " -outform arg    output format - "
    203                    "DER or PEM\n");
    204         BIO_printf(bio_err, " -in arg         input file\n");
    205         BIO_printf(bio_err, " -passin arg     input file pass "
    206                    "phrase source\n");
    207         BIO_printf(bio_err, " -out arg        output file\n");
    208         BIO_printf(bio_err, " -passout arg    output file pass "
    209                    "phrase source\n");
    210         BIO_printf(bio_err, " -engine e       use engine e, "
    211                    "possibly a hardware device.\n");
    212         BIO_printf(bio_err, " -des            encrypt PEM output, "
    213                    "instead of 'des' every other \n"
    214                    "                 cipher "
    215                    "supported by OpenSSL can be used\n");
    216         BIO_printf(bio_err, " -text           print the key\n");
    217         BIO_printf(bio_err, " -noout          don't print key out\n");
    218         BIO_printf(bio_err, " -param_out      print the elliptic "
    219                    "curve parameters\n");
    220         BIO_printf(bio_err, " -conv_form arg  specifies the "
    221                    "point conversion form \n");
    222         BIO_printf(bio_err, "                 possible values:"
    223                    " compressed\n");
    224         BIO_printf(bio_err, "                                 "
    225                    " uncompressed (default)\n");
    226         BIO_printf(bio_err, "                                  " " hybrid\n");
    227         BIO_printf(bio_err, " -param_enc arg  specifies the way"
    228                    " the ec parameters are encoded\n");
    229         BIO_printf(bio_err, "                 in the asn1 der " "encoding\n");
    230         BIO_printf(bio_err, "                 possible values:"
    231                    " named_curve (default)\n");
    232         BIO_printf(bio_err, "                                  "
    233                    "explicit\n");
    234         goto end;
    235     }
    236 
    237     ERR_load_crypto_strings();
    238 
    239     e = setup_engine(bio_err, engine, 0);
    240 
    241     if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
    242         BIO_printf(bio_err, "Error getting passwords\n");
    243         goto end;
    244     }
    245 
    246     in = BIO_new(BIO_s_file());
    247     out = BIO_new(BIO_s_file());
    248     if ((in == NULL) || (out == NULL)) {
    249         ERR_print_errors(bio_err);
    250         goto end;
    251     }
    252 
    253     if (infile == NULL)
    254         BIO_set_fp(in, stdin, BIO_NOCLOSE);
    255     else {
    256         if (BIO_read_filename(in, infile) <= 0) {
    257             perror(infile);
    258             goto end;
    259         }
    260     }
    261 
    262     BIO_printf(bio_err, "read EC key\n");
    263     if (informat == FORMAT_ASN1) {
    264         if (pubin)
    265             eckey = d2i_EC_PUBKEY_bio(in, NULL);
    266         else
    267             eckey = d2i_ECPrivateKey_bio(in, NULL);
    268     } else if (informat == FORMAT_PEM) {
    269         if (pubin)
    270             eckey = PEM_read_bio_EC_PUBKEY(in, NULL, NULL, NULL);
    271         else
    272             eckey = PEM_read_bio_ECPrivateKey(in, NULL, NULL, passin);
    273     } else {
    274         BIO_printf(bio_err, "bad input format specified for key\n");
    275         goto end;
    276     }
    277     if (eckey == NULL) {
    278         BIO_printf(bio_err, "unable to load Key\n");
    279         ERR_print_errors(bio_err);
    280         goto end;
    281     }
    282 
    283     if (outfile == NULL) {
    284         BIO_set_fp(out, stdout, BIO_NOCLOSE);
    285 # ifdef OPENSSL_SYS_VMS
    286         {
    287             BIO *tmpbio = BIO_new(BIO_f_linebuffer());
    288             out = BIO_push(tmpbio, out);
    289         }
    290 # endif
    291     } else {
    292         if (BIO_write_filename(out, outfile) <= 0) {
    293             perror(outfile);
    294             goto end;
    295         }
    296     }
    297 
    298     group = EC_KEY_get0_group(eckey);
    299 
    300     if (new_form)
    301         EC_KEY_set_conv_form(eckey, form);
    302 
    303     if (new_asn1_flag)
    304         EC_KEY_set_asn1_flag(eckey, asn1_flag);
    305 
    306     if (text)
    307         if (!EC_KEY_print(out, eckey, 0)) {
    308             perror(outfile);
    309             ERR_print_errors(bio_err);
    310             goto end;
    311         }
    312 
    313     if (noout) {
    314         ret = 0;
    315         goto end;
    316     }
    317 
    318     BIO_printf(bio_err, "writing EC key\n");
    319     if (outformat == FORMAT_ASN1) {
    320         if (param_out)
    321             i = i2d_ECPKParameters_bio(out, group);
    322         else if (pubin || pubout)
    323             i = i2d_EC_PUBKEY_bio(out, eckey);
    324         else
    325             i = i2d_ECPrivateKey_bio(out, eckey);
    326     } else if (outformat == FORMAT_PEM) {
    327         if (param_out)
    328             i = PEM_write_bio_ECPKParameters(out, group);
    329         else if (pubin || pubout)
    330             i = PEM_write_bio_EC_PUBKEY(out, eckey);
    331         else
    332             i = PEM_write_bio_ECPrivateKey(out, eckey, enc,
    333                                            NULL, 0, NULL, passout);
    334     } else {
    335         BIO_printf(bio_err, "bad output format specified for " "outfile\n");
    336         goto end;
    337     }
    338 
    339     if (!i) {
    340         BIO_printf(bio_err, "unable to write private key\n");
    341         ERR_print_errors(bio_err);
    342     } else
    343         ret = 0;
    344  end:
    345     if (in)
    346         BIO_free(in);
    347     if (out)
    348         BIO_free_all(out);
    349     if (eckey)
    350         EC_KEY_free(eckey);
    351     release_engine(e);
    352     if (passin)
    353         OPENSSL_free(passin);
    354     if (passout)
    355         OPENSSL_free(passout);
    356     apps_shutdown();
    357     OPENSSL_EXIT(ret);
    358 }
    359 #else                           /* !OPENSSL_NO_EC */
    360 
    361 # if PEDANTIC
    362 static void *dummy = &dummy;
    363 # endif
    364 
    365 #endif
    366