13b4e3dcbSSimon L. B. Nielsen /* 2*e71b7053SJung-uk Kim * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. 3*e71b7053SJung-uk Kim * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved 43b4e3dcbSSimon L. B. Nielsen * 5*e71b7053SJung-uk Kim * Licensed under the OpenSSL license (the "License"). You may not use 6*e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 7*e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at 8*e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html 93b4e3dcbSSimon L. B. Nielsen */ 103b4e3dcbSSimon L. B. Nielsen 113b4e3dcbSSimon L. B. Nielsen #include <openssl/opensslconf.h> 12*e71b7053SJung-uk Kim #ifdef OPENSSL_NO_EC 13*e71b7053SJung-uk Kim NON_EMPTY_TRANSLATION_UNIT 14*e71b7053SJung-uk Kim #else 15*e71b7053SJung-uk Kim 163b4e3dcbSSimon L. B. Nielsen # include <stdio.h> 173b4e3dcbSSimon L. B. Nielsen # include <stdlib.h> 183b4e3dcbSSimon L. B. Nielsen # include <time.h> 193b4e3dcbSSimon L. B. Nielsen # include <string.h> 203b4e3dcbSSimon L. B. Nielsen # include "apps.h" 21*e71b7053SJung-uk Kim # include "progs.h" 223b4e3dcbSSimon L. B. Nielsen # include <openssl/bio.h> 233b4e3dcbSSimon L. B. Nielsen # include <openssl/err.h> 243b4e3dcbSSimon L. B. Nielsen # include <openssl/bn.h> 253b4e3dcbSSimon L. B. Nielsen # include <openssl/ec.h> 263b4e3dcbSSimon L. B. Nielsen # include <openssl/x509.h> 273b4e3dcbSSimon L. B. Nielsen # include <openssl/pem.h> 283b4e3dcbSSimon L. B. Nielsen 29*e71b7053SJung-uk Kim typedef enum OPTION_choice { 30*e71b7053SJung-uk Kim OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, 31*e71b7053SJung-uk Kim OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, OPT_C, 32*e71b7053SJung-uk Kim OPT_CHECK, OPT_LIST_CURVES, OPT_NO_SEED, OPT_NOOUT, OPT_NAME, 33*e71b7053SJung-uk Kim OPT_CONV_FORM, OPT_PARAM_ENC, OPT_GENKEY, OPT_ENGINE, 34*e71b7053SJung-uk Kim OPT_R_ENUM 35*e71b7053SJung-uk Kim } OPTION_CHOICE; 363b4e3dcbSSimon L. B. Nielsen 37*e71b7053SJung-uk Kim const OPTIONS ecparam_options[] = { 38*e71b7053SJung-uk Kim {"help", OPT_HELP, '-', "Display this summary"}, 39*e71b7053SJung-uk Kim {"inform", OPT_INFORM, 'F', "Input format - default PEM (DER or PEM)"}, 40*e71b7053SJung-uk Kim {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"}, 41*e71b7053SJung-uk Kim {"in", OPT_IN, '<', "Input file - default stdin"}, 42*e71b7053SJung-uk Kim {"out", OPT_OUT, '>', "Output file - default stdout"}, 43*e71b7053SJung-uk Kim {"text", OPT_TEXT, '-', "Print the ec parameters in text form"}, 44*e71b7053SJung-uk Kim {"C", OPT_C, '-', "Print a 'C' function creating the parameters"}, 45*e71b7053SJung-uk Kim {"check", OPT_CHECK, '-', "Validate the ec parameters"}, 46*e71b7053SJung-uk Kim {"list_curves", OPT_LIST_CURVES, '-', 47*e71b7053SJung-uk Kim "Prints a list of all curve 'short names'"}, 48*e71b7053SJung-uk Kim {"no_seed", OPT_NO_SEED, '-', 49*e71b7053SJung-uk Kim "If 'explicit' parameters are chosen do not use the seed"}, 50*e71b7053SJung-uk Kim {"noout", OPT_NOOUT, '-', "Do not print the ec parameter"}, 51*e71b7053SJung-uk Kim {"name", OPT_NAME, 's', 52*e71b7053SJung-uk Kim "Use the ec parameters with specified 'short name'"}, 53*e71b7053SJung-uk Kim {"conv_form", OPT_CONV_FORM, 's', "Specifies the point conversion form "}, 54*e71b7053SJung-uk Kim {"param_enc", OPT_PARAM_ENC, 's', 55*e71b7053SJung-uk Kim "Specifies the way the ec parameters are encoded"}, 56*e71b7053SJung-uk Kim {"genkey", OPT_GENKEY, '-', "Generate ec key"}, 57*e71b7053SJung-uk Kim OPT_R_OPTIONS, 58*e71b7053SJung-uk Kim # ifndef OPENSSL_NO_ENGINE 59*e71b7053SJung-uk Kim {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 60*e71b7053SJung-uk Kim # endif 61*e71b7053SJung-uk Kim {NULL} 62*e71b7053SJung-uk Kim }; 633b4e3dcbSSimon L. B. Nielsen 64*e71b7053SJung-uk Kim static OPT_PAIR forms[] = { 65*e71b7053SJung-uk Kim {"compressed", POINT_CONVERSION_COMPRESSED}, 66*e71b7053SJung-uk Kim {"uncompressed", POINT_CONVERSION_UNCOMPRESSED}, 67*e71b7053SJung-uk Kim {"hybrid", POINT_CONVERSION_HYBRID}, 68*e71b7053SJung-uk Kim {NULL} 69*e71b7053SJung-uk Kim }; 703b4e3dcbSSimon L. B. Nielsen 71*e71b7053SJung-uk Kim static OPT_PAIR encodings[] = { 72*e71b7053SJung-uk Kim {"named_curve", OPENSSL_EC_NAMED_CURVE}, 73*e71b7053SJung-uk Kim {"explicit", 0}, 74*e71b7053SJung-uk Kim {NULL} 75*e71b7053SJung-uk Kim }; 763b4e3dcbSSimon L. B. Nielsen 77*e71b7053SJung-uk Kim int ecparam_main(int argc, char **argv) 783b4e3dcbSSimon L. B. Nielsen { 79*e71b7053SJung-uk Kim ENGINE *e = NULL; 80*e71b7053SJung-uk Kim BIGNUM *ec_gen = NULL, *ec_order = NULL, *ec_cofactor = NULL; 81*e71b7053SJung-uk Kim BIGNUM *ec_p = NULL, *ec_a = NULL, *ec_b = NULL; 82*e71b7053SJung-uk Kim BIO *in = NULL, *out = NULL; 833b4e3dcbSSimon L. B. Nielsen EC_GROUP *group = NULL; 843b4e3dcbSSimon L. B. Nielsen point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED; 85*e71b7053SJung-uk Kim char *curve_name = NULL; 863b4e3dcbSSimon L. B. Nielsen char *infile = NULL, *outfile = NULL, *prog; 873b4e3dcbSSimon L. B. Nielsen unsigned char *buffer = NULL; 88*e71b7053SJung-uk Kim OPTION_CHOICE o; 89*e71b7053SJung-uk Kim int asn1_flag = OPENSSL_EC_NAMED_CURVE, new_asn1_flag = 0; 90*e71b7053SJung-uk Kim int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0; 91*e71b7053SJung-uk Kim int ret = 1, private = 0; 92*e71b7053SJung-uk Kim int list_curves = 0, no_seed = 0, check = 0, new_form = 0; 93*e71b7053SJung-uk Kim int text = 0, i, genkey = 0; 943b4e3dcbSSimon L. B. Nielsen 95*e71b7053SJung-uk Kim prog = opt_init(argc, argv, ecparam_options); 96*e71b7053SJung-uk Kim while ((o = opt_next()) != OPT_EOF) { 97*e71b7053SJung-uk Kim switch (o) { 98*e71b7053SJung-uk Kim case OPT_EOF: 99*e71b7053SJung-uk Kim case OPT_ERR: 100*e71b7053SJung-uk Kim opthelp: 101*e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 1023b4e3dcbSSimon L. B. Nielsen goto end; 103*e71b7053SJung-uk Kim case OPT_HELP: 104*e71b7053SJung-uk Kim opt_help(ecparam_options); 105*e71b7053SJung-uk Kim ret = 0; 106*e71b7053SJung-uk Kim goto end; 107*e71b7053SJung-uk Kim case OPT_INFORM: 108*e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) 109*e71b7053SJung-uk Kim goto opthelp; 110*e71b7053SJung-uk Kim break; 111*e71b7053SJung-uk Kim case OPT_IN: 112*e71b7053SJung-uk Kim infile = opt_arg(); 113*e71b7053SJung-uk Kim break; 114*e71b7053SJung-uk Kim case OPT_OUTFORM: 115*e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) 116*e71b7053SJung-uk Kim goto opthelp; 117*e71b7053SJung-uk Kim break; 118*e71b7053SJung-uk Kim case OPT_OUT: 119*e71b7053SJung-uk Kim outfile = opt_arg(); 120*e71b7053SJung-uk Kim break; 121*e71b7053SJung-uk Kim case OPT_TEXT: 1223b4e3dcbSSimon L. B. Nielsen text = 1; 123*e71b7053SJung-uk Kim break; 124*e71b7053SJung-uk Kim case OPT_C: 1253b4e3dcbSSimon L. B. Nielsen C = 1; 126*e71b7053SJung-uk Kim break; 127*e71b7053SJung-uk Kim case OPT_CHECK: 1283b4e3dcbSSimon L. B. Nielsen check = 1; 129*e71b7053SJung-uk Kim break; 130*e71b7053SJung-uk Kim case OPT_LIST_CURVES: 1313b4e3dcbSSimon L. B. Nielsen list_curves = 1; 132*e71b7053SJung-uk Kim break; 133*e71b7053SJung-uk Kim case OPT_NO_SEED: 1343b4e3dcbSSimon L. B. Nielsen no_seed = 1; 135*e71b7053SJung-uk Kim break; 136*e71b7053SJung-uk Kim case OPT_NOOUT: 1373b4e3dcbSSimon L. B. Nielsen noout = 1; 138*e71b7053SJung-uk Kim break; 139*e71b7053SJung-uk Kim case OPT_NAME: 140*e71b7053SJung-uk Kim curve_name = opt_arg(); 141*e71b7053SJung-uk Kim break; 142*e71b7053SJung-uk Kim case OPT_CONV_FORM: 143*e71b7053SJung-uk Kim if (!opt_pair(opt_arg(), forms, &new_form)) 144*e71b7053SJung-uk Kim goto opthelp; 145*e71b7053SJung-uk Kim form = new_form; 146*e71b7053SJung-uk Kim new_form = 1; 147*e71b7053SJung-uk Kim break; 148*e71b7053SJung-uk Kim case OPT_PARAM_ENC: 149*e71b7053SJung-uk Kim if (!opt_pair(opt_arg(), encodings, &asn1_flag)) 150*e71b7053SJung-uk Kim goto opthelp; 151*e71b7053SJung-uk Kim new_asn1_flag = 1; 152*e71b7053SJung-uk Kim break; 153*e71b7053SJung-uk Kim case OPT_GENKEY: 1543b4e3dcbSSimon L. B. Nielsen genkey = 1; 155*e71b7053SJung-uk Kim break; 156*e71b7053SJung-uk Kim case OPT_R_CASES: 157*e71b7053SJung-uk Kim if (!opt_rand(o)) 158*e71b7053SJung-uk Kim goto end; 159*e71b7053SJung-uk Kim break; 160*e71b7053SJung-uk Kim case OPT_ENGINE: 161*e71b7053SJung-uk Kim e = setup_engine(opt_arg(), 0); 1623b4e3dcbSSimon L. B. Nielsen break; 1633b4e3dcbSSimon L. B. Nielsen } 1643b4e3dcbSSimon L. B. Nielsen } 165*e71b7053SJung-uk Kim argc = opt_num_rest(); 166*e71b7053SJung-uk Kim if (argc != 0) 167*e71b7053SJung-uk Kim goto opthelp; 1683b4e3dcbSSimon L. B. Nielsen 169*e71b7053SJung-uk Kim private = genkey ? 1 : 0; 170*e71b7053SJung-uk Kim 171*e71b7053SJung-uk Kim in = bio_open_default(infile, 'r', informat); 172*e71b7053SJung-uk Kim if (in == NULL) 1733b4e3dcbSSimon L. B. Nielsen goto end; 174*e71b7053SJung-uk Kim out = bio_open_owner(outfile, outformat, private); 175*e71b7053SJung-uk Kim if (out == NULL) 1763b4e3dcbSSimon L. B. Nielsen goto end; 1773b4e3dcbSSimon L. B. Nielsen 1786f9291ceSJung-uk Kim if (list_curves) { 1793b4e3dcbSSimon L. B. Nielsen EC_builtin_curve *curves = NULL; 180*e71b7053SJung-uk Kim size_t crv_len = EC_get_builtin_curves(NULL, 0); 181*e71b7053SJung-uk Kim size_t n; 1823b4e3dcbSSimon L. B. Nielsen 183*e71b7053SJung-uk Kim curves = app_malloc((int)sizeof(*curves) * crv_len, "list curves"); 1846f9291ceSJung-uk Kim if (!EC_get_builtin_curves(curves, crv_len)) { 1853b4e3dcbSSimon L. B. Nielsen OPENSSL_free(curves); 1863b4e3dcbSSimon L. B. Nielsen goto end; 1873b4e3dcbSSimon L. B. Nielsen } 1883b4e3dcbSSimon L. B. Nielsen 1896f9291ceSJung-uk Kim for (n = 0; n < crv_len; n++) { 1903b4e3dcbSSimon L. B. Nielsen const char *comment; 1913b4e3dcbSSimon L. B. Nielsen const char *sname; 1923b4e3dcbSSimon L. B. Nielsen comment = curves[n].comment; 1933b4e3dcbSSimon L. B. Nielsen sname = OBJ_nid2sn(curves[n].nid); 1943b4e3dcbSSimon L. B. Nielsen if (comment == NULL) 1953b4e3dcbSSimon L. B. Nielsen comment = "CURVE DESCRIPTION NOT AVAILABLE"; 1963b4e3dcbSSimon L. B. Nielsen if (sname == NULL) 1973b4e3dcbSSimon L. B. Nielsen sname = ""; 1983b4e3dcbSSimon L. B. Nielsen 1993b4e3dcbSSimon L. B. Nielsen BIO_printf(out, " %-10s: ", sname); 2003b4e3dcbSSimon L. B. Nielsen BIO_printf(out, "%s\n", comment); 2013b4e3dcbSSimon L. B. Nielsen } 2023b4e3dcbSSimon L. B. Nielsen 2033b4e3dcbSSimon L. B. Nielsen OPENSSL_free(curves); 2043b4e3dcbSSimon L. B. Nielsen ret = 0; 2053b4e3dcbSSimon L. B. Nielsen goto end; 2063b4e3dcbSSimon L. B. Nielsen } 2073b4e3dcbSSimon L. B. Nielsen 2086f9291ceSJung-uk Kim if (curve_name != NULL) { 2093b4e3dcbSSimon L. B. Nielsen int nid; 2103b4e3dcbSSimon L. B. Nielsen 2116f9291ceSJung-uk Kim /* 2126f9291ceSJung-uk Kim * workaround for the SECG curve names secp192r1 and secp256r1 (which 2136f9291ceSJung-uk Kim * are the same as the curves prime192v1 and prime256v1 defined in 2146f9291ceSJung-uk Kim * X9.62) 2153b4e3dcbSSimon L. B. Nielsen */ 216*e71b7053SJung-uk Kim if (strcmp(curve_name, "secp192r1") == 0) { 2173b4e3dcbSSimon L. B. Nielsen BIO_printf(bio_err, "using curve name prime192v1 " 2183b4e3dcbSSimon L. B. Nielsen "instead of secp192r1\n"); 2193b4e3dcbSSimon L. B. Nielsen nid = NID_X9_62_prime192v1; 220*e71b7053SJung-uk Kim } else if (strcmp(curve_name, "secp256r1") == 0) { 2213b4e3dcbSSimon L. B. Nielsen BIO_printf(bio_err, "using curve name prime256v1 " 2223b4e3dcbSSimon L. B. Nielsen "instead of secp256r1\n"); 2233b4e3dcbSSimon L. B. Nielsen nid = NID_X9_62_prime256v1; 224*e71b7053SJung-uk Kim } else { 2253b4e3dcbSSimon L. B. Nielsen nid = OBJ_sn2nid(curve_name); 226*e71b7053SJung-uk Kim } 2273b4e3dcbSSimon L. B. Nielsen 2287bded2dbSJung-uk Kim if (nid == 0) 2297bded2dbSJung-uk Kim nid = EC_curve_nist2nid(curve_name); 2307bded2dbSJung-uk Kim 2316f9291ceSJung-uk Kim if (nid == 0) { 2326f9291ceSJung-uk Kim BIO_printf(bio_err, "unknown curve name (%s)\n", curve_name); 2333b4e3dcbSSimon L. B. Nielsen goto end; 2343b4e3dcbSSimon L. B. Nielsen } 2353b4e3dcbSSimon L. B. Nielsen 2363b4e3dcbSSimon L. B. Nielsen group = EC_GROUP_new_by_curve_name(nid); 2376f9291ceSJung-uk Kim if (group == NULL) { 2386f9291ceSJung-uk Kim BIO_printf(bio_err, "unable to create curve (%s)\n", curve_name); 2393b4e3dcbSSimon L. B. Nielsen goto end; 2403b4e3dcbSSimon L. B. Nielsen } 2413b4e3dcbSSimon L. B. Nielsen EC_GROUP_set_asn1_flag(group, asn1_flag); 2423b4e3dcbSSimon L. B. Nielsen EC_GROUP_set_point_conversion_form(group, form); 2436f9291ceSJung-uk Kim } else if (informat == FORMAT_ASN1) { 2443b4e3dcbSSimon L. B. Nielsen group = d2i_ECPKParameters_bio(in, NULL); 2456f9291ceSJung-uk Kim } else { 246*e71b7053SJung-uk Kim group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL); 2473b4e3dcbSSimon L. B. Nielsen } 2486f9291ceSJung-uk Kim if (group == NULL) { 2496f9291ceSJung-uk Kim BIO_printf(bio_err, "unable to load elliptic curve parameters\n"); 2503b4e3dcbSSimon L. B. Nielsen ERR_print_errors(bio_err); 2513b4e3dcbSSimon L. B. Nielsen goto end; 2523b4e3dcbSSimon L. B. Nielsen } 2533b4e3dcbSSimon L. B. Nielsen 2543b4e3dcbSSimon L. B. Nielsen if (new_form) 2553b4e3dcbSSimon L. B. Nielsen EC_GROUP_set_point_conversion_form(group, form); 2563b4e3dcbSSimon L. B. Nielsen 2573b4e3dcbSSimon L. B. Nielsen if (new_asn1_flag) 2583b4e3dcbSSimon L. B. Nielsen EC_GROUP_set_asn1_flag(group, asn1_flag); 2593b4e3dcbSSimon L. B. Nielsen 2606f9291ceSJung-uk Kim if (no_seed) { 2613b4e3dcbSSimon L. B. Nielsen EC_GROUP_set_seed(group, NULL, 0); 2623b4e3dcbSSimon L. B. Nielsen } 2633b4e3dcbSSimon L. B. Nielsen 2646f9291ceSJung-uk Kim if (text) { 2653b4e3dcbSSimon L. B. Nielsen if (!ECPKParameters_print(out, group, 0)) 2663b4e3dcbSSimon L. B. Nielsen goto end; 2673b4e3dcbSSimon L. B. Nielsen } 2683b4e3dcbSSimon L. B. Nielsen 2696f9291ceSJung-uk Kim if (check) { 2703b4e3dcbSSimon L. B. Nielsen BIO_printf(bio_err, "checking elliptic curve parameters: "); 2716f9291ceSJung-uk Kim if (!EC_GROUP_check(group, NULL)) { 2723b4e3dcbSSimon L. B. Nielsen BIO_printf(bio_err, "failed\n"); 2733b4e3dcbSSimon L. B. Nielsen ERR_print_errors(bio_err); 27480815a77SJung-uk Kim goto end; 27580815a77SJung-uk Kim } 2763b4e3dcbSSimon L. B. Nielsen BIO_printf(bio_err, "ok\n"); 2773b4e3dcbSSimon L. B. Nielsen 2783b4e3dcbSSimon L. B. Nielsen } 2793b4e3dcbSSimon L. B. Nielsen 2806f9291ceSJung-uk Kim if (C) { 2813b4e3dcbSSimon L. B. Nielsen size_t buf_len = 0, tmp_len = 0; 2823b4e3dcbSSimon L. B. Nielsen const EC_POINT *point; 2833b4e3dcbSSimon L. B. Nielsen int is_prime, len = 0; 2843b4e3dcbSSimon L. B. Nielsen const EC_METHOD *meth = EC_GROUP_method_of(group); 2853b4e3dcbSSimon L. B. Nielsen 286*e71b7053SJung-uk Kim if ((ec_p = BN_new()) == NULL 287*e71b7053SJung-uk Kim || (ec_a = BN_new()) == NULL 288*e71b7053SJung-uk Kim || (ec_b = BN_new()) == NULL 289*e71b7053SJung-uk Kim || (ec_gen = BN_new()) == NULL 290*e71b7053SJung-uk Kim || (ec_order = BN_new()) == NULL 291*e71b7053SJung-uk Kim || (ec_cofactor = BN_new()) == NULL) { 292*e71b7053SJung-uk Kim perror("Can't allocate BN"); 2933b4e3dcbSSimon L. B. Nielsen goto end; 2943b4e3dcbSSimon L. B. Nielsen } 2953b4e3dcbSSimon L. B. Nielsen 2966f9291ceSJung-uk Kim is_prime = (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field); 297*e71b7053SJung-uk Kim if (!is_prime) { 298*e71b7053SJung-uk Kim BIO_printf(bio_err, "Can only handle X9.62 prime fields\n"); 2993b4e3dcbSSimon L. B. Nielsen goto end; 3003b4e3dcbSSimon L. B. Nielsen } 3013b4e3dcbSSimon L. B. Nielsen 302*e71b7053SJung-uk Kim if (!EC_GROUP_get_curve(group, ec_p, ec_a, ec_b, NULL)) 303*e71b7053SJung-uk Kim goto end; 304*e71b7053SJung-uk Kim 3053b4e3dcbSSimon L. B. Nielsen if ((point = EC_GROUP_get0_generator(group)) == NULL) 3063b4e3dcbSSimon L. B. Nielsen goto end; 3073b4e3dcbSSimon L. B. Nielsen if (!EC_POINT_point2bn(group, point, 3086f9291ceSJung-uk Kim EC_GROUP_get_point_conversion_form(group), 3096f9291ceSJung-uk Kim ec_gen, NULL)) 3103b4e3dcbSSimon L. B. Nielsen goto end; 3113b4e3dcbSSimon L. B. Nielsen if (!EC_GROUP_get_order(group, ec_order, NULL)) 3123b4e3dcbSSimon L. B. Nielsen goto end; 3133b4e3dcbSSimon L. B. Nielsen if (!EC_GROUP_get_cofactor(group, ec_cofactor, NULL)) 3143b4e3dcbSSimon L. B. Nielsen goto end; 3153b4e3dcbSSimon L. B. Nielsen 3166f9291ceSJung-uk Kim if (!ec_p || !ec_a || !ec_b || !ec_gen || !ec_order || !ec_cofactor) 3173b4e3dcbSSimon L. B. Nielsen goto end; 3183b4e3dcbSSimon L. B. Nielsen 3193b4e3dcbSSimon L. B. Nielsen len = BN_num_bits(ec_order); 3203b4e3dcbSSimon L. B. Nielsen 3213b4e3dcbSSimon L. B. Nielsen if ((tmp_len = (size_t)BN_num_bytes(ec_p)) > buf_len) 3223b4e3dcbSSimon L. B. Nielsen buf_len = tmp_len; 3233b4e3dcbSSimon L. B. Nielsen if ((tmp_len = (size_t)BN_num_bytes(ec_a)) > buf_len) 3243b4e3dcbSSimon L. B. Nielsen buf_len = tmp_len; 3253b4e3dcbSSimon L. B. Nielsen if ((tmp_len = (size_t)BN_num_bytes(ec_b)) > buf_len) 3263b4e3dcbSSimon L. B. Nielsen buf_len = tmp_len; 3273b4e3dcbSSimon L. B. Nielsen if ((tmp_len = (size_t)BN_num_bytes(ec_gen)) > buf_len) 3283b4e3dcbSSimon L. B. Nielsen buf_len = tmp_len; 3293b4e3dcbSSimon L. B. Nielsen if ((tmp_len = (size_t)BN_num_bytes(ec_order)) > buf_len) 3303b4e3dcbSSimon L. B. Nielsen buf_len = tmp_len; 3313b4e3dcbSSimon L. B. Nielsen if ((tmp_len = (size_t)BN_num_bytes(ec_cofactor)) > buf_len) 3323b4e3dcbSSimon L. B. Nielsen buf_len = tmp_len; 3333b4e3dcbSSimon L. B. Nielsen 334*e71b7053SJung-uk Kim buffer = app_malloc(buf_len, "BN buffer"); 3353b4e3dcbSSimon L. B. Nielsen 336*e71b7053SJung-uk Kim BIO_printf(out, "EC_GROUP *get_ec_group_%d(void)\n{\n", len); 337*e71b7053SJung-uk Kim print_bignum_var(out, ec_p, "ec_p", len, buffer); 338*e71b7053SJung-uk Kim print_bignum_var(out, ec_a, "ec_a", len, buffer); 339*e71b7053SJung-uk Kim print_bignum_var(out, ec_b, "ec_b", len, buffer); 340*e71b7053SJung-uk Kim print_bignum_var(out, ec_gen, "ec_gen", len, buffer); 341*e71b7053SJung-uk Kim print_bignum_var(out, ec_order, "ec_order", len, buffer); 342*e71b7053SJung-uk Kim print_bignum_var(out, ec_cofactor, "ec_cofactor", len, buffer); 343*e71b7053SJung-uk Kim BIO_printf(out, " int ok = 0;\n" 344*e71b7053SJung-uk Kim " EC_GROUP *group = NULL;\n" 345*e71b7053SJung-uk Kim " EC_POINT *point = NULL;\n" 346*e71b7053SJung-uk Kim " BIGNUM *tmp_1 = NULL;\n" 347*e71b7053SJung-uk Kim " BIGNUM *tmp_2 = NULL;\n" 348*e71b7053SJung-uk Kim " BIGNUM *tmp_3 = NULL;\n" 349*e71b7053SJung-uk Kim "\n"); 3503b4e3dcbSSimon L. B. Nielsen 351*e71b7053SJung-uk Kim BIO_printf(out, " if ((tmp_1 = BN_bin2bn(ec_p_%d, sizeof(ec_p_%d), NULL)) == NULL)\n" 3523b4e3dcbSSimon L. B. Nielsen " goto err;\n", len, len); 353*e71b7053SJung-uk Kim BIO_printf(out, " if ((tmp_2 = BN_bin2bn(ec_a_%d, sizeof(ec_a_%d), NULL)) == NULL)\n" 3543b4e3dcbSSimon L. B. Nielsen " goto err;\n", len, len); 355*e71b7053SJung-uk Kim BIO_printf(out, " if ((tmp_3 = BN_bin2bn(ec_b_%d, sizeof(ec_b_%d), NULL)) == NULL)\n" 3563b4e3dcbSSimon L. B. Nielsen " goto err;\n", len, len); 357*e71b7053SJung-uk Kim BIO_printf(out, " if ((group = EC_GROUP_new_curve_GFp(tmp_1, tmp_2, tmp_3, NULL)) == NULL)\n" 358*e71b7053SJung-uk Kim " goto err;\n" 359*e71b7053SJung-uk Kim "\n"); 360*e71b7053SJung-uk Kim BIO_printf(out, " /* build generator */\n"); 361*e71b7053SJung-uk Kim BIO_printf(out, " if ((tmp_1 = BN_bin2bn(ec_gen_%d, sizeof(ec_gen_%d), tmp_1)) == NULL)\n" 362*e71b7053SJung-uk Kim " goto err;\n", len, len); 363*e71b7053SJung-uk Kim BIO_printf(out, " point = EC_POINT_bn2point(group, tmp_1, NULL, NULL);\n"); 364*e71b7053SJung-uk Kim BIO_printf(out, " if (point == NULL)\n" 365*e71b7053SJung-uk Kim " goto err;\n"); 366*e71b7053SJung-uk Kim BIO_printf(out, " if ((tmp_2 = BN_bin2bn(ec_order_%d, sizeof(ec_order_%d), tmp_2)) == NULL)\n" 367*e71b7053SJung-uk Kim " goto err;\n", len, len); 368*e71b7053SJung-uk Kim BIO_printf(out, " if ((tmp_3 = BN_bin2bn(ec_cofactor_%d, sizeof(ec_cofactor_%d), tmp_3)) == NULL)\n" 369*e71b7053SJung-uk Kim " goto err;\n", len, len); 370*e71b7053SJung-uk Kim BIO_printf(out, " if (!EC_GROUP_set_generator(group, point, tmp_2, tmp_3))\n" 371*e71b7053SJung-uk Kim " goto err;\n" 372*e71b7053SJung-uk Kim "ok = 1;" 373*e71b7053SJung-uk Kim "\n"); 374*e71b7053SJung-uk Kim BIO_printf(out, "err:\n" 375*e71b7053SJung-uk Kim " BN_free(tmp_1);\n" 376*e71b7053SJung-uk Kim " BN_free(tmp_2);\n" 377*e71b7053SJung-uk Kim " BN_free(tmp_3);\n" 378*e71b7053SJung-uk Kim " EC_POINT_free(point);\n" 379*e71b7053SJung-uk Kim " if (!ok) {\n" 380*e71b7053SJung-uk Kim " EC_GROUP_free(group);\n" 381*e71b7053SJung-uk Kim " return NULL;\n" 382*e71b7053SJung-uk Kim " }\n" 383*e71b7053SJung-uk Kim " return (group);\n" 384*e71b7053SJung-uk Kim "}\n"); 3853b4e3dcbSSimon L. B. Nielsen } 3863b4e3dcbSSimon L. B. Nielsen 387dee36b4fSJung-uk Kim if (outformat == FORMAT_ASN1 && genkey) 388dee36b4fSJung-uk Kim noout = 1; 389dee36b4fSJung-uk Kim 3906f9291ceSJung-uk Kim if (!noout) { 3913b4e3dcbSSimon L. B. Nielsen if (outformat == FORMAT_ASN1) 3923b4e3dcbSSimon L. B. Nielsen i = i2d_ECPKParameters_bio(out, group); 393*e71b7053SJung-uk Kim else 3943b4e3dcbSSimon L. B. Nielsen i = PEM_write_bio_ECPKParameters(out, group); 3956f9291ceSJung-uk Kim if (!i) { 3963b4e3dcbSSimon L. B. Nielsen BIO_printf(bio_err, "unable to write elliptic " 3973b4e3dcbSSimon L. B. Nielsen "curve parameters\n"); 3983b4e3dcbSSimon L. B. Nielsen ERR_print_errors(bio_err); 3993b4e3dcbSSimon L. B. Nielsen goto end; 4003b4e3dcbSSimon L. B. Nielsen } 4013b4e3dcbSSimon L. B. Nielsen } 4023b4e3dcbSSimon L. B. Nielsen 4036f9291ceSJung-uk Kim if (genkey) { 4043b4e3dcbSSimon L. B. Nielsen EC_KEY *eckey = EC_KEY_new(); 4053b4e3dcbSSimon L. B. Nielsen 4063b4e3dcbSSimon L. B. Nielsen if (eckey == NULL) 4073b4e3dcbSSimon L. B. Nielsen goto end; 4083b4e3dcbSSimon L. B. Nielsen 409*e71b7053SJung-uk Kim if (EC_KEY_set_group(eckey, group) == 0) { 410*e71b7053SJung-uk Kim BIO_printf(bio_err, "unable to set group when generating key\n"); 411*e71b7053SJung-uk Kim EC_KEY_free(eckey); 412*e71b7053SJung-uk Kim ERR_print_errors(bio_err); 4133b4e3dcbSSimon L. B. Nielsen goto end; 414*e71b7053SJung-uk Kim } 4153b4e3dcbSSimon L. B. Nielsen 416dee36b4fSJung-uk Kim if (new_form) 417dee36b4fSJung-uk Kim EC_KEY_set_conv_form(eckey, form); 418dee36b4fSJung-uk Kim 4196f9291ceSJung-uk Kim if (!EC_KEY_generate_key(eckey)) { 420*e71b7053SJung-uk Kim BIO_printf(bio_err, "unable to generate key\n"); 4213b4e3dcbSSimon L. B. Nielsen EC_KEY_free(eckey); 422*e71b7053SJung-uk Kim ERR_print_errors(bio_err); 4233b4e3dcbSSimon L. B. Nielsen goto end; 4243b4e3dcbSSimon L. B. Nielsen } 425*e71b7053SJung-uk Kim assert(private); 4263b4e3dcbSSimon L. B. Nielsen if (outformat == FORMAT_ASN1) 4273b4e3dcbSSimon L. B. Nielsen i = i2d_ECPrivateKey_bio(out, eckey); 428*e71b7053SJung-uk Kim else 4293b4e3dcbSSimon L. B. Nielsen i = PEM_write_bio_ECPrivateKey(out, eckey, NULL, 4303b4e3dcbSSimon L. B. Nielsen NULL, 0, NULL, NULL); 4313b4e3dcbSSimon L. B. Nielsen EC_KEY_free(eckey); 4323b4e3dcbSSimon L. B. Nielsen } 4333b4e3dcbSSimon L. B. Nielsen 4343b4e3dcbSSimon L. B. Nielsen ret = 0; 4353b4e3dcbSSimon L. B. Nielsen end: 4363b4e3dcbSSimon L. B. Nielsen BN_free(ec_p); 4373b4e3dcbSSimon L. B. Nielsen BN_free(ec_a); 4383b4e3dcbSSimon L. B. Nielsen BN_free(ec_b); 4393b4e3dcbSSimon L. B. Nielsen BN_free(ec_gen); 4403b4e3dcbSSimon L. B. Nielsen BN_free(ec_order); 4413b4e3dcbSSimon L. B. Nielsen BN_free(ec_cofactor); 4423b4e3dcbSSimon L. B. Nielsen OPENSSL_free(buffer); 4436cf8931aSJung-uk Kim EC_GROUP_free(group); 4446cf8931aSJung-uk Kim release_engine(e); 4453b4e3dcbSSimon L. B. Nielsen BIO_free(in); 4463b4e3dcbSSimon L. B. Nielsen BIO_free_all(out); 447*e71b7053SJung-uk Kim return ret; 4483b4e3dcbSSimon L. B. Nielsen } 4493b4e3dcbSSimon L. B. Nielsen 4503b4e3dcbSSimon L. B. Nielsen #endif 451