wolfssl: Unlock keys if necessary when using FIPS module

Wrap the functions that require it in PRIVATE_KEY_UNLOCK/PRIVATE_KEY_LOCK.
This can't be done at plugin initialization because it needs to be done
for every thread. strongSwan currently doesn't provide on-thread-create
callbacks for plugins so we need to wrap each direct call. Another reason
to do so is that some functions we call (e.g. wc_EccKeyToDer) internally
call PRIVATE_KEY_UNLOCK/PRIVATE_KEY_LOCK and would leave the keys locked
for that particular thread.
This commit is contained in:
Juliusz Sosinowicz
2025-06-02 09:15:05 +02:00
committed by Tobias Brunner
parent 85eb5c7812
commit f38bb91654
3 changed files with 38 additions and 16 deletions
@@ -90,12 +90,17 @@ METHOD(key_exchange_t, get_shared_secret, bool,
private_wolfssl_diffie_hellman_t *this, chunk_t *secret)
{
word32 len;
int ret;
if (!this->shared_secret.len)
{
this->shared_secret = chunk_alloc(this->len);
if (wc_DhAgree(&this->dh, this->shared_secret.ptr, &len, this->priv.ptr,
this->priv.len, this->other.ptr, this->other.len) != 0)
PRIVATE_KEY_UNLOCK();
ret = wc_DhAgree(&this->dh, this->shared_secret.ptr, &len,
this->priv.ptr, this->priv.len, this->other.ptr,
this->other.len);
PRIVATE_KEY_LOCK();
if (ret != 0)
{
DBG1(DBG_LIB, "DH shared secret computation failed");
chunk_free(&this->shared_secret);
@@ -132,6 +137,7 @@ METHOD(key_exchange_t, set_seed, bool,
bool success = FALSE;
chunk_t g;
word32 len;
int ret;
chunk_clear(&this->priv);
this->priv = chunk_clone(value);
@@ -140,8 +146,11 @@ METHOD(key_exchange_t, set_seed, bool,
if (wolfssl_mp2chunk(&this->dh.g, &g))
{
len = this->pub.len;
if (wc_DhAgree(&this->dh, this->pub.ptr, &len, this->priv.ptr,
this->priv.len, g.ptr, g.len) == 0)
PRIVATE_KEY_UNLOCK();
ret = wc_DhAgree(&this->dh, this->pub.ptr, &len, this->priv.ptr,
this->priv.len, g.ptr, g.len);
PRIVATE_KEY_LOCK();
if (ret == 0)
{
this->pub.len = len;
success = TRUE;
@@ -220,6 +229,7 @@ static wolfssl_diffie_hellman_t *create_generic(key_exchange_method_t group,
private_wolfssl_diffie_hellman_t *this;
word32 privLen, pubLen;
WC_RNG rng;
int ret;
INIT(this,
.public = {
@@ -262,8 +272,11 @@ static wolfssl_diffie_hellman_t *create_generic(key_exchange_method_t group,
privLen = this->priv.len;
pubLen = this->pub.len;
/* generate my public and private values */
if (wc_DhGenerateKeyPair(&this->dh, &rng, this->priv.ptr, &privLen,
this->pub.ptr, &pubLen) != 0)
PRIVATE_KEY_UNLOCK();
ret = wc_DhGenerateKeyPair(&this->dh, &rng, this->priv.ptr, &privLen,
this->pub.ptr, &pubLen);
PRIVATE_KEY_LOCK();
if (ret != 0)
{
wc_FreeRng(&rng);
destroy(this);
@@ -219,6 +219,7 @@ METHOD(key_exchange_t, set_seed, bool,
static bool compute_shared_key(private_wolfssl_ec_diffie_hellman_t *this)
{
word32 len;
int ret;
#ifdef USE_RNG_FOR_TIMING_RESISTANCE
WC_RNG rng;
@@ -237,8 +238,11 @@ static bool compute_shared_key(private_wolfssl_ec_diffie_hellman_t *this)
this->shared_secret = chunk_alloc(this->keysize);
len = this->shared_secret.len;
if (wc_ecc_shared_secret(&this->key, &this->pubkey, this->shared_secret.ptr,
&len) != 0)
PRIVATE_KEY_UNLOCK();
ret = wc_ecc_shared_secret(&this->key, &this->pubkey,
this->shared_secret.ptr, &len);
PRIVATE_KEY_LOCK();
if (ret != 0)
{
DBG1(DBG_LIB, "ECDH shared secret computation failed");
chunk_clear(&this->shared_secret);
@@ -82,22 +82,27 @@ METHOD(kdf_t, get_length, size_t,
METHOD(kdf_t, get_bytes, bool,
private_kdf_t *this, size_t out_len, uint8_t *buffer)
{
int ret;
if (this->type == KDF_PRF)
{
if (out_len != get_length(this) ||
wc_HKDF_Extract(this->hash, this->salt.ptr, this->salt.len,
this->key.ptr, this->key.len, buffer))
if (out_len != get_length(this))
{
return FALSE;
}
return TRUE;
PRIVATE_KEY_UNLOCK();
ret = wc_HKDF_Extract(this->hash, this->salt.ptr, this->salt.len,
this->key.ptr, this->key.len, buffer);
PRIVATE_KEY_LOCK();
}
if (wc_HKDF_Expand(this->hash, this->key.ptr, this->key.len,
this->salt.ptr, this->salt.len, buffer, out_len))
else
{
return FALSE;
PRIVATE_KEY_UNLOCK();
ret = wc_HKDF_Expand(this->hash, this->key.ptr, this->key.len,
this->salt.ptr, this->salt.len, buffer, out_len);
PRIVATE_KEY_LOCK();
}
return TRUE;
return ret == 0;
}
METHOD(kdf_t, allocate_bytes, bool,