xref: /freebsd-src/crypto/openssl/providers/implementations/keymgmt/ec_kmgmt.c (revision b077aed33b7b6aefca7b17ddb250cf521f938613)
1*b077aed3SPierre Pronchery /*
2*b077aed3SPierre Pronchery  * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
3*b077aed3SPierre Pronchery  *
4*b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5*b077aed3SPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6*b077aed3SPierre Pronchery  * in the file LICENSE in the source distribution or at
7*b077aed3SPierre Pronchery  * https://www.openssl.org/source/license.html
8*b077aed3SPierre Pronchery  */
9*b077aed3SPierre Pronchery 
10*b077aed3SPierre Pronchery /*
11*b077aed3SPierre Pronchery  * ECDH/ECDSA low level APIs are deprecated for public use, but still ok for
12*b077aed3SPierre Pronchery  * internal use.
13*b077aed3SPierre Pronchery  */
14*b077aed3SPierre Pronchery #include "internal/deprecated.h"
15*b077aed3SPierre Pronchery 
16*b077aed3SPierre Pronchery #include <string.h>
17*b077aed3SPierre Pronchery #include <openssl/core_dispatch.h>
18*b077aed3SPierre Pronchery #include <openssl/core_names.h>
19*b077aed3SPierre Pronchery #include <openssl/bn.h>
20*b077aed3SPierre Pronchery #include <openssl/err.h>
21*b077aed3SPierre Pronchery #include <openssl/objects.h>
22*b077aed3SPierre Pronchery #include <openssl/proverr.h>
23*b077aed3SPierre Pronchery #include "crypto/bn.h"
24*b077aed3SPierre Pronchery #include "crypto/ec.h"
25*b077aed3SPierre Pronchery #include "prov/implementations.h"
26*b077aed3SPierre Pronchery #include "prov/providercommon.h"
27*b077aed3SPierre Pronchery #include "prov/provider_ctx.h"
28*b077aed3SPierre Pronchery #include "internal/param_build_set.h"
29*b077aed3SPierre Pronchery 
30*b077aed3SPierre Pronchery #ifndef FIPS_MODULE
31*b077aed3SPierre Pronchery # ifndef OPENSSL_NO_SM2
32*b077aed3SPierre Pronchery #  include "crypto/sm2.h"
33*b077aed3SPierre Pronchery # endif
34*b077aed3SPierre Pronchery #endif
35*b077aed3SPierre Pronchery 
36*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_new_fn ec_newdata;
37*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gen_init_fn ec_gen_init;
38*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gen_set_template_fn ec_gen_set_template;
39*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gen_set_params_fn ec_gen_set_params;
40*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gen_settable_params_fn ec_gen_settable_params;
41*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gen_fn ec_gen;
42*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gen_cleanup_fn ec_gen_cleanup;
43*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_load_fn ec_load;
44*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_free_fn ec_freedata;
45*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_get_params_fn ec_get_params;
46*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gettable_params_fn ec_gettable_params;
47*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_set_params_fn ec_set_params;
48*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_settable_params_fn ec_settable_params;
49*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_has_fn ec_has;
50*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_match_fn ec_match;
51*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_validate_fn ec_validate;
52*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_import_fn ec_import;
53*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_import_types_fn ec_import_types;
54*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_export_fn ec_export;
55*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_export_types_fn ec_export_types;
56*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_query_operation_name_fn ec_query_operation_name;
57*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_dup_fn ec_dup;
58*b077aed3SPierre Pronchery #ifndef FIPS_MODULE
59*b077aed3SPierre Pronchery # ifndef OPENSSL_NO_SM2
60*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_new_fn sm2_newdata;
61*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gen_init_fn sm2_gen_init;
62*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gen_fn sm2_gen;
63*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_get_params_fn sm2_get_params;
64*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gettable_params_fn sm2_gettable_params;
65*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_settable_params_fn sm2_settable_params;
66*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_import_fn sm2_import;
67*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_query_operation_name_fn sm2_query_operation_name;
68*b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_validate_fn sm2_validate;
69*b077aed3SPierre Pronchery # endif
70*b077aed3SPierre Pronchery #endif
71*b077aed3SPierre Pronchery 
72*b077aed3SPierre Pronchery #define EC_DEFAULT_MD "SHA256"
73*b077aed3SPierre Pronchery #define EC_POSSIBLE_SELECTIONS                                                 \
74*b077aed3SPierre Pronchery     (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS)
75*b077aed3SPierre Pronchery #define SM2_DEFAULT_MD "SM3"
76*b077aed3SPierre Pronchery 
77*b077aed3SPierre Pronchery static
ec_query_operation_name(int operation_id)78*b077aed3SPierre Pronchery const char *ec_query_operation_name(int operation_id)
79*b077aed3SPierre Pronchery {
80*b077aed3SPierre Pronchery     switch (operation_id) {
81*b077aed3SPierre Pronchery     case OSSL_OP_KEYEXCH:
82*b077aed3SPierre Pronchery         return "ECDH";
83*b077aed3SPierre Pronchery     case OSSL_OP_SIGNATURE:
84*b077aed3SPierre Pronchery         return "ECDSA";
85*b077aed3SPierre Pronchery     }
86*b077aed3SPierre Pronchery     return NULL;
87*b077aed3SPierre Pronchery }
88*b077aed3SPierre Pronchery 
89*b077aed3SPierre Pronchery #ifndef FIPS_MODULE
90*b077aed3SPierre Pronchery # ifndef OPENSSL_NO_SM2
91*b077aed3SPierre Pronchery static
sm2_query_operation_name(int operation_id)92*b077aed3SPierre Pronchery const char *sm2_query_operation_name(int operation_id)
93*b077aed3SPierre Pronchery {
94*b077aed3SPierre Pronchery     switch (operation_id) {
95*b077aed3SPierre Pronchery     case OSSL_OP_SIGNATURE:
96*b077aed3SPierre Pronchery         return "SM2";
97*b077aed3SPierre Pronchery     }
98*b077aed3SPierre Pronchery     return NULL;
99*b077aed3SPierre Pronchery }
100*b077aed3SPierre Pronchery # endif
101*b077aed3SPierre Pronchery #endif
102*b077aed3SPierre Pronchery 
103*b077aed3SPierre Pronchery /*
104*b077aed3SPierre Pronchery  * Callers of key_to_params MUST make sure that domparams_to_params is also
105*b077aed3SPierre Pronchery  * called!
106*b077aed3SPierre Pronchery  *
107*b077aed3SPierre Pronchery  * This function only exports the bare keypair, domain parameters and other
108*b077aed3SPierre Pronchery  * parameters are exported separately.
109*b077aed3SPierre Pronchery  */
110*b077aed3SPierre Pronchery static ossl_inline
key_to_params(const EC_KEY * eckey,OSSL_PARAM_BLD * tmpl,OSSL_PARAM params[],int include_private,unsigned char ** pub_key)111*b077aed3SPierre Pronchery int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl,
112*b077aed3SPierre Pronchery                   OSSL_PARAM params[], int include_private,
113*b077aed3SPierre Pronchery                   unsigned char **pub_key)
114*b077aed3SPierre Pronchery {
115*b077aed3SPierre Pronchery     BIGNUM *x = NULL, *y = NULL;
116*b077aed3SPierre Pronchery     const BIGNUM *priv_key = NULL;
117*b077aed3SPierre Pronchery     const EC_POINT *pub_point = NULL;
118*b077aed3SPierre Pronchery     const EC_GROUP *ecg = NULL;
119*b077aed3SPierre Pronchery     size_t pub_key_len = 0;
120*b077aed3SPierre Pronchery     int ret = 0;
121*b077aed3SPierre Pronchery     BN_CTX *bnctx = NULL;
122*b077aed3SPierre Pronchery 
123*b077aed3SPierre Pronchery     if (eckey == NULL
124*b077aed3SPierre Pronchery         || (ecg = EC_KEY_get0_group(eckey)) == NULL)
125*b077aed3SPierre Pronchery         return 0;
126*b077aed3SPierre Pronchery 
127*b077aed3SPierre Pronchery     priv_key = EC_KEY_get0_private_key(eckey);
128*b077aed3SPierre Pronchery     pub_point = EC_KEY_get0_public_key(eckey);
129*b077aed3SPierre Pronchery 
130*b077aed3SPierre Pronchery     if (pub_point != NULL) {
131*b077aed3SPierre Pronchery         OSSL_PARAM *p = NULL, *px = NULL, *py = NULL;
132*b077aed3SPierre Pronchery         /*
133*b077aed3SPierre Pronchery          * EC_POINT_point2buf() can generate random numbers in some
134*b077aed3SPierre Pronchery          * implementations so we need to ensure we use the correct libctx.
135*b077aed3SPierre Pronchery          */
136*b077aed3SPierre Pronchery         bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eckey));
137*b077aed3SPierre Pronchery         if (bnctx == NULL)
138*b077aed3SPierre Pronchery             goto err;
139*b077aed3SPierre Pronchery 
140*b077aed3SPierre Pronchery 
141*b077aed3SPierre Pronchery         /* If we are doing a get then check first before decoding the point */
142*b077aed3SPierre Pronchery         if (tmpl == NULL) {
143*b077aed3SPierre Pronchery             p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PUB_KEY);
144*b077aed3SPierre Pronchery             px = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_EC_PUB_X);
145*b077aed3SPierre Pronchery             py = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_EC_PUB_Y);
146*b077aed3SPierre Pronchery         }
147*b077aed3SPierre Pronchery 
148*b077aed3SPierre Pronchery         if (p != NULL || tmpl != NULL) {
149*b077aed3SPierre Pronchery             /* convert pub_point to a octet string according to the SECG standard */
150*b077aed3SPierre Pronchery             point_conversion_form_t format = EC_KEY_get_conv_form(eckey);
151*b077aed3SPierre Pronchery 
152*b077aed3SPierre Pronchery             if ((pub_key_len = EC_POINT_point2buf(ecg, pub_point,
153*b077aed3SPierre Pronchery                                                   format,
154*b077aed3SPierre Pronchery                                                   pub_key, bnctx)) == 0
155*b077aed3SPierre Pronchery                 || !ossl_param_build_set_octet_string(tmpl, p,
156*b077aed3SPierre Pronchery                                                       OSSL_PKEY_PARAM_PUB_KEY,
157*b077aed3SPierre Pronchery                                                       *pub_key, pub_key_len))
158*b077aed3SPierre Pronchery                 goto err;
159*b077aed3SPierre Pronchery         }
160*b077aed3SPierre Pronchery         if (px != NULL || py != NULL) {
161*b077aed3SPierre Pronchery             if (px != NULL) {
162*b077aed3SPierre Pronchery                 x = BN_CTX_get(bnctx);
163*b077aed3SPierre Pronchery                 if (x == NULL)
164*b077aed3SPierre Pronchery                     goto err;
165*b077aed3SPierre Pronchery             }
166*b077aed3SPierre Pronchery             if (py != NULL) {
167*b077aed3SPierre Pronchery                 y = BN_CTX_get(bnctx);
168*b077aed3SPierre Pronchery                 if (y == NULL)
169*b077aed3SPierre Pronchery                     goto err;
170*b077aed3SPierre Pronchery             }
171*b077aed3SPierre Pronchery 
172*b077aed3SPierre Pronchery             if (!EC_POINT_get_affine_coordinates(ecg, pub_point, x, y, bnctx))
173*b077aed3SPierre Pronchery                 goto err;
174*b077aed3SPierre Pronchery             if (px != NULL
175*b077aed3SPierre Pronchery                 && !ossl_param_build_set_bn(tmpl, px,
176*b077aed3SPierre Pronchery                                             OSSL_PKEY_PARAM_EC_PUB_X, x))
177*b077aed3SPierre Pronchery                 goto err;
178*b077aed3SPierre Pronchery             if (py != NULL
179*b077aed3SPierre Pronchery                 && !ossl_param_build_set_bn(tmpl, py,
180*b077aed3SPierre Pronchery                                             OSSL_PKEY_PARAM_EC_PUB_Y, y))
181*b077aed3SPierre Pronchery                 goto err;
182*b077aed3SPierre Pronchery         }
183*b077aed3SPierre Pronchery     }
184*b077aed3SPierre Pronchery 
185*b077aed3SPierre Pronchery     if (priv_key != NULL && include_private) {
186*b077aed3SPierre Pronchery         size_t sz;
187*b077aed3SPierre Pronchery         int ecbits;
188*b077aed3SPierre Pronchery 
189*b077aed3SPierre Pronchery         /*
190*b077aed3SPierre Pronchery          * Key import/export should never leak the bit length of the secret
191*b077aed3SPierre Pronchery          * scalar in the key.
192*b077aed3SPierre Pronchery          *
193*b077aed3SPierre Pronchery          * For this reason, on export we use padded BIGNUMs with fixed length.
194*b077aed3SPierre Pronchery          *
195*b077aed3SPierre Pronchery          * When importing we also should make sure that, even if short lived,
196*b077aed3SPierre Pronchery          * the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as
197*b077aed3SPierre Pronchery          * soon as possible, so that any processing of this BIGNUM might opt for
198*b077aed3SPierre Pronchery          * constant time implementations in the backend.
199*b077aed3SPierre Pronchery          *
200*b077aed3SPierre Pronchery          * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have
201*b077aed3SPierre Pronchery          * to preallocate the BIGNUM internal buffer to a fixed public size big
202*b077aed3SPierre Pronchery          * enough that operations performed during the processing never trigger
203*b077aed3SPierre Pronchery          * a realloc which would leak the size of the scalar through memory
204*b077aed3SPierre Pronchery          * accesses.
205*b077aed3SPierre Pronchery          *
206*b077aed3SPierre Pronchery          * Fixed Length
207*b077aed3SPierre Pronchery          * ------------
208*b077aed3SPierre Pronchery          *
209*b077aed3SPierre Pronchery          * The order of the large prime subgroup of the curve is our choice for
210*b077aed3SPierre Pronchery          * a fixed public size, as that is generally the upper bound for
211*b077aed3SPierre Pronchery          * generating a private key in EC cryptosystems and should fit all valid
212*b077aed3SPierre Pronchery          * secret scalars.
213*b077aed3SPierre Pronchery          *
214*b077aed3SPierre Pronchery          * For padding on export we just use the bit length of the order
215*b077aed3SPierre Pronchery          * converted to bytes (rounding up).
216*b077aed3SPierre Pronchery          *
217*b077aed3SPierre Pronchery          * For preallocating the BIGNUM storage we look at the number of "words"
218*b077aed3SPierre Pronchery          * required for the internal representation of the order, and we
219*b077aed3SPierre Pronchery          * preallocate 2 extra "words" in case any of the subsequent processing
220*b077aed3SPierre Pronchery          * might temporarily overflow the order length.
221*b077aed3SPierre Pronchery          */
222*b077aed3SPierre Pronchery         ecbits = EC_GROUP_order_bits(ecg);
223*b077aed3SPierre Pronchery         if (ecbits <= 0)
224*b077aed3SPierre Pronchery             goto err;
225*b077aed3SPierre Pronchery         sz = (ecbits + 7 ) / 8;
226*b077aed3SPierre Pronchery 
227*b077aed3SPierre Pronchery         if (!ossl_param_build_set_bn_pad(tmpl, params,
228*b077aed3SPierre Pronchery                                          OSSL_PKEY_PARAM_PRIV_KEY,
229*b077aed3SPierre Pronchery                                          priv_key, sz))
230*b077aed3SPierre Pronchery             goto err;
231*b077aed3SPierre Pronchery     }
232*b077aed3SPierre Pronchery     ret = 1;
233*b077aed3SPierre Pronchery  err:
234*b077aed3SPierre Pronchery     BN_CTX_free(bnctx);
235*b077aed3SPierre Pronchery     return ret;
236*b077aed3SPierre Pronchery }
237*b077aed3SPierre Pronchery 
238*b077aed3SPierre Pronchery static ossl_inline
otherparams_to_params(const EC_KEY * ec,OSSL_PARAM_BLD * tmpl,OSSL_PARAM params[])239*b077aed3SPierre Pronchery int otherparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl,
240*b077aed3SPierre Pronchery                           OSSL_PARAM params[])
241*b077aed3SPierre Pronchery {
242*b077aed3SPierre Pronchery     int ecdh_cofactor_mode = 0, group_check = 0;
243*b077aed3SPierre Pronchery     const char *name = NULL;
244*b077aed3SPierre Pronchery     point_conversion_form_t format;
245*b077aed3SPierre Pronchery 
246*b077aed3SPierre Pronchery     if (ec == NULL)
247*b077aed3SPierre Pronchery         return 0;
248*b077aed3SPierre Pronchery 
249*b077aed3SPierre Pronchery     format = EC_KEY_get_conv_form(ec);
250*b077aed3SPierre Pronchery     name = ossl_ec_pt_format_id2name((int)format);
251*b077aed3SPierre Pronchery     if (name != NULL
252*b077aed3SPierre Pronchery         && !ossl_param_build_set_utf8_string(tmpl, params,
253*b077aed3SPierre Pronchery                                              OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
254*b077aed3SPierre Pronchery                                              name))
255*b077aed3SPierre Pronchery         return 0;
256*b077aed3SPierre Pronchery 
257*b077aed3SPierre Pronchery     group_check = EC_KEY_get_flags(ec) & EC_FLAG_CHECK_NAMED_GROUP_MASK;
258*b077aed3SPierre Pronchery     name = ossl_ec_check_group_type_id2name(group_check);
259*b077aed3SPierre Pronchery     if (name != NULL
260*b077aed3SPierre Pronchery         && !ossl_param_build_set_utf8_string(tmpl, params,
261*b077aed3SPierre Pronchery                                              OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE,
262*b077aed3SPierre Pronchery                                              name))
263*b077aed3SPierre Pronchery         return 0;
264*b077aed3SPierre Pronchery 
265*b077aed3SPierre Pronchery     if ((EC_KEY_get_enc_flags(ec) & EC_PKEY_NO_PUBKEY) != 0
266*b077aed3SPierre Pronchery             && !ossl_param_build_set_int(tmpl, params,
267*b077aed3SPierre Pronchery                                          OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, 0))
268*b077aed3SPierre Pronchery         return 0;
269*b077aed3SPierre Pronchery 
270*b077aed3SPierre Pronchery     ecdh_cofactor_mode =
271*b077aed3SPierre Pronchery         (EC_KEY_get_flags(ec) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
272*b077aed3SPierre Pronchery     return ossl_param_build_set_int(tmpl, params,
273*b077aed3SPierre Pronchery                                     OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
274*b077aed3SPierre Pronchery                                     ecdh_cofactor_mode);
275*b077aed3SPierre Pronchery }
276*b077aed3SPierre Pronchery 
277*b077aed3SPierre Pronchery static
ec_newdata(void * provctx)278*b077aed3SPierre Pronchery void *ec_newdata(void *provctx)
279*b077aed3SPierre Pronchery {
280*b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
281*b077aed3SPierre Pronchery         return NULL;
282*b077aed3SPierre Pronchery     return EC_KEY_new_ex(PROV_LIBCTX_OF(provctx), NULL);
283*b077aed3SPierre Pronchery }
284*b077aed3SPierre Pronchery 
285*b077aed3SPierre Pronchery #ifndef FIPS_MODULE
286*b077aed3SPierre Pronchery # ifndef OPENSSL_NO_SM2
287*b077aed3SPierre Pronchery static
sm2_newdata(void * provctx)288*b077aed3SPierre Pronchery void *sm2_newdata(void *provctx)
289*b077aed3SPierre Pronchery {
290*b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
291*b077aed3SPierre Pronchery         return NULL;
292*b077aed3SPierre Pronchery     return EC_KEY_new_by_curve_name_ex(PROV_LIBCTX_OF(provctx), NULL, NID_sm2);
293*b077aed3SPierre Pronchery }
294*b077aed3SPierre Pronchery # endif
295*b077aed3SPierre Pronchery #endif
296*b077aed3SPierre Pronchery 
297*b077aed3SPierre Pronchery static
ec_freedata(void * keydata)298*b077aed3SPierre Pronchery void ec_freedata(void *keydata)
299*b077aed3SPierre Pronchery {
300*b077aed3SPierre Pronchery     EC_KEY_free(keydata);
301*b077aed3SPierre Pronchery }
302*b077aed3SPierre Pronchery 
303*b077aed3SPierre Pronchery static
ec_has(const void * keydata,int selection)304*b077aed3SPierre Pronchery int ec_has(const void *keydata, int selection)
305*b077aed3SPierre Pronchery {
306*b077aed3SPierre Pronchery     const EC_KEY *ec = keydata;
307*b077aed3SPierre Pronchery     int ok = 1;
308*b077aed3SPierre Pronchery 
309*b077aed3SPierre Pronchery     if (!ossl_prov_is_running() || ec == NULL)
310*b077aed3SPierre Pronchery         return 0;
311*b077aed3SPierre Pronchery     if ((selection & EC_POSSIBLE_SELECTIONS) == 0)
312*b077aed3SPierre Pronchery         return 1; /* the selection is not missing */
313*b077aed3SPierre Pronchery 
314*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
315*b077aed3SPierre Pronchery         ok = ok && (EC_KEY_get0_public_key(ec) != NULL);
316*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
317*b077aed3SPierre Pronchery         ok = ok && (EC_KEY_get0_private_key(ec) != NULL);
318*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
319*b077aed3SPierre Pronchery         ok = ok && (EC_KEY_get0_group(ec) != NULL);
320*b077aed3SPierre Pronchery     /*
321*b077aed3SPierre Pronchery      * We consider OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS to always be
322*b077aed3SPierre Pronchery      * available, so no extra check is needed other than the previous one
323*b077aed3SPierre Pronchery      * against EC_POSSIBLE_SELECTIONS.
324*b077aed3SPierre Pronchery      */
325*b077aed3SPierre Pronchery     return ok;
326*b077aed3SPierre Pronchery }
327*b077aed3SPierre Pronchery 
ec_match(const void * keydata1,const void * keydata2,int selection)328*b077aed3SPierre Pronchery static int ec_match(const void *keydata1, const void *keydata2, int selection)
329*b077aed3SPierre Pronchery {
330*b077aed3SPierre Pronchery     const EC_KEY *ec1 = keydata1;
331*b077aed3SPierre Pronchery     const EC_KEY *ec2 = keydata2;
332*b077aed3SPierre Pronchery     const EC_GROUP *group_a = EC_KEY_get0_group(ec1);
333*b077aed3SPierre Pronchery     const EC_GROUP *group_b = EC_KEY_get0_group(ec2);
334*b077aed3SPierre Pronchery     BN_CTX *ctx = NULL;
335*b077aed3SPierre Pronchery     int ok = 1;
336*b077aed3SPierre Pronchery 
337*b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
338*b077aed3SPierre Pronchery         return 0;
339*b077aed3SPierre Pronchery 
340*b077aed3SPierre Pronchery     ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec1));
341*b077aed3SPierre Pronchery     if (ctx == NULL)
342*b077aed3SPierre Pronchery         return 0;
343*b077aed3SPierre Pronchery 
344*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
345*b077aed3SPierre Pronchery         ok = ok && group_a != NULL && group_b != NULL
346*b077aed3SPierre Pronchery             && EC_GROUP_cmp(group_a, group_b, ctx) == 0;
347*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
348*b077aed3SPierre Pronchery         int key_checked = 0;
349*b077aed3SPierre Pronchery 
350*b077aed3SPierre Pronchery         if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
351*b077aed3SPierre Pronchery             const EC_POINT *pa = EC_KEY_get0_public_key(ec1);
352*b077aed3SPierre Pronchery             const EC_POINT *pb = EC_KEY_get0_public_key(ec2);
353*b077aed3SPierre Pronchery 
354*b077aed3SPierre Pronchery             if (pa != NULL && pb != NULL) {
355*b077aed3SPierre Pronchery                 ok = ok && EC_POINT_cmp(group_b, pa, pb, ctx) == 0;
356*b077aed3SPierre Pronchery                 key_checked = 1;
357*b077aed3SPierre Pronchery             }
358*b077aed3SPierre Pronchery         }
359*b077aed3SPierre Pronchery         if (!key_checked
360*b077aed3SPierre Pronchery             && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
361*b077aed3SPierre Pronchery             const BIGNUM *pa = EC_KEY_get0_private_key(ec1);
362*b077aed3SPierre Pronchery             const BIGNUM *pb = EC_KEY_get0_private_key(ec2);
363*b077aed3SPierre Pronchery 
364*b077aed3SPierre Pronchery             if (pa != NULL && pb != NULL) {
365*b077aed3SPierre Pronchery                 ok = ok && BN_cmp(pa, pb) == 0;
366*b077aed3SPierre Pronchery                 key_checked = 1;
367*b077aed3SPierre Pronchery             }
368*b077aed3SPierre Pronchery         }
369*b077aed3SPierre Pronchery         ok = ok && key_checked;
370*b077aed3SPierre Pronchery     }
371*b077aed3SPierre Pronchery     BN_CTX_free(ctx);
372*b077aed3SPierre Pronchery     return ok;
373*b077aed3SPierre Pronchery }
374*b077aed3SPierre Pronchery 
common_check_sm2(const EC_KEY * ec,int sm2_wanted)375*b077aed3SPierre Pronchery static int common_check_sm2(const EC_KEY *ec, int sm2_wanted)
376*b077aed3SPierre Pronchery {
377*b077aed3SPierre Pronchery     const EC_GROUP *ecg = NULL;
378*b077aed3SPierre Pronchery 
379*b077aed3SPierre Pronchery     /*
380*b077aed3SPierre Pronchery      * sm2_wanted: import the keys or domparams only on SM2 Curve
381*b077aed3SPierre Pronchery      * !sm2_wanted: import the keys or domparams only not on SM2 Curve
382*b077aed3SPierre Pronchery      */
383*b077aed3SPierre Pronchery     if ((ecg = EC_KEY_get0_group(ec)) == NULL
384*b077aed3SPierre Pronchery         || (sm2_wanted ^ (EC_GROUP_get_curve_name(ecg) == NID_sm2)))
385*b077aed3SPierre Pronchery         return 0;
386*b077aed3SPierre Pronchery     return 1;
387*b077aed3SPierre Pronchery }
388*b077aed3SPierre Pronchery 
389*b077aed3SPierre Pronchery static
common_import(void * keydata,int selection,const OSSL_PARAM params[],int sm2_wanted)390*b077aed3SPierre Pronchery int common_import(void *keydata, int selection, const OSSL_PARAM params[],
391*b077aed3SPierre Pronchery                   int sm2_wanted)
392*b077aed3SPierre Pronchery {
393*b077aed3SPierre Pronchery     EC_KEY *ec = keydata;
394*b077aed3SPierre Pronchery     int ok = 1;
395*b077aed3SPierre Pronchery 
396*b077aed3SPierre Pronchery     if (!ossl_prov_is_running() || ec == NULL)
397*b077aed3SPierre Pronchery         return 0;
398*b077aed3SPierre Pronchery 
399*b077aed3SPierre Pronchery     /*
400*b077aed3SPierre Pronchery      * In this implementation, we can export/import only keydata in the
401*b077aed3SPierre Pronchery      * following combinations:
402*b077aed3SPierre Pronchery      *   - domain parameters (+optional other params)
403*b077aed3SPierre Pronchery      *   - public key with associated domain parameters (+optional other params)
404*b077aed3SPierre Pronchery      *   - private key with associated domain parameters and optional public key
405*b077aed3SPierre Pronchery      *         (+optional other params)
406*b077aed3SPierre Pronchery      *
407*b077aed3SPierre Pronchery      * This means:
408*b077aed3SPierre Pronchery      *   - domain parameters must always be requested
409*b077aed3SPierre Pronchery      *   - private key must be requested alongside public key
410*b077aed3SPierre Pronchery      *   - other parameters are always optional
411*b077aed3SPierre Pronchery      */
412*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
413*b077aed3SPierre Pronchery         return 0;
414*b077aed3SPierre Pronchery 
415*b077aed3SPierre Pronchery     ok = ok && ossl_ec_group_fromdata(ec, params);
416*b077aed3SPierre Pronchery 
417*b077aed3SPierre Pronchery     if (!common_check_sm2(ec, sm2_wanted))
418*b077aed3SPierre Pronchery         return 0;
419*b077aed3SPierre Pronchery 
420*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
421*b077aed3SPierre Pronchery         int include_private =
422*b077aed3SPierre Pronchery             selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
423*b077aed3SPierre Pronchery 
424*b077aed3SPierre Pronchery         ok = ok && ossl_ec_key_fromdata(ec, params, include_private);
425*b077aed3SPierre Pronchery     }
426*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
427*b077aed3SPierre Pronchery         ok = ok && ossl_ec_key_otherparams_fromdata(ec, params);
428*b077aed3SPierre Pronchery 
429*b077aed3SPierre Pronchery     return ok;
430*b077aed3SPierre Pronchery }
431*b077aed3SPierre Pronchery 
432*b077aed3SPierre Pronchery static
ec_import(void * keydata,int selection,const OSSL_PARAM params[])433*b077aed3SPierre Pronchery int ec_import(void *keydata, int selection, const OSSL_PARAM params[])
434*b077aed3SPierre Pronchery {
435*b077aed3SPierre Pronchery     return common_import(keydata, selection, params, 0);
436*b077aed3SPierre Pronchery }
437*b077aed3SPierre Pronchery 
438*b077aed3SPierre Pronchery #ifndef FIPS_MODULE
439*b077aed3SPierre Pronchery # ifndef OPENSSL_NO_SM2
440*b077aed3SPierre Pronchery static
sm2_import(void * keydata,int selection,const OSSL_PARAM params[])441*b077aed3SPierre Pronchery int sm2_import(void *keydata, int selection, const OSSL_PARAM params[])
442*b077aed3SPierre Pronchery {
443*b077aed3SPierre Pronchery     return common_import(keydata, selection, params, 1);
444*b077aed3SPierre Pronchery }
445*b077aed3SPierre Pronchery # endif
446*b077aed3SPierre Pronchery #endif
447*b077aed3SPierre Pronchery 
448*b077aed3SPierre Pronchery static
ec_export(void * keydata,int selection,OSSL_CALLBACK * param_cb,void * cbarg)449*b077aed3SPierre Pronchery int ec_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
450*b077aed3SPierre Pronchery               void *cbarg)
451*b077aed3SPierre Pronchery {
452*b077aed3SPierre Pronchery     EC_KEY *ec = keydata;
453*b077aed3SPierre Pronchery     OSSL_PARAM_BLD *tmpl = NULL;
454*b077aed3SPierre Pronchery     OSSL_PARAM *params = NULL;
455*b077aed3SPierre Pronchery     unsigned char *pub_key = NULL, *genbuf = NULL;
456*b077aed3SPierre Pronchery     BN_CTX *bnctx = NULL;
457*b077aed3SPierre Pronchery     int ok = 1;
458*b077aed3SPierre Pronchery 
459*b077aed3SPierre Pronchery     if (!ossl_prov_is_running() || ec == NULL)
460*b077aed3SPierre Pronchery         return 0;
461*b077aed3SPierre Pronchery 
462*b077aed3SPierre Pronchery     /*
463*b077aed3SPierre Pronchery      * In this implementation, we can export/import only keydata in the
464*b077aed3SPierre Pronchery      * following combinations:
465*b077aed3SPierre Pronchery      *   - domain parameters (+optional other params)
466*b077aed3SPierre Pronchery      *   - public key with associated domain parameters (+optional other params)
467*b077aed3SPierre Pronchery      *   - private key with associated public key and domain parameters
468*b077aed3SPierre Pronchery      *         (+optional other params)
469*b077aed3SPierre Pronchery      *
470*b077aed3SPierre Pronchery      * This means:
471*b077aed3SPierre Pronchery      *   - domain parameters must always be requested
472*b077aed3SPierre Pronchery      *   - private key must be requested alongside public key
473*b077aed3SPierre Pronchery      *   - other parameters are always optional
474*b077aed3SPierre Pronchery      */
475*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
476*b077aed3SPierre Pronchery         return 0;
477*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
478*b077aed3SPierre Pronchery             && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
479*b077aed3SPierre Pronchery         return 0;
480*b077aed3SPierre Pronchery 
481*b077aed3SPierre Pronchery     tmpl = OSSL_PARAM_BLD_new();
482*b077aed3SPierre Pronchery     if (tmpl == NULL)
483*b077aed3SPierre Pronchery         return 0;
484*b077aed3SPierre Pronchery 
485*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
486*b077aed3SPierre Pronchery         bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec));
487*b077aed3SPierre Pronchery         if (bnctx == NULL) {
488*b077aed3SPierre Pronchery             ok = 0;
489*b077aed3SPierre Pronchery             goto end;
490*b077aed3SPierre Pronchery         }
491*b077aed3SPierre Pronchery         BN_CTX_start(bnctx);
492*b077aed3SPierre Pronchery         ok = ok && ossl_ec_group_todata(EC_KEY_get0_group(ec), tmpl, NULL,
493*b077aed3SPierre Pronchery                                         ossl_ec_key_get_libctx(ec),
494*b077aed3SPierre Pronchery                                         ossl_ec_key_get0_propq(ec),
495*b077aed3SPierre Pronchery                                         bnctx, &genbuf);
496*b077aed3SPierre Pronchery     }
497*b077aed3SPierre Pronchery 
498*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
499*b077aed3SPierre Pronchery         int include_private =
500*b077aed3SPierre Pronchery             selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
501*b077aed3SPierre Pronchery 
502*b077aed3SPierre Pronchery         ok = ok && key_to_params(ec, tmpl, NULL, include_private, &pub_key);
503*b077aed3SPierre Pronchery     }
504*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
505*b077aed3SPierre Pronchery         ok = ok && otherparams_to_params(ec, tmpl, NULL);
506*b077aed3SPierre Pronchery 
507*b077aed3SPierre Pronchery     if (!ok || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {
508*b077aed3SPierre Pronchery         ok = 0;
509*b077aed3SPierre Pronchery         goto end;
510*b077aed3SPierre Pronchery     }
511*b077aed3SPierre Pronchery 
512*b077aed3SPierre Pronchery     ok = param_cb(params, cbarg);
513*b077aed3SPierre Pronchery     OSSL_PARAM_free(params);
514*b077aed3SPierre Pronchery end:
515*b077aed3SPierre Pronchery     OSSL_PARAM_BLD_free(tmpl);
516*b077aed3SPierre Pronchery     OPENSSL_free(pub_key);
517*b077aed3SPierre Pronchery     OPENSSL_free(genbuf);
518*b077aed3SPierre Pronchery     BN_CTX_end(bnctx);
519*b077aed3SPierre Pronchery     BN_CTX_free(bnctx);
520*b077aed3SPierre Pronchery     return ok;
521*b077aed3SPierre Pronchery }
522*b077aed3SPierre Pronchery 
523*b077aed3SPierre Pronchery /* IMEXPORT = IMPORT + EXPORT */
524*b077aed3SPierre Pronchery 
525*b077aed3SPierre Pronchery # define EC_IMEXPORTABLE_DOM_PARAMETERS                                        \
526*b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),               \
527*b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0),              \
528*b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0),\
529*b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_FIELD_TYPE, NULL, 0),            \
530*b077aed3SPierre Pronchery     OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_P, NULL, 0),                              \
531*b077aed3SPierre Pronchery     OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_A, NULL, 0),                              \
532*b077aed3SPierre Pronchery     OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_B, NULL, 0),                              \
533*b077aed3SPierre Pronchery     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_GENERATOR, NULL, 0),            \
534*b077aed3SPierre Pronchery     OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_ORDER, NULL, 0),                          \
535*b077aed3SPierre Pronchery     OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_COFACTOR, NULL, 0),                       \
536*b077aed3SPierre Pronchery     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0),                 \
537*b077aed3SPierre Pronchery     OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, NULL)
538*b077aed3SPierre Pronchery 
539*b077aed3SPierre Pronchery # define EC_IMEXPORTABLE_PUBLIC_KEY                                            \
540*b077aed3SPierre Pronchery     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0)
541*b077aed3SPierre Pronchery # define EC_IMEXPORTABLE_PRIVATE_KEY                                           \
542*b077aed3SPierre Pronchery     OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
543*b077aed3SPierre Pronchery # define EC_IMEXPORTABLE_OTHER_PARAMETERS                                      \
544*b077aed3SPierre Pronchery     OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),                   \
545*b077aed3SPierre Pronchery     OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL)
546*b077aed3SPierre Pronchery 
547*b077aed3SPierre Pronchery /*
548*b077aed3SPierre Pronchery  * Include all the possible combinations of OSSL_PARAM arrays for
549*b077aed3SPierre Pronchery  * ec_imexport_types().
550*b077aed3SPierre Pronchery  *
551*b077aed3SPierre Pronchery  * They are in a separate file as it is ~100 lines of unreadable and
552*b077aed3SPierre Pronchery  * uninteresting machine generated stuff.
553*b077aed3SPierre Pronchery  */
554*b077aed3SPierre Pronchery #include "ec_kmgmt_imexport.inc"
555*b077aed3SPierre Pronchery 
556*b077aed3SPierre Pronchery static ossl_inline
ec_imexport_types(int selection)557*b077aed3SPierre Pronchery const OSSL_PARAM *ec_imexport_types(int selection)
558*b077aed3SPierre Pronchery {
559*b077aed3SPierre Pronchery     int type_select = 0;
560*b077aed3SPierre Pronchery 
561*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
562*b077aed3SPierre Pronchery         type_select += 1;
563*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
564*b077aed3SPierre Pronchery         type_select += 2;
565*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
566*b077aed3SPierre Pronchery         type_select += 4;
567*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
568*b077aed3SPierre Pronchery         type_select += 8;
569*b077aed3SPierre Pronchery     return ec_types[type_select];
570*b077aed3SPierre Pronchery }
571*b077aed3SPierre Pronchery 
572*b077aed3SPierre Pronchery static
ec_import_types(int selection)573*b077aed3SPierre Pronchery const OSSL_PARAM *ec_import_types(int selection)
574*b077aed3SPierre Pronchery {
575*b077aed3SPierre Pronchery     return ec_imexport_types(selection);
576*b077aed3SPierre Pronchery }
577*b077aed3SPierre Pronchery 
578*b077aed3SPierre Pronchery static
ec_export_types(int selection)579*b077aed3SPierre Pronchery const OSSL_PARAM *ec_export_types(int selection)
580*b077aed3SPierre Pronchery {
581*b077aed3SPierre Pronchery     return ec_imexport_types(selection);
582*b077aed3SPierre Pronchery }
583*b077aed3SPierre Pronchery 
ec_get_ecm_params(const EC_GROUP * group,OSSL_PARAM params[])584*b077aed3SPierre Pronchery static int ec_get_ecm_params(const EC_GROUP *group, OSSL_PARAM params[])
585*b077aed3SPierre Pronchery {
586*b077aed3SPierre Pronchery #ifdef OPENSSL_NO_EC2M
587*b077aed3SPierre Pronchery     return 1;
588*b077aed3SPierre Pronchery #else
589*b077aed3SPierre Pronchery     int ret = 0, m;
590*b077aed3SPierre Pronchery     unsigned int k1 = 0, k2 = 0, k3 = 0;
591*b077aed3SPierre Pronchery     int basis_nid;
592*b077aed3SPierre Pronchery     const char *basis_name = NULL;
593*b077aed3SPierre Pronchery     int fid = EC_GROUP_get_field_type(group);
594*b077aed3SPierre Pronchery 
595*b077aed3SPierre Pronchery     if (fid != NID_X9_62_characteristic_two_field)
596*b077aed3SPierre Pronchery         return 1;
597*b077aed3SPierre Pronchery 
598*b077aed3SPierre Pronchery     basis_nid = EC_GROUP_get_basis_type(group);
599*b077aed3SPierre Pronchery     if (basis_nid == NID_X9_62_tpBasis)
600*b077aed3SPierre Pronchery         basis_name = SN_X9_62_tpBasis;
601*b077aed3SPierre Pronchery     else if (basis_nid == NID_X9_62_ppBasis)
602*b077aed3SPierre Pronchery         basis_name = SN_X9_62_ppBasis;
603*b077aed3SPierre Pronchery     else
604*b077aed3SPierre Pronchery         goto err;
605*b077aed3SPierre Pronchery 
606*b077aed3SPierre Pronchery     m = EC_GROUP_get_degree(group);
607*b077aed3SPierre Pronchery     if (!ossl_param_build_set_int(NULL, params, OSSL_PKEY_PARAM_EC_CHAR2_M, m)
608*b077aed3SPierre Pronchery         || !ossl_param_build_set_utf8_string(NULL, params,
609*b077aed3SPierre Pronchery                                              OSSL_PKEY_PARAM_EC_CHAR2_TYPE,
610*b077aed3SPierre Pronchery                                              basis_name))
611*b077aed3SPierre Pronchery         goto err;
612*b077aed3SPierre Pronchery 
613*b077aed3SPierre Pronchery     if (basis_nid == NID_X9_62_tpBasis) {
614*b077aed3SPierre Pronchery         if (!EC_GROUP_get_trinomial_basis(group, &k1)
615*b077aed3SPierre Pronchery             || !ossl_param_build_set_int(NULL, params,
616*b077aed3SPierre Pronchery                                          OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS,
617*b077aed3SPierre Pronchery                                          (int)k1))
618*b077aed3SPierre Pronchery             goto err;
619*b077aed3SPierre Pronchery     } else {
620*b077aed3SPierre Pronchery         if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3)
621*b077aed3SPierre Pronchery             || !ossl_param_build_set_int(NULL, params,
622*b077aed3SPierre Pronchery                                          OSSL_PKEY_PARAM_EC_CHAR2_PP_K1, (int)k1)
623*b077aed3SPierre Pronchery             || !ossl_param_build_set_int(NULL, params,
624*b077aed3SPierre Pronchery                                          OSSL_PKEY_PARAM_EC_CHAR2_PP_K2, (int)k2)
625*b077aed3SPierre Pronchery             || !ossl_param_build_set_int(NULL, params,
626*b077aed3SPierre Pronchery                                          OSSL_PKEY_PARAM_EC_CHAR2_PP_K3, (int)k3))
627*b077aed3SPierre Pronchery             goto err;
628*b077aed3SPierre Pronchery     }
629*b077aed3SPierre Pronchery     ret = 1;
630*b077aed3SPierre Pronchery err:
631*b077aed3SPierre Pronchery     return ret;
632*b077aed3SPierre Pronchery #endif /* OPENSSL_NO_EC2M */
633*b077aed3SPierre Pronchery }
634*b077aed3SPierre Pronchery 
635*b077aed3SPierre Pronchery static
common_get_params(void * key,OSSL_PARAM params[],int sm2)636*b077aed3SPierre Pronchery int common_get_params(void *key, OSSL_PARAM params[], int sm2)
637*b077aed3SPierre Pronchery {
638*b077aed3SPierre Pronchery     int ret = 0;
639*b077aed3SPierre Pronchery     EC_KEY *eck = key;
640*b077aed3SPierre Pronchery     const EC_GROUP *ecg = NULL;
641*b077aed3SPierre Pronchery     OSSL_PARAM *p;
642*b077aed3SPierre Pronchery     unsigned char *pub_key = NULL, *genbuf = NULL;
643*b077aed3SPierre Pronchery     OSSL_LIB_CTX *libctx;
644*b077aed3SPierre Pronchery     const char *propq;
645*b077aed3SPierre Pronchery     BN_CTX *bnctx = NULL;
646*b077aed3SPierre Pronchery 
647*b077aed3SPierre Pronchery     ecg = EC_KEY_get0_group(eck);
648*b077aed3SPierre Pronchery     if (ecg == NULL) {
649*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET);
650*b077aed3SPierre Pronchery         return 0;
651*b077aed3SPierre Pronchery     }
652*b077aed3SPierre Pronchery 
653*b077aed3SPierre Pronchery     libctx = ossl_ec_key_get_libctx(eck);
654*b077aed3SPierre Pronchery     propq = ossl_ec_key_get0_propq(eck);
655*b077aed3SPierre Pronchery 
656*b077aed3SPierre Pronchery     bnctx = BN_CTX_new_ex(libctx);
657*b077aed3SPierre Pronchery     if (bnctx == NULL)
658*b077aed3SPierre Pronchery         return 0;
659*b077aed3SPierre Pronchery     BN_CTX_start(bnctx);
660*b077aed3SPierre Pronchery 
661*b077aed3SPierre Pronchery     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
662*b077aed3SPierre Pronchery         && !OSSL_PARAM_set_int(p, ECDSA_size(eck)))
663*b077aed3SPierre Pronchery         goto err;
664*b077aed3SPierre Pronchery     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
665*b077aed3SPierre Pronchery         && !OSSL_PARAM_set_int(p, EC_GROUP_order_bits(ecg)))
666*b077aed3SPierre Pronchery         goto err;
667*b077aed3SPierre Pronchery     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL) {
668*b077aed3SPierre Pronchery         int ecbits, sec_bits;
669*b077aed3SPierre Pronchery 
670*b077aed3SPierre Pronchery         ecbits = EC_GROUP_order_bits(ecg);
671*b077aed3SPierre Pronchery 
672*b077aed3SPierre Pronchery         /*
673*b077aed3SPierre Pronchery          * The following estimates are based on the values published
674*b077aed3SPierre Pronchery          * in Table 2 of "NIST Special Publication 800-57 Part 1 Revision 4"
675*b077aed3SPierre Pronchery          * at http://dx.doi.org/10.6028/NIST.SP.800-57pt1r4 .
676*b077aed3SPierre Pronchery          *
677*b077aed3SPierre Pronchery          * Note that the above reference explicitly categorizes algorithms in a
678*b077aed3SPierre Pronchery          * discrete set of values {80, 112, 128, 192, 256}, and that it is
679*b077aed3SPierre Pronchery          * relevant only for NIST approved Elliptic Curves, while OpenSSL
680*b077aed3SPierre Pronchery          * applies the same logic also to other curves.
681*b077aed3SPierre Pronchery          *
682*b077aed3SPierre Pronchery          * Classifications produced by other standardazing bodies might differ,
683*b077aed3SPierre Pronchery          * so the results provided for "bits of security" by this provider are
684*b077aed3SPierre Pronchery          * to be considered merely indicative, and it is the users'
685*b077aed3SPierre Pronchery          * responsibility to compare these values against the normative
686*b077aed3SPierre Pronchery          * references that may be relevant for their intent and purposes.
687*b077aed3SPierre Pronchery          */
688*b077aed3SPierre Pronchery         if (ecbits >= 512)
689*b077aed3SPierre Pronchery             sec_bits = 256;
690*b077aed3SPierre Pronchery         else if (ecbits >= 384)
691*b077aed3SPierre Pronchery             sec_bits = 192;
692*b077aed3SPierre Pronchery         else if (ecbits >= 256)
693*b077aed3SPierre Pronchery             sec_bits = 128;
694*b077aed3SPierre Pronchery         else if (ecbits >= 224)
695*b077aed3SPierre Pronchery             sec_bits = 112;
696*b077aed3SPierre Pronchery         else if (ecbits >= 160)
697*b077aed3SPierre Pronchery             sec_bits = 80;
698*b077aed3SPierre Pronchery         else
699*b077aed3SPierre Pronchery             sec_bits = ecbits / 2;
700*b077aed3SPierre Pronchery 
701*b077aed3SPierre Pronchery         if (!OSSL_PARAM_set_int(p, sec_bits))
702*b077aed3SPierre Pronchery             goto err;
703*b077aed3SPierre Pronchery     }
704*b077aed3SPierre Pronchery 
705*b077aed3SPierre Pronchery     if ((p = OSSL_PARAM_locate(params,
706*b077aed3SPierre Pronchery                                OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS))
707*b077aed3SPierre Pronchery             != NULL) {
708*b077aed3SPierre Pronchery         int explicitparams = EC_KEY_decoded_from_explicit_params(eck);
709*b077aed3SPierre Pronchery 
710*b077aed3SPierre Pronchery         if (explicitparams < 0
711*b077aed3SPierre Pronchery              || !OSSL_PARAM_set_int(p, explicitparams))
712*b077aed3SPierre Pronchery             goto err;
713*b077aed3SPierre Pronchery     }
714*b077aed3SPierre Pronchery 
715*b077aed3SPierre Pronchery     if (!sm2) {
716*b077aed3SPierre Pronchery         if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL
717*b077aed3SPierre Pronchery                 && !OSSL_PARAM_set_utf8_string(p, EC_DEFAULT_MD))
718*b077aed3SPierre Pronchery             goto err;
719*b077aed3SPierre Pronchery     } else {
720*b077aed3SPierre Pronchery         if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL
721*b077aed3SPierre Pronchery                 && !OSSL_PARAM_set_utf8_string(p, SM2_DEFAULT_MD))
722*b077aed3SPierre Pronchery             goto err;
723*b077aed3SPierre Pronchery     }
724*b077aed3SPierre Pronchery 
725*b077aed3SPierre Pronchery     /* SM2 doesn't support this PARAM */
726*b077aed3SPierre Pronchery     if (!sm2) {
727*b077aed3SPierre Pronchery         p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
728*b077aed3SPierre Pronchery         if (p != NULL) {
729*b077aed3SPierre Pronchery             int ecdh_cofactor_mode = 0;
730*b077aed3SPierre Pronchery 
731*b077aed3SPierre Pronchery             ecdh_cofactor_mode =
732*b077aed3SPierre Pronchery                 (EC_KEY_get_flags(eck) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
733*b077aed3SPierre Pronchery 
734*b077aed3SPierre Pronchery             if (!OSSL_PARAM_set_int(p, ecdh_cofactor_mode))
735*b077aed3SPierre Pronchery                 goto err;
736*b077aed3SPierre Pronchery         }
737*b077aed3SPierre Pronchery     }
738*b077aed3SPierre Pronchery     if ((p = OSSL_PARAM_locate(params,
739*b077aed3SPierre Pronchery                                OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL) {
740*b077aed3SPierre Pronchery         const EC_POINT *ecp = EC_KEY_get0_public_key(key);
741*b077aed3SPierre Pronchery 
742*b077aed3SPierre Pronchery         if (ecp == NULL) {
743*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
744*b077aed3SPierre Pronchery             goto err;
745*b077aed3SPierre Pronchery         }
746*b077aed3SPierre Pronchery         p->return_size = EC_POINT_point2oct(ecg, ecp,
747*b077aed3SPierre Pronchery                                             POINT_CONVERSION_UNCOMPRESSED,
748*b077aed3SPierre Pronchery                                             p->data, p->data_size, bnctx);
749*b077aed3SPierre Pronchery         if (p->return_size == 0)
750*b077aed3SPierre Pronchery             goto err;
751*b077aed3SPierre Pronchery     }
752*b077aed3SPierre Pronchery 
753*b077aed3SPierre Pronchery     ret = ec_get_ecm_params(ecg, params)
754*b077aed3SPierre Pronchery           && ossl_ec_group_todata(ecg, NULL, params, libctx, propq, bnctx,
755*b077aed3SPierre Pronchery                                   &genbuf)
756*b077aed3SPierre Pronchery           && key_to_params(eck, NULL, params, 1, &pub_key)
757*b077aed3SPierre Pronchery           && otherparams_to_params(eck, NULL, params);
758*b077aed3SPierre Pronchery err:
759*b077aed3SPierre Pronchery     OPENSSL_free(genbuf);
760*b077aed3SPierre Pronchery     OPENSSL_free(pub_key);
761*b077aed3SPierre Pronchery     BN_CTX_end(bnctx);
762*b077aed3SPierre Pronchery     BN_CTX_free(bnctx);
763*b077aed3SPierre Pronchery     return ret;
764*b077aed3SPierre Pronchery }
765*b077aed3SPierre Pronchery 
766*b077aed3SPierre Pronchery static
ec_get_params(void * key,OSSL_PARAM params[])767*b077aed3SPierre Pronchery int ec_get_params(void *key, OSSL_PARAM params[])
768*b077aed3SPierre Pronchery {
769*b077aed3SPierre Pronchery     return common_get_params(key, params, 0);
770*b077aed3SPierre Pronchery }
771*b077aed3SPierre Pronchery 
772*b077aed3SPierre Pronchery #ifndef OPENSSL_NO_EC2M
773*b077aed3SPierre Pronchery # define EC2M_GETTABLE_DOM_PARAMS                                              \
774*b077aed3SPierre Pronchery         OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_M, NULL),                      \
775*b077aed3SPierre Pronchery         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_CHAR2_TYPE, NULL, 0),        \
776*b077aed3SPierre Pronchery         OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS, NULL),               \
777*b077aed3SPierre Pronchery         OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K1, NULL),                  \
778*b077aed3SPierre Pronchery         OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K2, NULL),                  \
779*b077aed3SPierre Pronchery         OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K3, NULL),
780*b077aed3SPierre Pronchery #else
781*b077aed3SPierre Pronchery # define EC2M_GETTABLE_DOM_PARAMS
782*b077aed3SPierre Pronchery #endif
783*b077aed3SPierre Pronchery 
784*b077aed3SPierre Pronchery static const OSSL_PARAM ec_known_gettable_params[] = {
785*b077aed3SPierre Pronchery     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
786*b077aed3SPierre Pronchery     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
787*b077aed3SPierre Pronchery     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
788*b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0),
789*b077aed3SPierre Pronchery     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
790*b077aed3SPierre Pronchery     OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, NULL),
791*b077aed3SPierre Pronchery     EC_IMEXPORTABLE_DOM_PARAMETERS,
792*b077aed3SPierre Pronchery     EC2M_GETTABLE_DOM_PARAMS
793*b077aed3SPierre Pronchery     EC_IMEXPORTABLE_PUBLIC_KEY,
794*b077aed3SPierre Pronchery     OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0),
795*b077aed3SPierre Pronchery     OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0),
796*b077aed3SPierre Pronchery     EC_IMEXPORTABLE_PRIVATE_KEY,
797*b077aed3SPierre Pronchery     EC_IMEXPORTABLE_OTHER_PARAMETERS,
798*b077aed3SPierre Pronchery     OSSL_PARAM_END
799*b077aed3SPierre Pronchery };
800*b077aed3SPierre Pronchery 
801*b077aed3SPierre Pronchery static
ec_gettable_params(void * provctx)802*b077aed3SPierre Pronchery const OSSL_PARAM *ec_gettable_params(void *provctx)
803*b077aed3SPierre Pronchery {
804*b077aed3SPierre Pronchery     return ec_known_gettable_params;
805*b077aed3SPierre Pronchery }
806*b077aed3SPierre Pronchery 
807*b077aed3SPierre Pronchery static const OSSL_PARAM ec_known_settable_params[] = {
808*b077aed3SPierre Pronchery     OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
809*b077aed3SPierre Pronchery     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
810*b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0),
811*b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0),
812*b077aed3SPierre Pronchery     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0),
813*b077aed3SPierre Pronchery     OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL),
814*b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE, NULL, 0),
815*b077aed3SPierre Pronchery     OSSL_PARAM_END
816*b077aed3SPierre Pronchery };
817*b077aed3SPierre Pronchery 
818*b077aed3SPierre Pronchery static
ec_settable_params(void * provctx)819*b077aed3SPierre Pronchery const OSSL_PARAM *ec_settable_params(void *provctx)
820*b077aed3SPierre Pronchery {
821*b077aed3SPierre Pronchery     return ec_known_settable_params;
822*b077aed3SPierre Pronchery }
823*b077aed3SPierre Pronchery 
824*b077aed3SPierre Pronchery static
ec_set_params(void * key,const OSSL_PARAM params[])825*b077aed3SPierre Pronchery int ec_set_params(void *key, const OSSL_PARAM params[])
826*b077aed3SPierre Pronchery {
827*b077aed3SPierre Pronchery     EC_KEY *eck = key;
828*b077aed3SPierre Pronchery     const OSSL_PARAM *p;
829*b077aed3SPierre Pronchery 
830*b077aed3SPierre Pronchery     if (key == NULL)
831*b077aed3SPierre Pronchery         return 0;
832*b077aed3SPierre Pronchery     if (params == NULL)
833*b077aed3SPierre Pronchery         return 1;
834*b077aed3SPierre Pronchery 
835*b077aed3SPierre Pronchery 
836*b077aed3SPierre Pronchery     if (!ossl_ec_group_set_params((EC_GROUP *)EC_KEY_get0_group(key), params))
837*b077aed3SPierre Pronchery         return 0;
838*b077aed3SPierre Pronchery 
839*b077aed3SPierre Pronchery     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
840*b077aed3SPierre Pronchery     if (p != NULL) {
841*b077aed3SPierre Pronchery         BN_CTX *ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(key));
842*b077aed3SPierre Pronchery         int ret = 1;
843*b077aed3SPierre Pronchery 
844*b077aed3SPierre Pronchery         if (ctx == NULL
845*b077aed3SPierre Pronchery                 || p->data_type != OSSL_PARAM_OCTET_STRING
846*b077aed3SPierre Pronchery                 || !EC_KEY_oct2key(key, p->data, p->data_size, ctx))
847*b077aed3SPierre Pronchery             ret = 0;
848*b077aed3SPierre Pronchery         BN_CTX_free(ctx);
849*b077aed3SPierre Pronchery         if (!ret)
850*b077aed3SPierre Pronchery             return 0;
851*b077aed3SPierre Pronchery     }
852*b077aed3SPierre Pronchery 
853*b077aed3SPierre Pronchery     return ossl_ec_key_otherparams_fromdata(eck, params);
854*b077aed3SPierre Pronchery }
855*b077aed3SPierre Pronchery 
856*b077aed3SPierre Pronchery #ifndef FIPS_MODULE
857*b077aed3SPierre Pronchery # ifndef OPENSSL_NO_SM2
858*b077aed3SPierre Pronchery static
sm2_get_params(void * key,OSSL_PARAM params[])859*b077aed3SPierre Pronchery int sm2_get_params(void *key, OSSL_PARAM params[])
860*b077aed3SPierre Pronchery {
861*b077aed3SPierre Pronchery     return common_get_params(key, params, 1);
862*b077aed3SPierre Pronchery }
863*b077aed3SPierre Pronchery 
864*b077aed3SPierre Pronchery static const OSSL_PARAM sm2_known_gettable_params[] = {
865*b077aed3SPierre Pronchery     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
866*b077aed3SPierre Pronchery     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
867*b077aed3SPierre Pronchery     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
868*b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0),
869*b077aed3SPierre Pronchery     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
870*b077aed3SPierre Pronchery     OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, NULL),
871*b077aed3SPierre Pronchery     EC_IMEXPORTABLE_DOM_PARAMETERS,
872*b077aed3SPierre Pronchery     EC_IMEXPORTABLE_PUBLIC_KEY,
873*b077aed3SPierre Pronchery     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0),
874*b077aed3SPierre Pronchery     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0),
875*b077aed3SPierre Pronchery     EC_IMEXPORTABLE_PRIVATE_KEY,
876*b077aed3SPierre Pronchery     OSSL_PARAM_END
877*b077aed3SPierre Pronchery };
878*b077aed3SPierre Pronchery 
879*b077aed3SPierre Pronchery static
sm2_gettable_params(ossl_unused void * provctx)880*b077aed3SPierre Pronchery const OSSL_PARAM *sm2_gettable_params(ossl_unused void *provctx)
881*b077aed3SPierre Pronchery {
882*b077aed3SPierre Pronchery     return sm2_known_gettable_params;
883*b077aed3SPierre Pronchery }
884*b077aed3SPierre Pronchery 
885*b077aed3SPierre Pronchery static const OSSL_PARAM sm2_known_settable_params[] = {
886*b077aed3SPierre Pronchery     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
887*b077aed3SPierre Pronchery     OSSL_PARAM_END
888*b077aed3SPierre Pronchery };
889*b077aed3SPierre Pronchery 
890*b077aed3SPierre Pronchery static
sm2_settable_params(ossl_unused void * provctx)891*b077aed3SPierre Pronchery const OSSL_PARAM *sm2_settable_params(ossl_unused void *provctx)
892*b077aed3SPierre Pronchery {
893*b077aed3SPierre Pronchery     return sm2_known_settable_params;
894*b077aed3SPierre Pronchery }
895*b077aed3SPierre Pronchery 
896*b077aed3SPierre Pronchery static
sm2_validate(const void * keydata,int selection,int checktype)897*b077aed3SPierre Pronchery int sm2_validate(const void *keydata, int selection, int checktype)
898*b077aed3SPierre Pronchery {
899*b077aed3SPierre Pronchery     const EC_KEY *eck = keydata;
900*b077aed3SPierre Pronchery     int ok = 1;
901*b077aed3SPierre Pronchery     BN_CTX *ctx = NULL;
902*b077aed3SPierre Pronchery 
903*b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
904*b077aed3SPierre Pronchery         return 0;
905*b077aed3SPierre Pronchery 
906*b077aed3SPierre Pronchery     if ((selection & EC_POSSIBLE_SELECTIONS) == 0)
907*b077aed3SPierre Pronchery         return 1; /* nothing to validate */
908*b077aed3SPierre Pronchery 
909*b077aed3SPierre Pronchery     ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eck));
910*b077aed3SPierre Pronchery     if  (ctx == NULL)
911*b077aed3SPierre Pronchery         return 0;
912*b077aed3SPierre Pronchery 
913*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
914*b077aed3SPierre Pronchery         ok = ok && EC_GROUP_check(EC_KEY_get0_group(eck), ctx);
915*b077aed3SPierre Pronchery 
916*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
917*b077aed3SPierre Pronchery         if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK)
918*b077aed3SPierre Pronchery             ok = ok && ossl_ec_key_public_check_quick(eck, ctx);
919*b077aed3SPierre Pronchery         else
920*b077aed3SPierre Pronchery             ok = ok && ossl_ec_key_public_check(eck, ctx);
921*b077aed3SPierre Pronchery     }
922*b077aed3SPierre Pronchery 
923*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
924*b077aed3SPierre Pronchery         ok = ok && ossl_sm2_key_private_check(eck);
925*b077aed3SPierre Pronchery 
926*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
927*b077aed3SPierre Pronchery         ok = ok && ossl_ec_key_pairwise_check(eck, ctx);
928*b077aed3SPierre Pronchery 
929*b077aed3SPierre Pronchery     BN_CTX_free(ctx);
930*b077aed3SPierre Pronchery     return ok;
931*b077aed3SPierre Pronchery }
932*b077aed3SPierre Pronchery # endif
933*b077aed3SPierre Pronchery #endif
934*b077aed3SPierre Pronchery 
935*b077aed3SPierre Pronchery static
ec_validate(const void * keydata,int selection,int checktype)936*b077aed3SPierre Pronchery int ec_validate(const void *keydata, int selection, int checktype)
937*b077aed3SPierre Pronchery {
938*b077aed3SPierre Pronchery     const EC_KEY *eck = keydata;
939*b077aed3SPierre Pronchery     int ok = 1;
940*b077aed3SPierre Pronchery     BN_CTX *ctx = NULL;
941*b077aed3SPierre Pronchery 
942*b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
943*b077aed3SPierre Pronchery         return 0;
944*b077aed3SPierre Pronchery 
945*b077aed3SPierre Pronchery     if ((selection & EC_POSSIBLE_SELECTIONS) == 0)
946*b077aed3SPierre Pronchery         return 1; /* nothing to validate */
947*b077aed3SPierre Pronchery 
948*b077aed3SPierre Pronchery     ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eck));
949*b077aed3SPierre Pronchery     if  (ctx == NULL)
950*b077aed3SPierre Pronchery         return 0;
951*b077aed3SPierre Pronchery 
952*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
953*b077aed3SPierre Pronchery         int flags = EC_KEY_get_flags(eck);
954*b077aed3SPierre Pronchery 
955*b077aed3SPierre Pronchery         if ((flags & EC_FLAG_CHECK_NAMED_GROUP) != 0)
956*b077aed3SPierre Pronchery             ok = ok && EC_GROUP_check_named_curve(EC_KEY_get0_group(eck),
957*b077aed3SPierre Pronchery                            (flags & EC_FLAG_CHECK_NAMED_GROUP_NIST) != 0, ctx) > 0;
958*b077aed3SPierre Pronchery         else
959*b077aed3SPierre Pronchery             ok = ok && EC_GROUP_check(EC_KEY_get0_group(eck), ctx);
960*b077aed3SPierre Pronchery     }
961*b077aed3SPierre Pronchery 
962*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
963*b077aed3SPierre Pronchery         if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK)
964*b077aed3SPierre Pronchery             ok = ok && ossl_ec_key_public_check_quick(eck, ctx);
965*b077aed3SPierre Pronchery         else
966*b077aed3SPierre Pronchery             ok = ok && ossl_ec_key_public_check(eck, ctx);
967*b077aed3SPierre Pronchery     }
968*b077aed3SPierre Pronchery 
969*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
970*b077aed3SPierre Pronchery         ok = ok && ossl_ec_key_private_check(eck);
971*b077aed3SPierre Pronchery 
972*b077aed3SPierre Pronchery     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
973*b077aed3SPierre Pronchery         ok = ok && ossl_ec_key_pairwise_check(eck, ctx);
974*b077aed3SPierre Pronchery 
975*b077aed3SPierre Pronchery     BN_CTX_free(ctx);
976*b077aed3SPierre Pronchery     return ok;
977*b077aed3SPierre Pronchery }
978*b077aed3SPierre Pronchery 
979*b077aed3SPierre Pronchery struct ec_gen_ctx {
980*b077aed3SPierre Pronchery     OSSL_LIB_CTX *libctx;
981*b077aed3SPierre Pronchery     char *group_name;
982*b077aed3SPierre Pronchery     char *encoding;
983*b077aed3SPierre Pronchery     char *pt_format;
984*b077aed3SPierre Pronchery     char *group_check;
985*b077aed3SPierre Pronchery     char *field_type;
986*b077aed3SPierre Pronchery     BIGNUM *p, *a, *b, *order, *cofactor;
987*b077aed3SPierre Pronchery     unsigned char *gen, *seed;
988*b077aed3SPierre Pronchery     size_t gen_len, seed_len;
989*b077aed3SPierre Pronchery     int selection;
990*b077aed3SPierre Pronchery     int ecdh_mode;
991*b077aed3SPierre Pronchery     EC_GROUP *gen_group;
992*b077aed3SPierre Pronchery };
993*b077aed3SPierre Pronchery 
ec_gen_init(void * provctx,int selection,const OSSL_PARAM params[])994*b077aed3SPierre Pronchery static void *ec_gen_init(void *provctx, int selection,
995*b077aed3SPierre Pronchery                          const OSSL_PARAM params[])
996*b077aed3SPierre Pronchery {
997*b077aed3SPierre Pronchery     OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
998*b077aed3SPierre Pronchery     struct ec_gen_ctx *gctx = NULL;
999*b077aed3SPierre Pronchery 
1000*b077aed3SPierre Pronchery     if (!ossl_prov_is_running() || (selection & (EC_POSSIBLE_SELECTIONS)) == 0)
1001*b077aed3SPierre Pronchery         return NULL;
1002*b077aed3SPierre Pronchery 
1003*b077aed3SPierre Pronchery     if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
1004*b077aed3SPierre Pronchery         gctx->libctx = libctx;
1005*b077aed3SPierre Pronchery         gctx->selection = selection;
1006*b077aed3SPierre Pronchery         gctx->ecdh_mode = 0;
1007*b077aed3SPierre Pronchery         if (!ec_gen_set_params(gctx, params)) {
1008*b077aed3SPierre Pronchery             OPENSSL_free(gctx);
1009*b077aed3SPierre Pronchery             gctx = NULL;
1010*b077aed3SPierre Pronchery         }
1011*b077aed3SPierre Pronchery     }
1012*b077aed3SPierre Pronchery     return gctx;
1013*b077aed3SPierre Pronchery }
1014*b077aed3SPierre Pronchery 
1015*b077aed3SPierre Pronchery #ifndef FIPS_MODULE
1016*b077aed3SPierre Pronchery # ifndef OPENSSL_NO_SM2
sm2_gen_init(void * provctx,int selection,const OSSL_PARAM params[])1017*b077aed3SPierre Pronchery static void *sm2_gen_init(void *provctx, int selection,
1018*b077aed3SPierre Pronchery                          const OSSL_PARAM params[])
1019*b077aed3SPierre Pronchery {
1020*b077aed3SPierre Pronchery     struct ec_gen_ctx *gctx = ec_gen_init(provctx, selection, params);
1021*b077aed3SPierre Pronchery 
1022*b077aed3SPierre Pronchery     if (gctx != NULL) {
1023*b077aed3SPierre Pronchery         if (gctx->group_name != NULL)
1024*b077aed3SPierre Pronchery             return gctx;
1025*b077aed3SPierre Pronchery         if ((gctx->group_name = OPENSSL_strdup("sm2")) != NULL)
1026*b077aed3SPierre Pronchery             return gctx;
1027*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
1028*b077aed3SPierre Pronchery         ec_gen_cleanup(gctx);
1029*b077aed3SPierre Pronchery     }
1030*b077aed3SPierre Pronchery     return NULL;
1031*b077aed3SPierre Pronchery }
1032*b077aed3SPierre Pronchery # endif
1033*b077aed3SPierre Pronchery #endif
1034*b077aed3SPierre Pronchery 
ec_gen_set_group(void * genctx,const EC_GROUP * src)1035*b077aed3SPierre Pronchery static int ec_gen_set_group(void *genctx, const EC_GROUP *src)
1036*b077aed3SPierre Pronchery {
1037*b077aed3SPierre Pronchery     struct ec_gen_ctx *gctx = genctx;
1038*b077aed3SPierre Pronchery     EC_GROUP *group;
1039*b077aed3SPierre Pronchery 
1040*b077aed3SPierre Pronchery     group = EC_GROUP_dup(src);
1041*b077aed3SPierre Pronchery     if (group == NULL) {
1042*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CURVE);
1043*b077aed3SPierre Pronchery         return 0;
1044*b077aed3SPierre Pronchery     }
1045*b077aed3SPierre Pronchery     EC_GROUP_free(gctx->gen_group);
1046*b077aed3SPierre Pronchery     gctx->gen_group = group;
1047*b077aed3SPierre Pronchery     return 1;
1048*b077aed3SPierre Pronchery }
1049*b077aed3SPierre Pronchery 
ec_gen_set_template(void * genctx,void * templ)1050*b077aed3SPierre Pronchery static int ec_gen_set_template(void *genctx, void *templ)
1051*b077aed3SPierre Pronchery {
1052*b077aed3SPierre Pronchery     struct ec_gen_ctx *gctx = genctx;
1053*b077aed3SPierre Pronchery     EC_KEY *ec = templ;
1054*b077aed3SPierre Pronchery     const EC_GROUP *ec_group;
1055*b077aed3SPierre Pronchery 
1056*b077aed3SPierre Pronchery     if (!ossl_prov_is_running() || gctx == NULL || ec == NULL)
1057*b077aed3SPierre Pronchery         return 0;
1058*b077aed3SPierre Pronchery     if ((ec_group = EC_KEY_get0_group(ec)) == NULL)
1059*b077aed3SPierre Pronchery         return 0;
1060*b077aed3SPierre Pronchery     return ec_gen_set_group(gctx, ec_group);
1061*b077aed3SPierre Pronchery }
1062*b077aed3SPierre Pronchery 
1063*b077aed3SPierre Pronchery #define COPY_INT_PARAM(params, key, val)                                       \
1064*b077aed3SPierre Pronchery p = OSSL_PARAM_locate_const(params, key);                                      \
1065*b077aed3SPierre Pronchery if (p != NULL && !OSSL_PARAM_get_int(p, &val))                                 \
1066*b077aed3SPierre Pronchery     goto err;
1067*b077aed3SPierre Pronchery 
1068*b077aed3SPierre Pronchery #define COPY_UTF8_PARAM(params, key, val)                                      \
1069*b077aed3SPierre Pronchery p = OSSL_PARAM_locate_const(params, key);                                      \
1070*b077aed3SPierre Pronchery if (p != NULL) {                                                               \
1071*b077aed3SPierre Pronchery     if (p->data_type != OSSL_PARAM_UTF8_STRING)                                \
1072*b077aed3SPierre Pronchery         goto err;                                                              \
1073*b077aed3SPierre Pronchery     OPENSSL_free(val);                                                         \
1074*b077aed3SPierre Pronchery     val = OPENSSL_strdup(p->data);                                             \
1075*b077aed3SPierre Pronchery     if (val == NULL)                                                           \
1076*b077aed3SPierre Pronchery         goto err;                                                              \
1077*b077aed3SPierre Pronchery }
1078*b077aed3SPierre Pronchery 
1079*b077aed3SPierre Pronchery #define COPY_OCTET_PARAM(params, key, val, len)                                \
1080*b077aed3SPierre Pronchery p = OSSL_PARAM_locate_const(params, key);                                      \
1081*b077aed3SPierre Pronchery if (p != NULL) {                                                               \
1082*b077aed3SPierre Pronchery     if (p->data_type != OSSL_PARAM_OCTET_STRING)                               \
1083*b077aed3SPierre Pronchery         goto err;                                                              \
1084*b077aed3SPierre Pronchery     OPENSSL_free(val);                                                         \
1085*b077aed3SPierre Pronchery     len = p->data_size;                                                        \
1086*b077aed3SPierre Pronchery     val = OPENSSL_memdup(p->data, p->data_size);                               \
1087*b077aed3SPierre Pronchery     if (val == NULL)                                                           \
1088*b077aed3SPierre Pronchery         goto err;                                                              \
1089*b077aed3SPierre Pronchery }
1090*b077aed3SPierre Pronchery 
1091*b077aed3SPierre Pronchery #define COPY_BN_PARAM(params, key, bn)                                         \
1092*b077aed3SPierre Pronchery p = OSSL_PARAM_locate_const(params, key);                                      \
1093*b077aed3SPierre Pronchery if (p != NULL) {                                                               \
1094*b077aed3SPierre Pronchery     if (bn == NULL)                                                            \
1095*b077aed3SPierre Pronchery         bn = BN_new();                                                         \
1096*b077aed3SPierre Pronchery     if (bn == NULL || !OSSL_PARAM_get_BN(p, &bn))                              \
1097*b077aed3SPierre Pronchery         goto err;                                                              \
1098*b077aed3SPierre Pronchery }
1099*b077aed3SPierre Pronchery 
ec_gen_set_params(void * genctx,const OSSL_PARAM params[])1100*b077aed3SPierre Pronchery static int ec_gen_set_params(void *genctx, const OSSL_PARAM params[])
1101*b077aed3SPierre Pronchery {
1102*b077aed3SPierre Pronchery     int ret = 0;
1103*b077aed3SPierre Pronchery     struct ec_gen_ctx *gctx = genctx;
1104*b077aed3SPierre Pronchery     const OSSL_PARAM *p;
1105*b077aed3SPierre Pronchery     EC_GROUP *group = NULL;
1106*b077aed3SPierre Pronchery 
1107*b077aed3SPierre Pronchery     COPY_INT_PARAM(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, gctx->ecdh_mode);
1108*b077aed3SPierre Pronchery 
1109*b077aed3SPierre Pronchery     COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_GROUP_NAME, gctx->group_name);
1110*b077aed3SPierre Pronchery     COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_FIELD_TYPE, gctx->field_type);
1111*b077aed3SPierre Pronchery     COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_ENCODING, gctx->encoding);
1112*b077aed3SPierre Pronchery     COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, gctx->pt_format);
1113*b077aed3SPierre Pronchery     COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE, gctx->group_check);
1114*b077aed3SPierre Pronchery 
1115*b077aed3SPierre Pronchery     COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_P, gctx->p);
1116*b077aed3SPierre Pronchery     COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_A, gctx->a);
1117*b077aed3SPierre Pronchery     COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_B, gctx->b);
1118*b077aed3SPierre Pronchery     COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_ORDER, gctx->order);
1119*b077aed3SPierre Pronchery     COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_COFACTOR, gctx->cofactor);
1120*b077aed3SPierre Pronchery 
1121*b077aed3SPierre Pronchery     COPY_OCTET_PARAM(params, OSSL_PKEY_PARAM_EC_SEED, gctx->seed, gctx->seed_len);
1122*b077aed3SPierre Pronchery     COPY_OCTET_PARAM(params, OSSL_PKEY_PARAM_EC_GENERATOR, gctx->gen,
1123*b077aed3SPierre Pronchery                      gctx->gen_len);
1124*b077aed3SPierre Pronchery 
1125*b077aed3SPierre Pronchery     ret = 1;
1126*b077aed3SPierre Pronchery err:
1127*b077aed3SPierre Pronchery     EC_GROUP_free(group);
1128*b077aed3SPierre Pronchery     return ret;
1129*b077aed3SPierre Pronchery }
1130*b077aed3SPierre Pronchery 
ec_gen_set_group_from_params(struct ec_gen_ctx * gctx)1131*b077aed3SPierre Pronchery static int ec_gen_set_group_from_params(struct ec_gen_ctx *gctx)
1132*b077aed3SPierre Pronchery {
1133*b077aed3SPierre Pronchery     int ret = 0;
1134*b077aed3SPierre Pronchery     OSSL_PARAM_BLD *bld;
1135*b077aed3SPierre Pronchery     OSSL_PARAM *params = NULL;
1136*b077aed3SPierre Pronchery     EC_GROUP *group = NULL;
1137*b077aed3SPierre Pronchery 
1138*b077aed3SPierre Pronchery     bld = OSSL_PARAM_BLD_new();
1139*b077aed3SPierre Pronchery     if (bld == NULL)
1140*b077aed3SPierre Pronchery         return 0;
1141*b077aed3SPierre Pronchery 
1142*b077aed3SPierre Pronchery     if (gctx->encoding != NULL
1143*b077aed3SPierre Pronchery         && !OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_EC_ENCODING,
1144*b077aed3SPierre Pronchery                                             gctx->encoding, 0))
1145*b077aed3SPierre Pronchery         goto err;
1146*b077aed3SPierre Pronchery 
1147*b077aed3SPierre Pronchery     if (gctx->pt_format != NULL
1148*b077aed3SPierre Pronchery         && !OSSL_PARAM_BLD_push_utf8_string(bld,
1149*b077aed3SPierre Pronchery                                             OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
1150*b077aed3SPierre Pronchery                                             gctx->pt_format, 0))
1151*b077aed3SPierre Pronchery         goto err;
1152*b077aed3SPierre Pronchery 
1153*b077aed3SPierre Pronchery     if (gctx->group_name != NULL) {
1154*b077aed3SPierre Pronchery         if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME,
1155*b077aed3SPierre Pronchery                                              gctx->group_name, 0))
1156*b077aed3SPierre Pronchery             goto err;
1157*b077aed3SPierre Pronchery         /* Ignore any other parameters if there is a group name */
1158*b077aed3SPierre Pronchery         goto build;
1159*b077aed3SPierre Pronchery     } else if (gctx->field_type != NULL) {
1160*b077aed3SPierre Pronchery         if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_EC_FIELD_TYPE,
1161*b077aed3SPierre Pronchery                                              gctx->field_type, 0))
1162*b077aed3SPierre Pronchery             goto err;
1163*b077aed3SPierre Pronchery     } else {
1164*b077aed3SPierre Pronchery         goto err;
1165*b077aed3SPierre Pronchery     }
1166*b077aed3SPierre Pronchery     if (gctx->p == NULL
1167*b077aed3SPierre Pronchery         || gctx->a == NULL
1168*b077aed3SPierre Pronchery         || gctx->b == NULL
1169*b077aed3SPierre Pronchery         || gctx->order == NULL
1170*b077aed3SPierre Pronchery         || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_P, gctx->p)
1171*b077aed3SPierre Pronchery         || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_A, gctx->a)
1172*b077aed3SPierre Pronchery         || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_B, gctx->b)
1173*b077aed3SPierre Pronchery         || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_ORDER, gctx->order))
1174*b077aed3SPierre Pronchery         goto err;
1175*b077aed3SPierre Pronchery 
1176*b077aed3SPierre Pronchery     if (gctx->cofactor != NULL
1177*b077aed3SPierre Pronchery         && !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_COFACTOR,
1178*b077aed3SPierre Pronchery                                    gctx->cofactor))
1179*b077aed3SPierre Pronchery         goto err;
1180*b077aed3SPierre Pronchery 
1181*b077aed3SPierre Pronchery     if (gctx->seed != NULL
1182*b077aed3SPierre Pronchery         && !OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_EC_SEED,
1183*b077aed3SPierre Pronchery                                              gctx->seed, gctx->seed_len))
1184*b077aed3SPierre Pronchery         goto err;
1185*b077aed3SPierre Pronchery 
1186*b077aed3SPierre Pronchery     if (gctx->gen == NULL
1187*b077aed3SPierre Pronchery         || !OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_EC_GENERATOR,
1188*b077aed3SPierre Pronchery                                              gctx->gen, gctx->gen_len))
1189*b077aed3SPierre Pronchery         goto err;
1190*b077aed3SPierre Pronchery build:
1191*b077aed3SPierre Pronchery     params = OSSL_PARAM_BLD_to_param(bld);
1192*b077aed3SPierre Pronchery     if (params == NULL)
1193*b077aed3SPierre Pronchery         goto err;
1194*b077aed3SPierre Pronchery     group = EC_GROUP_new_from_params(params, gctx->libctx, NULL);
1195*b077aed3SPierre Pronchery     if (group == NULL)
1196*b077aed3SPierre Pronchery         goto err;
1197*b077aed3SPierre Pronchery 
1198*b077aed3SPierre Pronchery     EC_GROUP_free(gctx->gen_group);
1199*b077aed3SPierre Pronchery     gctx->gen_group = group;
1200*b077aed3SPierre Pronchery 
1201*b077aed3SPierre Pronchery     ret = 1;
1202*b077aed3SPierre Pronchery err:
1203*b077aed3SPierre Pronchery     OSSL_PARAM_free(params);
1204*b077aed3SPierre Pronchery     OSSL_PARAM_BLD_free(bld);
1205*b077aed3SPierre Pronchery     return ret;
1206*b077aed3SPierre Pronchery }
1207*b077aed3SPierre Pronchery 
ec_gen_settable_params(ossl_unused void * genctx,ossl_unused void * provctx)1208*b077aed3SPierre Pronchery static const OSSL_PARAM *ec_gen_settable_params(ossl_unused void *genctx,
1209*b077aed3SPierre Pronchery                                                 ossl_unused void *provctx)
1210*b077aed3SPierre Pronchery {
1211*b077aed3SPierre Pronchery     static OSSL_PARAM settable[] = {
1212*b077aed3SPierre Pronchery         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
1213*b077aed3SPierre Pronchery         OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
1214*b077aed3SPierre Pronchery         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0),
1215*b077aed3SPierre Pronchery         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0),
1216*b077aed3SPierre Pronchery         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_FIELD_TYPE, NULL, 0),
1217*b077aed3SPierre Pronchery         OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_P, NULL, 0),
1218*b077aed3SPierre Pronchery         OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_A, NULL, 0),
1219*b077aed3SPierre Pronchery         OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_B, NULL, 0),
1220*b077aed3SPierre Pronchery         OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_GENERATOR, NULL, 0),
1221*b077aed3SPierre Pronchery         OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_ORDER, NULL, 0),
1222*b077aed3SPierre Pronchery         OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_COFACTOR, NULL, 0),
1223*b077aed3SPierre Pronchery         OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0),
1224*b077aed3SPierre Pronchery         OSSL_PARAM_END
1225*b077aed3SPierre Pronchery     };
1226*b077aed3SPierre Pronchery 
1227*b077aed3SPierre Pronchery     return settable;
1228*b077aed3SPierre Pronchery }
1229*b077aed3SPierre Pronchery 
ec_gen_assign_group(EC_KEY * ec,EC_GROUP * group)1230*b077aed3SPierre Pronchery static int ec_gen_assign_group(EC_KEY *ec, EC_GROUP *group)
1231*b077aed3SPierre Pronchery {
1232*b077aed3SPierre Pronchery     if (group == NULL) {
1233*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET);
1234*b077aed3SPierre Pronchery         return 0;
1235*b077aed3SPierre Pronchery     }
1236*b077aed3SPierre Pronchery     return EC_KEY_set_group(ec, group) > 0;
1237*b077aed3SPierre Pronchery }
1238*b077aed3SPierre Pronchery 
1239*b077aed3SPierre Pronchery /*
1240*b077aed3SPierre Pronchery  * The callback arguments (osslcb & cbarg) are not used by EC_KEY generation
1241*b077aed3SPierre Pronchery  */
ec_gen(void * genctx,OSSL_CALLBACK * osslcb,void * cbarg)1242*b077aed3SPierre Pronchery static void *ec_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
1243*b077aed3SPierre Pronchery {
1244*b077aed3SPierre Pronchery     struct ec_gen_ctx *gctx = genctx;
1245*b077aed3SPierre Pronchery     EC_KEY *ec = NULL;
1246*b077aed3SPierre Pronchery     int ret = 0;
1247*b077aed3SPierre Pronchery 
1248*b077aed3SPierre Pronchery     if (!ossl_prov_is_running()
1249*b077aed3SPierre Pronchery         || gctx == NULL
1250*b077aed3SPierre Pronchery         || (ec = EC_KEY_new_ex(gctx->libctx, NULL)) == NULL)
1251*b077aed3SPierre Pronchery         return NULL;
1252*b077aed3SPierre Pronchery 
1253*b077aed3SPierre Pronchery     if (gctx->gen_group == NULL) {
1254*b077aed3SPierre Pronchery         if (!ec_gen_set_group_from_params(gctx))
1255*b077aed3SPierre Pronchery             goto err;
1256*b077aed3SPierre Pronchery     } else {
1257*b077aed3SPierre Pronchery         if (gctx->encoding != NULL) {
1258*b077aed3SPierre Pronchery             int flags = ossl_ec_encoding_name2id(gctx->encoding);
1259*b077aed3SPierre Pronchery 
1260*b077aed3SPierre Pronchery             if (flags < 0)
1261*b077aed3SPierre Pronchery                 goto err;
1262*b077aed3SPierre Pronchery             EC_GROUP_set_asn1_flag(gctx->gen_group, flags);
1263*b077aed3SPierre Pronchery         }
1264*b077aed3SPierre Pronchery         if (gctx->pt_format != NULL) {
1265*b077aed3SPierre Pronchery             int format = ossl_ec_pt_format_name2id(gctx->pt_format);
1266*b077aed3SPierre Pronchery 
1267*b077aed3SPierre Pronchery             if (format < 0)
1268*b077aed3SPierre Pronchery                 goto err;
1269*b077aed3SPierre Pronchery             EC_GROUP_set_point_conversion_form(gctx->gen_group, format);
1270*b077aed3SPierre Pronchery         }
1271*b077aed3SPierre Pronchery     }
1272*b077aed3SPierre Pronchery 
1273*b077aed3SPierre Pronchery     /* We must always assign a group, no matter what */
1274*b077aed3SPierre Pronchery     ret = ec_gen_assign_group(ec, gctx->gen_group);
1275*b077aed3SPierre Pronchery 
1276*b077aed3SPierre Pronchery     /* Whether you want it or not, you get a keypair, not just one half */
1277*b077aed3SPierre Pronchery     if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
1278*b077aed3SPierre Pronchery         ret = ret && EC_KEY_generate_key(ec);
1279*b077aed3SPierre Pronchery 
1280*b077aed3SPierre Pronchery     if (gctx->ecdh_mode != -1)
1281*b077aed3SPierre Pronchery         ret = ret && ossl_ec_set_ecdh_cofactor_mode(ec, gctx->ecdh_mode);
1282*b077aed3SPierre Pronchery 
1283*b077aed3SPierre Pronchery     if (gctx->group_check != NULL)
1284*b077aed3SPierre Pronchery         ret = ret && ossl_ec_set_check_group_type_from_name(ec, gctx->group_check);
1285*b077aed3SPierre Pronchery     if (ret)
1286*b077aed3SPierre Pronchery         return ec;
1287*b077aed3SPierre Pronchery err:
1288*b077aed3SPierre Pronchery     /* Something went wrong, throw the key away */
1289*b077aed3SPierre Pronchery     EC_KEY_free(ec);
1290*b077aed3SPierre Pronchery     return NULL;
1291*b077aed3SPierre Pronchery }
1292*b077aed3SPierre Pronchery 
1293*b077aed3SPierre Pronchery #ifndef FIPS_MODULE
1294*b077aed3SPierre Pronchery # ifndef OPENSSL_NO_SM2
1295*b077aed3SPierre Pronchery /*
1296*b077aed3SPierre Pronchery  * The callback arguments (osslcb & cbarg) are not used by EC_KEY generation
1297*b077aed3SPierre Pronchery  */
sm2_gen(void * genctx,OSSL_CALLBACK * osslcb,void * cbarg)1298*b077aed3SPierre Pronchery static void *sm2_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
1299*b077aed3SPierre Pronchery {
1300*b077aed3SPierre Pronchery     struct ec_gen_ctx *gctx = genctx;
1301*b077aed3SPierre Pronchery     EC_KEY *ec = NULL;
1302*b077aed3SPierre Pronchery     int ret = 1;
1303*b077aed3SPierre Pronchery 
1304*b077aed3SPierre Pronchery     if (gctx == NULL
1305*b077aed3SPierre Pronchery         || (ec = EC_KEY_new_ex(gctx->libctx, NULL)) == NULL)
1306*b077aed3SPierre Pronchery         return NULL;
1307*b077aed3SPierre Pronchery 
1308*b077aed3SPierre Pronchery     if (gctx->gen_group == NULL) {
1309*b077aed3SPierre Pronchery         if (!ec_gen_set_group_from_params(gctx))
1310*b077aed3SPierre Pronchery             goto err;
1311*b077aed3SPierre Pronchery     } else {
1312*b077aed3SPierre Pronchery         if (gctx->encoding) {
1313*b077aed3SPierre Pronchery             int flags = ossl_ec_encoding_name2id(gctx->encoding);
1314*b077aed3SPierre Pronchery 
1315*b077aed3SPierre Pronchery             if (flags < 0)
1316*b077aed3SPierre Pronchery                 goto err;
1317*b077aed3SPierre Pronchery             EC_GROUP_set_asn1_flag(gctx->gen_group, flags);
1318*b077aed3SPierre Pronchery         }
1319*b077aed3SPierre Pronchery         if (gctx->pt_format != NULL) {
1320*b077aed3SPierre Pronchery             int format = ossl_ec_pt_format_name2id(gctx->pt_format);
1321*b077aed3SPierre Pronchery 
1322*b077aed3SPierre Pronchery             if (format < 0)
1323*b077aed3SPierre Pronchery                 goto err;
1324*b077aed3SPierre Pronchery             EC_GROUP_set_point_conversion_form(gctx->gen_group, format);
1325*b077aed3SPierre Pronchery         }
1326*b077aed3SPierre Pronchery     }
1327*b077aed3SPierre Pronchery 
1328*b077aed3SPierre Pronchery     /* We must always assign a group, no matter what */
1329*b077aed3SPierre Pronchery     ret = ec_gen_assign_group(ec, gctx->gen_group);
1330*b077aed3SPierre Pronchery 
1331*b077aed3SPierre Pronchery     /* Whether you want it or not, you get a keypair, not just one half */
1332*b077aed3SPierre Pronchery     if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
1333*b077aed3SPierre Pronchery         ret = ret && EC_KEY_generate_key(ec);
1334*b077aed3SPierre Pronchery 
1335*b077aed3SPierre Pronchery     if (ret)
1336*b077aed3SPierre Pronchery         return ec;
1337*b077aed3SPierre Pronchery err:
1338*b077aed3SPierre Pronchery     /* Something went wrong, throw the key away */
1339*b077aed3SPierre Pronchery     EC_KEY_free(ec);
1340*b077aed3SPierre Pronchery     return NULL;
1341*b077aed3SPierre Pronchery }
1342*b077aed3SPierre Pronchery # endif
1343*b077aed3SPierre Pronchery #endif
1344*b077aed3SPierre Pronchery 
ec_gen_cleanup(void * genctx)1345*b077aed3SPierre Pronchery static void ec_gen_cleanup(void *genctx)
1346*b077aed3SPierre Pronchery {
1347*b077aed3SPierre Pronchery     struct ec_gen_ctx *gctx = genctx;
1348*b077aed3SPierre Pronchery 
1349*b077aed3SPierre Pronchery     if (gctx == NULL)
1350*b077aed3SPierre Pronchery         return;
1351*b077aed3SPierre Pronchery 
1352*b077aed3SPierre Pronchery     EC_GROUP_free(gctx->gen_group);
1353*b077aed3SPierre Pronchery     BN_free(gctx->p);
1354*b077aed3SPierre Pronchery     BN_free(gctx->a);
1355*b077aed3SPierre Pronchery     BN_free(gctx->b);
1356*b077aed3SPierre Pronchery     BN_free(gctx->order);
1357*b077aed3SPierre Pronchery     BN_free(gctx->cofactor);
1358*b077aed3SPierre Pronchery     OPENSSL_free(gctx->group_name);
1359*b077aed3SPierre Pronchery     OPENSSL_free(gctx->field_type);
1360*b077aed3SPierre Pronchery     OPENSSL_free(gctx->pt_format);
1361*b077aed3SPierre Pronchery     OPENSSL_free(gctx->encoding);
1362*b077aed3SPierre Pronchery     OPENSSL_free(gctx->seed);
1363*b077aed3SPierre Pronchery     OPENSSL_free(gctx->gen);
1364*b077aed3SPierre Pronchery     OPENSSL_free(gctx);
1365*b077aed3SPierre Pronchery }
1366*b077aed3SPierre Pronchery 
common_load(const void * reference,size_t reference_sz,int sm2_wanted)1367*b077aed3SPierre Pronchery static void *common_load(const void *reference, size_t reference_sz,
1368*b077aed3SPierre Pronchery                          int sm2_wanted)
1369*b077aed3SPierre Pronchery {
1370*b077aed3SPierre Pronchery     EC_KEY *ec = NULL;
1371*b077aed3SPierre Pronchery 
1372*b077aed3SPierre Pronchery     if (ossl_prov_is_running() && reference_sz == sizeof(ec)) {
1373*b077aed3SPierre Pronchery         /* The contents of the reference is the address to our object */
1374*b077aed3SPierre Pronchery         ec = *(EC_KEY **)reference;
1375*b077aed3SPierre Pronchery 
1376*b077aed3SPierre Pronchery         if (!common_check_sm2(ec, sm2_wanted))
1377*b077aed3SPierre Pronchery             return NULL;
1378*b077aed3SPierre Pronchery 
1379*b077aed3SPierre Pronchery         /* We grabbed, so we detach it */
1380*b077aed3SPierre Pronchery         *(EC_KEY **)reference = NULL;
1381*b077aed3SPierre Pronchery         return ec;
1382*b077aed3SPierre Pronchery     }
1383*b077aed3SPierre Pronchery     return NULL;
1384*b077aed3SPierre Pronchery }
1385*b077aed3SPierre Pronchery 
ec_load(const void * reference,size_t reference_sz)1386*b077aed3SPierre Pronchery static void *ec_load(const void *reference, size_t reference_sz)
1387*b077aed3SPierre Pronchery {
1388*b077aed3SPierre Pronchery     return common_load(reference, reference_sz, 0);
1389*b077aed3SPierre Pronchery }
1390*b077aed3SPierre Pronchery 
1391*b077aed3SPierre Pronchery #ifndef FIPS_MODULE
1392*b077aed3SPierre Pronchery # ifndef OPENSSL_NO_SM2
sm2_load(const void * reference,size_t reference_sz)1393*b077aed3SPierre Pronchery static void *sm2_load(const void *reference, size_t reference_sz)
1394*b077aed3SPierre Pronchery {
1395*b077aed3SPierre Pronchery     return common_load(reference, reference_sz, 1);
1396*b077aed3SPierre Pronchery }
1397*b077aed3SPierre Pronchery # endif
1398*b077aed3SPierre Pronchery #endif
1399*b077aed3SPierre Pronchery 
ec_dup(const void * keydata_from,int selection)1400*b077aed3SPierre Pronchery static void *ec_dup(const void *keydata_from, int selection)
1401*b077aed3SPierre Pronchery {
1402*b077aed3SPierre Pronchery     if (ossl_prov_is_running())
1403*b077aed3SPierre Pronchery         return ossl_ec_key_dup(keydata_from, selection);
1404*b077aed3SPierre Pronchery     return NULL;
1405*b077aed3SPierre Pronchery }
1406*b077aed3SPierre Pronchery 
1407*b077aed3SPierre Pronchery const OSSL_DISPATCH ossl_ec_keymgmt_functions[] = {
1408*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata },
1409*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ec_gen_init },
1410*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE,
1411*b077aed3SPierre Pronchery       (void (*)(void))ec_gen_set_template },
1412*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ec_gen_set_params },
1413*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
1414*b077aed3SPierre Pronchery       (void (*)(void))ec_gen_settable_params },
1415*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))ec_gen },
1416*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ec_gen_cleanup },
1417*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ec_load },
1418*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },
1419*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))ec_get_params },
1420*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ec_gettable_params },
1421*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))ec_set_params },
1422*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))ec_settable_params },
1423*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },
1424*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },
1425*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))ec_validate },
1426*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ec_import },
1427*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },
1428*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },
1429*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },
1430*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
1431*b077aed3SPierre Pronchery       (void (*)(void))ec_query_operation_name },
1432*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ec_dup },
1433*b077aed3SPierre Pronchery     { 0, NULL }
1434*b077aed3SPierre Pronchery };
1435*b077aed3SPierre Pronchery 
1436*b077aed3SPierre Pronchery #ifndef FIPS_MODULE
1437*b077aed3SPierre Pronchery # ifndef OPENSSL_NO_SM2
1438*b077aed3SPierre Pronchery const OSSL_DISPATCH ossl_sm2_keymgmt_functions[] = {
1439*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))sm2_newdata },
1440*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))sm2_gen_init },
1441*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE,
1442*b077aed3SPierre Pronchery       (void (*)(void))ec_gen_set_template },
1443*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ec_gen_set_params },
1444*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
1445*b077aed3SPierre Pronchery       (void (*)(void))ec_gen_settable_params },
1446*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))sm2_gen },
1447*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ec_gen_cleanup },
1448*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))sm2_load },
1449*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },
1450*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))sm2_get_params },
1451*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))sm2_gettable_params },
1452*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))ec_set_params },
1453*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))sm2_settable_params },
1454*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },
1455*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },
1456*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))sm2_validate },
1457*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))sm2_import },
1458*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },
1459*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },
1460*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },
1461*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
1462*b077aed3SPierre Pronchery       (void (*)(void))sm2_query_operation_name },
1463*b077aed3SPierre Pronchery     { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ec_dup },
1464*b077aed3SPierre Pronchery     { 0, NULL }
1465*b077aed3SPierre Pronchery };
1466*b077aed3SPierre Pronchery # endif
1467*b077aed3SPierre Pronchery #endif
1468