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