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 in
= bio_open_default(infile
, 'r', informat
);
226 out
= bio_open_owner(outfile
, outformat
, private);
231 EC_builtin_curve
*curves
= NULL
;
232 size_t crv_len
= EC_get_builtin_curves(NULL
, 0);
235 curves
= app_malloc((int)sizeof(*curves
) * crv_len
, "list curves");
236 if (!EC_get_builtin_curves(curves
, crv_len
)) {
237 OPENSSL_free(curves
);
241 for (n
= 0; n
< crv_len
; n
++) {
244 comment
= curves
[n
].comment
;
245 sname
= OBJ_nid2sn(curves
[n
].nid
);
247 comment
= "CURVE DESCRIPTION NOT AVAILABLE";
251 BIO_printf(out
, " %-10s: ", sname
);
252 BIO_printf(out
, "%s\n", comment
);
255 OPENSSL_free(curves
);
260 if (curve_name
!= NULL
) {
264 * workaround for the SECG curve names secp192r1 and secp256r1 (which
265 * are the same as the curves prime192v1 and prime256v1 defined in
268 if (strcmp(curve_name
, "secp192r1") == 0) {
269 BIO_printf(bio_err
, "using curve name prime192v1 "
270 "instead of secp192r1\n");
271 nid
= NID_X9_62_prime192v1
;
272 } else if (strcmp(curve_name
, "secp256r1") == 0) {
273 BIO_printf(bio_err
, "using curve name prime256v1 "
274 "instead of secp256r1\n");
275 nid
= NID_X9_62_prime256v1
;
277 nid
= OBJ_sn2nid(curve_name
);
280 nid
= EC_curve_nist2nid(curve_name
);
283 BIO_printf(bio_err
, "unknown curve name (%s)\n", curve_name
);
287 group
= EC_GROUP_new_by_curve_name(nid
);
289 BIO_printf(bio_err
, "unable to create curve (%s)\n", curve_name
);
292 EC_GROUP_set_asn1_flag(group
, asn1_flag
);
293 EC_GROUP_set_point_conversion_form(group
, form
);
294 } else if (informat
== FORMAT_ASN1
)
295 group
= d2i_ECPKParameters_bio(in
, NULL
);
297 group
= PEM_read_bio_ECPKParameters(in
, NULL
, NULL
, NULL
);
299 BIO_printf(bio_err
, "unable to load elliptic curve parameters\n");
300 ERR_print_errors(bio_err
);
305 EC_GROUP_set_point_conversion_form(group
, form
);
308 EC_GROUP_set_asn1_flag(group
, asn1_flag
);
311 EC_GROUP_set_seed(group
, NULL
, 0);
315 if (!ECPKParameters_print(out
, group
, 0))
321 BIO_printf(bio_err
, "no elliptic curve parameters\n");
322 BIO_printf(bio_err
, "checking elliptic curve parameters: ");
323 if (!EC_GROUP_check(group
, NULL
)) {
324 BIO_printf(bio_err
, "failed\n");
325 ERR_print_errors(bio_err
);
328 BIO_printf(bio_err
, "ok\n");
333 size_t buf_len
= 0, tmp_len
= 0;
334 const EC_POINT
*point
;
335 int is_prime
, len
= 0;
336 const EC_METHOD
*meth
= EC_GROUP_method_of(group
);
338 if ((ec_p
= BN_new()) == NULL
339 || (ec_a
= BN_new()) == NULL
340 || (ec_b
= BN_new()) == NULL
341 || (ec_gen
= BN_new()) == NULL
342 || (ec_order
= BN_new()) == NULL
343 || (ec_cofactor
= BN_new()) == NULL
) {
344 perror("Can't allocate BN");
348 is_prime
= (EC_METHOD_get_field_type(meth
) == NID_X9_62_prime_field
);
350 BIO_printf(bio_err
, "Can only handle X9.62 prime fields\n");
354 if (!EC_GROUP_get_curve_GFp(group
, ec_p
, ec_a
, ec_b
, NULL
))
357 if ((point
= EC_GROUP_get0_generator(group
)) == NULL
)
359 if (!EC_POINT_point2bn(group
, point
,
360 EC_GROUP_get_point_conversion_form(group
),
363 if (!EC_GROUP_get_order(group
, ec_order
, NULL
))
365 if (!EC_GROUP_get_cofactor(group
, ec_cofactor
, NULL
))
368 if (!ec_p
|| !ec_a
|| !ec_b
|| !ec_gen
|| !ec_order
|| !ec_cofactor
)
371 len
= BN_num_bits(ec_order
);
373 if ((tmp_len
= (size_t)BN_num_bytes(ec_p
)) > buf_len
)
375 if ((tmp_len
= (size_t)BN_num_bytes(ec_a
)) > buf_len
)
377 if ((tmp_len
= (size_t)BN_num_bytes(ec_b
)) > buf_len
)
379 if ((tmp_len
= (size_t)BN_num_bytes(ec_gen
)) > buf_len
)
381 if ((tmp_len
= (size_t)BN_num_bytes(ec_order
)) > buf_len
)
383 if ((tmp_len
= (size_t)BN_num_bytes(ec_cofactor
)) > buf_len
)
386 buffer
= app_malloc(buf_len
, "BN buffer");
388 BIO_printf(out
, "EC_GROUP *get_ec_group_%d(void)\n{\n", len
);
389 print_bignum_var(out
, ec_p
, "ec_p", len
, buffer
);
390 print_bignum_var(out
, ec_a
, "ec_a", len
, buffer
);
391 print_bignum_var(out
, ec_b
, "ec_b", len
, buffer
);
392 print_bignum_var(out
, ec_gen
, "ec_gen", len
, buffer
);
393 print_bignum_var(out
, ec_order
, "ec_order", len
, buffer
);
394 print_bignum_var(out
, ec_cofactor
, "ec_cofactor", len
, buffer
);
395 BIO_printf(out
, " int ok = 0;\n"
396 " EC_GROUP *group = NULL;\n"
397 " EC_POINT *point = NULL;\n"
398 " BIGNUM *tmp_1 = NULL;\n"
399 " BIGNUM *tmp_2 = NULL;\n"
400 " BIGNUM *tmp_3 = NULL;\n"
403 BIO_printf(out
, " if ((tmp_1 = BN_bin2bn(ec_p_%d, sizeof (ec_p_%d), NULL)) == NULL)\n"
404 " goto err;\n", len
, len
);
405 BIO_printf(out
, " if ((tmp_2 = BN_bin2bn(ec_a_%d, sizeof (ec_a_%d), NULL)) == NULL)\n"
406 " goto err;\n", len
, len
);
407 BIO_printf(out
, " if ((tmp_3 = BN_bin2bn(ec_b_%d, sizeof (ec_b_%d), NULL)) == NULL)\n"
408 " goto err;\n", len
, len
);
409 BIO_printf(out
, " if ((group = EC_GROUP_new_curve_GFp(tmp_1, tmp_2, tmp_3, NULL)) == NULL)\n"
412 BIO_printf(out
, " /* build generator */\n");
413 BIO_printf(out
, " if ((tmp_1 = BN_bin2bn(ec_gen_%d, sizeof (ec_gen_%d), tmp_1)) == NULL)\n"
414 " goto err;\n", len
, len
);
415 BIO_printf(out
, " point = EC_POINT_bn2point(group, tmp_1, NULL, NULL);\n");
416 BIO_printf(out
, " if (point == NULL)\n"
418 BIO_printf(out
, " if ((tmp_2 = BN_bin2bn(ec_order_%d, sizeof (ec_order_%d), tmp_2)) == NULL)\n"
419 " goto err;\n", len
, len
);
420 BIO_printf(out
, " if ((tmp_3 = BN_bin2bn(ec_cofactor_%d, sizeof (ec_cofactor_%d), tmp_3)) == NULL)\n"
421 " goto err;\n", len
, len
);
422 BIO_printf(out
, " if (!EC_GROUP_set_generator(group, point, tmp_2, tmp_3))\n"
426 BIO_printf(out
, "err:\n"
430 " EC_POINT_free(point);\n"
432 " EC_GROUP_free(group);\n"
440 if (outformat
== FORMAT_ASN1
)
441 i
= i2d_ECPKParameters_bio(out
, group
);
443 i
= PEM_write_bio_ECPKParameters(out
, group
);
445 BIO_printf(bio_err
, "unable to write elliptic "
446 "curve parameters\n");
447 ERR_print_errors(bio_err
);
453 app_RAND_load_file(NULL
, (inrand
!= NULL
));
455 BIO_printf(bio_err
, "%ld semi-random bytes loaded\n",
456 app_RAND_load_files(inrand
));
460 EC_KEY
*eckey
= EC_KEY_new();
467 if (EC_KEY_set_group(eckey
, group
) == 0)
470 if (!EC_KEY_generate_key(eckey
)) {
475 if (outformat
== FORMAT_ASN1
)
476 i
= i2d_ECPrivateKey_bio(out
, eckey
);
478 i
= PEM_write_bio_ECPrivateKey(out
, eckey
, NULL
,
479 NULL
, 0, NULL
, NULL
);
484 app_RAND_write_file(NULL
);
493 BN_free(ec_cofactor
);
494 OPENSSL_free(buffer
);
497 EC_GROUP_free(group
);
501 #else /* !OPENSSL_NO_EC */
504 static void *dummy
= &dummy
;