[BACK]Return to ec.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / openssl

Annotation of src/usr.bin/openssl/ec.c, Revision 1.12

1.12    ! inoguchi    1: /* $OpenBSD: ec.c,v 1.11 2018/02/07 05:47:55 jsing Exp $ */
1.1       jsing       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@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@cryptsoft.com).  This product includes software written by Tim
                     55:  * Hudson (tjh@cryptsoft.com).
                     56:  *
                     57:  */
                     58:
                     59: #include <openssl/opensslconf.h>
                     60:
                     61: #ifndef OPENSSL_NO_EC
                     62:
                     63: #include <stdio.h>
                     64: #include <stdlib.h>
                     65: #include <string.h>
                     66:
                     67: #include "apps.h"
                     68:
                     69: #include <openssl/bio.h>
                     70: #include <openssl/err.h>
                     71: #include <openssl/evp.h>
                     72: #include <openssl/pem.h>
                     73:
1.3       doug       74: static struct {
                     75:        int asn1_flag;
                     76:        const EVP_CIPHER *enc;
                     77:        point_conversion_form_t form;
                     78:        char *infile;
                     79:        int informat;
                     80:        char *outfile;
                     81:        int outformat;
                     82:        int new_asn1_flag;
                     83:        int new_form;
                     84:        int noout;
                     85:        int param_out;
                     86:        char *passargin;
                     87:        char *passargout;
                     88:        int pubin;
                     89:        int pubout;
                     90:        int text;
                     91: } ec_config;
                     92:
                     93: static int
                     94: ec_opt_enc(int argc, char **argv, int *argsused)
                     95: {
                     96:        char *name = argv[0];
                     97:
                     98:        if (*name++ != '-')
                     99:                return (1);
                    100:
                    101:        if ((ec_config.enc = EVP_get_cipherbyname(name)) != NULL) {
                    102:                *argsused = 1;
                    103:                return (0);
                    104:        }
                    105:
                    106:        return (1);
                    107: }
                    108:
                    109: static int
                    110: ec_opt_form(char *arg)
                    111: {
                    112:        if (strcmp(arg, "compressed") == 0)
                    113:                ec_config.form = POINT_CONVERSION_COMPRESSED;
                    114:        else if (strcmp(arg, "uncompressed") == 0)
                    115:                ec_config.form = POINT_CONVERSION_UNCOMPRESSED;
                    116:        else if (strcmp(arg, "hybrid") == 0)
                    117:                ec_config.form = POINT_CONVERSION_HYBRID;
                    118:        else {
                    119:                fprintf(stderr, "Invalid point conversion: %s\n", arg);
                    120:                return (1);
                    121:        }
                    122:
                    123:        ec_config.new_form = 1;
                    124:        return (0);
                    125: }
                    126:
                    127: static int
                    128: ec_opt_named(char *arg)
                    129: {
                    130:        if (strcmp(arg, "named_curve") == 0)
                    131:                ec_config.asn1_flag = OPENSSL_EC_NAMED_CURVE;
                    132:        else if (strcmp(arg, "explicit") == 0)
                    133:                ec_config.asn1_flag = 0;
                    134:        else {
                    135:                fprintf(stderr, "Invalid curve type: %s\n", arg);
                    136:                return (1);
                    137:        }
                    138:
                    139:        ec_config.new_asn1_flag = 1;
                    140:        return (0);
                    141: }
                    142:
                    143: static struct option ec_options[] = {
                    144:        {
                    145:                .name = "conv_form",
                    146:                .argname = "form",
                    147:                .desc = "Specify the point conversion form (default"
                    148:                    " \"named_curve\")",
                    149:                .type = OPTION_ARG_FUNC,
                    150:                .opt.argfunc = ec_opt_form,
                    151:        },
                    152:        {
                    153:                .name = "in",
                    154:                .argname = "file",
                    155:                .desc = "Input file (default stdin)",
                    156:                .type = OPTION_ARG,
                    157:                .opt.arg = &ec_config.infile,
                    158:        },
                    159:        {
                    160:                .name = "inform",
                    161:                .argname = "format",
                    162:                .desc = "Input format (DER or PEM (default))",
                    163:                .type = OPTION_ARG_FORMAT,
                    164:                .opt.value = &ec_config.informat,
                    165:        },
                    166:        {
                    167:                .name = "noout",
                    168:                .desc = "No output",
                    169:                .type = OPTION_FLAG,
                    170:                .opt.flag = &ec_config.noout,
                    171:        },
                    172:        {
                    173:                .name = "out",
                    174:                .argname = "file",
                    175:                .desc = "Output file (default stdout)",
                    176:                .type = OPTION_ARG,
                    177:                .opt.arg = &ec_config.outfile,
                    178:        },
                    179:        {
                    180:                .name = "outform",
                    181:                .argname = "format",
                    182:                .desc = "Output format (DER or PEM (default))",
                    183:                .type = OPTION_ARG_FORMAT,
                    184:                .opt.value = &ec_config.outformat,
                    185:        },
                    186:        {
                    187:                .name = "param_enc",
                    188:                .argname = "type",
                    189:                .desc = "Specify the way the ec parameters are encoded"
                    190:                    " (default \"uncompressed\")",
                    191:                .type = OPTION_ARG_FUNC,
                    192:                .opt.argfunc = ec_opt_named,
                    193:        },
                    194:        {
                    195:                .name = "param_out",
                    196:                .desc = "Print the elliptic curve parameters",
                    197:                .type = OPTION_FLAG,
                    198:                .opt.flag = &ec_config.param_out,
                    199:        },
                    200:        {
                    201:                .name = "passin",
                    202:                .argname = "source",
                    203:                .desc = "Input file passphrase source",
                    204:                .type = OPTION_ARG,
                    205:                .opt.arg = &ec_config.passargin,
                    206:        },
                    207:        {
                    208:                .name = "passout",
                    209:                .argname = "source",
                    210:                .desc = "Output file passphrase source",
                    211:                .type = OPTION_ARG,
                    212:                .opt.arg = &ec_config.passargout,
                    213:        },
                    214:        {
                    215:                .name = "pubin",
                    216:                .desc = "Read public key instead of private key from input",
                    217:                .type = OPTION_FLAG,
                    218:                .opt.flag = &ec_config.pubin,
                    219:        },
                    220:        {
                    221:                .name = "pubout",
                    222:                .desc = "Output public key instead of private key in output",
                    223:                .type = OPTION_FLAG,
                    224:                .opt.flag = &ec_config.pubout,
                    225:        },
                    226:        {
                    227:                .name = "text",
                    228:                .desc = "Print the public/private key components and parameters",
                    229:                .type = OPTION_FLAG,
                    230:                .opt.flag = &ec_config.text,
                    231:        },
                    232:        {
                    233:                .name = NULL,
                    234:                .desc = "Cipher to encrypt the output if using PEM format",
                    235:                .type = OPTION_ARGV_FUNC,
                    236:                .opt.argvfunc = ec_opt_enc,
                    237:        },
                    238:        { NULL },
                    239: };
                    240:
                    241: static void
                    242: ec_usage(void)
                    243: {
                    244:        fprintf(stderr,
1.5       bcook     245:            "usage: ec [-conv_form form] [-in file]\n"
1.3       doug      246:            "    [-inform format] [-noout] [-out file] [-outform format]\n"
                    247:            "    [-param_enc type] [-param_out] [-passin file]\n"
                    248:            "    [-passout file] [-pubin] [-pubout] [-text] [-ciphername]\n\n");
                    249:        options_usage(ec_options);
                    250:
                    251:        fprintf(stderr, "\n");
                    252:
                    253:        fprintf(stderr, "Valid ciphername values:\n\n");
1.12    ! inoguchi  254:        OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, show_cipher, NULL);
1.3       doug      255:        fprintf(stderr, "\n");
                    256: }
1.1       jsing     257:
                    258: int
                    259: ec_main(int argc, char **argv)
                    260: {
                    261:        int ret = 1;
                    262:        EC_KEY *eckey = NULL;
                    263:        const EC_GROUP *group;
1.3       doug      264:        int i;
1.1       jsing     265:        BIO *in = NULL, *out = NULL;
                    266:        char *passin = NULL, *passout = NULL;
1.6       doug      267:
                    268:        if (single_execution) {
1.9       deraadt   269:                if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
1.6       doug      270:                        perror("pledge");
1.8       doug      271:                        exit(1);
                    272:                }
1.6       doug      273:        }
1.1       jsing     274:
1.3       doug      275:        memset(&ec_config, 0, sizeof(ec_config));
                    276:
                    277:        ec_config.asn1_flag = OPENSSL_EC_NAMED_CURVE;
                    278:        ec_config.form = POINT_CONVERSION_UNCOMPRESSED;
                    279:        ec_config.informat = FORMAT_PEM;
                    280:        ec_config.outformat = FORMAT_PEM;
                    281:
                    282:        if (options_parse(argc, argv, ec_options, NULL, NULL) != 0) {
                    283:                ec_usage();
1.1       jsing     284:                goto end;
                    285:        }
                    286:
1.3       doug      287:        if (!app_passwd(bio_err, ec_config.passargin, ec_config.passargout,
                    288:            &passin, &passout)) {
1.1       jsing     289:                BIO_printf(bio_err, "Error getting passwords\n");
                    290:                goto end;
                    291:        }
                    292:        in = BIO_new(BIO_s_file());
                    293:        out = BIO_new(BIO_s_file());
1.3       doug      294:        if (in == NULL || out == NULL) {
1.1       jsing     295:                ERR_print_errors(bio_err);
                    296:                goto end;
                    297:        }
1.3       doug      298:        if (ec_config.infile == NULL)
1.1       jsing     299:                BIO_set_fp(in, stdin, BIO_NOCLOSE);
                    300:        else {
1.3       doug      301:                if (BIO_read_filename(in, ec_config.infile) <= 0) {
                    302:                        perror(ec_config.infile);
1.1       jsing     303:                        goto end;
                    304:                }
                    305:        }
                    306:
                    307:        BIO_printf(bio_err, "read EC key\n");
1.3       doug      308:        if (ec_config.informat == FORMAT_ASN1) {
                    309:                if (ec_config.pubin)
1.1       jsing     310:                        eckey = d2i_EC_PUBKEY_bio(in, NULL);
                    311:                else
                    312:                        eckey = d2i_ECPrivateKey_bio(in, NULL);
1.3       doug      313:        } else if (ec_config.informat == FORMAT_PEM) {
                    314:                if (ec_config.pubin)
1.1       jsing     315:                        eckey = PEM_read_bio_EC_PUBKEY(in, NULL, NULL,
                    316:                            NULL);
                    317:                else
                    318:                        eckey = PEM_read_bio_ECPrivateKey(in, NULL, NULL,
                    319:                            passin);
                    320:        } else {
                    321:                BIO_printf(bio_err, "bad input format specified for key\n");
                    322:                goto end;
                    323:        }
                    324:        if (eckey == NULL) {
                    325:                BIO_printf(bio_err, "unable to load Key\n");
                    326:                ERR_print_errors(bio_err);
                    327:                goto end;
                    328:        }
1.3       doug      329:        if (ec_config.outfile == NULL) {
1.1       jsing     330:                BIO_set_fp(out, stdout, BIO_NOCLOSE);
                    331:        } else {
1.3       doug      332:                if (BIO_write_filename(out, ec_config.outfile) <= 0) {
                    333:                        perror(ec_config.outfile);
1.1       jsing     334:                        goto end;
                    335:                }
                    336:        }
                    337:
                    338:        group = EC_KEY_get0_group(eckey);
                    339:
1.3       doug      340:        if (ec_config.new_form)
                    341:                EC_KEY_set_conv_form(eckey, ec_config.form);
1.1       jsing     342:
1.3       doug      343:        if (ec_config.new_asn1_flag)
                    344:                EC_KEY_set_asn1_flag(eckey, ec_config.asn1_flag);
1.1       jsing     345:
1.3       doug      346:        if (ec_config.text)
1.1       jsing     347:                if (!EC_KEY_print(out, eckey, 0)) {
1.3       doug      348:                        perror(ec_config.outfile);
1.1       jsing     349:                        ERR_print_errors(bio_err);
                    350:                        goto end;
                    351:                }
1.3       doug      352:        if (ec_config.noout) {
1.1       jsing     353:                ret = 0;
                    354:                goto end;
                    355:        }
                    356:        BIO_printf(bio_err, "writing EC key\n");
1.3       doug      357:        if (ec_config.outformat == FORMAT_ASN1) {
                    358:                if (ec_config.param_out)
1.1       jsing     359:                        i = i2d_ECPKParameters_bio(out, group);
1.3       doug      360:                else if (ec_config.pubin || ec_config.pubout)
1.1       jsing     361:                        i = i2d_EC_PUBKEY_bio(out, eckey);
                    362:                else
                    363:                        i = i2d_ECPrivateKey_bio(out, eckey);
1.3       doug      364:        } else if (ec_config.outformat == FORMAT_PEM) {
                    365:                if (ec_config.param_out)
1.1       jsing     366:                        i = PEM_write_bio_ECPKParameters(out, group);
1.3       doug      367:                else if (ec_config.pubin || ec_config.pubout)
1.1       jsing     368:                        i = PEM_write_bio_EC_PUBKEY(out, eckey);
                    369:                else
1.3       doug      370:                        i = PEM_write_bio_ECPrivateKey(out, eckey,
                    371:                            ec_config.enc, NULL, 0, NULL, passout);
1.1       jsing     372:        } else {
                    373:                BIO_printf(bio_err, "bad output format specified for "
                    374:                    "outfile\n");
                    375:                goto end;
                    376:        }
                    377:
                    378:        if (!i) {
                    379:                BIO_printf(bio_err, "unable to write private key\n");
                    380:                ERR_print_errors(bio_err);
                    381:        } else
                    382:                ret = 0;
1.11      jsing     383:  end:
1.1       jsing     384:        BIO_free(in);
1.10      jsing     385:        BIO_free_all(out);
                    386:        EC_KEY_free(eckey);
1.1       jsing     387:        free(passin);
                    388:        free(passout);
                    389:
                    390:        return (ret);
                    391: }
                    392: #endif