2 * Written by Nils Larsch for the OpenSSL project.
4 /* ====================================================================
5 * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
19 * 3. All advertising materials mentioning features or use of this
20 * software must display the following acknowledgment:
21 * "This product includes software developed by the OpenSSL Project
22 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25 * endorse or promote products derived from this software without
26 * prior written permission. For written permission, please contact
27 * openssl-core@openssl.org.
29 * 5. Products derived from this software may not be called "OpenSSL"
30 * nor may "OpenSSL" appear in their names without prior written
31 * permission of the OpenSSL Project.
33 * 6. Redistributions of any form whatsoever must retain the following
35 * "This product includes software developed by the OpenSSL Project
36 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49 * OF THE POSSIBILITY OF SUCH DAMAGE.
50 * ====================================================================
52 * This product includes cryptographic software written by Eric Young
53 * (eay@cryptsoft.com). This product includes software written by Tim
54 * Hudson (tjh@cryptsoft.com).
57 /* ====================================================================
58 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60 * Portions of the attached software ("Contribution") are developed by
61 * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
63 * The Contribution is licensed pursuant to the OpenSSL open source
64 * license provided above.
66 * The elliptic curve binary polynomial software is originally written by
67 * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
71 #include <openssl/opensslconf.h>
78 # include <openssl/bio.h>
79 # include <openssl/err.h>
80 # include <openssl/bn.h>
81 # include <openssl/ec.h>
82 # include <openssl/x509.h>
83 # include <openssl/pem.h>
85 typedef enum OPTION_choice
{
86 OPT_ERR
= -1, OPT_EOF
= 0, OPT_HELP
,
87 OPT_INFORM
, OPT_OUTFORM
, OPT_IN
, OPT_OUT
, OPT_TEXT
, OPT_C
,
88 OPT_CHECK
, OPT_LIST_CURVES
, OPT_NO_SEED
, OPT_NOOUT
, OPT_NAME
,
89 OPT_CONV_FORM
, OPT_PARAM_ENC
, OPT_GENKEY
, OPT_RAND
, OPT_ENGINE
92 OPTIONS ecparam_options
[] = {
93 {"help", OPT_HELP
, '-', "Display this summary"},
94 {"inform", OPT_INFORM
, 'F', "Input format - default PEM (DER or PEM)"},
95 {"outform", OPT_OUTFORM
, 'F', "Output format - default PEM"},
96 {"in", OPT_IN
, '<', "Input file - default stdin"},
97 {"out", OPT_OUT
, '>', "Output file - default stdout"},
98 {"text", OPT_TEXT
, '-', "Print the ec parameters in text form"},
99 {"C", OPT_C
, '-', "Print a 'C' function creating the parameters"},
100 {"check", OPT_CHECK
, '-', "Validate the ec parameters"},
101 {"list_curves", OPT_LIST_CURVES
, '-',
102 "Prints a list of all curve 'short names'"},
103 {"no_seed", OPT_NO_SEED
, '-',
104 "If 'explicit' parameters are chosen do not use the seed"},
105 {"noout", OPT_NOOUT
, '-', "Do not print the ec parameter"},
106 {"name", OPT_NAME
, 's',
107 "Use the ec parameters with specified 'short name'"},
108 {"conv_form", OPT_CONV_FORM
, 's', "Specifies the point conversion form "},
109 {"param_enc", OPT_PARAM_ENC
, 's',
110 "Specifies the way the ec parameters are encoded"},
111 {"genkey", OPT_GENKEY
, '-', "Generate ec key"},
112 {"rand", OPT_RAND
, 's', "Files to use for random number input"},
113 # ifndef OPENSSL_NO_ENGINE
114 {"engine", OPT_ENGINE
, 's', "Use engine, possibly a hardware device"},
119 static OPT_PAIR forms
[] = {
120 {"compressed", POINT_CONVERSION_COMPRESSED
},
121 {"uncompressed", POINT_CONVERSION_UNCOMPRESSED
},
122 {"hybrid", POINT_CONVERSION_HYBRID
},
126 static OPT_PAIR encodings
[] = {
127 {"named_curve", OPENSSL_EC_NAMED_CURVE
},
132 int ecparam_main(int argc
, char **argv
)
134 BIGNUM
*ec_gen
= NULL
, *ec_order
= NULL
, *ec_cofactor
= NULL
;
135 BIGNUM
*ec_p
= NULL
, *ec_a
= NULL
, *ec_b
= NULL
;
136 BIO
*in
= NULL
, *out
= NULL
;
137 EC_GROUP
*group
= NULL
;
138 point_conversion_form_t form
= POINT_CONVERSION_UNCOMPRESSED
;
139 char *curve_name
= NULL
, *inrand
= NULL
;
140 char *infile
= NULL
, *outfile
= NULL
, *prog
;
141 unsigned char *buffer
= NULL
;
143 int asn1_flag
= OPENSSL_EC_NAMED_CURVE
, new_asn1_flag
= 0;
144 int informat
= FORMAT_PEM
, outformat
= FORMAT_PEM
, noout
= 0, C
= 0;
145 int ret
= 1, private = 0;
146 int list_curves
= 0, no_seed
= 0, check
= 0, new_form
= 0;
147 int text
= 0, i
, need_rand
= 0, genkey
= 0;
149 prog
= opt_init(argc
, argv
, ecparam_options
);
150 while ((o
= opt_next()) != OPT_EOF
) {
155 BIO_printf(bio_err
, "%s: Use -help for summary.\n", prog
);
158 opt_help(ecparam_options
);
162 if (!opt_format(opt_arg(), OPT_FMT_PEMDER
, &informat
))
169 if (!opt_format(opt_arg(), OPT_FMT_PEMDER
, &outformat
))
184 case OPT_LIST_CURVES
:
194 curve_name
= opt_arg();
197 if (!opt_pair(opt_arg(), forms
, &new_form
))
203 if (!opt_pair(opt_arg(), encodings
, &asn1_flag
))
208 genkey
= need_rand
= 1;
215 (void)setup_engine(opt_arg(), 0);
219 argc
= opt_num_rest();
221 private = genkey
? 1 : 0;
223 if (!app_load_modules(NULL
))
226 in
= bio_open_default(infile
, 'r', informat
);
229 out
= bio_open_owner(outfile
, outformat
, private);
234 EC_builtin_curve
*curves
= NULL
;
235 size_t crv_len
= EC_get_builtin_curves(NULL
, 0);
238 curves
= app_malloc((int)sizeof(*curves
) * crv_len
, "list curves");
239 if (!EC_get_builtin_curves(curves
, crv_len
)) {
240 OPENSSL_free(curves
);
244 for (n
= 0; n
< crv_len
; n
++) {
247 comment
= curves
[n
].comment
;
248 sname
= OBJ_nid2sn(curves
[n
].nid
);
250 comment
= "CURVE DESCRIPTION NOT AVAILABLE";
254 BIO_printf(out
, " %-10s: ", sname
);
255 BIO_printf(out
, "%s\n", comment
);
258 OPENSSL_free(curves
);
263 if (curve_name
!= NULL
) {
267 * workaround for the SECG curve names secp192r1 and secp256r1 (which
268 * are the same as the curves prime192v1 and prime256v1 defined in
271 if (strcmp(curve_name
, "secp192r1") == 0) {
272 BIO_printf(bio_err
, "using curve name prime192v1 "
273 "instead of secp192r1\n");
274 nid
= NID_X9_62_prime192v1
;
275 } else if (strcmp(curve_name
, "secp256r1") == 0) {
276 BIO_printf(bio_err
, "using curve name prime256v1 "
277 "instead of secp256r1\n");
278 nid
= NID_X9_62_prime256v1
;
280 nid
= OBJ_sn2nid(curve_name
);
283 nid
= EC_curve_nist2nid(curve_name
);
286 BIO_printf(bio_err
, "unknown curve name (%s)\n", curve_name
);
290 group
= EC_GROUP_new_by_curve_name(nid
);
292 BIO_printf(bio_err
, "unable to create curve (%s)\n", curve_name
);
295 EC_GROUP_set_asn1_flag(group
, asn1_flag
);
296 EC_GROUP_set_point_conversion_form(group
, form
);
297 } else if (informat
== FORMAT_ASN1
)
298 group
= d2i_ECPKParameters_bio(in
, NULL
);
300 group
= PEM_read_bio_ECPKParameters(in
, NULL
, NULL
, NULL
);
302 BIO_printf(bio_err
, "unable to load elliptic curve parameters\n");
303 ERR_print_errors(bio_err
);
308 EC_GROUP_set_point_conversion_form(group
, form
);
311 EC_GROUP_set_asn1_flag(group
, asn1_flag
);
314 EC_GROUP_set_seed(group
, NULL
, 0);
318 if (!ECPKParameters_print(out
, group
, 0))
324 BIO_printf(bio_err
, "no elliptic curve parameters\n");
325 BIO_printf(bio_err
, "checking elliptic curve parameters: ");
326 if (!EC_GROUP_check(group
, NULL
)) {
327 BIO_printf(bio_err
, "failed\n");
328 ERR_print_errors(bio_err
);
331 BIO_printf(bio_err
, "ok\n");
336 size_t buf_len
= 0, tmp_len
= 0;
337 const EC_POINT
*point
;
338 int is_prime
, len
= 0;
339 const EC_METHOD
*meth
= EC_GROUP_method_of(group
);
341 if ((ec_p
= BN_new()) == NULL
342 || (ec_a
= BN_new()) == NULL
343 || (ec_b
= BN_new()) == NULL
344 || (ec_gen
= BN_new()) == NULL
345 || (ec_order
= BN_new()) == NULL
346 || (ec_cofactor
= BN_new()) == NULL
) {
347 perror("Can't allocate BN");
351 is_prime
= (EC_METHOD_get_field_type(meth
) == NID_X9_62_prime_field
);
353 BIO_printf(bio_err
, "Can only handle X9.62 prime fields\n");
357 if (!EC_GROUP_get_curve_GFp(group
, ec_p
, ec_a
, ec_b
, NULL
))
360 if ((point
= EC_GROUP_get0_generator(group
)) == NULL
)
362 if (!EC_POINT_point2bn(group
, point
,
363 EC_GROUP_get_point_conversion_form(group
),
366 if (!EC_GROUP_get_order(group
, ec_order
, NULL
))
368 if (!EC_GROUP_get_cofactor(group
, ec_cofactor
, NULL
))
371 if (!ec_p
|| !ec_a
|| !ec_b
|| !ec_gen
|| !ec_order
|| !ec_cofactor
)
374 len
= BN_num_bits(ec_order
);
376 if ((tmp_len
= (size_t)BN_num_bytes(ec_p
)) > buf_len
)
378 if ((tmp_len
= (size_t)BN_num_bytes(ec_a
)) > buf_len
)
380 if ((tmp_len
= (size_t)BN_num_bytes(ec_b
)) > buf_len
)
382 if ((tmp_len
= (size_t)BN_num_bytes(ec_gen
)) > buf_len
)
384 if ((tmp_len
= (size_t)BN_num_bytes(ec_order
)) > buf_len
)
386 if ((tmp_len
= (size_t)BN_num_bytes(ec_cofactor
)) > buf_len
)
389 buffer
= app_malloc(buf_len
, "BN buffer");
391 BIO_printf(out
, "EC_GROUP *get_ec_group_%d(void)\n{\n", len
);
392 print_bignum_var(out
, ec_p
, "ec_p", len
, buffer
);
393 print_bignum_var(out
, ec_a
, "ec_a", len
, buffer
);
394 print_bignum_var(out
, ec_b
, "ec_b", len
, buffer
);
395 print_bignum_var(out
, ec_gen
, "ec_gen", len
, buffer
);
396 print_bignum_var(out
, ec_order
, "ec_order", len
, buffer
);
397 print_bignum_var(out
, ec_cofactor
, "ec_cofactor", len
, buffer
);
398 BIO_printf(out
, " int ok = 0;\n"
399 " EC_GROUP *group = NULL;\n"
400 " EC_POINT *point = NULL;\n"
401 " BIGNUM *tmp_1 = NULL;\n"
402 " BIGNUM *tmp_2 = NULL;\n"
403 " BIGNUM *tmp_3 = NULL;\n"
406 BIO_printf(out
, " if ((tmp_1 = BN_bin2bn(ec_p_%d, sizeof (ec_p_%d), NULL)) == NULL)\n"
407 " goto err;\n", len
, len
);
408 BIO_printf(out
, " if ((tmp_2 = BN_bin2bn(ec_a_%d, sizeof (ec_a_%d), NULL)) == NULL)\n"
409 " goto err;\n", len
, len
);
410 BIO_printf(out
, " if ((tmp_3 = BN_bin2bn(ec_b_%d, sizeof (ec_b_%d), NULL)) == NULL)\n"
411 " goto err;\n", len
, len
);
412 BIO_printf(out
, " if ((group = EC_GROUP_new_curve_GFp(tmp_1, tmp_2, tmp_3, NULL)) == NULL)\n"
415 BIO_printf(out
, " /* build generator */\n");
416 BIO_printf(out
, " if ((tmp_1 = BN_bin2bn(ec_gen_%d, sizeof (ec_gen_%d), tmp_1)) == NULL)\n"
417 " goto err;\n", len
, len
);
418 BIO_printf(out
, " point = EC_POINT_bn2point(group, tmp_1, NULL, NULL);\n");
419 BIO_printf(out
, " if (point == NULL)\n"
421 BIO_printf(out
, " if ((tmp_2 = BN_bin2bn(ec_order_%d, sizeof (ec_order_%d), tmp_2)) == NULL)\n"
422 " goto err;\n", len
, len
);
423 BIO_printf(out
, " if ((tmp_3 = BN_bin2bn(ec_cofactor_%d, sizeof (ec_cofactor_%d), tmp_3)) == NULL)\n"
424 " goto err;\n", len
, len
);
425 BIO_printf(out
, " if (!EC_GROUP_set_generator(group, point, tmp_2, tmp_3))\n"
429 BIO_printf(out
, "err:\n"
433 " EC_POINT_free(point);\n"
435 " EC_GROUP_free(group);\n"
443 if (outformat
== FORMAT_ASN1
)
444 i
= i2d_ECPKParameters_bio(out
, group
);
446 i
= PEM_write_bio_ECPKParameters(out
, group
);
448 BIO_printf(bio_err
, "unable to write elliptic "
449 "curve parameters\n");
450 ERR_print_errors(bio_err
);
456 app_RAND_load_file(NULL
, (inrand
!= NULL
));
458 BIO_printf(bio_err
, "%ld semi-random bytes loaded\n",
459 app_RAND_load_files(inrand
));
463 EC_KEY
*eckey
= EC_KEY_new();
470 if (EC_KEY_set_group(eckey
, group
) == 0)
473 if (!EC_KEY_generate_key(eckey
)) {
478 if (outformat
== FORMAT_ASN1
)
479 i
= i2d_ECPrivateKey_bio(out
, eckey
);
481 i
= PEM_write_bio_ECPrivateKey(out
, eckey
, NULL
,
482 NULL
, 0, NULL
, NULL
);
487 app_RAND_write_file(NULL
);
496 BN_free(ec_cofactor
);
497 OPENSSL_free(buffer
);
500 EC_GROUP_free(group
);
504 #else /* !OPENSSL_NO_EC */
507 static void *dummy
= &dummy
;