From 557b8fda219ab60da36392442dced3c2cf87ab7f Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Mon, 6 Apr 2026 17:05:09 -0600 Subject: [PATCH 1/7] JNI: Fix ByteBuffer read passing maxOutputSz instead of clamped outSz (F-2149) --- native/com_wolfssl_WolfSSLSession.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/com_wolfssl_WolfSSLSession.c b/native/com_wolfssl_WolfSSLSession.c index 2e6cc6e6..1657750c 100644 --- a/native/com_wolfssl_WolfSSLSession.c +++ b/native/com_wolfssl_WolfSSLSession.c @@ -1574,7 +1574,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__JLjava_nio_ByteBuff } size = SSLReadNonblockingWithSelectPoll(ssl, data + position, - maxOutputSz, (int)timeout); + outSz, (int)timeout); /* Release array elements if using array-backed buffer. * Note: DirectByteBuffer doesn't need releasing data */ From fbb63139f5a81fde481d1a29452ff61ede63080d Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Mon, 6 Apr 2026 17:18:26 -0600 Subject: [PATCH 2/7] JNI: Zero ECC private key buffers after use in EccKey JNI functions (F-2153, F-2154) --- native/com_wolfssl_WolfCryptEccKey.c | 47 +++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/native/com_wolfssl_WolfCryptEccKey.c b/native/com_wolfssl_WolfCryptEccKey.c index f91cebf1..c68ccbd4 100644 --- a/native/com_wolfssl_WolfCryptEccKey.c +++ b/native/com_wolfssl_WolfCryptEccKey.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "com_wolfssl_WolfCryptEccKey.h" JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfCryptEccKey_EccPublicKeyToDer @@ -128,6 +129,12 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfCryptEccKey_EccPrivateKeyToDer ret = wc_EccPrivateKeyToDer(key, result, resultSz); if (ret <= 0) { + #if (LIBWOLFSSL_VERSION_HEX >= 0x05008004) && \ + !defined(WOLFSSL_NO_FORCE_ZERO) + wc_ForceZero(result, sizeof(result)); + #else + XMEMSET(result, 0, sizeof(result)); + #endif (*jenv)->ThrowNew(jenv, excClass, "Native call to wc_EccPrivateKeyToDer failed"); return NULL; @@ -137,12 +144,24 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfCryptEccKey_EccPrivateKeyToDer /* create byte array to return */ resultArray = (*jenv)->NewByteArray(jenv, resultSz); if (!resultArray) { + #if (LIBWOLFSSL_VERSION_HEX >= 0x05008004) && \ + !defined(WOLFSSL_NO_FORCE_ZERO) + wc_ForceZero(result, sizeof(result)); + #else + XMEMSET(result, 0, sizeof(result)); + #endif (*jenv)->ThrowNew(jenv, excClass, "Failed to create new byte array in native EccPrivateKeyToDer"); return NULL; } (*jenv)->SetByteArrayRegion(jenv, resultArray, 0, resultSz, (jbyte*)result); + #if (LIBWOLFSSL_VERSION_HEX >= 0x05008004) && \ + !defined(WOLFSSL_NO_FORCE_ZERO) + wc_ForceZero(result, sizeof(result)); + #else + XMEMSET(result, 0, sizeof(result)); + #endif if ((*jenv)->ExceptionOccurred(jenv)) { (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); @@ -207,9 +226,15 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfCryptEccKey_EccPrivateKeyToPKC ret = wc_EccPrivateKeyToPKCS8(key, result, &resultSz); if (ret <= 0) { + #if (LIBWOLFSSL_VERSION_HEX >= 0x05008004) && \ + !defined(WOLFSSL_NO_FORCE_ZERO) + wc_ForceZero(result, resultSz); + #else + XMEMSET(result, 0, resultSz); + #endif XFREE(result, NULL, DYNAMIC_TYPE_TMP_BUFFER); (*jenv)->ThrowNew(jenv, excClass, - "Native call to wc_EccPrivateKeyToDer failed"); + "Native call to wc_EccPrivateKeyToPKCS8 failed"); return NULL; } resultSz = ret; @@ -217,21 +242,35 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfCryptEccKey_EccPrivateKeyToPKC /* create byte array to return */ resultArray = (*jenv)->NewByteArray(jenv, resultSz); if (!resultArray) { + #if (LIBWOLFSSL_VERSION_HEX >= 0x05008004) && \ + !defined(WOLFSSL_NO_FORCE_ZERO) + wc_ForceZero(result, resultSz); + #else + XMEMSET(result, 0, resultSz); + #endif XFREE(result, NULL, DYNAMIC_TYPE_TMP_BUFFER); (*jenv)->ThrowNew(jenv, excClass, - "Failed to create new byte array in native EccPrivateKeyToPKCS8"); + "Failed to create new byte array in native " + "EccPrivateKeyToPKCS8"); return NULL; } (*jenv)->SetByteArrayRegion(jenv, resultArray, 0, resultSz, (jbyte*)result); + #if (LIBWOLFSSL_VERSION_HEX >= 0x05008004) && \ + !defined(WOLFSSL_NO_FORCE_ZERO) + wc_ForceZero(result, resultSz); + #else + XMEMSET(result, 0, resultSz); + #endif + + XFREE(result, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if ((*jenv)->ExceptionOccurred(jenv)) { (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); - XFREE(result, NULL, DYNAMIC_TYPE_TMP_BUFFER); return NULL; } - XFREE(result, NULL, DYNAMIC_TYPE_TMP_BUFFER); return resultArray; #else From d5d0cfc2949956c9ab81ae4c288dfe19010bcd7e Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Mon, 6 Apr 2026 17:26:32 -0600 Subject: [PATCH 3/7] JNI: Zero private key buffer in CTX usePrivateKeyBuffer when JNI copy (F-2157) --- native/com_wolfssl_WolfSSLContext.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/native/com_wolfssl_WolfSSLContext.c b/native/com_wolfssl_WolfSSLContext.c index 6241b757..faf13ad4 100644 --- a/native/com_wolfssl_WolfSSLContext.c +++ b/native/com_wolfssl_WolfSSLContext.c @@ -29,6 +29,7 @@ #endif #include #include +#include #include #include "com_wolfssl_globals.h" @@ -926,6 +927,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_usePrivateKeyBuffer int ret = WOLFSSL_FAILURE; byte* buff = NULL; word32 buffSz = 0; + jboolean isCopy = JNI_FALSE; WOLFSSL_CTX* ctx = (WOLFSSL_CTX*)(uintptr_t)ctxPtr; (void)jcl; (void)sz; @@ -934,13 +936,22 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_usePrivateKeyBuffer return (jint)BAD_FUNC_ARG; } - buff = (byte*)(*jenv)->GetByteArrayElements(jenv, in, NULL); + buff = (byte*)(*jenv)->GetByteArrayElements(jenv, in, &isCopy); buffSz = (*jenv)->GetArrayLength(jenv, in); if (buff != NULL && buffSz > 0) { ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, buffSz, format); } + /* Only zero if JVM made a copy */ + if (buff != NULL && isCopy == JNI_TRUE) { + #if (LIBWOLFSSL_VERSION_HEX >= 0x05008004) && \ + !defined(WOLFSSL_NO_FORCE_ZERO) + wc_ForceZero(buff, buffSz); + #else + XMEMSET(buff, 0, buffSz); + #endif + } (*jenv)->ReleaseByteArrayElements(jenv, in, (jbyte*)buff, JNI_ABORT); return (jint)ret; From 6a6793837e8856fcf6329908ba6830f749446afc Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Mon, 6 Apr 2026 17:31:57 -0600 Subject: [PATCH 4/7] JNI: Zero PKCS8 key buffer before free in getPkcs8TraditionalOffset (F-2158) --- native/com_wolfssl_WolfSSL.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/native/com_wolfssl_WolfSSL.c b/native/com_wolfssl_WolfSSL.c index a67429f5..1fd9facb 100644 --- a/native/com_wolfssl_WolfSSL.c +++ b/native/com_wolfssl_WolfSSL.c @@ -32,6 +32,7 @@ #include #include #include +#include #ifdef HAVE_FIPS #include #endif @@ -1995,13 +1996,25 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_getPkcs8TraditionalOffset if ((*jenv)->ExceptionOccurred(jenv)) { (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); - XFREE(inBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #if (LIBWOLFSSL_VERSION_HEX >= 0x05008004) && \ + !defined(WOLFSSL_NO_FORCE_ZERO) + wc_ForceZero(inBuf, (long)sz); + #else + XMEMSET(inBuf, 0, (long)sz); + #endif + XFREE(inBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); return SSL_FAILURE; } inOutIdx = (word32)idx; ret = wc_GetPkcs8TraditionalOffset(inBuf, &inOutIdx, (word32)sz); + #if (LIBWOLFSSL_VERSION_HEX >= 0x05008004) && \ + !defined(WOLFSSL_NO_FORCE_ZERO) + wc_ForceZero(inBuf, (long)sz); + #else + XMEMSET(inBuf, 0, (long)sz); + #endif XFREE(inBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (ret < 0) From 9f90e08aefa0eac7b498752c4805359ea537b14e Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Mon, 6 Apr 2026 17:33:09 -0600 Subject: [PATCH 5/7] JNI: Fix missing DetachCurrentThread on ALPN callback success path (F-2150) --- native/com_wolfssl_WolfSSLSession.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/native/com_wolfssl_WolfSSLSession.c b/native/com_wolfssl_WolfSSLSession.c index 1657750c..39ea36bd 100644 --- a/native/com_wolfssl_WolfSSLSession.c +++ b/native/com_wolfssl_WolfSSLSession.c @@ -5957,7 +5957,11 @@ int NativeALPNSelectCb(WOLFSSL *ssl, const unsigned char **out, } } - return ret; + if (needsDetach) { + (*g_vm)->DetachCurrentThread(g_vm); + } + + return ret; } #endif /* HAVE_ALPN */ From 7a5ac24e71ae2e4c39fc31367c17aa683442cfed Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Mon, 6 Apr 2026 17:35:18 -0600 Subject: [PATCH 6/7] JNI: Add bounds check for SNI data size before word16 cast (F-2155) --- native/com_wolfssl_WolfSSLSession.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/native/com_wolfssl_WolfSSLSession.c b/native/com_wolfssl_WolfSSLSession.c index 39ea36bd..0dfdb872 100644 --- a/native/com_wolfssl_WolfSSLSession.c +++ b/native/com_wolfssl_WolfSSLSession.c @@ -5209,8 +5209,12 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useSNI return BAD_FUNC_ARG; } - dataBuf = (byte*)(*jenv)->GetByteArrayElements(jenv, data, NULL); dataSz = (*jenv)->GetArrayLength(jenv, data); + if (dataSz > WOLFSSL_MAX_16BIT) { + return BAD_FUNC_ARG; + } + + dataBuf = (byte*)(*jenv)->GetByteArrayElements(jenv, data, NULL); if (dataBuf != NULL && dataSz > 0) { ret = wolfSSL_UseSNI(ssl, (byte)type, dataBuf, (word16)dataSz); From 9b08e4bec87d624322e40d3da50258b3b13ccea5 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Mon, 6 Apr 2026 17:37:50 -0600 Subject: [PATCH 7/7] Build: Guard JaCoCo taskdef behind availability check (F-2151) --- build.xml | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/build.xml b/build.xml index b61f91f3..14f792e9 100644 --- a/build.xml +++ b/build.xml @@ -93,9 +93,13 @@ - - - + + + + + + + @@ -430,7 +434,16 @@ - + + + + + + + @@ -460,7 +473,9 @@ - +