openssl: Use ECDH_compute_key() for 'x-coordinate only' setting

ECDH_compute_key() was not used because it only gives x-coordinate of
the result. However, the default setting, as per the errata mentioned,
is to use x-coordinate only.
Use ECDH_compute_key() for this setting as it additionally allows HW
offload of the computation using dynamic engine feature in OpenSSL.
EC_POINT_mul() doesn't allow HW offload.

Signed-off-by: Mahantesh Salimath <[email protected]>
This commit is contained in:
Mahantesh Salimath
2021-01-20 17:53:35 +01:00
committed by Tobias Brunner
parent aa3d5bf791
commit 7733ff7d4e
@@ -163,14 +163,6 @@ error:
/**
* Compute the shared secret.
*
* We cannot use the function ECDH_compute_key() because that returns only the
* x coordinate of the shared secret point (which is defined, for instance, in
* 'NIST SP 800-56A').
* However, we need both coordinates as RFC 4753 says: "The Diffie-Hellman
* public value is obtained by concatenating the x and y values. The format
* of the Diffie-Hellman shared secret value is the same as that of the
* Diffie-Hellman public value."
*/
static bool compute_shared_key(private_openssl_ec_diffie_hellman_t *this,
chunk_t *shared_secret)
@@ -178,34 +170,54 @@ static bool compute_shared_key(private_openssl_ec_diffie_hellman_t *this,
const BIGNUM *priv_key;
EC_POINT *secret = NULL;
bool x_coordinate_only, ret = FALSE;
priv_key = EC_KEY_get0_private_key(this->key);
if (!priv_key)
{
goto error;
}
secret = EC_POINT_new(this->ec_group);
if (!secret)
{
goto error;
}
if (!EC_POINT_mul(this->ec_group, secret, NULL, this->pub_key, priv_key, NULL))
{
goto error;
}
int len;
/*
* The default setting ecp_x_coordinate_only = TRUE
* applies the following errata for RFC 4753:
* http://www.rfc-editor.org/errata_search.php?eid=9
* ECDH_compute_key() is used under this setting as
* it also facilitates hardware offload through the use of
* dynamic engines in OpenSSL.
*/
x_coordinate_only = lib->settings->get_bool(lib->settings,
"%s.ecp_x_coordinate_only", TRUE, lib->ns);
if (!ecp2chunk(this->ec_group, secret, shared_secret, x_coordinate_only))
if (x_coordinate_only)
{
goto error;
*shared_secret = chunk_alloc(EC_FIELD_ELEMENT_LEN(this->ec_group));
len = ECDH_compute_key(shared_secret->ptr, shared_secret->len,
this->pub_key, this->key, NULL);
if (len <= 0)
{
chunk_free(shared_secret);
goto error;
}
shared_secret->len = len;
}
else
{
priv_key = EC_KEY_get0_private_key(this->key);
if (!priv_key)
{
goto error;
}
secret = EC_POINT_new(this->ec_group);
if (!secret)
{
goto error;
}
if (!EC_POINT_mul(this->ec_group, secret, NULL, this->pub_key, priv_key,
NULL))
{
goto error;
}
if (!ecp2chunk(this->ec_group, secret, shared_secret, x_coordinate_only))
{
goto error;
}
}
ret = TRUE;