Coverage Report

Created: 2026-09-12 06:55

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