X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=providers%2Fimplementations%2Fkeymgmt%2Fec_kmgmt.c;h=7e3fadc580f2659d5dd9234715b232fdf555bbe3;hp=8b020711fbeaf808edae9af436ae9fca617fc209;hb=HEAD;hpb=4333b89f504e7a8de9c42a0d27f68530b5301848 diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c index 8b020711fb..9390935394 100644 --- a/providers/implementations/keymgmt/ec_kmgmt.c +++ b/providers/implementations/keymgmt/ec_kmgmt.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -13,18 +13,17 @@ */ #include "internal/deprecated.h" -#include "e_os.h" /* strcasecmp */ #include #include #include #include #include #include +#include #include "crypto/bn.h" #include "crypto/ec.h" #include "prov/implementations.h" #include "prov/providercommon.h" -#include "prov/providercommonerr.h" #include "prov/provider_ctx.h" #include "internal/param_build_set.h" @@ -55,8 +54,11 @@ static OSSL_FUNC_keymgmt_import_types_fn ec_import_types; static OSSL_FUNC_keymgmt_export_fn ec_export; static OSSL_FUNC_keymgmt_export_types_fn ec_export_types; static OSSL_FUNC_keymgmt_query_operation_name_fn ec_query_operation_name; +static OSSL_FUNC_keymgmt_dup_fn ec_dup; #ifndef FIPS_MODULE # ifndef OPENSSL_NO_SM2 +static OSSL_FUNC_keymgmt_new_fn sm2_newdata; +static OSSL_FUNC_keymgmt_gen_init_fn sm2_gen_init; static OSSL_FUNC_keymgmt_gen_fn sm2_gen; static OSSL_FUNC_keymgmt_get_params_fn sm2_get_params; static OSSL_FUNC_keymgmt_gettable_params_fn sm2_gettable_params; @@ -131,7 +133,7 @@ int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl, * EC_POINT_point2buf() can generate random numbers in some * implementations so we need to ensure we use the correct libctx. */ - bnctx = BN_CTX_new_ex(ec_key_get_libctx(eckey)); + bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eckey)); if (bnctx == NULL) goto err; @@ -145,8 +147,10 @@ int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl, if (p != NULL || tmpl != NULL) { /* convert pub_point to a octet string according to the SECG standard */ + point_conversion_form_t format = EC_KEY_get_conv_form(eckey); + if ((pub_key_len = EC_POINT_point2buf(ecg, pub_point, - POINT_CONVERSION_COMPRESSED, + format, pub_key, bnctx)) == 0 || !ossl_param_build_set_octet_string(tmpl, p, OSSL_PKEY_PARAM_PUB_KEY, @@ -154,10 +158,16 @@ int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl, goto err; } if (px != NULL || py != NULL) { - if (px != NULL) + if (px != NULL) { x = BN_CTX_get(bnctx); - if (py != NULL) + if (x == NULL) + goto err; + } + if (py != NULL) { y = BN_CTX_get(bnctx); + if (y == NULL) + goto err; + } if (!EC_POINT_get_affine_coordinates(ecg, pub_point, x, y, bnctx)) goto err; @@ -212,7 +222,7 @@ int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl, ecbits = EC_GROUP_order_bits(ecg); if (ecbits <= 0) goto err; - sz = (ecbits + 7 ) / 8; + sz = (ecbits + 7) / 8; if (!ossl_param_build_set_bn_pad(tmpl, params, OSSL_PKEY_PARAM_PRIV_KEY, @@ -237,7 +247,7 @@ int otherparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl, return 0; format = EC_KEY_get_conv_form(ec); - name = ec_pt_format_id2name((int)format); + name = ossl_ec_pt_format_id2name((int)format); if (name != NULL && !ossl_param_build_set_utf8_string(tmpl, params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, @@ -245,16 +255,17 @@ int otherparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl, return 0; group_check = EC_KEY_get_flags(ec) & EC_FLAG_CHECK_NAMED_GROUP_MASK; - name = ec_check_group_type_id2name(group_check); + name = ossl_ec_check_group_type_id2name(group_check); if (name != NULL && !ossl_param_build_set_utf8_string(tmpl, params, OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE, name)) return 0; - if ((EC_KEY_get_enc_flags(ec) & EC_PKEY_NO_PUBKEY) != 0) - ossl_param_build_set_int(tmpl, params, - OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, 0); + if ((EC_KEY_get_enc_flags(ec) & EC_PKEY_NO_PUBKEY) != 0 + && !ossl_param_build_set_int(tmpl, params, + OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, 0)) + return 0; ecdh_cofactor_mode = (EC_KEY_get_flags(ec) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0; @@ -271,6 +282,18 @@ void *ec_newdata(void *provctx) return EC_KEY_new_ex(PROV_LIBCTX_OF(provctx), NULL); } +#ifndef FIPS_MODULE +# ifndef OPENSSL_NO_SM2 +static +void *sm2_newdata(void *provctx) +{ + if (!ossl_prov_is_running()) + return NULL; + return EC_KEY_new_by_curve_name_ex(PROV_LIBCTX_OF(provctx), NULL, NID_sm2); +} +# endif +#endif + static void ec_freedata(void *keydata) { @@ -281,24 +304,24 @@ static int ec_has(const void *keydata, int selection) { const EC_KEY *ec = keydata; - int ok = 0; - - if (ossl_prov_is_running() && ec != NULL) { - if ((selection & EC_POSSIBLE_SELECTIONS) != 0) - ok = 1; - - if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) - ok = ok && (EC_KEY_get0_public_key(ec) != NULL); - if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) - ok = ok && (EC_KEY_get0_private_key(ec) != NULL); - if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) - ok = ok && (EC_KEY_get0_group(ec) != NULL); - /* - * We consider OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS to always be - * available, so no extra check is needed other than the previous one - * against EC_POSSIBLE_SELECTIONS. - */ - } + int ok = 1; + + if (!ossl_prov_is_running() || ec == NULL) + return 0; + if ((selection & EC_POSSIBLE_SELECTIONS) == 0) + return 1; /* the selection is not missing */ + + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) + ok = ok && (EC_KEY_get0_public_key(ec) != NULL); + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) + ok = ok && (EC_KEY_get0_private_key(ec) != NULL); + if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) + ok = ok && (EC_KEY_get0_group(ec) != NULL); + /* + * We consider OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS to always be + * available, so no extra check is needed other than the previous one + * against EC_POSSIBLE_SELECTIONS. + */ return ok; } @@ -314,35 +337,60 @@ static int ec_match(const void *keydata1, const void *keydata2, int selection) if (!ossl_prov_is_running()) return 0; - ctx = BN_CTX_new_ex(ec_key_get_libctx(ec1)); + ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec1)); if (ctx == NULL) return 0; if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) ok = ok && group_a != NULL && group_b != NULL && EC_GROUP_cmp(group_a, group_b, ctx) == 0; - if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { - const BIGNUM *pa = EC_KEY_get0_private_key(ec1); - const BIGNUM *pb = EC_KEY_get0_private_key(ec2); + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { + int key_checked = 0; - ok = ok && BN_cmp(pa, pb) == 0; - } - if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { - const EC_POINT *pa = EC_KEY_get0_public_key(ec1); - const EC_POINT *pb = EC_KEY_get0_public_key(ec2); + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { + const EC_POINT *pa = EC_KEY_get0_public_key(ec1); + const EC_POINT *pb = EC_KEY_get0_public_key(ec2); - ok = ok && EC_POINT_cmp(group_b, pa, pb, ctx) == 0; + if (pa != NULL && pb != NULL) { + ok = ok && EC_POINT_cmp(group_b, pa, pb, ctx) == 0; + key_checked = 1; + } + } + if (!key_checked + && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { + const BIGNUM *pa = EC_KEY_get0_private_key(ec1); + const BIGNUM *pb = EC_KEY_get0_private_key(ec2); + + if (pa != NULL && pb != NULL) { + ok = ok && BN_cmp(pa, pb) == 0; + key_checked = 1; + } + } + ok = ok && key_checked; } BN_CTX_free(ctx); return ok; } +static int common_check_sm2(const EC_KEY *ec, int sm2_wanted) +{ + const EC_GROUP *ecg = NULL; + + /* + * sm2_wanted: import the keys or domparams only on SM2 Curve + * !sm2_wanted: import the keys or domparams only not on SM2 Curve + */ + if ((ecg = EC_KEY_get0_group(ec)) == NULL + || (sm2_wanted ^ (EC_GROUP_get_curve_name(ecg) == NID_sm2))) + return 0; + return 1; +} + static int common_import(void *keydata, int selection, const OSSL_PARAM params[], - int sm2_curve) + int sm2_wanted) { EC_KEY *ec = keydata; - const EC_GROUP *ecg = NULL; int ok = 1; if (!ossl_prov_is_running() || ec == NULL) @@ -353,7 +401,7 @@ int common_import(void *keydata, int selection, const OSSL_PARAM params[], * following combinations: * - domain parameters (+optional other params) * - public key with associated domain parameters (+optional other params) - * - private key with associated public key and domain parameters + * - private key with associated domain parameters and optional public key * (+optional other params) * * This means: @@ -363,29 +411,20 @@ int common_import(void *keydata, int selection, const OSSL_PARAM params[], */ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0) return 0; - if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 - && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0) - return 0; - if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) - ok = ok && ec_group_fromdata(ec, params); + ok = ok && ossl_ec_group_fromdata(ec, params); - /* - * sm2_curve: import the keys or domparams only on SM2 Curve - * !sm2_curve: import the keys or domparams only not on SM2 Curve - */ - if ((ecg = EC_KEY_get0_group(ec)) == NULL - || (sm2_curve ^ (EC_GROUP_get_curve_name(ecg) == NID_sm2))) + if (!common_check_sm2(ec, sm2_wanted)) return 0; if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { int include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0; - ok = ok && ec_key_fromdata(ec, params, include_private); + ok = ok && ossl_ec_key_fromdata(ec, params, include_private); } if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0) - ok = ok && ec_key_otherparams_fromdata(ec, params); + ok = ok && ossl_ec_key_otherparams_fromdata(ec, params); return ok; } @@ -438,24 +477,22 @@ int ec_export(void *keydata, int selection, OSSL_CALLBACK *param_cb, if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0) return 0; - if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0 - && (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) - return 0; tmpl = OSSL_PARAM_BLD_new(); if (tmpl == NULL) return 0; if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { - bnctx = BN_CTX_new_ex(ec_key_get_libctx(ec)); + bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec)); if (bnctx == NULL) { ok = 0; goto end; } BN_CTX_start(bnctx); - ok = ok && ec_group_todata(EC_KEY_get0_group(ec), tmpl, NULL, - ec_key_get_libctx(ec), ec_key_get0_propq(ec), - bnctx, &genbuf); + ok = ok && ossl_ec_group_todata(EC_KEY_get0_group(ec), tmpl, NULL, + ossl_ec_key_get_libctx(ec), + ossl_ec_key_get0_propq(ec), + bnctx, &genbuf); } if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { @@ -467,10 +504,14 @@ int ec_export(void *keydata, int selection, OSSL_CALLBACK *param_cb, if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0) ok = ok && otherparams_to_params(ec, tmpl, NULL); - if (ok && (params = OSSL_PARAM_BLD_to_param(tmpl)) != NULL) - ok = param_cb(params, cbarg); + if (!ok || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) { + ok = 0; + goto end; + } + + ok = param_cb(params, cbarg); + OSSL_PARAM_free(params); end: - OSSL_PARAM_BLD_free_params(params); OSSL_PARAM_BLD_free(tmpl); OPENSSL_free(pub_key); OPENSSL_free(genbuf); @@ -492,7 +533,8 @@ end: OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_GENERATOR, NULL, 0), \ OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_ORDER, NULL, 0), \ OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_COFACTOR, NULL, 0), \ - OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0) + OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0), \ + OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, NULL) # define EC_IMEXPORTABLE_PUBLIC_KEY \ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0) @@ -603,11 +645,13 @@ int common_get_params(void *key, OSSL_PARAM params[], int sm2) BN_CTX *bnctx = NULL; ecg = EC_KEY_get0_group(eck); - if (ecg == NULL) + if (ecg == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); return 0; + } - libctx = ec_key_get_libctx(eck); - propq = ec_key_get0_propq(eck); + libctx = ossl_ec_key_get_libctx(eck); + propq = ossl_ec_key_get0_propq(eck); bnctx = BN_CTX_new_ex(libctx); if (bnctx == NULL) @@ -658,6 +702,16 @@ int common_get_params(void *key, OSSL_PARAM params[], int sm2) goto err; } + if ((p = OSSL_PARAM_locate(params, + OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS)) + != NULL) { + int explicitparams = EC_KEY_decoded_from_explicit_params(eck); + + if (explicitparams < 0 + || !OSSL_PARAM_set_int(p, explicitparams)) + goto err; + } + if (!sm2) { if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL && !OSSL_PARAM_set_utf8_string(p, EC_DEFAULT_MD)) @@ -683,16 +737,22 @@ int common_get_params(void *key, OSSL_PARAM params[], int sm2) } if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL) { - p->return_size = EC_POINT_point2oct(EC_KEY_get0_group(key), - EC_KEY_get0_public_key(key), + const EC_POINT *ecp = EC_KEY_get0_public_key(key); + + if (ecp == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY); + goto err; + } + p->return_size = EC_POINT_point2oct(ecg, ecp, POINT_CONVERSION_UNCOMPRESSED, - p->data, p->return_size, bnctx); + p->data, p->data_size, bnctx); if (p->return_size == 0) goto err; } ret = ec_get_ecm_params(ecg, params) - && ec_group_todata(ecg, NULL, params, libctx, propq, bnctx, &genbuf) + && ossl_ec_group_todata(ecg, NULL, params, libctx, propq, bnctx, + &genbuf) && key_to_params(eck, NULL, params, 1, &pub_key) && otherparams_to_params(eck, NULL, params); err: @@ -727,11 +787,12 @@ static const OSSL_PARAM ec_known_gettable_params[] = { OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0), OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), + OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, NULL), EC_IMEXPORTABLE_DOM_PARAMETERS, EC2M_GETTABLE_DOM_PARAMS EC_IMEXPORTABLE_PUBLIC_KEY, - OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0), - OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0), + OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0), + OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0), EC_IMEXPORTABLE_PRIVATE_KEY, EC_IMEXPORTABLE_OTHER_PARAMETERS, OSSL_PARAM_END @@ -768,13 +829,16 @@ int ec_set_params(void *key, const OSSL_PARAM params[]) if (key == NULL) return 0; + if (params == NULL) + return 1; + - if (!ec_group_set_params((EC_GROUP *)EC_KEY_get0_group(key), params)) + if (!ossl_ec_group_set_params((EC_GROUP *)EC_KEY_get0_group(key), params)) return 0; p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY); if (p != NULL) { - BN_CTX *ctx = BN_CTX_new_ex(ec_key_get_libctx(key)); + BN_CTX *ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(key)); int ret = 1; if (ctx == NULL @@ -786,7 +850,7 @@ int ec_set_params(void *key, const OSSL_PARAM params[]) return 0; } - return ec_key_otherparams_fromdata(eck, params); + return ossl_ec_key_otherparams_fromdata(eck, params); } #ifndef FIPS_MODULE @@ -803,6 +867,7 @@ static const OSSL_PARAM sm2_known_gettable_params[] = { OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0), OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), + OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, NULL), EC_IMEXPORTABLE_DOM_PARAMETERS, EC_IMEXPORTABLE_PUBLIC_KEY, OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0), @@ -829,33 +894,37 @@ const OSSL_PARAM *sm2_settable_params(ossl_unused void *provctx) } static -int sm2_validate(const void *keydata, int selection) +int sm2_validate(const void *keydata, int selection, int checktype) { const EC_KEY *eck = keydata; - int ok = 0; + int ok = 1; BN_CTX *ctx = NULL; if (!ossl_prov_is_running()) return 0; - ctx = BN_CTX_new_ex(ec_key_get_libctx(eck)); + if ((selection & EC_POSSIBLE_SELECTIONS) == 0) + return 1; /* nothing to validate */ + + ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eck)); if (ctx == NULL) return 0; - if ((selection & EC_POSSIBLE_SELECTIONS) != 0) - ok = 1; - if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) ok = ok && EC_GROUP_check(EC_KEY_get0_group(eck), ctx); - if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) - ok = ok && ec_key_public_check(eck, ctx); + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { + if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK) + ok = ok && ossl_ec_key_public_check_quick(eck, ctx); + else + ok = ok && ossl_ec_key_public_check(eck, ctx); + } if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) - ok = ok && sm2_key_private_check(eck); + ok = ok && ossl_sm2_key_private_check(eck); if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR) - ok = ok && ec_key_pairwise_check(eck, ctx); + ok = ok && ossl_ec_key_pairwise_check(eck, ctx); BN_CTX_free(ctx); return ok; @@ -864,40 +933,44 @@ int sm2_validate(const void *keydata, int selection) #endif static -int ec_validate(const void *keydata, int selection) +int ec_validate(const void *keydata, int selection, int checktype) { const EC_KEY *eck = keydata; - int ok = 0; + int ok = 1; BN_CTX *ctx = NULL; if (!ossl_prov_is_running()) return 0; - ctx = BN_CTX_new_ex(ec_key_get_libctx(eck)); + if ((selection & EC_POSSIBLE_SELECTIONS) == 0) + return 1; /* nothing to validate */ + + ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eck)); if (ctx == NULL) return 0; - if ((selection & EC_POSSIBLE_SELECTIONS) != 0) - ok = 1; - if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { int flags = EC_KEY_get_flags(eck); if ((flags & EC_FLAG_CHECK_NAMED_GROUP) != 0) ok = ok && EC_GROUP_check_named_curve(EC_KEY_get0_group(eck), - (flags & EC_FLAG_CHECK_NAMED_GROUP_NIST) != 0, ctx); + (flags & EC_FLAG_CHECK_NAMED_GROUP_NIST) != 0, ctx) > 0; else ok = ok && EC_GROUP_check(EC_KEY_get0_group(eck), ctx); } - if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) - ok = ok && ec_key_public_check(eck, ctx); + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { + if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK) + ok = ok && ossl_ec_key_public_check_quick(eck, ctx); + else + ok = ok && ossl_ec_key_public_check(eck, ctx); + } if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) - ok = ok && ec_key_private_check(eck); + ok = ok && ossl_ec_key_private_check(eck); if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR) - ok = ok && ec_key_pairwise_check(eck, ctx); + ok = ok && ossl_ec_key_pairwise_check(eck, ctx); BN_CTX_free(ctx); return ok; @@ -916,9 +989,12 @@ struct ec_gen_ctx { int selection; int ecdh_mode; EC_GROUP *gen_group; + unsigned char *dhkem_ikm; + size_t dhkem_ikmlen; }; -static void *ec_gen_init(void *provctx, int selection) +static void *ec_gen_init(void *provctx, int selection, + const OSSL_PARAM params[]) { OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx); struct ec_gen_ctx *gctx = NULL; @@ -930,10 +1006,33 @@ static void *ec_gen_init(void *provctx, int selection) gctx->libctx = libctx; gctx->selection = selection; gctx->ecdh_mode = 0; + if (!ec_gen_set_params(gctx, params)) { + OPENSSL_free(gctx); + gctx = NULL; + } } return gctx; } +#ifndef FIPS_MODULE +# ifndef OPENSSL_NO_SM2 +static void *sm2_gen_init(void *provctx, int selection, + const OSSL_PARAM params[]) +{ + struct ec_gen_ctx *gctx = ec_gen_init(provctx, selection, params); + + if (gctx != NULL) { + if (gctx->group_name != NULL) + return gctx; + if ((gctx->group_name = OPENSSL_strdup("sm2")) != NULL) + return gctx; + ec_gen_cleanup(gctx); + } + return NULL; +} +# endif +#endif + static int ec_gen_set_group(void *genctx, const EC_GROUP *src) { struct ec_gen_ctx *gctx = genctx; @@ -1024,6 +1123,9 @@ static int ec_gen_set_params(void *genctx, const OSSL_PARAM params[]) COPY_OCTET_PARAM(params, OSSL_PKEY_PARAM_EC_GENERATOR, gctx->gen, gctx->gen_len); + COPY_OCTET_PARAM(params, OSSL_PKEY_PARAM_DHKEM_IKM, gctx->dhkem_ikm, + gctx->dhkem_ikmlen); + ret = 1; err: EC_GROUP_free(group); @@ -1102,12 +1204,13 @@ build: ret = 1; err: - OSSL_PARAM_BLD_free_params(params); + OSSL_PARAM_free(params); OSSL_PARAM_BLD_free(bld); return ret; } -static const OSSL_PARAM *ec_gen_settable_params(void *provctx) +static const OSSL_PARAM *ec_gen_settable_params(ossl_unused void *genctx, + ossl_unused void *provctx) { static OSSL_PARAM settable[] = { OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), @@ -1122,6 +1225,7 @@ static const OSSL_PARAM *ec_gen_settable_params(void *provctx) OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_ORDER, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_COFACTOR, NULL, 0), OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0), + OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM, NULL, 0), OSSL_PARAM_END }; @@ -1156,14 +1260,14 @@ static void *ec_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) goto err; } else { if (gctx->encoding != NULL) { - int flags = ec_encoding_name2id(gctx->encoding); + int flags = ossl_ec_encoding_name2id(gctx->encoding); if (flags < 0) goto err; EC_GROUP_set_asn1_flag(gctx->gen_group, flags); } if (gctx->pt_format != NULL) { - int format = ec_pt_format_name2id(gctx->pt_format); + int format = ossl_ec_pt_format_name2id(gctx->pt_format); if (format < 0) goto err; @@ -1175,14 +1279,22 @@ static void *ec_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) ret = ec_gen_assign_group(ec, gctx->gen_group); /* Whether you want it or not, you get a keypair, not just one half */ - if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) - ret = ret && EC_KEY_generate_key(ec); + if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { +#ifndef FIPS_MODULE + if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) + ret = ret && ossl_ec_generate_key_dhkem(ec, gctx->dhkem_ikm, + gctx->dhkem_ikmlen); + else +#endif + ret = ret && EC_KEY_generate_key(ec); + } if (gctx->ecdh_mode != -1) - ret = ret && ec_set_ecdh_cofactor_mode(ec, gctx->ecdh_mode); + ret = ret && ossl_ec_set_ecdh_cofactor_mode(ec, gctx->ecdh_mode); if (gctx->group_check != NULL) - ret = ret && ec_set_check_group_type_from_name(ec, gctx->group_check); + ret = ret && ossl_ec_set_check_group_type_from_name(ec, + gctx->group_check); if (ret) return ec; err: @@ -1211,14 +1323,14 @@ static void *sm2_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) goto err; } else { if (gctx->encoding) { - int flags = ec_encoding_name2id(gctx->encoding); + int flags = ossl_ec_encoding_name2id(gctx->encoding); if (flags < 0) goto err; EC_GROUP_set_asn1_flag(gctx->gen_group, flags); } if (gctx->pt_format != NULL) { - int format = ec_pt_format_name2id(gctx->pt_format); + int format = ossl_ec_pt_format_name2id(gctx->pt_format); if (format < 0) goto err; @@ -1230,14 +1342,8 @@ static void *sm2_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) ret = ec_gen_assign_group(ec, gctx->gen_group); /* Whether you want it or not, you get a keypair, not just one half */ - if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { - /* - * For SM2, we need a new flag to indicate the 'generate' function - * to use a new range - */ - EC_KEY_set_flags(ec, EC_FLAG_SM2_RANGE); + if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) ret = ret && EC_KEY_generate_key(ec); - } if (ret) return ec; @@ -1256,6 +1362,7 @@ static void ec_gen_cleanup(void *genctx) if (gctx == NULL) return; + OPENSSL_clear_free(gctx->dhkem_ikm, gctx->dhkem_ikmlen); EC_GROUP_free(gctx->gen_group); BN_free(gctx->p); BN_free(gctx->a); @@ -1271,13 +1378,18 @@ static void ec_gen_cleanup(void *genctx) OPENSSL_free(gctx); } -void *ec_load(const void *reference, size_t reference_sz) +static void *common_load(const void *reference, size_t reference_sz, + int sm2_wanted) { EC_KEY *ec = NULL; if (ossl_prov_is_running() && reference_sz == sizeof(ec)) { /* The contents of the reference is the address to our object */ ec = *(EC_KEY **)reference; + + if (!common_check_sm2(ec, sm2_wanted)) + return NULL; + /* We grabbed, so we detach it */ *(EC_KEY **)reference = NULL; return ec; @@ -1285,6 +1397,27 @@ void *ec_load(const void *reference, size_t reference_sz) return NULL; } +static void *ec_load(const void *reference, size_t reference_sz) +{ + return common_load(reference, reference_sz, 0); +} + +#ifndef FIPS_MODULE +# ifndef OPENSSL_NO_SM2 +static void *sm2_load(const void *reference, size_t reference_sz) +{ + return common_load(reference, reference_sz, 1); +} +# endif +#endif + +static void *ec_dup(const void *keydata_from, int selection) +{ + if (ossl_prov_is_running()) + return ossl_ec_key_dup(keydata_from, selection); + return NULL; +} + const OSSL_DISPATCH ossl_ec_keymgmt_functions[] = { { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata }, { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ec_gen_init }, @@ -1310,14 +1443,15 @@ const OSSL_DISPATCH ossl_ec_keymgmt_functions[] = { { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types }, { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME, (void (*)(void))ec_query_operation_name }, - { 0, NULL } + { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ec_dup }, + OSSL_DISPATCH_END }; #ifndef FIPS_MODULE # ifndef OPENSSL_NO_SM2 -const OSSL_DISPATCH sm2_keymgmt_functions[] = { - { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata }, - { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ec_gen_init }, +const OSSL_DISPATCH ossl_sm2_keymgmt_functions[] = { + { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))sm2_newdata }, + { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))sm2_gen_init }, { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))ec_gen_set_template }, { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ec_gen_set_params }, @@ -1325,6 +1459,7 @@ const OSSL_DISPATCH sm2_keymgmt_functions[] = { (void (*)(void))ec_gen_settable_params }, { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))sm2_gen }, { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ec_gen_cleanup }, + { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))sm2_load }, { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata }, { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))sm2_get_params }, { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))sm2_gettable_params }, @@ -1339,7 +1474,8 @@ const OSSL_DISPATCH sm2_keymgmt_functions[] = { { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types }, { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME, (void (*)(void))sm2_query_operation_name }, - { 0, NULL } + { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ec_dup }, + OSSL_DISPATCH_END }; # endif #endif