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