2 * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
11 * Low level APIs related to EC_KEY are deprecated for public use,
12 * but still ok for internal use.
14 #include "internal/deprecated.h"
16 #include <openssl/core_names.h>
17 #include <openssl/objects.h>
18 #include <openssl/params.h>
19 #include <openssl/err.h>
20 #include "crypto/bn.h"
21 #include "crypto/ec.h"
24 #include "internal/param_build_set.h"
26 /* Mapping between a flag and a name */
27 static const OSSL_ITEM encoding_nameid_map
[] = {
28 { OPENSSL_EC_EXPLICIT_CURVE
, OSSL_PKEY_EC_ENCODING_EXPLICIT
},
29 { OPENSSL_EC_NAMED_CURVE
, OSSL_PKEY_EC_ENCODING_GROUP
},
32 static const OSSL_ITEM check_group_type_nameid_map
[] = {
33 { 0, OSSL_PKEY_EC_GROUP_CHECK_DEFAULT
},
34 { EC_FLAG_CHECK_NAMED_GROUP
, OSSL_PKEY_EC_GROUP_CHECK_NAMED
},
35 { EC_FLAG_CHECK_NAMED_GROUP_NIST
, OSSL_PKEY_EC_GROUP_CHECK_NAMED_NIST
},
38 static const OSSL_ITEM format_nameid_map
[] = {
39 { (int)POINT_CONVERSION_UNCOMPRESSED
, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_UNCOMPRESSED
},
40 { (int)POINT_CONVERSION_COMPRESSED
, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_COMPRESSED
},
41 { (int)POINT_CONVERSION_HYBRID
, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_HYBRID
},
44 int ec_encoding_name2id(const char *name
)
48 /* Return the default value if there is no name */
50 return OPENSSL_EC_NAMED_CURVE
;
52 for (i
= 0, sz
= OSSL_NELEM(encoding_nameid_map
); i
< sz
; i
++) {
53 if (strcasecmp(name
, encoding_nameid_map
[i
].ptr
) == 0)
54 return encoding_nameid_map
[i
].id
;
59 static char *ec_param_encoding_id2name(int id
)
63 for (i
= 0, sz
= OSSL_NELEM(encoding_nameid_map
); i
< sz
; i
++) {
64 if (id
== (int)encoding_nameid_map
[i
].id
)
65 return encoding_nameid_map
[i
].ptr
;
70 char *ec_check_group_type_id2name(int id
)
74 for (i
= 0, sz
= OSSL_NELEM(check_group_type_nameid_map
); i
< sz
; i
++) {
75 if (id
== (int)check_group_type_nameid_map
[i
].id
)
76 return check_group_type_nameid_map
[i
].ptr
;
81 static int ec_check_group_type_name2id(const char *name
)
85 /* Return the default value if there is no name */
89 for (i
= 0, sz
= OSSL_NELEM(check_group_type_nameid_map
); i
< sz
; i
++) {
90 if (strcasecmp(name
, check_group_type_nameid_map
[i
].ptr
) == 0)
91 return check_group_type_nameid_map
[i
].id
;
96 int ec_set_check_group_type_from_name(EC_KEY
*ec
, const char *name
)
98 int flags
= ec_check_group_type_name2id(name
);
102 EC_KEY_clear_flags(ec
, EC_FLAG_CHECK_NAMED_GROUP_MASK
);
103 EC_KEY_set_flags(ec
, flags
);
107 static int ec_set_check_group_type_from_param(EC_KEY
*ec
, const OSSL_PARAM
*p
)
109 const char *name
= NULL
;
112 switch (p
->data_type
) {
113 case OSSL_PARAM_UTF8_STRING
:
115 status
= (name
!= NULL
);
117 case OSSL_PARAM_UTF8_PTR
:
118 status
= OSSL_PARAM_get_utf8_ptr(p
, &name
);
122 return ec_set_check_group_type_from_name(ec
, name
);
126 int ec_pt_format_name2id(const char *name
)
130 /* Return the default value if there is no name */
132 return (int)POINT_CONVERSION_UNCOMPRESSED
;
134 for (i
= 0, sz
= OSSL_NELEM(format_nameid_map
); i
< sz
; i
++) {
135 if (strcasecmp(name
, format_nameid_map
[i
].ptr
) == 0)
136 return format_nameid_map
[i
].id
;
141 char *ec_pt_format_id2name(int id
)
145 for (i
= 0, sz
= OSSL_NELEM(format_nameid_map
); i
< sz
; i
++) {
146 if (id
== (int)format_nameid_map
[i
].id
)
147 return format_nameid_map
[i
].ptr
;
152 int ec_group_todata(const EC_GROUP
*group
, OSSL_PARAM_BLD
*tmpl
,
153 OSSL_PARAM params
[], OSSL_LIB_CTX
*libctx
,
155 BN_CTX
*bnctx
, unsigned char **genbuf
)
157 int ret
= 0, curve_nid
, encoding_flag
;
158 const char *field_type
, *encoding_name
, *pt_form_name
;
159 const BIGNUM
*cofactor
, *order
;
160 BIGNUM
*p
= NULL
, *a
= NULL
, *b
= NULL
;
161 point_conversion_form_t genform
;
162 const EC_POINT
*genpt
;
163 unsigned char *seed
= NULL
;
164 size_t genbuf_len
, seed_len
;
167 ERR_raise(ERR_LIB_EC
,EC_R_PASSED_NULL_PARAMETER
);
171 genform
= EC_GROUP_get_point_conversion_form(group
);
172 pt_form_name
= ec_pt_format_id2name(genform
);
173 if (pt_form_name
== NULL
174 || !ossl_param_build_set_utf8_string(
176 OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT
, pt_form_name
)) {
177 ECerr(0, EC_R_INVALID_FORM
);
180 encoding_flag
= EC_GROUP_get_asn1_flag(group
) & OPENSSL_EC_NAMED_CURVE
;
181 encoding_name
= ec_param_encoding_id2name(encoding_flag
);
182 if (encoding_name
== NULL
183 || !ossl_param_build_set_utf8_string(tmpl
, params
,
184 OSSL_PKEY_PARAM_EC_ENCODING
,
186 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_ENCODING
);
190 curve_nid
= EC_GROUP_get_curve_name(group
);
191 if (curve_nid
== NID_undef
) {
193 int fid
= EC_GROUP_get_field_type(group
);
195 if (fid
== NID_X9_62_prime_field
) {
196 field_type
= SN_X9_62_prime_field
;
197 } else if (fid
== NID_X9_62_characteristic_two_field
) {
198 field_type
= SN_X9_62_characteristic_two_field
;
200 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_FIELD
);
204 p
= BN_CTX_get(bnctx
);
205 a
= BN_CTX_get(bnctx
);
206 b
= BN_CTX_get(bnctx
);
208 ERR_raise(ERR_LIB_EC
, ERR_R_MALLOC_FAILURE
);
212 if (!EC_GROUP_get_curve(group
, p
, a
, b
, bnctx
)) {
213 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_CURVE
);
217 order
= EC_GROUP_get0_order(group
);
219 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_GROUP_ORDER
);
222 genpt
= EC_GROUP_get0_generator(group
);
224 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_GENERATOR
);
227 genbuf_len
= EC_POINT_point2buf(group
, genpt
, genform
, genbuf
, bnctx
);
228 if (genbuf_len
== 0) {
229 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_GENERATOR
);
233 if (!ossl_param_build_set_utf8_string(tmpl
, params
,
234 OSSL_PKEY_PARAM_EC_FIELD_TYPE
,
236 || !ossl_param_build_set_bn(tmpl
, params
, OSSL_PKEY_PARAM_EC_P
, p
)
237 || !ossl_param_build_set_bn(tmpl
, params
, OSSL_PKEY_PARAM_EC_A
, a
)
238 || !ossl_param_build_set_bn(tmpl
, params
, OSSL_PKEY_PARAM_EC_B
, b
)
239 || !ossl_param_build_set_bn(tmpl
, params
, OSSL_PKEY_PARAM_EC_ORDER
,
241 || !ossl_param_build_set_octet_string(tmpl
, params
,
242 OSSL_PKEY_PARAM_EC_GENERATOR
,
243 *genbuf
, genbuf_len
)) {
244 ERR_raise(ERR_LIB_EC
, ERR_R_MALLOC_FAILURE
);
248 cofactor
= EC_GROUP_get0_cofactor(group
);
250 && !ossl_param_build_set_bn(tmpl
, params
,
251 OSSL_PKEY_PARAM_EC_COFACTOR
, cofactor
)) {
252 ERR_raise(ERR_LIB_EC
, ERR_R_MALLOC_FAILURE
);
256 seed
= EC_GROUP_get0_seed(group
);
257 seed_len
= EC_GROUP_get_seed_len(group
);
260 && !ossl_param_build_set_octet_string(tmpl
, params
,
261 OSSL_PKEY_PARAM_EC_SEED
,
263 ERR_raise(ERR_LIB_EC
, ERR_R_MALLOC_FAILURE
);
266 #ifdef OPENSSL_NO_EC2M
267 if (fid
== NID_X9_62_characteristic_two_field
) {
268 ERR_raise(ERR_LIB_EC
, EC_R_GF2M_NOT_SUPPORTED
);
274 const char *curve_name
= ec_curve_nid2name(curve_nid
);
276 if (curve_name
== NULL
277 || !ossl_param_build_set_utf8_string(tmpl
, params
,
278 OSSL_PKEY_PARAM_GROUP_NAME
,
280 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_CURVE
);
290 * The intention with the "backend" source file is to offer backend support
291 * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider
292 * implementations alike.
294 int ec_set_ecdh_cofactor_mode(EC_KEY
*ec
, int mode
)
296 const EC_GROUP
*ecg
= EC_KEY_get0_group(ec
);
297 const BIGNUM
*cofactor
;
299 * mode can be only 0 for disable, or 1 for enable here.
301 * This is in contrast with the same parameter on an ECDH EVP_PKEY_CTX that
302 * also supports mode == -1 with the meaning of "reset to the default for
303 * the associated key".
305 if (mode
< 0 || mode
> 1)
308 if ((cofactor
= EC_GROUP_get0_cofactor(ecg
)) == NULL
)
311 /* ECDH cofactor mode has no effect if cofactor is 1 */
312 if (BN_is_one(cofactor
))
316 EC_KEY_set_flags(ec
, EC_FLAG_COFACTOR_ECDH
);
318 EC_KEY_clear_flags(ec
, EC_FLAG_COFACTOR_ECDH
);
324 * Callers of ec_key_fromdata MUST make sure that ec_key_params_fromdata has
325 * been called before!
327 * This function only gets the bare keypair, domain parameters and other
328 * parameters are treated separately, and domain parameters are required to
331 int ec_key_fromdata(EC_KEY
*ec
, const OSSL_PARAM params
[], int include_private
)
333 const OSSL_PARAM
*param_priv_key
= NULL
, *param_pub_key
= NULL
;
335 BIGNUM
*priv_key
= NULL
;
336 unsigned char *pub_key
= NULL
;
338 const EC_GROUP
*ecg
= NULL
;
339 EC_POINT
*pub_point
= NULL
;
342 ecg
= EC_KEY_get0_group(ec
);
347 OSSL_PARAM_locate_const(params
, OSSL_PKEY_PARAM_PUB_KEY
);
350 OSSL_PARAM_locate_const(params
, OSSL_PKEY_PARAM_PRIV_KEY
);
352 ctx
= BN_CTX_new_ex(ec_key_get_libctx(ec
));
356 if (param_pub_key
!= NULL
)
357 if (!OSSL_PARAM_get_octet_string(param_pub_key
,
358 (void **)&pub_key
, 0, &pub_key_len
)
359 || (pub_point
= EC_POINT_new(ecg
)) == NULL
360 || !EC_POINT_oct2point(ecg
, pub_point
, pub_key
, pub_key_len
, ctx
))
363 if (param_priv_key
!= NULL
&& include_private
) {
368 * Key import/export should never leak the bit length of the secret
371 * For this reason, on export we use padded BIGNUMs with fixed length.
373 * When importing we also should make sure that, even if short lived,
374 * the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as
375 * soon as possible, so that any processing of this BIGNUM might opt for
376 * constant time implementations in the backend.
378 * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have
379 * to preallocate the BIGNUM internal buffer to a fixed public size big
380 * enough that operations performed during the processing never trigger
381 * a realloc which would leak the size of the scalar through memory
387 * The order of the large prime subgroup of the curve is our choice for
388 * a fixed public size, as that is generally the upper bound for
389 * generating a private key in EC cryptosystems and should fit all valid
392 * For padding on export we just use the bit length of the order
393 * converted to bytes (rounding up).
395 * For preallocating the BIGNUM storage we look at the number of "words"
396 * required for the internal representation of the order, and we
397 * preallocate 2 extra "words" in case any of the subsequent processing
398 * might temporarily overflow the order length.
400 order
= EC_GROUP_get0_order(ecg
);
401 if (order
== NULL
|| BN_is_zero(order
))
404 fixed_words
= bn_get_top(order
) + 2;
406 if ((priv_key
= BN_secure_new()) == NULL
)
408 if (bn_wexpand(priv_key
, fixed_words
) == NULL
)
410 BN_set_flags(priv_key
, BN_FLG_CONSTTIME
);
412 if (!OSSL_PARAM_get_BN(param_priv_key
, &priv_key
))
417 && !EC_KEY_set_private_key(ec
, priv_key
))
420 if (pub_point
!= NULL
421 && !EC_KEY_set_public_key(ec
, pub_point
))
428 BN_clear_free(priv_key
);
429 OPENSSL_free(pub_key
);
430 EC_POINT_free(pub_point
);
434 int ec_group_fromdata(EC_KEY
*ec
, const OSSL_PARAM params
[])
437 EC_GROUP
*group
= NULL
;
442 group
= EC_GROUP_new_from_params(params
, ec_key_get_libctx(ec
),
443 ec_key_get0_propq(ec
));
445 if (!EC_KEY_set_group(ec
, group
))
449 EC_GROUP_free(group
);
453 static int ec_key_point_format_fromdata(EC_KEY
*ec
, const OSSL_PARAM params
[])
458 p
= OSSL_PARAM_locate_const(params
, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT
);
460 if (!ec_pt_format_param2id(p
, &format
)) {
461 ECerr(0, EC_R_INVALID_FORM
);
464 EC_KEY_set_conv_form(ec
, format
);
469 static int ec_key_group_check_fromdata(EC_KEY
*ec
, const OSSL_PARAM params
[])
473 p
= OSSL_PARAM_locate_const(params
, OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE
);
475 return ec_set_check_group_type_from_param(ec
, p
);
479 static int ec_set_include_public(EC_KEY
*ec
, int include
)
481 int flags
= EC_KEY_get_enc_flags(ec
);
484 flags
|= EC_PKEY_NO_PUBKEY
;
486 flags
&= ~EC_PKEY_NO_PUBKEY
;
487 EC_KEY_set_enc_flags(ec
, flags
);
491 int ec_key_otherparams_fromdata(EC_KEY
*ec
, const OSSL_PARAM params
[])
498 p
= OSSL_PARAM_locate_const(params
, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH
);
502 if (!OSSL_PARAM_get_int(p
, &mode
)
503 || !ec_set_ecdh_cofactor_mode(ec
, mode
))
507 p
= OSSL_PARAM_locate_const(params
, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC
);
511 if (!OSSL_PARAM_get_int(p
, &include
)
512 || !ec_set_include_public(ec
, include
))
515 if (!ec_key_point_format_fromdata(ec
, params
))
517 if (!ec_key_group_check_fromdata(ec
, params
))
522 int ec_encoding_param2id(const OSSL_PARAM
*p
, int *id
)
524 const char *name
= NULL
;
527 switch (p
->data_type
) {
528 case OSSL_PARAM_UTF8_STRING
:
529 /* The OSSL_PARAM functions have no support for this */
531 status
= (name
!= NULL
);
533 case OSSL_PARAM_UTF8_PTR
:
534 status
= OSSL_PARAM_get_utf8_ptr(p
, &name
);
538 int i
= ec_encoding_name2id(name
);
548 int ec_pt_format_param2id(const OSSL_PARAM
*p
, int *id
)
550 const char *name
= NULL
;
553 switch (p
->data_type
) {
554 case OSSL_PARAM_UTF8_STRING
:
555 /* The OSSL_PARAM functions have no support for this */
557 status
= (name
!= NULL
);
559 case OSSL_PARAM_UTF8_PTR
:
560 status
= OSSL_PARAM_get_utf8_ptr(p
, &name
);
564 int i
= ec_pt_format_name2id(name
);