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