From e695c9c3cc5116579cc693d0c867f1d2cce6c2a6 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 19 Mar 2026 16:31:56 -0600 Subject: [PATCH 01/16] JNI: Fix unsigned int to jlong type mismatch in doSign outSz --- native/com_wolfssl_WolfCryptECC.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/native/com_wolfssl_WolfCryptECC.c b/native/com_wolfssl_WolfCryptECC.c index 70233488..2d20035a 100644 --- a/native/com_wolfssl_WolfCryptECC.c +++ b/native/com_wolfssl_WolfCryptECC.c @@ -150,7 +150,8 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptECC_doSign wc_ecc_free(&myKey); - (*jenv)->SetLongArrayRegion(jenv, outSz, 0, 1, (jlong*)&tmpOut); + tmp = (jlong)tmpOut; + (*jenv)->SetLongArrayRegion(jenv, outSz, 0, 1, &tmp); (void)jcl; return ret; From 19836da227685b26321461191a98f966abe0a805 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 19 Mar 2026 16:42:38 -0600 Subject: [PATCH 02/16] JNI: Fix unsigned int to jlong type mismatch in NativeEccSignCb outSz --- native/com_wolfssl_WolfSSLContext.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/native/com_wolfssl_WolfSSLContext.c b/native/com_wolfssl_WolfSSLContext.c index 3795fada..56e7842b 100644 --- a/native/com_wolfssl_WolfSSLContext.c +++ b/native/com_wolfssl_WolfSSLContext.c @@ -3049,7 +3049,8 @@ int NativeEccSignCb(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz, } /* copy outSz into j_outSz */ - (*jenv)->SetLongArrayRegion(jenv, j_outSz, 0, 1, (jlong*)outSz); + tmpVal = (jlong)(*outSz); + (*jenv)->SetLongArrayRegion(jenv, j_outSz, 0, 1, &tmpVal); if ((*jenv)->ExceptionOccurred(jenv)) { (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); From d7a6efe71213f3e78a18434fad0024b2681ddfe9 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 19 Mar 2026 16:52:17 -0600 Subject: [PATCH 03/16] JNI: Add missing return after throw for NULL checks in WolfSSLSession --- native/com_wolfssl_WolfSSLSession.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/native/com_wolfssl_WolfSSLSession.c b/native/com_wolfssl_WolfSSLSession.c index a30decdd..800b7895 100644 --- a/native/com_wolfssl_WolfSSLSession.c +++ b/native/com_wolfssl_WolfSSLSession.c @@ -698,6 +698,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setUsingNonblock if (ssl == NULL) { throwWolfSSLJNIException(jenv, "Input WolfSSLSession object was null in setUsingNonblock"); + return; } wolfSSL_set_using_nonblock(ssl, nonblock); @@ -716,6 +717,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getUsingNonblock if (ssl == NULL) { throwWolfSSLJNIException(jenv, "Input WolfSSLSession object was null in getUsingNonblock"); + return 0; } return wolfSSL_get_using_nonblock(ssl); @@ -3847,6 +3849,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setCRLCb if (g_crlCbIfaceObj == NULL) { throwWolfSSLException(jenv, "Error storing global missingCRLCallback interface"); + return SSL_FAILURE; } ret = wolfSSL_SetCRL_Cb(ssl, NativeMissingCRLCallback); From 3fd32a8028b9b201682c7f7887fd78d3b4afb73e Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 19 Mar 2026 17:03:47 -0600 Subject: [PATCH 04/16] JNI: Fix RsaKey resource leak on error paths in doVerify and doDec --- native/com_wolfssl_WolfCryptRSA.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/native/com_wolfssl_WolfCryptRSA.c b/native/com_wolfssl_WolfCryptRSA.c index 74a341b0..f1025c0b 100644 --- a/native/com_wolfssl_WolfCryptRSA.c +++ b/native/com_wolfssl_WolfCryptRSA.c @@ -141,7 +141,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doVerify (unsigned int)outSz, &myKey); if (ret < 0) { printf("wc_RsaSSL_Verify failed, ret = %d\n", ret); - return ret; } } else { printf("wc_RsaPublicKeyDecode failed, ret = %d\n", ret); @@ -444,7 +443,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doDec (unsigned int)outSz, &myKey); if (ret < 0) { printf("wc_RsaPrivateDecrypt failed, ret = %d\n", ret); - return ret; } } else { printf("wc_RsaPrivateKeyDecode failed, ret = %d\n", ret); From d8f5cbfee3e5ff3e18682ebf56d5dac21af1c0ac Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 19 Mar 2026 17:05:53 -0600 Subject: [PATCH 05/16] JNI: Add missing wc_FreeRng calls in doSign and doEnc --- native/com_wolfssl_WolfCryptRSA.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/native/com_wolfssl_WolfCryptRSA.c b/native/com_wolfssl_WolfCryptRSA.c index f1025c0b..267a2306 100644 --- a/native/com_wolfssl_WolfCryptRSA.c +++ b/native/com_wolfssl_WolfCryptRSA.c @@ -92,6 +92,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doSign } wc_FreeRsaKey(&myKey); + wc_FreeRng(&rng); return ret; } @@ -211,6 +212,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doEnc } wc_FreeRsaKey(&myKey); + wc_FreeRng(&rng); return ret; } From e093eb27714fa215d64a0decfaf2a72485b6945e Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 19 Mar 2026 17:08:43 -0600 Subject: [PATCH 06/16] JNI: Fix resource leaks on error paths in ECC doVerify and doSign --- native/com_wolfssl_WolfCryptECC.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/native/com_wolfssl_WolfCryptECC.c b/native/com_wolfssl_WolfCryptECC.c index 2d20035a..6a980aea 100644 --- a/native/com_wolfssl_WolfCryptECC.c +++ b/native/com_wolfssl_WolfCryptECC.c @@ -73,17 +73,16 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptECC_doVerify (unsigned int)hashSz, &tmpResult, &myKey); if (ret != 0) { printf("wc_ecc_verify_hash failed, ret = %d\n", ret); - wc_ecc_free(&myKey); - return -1; } } else { printf("wc_ecc_import_x963 failed, ret = %d\n", ret); - return -1; } wc_ecc_free(&myKey); - (*jenv)->SetIntArrayRegion(jenv, result, 0, 1, &tmpResult); + if (ret == 0) { + (*jenv)->SetIntArrayRegion(jenv, result, 0, 1, &tmpResult); + } (void)jcl; return ret; @@ -140,18 +139,18 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptECC_doSign &rng, &myKey); if (ret != 0) { printf("wc_ecc_sign_hash failed, ret = %d\n", ret); - wc_ecc_free(&myKey); - return -1; } } else { printf("wc_EccPrivateKeyDecode failed, ret = %d\n", ret); - return -1; } wc_ecc_free(&myKey); + wc_FreeRng(&rng); - tmp = (jlong)tmpOut; - (*jenv)->SetLongArrayRegion(jenv, outSz, 0, 1, &tmp); + if (ret == 0) { + tmp = (jlong)tmpOut; + (*jenv)->SetLongArrayRegion(jenv, outSz, 0, 1, &tmp); + } (void)jcl; return ret; From d36347c10c99f2d687a9eebbc4d84b375c4e2402 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 19 Mar 2026 17:29:25 -0600 Subject: [PATCH 07/16] JNI: Add bounds check for offset/length in byte array read and write --- native/com_wolfssl_WolfSSLSession.c | 10 ++ .../com/wolfssl/test/WolfSSLSessionTest.java | 170 ++++++++++++++++++ 2 files changed, 180 insertions(+) diff --git a/native/com_wolfssl_WolfSSLSession.c b/native/com_wolfssl_WolfSSLSession.c index 800b7895..67ab1984 100644 --- a/native/com_wolfssl_WolfSSLSession.c +++ b/native/com_wolfssl_WolfSSLSession.c @@ -1231,6 +1231,11 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_write__J_3BIII } if ((offset >= 0) && (length >= 0)) { + jsize arrayLen = (*jenv)->GetArrayLength(jenv, raw); + if (offset > arrayLen || length > arrayLen - offset) { + return BAD_FUNC_ARG; + } + data = (byte*)(*jenv)->GetByteArrayElements(jenv, raw, NULL); if ((*jenv)->ExceptionOccurred(jenv)) { (*jenv)->ExceptionDescribe(jenv); @@ -1440,6 +1445,11 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__J_3BIII } if ((offset >= 0) && (length >= 0)) { + jsize arrayLen = (*jenv)->GetArrayLength(jenv, raw); + if (offset > arrayLen || length > arrayLen - offset) { + return BAD_FUNC_ARG; + } + data = (byte*)(*jenv)->GetByteArrayElements(jenv, raw, NULL); if ((*jenv)->ExceptionOccurred(jenv)) { (*jenv)->ExceptionDescribe(jenv); diff --git a/src/test/com/wolfssl/test/WolfSSLSessionTest.java b/src/test/com/wolfssl/test/WolfSSLSessionTest.java index c5bc8562..4232bc6f 100644 --- a/src/test/com/wolfssl/test/WolfSSLSessionTest.java +++ b/src/test/com/wolfssl/test/WolfSSLSessionTest.java @@ -2857,6 +2857,176 @@ public Void call() throws Exception { System.out.println("\t... passed"); } + @Test + public void test_WolfSSLSession_readWriteBoundsCheck() throws Exception { + int ret = 0; + int err = 0; + Socket cliSock = null; + WolfSSLSession cliSes = null; + byte[] testData = "Hello from client".getBytes(); + + /* Create client/server WolfSSLContext objects */ + final WolfSSLContext srvCtx; + WolfSSLContext cliCtx; + + System.out.print("\tTesting read/write bounds check"); + + /* Create ServerSocket first to get ephemeral port */ + final ServerSocket srvSocket = new ServerSocket(0); + + srvCtx = createAndSetupWolfSSLContext(srvCert, srvKey, + WolfSSL.SSL_FILETYPE_PEM, cliCert, WolfSSL.SSLv23_ServerMethod()); + cliCtx = createAndSetupWolfSSLContext(cliCert, cliKey, + WolfSSL.SSL_FILETYPE_PEM, caCert, WolfSSL.SSLv23_ClientMethod()); + + ExecutorService es = Executors.newSingleThreadExecutor(); + + /* Start server */ + try { + es.submit(new Callable() { + @Override + public Void call() throws Exception { + int ret; + int err; + Socket server = null; + WolfSSLSession srvSes = null; + + try { + server = srvSocket.accept(); + srvSes = new WolfSSLSession(srvCtx); + + ret = srvSes.setFd(server); + if (ret != WolfSSL.SSL_SUCCESS) { + throw new Exception( + "WolfSSLSession.setFd() failed: " + ret); + } + + do { + ret = srvSes.accept(); + err = srvSes.getError(ret); + } while (ret != WolfSSL.SSL_SUCCESS && + (err == WolfSSL.SSL_ERROR_WANT_READ || + err == WolfSSL.SSL_ERROR_WANT_WRITE)); + + if (ret != WolfSSL.SSL_SUCCESS) { + throw new Exception( + "WolfSSLSession.accept() failed: " + err); + } + + srvSes.shutdownSSL(); + srvSes.freeSSL(); + srvSes = null; + server.close(); + server = null; + + } finally { + if (srvSes != null) { + srvSes.freeSSL(); + } + if (server != null) { + server.close(); + } + } + + return null; + } + }); + + } catch (Exception e) { + System.out.println("\t... failed"); + e.printStackTrace(); + fail(); + } + + synchronized (byteBufferPoolPropertyLock) { + + /* Disable ByteBuffer pool so native byte[] path is used */ + String originalProp = Security.getProperty( + "wolfssl.readWriteByteBufferPool.disabled"); + Security.setProperty( + "wolfssl.readWriteByteBufferPool.disabled", "true"); + + try { + /* Client connection */ + cliSock = new Socket(InetAddress.getLocalHost(), + srvSocket.getLocalPort()); + + cliSes = new WolfSSLSession(cliCtx); + + ret = cliSes.setFd(cliSock); + if (ret != WolfSSL.SSL_SUCCESS) { + throw new Exception( + "WolfSSLSession.setFd() failed, ret = " + ret); + } + + /* Do handshake */ + do { + ret = cliSes.connect(); + err = cliSes.getError(ret); + } while (ret != WolfSSL.SSL_SUCCESS && + (err == WolfSSL.SSL_ERROR_WANT_READ || + err == WolfSSL.SSL_ERROR_WANT_WRITE)); + + if (ret != WolfSSL.SSL_SUCCESS) { + throw new Exception( + "WolfSSLSession.connect() failed: " + err); + } + + /* Test write with offset + length > array length. + * Array is 17 bytes, offset=5 length=100 should be rejected */ + ret = cliSes.write(testData, 5, 100, 0); + if (ret >= 0) { + throw new Exception("write() with out-of-bounds offset/" + + "length should have failed but got: " + ret); + } + + /* Test read with offset + length > array length */ + byte[] readBuf = new byte[10]; + ret = cliSes.read(readBuf, 5, 100, 0); + if (ret >= 0) { + throw new Exception("read() with out-of-bounds offset/" + + "length should have failed but got: " + ret); + } + + cliSes.shutdownSSL(); + cliSes.freeSSL(); + cliSes = null; + cliSock.close(); + cliSock = null; + + } catch (Exception e) { + System.out.println("\t... failed"); + e.printStackTrace(); + fail(); + + } finally { + /* Restore original property */ + if (originalProp == null) { + originalProp = ""; + } + Security.setProperty( + "wolfssl.readWriteByteBufferPool.disabled", originalProp); + + /* Free resources */ + if (cliSes != null) { + cliSes.freeSSL(); + } + if (cliSock != null) { + cliSock.close(); + } + if (srvSocket != null) { + srvSocket.close(); + } + if (srvCtx != null) { + srvCtx.free(); + } + es.shutdown(); + } + } + + System.out.println("\t... passed"); + } + @Test public void test_WolfSSLSession_sessionToDerFromDer() throws Exception { From d30b4a3ff99529db0c13634f48a7fb46b20474a0 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 19 Mar 2026 17:33:37 -0600 Subject: [PATCH 08/16] JNI: Add FD_SETSIZE bounds check in socketSelect before FD_SET calls --- native/com_wolfssl_WolfSSLSession.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/native/com_wolfssl_WolfSSLSession.c b/native/com_wolfssl_WolfSSLSession.c index 67ab1984..38575a5a 100644 --- a/native/com_wolfssl_WolfSSLSession.c +++ b/native/com_wolfssl_WolfSSLSession.c @@ -813,6 +813,12 @@ static int socketSelect(SSLAppData* appData, int sockfd, int timeout_ms, int rx, return WOLFJNI_IO_EVENT_ERROR; } + /* Guard against FD_SET overflow. FD_SET behavior is undefined + * if sockfd >= FD_SETSIZE (1024 on Linux, 64 on Windows). */ + if (sockfd < 0 || sockfd >= FD_SETSIZE) { + return WOLFJNI_IO_EVENT_ERROR; + } + #ifndef USE_WINDOWS_API do { #endif @@ -824,6 +830,9 @@ static int socketSelect(SSLAppData* appData, int sockfd, int timeout_ms, int rx, FD_SET(sockfd, &fds); #ifndef USE_WINDOWS_API if ((shutdown == 0) && (appData->interruptFds[0] != -1)) { + if (appData->interruptFds[0] >= FD_SETSIZE) { + return WOLFJNI_IO_EVENT_ERROR; + } FD_SET(appData->interruptFds[0], &fds); /* nfds should be set to the highest number descriptor plus 1 */ if (appData->interruptFds[0] > sockfd) { From 98b1df7739cbedbc16c502890fb504ed9cdb9a5d Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 20 Mar 2026 10:23:55 -0600 Subject: [PATCH 09/16] JNI: Fix ThrowNew calls passing jcl instead of exception class --- native/com_wolfssl_WolfSSLCRL.c | 6 ++--- native/com_wolfssl_WolfSSLCertRequest.c | 4 +-- native/com_wolfssl_WolfSSLCertificate.c | 34 ++++++++++++++++--------- native/com_wolfssl_WolfSSLSession.c | 9 ++++--- 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/native/com_wolfssl_WolfSSLCRL.c b/native/com_wolfssl_WolfSSLCRL.c index ce4172c7..c0d6ef44 100644 --- a/native/com_wolfssl_WolfSSLCRL.c +++ b/native/com_wolfssl_WolfSSLCRL.c @@ -660,7 +660,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1get_1der derArr = (*jenv)->NewByteArray(jenv, sz); if (derArr == NULL) { - (*jenv)->ThrowNew(jenv, jcl, + throwWolfSSLJNIException(jenv, "Failed to create byte array in native X509_CRL_get_der"); XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL); return NULL; @@ -742,7 +742,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1get_1pem pemArr = (*jenv)->NewByteArray(jenv, pemSz); if (pemArr == NULL) { - (*jenv)->ThrowNew(jenv, jcl, + throwWolfSSLJNIException(jenv, "Failed to create byte array in native X509_CRL_get_pem"); XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); return NULL; @@ -801,7 +801,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1get_1signatu sigArr = (*jenv)->NewByteArray(jenv, sigSz); if (sigArr == NULL) { - (*jenv)->ThrowNew(jenv, jcl, + throwWolfSSLJNIException(jenv, "Failed to create byte array in native X509_CRL_get_signature"); return NULL; } diff --git a/native/com_wolfssl_WolfSSLCertRequest.c b/native/com_wolfssl_WolfSSLCertRequest.c index 935f71b3..33156272 100644 --- a/native/com_wolfssl_WolfSSLCertRequest.c +++ b/native/com_wolfssl_WolfSSLCertRequest.c @@ -484,7 +484,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1get_ derArr = (*jenv)->NewByteArray(jenv, sz); if (derArr == NULL) { - (*jenv)->ThrowNew(jenv, jcl, + throwWolfSSLJNIException(jenv, "Failed to create byte array in native X509_REQ_get_der"); return NULL; } @@ -567,7 +567,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1get_ pemArr = (*jenv)->NewByteArray(jenv, pemSz); if (pemArr == NULL) { - (*jenv)->ThrowNew(jenv, jcl, + throwWolfSSLJNIException(jenv, "Failed to create byte array in native X509_REQ_get_pem"); XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); return NULL; diff --git a/native/com_wolfssl_WolfSSLCertificate.c b/native/com_wolfssl_WolfSSLCertificate.c index c446ed12..737dbf7d 100644 --- a/native/com_wolfssl_WolfSSLCertificate.c +++ b/native/com_wolfssl_WolfSSLCertificate.c @@ -1085,6 +1085,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1der jbyteArray derArr = NULL; jclass excClass = NULL; WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + (void)jcl; if (jenv == NULL || x509 == NULL) { return NULL; @@ -1097,7 +1098,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1der derArr = (*jenv)->NewByteArray(jenv, sz); if (derArr == NULL) { - (*jenv)->ThrowNew(jenv, jcl, + throwWolfSSLJNIException(jenv, "Failed to create byte array in native X509_get_der"); return NULL; } @@ -1133,6 +1134,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1pem jbyteArray pemArr = NULL; jclass excClass = NULL; WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + (void)jcl; if (jenv == NULL || x509 == NULL) { return NULL; @@ -1162,7 +1164,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1pem pemArr = (*jenv)->NewByteArray(jenv, pemSz); if (pemArr == NULL) { - (*jenv)->ThrowNew(jenv, jcl, + throwWolfSSLJNIException(jenv, "Failed to create byte array in native X509_get_pem"); XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); return NULL; @@ -1207,6 +1209,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1tbs const unsigned char* tbs; WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; jclass excClass = NULL; + (void)jcl; if (jenv == NULL || x509 == NULL) { return NULL; @@ -1219,7 +1222,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1tbs tbsArr = (*jenv)->NewByteArray(jenv, sz); if (tbsArr == NULL) { - (*jenv)->ThrowNew(jenv, jcl, + throwWolfSSLJNIException(jenv, "Failed to create byte array in native X509_get_tbs"); return NULL; } @@ -1374,6 +1377,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1sign unsigned char* buf = NULL; jbyteArray ret = NULL; WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + (void)jcl; if (jenv == NULL || x509 == NULL) { return NULL; @@ -1385,7 +1389,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1sign ret = (*jenv)->NewByteArray(jenv, sz); if (!ret) { - (*jenv)->ThrowNew(jenv, jcl, + throwWolfSSLJNIException(jenv, "Failed to create byte array in native X509_get_signature"); return NULL; } @@ -1419,6 +1423,7 @@ JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1signatu { int type; WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + (void)jcl; if (jenv == NULL || x509 == NULL) { return NULL; @@ -1459,7 +1464,7 @@ JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1signatu return (*jenv)->NewStringUTF(jenv, "RSASSA-PSS"); default: - (*jenv)->ThrowNew(jenv, jcl, "Unknown signature type"); + throwWolfSSLJNIException(jenv, "Unknown signature type"); return NULL; } } @@ -1773,6 +1778,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1pubk unsigned char* buf; jbyteArray ret; WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + (void)jcl; if (jenv == NULL || x509 == NULL) { return NULL; @@ -1784,7 +1790,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1pubk ret = (*jenv)->NewByteArray(jenv, sz); if (!ret) { - (*jenv)->ThrowNew(jenv, jcl, + throwWolfSSLJNIException(jenv, "Failed to create byte array in native X509_get_signature"); return NULL; } @@ -1818,6 +1824,7 @@ JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1pubkey_ { int type; WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + (void)jcl; if (jenv == NULL || x509 == NULL) { return NULL; @@ -1834,7 +1841,7 @@ JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1pubkey_ case ED25519k: return (*jenv)->NewStringUTF(jenv, "EdDSA"); default: - (*jenv)->ThrowNew(jenv, jcl, "Unknown public key type"); + throwWolfSSLJNIException(jenv, "Unknown public key type"); return NULL; } } @@ -1944,6 +1951,7 @@ JNIEXPORT jbooleanArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1k jboolean values[9]; unsigned short kuse; WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + (void)jcl; if (jenv == NULL || x509 == NULL) { return NULL; @@ -1953,7 +1961,7 @@ JNIEXPORT jbooleanArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1k if (kuse != 0) { ret = (*jenv)->NewBooleanArray(jenv, 9); if (!ret) { - (*jenv)->ThrowNew(jenv, jcl, + throwWolfSSLJNIException(jenv, "Failed to create boolean array in native X509_get_key_usage"); return NULL; } @@ -1973,7 +1981,7 @@ JNIEXPORT jbooleanArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1k (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); (*jenv)->DeleteLocalRef(jenv, ret); - (*jenv)->ThrowNew(jenv, jcl, + throwWolfSSLJNIException(jenv, "Failed to set boolean region getting key usage"); return NULL; } @@ -2032,6 +2040,7 @@ static jobjectArray stackStringToArray(JNIEnv* jenv, jclass jcl, jclass stringClass = NULL; int count; int i; + (void)jcl; if (jenv == NULL || sk == NULL) { return NULL; @@ -2063,7 +2072,7 @@ static jobjectArray stackStringToArray(JNIEnv* jenv, jclass jcl, (*jenv)->DeleteLocalRef(jenv, ret); (*jenv)->DeleteLocalRef(jenv, stringClass); wolfSSL_X509_email_free(sk); - (*jenv)->ThrowNew(jenv, jcl, + throwWolfSSLJNIException(jenv, "Failed to create String in native AIA getter"); return NULL; } @@ -2076,7 +2085,7 @@ static jobjectArray stackStringToArray(JNIEnv* jenv, jclass jcl, (*jenv)->DeleteLocalRef(jenv, ret); (*jenv)->DeleteLocalRef(jenv, stringClass); wolfSSL_X509_email_free(sk); - (*jenv)->ThrowNew(jenv, jcl, + throwWolfSSLJNIException(jenv, "Failed to set String[] element in native AIA getter"); return NULL; } @@ -2249,6 +2258,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1exte unsigned char* data = NULL; unsigned int sz = 0; WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + (void)jcl; if (jenv == NULL || oidIn == NULL || x509 == NULL) { return NULL; @@ -2290,7 +2300,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1exte ret = (*jenv)->NewByteArray(jenv, sz); if (!ret) { - (*jenv)->ThrowNew(jenv, jcl, + throwWolfSSLJNIException(jenv, "Failed to create byte array in native X509_get_extension"); return NULL; } diff --git a/native/com_wolfssl_WolfSSLSession.c b/native/com_wolfssl_WolfSSLSession.c index 38575a5a..aa64e76b 100644 --- a/native/com_wolfssl_WolfSSLSession.c +++ b/native/com_wolfssl_WolfSSLSession.c @@ -2296,6 +2296,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getSessionID jbyteArray ret = NULL; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; WOLFSSL_SESSION* session = NULL; + (void)jcl; if (ssl == NULL) { return NULL; @@ -2311,7 +2312,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getSessionID ret = (*jenv)->NewByteArray(jenv, sz); if (!ret) { - (*jenv)->ThrowNew(jenv, jcl, + throwWolfSSLJNIException(jenv, "Failed to create byte array in native getSessionID"); wolfSSL_SESSION_free(session); return NULL; @@ -5197,7 +5198,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getSNIRequest if (ret > 0) { sniRequest = (*jenv)->NewByteArray(jenv, ret); if (sniRequest == NULL) { - (*jenv)->ThrowNew(jenv, jcl, + throwWolfSSLJNIException(jenv, "Failed to create byte array in native getSNIRequest"); return NULL; } @@ -5454,7 +5455,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_sslGet0AlpnSelected alpnArray = (*jenv)->NewByteArray(jenv, protocol_nameSz); if (alpnArray == NULL) { - (*jenv)->ThrowNew(jenv, jcl, + throwWolfSSLJNIException(jenv, "Failed to create byte array in native sslGet0AlpnSelected"); return NULL; } @@ -5943,7 +5944,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getClientRandom randomArr = (*jenv)->NewByteArray(jenv, clientRandomSz); if (randomArr == NULL) { - (*jenv)->ThrowNew(jenv, jcl, + throwWolfSSLJNIException(jenv, "Failed to create byte array in native getClientRandom()"); return NULL; } From 0c8cc048f265a6f3af314363b8098820f6f4e45e Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 20 Mar 2026 10:24:04 -0600 Subject: [PATCH 10/16] JNI: Fix null jstring crash in CertManagerLoadCA --- native/com_wolfssl_WolfSSLCertManager.c | 25 +++++++++-- .../wolfssl/test/WolfSSLCertManagerTest.java | 41 +++++++++++++++++++ 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/native/com_wolfssl_WolfSSLCertManager.c b/native/com_wolfssl_WolfSSLCertManager.c index 9169b7ec..bff116e6 100644 --- a/native/com_wolfssl_WolfSSLCertManager.c +++ b/native/com_wolfssl_WolfSSLCertManager.c @@ -67,13 +67,30 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertManager_CertManagerLoadCA return (jint)BAD_FUNC_ARG; } - certFile = (*jenv)->GetStringUTFChars(jenv, f, 0); - certPath = (*jenv)->GetStringUTFChars(jenv, d, 0); + if (f != NULL) { + certFile = (*jenv)->GetStringUTFChars(jenv, f, 0); + if (certFile == NULL) { + return (jint)MEMORY_E; + } + } + if (d != NULL) { + certPath = (*jenv)->GetStringUTFChars(jenv, d, 0); + if (certPath == NULL) { + if (certFile != NULL) { + (*jenv)->ReleaseStringUTFChars(jenv, f, certFile); + } + return (jint)MEMORY_E; + } + } ret = wolfSSL_CertManagerLoadCA(cm, certFile, certPath); - (*jenv)->ReleaseStringUTFChars(jenv, f, certFile); - (*jenv)->ReleaseStringUTFChars(jenv, d, certPath); + if (certFile != NULL) { + (*jenv)->ReleaseStringUTFChars(jenv, f, certFile); + } + if (certPath != NULL) { + (*jenv)->ReleaseStringUTFChars(jenv, d, certPath); + } return (jint)ret; #else diff --git a/src/test/com/wolfssl/test/WolfSSLCertManagerTest.java b/src/test/com/wolfssl/test/WolfSSLCertManagerTest.java index 784429de..a59d2d56 100644 --- a/src/test/com/wolfssl/test/WolfSSLCertManagerTest.java +++ b/src/test/com/wolfssl/test/WolfSSLCertManagerTest.java @@ -524,6 +524,47 @@ public static void loadLibrary() throws WolfSSLException { serverCert = WolfSSLTestCommon.getPath(serverCert); } + @Test + public void testCertManagerLoadCA() throws Exception { + + int ret = 0; + WolfSSLCertManager cm = null; + + System.out.print("\tCertManagerLoadCA()"); + + try { + cm = new WolfSSLCertManager(); + + /* Test loading CA cert by file only (null path) */ + ret = cm.CertManagerLoadCA(ocspRootCaCert, null); + if (ret != WolfSSL.SSL_SUCCESS) { + System.out.println("\t\t... failed"); + fail("CertManagerLoadCA(file, null) failed, ret = " + ret); + } + + /* Test with null file (null, null) should not crash, expected to + * return error */ + ret = cm.CertManagerLoadCA(null, null); + if (ret == WolfSSL.SSL_SUCCESS) { + System.out.println("\t\t... failed"); + fail("CertManagerLoadCA(null, null) should " + + "have failed but returned success"); + } + + } catch (WolfSSLException e) { + System.out.println("\t\t... failed"); + fail("CertManagerLoadCA test failed: " + e.getMessage()); + + } finally { + if (cm != null) { + cm.free(); + cm = null; + } + } + + System.out.println("\t\t... passed"); + } + @Test public void testCertManagerCheckOCSPResponse() throws Exception { From 612ab819fafdf57dfad4f589502a4cbd0a97464a Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 20 Mar 2026 10:31:18 -0600 Subject: [PATCH 11/16] JNI: Fix SHA224 typo in signature type strings --- native/com_wolfssl_WolfSSLCertificate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/native/com_wolfssl_WolfSSLCertificate.c b/native/com_wolfssl_WolfSSLCertificate.c index 737dbf7d..c7a1d890 100644 --- a/native/com_wolfssl_WolfSSLCertificate.c +++ b/native/com_wolfssl_WolfSSLCertificate.c @@ -1443,9 +1443,9 @@ JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1signatu case CTC_SHAwECDSA: return (*jenv)->NewStringUTF(jenv, "SHAwithECDSA"); case CTC_SHA224wRSA: - return (*jenv)->NewStringUTF(jenv, "SHA244withRSA"); + return (*jenv)->NewStringUTF(jenv, "SHA224withRSA"); case CTC_SHA224wECDSA: - return (*jenv)->NewStringUTF(jenv, "SHA244withECDSA"); + return (*jenv)->NewStringUTF(jenv, "SHA224withECDSA"); case CTC_SHA256wRSA: return (*jenv)->NewStringUTF(jenv, "SHA256withRSA"); case CTC_SHA256wECDSA: From 2c658f37f543c33c21ee8ff462e4c2419841d73a Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 20 Mar 2026 10:41:49 -0600 Subject: [PATCH 12/16] JNI: Remove static qualifier from g_cachedSSLObj in native callbacks --- native/com_wolfssl_WolfSSLContext.c | 36 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/native/com_wolfssl_WolfSSLContext.c b/native/com_wolfssl_WolfSSLContext.c index 56e7842b..3a0633a4 100644 --- a/native/com_wolfssl_WolfSSLContext.c +++ b/native/com_wolfssl_WolfSSLContext.c @@ -1031,7 +1031,7 @@ int NativeIORecvCb(WOLFSSL *ssl, char *buf, int sz, void *ctx) jclass excClass; /* WolfSSLJNIException class */ int needsDetach = 0; /* Should we explicitly detach? */ - static jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ + jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ jclass sessClass; /* WolfSSLSession class */ jfieldID ctxFid; /* WolfSSLSession->ctx FieldID */ jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */ @@ -1242,7 +1242,7 @@ int NativeIOSendCb(WOLFSSL *ssl, char *buf, int sz, void *ctx) jclass excClass; /* WolfSSLJNIException class */ int needsDetach = 0; /* Should we explicitly detach? */ - static jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ + jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ jclass sessClass; /* WolfSSLSession class */ jfieldID ctxFid; /* WolfSSLSession->ctx FieldID */ jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */ @@ -1467,7 +1467,7 @@ int NativeGenCookieCb(WOLFSSL *ssl, unsigned char *buf, int sz, void *ctx) jclass excClass; /* WolfSSLJNIException class */ int needsDetach = 0; /* Should we explicitly detach? */ - static jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ + jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ jclass sessClass; /* WolfSSLSession class */ jfieldID ctxFid; /* WolfSSLSession->ctx FieldID */ jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */ @@ -2036,7 +2036,7 @@ int NativeMacEncryptCb(WOLFSSL* ssl, unsigned char* macOut, jclass excClass; /* WolfSSLJNIException class */ int needsDetach = 0; /* Should we explicitly detach? */ - static jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ + jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ jclass sessClass; /* WolfSSLSession class */ jfieldID ctxFid; /* WolfSSLSession->ctx FieldID */ jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */ @@ -2299,7 +2299,7 @@ int NativeDecryptVerifyCb(WOLFSSL* ssl, unsigned char* decOut, jclass excClass; /* WolfSSLJNIException class */ int needsDetach = 0; /* Should we explicitly detach? */ - static jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ + jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ jclass sessClass; /* WolfSSLSession class */ jfieldID ctxFid; /* WolfSSLSession->ctx FieldID */ jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */ @@ -2556,7 +2556,7 @@ int NativeVerifyDecryptCb(WOLFSSL* ssl, unsigned char* decOut, int needsDetach = 0; /* Should we explicitly detach? */ int hmacSize = 0; /* WOLFSSL HMAC digest size */ - static jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ + jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ jclass sessClass; /* WolfSSLSession class */ jfieldID ctxFid; /* WolfSSLSession->ctx FieldID */ jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */ @@ -2851,7 +2851,7 @@ int NativeEccSignCb(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz, jclass excClass; /* WolfSSLJNIException class */ int needsDetach = 0; /* Should we explicitly detach? */ - static jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ + jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ jclass sessClass; /* WolfSSLSession class */ jfieldID ctxFid; /* WolfSSLSession->ctx FieldID */ jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */ @@ -3158,7 +3158,7 @@ int NativeEccVerifyCb(WOLFSSL* ssl, const unsigned char* sig, jclass excClass; /* WolfSSLJNIException class */ int needsDetach = 0; /* Should we explicitly detach? */ - static jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ + jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ jclass sessClass; /* WolfSSLSession class */ jfieldID ctxFid; /* WolfSSLSession->ctx FieldID */ jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */ @@ -3561,7 +3561,7 @@ int NativeEccSharedSecretCb(WOLFSSL* ssl, ecc_key* otherKey, JNIEnv* jenv = NULL; /* JNI Environment */ int needsDetach = 0; /* Should we explicitly detach? */ - static jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ + jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ jobject ctxRef; /* WolfSSLContext object */ jmethodID eccSharedSecretMethodId; @@ -3899,7 +3899,7 @@ int NativeRsaSignCb(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz, jclass excClass; /* WolfSSLJNIException class */ int needsDetach = 0; /* Should we explicitly detach? */ - static jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ + jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ jclass sessClass; /* WolfSSLSession class */ jfieldID ctxFid; /* WolfSSLSession->ctx FieldID */ jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */ @@ -4206,7 +4206,7 @@ int NativeRsaPssSignCb(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz, jclass excClass; int needsDetach = 0; - static jobject* g_cachedSSLObj; + jobject* g_cachedSSLObj; jclass sessClass; jfieldID ctxFid; jmethodID getCtxMethodId; @@ -4526,7 +4526,7 @@ int NativeRsaVerifyCb(WOLFSSL* ssl, unsigned char* sig, unsigned int sigSz, jclass excClass; /* WolfSSLJNIException class */ int needsDetach = 0; /* Should we explicitly detach? */ - static jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ + jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ jclass sessClass; /* WolfSSLSession class */ jfieldID ctxFid; /* WolfSSLSession->ctx FieldID */ jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */ @@ -4810,7 +4810,7 @@ int NativeRsaSignCheckCb(WOLFSSL* ssl, unsigned char* sig, unsigned int sigSz, jclass excClass; int needsDetach = 0; - static jobject* g_cachedSSLObj; + jobject* g_cachedSSLObj; jclass sessClass; jfieldID ctxFid; jmethodID getCtxMethodId; @@ -5039,7 +5039,7 @@ int NativeRsaPssSignCheckCb(WOLFSSL* ssl, unsigned char* sig, jclass excClass; int needsDetach = 0; - static jobject* g_cachedSSLObj; + jobject* g_cachedSSLObj; jclass sessClass; jfieldID ctxFid; jmethodID getCtxMethodId; @@ -5300,7 +5300,7 @@ int NativeRsaEncCb(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz, jclass excClass; /* WolfSSLJNIException class */ int needsDetach = 0; /* Should we explicitly detach? */ - static jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ + jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ jclass sessClass; /* WolfSSLSession class */ jfieldID ctxFid; /* WolfSSLSession->ctx FieldID */ jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */ @@ -5602,7 +5602,7 @@ int NativeRsaDecCb(WOLFSSL* ssl, unsigned char* in, unsigned int inSz, jclass excClass; /* WolfSSLJNIException class */ int needsDetach = 0; /* Should we explicitly detach? */ - static jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ + jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ jclass sessClass; /* WolfSSLSession class */ jfieldID ctxFid; /* WolfSSLSession->ctx FieldID */ jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */ @@ -5861,7 +5861,7 @@ unsigned int NativePskClientCb(WOLFSSL* ssl, const char* hint, char* identity, JNIEnv* jenv; /* JNI environment */ jclass excClass; /* class: WolfSSLJNIException */ - static jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ + jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ jclass sessClass; /* WolfSSLSession class */ jfieldID ctxFid; /* WolfSSLSession->ctx fieldID */ jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */ @@ -6301,7 +6301,7 @@ unsigned int NativePskServerCb(WOLFSSL* ssl, const char* identity, JNIEnv* jenv; /* JNI environment */ jclass excClass; /* class: WolfSSLJNIException */ - static jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ + jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ jclass sessClass; /* WolfSSLSession class */ jfieldID ctxFid; /* WolfSSLSession->ctx fieldID */ jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */ From 2ba343426fe98c9a8b849a661231ba0ead2f84b1 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 20 Mar 2026 10:55:12 -0600 Subject: [PATCH 13/16] JSSE: Zeroize private key byte arrays after use in loadKeyAndCertChain --- .../provider/jsse/WolfSSLEngineHelper.java | 53 +++++++++++-------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/src/java/com/wolfssl/provider/jsse/WolfSSLEngineHelper.java b/src/java/com/wolfssl/provider/jsse/WolfSSLEngineHelper.java index 537253e4..3e378b58 100644 --- a/src/java/com/wolfssl/provider/jsse/WolfSSLEngineHelper.java +++ b/src/java/com/wolfssl/provider/jsse/WolfSSLEngineHelper.java @@ -359,32 +359,43 @@ protected synchronized void loadKeyAndCertChain( if (privKey != null) { byte[] privKeyEncoded = privKey.getEncoded(); - if (!privKey.getFormat().equals("PKCS#8")) { - throw new WolfSSLException( - "Private key is not in PKCS#8 format"); - } + byte[] privKeyTraditional = null; + try { + if (!privKey.getFormat().equals("PKCS#8")) { + throw new WolfSSLException( + "Private key is not in PKCS#8 format"); + } - /* Skip past PKCS#8 offset */ - offset = WolfSSL.getPkcs8TraditionalOffset(privKeyEncoded, 0, - privKeyEncoded.length); + /* Skip past PKCS#8 offset */ + offset = WolfSSL.getPkcs8TraditionalOffset(privKeyEncoded, 0, + privKeyEncoded.length); - byte[] privKeyTraditional = Arrays.copyOfRange(privKeyEncoded, - offset, privKeyEncoded.length); + privKeyTraditional = Arrays.copyOfRange(privKeyEncoded, + offset, privKeyEncoded.length); - try { - ret = this.ssl.usePrivateKeyBuffer(privKeyTraditional, - privKeyTraditional.length, WolfSSL.SSL_FILETYPE_ASN1); - } catch (WolfSSLJNIException e) { - throw new WolfSSLException(e); - } + try { + ret = this.ssl.usePrivateKeyBuffer(privKeyTraditional, + privKeyTraditional.length, WolfSSL.SSL_FILETYPE_ASN1); + } catch (WolfSSLJNIException e) { + throw new WolfSSLException(e); + } - if (ret != WolfSSL.SSL_SUCCESS) { - throw new WolfSSLException("Failed to load private key " + - "buffer into WOLFSSL, err = " + ret); + if (ret != WolfSSL.SSL_SUCCESS) { + throw new WolfSSLException("Failed to load private key " + + "buffer into WOLFSSL, err = " + ret); + } + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + () -> "loaded private key from X509KeyManager (alias: " + + alias + ")"); + + } finally { + if (privKeyEncoded != null) { + Arrays.fill(privKeyEncoded, (byte)0); + } + if (privKeyTraditional != null) { + Arrays.fill(privKeyTraditional, (byte)0); + } } - WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, - () -> "loaded private key from X509KeyManager " + - "(alias: " + alias + ")"); } else { WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, () -> "no private key found in X509KeyManager " + From c5885abe2786463aface6f28d5e79fe99fc45c15 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 20 Mar 2026 11:10:38 -0600 Subject: [PATCH 14/16] JNI: Add null check for fieldStr and entryArr in X509_NAME_add_entry_by_txt --- native/com_wolfssl_WolfSSLX509Name.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/com_wolfssl_WolfSSLX509Name.c b/native/com_wolfssl_WolfSSLX509Name.c index fffbe9b2..f9d0c8c0 100644 --- a/native/com_wolfssl_WolfSSLX509Name.c +++ b/native/com_wolfssl_WolfSSLX509Name.c @@ -92,7 +92,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLX509Name_X509_1NAME_1add_1entry_1 (void)jcl; (void)entryLen; - if (jenv == NULL) { + if (jenv == NULL || fieldStr == NULL || entryArr == NULL) { return ret; } From ece3dcac7a16c2eb0386afc9caa94898255c3fa9 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 20 Mar 2026 11:17:45 -0600 Subject: [PATCH 15/16] JNI: Reset pollRx/pollTx flags at start of each I/O loop iteration --- native/com_wolfssl_WolfSSLSession.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/native/com_wolfssl_WolfSSLSession.c b/native/com_wolfssl_WolfSSLSession.c index aa64e76b..a4bca55f 100644 --- a/native/com_wolfssl_WolfSSLSession.c +++ b/native/com_wolfssl_WolfSSLSession.c @@ -1056,6 +1056,11 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_connect } do { + pollRx = 0; + #if !defined(WOLFJNI_USE_IO_SELECT) && !defined(USE_WINDOWS_API) + pollTx = 0; + #endif + /* get I/O lock */ if (wc_LockMutex(jniSessLock) != 0) { ret = WOLFSSL_FAILURE; @@ -1162,6 +1167,11 @@ static int SSLWriteNonblockingWithSelectPoll(WOLFSSL* ssl, byte* data, } do { + pollRx = 0; + #if !defined(WOLFJNI_USE_IO_SELECT) && !defined(USE_WINDOWS_API) + pollTx = 0; + #endif + /* lock mutex around session I/O before write attempt */ if (wc_LockMutex(jniSessLock) != 0) { ret = WOLFSSL_FAILURE; @@ -1381,6 +1391,11 @@ static int SSLReadNonblockingWithSelectPoll(WOLFSSL* ssl, byte* out, } do { + pollRx = 0; + #if !defined(WOLFJNI_USE_IO_SELECT) && !defined(USE_WINDOWS_API) + pollTx = 0; + #endif + /* lock mutex around session I/O before read attempt */ if (wc_LockMutex(jniSessLock) != 0) { size = WOLFSSL_FAILURE; @@ -1621,6 +1636,11 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_accept } do { + pollRx = 0; + #if !defined(WOLFJNI_USE_IO_SELECT) && !defined(USE_WINDOWS_API) + pollTx = 0; + #endif + /* get I/O lock */ if (wc_LockMutex(jniSessLock) != 0) { ret = WOLFSSL_FAILURE; @@ -1910,6 +1930,11 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_shutdownSSL } do { + pollRx = 0; + #if !defined(WOLFJNI_USE_IO_SELECT) && !defined(USE_WINDOWS_API) + pollTx = 0; + #endif + /* get I/O lock */ if (wc_LockMutex(jniSessLock) != 0) { ret = WOLFSSL_FAILURE; From 6daeaa767bd87037056480cf63938b209aad3b65 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 20 Mar 2026 11:18:57 -0600 Subject: [PATCH 16/16] JNI: Guard ReleaseStringUTFChars calls against null mdName --- native/com_wolfssl_WolfSSLCertRequest.c | 4 +++- native/com_wolfssl_WolfSSLCertificate.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/native/com_wolfssl_WolfSSLCertRequest.c b/native/com_wolfssl_WolfSSLCertRequest.c index 33156272..b21f9843 100644 --- a/native/com_wolfssl_WolfSSLCertRequest.c +++ b/native/com_wolfssl_WolfSSLCertRequest.c @@ -340,7 +340,9 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1sign } (*jenv)->ReleaseByteArrayElements(jenv, keyBytes, (jbyte*)keyBuf, JNI_ABORT); - (*jenv)->ReleaseStringUTFChars(jenv, digestAlg, mdName); + if (mdName != NULL) { + (*jenv)->ReleaseStringUTFChars(jenv, digestAlg, mdName); + } return (jint)ret; #else diff --git a/native/com_wolfssl_WolfSSLCertificate.c b/native/com_wolfssl_WolfSSLCertificate.c index c7a1d890..dd5a12bc 100644 --- a/native/com_wolfssl_WolfSSLCertificate.c +++ b/native/com_wolfssl_WolfSSLCertificate.c @@ -970,7 +970,9 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1sign } (*jenv)->ReleaseByteArrayElements(jenv, fileBytes, (jbyte*)fileBuf, JNI_ABORT); - (*jenv)->ReleaseStringUTFChars(jenv, digestAlg, mdName); + if (mdName != NULL) { + (*jenv)->ReleaseStringUTFChars(jenv, digestAlg, mdName); + } return (jint)ret; #else