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