From c5304ebb195c559c4d225b4c40b2e894a2ea87bc Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 18 Apr 2024 16:33:43 -0600 Subject: [PATCH 1/6] JSSE: close WolfSSLInput/OutputStream when SSLSocket.close() is called, allows stream objects to be garbage collected more easily --- .../wolfssl/provider/jsse/WolfSSLSocket.java | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/java/com/wolfssl/provider/jsse/WolfSSLSocket.java b/src/java/com/wolfssl/provider/jsse/WolfSSLSocket.java index c93e22aa..4b474e70 100644 --- a/src/java/com/wolfssl/provider/jsse/WolfSSLSocket.java +++ b/src/java/com/wolfssl/provider/jsse/WolfSSLSocket.java @@ -1890,6 +1890,9 @@ public synchronized void close() throws IOException { this.connectionClosed = true; + /* Release native verify callback (JNI global) */ + this.EngineHelper.unsetVerifyCallback(); + /* Connection is closed, free native WOLFSSL session * to release native memory earlier than garbage * collector might with finalize(). */ @@ -1905,6 +1908,17 @@ public synchronized void close() throws IOException { "calling this.ssl.freeSSL()"); this.ssl.freeSSL(); this.ssl = null; + + /* Release Input/OutputStream objects */ + if (this.inStream != null) { + this.inStream.close(); + this.inStream = null; + } + if (this.outStream != null) { + this.outStream.close(); + this.outStream = null; + } + } /* handshakeLock */ WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, @@ -2326,13 +2340,20 @@ class WolfSSLInputStream extends InputStream { private WolfSSLSession ssl; private WolfSSLSocket socket; + private boolean isClosed = true; public WolfSSLInputStream(WolfSSLSession ssl, WolfSSLSocket socket) { this.ssl = ssl; this.socket = socket; /* parent socket */ + this.isClosed = false; } public synchronized void close() throws IOException { + + if (this.socket == null || this.isClosed) { + return; + } + if (this.socket.isClosed()) { WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, "socket (input) already closed"); @@ -2343,6 +2364,10 @@ public synchronized void close() throws IOException { "socket (input) closed: " + this.socket); } + this.socket = null; + this.ssl = null; + this.isClosed = true; + return; } @@ -2381,7 +2406,7 @@ public synchronized int read(byte[] b, int off, int len) } /* check if socket is closed */ - if (socket.isClosed()) { + if (this.isClosed || socket == null || socket.isClosed()) { throw new SocketException("Socket is closed"); } @@ -2470,13 +2495,20 @@ class WolfSSLOutputStream extends OutputStream { private WolfSSLSession ssl; private WolfSSLSocket socket; + private boolean isClosed = true; public WolfSSLOutputStream(WolfSSLSession ssl, WolfSSLSocket socket) { this.ssl = ssl; this.socket = socket; /* parent socket */ + this.isClosed = false; } public synchronized void close() throws IOException { + + if (this.socket == null || this.isClosed) { + return; + } + if (this.socket.isClosed()) { WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, "socket (output) already closed"); @@ -2487,6 +2519,10 @@ public synchronized void close() throws IOException { "socket (output) closed: " + this.socket); } + this.socket = null; + this.ssl = null; + this.isClosed = true; + return; } @@ -2510,6 +2546,10 @@ public synchronized void write(byte[] b, int off, int len) throw new NullPointerException("Input array is null"); } + if (this.socket == null || this.isClosed) { + throw new SocketException("Socket is closed"); + } + /* check if connection has already been closed/shutdown */ WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, "trying to get socket.handshakeLock (write)"); From 10e991c52d50ddb1e138690a6cc15d57d27a7b8b Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 18 Apr 2024 16:47:00 -0600 Subject: [PATCH 2/6] JSSE: remove finalizer() from WolfSSLInternalVerifyCb, not needed and slows down garbage collection --- .../wolfssl/provider/jsse/WolfSSLInternalVerifyCb.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/java/com/wolfssl/provider/jsse/WolfSSLInternalVerifyCb.java b/src/java/com/wolfssl/provider/jsse/WolfSSLInternalVerifyCb.java index d5cd6131..f0fae971 100644 --- a/src/java/com/wolfssl/provider/jsse/WolfSSLInternalVerifyCb.java +++ b/src/java/com/wolfssl/provider/jsse/WolfSSLInternalVerifyCb.java @@ -359,15 +359,5 @@ else if ((preverify_ok == 1) && (x509certs.length == 0) && /* Continue handshake, verification succeeded */ return 1; } - - @SuppressWarnings("deprecation") - @Override - protected void finalize() throws Throwable { - this.callingSocket = null; - this.callingEngine = null; - this.tm = null; - this.params = null; - super.finalize(); - } } From a7c1830b0e6b53ced9eb87522722c87384c95493 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 18 Apr 2024 17:10:45 -0600 Subject: [PATCH 3/6] JNI: set clientSNIRequested and ctx to null in freeSSL() to reduce object size in GC finalizer --- src/java/com/wolfssl/WolfSSLSession.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/java/com/wolfssl/WolfSSLSession.java b/src/java/com/wolfssl/WolfSSLSession.java index 3ecc4854..3606fb61 100644 --- a/src/java/com/wolfssl/WolfSSLSession.java +++ b/src/java/com/wolfssl/WolfSSLSession.java @@ -1165,6 +1165,8 @@ public synchronized void freeSSL() /* free Java resources */ this.active = false; this.sslPtr = 0; + this.clientSNIRequested = null; + this.ctx = null; } } } From 65e4191ba47f7d9a450c51f073db393fc6da1a54 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 18 Apr 2024 17:12:24 -0600 Subject: [PATCH 4/6] JSSE: release WolfSSLEngineHelper state from WolfSSLSocket when SSLSocket.close() is called --- .../com/wolfssl/provider/jsse/WolfSSLEngineHelper.java | 7 +++++++ src/java/com/wolfssl/provider/jsse/WolfSSLSocket.java | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/src/java/com/wolfssl/provider/jsse/WolfSSLEngineHelper.java b/src/java/com/wolfssl/provider/jsse/WolfSSLEngineHelper.java index 257eec22..3780c800 100644 --- a/src/java/com/wolfssl/provider/jsse/WolfSSLEngineHelper.java +++ b/src/java/com/wolfssl/provider/jsse/WolfSSLEngineHelper.java @@ -1390,6 +1390,13 @@ protected synchronized int saveSession() { return WolfSSL.SSL_FAILURE; } + protected synchronized void clearObjectState() { + this.ssl = null; + this.session = null; + this.params = null; + this.authStore = null; + } + @SuppressWarnings("deprecation") @Override protected synchronized void finalize() throws Throwable { diff --git a/src/java/com/wolfssl/provider/jsse/WolfSSLSocket.java b/src/java/com/wolfssl/provider/jsse/WolfSSLSocket.java index 4b474e70..1f83442b 100644 --- a/src/java/com/wolfssl/provider/jsse/WolfSSLSocket.java +++ b/src/java/com/wolfssl/provider/jsse/WolfSSLSocket.java @@ -1909,6 +1909,10 @@ public synchronized void close() throws IOException { this.ssl.freeSSL(); this.ssl = null; + /* Reset internal WolfSSLEngineHelper to null */ + this.EngineHelper.clearObjectState(); + this.EngineHelper = null; + /* Release Input/OutputStream objects */ if (this.inStream != null) { this.inStream.close(); @@ -2080,6 +2084,8 @@ protected synchronized void finalize() throws Throwable { } this.ssl.freeSSL(); this.ssl = null; + this.EngineHelper = null; + this.params = null; } super.finalize(); } From 95777fd6531282fefd40401fd0e88ff7c1c0d2a8 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 18 Apr 2024 17:17:44 -0600 Subject: [PATCH 5/6] JSSE: add close() to WolfSSLServerSocket, closes unerlying WolfSSLSocket if needed which frees resources earlier --- .../com/wolfssl/provider/jsse/WolfSSLServerSocket.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/java/com/wolfssl/provider/jsse/WolfSSLServerSocket.java b/src/java/com/wolfssl/provider/jsse/WolfSSLServerSocket.java index f2ee750b..5639c72f 100644 --- a/src/java/com/wolfssl/provider/jsse/WolfSSLServerSocket.java +++ b/src/java/com/wolfssl/provider/jsse/WolfSSLServerSocket.java @@ -375,5 +375,13 @@ synchronized public Socket accept() throws IOException { return socket; } + + @Override + public synchronized void close() throws IOException { + if (this.socket != null) { + this.socket.close(); + } + super.close(); + } } From 0bf4b585354354c4d56b5de5c69bb9a818ec2ec8 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 18 Apr 2024 17:45:50 -0600 Subject: [PATCH 6/6] JNI: rework WolfSSLSession.useALPN() to guarantee list is null terminated --- native/com_wolfssl_WolfSSLSession.c | 30 +++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/native/com_wolfssl_WolfSSLSession.c b/native/com_wolfssl_WolfSSLSession.c index 70028a92..915aa653 100644 --- a/native/com_wolfssl_WolfSSLSession.c +++ b/native/com_wolfssl_WolfSSLSession.c @@ -4221,33 +4221,47 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_sslGet0AlpnSelected } JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useALPN - (JNIEnv* jenv, jobject jcl, jlong ssl, jstring protocols, jint options) + (JNIEnv* jenv, jobject jcl, jlong sslPtr, jstring protocols, jint options) { int ret = SSL_FAILURE; #ifdef HAVE_ALPN - const char* protoList; + WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; + char* protoList = NULL; + jsize protocolsLen = 0; (void)jcl; if (jenv == NULL || ssl == 0 || protocols == NULL || options < 0) { return BAD_FUNC_ARG; } - protoList = (*jenv)->GetStringUTFChars(jenv, protocols, 0); + protocolsLen = (*jenv)->GetStringUTFLength(jenv, protocols); + if (protocolsLen == 0) { + return BAD_FUNC_ARG; + } + + /* Allocate size + 1 to guarantee we are null terminated */ + protoList = (char*)XMALLOC(protocolsLen + 1, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (protoList == NULL) { + return MEMORY_E; + } - ret = (jint) wolfSSL_UseALPN((WOLFSSL*)(uintptr_t)ssl, (char*)protoList, - (unsigned int)XSTRLEN(protoList), (int)options); + /* GetStringUTFRegion() does not need to be freed/released */ + (*jenv)->GetStringUTFRegion(jenv, protocols, 0, protocolsLen, protoList); + protoList[protocolsLen] = '\0'; - (*jenv)->ReleaseStringUTFChars(jenv, protocols, protoList); + ret = wolfSSL_UseALPN(ssl, protoList, protocolsLen, (int)options); + + XFREE(protoList, NULL, DYNAMIC_TYPE_TMP_BUFFER); #else (void)jenv; (void)jcl; - (void)ssl; + (void)sslPtr; (void)protocols; (void)options; ret = NOT_COMPILED_IN; #endif - return ret; + return (jint)ret; } JNIEXPORT int JNICALL Java_com_wolfssl_WolfSSLSession_setALPNSelectCb