openssl: Move shared secret calculation to get_shared_secret()

This commit is contained in:
Tobias Brunner 2021-07-23 16:44:07 +02:00
parent b3c9c005b6
commit 65dd5a7f38
4 changed files with 48 additions and 76 deletions

View File

@ -63,11 +63,6 @@ struct private_openssl_diffie_hellman_t {
* Shared secret
*/
chunk_t shared_secret;
/**
* True if shared secret is computed
*/
bool computed;
};
METHOD(key_exchange_t, get_public_key, bool,
@ -85,15 +80,24 @@ METHOD(key_exchange_t, get_public_key, bool,
METHOD(key_exchange_t, get_shared_secret, bool,
private_openssl_diffie_hellman_t *this, chunk_t *secret)
{
if (!this->computed)
int len;
if (!this->shared_secret.len)
{
return FALSE;
this->shared_secret = chunk_alloc(DH_size(this->dh));
memset(this->shared_secret.ptr, 0xFF, this->shared_secret.len);
len = DH_compute_key(this->shared_secret.ptr, this->pub_key, this->dh);
if (len < 0)
{
DBG1(DBG_LIB, "DH shared secret computation failed");
chunk_clear(&this->shared_secret);
return FALSE;
}
this->shared_secret.len = len;
}
/* shared secret should requires a len according the DH group */
*secret = chunk_alloc(DH_size(this->dh));
memset(secret->ptr, 0, secret->len);
memcpy(secret->ptr + secret->len - this->shared_secret.len,
this->shared_secret.ptr, this->shared_secret.len);
/* shared secret requires a length according to the DH group */
*secret = chunk_copy_pad(chunk_alloc(DH_size(this->dh)),
this->shared_secret, 0);
return TRUE;
}
@ -101,25 +105,12 @@ METHOD(key_exchange_t, get_shared_secret, bool,
METHOD(key_exchange_t, set_public_key, bool,
private_openssl_diffie_hellman_t *this, chunk_t value)
{
int len;
if (!key_exchange_verify_pubkey(this->group, value))
{
return FALSE;
}
BN_bin2bn(value.ptr, value.len, this->pub_key);
chunk_clear(&this->shared_secret);
this->shared_secret.ptr = malloc(DH_size(this->dh));
memset(this->shared_secret.ptr, 0xFF, this->shared_secret.len);
len = DH_compute_key(this->shared_secret.ptr, this->pub_key, this->dh);
if (len < 0)
{
DBG1(DBG_LIB, "DH shared secret computation failed");
return FALSE;
}
this->shared_secret.len = len;
this->computed = TRUE;
return TRUE;
}
@ -136,7 +127,6 @@ METHOD(key_exchange_t, set_seed, bool,
return FALSE;
}
chunk_clear(&this->shared_secret);
this->computed = FALSE;
return DH_generate_key(this->dh);
}
return FALSE;
@ -220,9 +210,7 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create(
}
this->group = group;
this->computed = FALSE;
this->pub_key = BN_new();
this->shared_secret = chunk_empty;
if (group == MODP_CUSTOM)
{

View File

@ -51,6 +51,11 @@ struct private_openssl_ec_diffie_hellman_t {
*/
EVP_PKEY *key;
/**
* Public key provided by peer
*/
EVP_PKEY *pub;
/**
* EC group
*/
@ -186,50 +191,34 @@ error:
METHOD(key_exchange_t, set_public_key, bool,
private_openssl_ec_diffie_hellman_t *this, chunk_t value)
{
EVP_PKEY *pub = NULL;
chunk_clear(&this->shared_secret);
this->computed = FALSE;
if (!key_exchange_verify_pubkey(this->group, value))
{
return FALSE;
}
pub = EVP_PKEY_new();
if (!pub)
if (!this->pub)
{
goto error;
this->pub = EVP_PKEY_new();
}
#if OPENSSL_VERSION_NUMBER < 0x1010000fL
if (!chunk2ecp(this->ec_group, value, pub))
if (!chunk2ecp(this->ec_group, value, this->pub))
{
DBG1(DBG_LIB, "ECDH public value is malformed");
goto error;
return FALSE;
}
#else
/* OpenSSL expects the pubkey in the format specified in section 2.3.4 of
* SECG SEC 1, i.e. prefixed with 0x04 to indicate an uncompressed point */
value = chunk_cata("cc", chunk_from_chars(0x04), value);
if (EVP_PKEY_copy_parameters(pub, this->key) <= 0 ||
EVP_PKEY_set1_tls_encodedpoint(pub, value.ptr, value.len) <= 0)
if (EVP_PKEY_copy_parameters(this->pub, this->key) <= 0 ||
EVP_PKEY_set1_tls_encodedpoint(this->pub, value.ptr, value.len) <= 0)
{
DBG1(DBG_LIB, "ECDH public value is malformed");
goto error;
return FALSE;
}
#endif
if (!openssl_compute_shared_key(this->key, pub, &this->shared_secret))
{
DBG1(DBG_LIB, "ECDH shared secret computation failed");
goto error;
}
this->computed = TRUE;
error:
EVP_PKEY_free(pub);
return this->computed;
return TRUE;
}
METHOD(key_exchange_t, get_public_key, bool,
@ -304,8 +293,10 @@ error:
METHOD(key_exchange_t, get_shared_secret, bool,
private_openssl_ec_diffie_hellman_t *this, chunk_t *secret)
{
if (!this->computed)
if (!this->shared_secret.len &&
!openssl_compute_shared_key(this->key, this->pub, &this->shared_secret))
{
DBG1(DBG_LIB, "ECDH shared secret computation failed");
return FALSE;
}
*secret = chunk_clone(this->shared_secret);
@ -323,6 +314,7 @@ METHOD(key_exchange_t, destroy, void,
{
EC_GROUP_free(this->ec_group);
EVP_PKEY_free(this->key);
EVP_PKEY_free(this->pub);
chunk_clear(&this->shared_secret);
free(this);
}

View File

@ -62,6 +62,7 @@ bool openssl_compute_shared_key(EVP_PKEY *priv, EVP_PKEY *pub, chunk_t *shared)
if (EVP_PKEY_derive(ctx, shared->ptr, &shared->len) <= 0)
{
chunk_clear(shared);
goto error;
}

View File

@ -45,15 +45,15 @@ struct private_key_exchange_t {
*/
EVP_PKEY *key;
/**
* Public key provided by peer
*/
EVP_PKEY *pub;
/**
* Shared secret
*/
chunk_t shared_secret;
/**
* True if shared secret is computed
*/
bool computed;
};
/**
@ -75,33 +75,20 @@ static int map_key_type(key_exchange_method_t ke)
METHOD(key_exchange_t, set_public_key, bool,
private_key_exchange_t *this, chunk_t value)
{
EVP_PKEY *pub;
if (!key_exchange_verify_pubkey(this->ke, value))
{
return FALSE;
}
pub = EVP_PKEY_new_raw_public_key(map_key_type(this->ke), NULL,
value.ptr, value.len);
if (!pub)
EVP_PKEY_free(this->pub);
this->pub = EVP_PKEY_new_raw_public_key(map_key_type(this->ke), NULL,
value.ptr, value.len);
if (!this->pub)
{
DBG1(DBG_LIB, "%N public value is malformed",
key_exchange_method_names, this->ke);
return FALSE;
}
chunk_clear(&this->shared_secret);
if (!openssl_compute_shared_key(this->key, pub, &this->shared_secret))
{
DBG1(DBG_LIB, "%N shared secret computation failed",
key_exchange_method_names, this->ke);
EVP_PKEY_free(pub);
return FALSE;
}
this->computed = TRUE;
EVP_PKEY_free(pub);
return TRUE;
}
@ -141,8 +128,11 @@ METHOD(key_exchange_t, set_seed, bool,
METHOD(key_exchange_t, get_shared_secret, bool,
private_key_exchange_t *this, chunk_t *secret)
{
if (!this->computed)
if (!this->shared_secret.len &&
!openssl_compute_shared_key(this->key, this->pub, &this->shared_secret))
{
DBG1(DBG_LIB, "%N shared secret computation failed",
key_exchange_method_names, this->ke);
return FALSE;
}
*secret = chunk_clone(this->shared_secret);
@ -159,6 +149,7 @@ METHOD(key_exchange_t, destroy, void,
private_key_exchange_t *this)
{
EVP_PKEY_free(this->key);
EVP_PKEY_free(this->pub);
chunk_clear(&this->shared_secret);
free(this);
}