From 0d7ef87f0974ff0d2ee06d32d09148e0c5488224 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 16 Mar 2026 14:55:06 +0100 Subject: [PATCH 01/16] Fix bounds check in session deserialization F-717 --- src/ssl_sess.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/ssl_sess.c b/src/ssl_sess.c index 93b23970d27..e1c3cab7b73 100644 --- a/src/ssl_sess.c +++ b/src/ssl_sess.c @@ -2930,17 +2930,21 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, #endif #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) #ifdef WOLFSSL_TLS13 - if (i - idx < (OPAQUE32_LEN * 2)) { + +#ifdef WOLFSSL_32BIT_MILLI_TIME + if (i - idx < OPAQUE32_LEN) { ret = BUFFER_ERROR; goto end; } -#ifdef WOLFSSL_32BIT_MILLI_TIME ato32(data + idx, &s->ticketSeen); idx += OPAQUE32_LEN; #else + if (i - idx < (OPAQUE32_LEN * 2)) { + ret = BUFFER_ERROR; + goto end; + } { word32 seenHi, seenLo; - ato32(data + idx, &seenHi); idx += OPAQUE32_LEN; ato32(data + idx, &seenLo); @@ -2948,6 +2952,11 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, s->ticketSeen = ((sword64)seenHi << 32) + seenLo; } #endif + + if (i - idx < OPAQUE32_LEN) { + ret = BUFFER_ERROR; + goto end; + } ato32(data + idx, &s->ticketAdd); idx += OPAQUE32_LEN; if (i - idx < OPAQUE8_LEN) { From 3ff051f3e4c3d905fd9ebdc5018c73da2126ebe3 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 16 Mar 2026 14:55:06 +0100 Subject: [PATCH 02/16] Use secure wipe for RSA temporary F-718 --- src/pk_rsa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pk_rsa.c b/src/pk_rsa.c index b454ac79e23..c102f4ec21f 100644 --- a/src/pk_rsa.c +++ b/src/pk_rsa.c @@ -3899,7 +3899,7 @@ int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa) } } - mp_clear(t); + mp_forcezero(t); #ifdef WOLFSSL_SMALL_STACK if (rsa != NULL) { From a9a9eae4d9a252b87fb22ee5e50f62dc2a7f65db Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 16 Mar 2026 14:55:06 +0100 Subject: [PATCH 03/16] Fix error propagation in InitSSL QUIC path F-719 --- src/internal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal.c b/src/internal.c index 7897a294bfa..7196f2d8287 100644 --- a/src/internal.c +++ b/src/internal.c @@ -8106,7 +8106,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) if (ctx->quic.method) { ret = wolfSSL_set_quic_method(ssl, ctx->quic.method); if (ret != WOLFSSL_SUCCESS) - return ret; + return WOLFSSL_FATAL_ERROR; } #endif From 4596e9e1a7ebc711802f9da99e70c3d894f52c7b Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 16 Mar 2026 14:55:07 +0100 Subject: [PATCH 04/16] Fix error return in InitSSL verify param path F-720 --- src/internal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal.c b/src/internal.c index 7196f2d8287..22984234406 100644 --- a/src/internal.c +++ b/src/internal.c @@ -7956,7 +7956,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) (unsigned long)wolfSSL_X509_VERIFY_PARAM_get_flags( wolfSSL_CTX_get0_param(ctx))) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("ssl->param set flags error"); - return WOLFSSL_FAILURE; + return BAD_STATE_E; } #endif From c6f41bce2f786e654d90bbe9158f8b287c703c52 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 16 Mar 2026 14:55:07 +0100 Subject: [PATCH 05/16] Fix memory leak on hash failure in LoadCertByIssuer F-721 --- src/internal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal.c b/src/internal.c index 22984234406..ce82d0f0bee 100644 --- a/src/internal.c +++ b/src/internal.c @@ -14957,6 +14957,7 @@ int LoadCertByIssuer(WOLFSSL_X509_STORE* store, X509_NAME* issuer, int type) #elif !defined(NO_SHA) retHash = wc_ShaHash((const byte*)pbuf, (word32)len, dgt); #endif + wolfSSL_OPENSSL_free(pbuf); if (retHash == 0) { /* 4 bytes in little endian as unsigned long */ hash = (((unsigned long)dgt[3] << 24) | @@ -14967,7 +14968,6 @@ int LoadCertByIssuer(WOLFSSL_X509_STORE* store, X509_NAME* issuer, int type) WOLFSSL_MSG("failed hash operation"); return WOLFSSL_FAILURE; } - wolfSSL_OPENSSL_free(pbuf); } /* try to load each hashed name file in path */ From 43a36a17d495804d17a95b86c363ba8d8a3311f4 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 16 Mar 2026 14:55:07 +0100 Subject: [PATCH 06/16] Upgrade deprecated GitHub Actions to v4 F-876 --- .github/workflows/haproxy.yml | 2 +- .github/workflows/msys2.yml | 2 +- .github/workflows/threadx.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/haproxy.yml b/.github/workflows/haproxy.yml index a391bf6c94d..90b12b93655 100644 --- a/.github/workflows/haproxy.yml +++ b/.github/workflows/haproxy.yml @@ -72,7 +72,7 @@ jobs: - name: Download haproxy if needed if: steps.cache-haproxy.outputs.cache-hit != 'true' - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: haproxy/haproxy ref: ${{matrix.haproxy_ref}} diff --git a/.github/workflows/msys2.yml b/.github/workflows/msys2.yml index f1f0f5d7453..93e555a26d3 100644 --- a/.github/workflows/msys2.yml +++ b/.github/workflows/msys2.yml @@ -20,7 +20,7 @@ jobs: run: shell: msys2 {0} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: msys2/setup-msys2@v2 with: msystem: msys diff --git a/.github/workflows/threadx.yml b/.github/workflows/threadx.yml index 4cd1be57bd8..d1921418068 100644 --- a/.github/workflows/threadx.yml +++ b/.github/workflows/threadx.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Cache NetXDuo bundle id: cache-netxduo - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ./v6.4.3_rel.tar.gz key: netxduo-bundle-v6.4.3_rel From f56356a9b420a046e1fd2f9850d6e5817408ce31 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 16 Mar 2026 15:39:30 +0100 Subject: [PATCH 07/16] test_lms_write_key: check `fwrite` return --- tests/api.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/api.c b/tests/api.c index f256c068141..e27f3059d71 100644 --- a/tests/api.c +++ b/tests/api.c @@ -33615,14 +33615,13 @@ int test_wc_LmsKey_reload_cache(void); static int test_lms_write_key(const byte* priv, word32 privSz, void* context) { FILE* f = fopen((const char*)context, "wb"); + int ret = WC_LMS_RC_SAVED_TO_NV_MEMORY; if (f == NULL) return -1; - if (fwrite(priv, 1, privSz, f) != privSz) { - fclose(f); - return -1; - } + if (fwrite(priv, 1, privSz, f) != privSz) + ret = -1; fclose(f); - return WC_LMS_RC_SAVED_TO_NV_MEMORY; + return ret; } static int test_lms_read_key(byte* priv, word32 privSz, void* context) From 265fbdb3dd50a94907f5133f9b068bff33510cfd Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 16 Mar 2026 15:44:09 +0100 Subject: [PATCH 08/16] Check wc_InitRsaKey return value in wc_GetKeyOID F-748 --- wolfcrypt/src/asn.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 67086e3c5b7..fce0dff78d7 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -9491,14 +9491,15 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, if (rsa == NULL) return MEMORY_E; - wc_InitRsaKey(rsa, heap); - if (wc_RsaPrivateKeyDecode(key, &tmpIdx, rsa, keySz) == 0) { - *algoID = RSAk; - } - else { - WOLFSSL_MSG("Not RSA DER key"); + if (wc_InitRsaKey(rsa, heap) == 0) { + if (wc_RsaPrivateKeyDecode(key, &tmpIdx, rsa, keySz) == 0) { + *algoID = RSAk; + } + else { + WOLFSSL_MSG("Not RSA DER key"); + } + wc_FreeRsaKey(rsa); } - wc_FreeRsaKey(rsa); XFREE(rsa, heap, DYNAMIC_TYPE_TMP_BUFFER); } #endif /* !NO_RSA && !NO_ASN_CRYPT */ From b168bfaa6a1de0e5bd68146c8170992e045fe580 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 16 Mar 2026 15:44:09 +0100 Subject: [PATCH 09/16] Check wc_ecc_init_ex return value in wc_GetKeyOID F-749 --- wolfcrypt/src/asn.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index fce0dff78d7..2ee9344f047 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -9510,22 +9510,23 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, return MEMORY_E; tmpIdx = 0; - wc_ecc_init_ex(ecc, heap, INVALID_DEVID); - if (wc_EccPrivateKeyDecode(key, &tmpIdx, ecc, keySz) == 0) { - *algoID = ECDSAk; - - /* now find oid */ - if (wc_ecc_get_oid(ecc->dp->oidSum, curveOID, oidSz) < 0) { - WOLFSSL_MSG("Error getting ECC curve OID"); - wc_ecc_free(ecc); - XFREE(ecc, heap, DYNAMIC_TYPE_TMP_BUFFER); - return BAD_FUNC_ARG; + if (wc_ecc_init_ex(ecc, heap, INVALID_DEVID) == 0) { + if (wc_EccPrivateKeyDecode(key, &tmpIdx, ecc, keySz) == 0) { + *algoID = ECDSAk; + + /* now find oid */ + if (wc_ecc_get_oid(ecc->dp->oidSum, curveOID, oidSz) < 0) { + WOLFSSL_MSG("Error getting ECC curve OID"); + wc_ecc_free(ecc); + XFREE(ecc, heap, DYNAMIC_TYPE_TMP_BUFFER); + return BAD_FUNC_ARG; + } } + else { + WOLFSSL_MSG("Not ECC DER key either"); + } + wc_ecc_free(ecc); } - else { - WOLFSSL_MSG("Not ECC DER key either"); - } - wc_ecc_free(ecc); XFREE(ecc, heap, DYNAMIC_TYPE_TMP_BUFFER); } #endif /* HAVE_ECC && !NO_ASN_CRYPT */ From 4ee9a263f0f575b11055a3014206af730ec68483 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 16 Mar 2026 15:44:09 +0100 Subject: [PATCH 10/16] Fix resource leak in wc_InitEccsiKey_ex error path F-752 --- wolfcrypt/src/eccsi.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/wolfcrypt/src/eccsi.c b/wolfcrypt/src/eccsi.c index 54cc128a9ef..b4cf859e500 100644 --- a/wolfcrypt/src/eccsi.c +++ b/wolfcrypt/src/eccsi.c @@ -68,8 +68,6 @@ int wc_InitEccsiKey_ex(EccsiKey* key, int keySz, int curveId, void* heap, int devId) { int err = 0; - ecc_key* ecc = NULL; - ecc_key* pubkey = NULL; EccsiKeyParams* params = NULL; if (key == NULL) { @@ -84,7 +82,6 @@ int wc_InitEccsiKey_ex(EccsiKey* key, int keySz, int curveId, void* heap, err = wc_ecc_init_ex(&key->ecc, heap, devId); } if (err == 0) { - ecc = &key->ecc; err = wc_ecc_init_ex(&key->pubkey, heap, devId); } if (err == 0) { @@ -94,7 +91,6 @@ int wc_InitEccsiKey_ex(EccsiKey* key, int keySz, int curveId, void* heap, } } if (err == 0) { - pubkey = &key->pubkey; err = mp_init_multi(¶ms->order, #ifdef WOLFCRYPT_ECCSI_CLIENT ¶ms->a, ¶ms->b, ¶ms->prime, &key->tmp, &key->ssk @@ -111,8 +107,7 @@ int wc_InitEccsiKey_ex(EccsiKey* key, int keySz, int curveId, void* heap, } if (err != 0) { - wc_ecc_free(pubkey); - wc_ecc_free(ecc); + wc_FreeEccsiKey(key); } return err; From 643427040bb405cd74e634b6788e0866c281b89e Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 16 Mar 2026 15:44:09 +0100 Subject: [PATCH 11/16] Clear seed buffer after dilithium key generation F-767 --- wolfcrypt/src/dilithium.c | 1 + 1 file changed, 1 insertion(+) diff --git a/wolfcrypt/src/dilithium.c b/wolfcrypt/src/dilithium.c index a53de82883d..f5b25d2258b 100644 --- a/wolfcrypt/src/dilithium.c +++ b/wolfcrypt/src/dilithium.c @@ -8026,6 +8026,7 @@ static int dilithium_make_key(dilithium_key* key, WC_RNG* rng) ret = wc_dilithium_make_key_from_seed(key, seed); } + ForceZero(seed, sizeof(seed)); return ret; } #endif /* !WOLFSSL_DILITHIUM_NO_MAKE_KEY */ From e4b55be65a61544468ec04314179cc82942e433e Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 16 Mar 2026 15:44:09 +0100 Subject: [PATCH 12/16] Use mp_forcezero for DH private key in async path F-766 --- wolfcrypt/src/dh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wolfcrypt/src/dh.c b/wolfcrypt/src/dh.c index 0054374480b..69fa1152a91 100644 --- a/wolfcrypt/src/dh.c +++ b/wolfcrypt/src/dh.c @@ -1465,7 +1465,7 @@ static int wc_DhGenerateKeyPair_Async(DhKey* key, WC_RNG* rng, if (ret == MP_OKAY) ret = IntelQaDhKeyGen(&key->asyncDev, &key->p.raw, &key->g.raw, &x.raw, pub, pubSz); - mp_clear(&x); + mp_forcezero(&x); return ret; } From 109e765b5b3f95162294b769970ee3187007aa99 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 16 Mar 2026 15:44:09 +0100 Subject: [PATCH 13/16] Clear sensitive stack buffers in ed25519 signing F-764 --- wolfcrypt/src/ed25519.c | 72 +++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 39 deletions(-) diff --git a/wolfcrypt/src/ed25519.c b/wolfcrypt/src/ed25519.c index d8e53d91cd6..2e30d74899d 100644 --- a/wolfcrypt/src/ed25519.c +++ b/wolfcrypt/src/ed25519.c @@ -416,26 +416,21 @@ int wc_ed25519_sign_msg_ex(const byte* in, word32 inLen, byte* out, /* step 1: create nonce to use where nonce is r in r = H(h_b, ... ,h_2b-1,M) */ ret = ed25519_hash(key, key->k, ED25519_KEY_SIZE, az); - if (ret != 0) - return ret; - /* apply clamp */ - az[0] &= 248; - az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */ - az[31] |= 64; - - { + if (ret == 0) { #ifdef WOLFSSL_ED25519_PERSISTENT_SHA wc_Sha512 *sha = &key->sha; #else wc_Sha512 sha[1]; ret = ed25519_hash_init(key, sha); - if (ret < 0) { - return ret; - } #endif - if (type == Ed25519ctx || type == Ed25519ph) { + /* apply clamp */ + az[0] &= 248; + az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */ + az[31] |= 64; + + if (ret == 0 && (type == Ed25519ctx || type == Ed25519ph)) { ret = ed25519_hash_update(key, sha, ed25519Ctx, ED25519CTX_SIZE); if (ret == 0) ret = ed25519_hash_update(key, sha, &type, sizeof(type)); @@ -457,39 +452,36 @@ int wc_ed25519_sign_msg_ex(const byte* in, word32 inLen, byte* out, #endif } - if (ret != 0) - return ret; - + if (ret == 0) { #ifdef FREESCALE_LTC_ECC - ltcPoint.X = &tempBuf[0]; - ltcPoint.Y = &tempBuf[32]; - LTC_PKHA_sc_reduce(nonce); - LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), nonce, - ED25519_KEY_SIZE, <cPoint, kLTC_Ed25519 /* result on Ed25519 */); - LTC_PKHA_Ed25519_Compress(<cPoint, out); + ltcPoint.X = &tempBuf[0]; + ltcPoint.Y = &tempBuf[32]; + LTC_PKHA_sc_reduce(nonce); + LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), nonce, + ED25519_KEY_SIZE, <cPoint, + kLTC_Ed25519 /* result on Ed25519 */); + LTC_PKHA_Ed25519_Compress(<cPoint, out); #else - sc_reduce(nonce); + sc_reduce(nonce); - /* step 2: computing R = rB where rB is the scalar multiplication of - r and B */ - ge_scalarmult_base(&R,nonce); - ge_p3_tobytes(out,&R); + /* step 2: computing R = rB where rB is the scalar multiplication of + r and B */ + ge_scalarmult_base(&R,nonce); + ge_p3_tobytes(out,&R); #endif + } /* step 3: hash R + public key + message getting H(R,A,M) then creating S = (r + H(R,A,M)a) mod l */ - { + if (ret == 0) { #ifdef WOLFSSL_ED25519_PERSISTENT_SHA wc_Sha512 *sha = &key->sha; #else wc_Sha512 sha[1]; - ret = ed25519_hash_init(key, sha); - if (ret < 0) - return ret; #endif - if (type == Ed25519ctx || type == Ed25519ph) { + if (ret == 0 && (type == Ed25519ctx || type == Ed25519ph)) { ret = ed25519_hash_update(key, sha, ed25519Ctx, ED25519CTX_SIZE); if (ret == 0) ret = ed25519_hash_update(key, sha, &type, sizeof(type)); @@ -512,20 +504,22 @@ int wc_ed25519_sign_msg_ex(const byte* in, word32 inLen, byte* out, #endif } - if (ret != 0) - return ret; - + if (ret == 0) { #ifdef FREESCALE_LTC_ECC - LTC_PKHA_sc_reduce(hram); - LTC_PKHA_sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce); + LTC_PKHA_sc_reduce(hram); + LTC_PKHA_sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce); #else - sc_reduce(hram); - sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce); + sc_reduce(hram); + sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce); #endif + } + + ForceZero(az, sizeof(az)); + ForceZero(nonce, sizeof(nonce)); #endif /* WOLFSSL_SE050 */ #ifdef WOLFSSL_EDDSA_CHECK_PRIV_ON_SIGN - { + if (ret == 0) { int i; byte c = 0; for (i = 0; i < ED25519_KEY_SIZE; i++) { From 5f7bc0f3a6e5cbd7dab982759e25b681a7949892 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 16 Mar 2026 15:44:09 +0100 Subject: [PATCH 14/16] Clear sensitive stack buffers in ed448 signing F-765 --- wolfcrypt/src/ed448.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/wolfcrypt/src/ed448.c b/wolfcrypt/src/ed448.c index 4e40e5d89e5..b46d5f93f09 100644 --- a/wolfcrypt/src/ed448.c +++ b/wolfcrypt/src/ed448.c @@ -391,16 +391,15 @@ int wc_ed448_sign_msg_ex(const byte* in, word32 inLen, byte* out, #else wc_Shake sha[1]; ret = ed448_hash_init(key, sha); - if (ret < 0) - return ret; #endif /* apply clamp */ az[0] &= 0xfc; az[55] |= 0x80; az[56] = 0x00; - ret = ed448_hash_update(key, sha, ed448Ctx, ED448CTX_SIZE); - + if (ret == 0) { + ret = ed448_hash_update(key, sha, ed448Ctx, ED448CTX_SIZE); + } if (ret == 0) { ret = ed448_hash_update(key, sha, &type, sizeof(type)); } @@ -429,15 +428,14 @@ int wc_ed448_sign_msg_ex(const byte* in, word32 inLen, byte* out, #else wc_Shake sha[1]; ret = ed448_hash_init(key, sha); - if (ret < 0) - return ret; #endif - sc448_reduce(nonce); - + if (ret == 0) + sc448_reduce(nonce); /* step 2: computing R = rB where rB is the scalar multiplication of r and B */ - ret = ge448_scalarmult_base(&R,nonce); - + if (ret == 0) { + ret = ge448_scalarmult_base(&R,nonce); + } /* step 3: hash R + public key + message getting H(R,A,M) then creating S = (r + H(R,A,M)a) mod l */ if (ret == 0) { @@ -487,6 +485,8 @@ int wc_ed448_sign_msg_ex(const byte* in, word32 inLen, byte* out, } #endif + ForceZero(az, sizeof(az)); + ForceZero(nonce, sizeof(nonce)); return ret; } From fac08427e5cf3179a25dd3b0a806fdf9b3e46b42 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 16 Mar 2026 15:44:09 +0100 Subject: [PATCH 15/16] Fix missing op validation in EVP_PKEY_decrypt F-747 --- wolfcrypt/src/evp.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 9aaefbef2b0..e1a45c2d222 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -3096,6 +3096,12 @@ int wolfSSL_EVP_PKEY_decrypt(WOLFSSL_EVP_PKEY_CTX *ctx, return 0; } + if (ctx->op != WC_EVP_PKEY_OP_DECRYPT) { + WOLFSSL_MSG("ctx->op must be set to WC_EVP_PKEY_OP_DECRYPT. Use " + "wolfSSL_EVP_PKEY_decrypt_init."); + return WOLFSSL_FAILURE; + } + (void)out; (void)outLen; (void)in; From 7c92fb204d9d9d71e28b0dbd38bd3ec3984ff908 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 16 Mar 2026 15:44:09 +0100 Subject: [PATCH 16/16] Use constant-time PKCS#7 padding check in EVP F-763 --- wolfcrypt/src/evp.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index e1a45c2d222..74e432cec0e 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -1263,13 +1263,17 @@ static int checkPad(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *buff) { int i; int n; + byte mask = 0; n = buff[ctx->block_size-1]; - if (n > ctx->block_size || n == 0) return -1; - for (i = 0; i < n; i++) { - if (buff[ctx->block_size-i-1] != n) - return -1; - } - return ctx->block_size - n; + /* Encode invalid n into mask constant-time instead of early-returning, + * so the loop always runs and timing does not reveal padding length. */ + mask |= ctMaskEq(n, 0) | ctMaskGT(n, ctx->block_size); + for (i = 0; i < ctx->block_size; i++) { + byte in_padding = ctMaskLT(i, n); + mask |= ctMaskSel(in_padding, + ctMaskNotEq(buff[ctx->block_size - 1 - i], n), 0); + } + return ctMaskSelInt(ctMaskEq(mask, 0), ctx->block_size - n, -1); } #if (defined(HAVE_AESGCM) || defined(HAVE_AESCCM) || \