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