1*a9d90585Stb /* $OpenBSD: ecparam.c,v 1.25 2025/01/19 10:24:17 tb Exp $ */ 2dab3f910Sjsing /* 3dab3f910Sjsing * Written by Nils Larsch for the OpenSSL project. 4dab3f910Sjsing */ 5dab3f910Sjsing /* ==================================================================== 6dab3f910Sjsing * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. 7dab3f910Sjsing * 8dab3f910Sjsing * Redistribution and use in source and binary forms, with or without 9dab3f910Sjsing * modification, are permitted provided that the following conditions 10dab3f910Sjsing * are met: 11dab3f910Sjsing * 12dab3f910Sjsing * 1. Redistributions of source code must retain the above copyright 13dab3f910Sjsing * notice, this list of conditions and the following disclaimer. 14dab3f910Sjsing * 15dab3f910Sjsing * 2. Redistributions in binary form must reproduce the above copyright 16dab3f910Sjsing * notice, this list of conditions and the following disclaimer in 17dab3f910Sjsing * the documentation and/or other materials provided with the 18dab3f910Sjsing * distribution. 19dab3f910Sjsing * 20dab3f910Sjsing * 3. All advertising materials mentioning features or use of this 21dab3f910Sjsing * software must display the following acknowledgment: 22dab3f910Sjsing * "This product includes software developed by the OpenSSL Project 23dab3f910Sjsing * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 24dab3f910Sjsing * 25dab3f910Sjsing * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26dab3f910Sjsing * endorse or promote products derived from this software without 27dab3f910Sjsing * prior written permission. For written permission, please contact 28dab3f910Sjsing * openssl-core@openssl.org. 29dab3f910Sjsing * 30dab3f910Sjsing * 5. Products derived from this software may not be called "OpenSSL" 31dab3f910Sjsing * nor may "OpenSSL" appear in their names without prior written 32dab3f910Sjsing * permission of the OpenSSL Project. 33dab3f910Sjsing * 34dab3f910Sjsing * 6. Redistributions of any form whatsoever must retain the following 35dab3f910Sjsing * acknowledgment: 36dab3f910Sjsing * "This product includes software developed by the OpenSSL Project 37dab3f910Sjsing * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 38dab3f910Sjsing * 39dab3f910Sjsing * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40dab3f910Sjsing * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41dab3f910Sjsing * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42dab3f910Sjsing * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43dab3f910Sjsing * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44dab3f910Sjsing * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45dab3f910Sjsing * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46dab3f910Sjsing * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47dab3f910Sjsing * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48dab3f910Sjsing * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49dab3f910Sjsing * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50dab3f910Sjsing * OF THE POSSIBILITY OF SUCH DAMAGE. 51dab3f910Sjsing * ==================================================================== 52dab3f910Sjsing * 53dab3f910Sjsing * This product includes cryptographic software written by Eric Young 54dab3f910Sjsing * (eay@cryptsoft.com). This product includes software written by Tim 55dab3f910Sjsing * Hudson (tjh@cryptsoft.com). 56dab3f910Sjsing * 57dab3f910Sjsing */ 58dab3f910Sjsing /* ==================================================================== 59dab3f910Sjsing * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 60dab3f910Sjsing * 61dab3f910Sjsing * Portions of the attached software ("Contribution") are developed by 62dab3f910Sjsing * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. 63dab3f910Sjsing * 64dab3f910Sjsing * The Contribution is licensed pursuant to the OpenSSL open source 65dab3f910Sjsing * license provided above. 66dab3f910Sjsing * 67dab3f910Sjsing * The elliptic curve binary polynomial software is originally written by 68dab3f910Sjsing * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories. 69dab3f910Sjsing * 70dab3f910Sjsing */ 71dab3f910Sjsing 72dab3f910Sjsing #include <openssl/opensslconf.h> 73dab3f910Sjsing 74dab3f910Sjsing #ifndef OPENSSL_NO_EC 75dab3f910Sjsing 76dab3f910Sjsing #include <stdio.h> 77dab3f910Sjsing #include <stdlib.h> 78dab3f910Sjsing #include <string.h> 79dab3f910Sjsing #include <time.h> 80dab3f910Sjsing 81dab3f910Sjsing #include "apps.h" 82dab3f910Sjsing 83dab3f910Sjsing #include <openssl/bio.h> 84dab3f910Sjsing #include <openssl/bn.h> 85dab3f910Sjsing #include <openssl/ec.h> 86dab3f910Sjsing #include <openssl/err.h> 87dab3f910Sjsing #include <openssl/pem.h> 88dab3f910Sjsing #include <openssl/x509.h> 89dab3f910Sjsing 906f5941c5Sjsing static struct { 916f5941c5Sjsing int asn1_flag; 926f5941c5Sjsing int check; 936f5941c5Sjsing char *curve_name; 946f5941c5Sjsing point_conversion_form_t form; 956f5941c5Sjsing int genkey; 966f5941c5Sjsing char *infile; 976f5941c5Sjsing int informat; 986f5941c5Sjsing int list_curves; 996f5941c5Sjsing int new_asn1_flag; 1006f5941c5Sjsing int new_form; 1016f5941c5Sjsing int no_seed; 1026f5941c5Sjsing int noout; 1036f5941c5Sjsing char *outfile; 1046f5941c5Sjsing int outformat; 1056f5941c5Sjsing int text; 106e7718adaStb } cfg; 107dab3f910Sjsing 1086f5941c5Sjsing static int 109d16f2e55Sjsing ecparam_opt_form(char *arg) 1106f5941c5Sjsing { 1116f5941c5Sjsing if (strcmp(arg, "compressed") == 0) 112e7718adaStb cfg.form = POINT_CONVERSION_COMPRESSED; 1136f5941c5Sjsing else if (strcmp(arg, "uncompressed") == 0) 114e7718adaStb cfg.form = POINT_CONVERSION_UNCOMPRESSED; 1156f5941c5Sjsing else if (strcmp(arg, "hybrid") == 0) 116e7718adaStb cfg.form = POINT_CONVERSION_HYBRID; 1176f5941c5Sjsing else 1186f5941c5Sjsing return (1); 1196f5941c5Sjsing 120e7718adaStb cfg.new_form = 1; 1216f5941c5Sjsing return (0); 1226f5941c5Sjsing } 1236f5941c5Sjsing 1246f5941c5Sjsing static int 125d16f2e55Sjsing ecparam_opt_enctype(char *arg) 1266f5941c5Sjsing { 1276f5941c5Sjsing if (strcmp(arg, "explicit") == 0) 128e7718adaStb cfg.asn1_flag = 0; 1296f5941c5Sjsing else if (strcmp(arg, "named_curve") == 0) 130e7718adaStb cfg.asn1_flag = OPENSSL_EC_NAMED_CURVE; 1316f5941c5Sjsing else 1326f5941c5Sjsing return (1); 1336f5941c5Sjsing 134e7718adaStb cfg.new_asn1_flag = 1; 1356f5941c5Sjsing return (0); 1366f5941c5Sjsing } 1376f5941c5Sjsing 138ea149709Sguenther static const struct option ecparam_options[] = { 1396f5941c5Sjsing { 1406f5941c5Sjsing .name = "check", 1416f5941c5Sjsing .desc = "Validate the elliptic curve parameters", 1426f5941c5Sjsing .type = OPTION_FLAG, 143e7718adaStb .opt.flag = &cfg.check, 1446f5941c5Sjsing }, 1456f5941c5Sjsing { 1466f5941c5Sjsing .name = "conv_form", 1476f5941c5Sjsing .argname = "form", 1486f5941c5Sjsing .desc = "Specify point conversion form:\n" 1496f5941c5Sjsing " compressed, uncompressed (default), hybrid", 1506f5941c5Sjsing .type = OPTION_ARG_FUNC, 151d16f2e55Sjsing .opt.argfunc = ecparam_opt_form, 1526f5941c5Sjsing }, 1536f5941c5Sjsing { 1546f5941c5Sjsing .name = "genkey", 1556f5941c5Sjsing .desc = "Generate an EC private key using the specified " 1566f5941c5Sjsing "parameters", 1576f5941c5Sjsing .type = OPTION_FLAG, 158e7718adaStb .opt.flag = &cfg.genkey, 1596f5941c5Sjsing }, 1606f5941c5Sjsing { 1616f5941c5Sjsing .name = "in", 1626f5941c5Sjsing .argname = "file", 1636f5941c5Sjsing .desc = "Input file to read parameters from (default stdin)", 1646f5941c5Sjsing .type = OPTION_ARG, 165e7718adaStb .opt.arg = &cfg.infile, 1666f5941c5Sjsing }, 1676f5941c5Sjsing { 1686f5941c5Sjsing .name = "inform", 1696f5941c5Sjsing .argname = "format", 1706f5941c5Sjsing .desc = "Input format (DER or PEM)", 1716f5941c5Sjsing .type = OPTION_ARG_FORMAT, 172e7718adaStb .opt.value = &cfg.informat, 1736f5941c5Sjsing }, 1746f5941c5Sjsing { 1756f5941c5Sjsing .name = "list_curves", 1766f5941c5Sjsing .desc = "Print list of all currently implemented EC " 1776f5941c5Sjsing "parameter names", 1786f5941c5Sjsing .type = OPTION_FLAG, 179e7718adaStb .opt.flag = &cfg.list_curves, 1806f5941c5Sjsing }, 1816f5941c5Sjsing { 1826f5941c5Sjsing .name = "name", 1836f5941c5Sjsing .argname = "curve", 1846f5941c5Sjsing .desc = "Use the EC parameters with the specified name", 1856f5941c5Sjsing .type = OPTION_ARG, 186e7718adaStb .opt.arg = &cfg.curve_name, 1876f5941c5Sjsing }, 1886f5941c5Sjsing { 1896f5941c5Sjsing .name = "no_seed", 1906f5941c5Sjsing .desc = "Do not output seed with explicit parameter encoding", 1916f5941c5Sjsing .type = OPTION_FLAG, 192e7718adaStb .opt.flag = &cfg.no_seed, 1936f5941c5Sjsing }, 1946f5941c5Sjsing { 1956f5941c5Sjsing .name = "noout", 1966f5941c5Sjsing .desc = "Do not output encoded version of EC parameters", 1976f5941c5Sjsing .type = OPTION_FLAG, 198e7718adaStb .opt.flag = &cfg.noout, 1996f5941c5Sjsing }, 2006f5941c5Sjsing { 2016f5941c5Sjsing .name = "out", 2026f5941c5Sjsing .argname = "file", 2036f5941c5Sjsing .desc = "Output file to write parameters to (default stdout)", 2046f5941c5Sjsing .type = OPTION_ARG, 205e7718adaStb .opt.arg = &cfg.outfile, 2066f5941c5Sjsing }, 2076f5941c5Sjsing { 2086f5941c5Sjsing .name = "outform", 2096f5941c5Sjsing .argname = "format", 2106f5941c5Sjsing .desc = "Output format (DER or PEM)", 2116f5941c5Sjsing .type = OPTION_ARG_FORMAT, 212e7718adaStb .opt.value = &cfg.outformat, 2136f5941c5Sjsing }, 2146f5941c5Sjsing { 2156f5941c5Sjsing .name = "param_enc", 2166f5941c5Sjsing .argname = "type", 2176f5941c5Sjsing .desc = "Specify EC parameter ASN.1 encoding type:\n" 2186f5941c5Sjsing " explicit, named_curve (default)", 2196f5941c5Sjsing .type = OPTION_ARG_FUNC, 220d16f2e55Sjsing .opt.argfunc = ecparam_opt_enctype, 2216f5941c5Sjsing }, 2226f5941c5Sjsing { 2236f5941c5Sjsing .name = "text", 2246f5941c5Sjsing .desc = "Print out the EC parameters in human readable form", 2256f5941c5Sjsing .type = OPTION_FLAG, 226e7718adaStb .opt.flag = &cfg.text, 2276f5941c5Sjsing }, 228d220e929Sbcook {NULL}, 2296f5941c5Sjsing }; 2306f5941c5Sjsing 2316f5941c5Sjsing static void 2326f5941c5Sjsing ecparam_usage(void) 2336f5941c5Sjsing { 234*a9d90585Stb fprintf(stderr, "usage: ecparam [-check] [-conv_form arg] " 2355284dfeaSbcook " [-genkey]\n" 2366f5941c5Sjsing " [-in file] [-inform DER | PEM] [-list_curves] [-name arg]\n" 2376f5941c5Sjsing " [-no_seed] [-noout] [-out file] [-outform DER | PEM]\n" 2386f5941c5Sjsing " [-param_enc arg] [-text]\n\n"); 2396f5941c5Sjsing options_usage(ecparam_options); 2406f5941c5Sjsing } 241dab3f910Sjsing 242dab3f910Sjsing int 243dab3f910Sjsing ecparam_main(int argc, char **argv) 244dab3f910Sjsing { 245dab3f910Sjsing EC_GROUP *group = NULL; 2466f5941c5Sjsing BIO *in = NULL, *out = NULL; 2476f5941c5Sjsing int i, ret = 1; 248dab3f910Sjsing 24951811eadSderaadt if (pledge("stdio cpath wpath rpath", NULL) == -1) { 2509bc487adSdoug perror("pledge"); 251e370f0eeSdoug exit(1); 252e370f0eeSdoug } 2539bc487adSdoug 254e7718adaStb memset(&cfg, 0, sizeof(cfg)); 255e7718adaStb cfg.asn1_flag = OPENSSL_EC_NAMED_CURVE; 256e7718adaStb cfg.form = POINT_CONVERSION_UNCOMPRESSED; 257e7718adaStb cfg.informat = FORMAT_PEM; 258e7718adaStb cfg.outformat = FORMAT_PEM; 259dab3f910Sjsing 260beba0da1Sjsing if (options_parse(argc, argv, ecparam_options, NULL, NULL) != 0) { 2616f5941c5Sjsing ecparam_usage(); 262dab3f910Sjsing goto end; 263dab3f910Sjsing } 264dab3f910Sjsing 265dab3f910Sjsing in = BIO_new(BIO_s_file()); 266dab3f910Sjsing out = BIO_new(BIO_s_file()); 267dab3f910Sjsing if ((in == NULL) || (out == NULL)) { 268dab3f910Sjsing ERR_print_errors(bio_err); 269dab3f910Sjsing goto end; 270dab3f910Sjsing } 271e7718adaStb if (cfg.infile == NULL) 272dab3f910Sjsing BIO_set_fp(in, stdin, BIO_NOCLOSE); 273dab3f910Sjsing else { 274e7718adaStb if (BIO_read_filename(in, cfg.infile) <= 0) { 275e7718adaStb perror(cfg.infile); 276dab3f910Sjsing goto end; 277dab3f910Sjsing } 278dab3f910Sjsing } 279e7718adaStb if (cfg.outfile == NULL) { 280dab3f910Sjsing BIO_set_fp(out, stdout, BIO_NOCLOSE); 281dab3f910Sjsing } else { 282e7718adaStb if (BIO_write_filename(out, cfg.outfile) <= 0) { 283e7718adaStb perror(cfg.outfile); 284dab3f910Sjsing goto end; 285dab3f910Sjsing } 286dab3f910Sjsing } 287dab3f910Sjsing 288e7718adaStb if (cfg.list_curves) { 289dab3f910Sjsing EC_builtin_curve *curves = NULL; 290dab3f910Sjsing size_t crv_len = 0; 291dab3f910Sjsing size_t n = 0; 292dab3f910Sjsing 293dab3f910Sjsing crv_len = EC_get_builtin_curves(NULL, 0); 294dab3f910Sjsing 295dab3f910Sjsing curves = reallocarray(NULL, crv_len, sizeof(EC_builtin_curve)); 296dab3f910Sjsing if (curves == NULL) 297dab3f910Sjsing goto end; 298dab3f910Sjsing 299dab3f910Sjsing if (!EC_get_builtin_curves(curves, crv_len)) { 300dab3f910Sjsing free(curves); 301dab3f910Sjsing goto end; 302dab3f910Sjsing } 303dab3f910Sjsing for (n = 0; n < crv_len; n++) { 304dab3f910Sjsing const char *comment; 305dab3f910Sjsing const char *sname; 306dab3f910Sjsing comment = curves[n].comment; 307dab3f910Sjsing sname = OBJ_nid2sn(curves[n].nid); 308dab3f910Sjsing if (comment == NULL) 309dab3f910Sjsing comment = "CURVE DESCRIPTION NOT AVAILABLE"; 310dab3f910Sjsing if (sname == NULL) 311dab3f910Sjsing sname = ""; 312dab3f910Sjsing 313dab3f910Sjsing BIO_printf(out, " %-10s: ", sname); 314dab3f910Sjsing BIO_printf(out, "%s\n", comment); 315dab3f910Sjsing } 316dab3f910Sjsing 317dab3f910Sjsing free(curves); 318dab3f910Sjsing ret = 0; 319dab3f910Sjsing goto end; 320dab3f910Sjsing } 321e7718adaStb if (cfg.curve_name != NULL) { 322dab3f910Sjsing int nid; 323dab3f910Sjsing 324dab3f910Sjsing /* 325dab3f910Sjsing * workaround for the SECG curve names secp192r1 and 326dab3f910Sjsing * secp256r1 (which are the same as the curves prime192v1 and 327dab3f910Sjsing * prime256v1 defined in X9.62) 328dab3f910Sjsing */ 329e7718adaStb if (!strcmp(cfg.curve_name, "secp192r1")) { 330dab3f910Sjsing BIO_printf(bio_err, "using curve name prime192v1 " 331dab3f910Sjsing "instead of secp192r1\n"); 332dab3f910Sjsing nid = NID_X9_62_prime192v1; 333e7718adaStb } else if (!strcmp(cfg.curve_name, "secp256r1")) { 334dab3f910Sjsing BIO_printf(bio_err, "using curve name prime256v1 " 335dab3f910Sjsing "instead of secp256r1\n"); 336dab3f910Sjsing nid = NID_X9_62_prime256v1; 337dab3f910Sjsing } else 338e7718adaStb nid = OBJ_sn2nid(cfg.curve_name); 339dab3f910Sjsing 340b4c4114dSjsing if (nid == 0) 341e7718adaStb nid = EC_curve_nist2nid(cfg.curve_name); 342b4c4114dSjsing 343dab3f910Sjsing if (nid == 0) { 344dab3f910Sjsing BIO_printf(bio_err, "unknown curve name (%s)\n", 345e7718adaStb cfg.curve_name); 346dab3f910Sjsing goto end; 347dab3f910Sjsing } 348dab3f910Sjsing group = EC_GROUP_new_by_curve_name(nid); 349dab3f910Sjsing if (group == NULL) { 350dab3f910Sjsing BIO_printf(bio_err, "unable to create curve (%s)\n", 351e7718adaStb cfg.curve_name); 352dab3f910Sjsing goto end; 353dab3f910Sjsing } 354e7718adaStb EC_GROUP_set_asn1_flag(group, cfg.asn1_flag); 355e7718adaStb EC_GROUP_set_point_conversion_form(group, cfg.form); 356e7718adaStb } else if (cfg.informat == FORMAT_ASN1) { 357dab3f910Sjsing group = d2i_ECPKParameters_bio(in, NULL); 358e7718adaStb } else if (cfg.informat == FORMAT_PEM) { 359dab3f910Sjsing group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL); 360dab3f910Sjsing } else { 361dab3f910Sjsing BIO_printf(bio_err, "bad input format specified\n"); 362dab3f910Sjsing goto end; 363dab3f910Sjsing } 364dab3f910Sjsing 365dab3f910Sjsing if (group == NULL) { 366dab3f910Sjsing BIO_printf(bio_err, 367dab3f910Sjsing "unable to load elliptic curve parameters\n"); 368dab3f910Sjsing ERR_print_errors(bio_err); 369dab3f910Sjsing goto end; 370dab3f910Sjsing } 371e7718adaStb if (cfg.new_form) 372e7718adaStb EC_GROUP_set_point_conversion_form(group, cfg.form); 373dab3f910Sjsing 374e7718adaStb if (cfg.new_asn1_flag) 375e7718adaStb EC_GROUP_set_asn1_flag(group, cfg.asn1_flag); 376dab3f910Sjsing 377e7718adaStb if (cfg.no_seed) 378dab3f910Sjsing EC_GROUP_set_seed(group, NULL, 0); 3796f5941c5Sjsing 380e7718adaStb if (cfg.text) { 381dab3f910Sjsing if (!ECPKParameters_print(out, group, 0)) 382dab3f910Sjsing goto end; 383dab3f910Sjsing } 384e7718adaStb if (cfg.check) { 385dab3f910Sjsing BIO_printf(bio_err, "checking elliptic curve parameters: "); 386dab3f910Sjsing if (!EC_GROUP_check(group, NULL)) { 387dab3f910Sjsing BIO_printf(bio_err, "failed\n"); 388dab3f910Sjsing ERR_print_errors(bio_err); 389dab3f910Sjsing } else 390dab3f910Sjsing BIO_printf(bio_err, "ok\n"); 391dab3f910Sjsing 392dab3f910Sjsing } 393e7718adaStb if (!cfg.noout) { 394e7718adaStb if (cfg.outformat == FORMAT_ASN1) 395dab3f910Sjsing i = i2d_ECPKParameters_bio(out, group); 396e7718adaStb else if (cfg.outformat == FORMAT_PEM) 397dab3f910Sjsing i = PEM_write_bio_ECPKParameters(out, group); 398dab3f910Sjsing else { 399dab3f910Sjsing BIO_printf(bio_err, "bad output format specified for" 400dab3f910Sjsing " outfile\n"); 401dab3f910Sjsing goto end; 402dab3f910Sjsing } 403dab3f910Sjsing if (!i) { 404dab3f910Sjsing BIO_printf(bio_err, "unable to write elliptic " 405dab3f910Sjsing "curve parameters\n"); 406dab3f910Sjsing ERR_print_errors(bio_err); 407dab3f910Sjsing goto end; 408dab3f910Sjsing } 409dab3f910Sjsing } 410e7718adaStb if (cfg.genkey) { 411dab3f910Sjsing EC_KEY *eckey = EC_KEY_new(); 412dab3f910Sjsing 413dab3f910Sjsing if (eckey == NULL) 414dab3f910Sjsing goto end; 415dab3f910Sjsing 416dab3f910Sjsing if (EC_KEY_set_group(eckey, group) == 0) { 417dab3f910Sjsing EC_KEY_free(eckey); 418dab3f910Sjsing goto end; 419dab3f910Sjsing } 420dab3f910Sjsing 421dab3f910Sjsing if (!EC_KEY_generate_key(eckey)) { 422dab3f910Sjsing EC_KEY_free(eckey); 423dab3f910Sjsing goto end; 424dab3f910Sjsing } 425e7718adaStb if (cfg.outformat == FORMAT_ASN1) 426dab3f910Sjsing i = i2d_ECPrivateKey_bio(out, eckey); 427e7718adaStb else if (cfg.outformat == FORMAT_PEM) 428dab3f910Sjsing i = PEM_write_bio_ECPrivateKey(out, eckey, NULL, 429dab3f910Sjsing NULL, 0, NULL, NULL); 430dab3f910Sjsing else { 431dab3f910Sjsing BIO_printf(bio_err, "bad output format specified " 432dab3f910Sjsing "for outfile\n"); 433dab3f910Sjsing EC_KEY_free(eckey); 434dab3f910Sjsing goto end; 435dab3f910Sjsing } 436dab3f910Sjsing EC_KEY_free(eckey); 437dab3f910Sjsing } 438dab3f910Sjsing ret = 0; 43963188486Sjsing 440dab3f910Sjsing end: 441dab3f910Sjsing BIO_free(in); 442dab3f910Sjsing BIO_free_all(out); 443dab3f910Sjsing EC_GROUP_free(group); 444dab3f910Sjsing 445dab3f910Sjsing return (ret); 446dab3f910Sjsing } 447dab3f910Sjsing 448dab3f910Sjsing #endif 449