Path: blob/main/crypto/openssl/providers/implementations/keymgmt/ec_kmgmt.c
108106 views
/*1* Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89/*10* ECDH/ECDSA low level APIs are deprecated for public use, but still ok for11* internal use.12*/13#include "internal/deprecated.h"1415#include <string.h>16#include <openssl/core_dispatch.h>17#include <openssl/core_names.h>18#include <openssl/bn.h>19#include <openssl/err.h>20#include <openssl/objects.h>21#include <openssl/proverr.h>22#include <openssl/self_test.h>23#include "crypto/bn.h"24#include "crypto/ec.h"25#include "prov/implementations.h"26#include "prov/providercommon.h"27#include "prov/provider_ctx.h"28#include "prov/securitycheck.h"29#include "internal/fips.h"30#include "internal/param_build_set.h"3132#ifndef FIPS_MODULE33#ifndef OPENSSL_NO_SM234#include "crypto/sm2.h"35#endif36#endif3738static OSSL_FUNC_keymgmt_new_fn ec_newdata;39static OSSL_FUNC_keymgmt_gen_init_fn ec_gen_init;40static OSSL_FUNC_keymgmt_gen_set_template_fn ec_gen_set_template;41static OSSL_FUNC_keymgmt_gen_set_params_fn ec_gen_set_params;42static OSSL_FUNC_keymgmt_gen_settable_params_fn ec_gen_settable_params;43static OSSL_FUNC_keymgmt_gen_get_params_fn ec_gen_get_params;44static OSSL_FUNC_keymgmt_gen_gettable_params_fn ec_gen_gettable_params;45static OSSL_FUNC_keymgmt_gen_fn ec_gen;46static OSSL_FUNC_keymgmt_gen_cleanup_fn ec_gen_cleanup;47static OSSL_FUNC_keymgmt_load_fn ec_load;48static OSSL_FUNC_keymgmt_free_fn ec_freedata;49static OSSL_FUNC_keymgmt_get_params_fn ec_get_params;50static OSSL_FUNC_keymgmt_gettable_params_fn ec_gettable_params;51static OSSL_FUNC_keymgmt_set_params_fn ec_set_params;52static OSSL_FUNC_keymgmt_settable_params_fn ec_settable_params;53static OSSL_FUNC_keymgmt_has_fn ec_has;54static OSSL_FUNC_keymgmt_match_fn ec_match;55static OSSL_FUNC_keymgmt_validate_fn ec_validate;56static OSSL_FUNC_keymgmt_import_fn ec_import;57static OSSL_FUNC_keymgmt_import_types_fn ec_import_types;58static OSSL_FUNC_keymgmt_export_fn ec_export;59static OSSL_FUNC_keymgmt_export_types_fn ec_export_types;60static OSSL_FUNC_keymgmt_query_operation_name_fn ec_query_operation_name;61static OSSL_FUNC_keymgmt_dup_fn ec_dup;62#ifndef FIPS_MODULE63#ifndef OPENSSL_NO_SM264static OSSL_FUNC_keymgmt_new_fn sm2_newdata;65static OSSL_FUNC_keymgmt_gen_init_fn sm2_gen_init;66static OSSL_FUNC_keymgmt_gen_fn sm2_gen;67static OSSL_FUNC_keymgmt_get_params_fn sm2_get_params;68static OSSL_FUNC_keymgmt_gettable_params_fn sm2_gettable_params;69static OSSL_FUNC_keymgmt_settable_params_fn sm2_settable_params;70static OSSL_FUNC_keymgmt_import_fn sm2_import;71static OSSL_FUNC_keymgmt_query_operation_name_fn sm2_query_operation_name;72static OSSL_FUNC_keymgmt_validate_fn sm2_validate;73#endif74#endif7576#define EC_DEFAULT_MD "SHA256"77#define EC_POSSIBLE_SELECTIONS \78(OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS)79#define SM2_DEFAULT_MD "SM3"8081static const char *ec_query_operation_name(int operation_id)82{83switch (operation_id) {84case OSSL_OP_KEYEXCH:85return "ECDH";86case OSSL_OP_SIGNATURE:87return "ECDSA";88}89return NULL;90}9192#ifndef FIPS_MODULE93#ifndef OPENSSL_NO_SM294static const char *sm2_query_operation_name(int operation_id)95{96switch (operation_id) {97case OSSL_OP_SIGNATURE:98return "SM2";99}100return NULL;101}102#endif103#endif104105/*106* Callers of key_to_params MUST make sure that domparams_to_params is also107* called!108*109* This function only exports the bare keypair, domain parameters and other110* parameters are exported separately.111*/112static ossl_inline int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl,113OSSL_PARAM params[], int include_private,114unsigned char **pub_key)115{116BIGNUM *x = NULL, *y = NULL;117const BIGNUM *priv_key = NULL;118const EC_POINT *pub_point = NULL;119const EC_GROUP *ecg = NULL;120size_t pub_key_len = 0;121int ret = 0;122BN_CTX *bnctx = NULL;123124if (eckey == NULL125|| (ecg = EC_KEY_get0_group(eckey)) == NULL)126return 0;127128priv_key = EC_KEY_get0_private_key(eckey);129pub_point = EC_KEY_get0_public_key(eckey);130131if (pub_point != NULL) {132OSSL_PARAM *p = NULL, *px = NULL, *py = NULL;133/*134* EC_POINT_point2buf() can generate random numbers in some135* implementations so we need to ensure we use the correct libctx.136*/137bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eckey));138if (bnctx == NULL)139goto err;140141/* If we are doing a get then check first before decoding the point */142if (tmpl == NULL) {143p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PUB_KEY);144px = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_EC_PUB_X);145py = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_EC_PUB_Y);146}147148if (p != NULL || tmpl != NULL) {149/* convert pub_point to a octet string according to the SECG standard */150point_conversion_form_t format = EC_KEY_get_conv_form(eckey);151152if ((pub_key_len = EC_POINT_point2buf(ecg, pub_point,153format,154pub_key, bnctx))155== 0156|| !ossl_param_build_set_octet_string(tmpl, p,157OSSL_PKEY_PARAM_PUB_KEY,158*pub_key, pub_key_len))159goto err;160}161if (px != NULL || py != NULL) {162if (px != NULL) {163x = BN_CTX_get(bnctx);164if (x == NULL)165goto err;166}167if (py != NULL) {168y = BN_CTX_get(bnctx);169if (y == NULL)170goto err;171}172173if (!EC_POINT_get_affine_coordinates(ecg, pub_point, x, y, bnctx))174goto err;175if (px != NULL176&& !ossl_param_build_set_bn(tmpl, px,177OSSL_PKEY_PARAM_EC_PUB_X, x))178goto err;179if (py != NULL180&& !ossl_param_build_set_bn(tmpl, py,181OSSL_PKEY_PARAM_EC_PUB_Y, y))182goto err;183}184}185186if (priv_key != NULL && include_private) {187size_t sz;188int ecbits;189190/*191* Key import/export should never leak the bit length of the secret192* scalar in the key.193*194* For this reason, on export we use padded BIGNUMs with fixed length.195*196* When importing we also should make sure that, even if short lived,197* the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as198* soon as possible, so that any processing of this BIGNUM might opt for199* constant time implementations in the backend.200*201* Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have202* to preallocate the BIGNUM internal buffer to a fixed public size big203* enough that operations performed during the processing never trigger204* a realloc which would leak the size of the scalar through memory205* accesses.206*207* Fixed Length208* ------------209*210* The order of the large prime subgroup of the curve is our choice for211* a fixed public size, as that is generally the upper bound for212* generating a private key in EC cryptosystems and should fit all valid213* secret scalars.214*215* For padding on export we just use the bit length of the order216* converted to bytes (rounding up).217*218* For preallocating the BIGNUM storage we look at the number of "words"219* required for the internal representation of the order, and we220* preallocate 2 extra "words" in case any of the subsequent processing221* might temporarily overflow the order length.222*/223ecbits = EC_GROUP_order_bits(ecg);224if (ecbits <= 0)225goto err;226sz = (ecbits + 7) / 8;227228if (!ossl_param_build_set_bn_pad(tmpl, params,229OSSL_PKEY_PARAM_PRIV_KEY,230priv_key, sz))231goto err;232}233ret = 1;234err:235BN_CTX_free(bnctx);236return ret;237}238239static ossl_inline int otherparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl,240OSSL_PARAM params[])241{242int ecdh_cofactor_mode = 0, group_check = 0;243const char *name = NULL;244point_conversion_form_t format;245246if (ec == NULL)247return 0;248249format = EC_KEY_get_conv_form(ec);250name = ossl_ec_pt_format_id2name((int)format);251if (name != NULL252&& !ossl_param_build_set_utf8_string(tmpl, params,253OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,254name))255return 0;256257group_check = EC_KEY_get_flags(ec) & EC_FLAG_CHECK_NAMED_GROUP_MASK;258name = ossl_ec_check_group_type_id2name(group_check);259if (name != NULL260&& !ossl_param_build_set_utf8_string(tmpl, params,261OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE,262name))263return 0;264265if ((EC_KEY_get_enc_flags(ec) & EC_PKEY_NO_PUBKEY) != 0266&& !ossl_param_build_set_int(tmpl, params,267OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, 0))268return 0;269270ecdh_cofactor_mode = (EC_KEY_get_flags(ec) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;271return ossl_param_build_set_int(tmpl, params,272OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,273ecdh_cofactor_mode);274}275276static void *ec_newdata(void *provctx)277{278if (!ossl_prov_is_running())279return NULL;280return EC_KEY_new_ex(PROV_LIBCTX_OF(provctx), NULL);281}282283#ifndef FIPS_MODULE284#ifndef OPENSSL_NO_SM2285static void *sm2_newdata(void *provctx)286{287if (!ossl_prov_is_running())288return NULL;289return EC_KEY_new_by_curve_name_ex(PROV_LIBCTX_OF(provctx), NULL, NID_sm2);290}291#endif292#endif293294static void ec_freedata(void *keydata)295{296EC_KEY_free(keydata);297}298299static int ec_has(const void *keydata, int selection)300{301const EC_KEY *ec = keydata;302int ok = 1;303304if (!ossl_prov_is_running() || ec == NULL)305return 0;306if ((selection & EC_POSSIBLE_SELECTIONS) == 0)307return 1; /* the selection is not missing */308309if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)310ok = ok && (EC_KEY_get0_public_key(ec) != NULL);311if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)312ok = ok && (EC_KEY_get0_private_key(ec) != NULL);313if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)314ok = ok && (EC_KEY_get0_group(ec) != NULL);315/*316* We consider OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS to always be317* available, so no extra check is needed other than the previous one318* against EC_POSSIBLE_SELECTIONS.319*/320return ok;321}322323static int ec_match(const void *keydata1, const void *keydata2, int selection)324{325const EC_KEY *ec1 = keydata1;326const EC_KEY *ec2 = keydata2;327const EC_GROUP *group_a = EC_KEY_get0_group(ec1);328const EC_GROUP *group_b = EC_KEY_get0_group(ec2);329BN_CTX *ctx = NULL;330int ok = 1;331332if (!ossl_prov_is_running())333return 0;334335ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec1));336if (ctx == NULL)337return 0;338339if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)340ok = ok && group_a != NULL && group_b != NULL341&& EC_GROUP_cmp(group_a, group_b, ctx) == 0;342if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {343int key_checked = 0;344345if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {346const EC_POINT *pa = EC_KEY_get0_public_key(ec1);347const EC_POINT *pb = EC_KEY_get0_public_key(ec2);348349if (pa != NULL && pb != NULL) {350ok = ok && EC_POINT_cmp(group_b, pa, pb, ctx) == 0;351key_checked = 1;352}353}354if (!key_checked355&& (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {356const BIGNUM *pa = EC_KEY_get0_private_key(ec1);357const BIGNUM *pb = EC_KEY_get0_private_key(ec2);358359if (pa != NULL && pb != NULL) {360ok = ok && BN_cmp(pa, pb) == 0;361key_checked = 1;362}363}364ok = ok && key_checked;365}366BN_CTX_free(ctx);367return ok;368}369370static int common_check_sm2(const EC_KEY *ec, int sm2_wanted)371{372const EC_GROUP *ecg = NULL;373374/*375* sm2_wanted: import the keys or domparams only on SM2 Curve376* !sm2_wanted: import the keys or domparams only not on SM2 Curve377*/378if ((ecg = EC_KEY_get0_group(ec)) == NULL379|| (sm2_wanted ^ (EC_GROUP_get_curve_name(ecg) == NID_sm2)))380return 0;381return 1;382}383384static int common_import(void *keydata, int selection, const OSSL_PARAM params[],385int sm2_wanted)386{387EC_KEY *ec = keydata;388int ok = 1;389390if (!ossl_prov_is_running() || ec == NULL)391return 0;392393/*394* In this implementation, we can export/import only keydata in the395* following combinations:396* - domain parameters (+optional other params)397* - public key with associated domain parameters (+optional other params)398* - private key with associated domain parameters and optional public key399* (+optional other params)400*401* This means:402* - domain parameters must always be requested403* - private key must be requested alongside public key404* - other parameters are always optional405*/406if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)407return 0;408409ok = ok && ossl_ec_group_fromdata(ec, params);410411if (!common_check_sm2(ec, sm2_wanted))412return 0;413414if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {415int include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;416417ok = ok && ossl_ec_key_fromdata(ec, params, include_private);418}419if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)420ok = ok && ossl_ec_key_otherparams_fromdata(ec, params);421422return ok;423}424425static int ec_import(void *keydata, int selection, const OSSL_PARAM params[])426{427return common_import(keydata, selection, params, 0);428}429430#ifndef FIPS_MODULE431#ifndef OPENSSL_NO_SM2432static int sm2_import(void *keydata, int selection, const OSSL_PARAM params[])433{434return common_import(keydata, selection, params, 1);435}436#endif437#endif438439static int ec_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,440void *cbarg)441{442EC_KEY *ec = keydata;443OSSL_PARAM_BLD *tmpl = NULL;444OSSL_PARAM *params = NULL;445unsigned char *pub_key = NULL, *genbuf = NULL;446BN_CTX *bnctx = NULL;447int ok = 1;448449if (!ossl_prov_is_running() || ec == NULL)450return 0;451452/*453* In this implementation, we can export/import only keydata in the454* following combinations:455* - domain parameters (+optional other params)456* - public key with associated domain parameters (+optional other params)457* - private key with associated public key and domain parameters458* (+optional other params)459*460* This means:461* - domain parameters must always be requested462* - private key must be requested alongside public key463* - other parameters are always optional464*/465if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)466return 0;467if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0468&& (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)469return 0;470471tmpl = OSSL_PARAM_BLD_new();472if (tmpl == NULL)473return 0;474475if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {476bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec));477if (bnctx == NULL) {478ok = 0;479goto end;480}481BN_CTX_start(bnctx);482ok = ok && ossl_ec_group_todata(EC_KEY_get0_group(ec), tmpl, NULL, ossl_ec_key_get_libctx(ec), ossl_ec_key_get0_propq(ec), bnctx, &genbuf);483}484485if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {486int include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;487488ok = ok && key_to_params(ec, tmpl, NULL, include_private, &pub_key);489}490if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)491ok = ok && otherparams_to_params(ec, tmpl, NULL);492493if (!ok || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {494ok = 0;495goto end;496}497498ok = param_cb(params, cbarg);499OSSL_PARAM_free(params);500end:501OSSL_PARAM_BLD_free(tmpl);502OPENSSL_free(pub_key);503OPENSSL_free(genbuf);504BN_CTX_end(bnctx);505BN_CTX_free(bnctx);506return ok;507}508509/* IMEXPORT = IMPORT + EXPORT */510511#define EC_IMEXPORTABLE_DOM_PARAMETERS \512OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), \513OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0), \514OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0), \515OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_FIELD_TYPE, NULL, 0), \516OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_P, NULL, 0), \517OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_A, NULL, 0), \518OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_B, NULL, 0), \519OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_GENERATOR, NULL, 0), \520OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_ORDER, NULL, 0), \521OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_COFACTOR, NULL, 0), \522OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0), \523OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, NULL)524525#define EC_IMEXPORTABLE_PUBLIC_KEY \526OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0)527#define EC_IMEXPORTABLE_PRIVATE_KEY \528OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)529#define EC_IMEXPORTABLE_OTHER_PARAMETERS \530OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL), \531OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL)532533/*534* Include all the possible combinations of OSSL_PARAM arrays for535* ec_imexport_types().536*537* They are in a separate file as it is ~100 lines of unreadable and538* uninteresting machine generated stuff.539*/540#include "ec_kmgmt_imexport.inc"541542static ossl_inline const OSSL_PARAM *ec_imexport_types(int selection)543{544int type_select = 0;545546if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)547type_select += 1;548if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)549type_select += 2;550if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)551type_select += 4;552if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)553type_select += 8;554return ec_types[type_select];555}556557static const OSSL_PARAM *ec_import_types(int selection)558{559return ec_imexport_types(selection);560}561562static const OSSL_PARAM *ec_export_types(int selection)563{564return ec_imexport_types(selection);565}566567static int ec_get_ecm_params(const EC_GROUP *group, OSSL_PARAM params[])568{569#ifdef OPENSSL_NO_EC2M570return 1;571#else572int ret = 0, m;573unsigned int k1 = 0, k2 = 0, k3 = 0;574int basis_nid;575const char *basis_name = NULL;576int fid = EC_GROUP_get_field_type(group);577578if (fid != NID_X9_62_characteristic_two_field)579return 1;580581basis_nid = EC_GROUP_get_basis_type(group);582if (basis_nid == NID_X9_62_tpBasis)583basis_name = SN_X9_62_tpBasis;584else if (basis_nid == NID_X9_62_ppBasis)585basis_name = SN_X9_62_ppBasis;586else587goto err;588589m = EC_GROUP_get_degree(group);590if (!ossl_param_build_set_int(NULL, params, OSSL_PKEY_PARAM_EC_CHAR2_M, m)591|| !ossl_param_build_set_utf8_string(NULL, params,592OSSL_PKEY_PARAM_EC_CHAR2_TYPE,593basis_name))594goto err;595596if (basis_nid == NID_X9_62_tpBasis) {597if (!EC_GROUP_get_trinomial_basis(group, &k1)598|| !ossl_param_build_set_int(NULL, params,599OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS,600(int)k1))601goto err;602} else {603if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3)604|| !ossl_param_build_set_int(NULL, params,605OSSL_PKEY_PARAM_EC_CHAR2_PP_K1, (int)k1)606|| !ossl_param_build_set_int(NULL, params,607OSSL_PKEY_PARAM_EC_CHAR2_PP_K2, (int)k2)608|| !ossl_param_build_set_int(NULL, params,609OSSL_PKEY_PARAM_EC_CHAR2_PP_K3, (int)k3))610goto err;611}612ret = 1;613err:614return ret;615#endif /* OPENSSL_NO_EC2M */616}617618static int common_get_params(void *key, OSSL_PARAM params[], int sm2)619{620int ret = 0;621EC_KEY *eck = key;622const EC_GROUP *ecg = NULL;623OSSL_PARAM *p;624unsigned char *pub_key = NULL, *genbuf = NULL;625OSSL_LIB_CTX *libctx;626const char *propq;627BN_CTX *bnctx = NULL;628629ecg = EC_KEY_get0_group(eck);630if (ecg == NULL) {631ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET);632return 0;633}634635libctx = ossl_ec_key_get_libctx(eck);636propq = ossl_ec_key_get0_propq(eck);637638bnctx = BN_CTX_new_ex(libctx);639if (bnctx == NULL)640return 0;641BN_CTX_start(bnctx);642643if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL644&& !OSSL_PARAM_set_int(p, ECDSA_size(eck)))645goto err;646if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL647&& !OSSL_PARAM_set_int(p, EC_GROUP_order_bits(ecg)))648goto err;649if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL) {650int ecbits, sec_bits;651652ecbits = EC_GROUP_order_bits(ecg);653654/*655* The following estimates are based on the values published656* in Table 2 of "NIST Special Publication 800-57 Part 1 Revision 4"657* at http://dx.doi.org/10.6028/NIST.SP.800-57pt1r4 .658*659* Note that the above reference explicitly categorizes algorithms in a660* discrete set of values {80, 112, 128, 192, 256}, and that it is661* relevant only for NIST approved Elliptic Curves, while OpenSSL662* applies the same logic also to other curves.663*664* Classifications produced by other standardazing bodies might differ,665* so the results provided for "bits of security" by this provider are666* to be considered merely indicative, and it is the users'667* responsibility to compare these values against the normative668* references that may be relevant for their intent and purposes.669*/670if (ecbits >= 512)671sec_bits = 256;672else if (ecbits >= 384)673sec_bits = 192;674else if (ecbits >= 256)675sec_bits = 128;676else if (ecbits >= 224)677sec_bits = 112;678else if (ecbits >= 160)679sec_bits = 80;680else681sec_bits = ecbits / 2;682683if (!OSSL_PARAM_set_int(p, sec_bits))684goto err;685}686687if ((p = OSSL_PARAM_locate(params,688OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS))689!= NULL) {690int explicitparams = EC_KEY_decoded_from_explicit_params(eck);691692if (explicitparams < 0693|| !OSSL_PARAM_set_int(p, explicitparams))694goto err;695}696697if (!sm2) {698if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL699&& !OSSL_PARAM_set_utf8_string(p, EC_DEFAULT_MD))700goto err;701} else {702if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL703&& !OSSL_PARAM_set_utf8_string(p, SM2_DEFAULT_MD))704goto err;705}706707/* SM2 doesn't support this PARAM */708if (!sm2) {709p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);710if (p != NULL) {711int ecdh_cofactor_mode = 0;712713ecdh_cofactor_mode = (EC_KEY_get_flags(eck) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;714715if (!OSSL_PARAM_set_int(p, ecdh_cofactor_mode))716goto err;717}718}719if ((p = OSSL_PARAM_locate(params,720OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY))721!= NULL) {722const EC_POINT *ecp = EC_KEY_get0_public_key(key);723724if (ecp == NULL) {725ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);726goto err;727}728p->return_size = EC_POINT_point2oct(ecg, ecp,729POINT_CONVERSION_UNCOMPRESSED,730p->data, p->data_size, bnctx);731if (p->return_size == 0)732goto err;733}734735ret = ec_get_ecm_params(ecg, params)736&& ossl_ec_group_todata(ecg, NULL, params, libctx, propq, bnctx,737&genbuf)738&& key_to_params(eck, NULL, params, 1, &pub_key)739&& otherparams_to_params(eck, NULL, params);740err:741OPENSSL_free(genbuf);742OPENSSL_free(pub_key);743BN_CTX_end(bnctx);744BN_CTX_free(bnctx);745return ret;746}747748static int ec_get_params(void *key, OSSL_PARAM params[])749{750return common_get_params(key, params, 0);751}752753#ifndef OPENSSL_NO_EC2M754#define EC2M_GETTABLE_DOM_PARAMS \755OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_M, NULL), \756OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_CHAR2_TYPE, NULL, 0), \757OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS, NULL), \758OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K1, NULL), \759OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K2, NULL), \760OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K3, NULL),761#else762#define EC2M_GETTABLE_DOM_PARAMS763#endif764765static const OSSL_PARAM ec_known_gettable_params[] = {766OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),767OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),768OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),769OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0),770OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),771OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, NULL),772EC_IMEXPORTABLE_DOM_PARAMETERS,773EC2M_GETTABLE_DOM_PARAMS774EC_IMEXPORTABLE_PUBLIC_KEY,775OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0),776OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0),777EC_IMEXPORTABLE_PRIVATE_KEY,778EC_IMEXPORTABLE_OTHER_PARAMETERS,779OSSL_PARAM_END780};781782static const OSSL_PARAM *ec_gettable_params(void *provctx)783{784return ec_known_gettable_params;785}786787static const OSSL_PARAM ec_known_settable_params[] = {788OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),789OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),790OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0),791OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0),792OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0),793OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL),794OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE, NULL, 0),795OSSL_PARAM_END796};797798static const OSSL_PARAM *ec_settable_params(void *provctx)799{800return ec_known_settable_params;801}802803static int ec_set_params(void *key, const OSSL_PARAM params[])804{805EC_KEY *eck = key;806const OSSL_PARAM *p;807808if (key == NULL)809return 0;810if (ossl_param_is_empty(params))811return 1;812813if (!ossl_ec_group_set_params((EC_GROUP *)EC_KEY_get0_group(key), params))814return 0;815816p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);817if (p != NULL) {818BN_CTX *ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(key));819int ret = 1;820821if (ctx == NULL822|| p->data_type != OSSL_PARAM_OCTET_STRING823|| !EC_KEY_oct2key(key, p->data, p->data_size, ctx))824ret = 0;825BN_CTX_free(ctx);826if (!ret)827return 0;828}829830return ossl_ec_key_otherparams_fromdata(eck, params);831}832833#ifndef FIPS_MODULE834#ifndef OPENSSL_NO_SM2835static int sm2_get_params(void *key, OSSL_PARAM params[])836{837return common_get_params(key, params, 1);838}839840static const OSSL_PARAM sm2_known_gettable_params[] = {841OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),842OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),843OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),844OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0),845OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),846OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, NULL),847EC_IMEXPORTABLE_DOM_PARAMETERS,848EC_IMEXPORTABLE_PUBLIC_KEY,849OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0),850OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0),851EC_IMEXPORTABLE_PRIVATE_KEY,852OSSL_PARAM_END853};854855static const OSSL_PARAM *sm2_gettable_params(ossl_unused void *provctx)856{857return sm2_known_gettable_params;858}859860static const OSSL_PARAM sm2_known_settable_params[] = {861OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),862OSSL_PARAM_END863};864865static const OSSL_PARAM *sm2_settable_params(ossl_unused void *provctx)866{867return sm2_known_settable_params;868}869870static int sm2_validate(const void *keydata, int selection, int checktype)871{872const EC_KEY *eck = keydata;873int ok = 1;874BN_CTX *ctx = NULL;875876if (!ossl_prov_is_running())877return 0;878879if ((selection & EC_POSSIBLE_SELECTIONS) == 0)880return 1; /* nothing to validate */881882ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eck));883if (ctx == NULL)884return 0;885886if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)887ok = ok && EC_GROUP_check(EC_KEY_get0_group(eck), ctx);888889if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {890if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK)891ok = ok && ossl_ec_key_public_check_quick(eck, ctx);892else893ok = ok && ossl_ec_key_public_check(eck, ctx);894}895896if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)897ok = ok && ossl_sm2_key_private_check(eck);898899if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)900ok = ok && ossl_ec_key_pairwise_check(eck, ctx);901902BN_CTX_free(ctx);903return ok;904}905#endif906#endif907908static int ec_validate(const void *keydata, int selection, int checktype)909{910const EC_KEY *eck = keydata;911int ok = 1;912BN_CTX *ctx = NULL;913914if (!ossl_prov_is_running())915return 0;916917if ((selection & EC_POSSIBLE_SELECTIONS) == 0)918return 1; /* nothing to validate */919920ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eck));921if (ctx == NULL)922return 0;923924if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {925int flags = EC_KEY_get_flags(eck);926927if ((flags & EC_FLAG_CHECK_NAMED_GROUP) != 0)928ok = ok && EC_GROUP_check_named_curve(EC_KEY_get0_group(eck), (flags & EC_FLAG_CHECK_NAMED_GROUP_NIST) != 0, ctx) > 0;929else930ok = ok && EC_GROUP_check(EC_KEY_get0_group(eck), ctx);931}932933if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {934if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK)935ok = ok && ossl_ec_key_public_check_quick(eck, ctx);936else937ok = ok && ossl_ec_key_public_check(eck, ctx);938}939940if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)941ok = ok && ossl_ec_key_private_check(eck);942943if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)944ok = ok && ossl_ec_key_pairwise_check(eck, ctx);945946BN_CTX_free(ctx);947return ok;948}949950struct ec_gen_ctx {951OSSL_LIB_CTX *libctx;952char *group_name;953char *encoding;954char *pt_format;955char *group_check;956char *field_type;957BIGNUM *p, *a, *b, *order, *cofactor;958unsigned char *gen, *seed;959size_t gen_len, seed_len;960int selection;961int ecdh_mode;962EC_GROUP *gen_group;963unsigned char *dhkem_ikm;964size_t dhkem_ikmlen;965OSSL_FIPS_IND_DECLARE966};967968static void *ec_gen_init(void *provctx, int selection,969const OSSL_PARAM params[])970{971OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);972struct ec_gen_ctx *gctx = NULL;973974if (!ossl_prov_is_running() || (selection & (EC_POSSIBLE_SELECTIONS)) == 0)975return NULL;976977if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {978gctx->libctx = libctx;979gctx->selection = selection;980gctx->ecdh_mode = 0;981OSSL_FIPS_IND_INIT(gctx)982if (!ec_gen_set_params(gctx, params)) {983ec_gen_cleanup(gctx);984gctx = NULL;985}986}987return gctx;988}989990#ifndef FIPS_MODULE991#ifndef OPENSSL_NO_SM2992static void *sm2_gen_init(void *provctx, int selection,993const OSSL_PARAM params[])994{995struct ec_gen_ctx *gctx = ec_gen_init(provctx, selection, params);996997if (gctx != NULL) {998if (gctx->group_name != NULL)999return gctx;1000if ((gctx->group_name = OPENSSL_strdup("sm2")) != NULL)1001return gctx;1002ec_gen_cleanup(gctx);1003}1004return NULL;1005}1006#endif1007#endif10081009static int ec_gen_set_group(void *genctx, const EC_GROUP *src)1010{1011struct ec_gen_ctx *gctx = genctx;1012EC_GROUP *group;10131014group = EC_GROUP_dup(src);1015if (group == NULL) {1016ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CURVE);1017return 0;1018}1019EC_GROUP_free(gctx->gen_group);1020gctx->gen_group = group;1021return 1;1022}10231024static int ec_gen_set_template(void *genctx, void *templ)1025{1026struct ec_gen_ctx *gctx = genctx;1027EC_KEY *ec = templ;1028const EC_GROUP *ec_group;10291030if (!ossl_prov_is_running() || gctx == NULL || ec == NULL)1031return 0;1032if ((ec_group = EC_KEY_get0_group(ec)) == NULL)1033return 0;1034return ec_gen_set_group(gctx, ec_group);1035}10361037#define COPY_INT_PARAM(params, key, val) \1038p = OSSL_PARAM_locate_const(params, key); \1039if (p != NULL && !OSSL_PARAM_get_int(p, &val)) \1040goto err;10411042#define COPY_UTF8_PARAM(params, key, val) \1043p = OSSL_PARAM_locate_const(params, key); \1044if (p != NULL) { \1045if (p->data_type != OSSL_PARAM_UTF8_STRING) \1046goto err; \1047OPENSSL_free(val); \1048val = OPENSSL_strdup(p->data); \1049if (val == NULL) \1050goto err; \1051}10521053#define COPY_OCTET_PARAM(params, key, val, len) \1054p = OSSL_PARAM_locate_const(params, key); \1055if (p != NULL) { \1056if (p->data_type != OSSL_PARAM_OCTET_STRING) \1057goto err; \1058OPENSSL_free(val); \1059len = p->data_size; \1060val = OPENSSL_memdup(p->data, p->data_size); \1061if (val == NULL) \1062goto err; \1063}10641065#define COPY_BN_PARAM(params, key, bn) \1066p = OSSL_PARAM_locate_const(params, key); \1067if (p != NULL) { \1068if (bn == NULL) \1069bn = BN_new(); \1070if (bn == NULL || !OSSL_PARAM_get_BN(p, &bn)) \1071goto err; \1072}10731074static int ec_gen_set_params(void *genctx, const OSSL_PARAM params[])1075{1076int ret = 0;1077struct ec_gen_ctx *gctx = genctx;1078const OSSL_PARAM *p;10791080if (!OSSL_FIPS_IND_SET_CTX_PARAM(gctx, OSSL_FIPS_IND_SETTABLE0, params,1081OSSL_PKEY_PARAM_FIPS_KEY_CHECK))1082goto err;10831084COPY_INT_PARAM(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, gctx->ecdh_mode);10851086COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_GROUP_NAME, gctx->group_name);1087COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_FIELD_TYPE, gctx->field_type);1088COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_ENCODING, gctx->encoding);1089COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, gctx->pt_format);1090COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE, gctx->group_check);10911092COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_P, gctx->p);1093COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_A, gctx->a);1094COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_B, gctx->b);1095COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_ORDER, gctx->order);1096COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_COFACTOR, gctx->cofactor);10971098COPY_OCTET_PARAM(params, OSSL_PKEY_PARAM_EC_SEED, gctx->seed, gctx->seed_len);1099COPY_OCTET_PARAM(params, OSSL_PKEY_PARAM_EC_GENERATOR, gctx->gen,1100gctx->gen_len);11011102COPY_OCTET_PARAM(params, OSSL_PKEY_PARAM_DHKEM_IKM, gctx->dhkem_ikm,1103gctx->dhkem_ikmlen);11041105ret = 1;1106err:1107return ret;1108}11091110static int ec_gen_set_group_from_params(struct ec_gen_ctx *gctx)1111{1112int ret = 0;1113OSSL_PARAM_BLD *bld;1114OSSL_PARAM *params = NULL;1115EC_GROUP *group = NULL;11161117bld = OSSL_PARAM_BLD_new();1118if (bld == NULL)1119return 0;11201121if (gctx->encoding != NULL1122&& !OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_EC_ENCODING,1123gctx->encoding, 0))1124goto err;11251126if (gctx->pt_format != NULL1127&& !OSSL_PARAM_BLD_push_utf8_string(bld,1128OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,1129gctx->pt_format, 0))1130goto err;11311132if (gctx->group_name != NULL) {1133if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME,1134gctx->group_name, 0))1135goto err;1136/* Ignore any other parameters if there is a group name */1137goto build;1138} else if (gctx->field_type != NULL) {1139if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_EC_FIELD_TYPE,1140gctx->field_type, 0))1141goto err;1142} else {1143goto err;1144}1145if (gctx->p == NULL1146|| gctx->a == NULL1147|| gctx->b == NULL1148|| gctx->order == NULL1149|| !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_P, gctx->p)1150|| !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_A, gctx->a)1151|| !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_B, gctx->b)1152|| !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_ORDER, gctx->order))1153goto err;11541155if (gctx->cofactor != NULL1156&& !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_COFACTOR,1157gctx->cofactor))1158goto err;11591160if (gctx->seed != NULL1161&& !OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_EC_SEED,1162gctx->seed, gctx->seed_len))1163goto err;11641165if (gctx->gen == NULL1166|| !OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_EC_GENERATOR,1167gctx->gen, gctx->gen_len))1168goto err;1169build:1170params = OSSL_PARAM_BLD_to_param(bld);1171if (params == NULL)1172goto err;1173group = EC_GROUP_new_from_params(params, gctx->libctx, NULL);1174if (group == NULL)1175goto err;11761177EC_GROUP_free(gctx->gen_group);1178gctx->gen_group = group;11791180ret = 1;1181err:1182OSSL_PARAM_free(params);1183OSSL_PARAM_BLD_free(bld);1184return ret;1185}11861187static const OSSL_PARAM *ec_gen_settable_params(ossl_unused void *genctx,1188ossl_unused void *provctx)1189{1190static OSSL_PARAM settable[] = {1191OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),1192OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),1193OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0),1194OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0),1195OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_FIELD_TYPE, NULL, 0),1196OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_P, NULL, 0),1197OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_A, NULL, 0),1198OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_B, NULL, 0),1199OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_GENERATOR, NULL, 0),1200OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_ORDER, NULL, 0),1201OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_COFACTOR, NULL, 0),1202OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0),1203OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM, NULL, 0),1204OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_PKEY_PARAM_FIPS_KEY_CHECK)1205OSSL_PARAM_END1206};1207return settable;1208}12091210static const OSSL_PARAM *ec_gen_gettable_params(ossl_unused void *genctx,1211ossl_unused void *provctx)1212{1213static const OSSL_PARAM known_ec_gen_gettable_ctx_params[] = {1214OSSL_FIPS_IND_GETTABLE_CTX_PARAM()1215OSSL_PARAM_END1216};1217return known_ec_gen_gettable_ctx_params;1218}12191220static int ec_gen_get_params(void *genctx, OSSL_PARAM *params)1221{1222struct ec_gen_ctx *gctx = genctx;12231224if (gctx == NULL)1225return 0;12261227if (!OSSL_FIPS_IND_GET_CTX_PARAM(gctx, params))1228return 0;12291230return 1;1231}12321233static int ec_gen_assign_group(EC_KEY *ec, EC_GROUP *group)1234{1235if (group == NULL) {1236ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET);1237return 0;1238}1239return EC_KEY_set_group(ec, group) > 0;1240}12411242/*1243* The callback arguments (osslcb & cbarg) are not used by EC_KEY generation1244*/1245static void *ec_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)1246{1247struct ec_gen_ctx *gctx = genctx;1248EC_KEY *ec = NULL;1249int ret = 0;12501251if (!ossl_prov_is_running()1252|| gctx == NULL1253|| (ec = EC_KEY_new_ex(gctx->libctx, NULL)) == NULL)1254return NULL;12551256if (gctx->gen_group == NULL) {1257if (!ec_gen_set_group_from_params(gctx))1258goto err;1259} else {1260if (gctx->encoding != NULL) {1261int flags = ossl_ec_encoding_name2id(gctx->encoding);12621263if (flags < 0)1264goto err;1265EC_GROUP_set_asn1_flag(gctx->gen_group, flags);1266}1267if (gctx->pt_format != NULL) {1268int format = ossl_ec_pt_format_name2id(gctx->pt_format);12691270if (format < 0)1271goto err;1272EC_GROUP_set_point_conversion_form(gctx->gen_group, format);1273}1274}1275#ifdef FIPS_MODULE1276if (!ossl_fips_ind_ec_key_check(OSSL_FIPS_IND_GET(gctx),1277OSSL_FIPS_IND_SETTABLE0, gctx->libctx,1278gctx->gen_group, "EC KeyGen", 1))1279goto err;1280#endif12811282/* We must always assign a group, no matter what */1283ret = ec_gen_assign_group(ec, gctx->gen_group);12841285/* Whether you want it or not, you get a keypair, not just one half */1286if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {1287#ifndef FIPS_MODULE1288if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0)1289ret = ret && ossl_ec_generate_key_dhkem(ec, gctx->dhkem_ikm, gctx->dhkem_ikmlen);1290else1291#endif1292ret = ret && EC_KEY_generate_key(ec);1293}12941295if (gctx->ecdh_mode != -1)1296ret = ret && ossl_ec_set_ecdh_cofactor_mode(ec, gctx->ecdh_mode);12971298if (gctx->group_check != NULL)1299ret = ret && ossl_ec_set_check_group_type_from_name(ec, gctx->group_check);1300#ifdef FIPS_MODULE1301if (ret > 01302&& !ossl_fips_self_testing()1303&& EC_KEY_get0_public_key(ec) != NULL1304&& EC_KEY_get0_private_key(ec) != NULL1305&& EC_KEY_get0_group(ec) != NULL) {1306BN_CTX *bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec));13071308ret = bnctx != NULL && ossl_ec_key_pairwise_check(ec, bnctx);1309BN_CTX_free(bnctx);1310if (ret <= 0)1311ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);1312}1313#endif /* FIPS_MODULE */13141315if (ret)1316return ec;1317err:1318/* Something went wrong, throw the key away */1319EC_KEY_free(ec);1320return NULL;1321}13221323#ifndef FIPS_MODULE1324#ifndef OPENSSL_NO_SM21325/*1326* The callback arguments (osslcb & cbarg) are not used by EC_KEY generation1327*/1328static void *sm2_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)1329{1330struct ec_gen_ctx *gctx = genctx;1331EC_KEY *ec = NULL;1332int ret = 1;13331334if (gctx == NULL1335|| (ec = EC_KEY_new_ex(gctx->libctx, NULL)) == NULL)1336return NULL;13371338if (gctx->gen_group == NULL) {1339if (!ec_gen_set_group_from_params(gctx))1340goto err;1341} else {1342if (gctx->encoding) {1343int flags = ossl_ec_encoding_name2id(gctx->encoding);13441345if (flags < 0)1346goto err;1347EC_GROUP_set_asn1_flag(gctx->gen_group, flags);1348}1349if (gctx->pt_format != NULL) {1350int format = ossl_ec_pt_format_name2id(gctx->pt_format);13511352if (format < 0)1353goto err;1354EC_GROUP_set_point_conversion_form(gctx->gen_group, format);1355}1356}13571358/* We must always assign a group, no matter what */1359ret = ec_gen_assign_group(ec, gctx->gen_group);13601361/* Whether you want it or not, you get a keypair, not just one half */1362if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)1363ret = ret && EC_KEY_generate_key(ec);13641365if (ret)1366return ec;1367err:1368/* Something went wrong, throw the key away */1369EC_KEY_free(ec);1370return NULL;1371}1372#endif1373#endif13741375static void ec_gen_cleanup(void *genctx)1376{1377struct ec_gen_ctx *gctx = genctx;13781379if (gctx == NULL)1380return;13811382OPENSSL_clear_free(gctx->dhkem_ikm, gctx->dhkem_ikmlen);1383EC_GROUP_free(gctx->gen_group);1384BN_free(gctx->p);1385BN_free(gctx->a);1386BN_free(gctx->b);1387BN_free(gctx->order);1388BN_free(gctx->cofactor);1389OPENSSL_free(gctx->group_name);1390OPENSSL_free(gctx->field_type);1391OPENSSL_free(gctx->pt_format);1392OPENSSL_free(gctx->encoding);1393OPENSSL_free(gctx->seed);1394OPENSSL_free(gctx->gen);1395OPENSSL_free(gctx);1396}13971398static void *common_load(const void *reference, size_t reference_sz,1399int sm2_wanted)1400{1401EC_KEY *ec = NULL;14021403if (ossl_prov_is_running() && reference_sz == sizeof(ec)) {1404/* The contents of the reference is the address to our object */1405ec = *(EC_KEY **)reference;14061407if (!common_check_sm2(ec, sm2_wanted))1408return NULL;14091410/* We grabbed, so we detach it */1411*(EC_KEY **)reference = NULL;1412return ec;1413}1414return NULL;1415}14161417static void *ec_load(const void *reference, size_t reference_sz)1418{1419return common_load(reference, reference_sz, 0);1420}14211422#ifndef FIPS_MODULE1423#ifndef OPENSSL_NO_SM21424static void *sm2_load(const void *reference, size_t reference_sz)1425{1426return common_load(reference, reference_sz, 1);1427}1428#endif1429#endif14301431static void *ec_dup(const void *keydata_from, int selection)1432{1433if (ossl_prov_is_running())1434return ossl_ec_key_dup(keydata_from, selection);1435return NULL;1436}14371438const OSSL_DISPATCH ossl_ec_keymgmt_functions[] = {1439{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata },1440{ OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ec_gen_init },1441{ OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE,1442(void (*)(void))ec_gen_set_template },1443{ OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ec_gen_set_params },1444{ OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,1445(void (*)(void))ec_gen_settable_params },1446{ OSSL_FUNC_KEYMGMT_GEN_GET_PARAMS, (void (*)(void))ec_gen_get_params },1447{ OSSL_FUNC_KEYMGMT_GEN_GETTABLE_PARAMS,1448(void (*)(void))ec_gen_gettable_params },1449{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))ec_gen },1450{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ec_gen_cleanup },1451{ OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ec_load },1452{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },1453{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*)(void))ec_get_params },1454{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*)(void))ec_gettable_params },1455{ OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*)(void))ec_set_params },1456{ OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*)(void))ec_settable_params },1457{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },1458{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },1459{ OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))ec_validate },1460{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ec_import },1461{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },1462{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },1463{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },1464{ OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,1465(void (*)(void))ec_query_operation_name },1466{ OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ec_dup },1467OSSL_DISPATCH_END1468};14691470#ifndef FIPS_MODULE1471#ifndef OPENSSL_NO_SM21472const OSSL_DISPATCH ossl_sm2_keymgmt_functions[] = {1473{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))sm2_newdata },1474{ OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))sm2_gen_init },1475{ OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE,1476(void (*)(void))ec_gen_set_template },1477{ OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ec_gen_set_params },1478{ OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,1479(void (*)(void))ec_gen_settable_params },1480{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))sm2_gen },1481{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ec_gen_cleanup },1482{ OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))sm2_load },1483{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },1484{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*)(void))sm2_get_params },1485{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*)(void))sm2_gettable_params },1486{ OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*)(void))ec_set_params },1487{ OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*)(void))sm2_settable_params },1488{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },1489{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },1490{ OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))sm2_validate },1491{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))sm2_import },1492{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },1493{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },1494{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },1495{ OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,1496(void (*)(void))sm2_query_operation_name },1497{ OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ec_dup },1498OSSL_DISPATCH_END1499};1500#endif1501#endif150215031504