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>
79 # include <openssl/bio.h>
80 # include <openssl/err.h>
81 # include <openssl/bn.h>
82 # include <openssl/ec.h>
83 # include <openssl/x509.h>
84 # include <openssl/pem.h>
86 typedef enum OPTION_choice
{
87 OPT_ERR
= -1, OPT_EOF
= 0, OPT_HELP
,
88 OPT_INFORM
, OPT_OUTFORM
, OPT_IN
, OPT_OUT
, OPT_TEXT
, OPT_C
,
89 OPT_CHECK
, OPT_LIST_CURVES
, OPT_NO_SEED
, OPT_NOOUT
, OPT_NAME
,
90 OPT_CONV_FORM
, OPT_PARAM_ENC
, OPT_GENKEY
, OPT_RAND
, OPT_ENGINE
93 OPTIONS ecparam_options
[] = {
94 {"help", OPT_HELP
, '-', "Display this summary"},
95 {"inform", OPT_INFORM
, 'F', "Input format - default PEM (DER or PEM)"},
96 {"outform", OPT_OUTFORM
, 'F', "Output format - default PEM"},
97 {"in", OPT_IN
, '<', "Input file - default stdin"},
98 {"out", OPT_OUT
, '>', "Output file - default stdout"},
99 {"text", OPT_TEXT
, '-', "Print the ec parameters in text form"},
100 {"C", OPT_C
, '-', "Print a 'C' function creating the parameters"},
101 {"check", OPT_CHECK
, '-', "Validate the ec parameters"},
102 {"list_curves", OPT_LIST_CURVES
, '-',
103 "Prints a list of all curve 'short names'"},
104 {"no_seed", OPT_NO_SEED
, '-',
105 "If 'explicit' parameters are chosen do not use the seed"},
106 {"noout", OPT_NOOUT
, '-', "Do not print the ec parameter"},
107 {"name", OPT_NAME
, 's',
108 "Use the ec parameters with specified 'short name'"},
109 {"conv_form", OPT_CONV_FORM
, 's', "Specifies the point conversion form "},
110 {"param_enc", OPT_PARAM_ENC
, 's',
111 "Specifies the way the ec parameters are encoded"},
112 {"genkey", OPT_GENKEY
, '-', "Generate ec key"},
113 {"rand", OPT_RAND
, 's', "Files to use for random number input"},
114 # ifndef OPENSSL_NO_ENGINE
115 {"engine", OPT_ENGINE
, 's', "Use engine, possibly a hardware device"},
121 {"compressed", POINT_CONVERSION_COMPRESSED
},
122 {"uncompressed", POINT_CONVERSION_UNCOMPRESSED
},
123 {"hybrid", POINT_CONVERSION_HYBRID
},
127 OPT_PAIR encodings
[] = {
128 {"named_curve", OPENSSL_EC_NAMED_CURVE
},
133 int ecparam_main(int argc
, char **argv
)
135 BIGNUM
*ec_gen
= NULL
, *ec_order
= NULL
, *ec_cofactor
= NULL
;
136 BIGNUM
*ec_p
= NULL
, *ec_a
= NULL
, *ec_b
= NULL
;
137 BIO
*in
= NULL
, *out
= NULL
;
138 EC_GROUP
*group
= NULL
;
139 point_conversion_form_t form
= POINT_CONVERSION_UNCOMPRESSED
;
140 char *curve_name
= NULL
, *inrand
= NULL
;
141 char *infile
= NULL
, *outfile
= NULL
, *prog
;
142 unsigned char *buffer
= NULL
;
144 int asn1_flag
= OPENSSL_EC_NAMED_CURVE
, new_asn1_flag
= 0;
145 int informat
= FORMAT_PEM
, outformat
= FORMAT_PEM
, noout
= 0, C
= 0, ret
=
147 int list_curves
= 0, no_seed
= 0, check
= 0, new_form
= 0;
148 int text
= 0, i
, need_rand
= 0, genkey
= 0;
150 prog
= opt_init(argc
, argv
, ecparam_options
);
151 while ((o
= opt_next()) != OPT_EOF
) {
156 BIO_printf(bio_err
, "%s: Use -help for summary.\n", prog
);
159 opt_help(ecparam_options
);
163 if (!opt_format(opt_arg(), OPT_FMT_PEMDER
, &informat
))
170 if (!opt_format(opt_arg(), OPT_FMT_PEMDER
, &outformat
))
185 case OPT_LIST_CURVES
:
195 curve_name
= opt_arg();
198 if (!opt_pair(opt_arg(), forms
, &new_form
))
204 if (!opt_pair(opt_arg(), encodings
, &asn1_flag
))
209 genkey
= need_rand
= 1;
216 (void)setup_engine(opt_arg(), 0);
220 argc
= opt_num_rest();
223 in
= bio_open_default(infile
, RB(informat
));
226 out
= bio_open_default(outfile
, WB(outformat
));
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")) {
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")) {
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
);
327 BIO_printf(bio_err
, "ok\n");
332 size_t buf_len
= 0, tmp_len
= 0;
333 const EC_POINT
*point
;
334 int is_prime
, len
= 0;
335 const EC_METHOD
*meth
= EC_GROUP_method_of(group
);
337 if ((ec_p
= BN_new()) == NULL
338 || (ec_a
= BN_new()) == NULL
339 || (ec_b
= BN_new()) == NULL
340 || (ec_gen
= BN_new()) == NULL
341 || (ec_order
= BN_new()) == NULL
342 || (ec_cofactor
= BN_new()) == NULL
) {
343 perror("Can't allocate BN");
347 is_prime
= (EC_METHOD_get_field_type(meth
) == NID_X9_62_prime_field
);
349 BIO_printf(bio_err
, "Can only handle X9.62 prime fields\n");
353 if (!EC_GROUP_get_curve_GFp(group
, ec_p
, ec_a
, ec_b
, NULL
))
356 if ((point
= EC_GROUP_get0_generator(group
)) == NULL
)
358 if (!EC_POINT_point2bn(group
, point
,
359 EC_GROUP_get_point_conversion_form(group
),
362 if (!EC_GROUP_get_order(group
, ec_order
, NULL
))
364 if (!EC_GROUP_get_cofactor(group
, ec_cofactor
, NULL
))
367 if (!ec_p
|| !ec_a
|| !ec_b
|| !ec_gen
|| !ec_order
|| !ec_cofactor
)
370 len
= BN_num_bits(ec_order
);
372 if ((tmp_len
= (size_t)BN_num_bytes(ec_p
)) > buf_len
)
374 if ((tmp_len
= (size_t)BN_num_bytes(ec_a
)) > buf_len
)
376 if ((tmp_len
= (size_t)BN_num_bytes(ec_b
)) > buf_len
)
378 if ((tmp_len
= (size_t)BN_num_bytes(ec_gen
)) > buf_len
)
380 if ((tmp_len
= (size_t)BN_num_bytes(ec_order
)) > buf_len
)
382 if ((tmp_len
= (size_t)BN_num_bytes(ec_cofactor
)) > buf_len
)
385 buffer
= app_malloc(buf_len
, "BN buffer");
387 BIO_printf(out
, "EC_GROUP *get_ec_group_%d(void)\n{\n", len
);
388 print_bignum_var(out
, ec_p
, "ec_p", len
, buffer
);
389 print_bignum_var(out
, ec_a
, "ec_a", len
, buffer
);
390 print_bignum_var(out
, ec_b
, "ec_b", len
, buffer
);
391 print_bignum_var(out
, ec_gen
, "ec_gen", len
, buffer
);
392 print_bignum_var(out
, ec_order
, "ec_order", len
, buffer
);
393 print_bignum_var(out
, ec_cofactor
, "ec_cofactor", len
, buffer
);
394 BIO_printf(out
, " int ok = 0;\n"
395 " EC_GROUP *group = NULL;\n"
396 " EC_POINT *point = NULL;\n"
397 " BIGNUM *tmp_1 = NULL;\n"
398 " BIGNUM *tmp_2 = NULL;\n"
399 " BIGNUM *tmp_3 = NULL;\n"
402 BIO_printf(out
, " if ((tmp_1 = BN_bin2bn(ec_p_%d, sizeof (ec_p_%d), NULL)) == NULL)\n"
403 " goto err;\n", len
, len
);
404 BIO_printf(out
, " if ((tmp_2 = BN_bin2bn(ec_a_%d, sizeof (ec_a_%d), NULL)) == NULL)\n"
405 " goto err;\n", len
, len
);
406 BIO_printf(out
, " if ((tmp_3 = BN_bin2bn(ec_b_%d, sizeof (ec_b_%d), NULL)) == NULL)\n"
407 " goto err;\n", len
, len
);
408 BIO_printf(out
, " if ((group = EC_GROUP_new_curve_GFp(tmp_1, tmp_2, tmp_3, NULL)) == NULL)\n"
411 BIO_printf(out
, " /* build generator */\n");
412 BIO_printf(out
, " if ((tmp_1 = BN_bin2bn(ec_gen_%d, sizeof (ec_gen_%d), tmp_1)) == NULL)\n"
413 " goto err;\n", len
, len
);
414 BIO_printf(out
, " point = EC_POINT_bn2point(group, tmp_1, NULL, NULL);\n");
415 BIO_printf(out
, " if (point == NULL)\n"
417 BIO_printf(out
, " if ((tmp_2 = BN_bin2bn(ec_order_%d, sizeof (ec_order_%d), tmp_2)) == NULL)\n"
418 " goto err;\n", len
, len
);
419 BIO_printf(out
, " if ((tmp_3 = BN_bin2bn(ec_cofactor_%d, sizeof (ec_cofactor_%d), tmp_3)) == NULL)\n"
420 " goto err;\n", len
, len
);
421 BIO_printf(out
, " if (!EC_GROUP_set_generator(group, point, tmp_2, tmp_3))\n"
425 BIO_printf(out
, "err:\n"
429 " EC_POINT_free(point);\n"
431 " EC_GROUP_free(group);\n"
439 if (outformat
== FORMAT_ASN1
)
440 i
= i2d_ECPKParameters_bio(out
, group
);
442 i
= PEM_write_bio_ECPKParameters(out
, group
);
444 BIO_printf(bio_err
, "unable to write elliptic "
445 "curve parameters\n");
446 ERR_print_errors(bio_err
);
452 app_RAND_load_file(NULL
, (inrand
!= NULL
));
454 BIO_printf(bio_err
, "%ld semi-random bytes loaded\n",
455 app_RAND_load_files(inrand
));
459 EC_KEY
*eckey
= EC_KEY_new();
466 if (EC_KEY_set_group(eckey
, group
) == 0)
469 if (!EC_KEY_generate_key(eckey
)) {
473 if (outformat
== FORMAT_ASN1
)
474 i
= i2d_ECPrivateKey_bio(out
, eckey
);
476 i
= PEM_write_bio_ECPrivateKey(out
, eckey
, NULL
,
477 NULL
, 0, NULL
, NULL
);
482 app_RAND_write_file(NULL
);
491 BN_free(ec_cofactor
);
493 OPENSSL_free(buffer
);
496 EC_GROUP_free(group
);
500 #else /* !OPENSSL_NO_EC */
503 static void *dummy
= &dummy
;