Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JNI: wrap wolfSSL_SessionIsSetup() in WolfSSLSession #191

Merged
merged 7 commits into from
Apr 25, 2024
4 changes: 3 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,13 @@ jobs:
wolfssl_configure: ${{ matrix.wolfssl_configure }}

# Temurin JDK (Linux, Mac)
# JDK 8 seems to have been removed from Temurin macos, with 8 we see the error
# Could not find satisfied version for SemVer '8'
linux-temurin:
strategy:
matrix:
os: [ 'ubuntu-latest', 'macos-latest' ]
jdk_version: [ '8', '11', '17', '21' ]
jdk_version: [ '11', '17', '21' ]
wolfssl_configure: [ '--enable-jni' ]
name: ${{ matrix.os }} (Temurin JDK ${{ matrix.jdk_version }}, ${{ matrix.wolfssl_configure}})
uses: ./.github/workflows/linux-common.yml
Expand Down
59 changes: 52 additions & 7 deletions native/com_wolfssl_WolfSSLSession.c
Original file line number Diff line number Diff line change
Expand Up @@ -1331,20 +1331,28 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_getSession
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_get1Session
(JNIEnv* jenv, jobject jcl, jlong sslPtr)
{
int ret = 0;
int err = 0;
int sockfd = 0;
int version = 0;
int hasTicket = 0;
WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr;
WOLFSSL_SESSION* sess = NULL;
WOLFSSL_SESSION* dup = NULL;
wolfSSL_Mutex* jniSessLock = NULL;
SSLAppData* appData = NULL;

/* tmpBuf is only 1 byte since wolfSSL_peek() doesn't need to read
* any app data, only session ticket internally */
char tmpBuf[1];
int ret = 0;
int err = 0;
int sockfd = 0;

(void)jenv;
(void)jcl;

if (ssl == NULL) {
return (jlong)0;
}

/* get session mutex from SSL app data */
appData = (SSLAppData*)wolfSSL_get_app_data(ssl);
if (appData == NULL) {
Expand All @@ -1364,13 +1372,22 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_get1Session
return (jlong)0;
}

/* get protocol version for this session */
version = wolfSSL_version(ssl);

/* Use wolfSSL_get_session() only as an indicator if we need to call
* wolfSSL_peek() for TLS 1.3 connections to potentially get the
* session ticket message. */
sess = wolfSSL_get_session(ssl);
if (sess == NULL) {

/* session not available yet (TLS 1.3), try peeking to get ticket */
/* Check if session has session ticket, checks sess for null internal */
hasTicket = wolfSSL_SESSION_has_ticket((const WOLFSSL_SESSION*)sess);

/* If session is not available yet, or if TLS 1.3 and we have a session
* pointer but no session ticket yet, try peeking to get ticket */
if (sess == NULL ||
((sess != NULL) && (version == TLS1_3_VERSION) && (hasTicket == 0))) {

do {
ret = wolfSSL_peek(ssl, tmpBuf, (int)sizeof(tmpBuf));
err = wolfSSL_get_error(ssl, ret);
Expand All @@ -1397,12 +1414,12 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_get1Session
} while (err == SSL_ERROR_WANT_READ);

sess = wolfSSL_get_session(ssl);
hasTicket = wolfSSL_SESSION_has_ticket((const WOLFSSL_SESSION*)sess);
}

/* Only duplicate / save session if not TLS 1.3 (will be using normal
* session IDs), or is TLS 1.3 and we have a session ticket */
if ((wolfSSL_version(ssl) != TLS1_3_VERSION) ||
(wolfSSL_SESSION_has_ticket((const WOLFSSL_SESSION*)sess))) {
if (version != TLS1_3_VERSION || hasTicket == 1) {

/* wolfSSL checks ssl for NULL, returns pointer to new WOLFSSL_SESSION,
* Returns new duplicated WOLFSSL_SESSION. Needs to be freed with
Expand All @@ -1420,6 +1437,34 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_get1Session
return (jlong)(uintptr_t)dup;
}

JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_wolfsslSessionIsSetup
(JNIEnv* jenv, jclass jcl, jlong sessionPtr)
{
#if (LIBWOLFSSL_VERSION_HEX > 0x05007000) || \
defined(WOLFSSL_PR7430_PATCH_APPLIED)
int ret;
WOLFSSL_SESSION* session = (WOLFSSL_SESSION*)(uintptr_t)sessionPtr;
(void)jcl;

if (jenv == NULL) {
return 0;
}

/* wolfSSL_SessionIsSetup() was added after wolfSSL 5.7.0 in PR
* 7430. Version checked above must be greater than 5.7.0 or patch
* from this PR must be applied and WOLFSSL_PR7430_PATCH_APPLIED defined
* when compiling this JNI wrapper */
ret = wolfSSL_SessionIsSetup(session);

return (jint)ret;
#else
(void)jenv;
(void)jcl;
(void)sessionPtr;
return (jint)NOT_COMPILED_IN;
#endif
}

JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_freeNativeSession
(JNIEnv* jenv, jclass jcl, jlong sessionPtr)
{
Expand Down
8 changes: 8 additions & 0 deletions native/com_wolfssl_WolfSSLSession.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 26 additions & 1 deletion src/java/com/wolfssl/WolfSSLSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public WolfSSLSession(WolfSSLContext ctx) throws WolfSSLException {
/* ------------------- private/protected methods -------------------- */

/* used from JNI code */
WolfSSLContext getAssociatedContextPtr() {
synchronized WolfSSLContext getAssociatedContextPtr() {
return ctx;
}

Expand Down Expand Up @@ -262,6 +262,7 @@ private native int read(long ssl, byte[] data, int offset, int sz,
private native int setSession(long ssl, long session);
private native long getSession(long ssl);
private native long get1Session(long ssl);
private static native int wolfsslSessionIsSetup(long ssl);
private static native void freeNativeSession(long session);
private native byte[] getSessionID(long session);
private native int setServerID(long ssl, byte[] id, int len, int newSess);
Expand Down Expand Up @@ -1364,6 +1365,30 @@ public long getSession() throws IllegalStateException {
}
}

/**
* Check if native WOLFSSL_SESSION has been set up or not.
*
* This method is static and does not check active state since this
* takes a native pointer and has no interaction with the rest of this
* object.
*
* @param session pointer to native WOLFSSL_SESSION structure. May be
* obtained from getSession().
*
* @return 1 if session has been set up, otherwise 0 if not set up. May
* return WolfSSL.NOT_COMPILED_IN if native wolfSSL does not have
* wolfSSL_SessionIsSetup() compiled in. This API was added
* after the wolfSSL 5.7.0 release.
*/
public static int sessionIsSetup(long session) {

if (session == 0) {
return 0;
}

return wolfsslSessionIsSetup(session);
}

/**
* Free the native WOLFSSL_SESSION structure pointed to be session.
*
Expand Down
4 changes: 2 additions & 2 deletions src/java/com/wolfssl/provider/jsse/WolfSSLSocket.java
Original file line number Diff line number Diff line change
Expand Up @@ -975,7 +975,7 @@ private void setFd() throws IllegalArgumentException, WolfSSLException {
* @return array of supported cipher suite Strings
*/
@Override
public String[] getSupportedCipherSuites() {
public synchronized String[] getSupportedCipherSuites() {

WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"entered getSupportedCipherSuites()");
Expand Down Expand Up @@ -1197,7 +1197,7 @@ public int alpnSelectCallback(WolfSSLSession ssl, String[] out,
* @return String array containing supported SSL/TLS protocols
*/
@Override
public String[] getSupportedProtocols() {
public synchronized String[] getSupportedProtocols() {

WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"entered getSupportedProtocols()");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2023,6 +2023,7 @@ private void protocolConnectionTestExtendedSocket(String protocol)
public Void call() throws Exception {
try {
server.startHandshake();
server.close();

} catch (SSLException e) {
System.out.println("\t... failed");
Expand All @@ -2034,6 +2035,7 @@ public Void call() throws Exception {

try {
cs.startHandshake();
cs.close();

} catch (SSLHandshakeException e) {
System.out.println("\t... failed");
Expand All @@ -2042,8 +2044,6 @@ public Void call() throws Exception {

es.shutdown();
serverFuture.get();
cs.close();
server.close();
ss.close();

System.out.println("\t... passed");
Expand Down
Loading