version 1.2, 2014/08/28 14:23:52 |
version 1.3, 2014/09/01 14:26:01 |
|
|
#include <openssl/pem.h> |
#include <openssl/pem.h> |
#include <openssl/x509.h> |
#include <openssl/x509.h> |
|
|
/* -inform arg - input format - default PEM (DER or PEM) |
static int ecparam_print_var(BIO *, BIGNUM *, const char *, int, |
* -outform arg - output format - default PEM |
unsigned char *); |
* -in arg - input file - default stdin |
|
* -out arg - output file - default stdout |
|
* -noout - do not print the ec parameter |
|
* -text - print the ec parameters in text form |
|
* -check - validate the ec parameters |
|
* -C - print a 'C' function creating the parameters |
|
* -name arg - use the ec parameters with 'short name' name |
|
* -list_curves - prints a list of all currently available curve 'short names' |
|
* -conv_form arg - specifies the point conversion form |
|
* - possible values: compressed |
|
* uncompressed (default) |
|
* hybrid |
|
* -param_enc arg - specifies the way the ec parameters are encoded |
|
* in the asn1 der encoding |
|
* possible values: named_curve (default) |
|
* explicit |
|
* -no_seed - if 'explicit' parameters are chosen do not use the seed |
|
* -genkey - generate ec key |
|
* -engine e - use engine e, possibly a hardware device |
|
*/ |
|
|
|
|
static struct { |
|
int C; |
|
int asn1_flag; |
|
int check; |
|
char *curve_name; |
|
char *engine; |
|
point_conversion_form_t form; |
|
int genkey; |
|
char *infile; |
|
int informat; |
|
int list_curves; |
|
int new_asn1_flag; |
|
int new_form; |
|
int no_seed; |
|
int noout; |
|
char *outfile; |
|
int outformat; |
|
int text; |
|
} ecparam_config; |
|
|
static int ecparam_print_var(BIO *, BIGNUM *, const char *, int, unsigned char *); |
static int |
|
ecparam_opt_form(struct option *opt, char *arg) |
|
{ |
|
if (strcmp(arg, "compressed") == 0) |
|
ecparam_config.form = POINT_CONVERSION_COMPRESSED; |
|
else if (strcmp(arg, "uncompressed") == 0) |
|
ecparam_config.form = POINT_CONVERSION_UNCOMPRESSED; |
|
else if (strcmp(arg, "hybrid") == 0) |
|
ecparam_config.form = POINT_CONVERSION_HYBRID; |
|
else |
|
return (1); |
|
|
|
ecparam_config.new_form = 1; |
|
return (0); |
|
} |
|
|
|
static int |
|
ecparam_opt_enctype(struct option *opt, char *arg) |
|
{ |
|
if (strcmp(arg, "explicit") == 0) |
|
ecparam_config.asn1_flag = 0; |
|
else if (strcmp(arg, "named_curve") == 0) |
|
ecparam_config.asn1_flag = OPENSSL_EC_NAMED_CURVE; |
|
else |
|
return (1); |
|
|
|
ecparam_config.new_asn1_flag = 1; |
|
return (0); |
|
} |
|
|
|
struct option ecparam_options[] = { |
|
{ |
|
.name = "C", |
|
.desc = "Convert the EC parameters into C code", |
|
.type = OPTION_FLAG, |
|
.opt.flag = &ecparam_config.C, |
|
}, |
|
{ |
|
.name = "check", |
|
.desc = "Validate the elliptic curve parameters", |
|
.type = OPTION_FLAG, |
|
.opt.flag = &ecparam_config.check, |
|
}, |
|
{ |
|
.name = "conv_form", |
|
.argname = "form", |
|
.desc = "Specify point conversion form:\n" |
|
" compressed, uncompressed (default), hybrid", |
|
.type = OPTION_ARG_FUNC, |
|
.func = ecparam_opt_form, |
|
}, |
|
#ifndef OPENSSL_NO_ENGINE |
|
{ |
|
.name = "engine", |
|
.argname = "id", |
|
.desc = "Use the engine specified by the given identifier", |
|
.type = OPTION_ARG, |
|
.opt.arg = &ecparam_config.engine, |
|
}, |
|
#endif |
|
{ |
|
.name = "genkey", |
|
.desc = "Generate an EC private key using the specified " |
|
"parameters", |
|
.type = OPTION_FLAG, |
|
.opt.flag = &ecparam_config.genkey, |
|
}, |
|
{ |
|
.name = "in", |
|
.argname = "file", |
|
.desc = "Input file to read parameters from (default stdin)", |
|
.type = OPTION_ARG, |
|
.opt.arg = &ecparam_config.infile, |
|
}, |
|
{ |
|
.name = "inform", |
|
.argname = "format", |
|
.desc = "Input format (DER or PEM)", |
|
.type = OPTION_ARG_FORMAT, |
|
.opt.value = &ecparam_config.informat, |
|
}, |
|
{ |
|
.name = "list_curves", |
|
.desc = "Print list of all currently implemented EC " |
|
"parameter names", |
|
.type = OPTION_FLAG, |
|
.opt.flag = &ecparam_config.list_curves, |
|
}, |
|
{ |
|
.name = "name", |
|
.argname = "curve", |
|
.desc = "Use the EC parameters with the specified name", |
|
.type = OPTION_ARG, |
|
.opt.arg = &ecparam_config.curve_name, |
|
}, |
|
{ |
|
.name = "no_seed", |
|
.desc = "Do not output seed with explicit parameter encoding", |
|
.type = OPTION_FLAG, |
|
.opt.flag = &ecparam_config.no_seed, |
|
}, |
|
{ |
|
.name = "noout", |
|
.desc = "Do not output encoded version of EC parameters", |
|
.type = OPTION_FLAG, |
|
.opt.flag = &ecparam_config.noout, |
|
}, |
|
{ |
|
.name = "out", |
|
.argname = "file", |
|
.desc = "Output file to write parameters to (default stdout)", |
|
.type = OPTION_ARG, |
|
.opt.arg = &ecparam_config.outfile, |
|
}, |
|
{ |
|
.name = "outform", |
|
.argname = "format", |
|
.desc = "Output format (DER or PEM)", |
|
.type = OPTION_ARG_FORMAT, |
|
.opt.value = &ecparam_config.outformat, |
|
}, |
|
{ |
|
.name = "param_enc", |
|
.argname = "type", |
|
.desc = "Specify EC parameter ASN.1 encoding type:\n" |
|
" explicit, named_curve (default)", |
|
.type = OPTION_ARG_FUNC, |
|
.func = ecparam_opt_enctype, |
|
}, |
|
{ |
|
.name = "text", |
|
.desc = "Print out the EC parameters in human readable form", |
|
.type = OPTION_FLAG, |
|
.opt.flag = &ecparam_config.text, |
|
}, |
|
{}, |
|
}; |
|
|
|
static void |
|
ecparam_usage(void) |
|
{ |
|
fprintf(stderr, "usage: ecparam [-C] [-check] [-conv_form arg] " |
|
"[-engine id] [-genkey]\n" |
|
" [-in file] [-inform DER | PEM] [-list_curves] [-name arg]\n" |
|
" [-no_seed] [-noout] [-out file] [-outform DER | PEM]\n" |
|
" [-param_enc arg] [-text]\n\n"); |
|
options_usage(ecparam_options); |
|
} |
|
|
int ecparam_main(int, char **); |
int ecparam_main(int, char **); |
|
|
int |
int |
ecparam_main(int argc, char **argv) |
ecparam_main(int argc, char **argv) |
{ |
{ |
|
BIGNUM *ec_p = NULL, *ec_a = NULL, *ec_b = NULL, *ec_gen = NULL; |
|
BIGNUM *ec_order = NULL, *ec_cofactor = NULL; |
EC_GROUP *group = NULL; |
EC_GROUP *group = NULL; |
point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED; |
unsigned char *buffer = NULL; |
int new_form = 0; |
|
int asn1_flag = OPENSSL_EC_NAMED_CURVE; |
|
int new_asn1_flag = 0; |
|
char *curve_name = NULL; |
|
int list_curves = 0, no_seed = 0, check = 0, badops = 0, text = 0, |
|
i, genkey = 0; |
|
char *infile = NULL, *outfile = NULL, *prog; |
|
BIO *in = NULL, *out = NULL; |
BIO *in = NULL, *out = NULL; |
int informat, outformat, noout = 0, C = 0, ret = 1; |
int i, ret = 1; |
char *engine = NULL; |
|
|
|
BIGNUM *ec_p = NULL, *ec_a = NULL, *ec_b = NULL, *ec_gen = NULL, |
memset(&ecparam_config, 0, sizeof(ecparam_config)); |
*ec_order = NULL, *ec_cofactor = NULL; |
ecparam_config.asn1_flag = OPENSSL_EC_NAMED_CURVE; |
unsigned char *buffer = NULL; |
ecparam_config.form = POINT_CONVERSION_UNCOMPRESSED; |
|
ecparam_config.informat = FORMAT_PEM; |
|
ecparam_config.outformat = FORMAT_PEM; |
|
|
informat = FORMAT_PEM; |
if (options_parse(argc, argv, ecparam_options, NULL) != 0) { |
outformat = FORMAT_PEM; |
ecparam_usage(); |
|
|
prog = argv[0]; |
|
argc--; |
|
argv++; |
|
while (argc >= 1) { |
|
if (strcmp(*argv, "-inform") == 0) { |
|
if (--argc < 1) |
|
goto bad; |
|
informat = str2fmt(*(++argv)); |
|
} else if (strcmp(*argv, "-outform") == 0) { |
|
if (--argc < 1) |
|
goto bad; |
|
outformat = str2fmt(*(++argv)); |
|
} else if (strcmp(*argv, "-in") == 0) { |
|
if (--argc < 1) |
|
goto bad; |
|
infile = *(++argv); |
|
} else if (strcmp(*argv, "-out") == 0) { |
|
if (--argc < 1) |
|
goto bad; |
|
outfile = *(++argv); |
|
} else if (strcmp(*argv, "-text") == 0) |
|
text = 1; |
|
else if (strcmp(*argv, "-C") == 0) |
|
C = 1; |
|
else if (strcmp(*argv, "-check") == 0) |
|
check = 1; |
|
else if (strcmp(*argv, "-name") == 0) { |
|
if (--argc < 1) |
|
goto bad; |
|
curve_name = *(++argv); |
|
} else if (strcmp(*argv, "-list_curves") == 0) |
|
list_curves = 1; |
|
else if (strcmp(*argv, "-conv_form") == 0) { |
|
if (--argc < 1) |
|
goto bad; |
|
++argv; |
|
new_form = 1; |
|
if (strcmp(*argv, "compressed") == 0) |
|
form = POINT_CONVERSION_COMPRESSED; |
|
else if (strcmp(*argv, "uncompressed") == 0) |
|
form = POINT_CONVERSION_UNCOMPRESSED; |
|
else if (strcmp(*argv, "hybrid") == 0) |
|
form = POINT_CONVERSION_HYBRID; |
|
else |
|
goto bad; |
|
} else if (strcmp(*argv, "-param_enc") == 0) { |
|
if (--argc < 1) |
|
goto bad; |
|
++argv; |
|
new_asn1_flag = 1; |
|
if (strcmp(*argv, "named_curve") == 0) |
|
asn1_flag = OPENSSL_EC_NAMED_CURVE; |
|
else if (strcmp(*argv, "explicit") == 0) |
|
asn1_flag = 0; |
|
else |
|
goto bad; |
|
} else if (strcmp(*argv, "-no_seed") == 0) |
|
no_seed = 1; |
|
else if (strcmp(*argv, "-noout") == 0) |
|
noout = 1; |
|
else if (strcmp(*argv, "-genkey") == 0) { |
|
genkey = 1; |
|
} else if (strcmp(*argv, "-engine") == 0) { |
|
if (--argc < 1) |
|
goto bad; |
|
engine = *(++argv); |
|
} else { |
|
BIO_printf(bio_err, "unknown option %s\n", *argv); |
|
badops = 1; |
|
break; |
|
} |
|
argc--; |
|
argv++; |
|
} |
|
|
|
if (badops) { |
|
bad: |
|
BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog); |
|
BIO_printf(bio_err, "where options are\n"); |
|
BIO_printf(bio_err, " -inform arg input format - " |
|
"default PEM (DER or PEM)\n"); |
|
BIO_printf(bio_err, " -outform arg output format - " |
|
"default PEM\n"); |
|
BIO_printf(bio_err, " -in arg input file - " |
|
"default stdin\n"); |
|
BIO_printf(bio_err, " -out arg output file - " |
|
"default stdout\n"); |
|
BIO_printf(bio_err, " -noout do not print the " |
|
"ec parameter\n"); |
|
BIO_printf(bio_err, " -text print the ec " |
|
"parameters in text form\n"); |
|
BIO_printf(bio_err, " -check validate the ec " |
|
"parameters\n"); |
|
BIO_printf(bio_err, " -C print a 'C' " |
|
"function creating the parameters\n"); |
|
BIO_printf(bio_err, " -name arg use the " |
|
"ec parameters with 'short name' name\n"); |
|
BIO_printf(bio_err, " -list_curves prints a list of " |
|
"all currently available curve 'short names'\n"); |
|
BIO_printf(bio_err, " -conv_form arg specifies the " |
|
"point conversion form \n"); |
|
BIO_printf(bio_err, " possible values:" |
|
" compressed\n"); |
|
BIO_printf(bio_err, " " |
|
" uncompressed (default)\n"); |
|
BIO_printf(bio_err, " " |
|
" hybrid\n"); |
|
BIO_printf(bio_err, " -param_enc arg specifies the way" |
|
" the ec parameters are encoded\n"); |
|
BIO_printf(bio_err, " in the asn1 der " |
|
"encoding\n"); |
|
BIO_printf(bio_err, " possible values:" |
|
" named_curve (default)\n"); |
|
BIO_printf(bio_err, " " |
|
" explicit\n"); |
|
BIO_printf(bio_err, " -no_seed if 'explicit'" |
|
" parameters are chosen do not" |
|
" use the seed\n"); |
|
BIO_printf(bio_err, " -genkey generate ec" |
|
" key\n"); |
|
BIO_printf(bio_err, " -engine e use engine e, " |
|
"possibly a hardware device\n"); |
|
goto end; |
goto end; |
} |
} |
|
|
|
|
ERR_print_errors(bio_err); |
ERR_print_errors(bio_err); |
goto end; |
goto end; |
} |
} |
if (infile == NULL) |
if (ecparam_config.infile == NULL) |
BIO_set_fp(in, stdin, BIO_NOCLOSE); |
BIO_set_fp(in, stdin, BIO_NOCLOSE); |
else { |
else { |
if (BIO_read_filename(in, infile) <= 0) { |
if (BIO_read_filename(in, ecparam_config.infile) <= 0) { |
perror(infile); |
perror(ecparam_config.infile); |
goto end; |
goto end; |
} |
} |
} |
} |
if (outfile == NULL) { |
if (ecparam_config.outfile == NULL) { |
BIO_set_fp(out, stdout, BIO_NOCLOSE); |
BIO_set_fp(out, stdout, BIO_NOCLOSE); |
} else { |
} else { |
if (BIO_write_filename(out, outfile) <= 0) { |
if (BIO_write_filename(out, ecparam_config.outfile) <= 0) { |
perror(outfile); |
perror(ecparam_config.outfile); |
goto end; |
goto end; |
} |
} |
} |
} |
|
|
#ifndef OPENSSL_NO_ENGINE |
#ifndef OPENSSL_NO_ENGINE |
setup_engine(bio_err, engine, 0); |
setup_engine(bio_err, ecparam_config.engine, 0); |
#endif |
#endif |
|
|
if (list_curves) { |
if (ecparam_config.list_curves) { |
EC_builtin_curve *curves = NULL; |
EC_builtin_curve *curves = NULL; |
size_t crv_len = 0; |
size_t crv_len = 0; |
size_t n = 0; |
size_t n = 0; |
|
|
crv_len = EC_get_builtin_curves(NULL, 0); |
crv_len = EC_get_builtin_curves(NULL, 0); |
|
|
curves = reallocarray(NULL, crv_len, sizeof(EC_builtin_curve)); |
curves = reallocarray(NULL, crv_len, sizeof(EC_builtin_curve)); |
|
|
if (curves == NULL) |
if (curves == NULL) |
goto end; |
goto end; |
|
|
|
|
ret = 0; |
ret = 0; |
goto end; |
goto end; |
} |
} |
if (curve_name != NULL) { |
if (ecparam_config.curve_name != NULL) { |
int nid; |
int nid; |
|
|
/* |
/* |
|
|
* secp256r1 (which are the same as the curves prime192v1 and |
* secp256r1 (which are the same as the curves prime192v1 and |
* prime256v1 defined in X9.62) |
* prime256v1 defined in X9.62) |
*/ |
*/ |
if (!strcmp(curve_name, "secp192r1")) { |
if (!strcmp(ecparam_config.curve_name, "secp192r1")) { |
BIO_printf(bio_err, "using curve name prime192v1 " |
BIO_printf(bio_err, "using curve name prime192v1 " |
"instead of secp192r1\n"); |
"instead of secp192r1\n"); |
nid = NID_X9_62_prime192v1; |
nid = NID_X9_62_prime192v1; |
} else if (!strcmp(curve_name, "secp256r1")) { |
} else if (!strcmp(ecparam_config.curve_name, "secp256r1")) { |
BIO_printf(bio_err, "using curve name prime256v1 " |
BIO_printf(bio_err, "using curve name prime256v1 " |
"instead of secp256r1\n"); |
"instead of secp256r1\n"); |
nid = NID_X9_62_prime256v1; |
nid = NID_X9_62_prime256v1; |
} else |
} else |
nid = OBJ_sn2nid(curve_name); |
nid = OBJ_sn2nid(ecparam_config.curve_name); |
|
|
if (nid == 0) { |
if (nid == 0) { |
BIO_printf(bio_err, "unknown curve name (%s)\n", |
BIO_printf(bio_err, "unknown curve name (%s)\n", |
curve_name); |
ecparam_config.curve_name); |
goto end; |
goto end; |
} |
} |
group = EC_GROUP_new_by_curve_name(nid); |
group = EC_GROUP_new_by_curve_name(nid); |
if (group == NULL) { |
if (group == NULL) { |
BIO_printf(bio_err, "unable to create curve (%s)\n", |
BIO_printf(bio_err, "unable to create curve (%s)\n", |
curve_name); |
ecparam_config.curve_name); |
goto end; |
goto end; |
} |
} |
EC_GROUP_set_asn1_flag(group, asn1_flag); |
EC_GROUP_set_asn1_flag(group, ecparam_config.asn1_flag); |
EC_GROUP_set_point_conversion_form(group, form); |
EC_GROUP_set_point_conversion_form(group, ecparam_config.form); |
} else if (informat == FORMAT_ASN1) { |
} else if (ecparam_config.informat == FORMAT_ASN1) { |
group = d2i_ECPKParameters_bio(in, NULL); |
group = d2i_ECPKParameters_bio(in, NULL); |
} else if (informat == FORMAT_PEM) { |
} else if (ecparam_config.informat == FORMAT_PEM) { |
group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL); |
group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL); |
} else { |
} else { |
BIO_printf(bio_err, "bad input format specified\n"); |
BIO_printf(bio_err, "bad input format specified\n"); |
|
|
ERR_print_errors(bio_err); |
ERR_print_errors(bio_err); |
goto end; |
goto end; |
} |
} |
if (new_form) |
if (ecparam_config.new_form) |
EC_GROUP_set_point_conversion_form(group, form); |
EC_GROUP_set_point_conversion_form(group, ecparam_config.form); |
|
|
if (new_asn1_flag) |
if (ecparam_config.new_asn1_flag) |
EC_GROUP_set_asn1_flag(group, asn1_flag); |
EC_GROUP_set_asn1_flag(group, ecparam_config.asn1_flag); |
|
|
if (no_seed) { |
if (ecparam_config.no_seed) |
EC_GROUP_set_seed(group, NULL, 0); |
EC_GROUP_set_seed(group, NULL, 0); |
} |
|
if (text) { |
if (ecparam_config.text) { |
if (!ECPKParameters_print(out, group, 0)) |
if (!ECPKParameters_print(out, group, 0)) |
goto end; |
goto end; |
} |
} |
if (check) { |
if (ecparam_config.check) { |
if (group == NULL) |
if (group == NULL) |
BIO_printf(bio_err, "no elliptic curve parameters\n"); |
BIO_printf(bio_err, "no elliptic curve parameters\n"); |
BIO_printf(bio_err, "checking elliptic curve parameters: "); |
BIO_printf(bio_err, "checking elliptic curve parameters: "); |
|
|
BIO_printf(bio_err, "ok\n"); |
BIO_printf(bio_err, "ok\n"); |
|
|
} |
} |
if (C) { |
if (ecparam_config.C) { |
size_t buf_len = 0, tmp_len = 0; |
size_t buf_len = 0, tmp_len = 0; |
const EC_POINT *point; |
const EC_POINT *point; |
int is_prime, len = 0; |
int is_prime, len = 0; |
|
|
|
|
if (is_prime) { |
if (is_prime) { |
if (!EC_GROUP_get_curve_GFp(group, ec_p, ec_a, |
if (!EC_GROUP_get_curve_GFp(group, ec_p, ec_a, |
ec_b, NULL)) |
ec_b, NULL)) |
goto end; |
goto end; |
} else { |
} else { |
/* TODO */ |
/* TODO */ |
|
|
BIO_printf(out, "\t\t}\n"); |
BIO_printf(out, "\t\t}\n"); |
BIO_printf(out, "\treturn(group);\n\t}\n"); |
BIO_printf(out, "\treturn(group);\n\t}\n"); |
} |
} |
if (!noout) { |
if (!ecparam_config.noout) { |
if (outformat == FORMAT_ASN1) |
if (ecparam_config.outformat == FORMAT_ASN1) |
i = i2d_ECPKParameters_bio(out, group); |
i = i2d_ECPKParameters_bio(out, group); |
else if (outformat == FORMAT_PEM) |
else if (ecparam_config.outformat == FORMAT_PEM) |
i = PEM_write_bio_ECPKParameters(out, group); |
i = PEM_write_bio_ECPKParameters(out, group); |
else { |
else { |
BIO_printf(bio_err, "bad output format specified for" |
BIO_printf(bio_err, "bad output format specified for" |
|
|
goto end; |
goto end; |
} |
} |
} |
} |
if (genkey) { |
if (ecparam_config.genkey) { |
EC_KEY *eckey = EC_KEY_new(); |
EC_KEY *eckey = EC_KEY_new(); |
|
|
if (eckey == NULL) |
if (eckey == NULL) |
|
|
EC_KEY_free(eckey); |
EC_KEY_free(eckey); |
goto end; |
goto end; |
} |
} |
if (outformat == FORMAT_ASN1) |
if (ecparam_config.outformat == FORMAT_ASN1) |
i = i2d_ECPrivateKey_bio(out, eckey); |
i = i2d_ECPrivateKey_bio(out, eckey); |
else if (outformat == FORMAT_PEM) |
else if (ecparam_config.outformat == FORMAT_PEM) |
i = PEM_write_bio_ECPrivateKey(out, eckey, NULL, |
i = PEM_write_bio_ECPrivateKey(out, eckey, NULL, |
NULL, 0, NULL, NULL); |
NULL, 0, NULL, NULL); |
else { |
else { |