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