From 9e2c03582de42e8ac5aa23412affcb9645395e94 Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Tue, 24 Mar 2020 16:31:43 +0100 Subject: [PATCH] PROV: Fix EC_KEY exporters to allow domain parameter keys The provider key export functions for EC_KEY assumed that a public key is always present, and would fail if not. This blocks any attempt to export a key structure with only domain parameters. This is similar to earlier work done in EVP_PKEY_ASN1_METHODs. Reviewed-by: Shane Lontis (Merged from https://github.com/openssl/openssl/pull/11394) --- crypto/ec/ec_backend.c | 30 +++++++++++--------- providers/implementations/keymgmt/ec_kmgmt.c | 26 ++++++++--------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/crypto/ec/ec_backend.c b/crypto/ec/ec_backend.c index b4520a7c60..98dd0ecf5d 100644 --- a/crypto/ec/ec_backend.c +++ b/crypto/ec/ec_backend.c @@ -63,7 +63,7 @@ int ec_set_param_ecdh_cofactor_mode(EC_KEY *ec, const OSSL_PARAM *p) */ int ec_key_fromdata(EC_KEY *ec, const OSSL_PARAM params[], int include_private) { - const OSSL_PARAM *param_priv_key, *param_pub_key; + const OSSL_PARAM *param_priv_key = NULL, *param_pub_key = NULL; BN_CTX *ctx = NULL; BIGNUM *priv_key = NULL; unsigned char *pub_key = NULL; @@ -76,24 +76,25 @@ int ec_key_fromdata(EC_KEY *ec, const OSSL_PARAM params[], int include_private) if (ecg == NULL) return 0; - param_priv_key = - OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY); param_pub_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY); + if (include_private) + param_priv_key = + OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY); ctx = BN_CTX_new_ex(ec_key_get_libctx(ec)); if (ctx == NULL) goto err; - /* - * We want to have at least a public key either way, so we end up - * requiring it unconditionally. - */ - if (param_pub_key == NULL - || !OSSL_PARAM_get_octet_string(param_pub_key, - (void **)&pub_key, 0, &pub_key_len) + + /* OpenSSL decree: If there's a private key, there must be a public key */ + if (param_priv_key != NULL && param_pub_key == NULL) + goto err; + + if (param_pub_key != NULL) + if (!OSSL_PARAM_get_octet_string(param_pub_key, + (void **)&pub_key, 0, &pub_key_len) || (pub_point = EC_POINT_new(ecg)) == NULL - || !EC_POINT_oct2point(ecg, pub_point, - pub_key, pub_key_len, ctx)) + || !EC_POINT_oct2point(ecg, pub_point, pub_key, pub_key_len, ctx)) goto err; if (param_priv_key != NULL && include_private) { @@ -150,10 +151,11 @@ int ec_key_fromdata(EC_KEY *ec, const OSSL_PARAM params[], int include_private) } if (priv_key != NULL - && !EC_KEY_set_private_key(ec, priv_key)) + && !EC_KEY_set_private_key(ec, priv_key)) goto err; - if (!EC_KEY_set_public_key(ec, pub_point)) + if (pub_point != NULL + && !EC_KEY_set_public_key(ec, pub_point)) goto err; ok = 1; diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c index 354ca0c5bb..e2cc9ca7ed 100644 --- a/providers/implementations/keymgmt/ec_kmgmt.c +++ b/providers/implementations/keymgmt/ec_kmgmt.c @@ -109,25 +109,23 @@ int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl, int include_private size_t pub_key_len = 0; int ret = 0; - if (eckey == NULL) + if (eckey == NULL + || (ecg = EC_KEY_get0_group(eckey)) == NULL) return 0; - ecg = EC_KEY_get0_group(eckey); priv_key = EC_KEY_get0_private_key(eckey); pub_point = EC_KEY_get0_public_key(eckey); - /* group and public_key must be present, priv_key is optional */ - if (ecg == NULL || pub_point == NULL) - return 0; - if ((pub_key_len = EC_POINT_point2buf(ecg, pub_point, - POINT_CONVERSION_COMPRESSED, - &pub_key, NULL)) == 0) - return 0; - - if (!ossl_param_bld_push_octet_string(tmpl, - OSSL_PKEY_PARAM_PUB_KEY, - pub_key, pub_key_len)) - goto err; + if (pub_point != NULL) { + /* convert pub_point to a octet string according to the SECG standard */ + if ((pub_key_len = EC_POINT_point2buf(ecg, pub_point, + POINT_CONVERSION_COMPRESSED, + &pub_key, NULL)) == 0 + || !ossl_param_bld_push_octet_string(tmpl, + OSSL_PKEY_PARAM_PUB_KEY, + pub_key, pub_key_len)) + goto err; + } if (priv_key != NULL && include_private) { size_t sz; -- 2.25.1