]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
wolfssl: Unlock keys if necessary when using FIPS module
authorJuliusz Sosinowicz <juliusz@wolfssl.com>
Wed, 23 Apr 2025 14:32:52 +0000 (16:32 +0200)
committerTobias Brunner <tobias@strongswan.org>
Mon, 2 Jun 2025 07:15:05 +0000 (09:15 +0200)
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.

src/libstrongswan/plugins/wolfssl/wolfssl_diffie_hellman.c
src/libstrongswan/plugins/wolfssl/wolfssl_ec_diffie_hellman.c
src/libstrongswan/plugins/wolfssl/wolfssl_kdf.c

index b32b40e058d35f84a27e46f9f27f27a2d909a095..7591196068c38cea62ceeda2779694498d3626d9 100644 (file)
@@ -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);
index 969099b790c1609a2287e87da5e2ff15c261af3e..94a92ff0bce59ba187b76d933a61528eb3d6b659 100644 (file)
@@ -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);
index da06cab310a1814af8f4c96d401c8f9c7058aed2..dd5a87d78bb3c4a61aa9b760ef84a5368f735c3c 100644 (file)
@@ -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,