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