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