Skip to content

Commit

Permalink
Merge pull request #193 from cconlon/sslEngineFixesMay2024
Browse files Browse the repository at this point in the history
SSLEngine fixes for session cache, getError(), and unwrap() HandshakeStatus
  • Loading branch information
JacobBarthelmeh authored May 22, 2024
2 parents 37cf4dc + 8d805ff commit 2353670
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 19 deletions.
21 changes: 21 additions & 0 deletions native/com_wolfssl_WolfSSLSession.c
Original file line number Diff line number Diff line change
Expand Up @@ -4945,6 +4945,27 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useSupportedCurve
#endif
}

JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_hasTicket
(JNIEnv* jenv, jobject jcl, jlong sessionPtr)
{
#if !defined(NO_SESSION_CACHE) && \
(defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE))
WOLFSSL_SESSION* session = (WOLFSSL_SESSION*)(uintptr_t)sessionPtr;
(void)jcl;

if (jenv == NULL || session == NULL) {
return WOLFSSL_FAILURE;
}

return (jint)wolfSSL_SESSION_has_ticket((const WOLFSSL_SESSION*)session);
#else
(void)jenv;
(void)jcl;
(void)sessionPtr;
return (jint)WolfSSL.SSL_FAILURE;
#endif
}

JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setSSLIORecv
(JNIEnv* jenv, jobject jcl, jlong sslPtr)
{
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.

26 changes: 26 additions & 0 deletions src/java/com/wolfssl/WolfSSLSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ private native int setTlsHmacInner(long ssl, byte[] inner, long sz,
private native int rehandshake(long ssl);
private native int set1SigAlgsList(long ssl, String list);
private native int useSupportedCurve(long ssl, int name);
private native int hasTicket(long session);

/* ------------------- session-specific methods --------------------- */

Expand Down Expand Up @@ -1429,6 +1430,31 @@ public byte[] getSessionID() throws IllegalStateException {
}
}

/**
* Check if there is a session ticket associated with this
* WolfSSLSession (WOLFSSL_SESSION).
*
* @return true if internal session has session ticket, otherwise false
* @throws IllegalStateException WolfSSLContext has been freed
*/
public boolean hasSessionTicket() throws IllegalStateException {

boolean hasTicket = false;

confirmObjectIsActive();

synchronized (sslLock) {
long sess = getSession(this.sslPtr);
if (sess != 0) {
if (hasTicket(sess) == WolfSSL.SSL_SUCCESS) {
hasTicket = true;
}
}

return hasTicket;
}
}

/**
* Gets the cache size is set at compile time.
* This function returns the current cache size which has been set at compile
Expand Down
70 changes: 52 additions & 18 deletions src/java/com/wolfssl/provider/jsse/WolfSSLEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ public class WolfSSLEngine extends SSLEngine {
/* session stored (WOLFSSL_SESSION), relevant on client side */
private boolean sessionStored = false;

/* TLS 1.3 session ticket received (on client side) */
private boolean sessionTicketReceived = false;

/* client/server mode has been set */
private boolean clientModeSet = false;

Expand Down Expand Up @@ -345,16 +348,22 @@ private synchronized void UpdateCloseNotifyStatus() {
/**
* Handles logic during shutdown
*
* @return WolfSSL.SSL_SUCCESS on success, zero or negative on error
* @throws SocketException if ssl.shutdownSSL() encounters a socket error
*/
private synchronized int ClosingConnection() throws SocketException {
int ret;

/* Save session into WolfSSLAuthStore cache, saves session
* pointer for resumption if on client side. Protected with ioLock
* since underlying get1Session can use I/O with peek. */
if (!this.sessionStored) {
synchronized (ioLock) {
* since underlying get1Session can use I/O with peek.
*
* Only store session if handshake is finished, SSL_get_error() does
* not have an active error state, and the session has not been
* stored previously. */
synchronized (ioLock) {
if (this.handshakeFinished && (ssl.getError(0) == 0) &&
!this.sessionStored) {
this.engineHelper.saveSession();
}
}
Expand All @@ -369,11 +378,11 @@ private synchronized int ClosingConnection() throws SocketException {
synchronized (ioLock) {
ret = ssl.shutdownSSL();
if (ssl.getError(ret) == WolfSSL.SSL_ERROR_ZERO_RETURN) {
/* got close_notify alert, reset ret to 0 to continue
/* got close_notify alert, reset ret to SSL_SUCCESS to continue
* and let corresponding close_notify to be sent */
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"ClosingConnection(), ssl.getError() is ZERO_RETURN");
ret = 0;
ret = WolfSSL.SSL_SUCCESS;
}
}
UpdateCloseNotifyStatus();
Expand All @@ -392,18 +401,20 @@ private synchronized int DoHandshake() throws SSLException {
if (this.getUseClientMode()) {
synchronized (ioLock) {
ret = this.ssl.connect();

WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"ssl.connect() ret:err = " + ret + " : " +
ssl.getError(ret));
}
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"ssl.connect() ret:err = " + ret + " : " +
ssl.getError(ret));
}
else {
synchronized (ioLock) {
ret = this.ssl.accept();

WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"ssl.accept() ret:err = " + ret + " : " +
ssl.getError(ret));
}
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"ssl.accept() ret:err = " + ret + " : " +
ssl.getError(ret));
}

} catch (SocketTimeoutException | SocketException e) {
Expand Down Expand Up @@ -749,6 +760,7 @@ private synchronized int RecvAppData(ByteBuffer[] out, int ofst, int length)
int maxOutSz = 0;
int ret = 0;
int idx = 0; /* index into out[] array */
int err = 0;
byte[] tmp;

/* create read buffer of max output size */
Expand All @@ -763,10 +775,11 @@ private synchronized int RecvAppData(ByteBuffer[] out, int ofst, int length)
}
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"RecvAppData(), ssl.read() ret = " + ret);

err = ssl.getError(ret);
}

if (ret <= 0) {
int err = ssl.getError(ret);
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"RecvAppData(), ssl.getError() = " + err);

Expand Down Expand Up @@ -852,7 +865,7 @@ public synchronized SSLEngineResult unwrap(ByteBuffer in, ByteBuffer out)
@Override
public synchronized SSLEngineResult unwrap(ByteBuffer in, ByteBuffer[] out,
int ofst, int length) throws SSLException {
int i, ret = 0, sz = 0;
int i, ret = 0, sz = 0, err = 0;
int inPosition = 0;
int inRemaining = 0;
int consumed = 0;
Expand Down Expand Up @@ -952,7 +965,7 @@ public synchronized SSLEngineResult unwrap(ByteBuffer in, ByteBuffer[] out,
hs = SSLEngineResult.HandshakeStatus.NEED_WRAP;
}
else if (hs == SSLEngineResult.HandshakeStatus.NEED_WRAP &&
this.toSend.length > 0) {
(this.toSend != null) && (this.toSend.length > 0)) {
/* Already have data buffered to send and in NEED_WRAP state,
* just return so wrap() can be called */
hs = SSLEngineResult.HandshakeStatus.NEED_WRAP;
Expand Down Expand Up @@ -1025,8 +1038,9 @@ else if (hs == SSLEngineResult.HandshakeStatus.NEED_WRAP &&
* we may need to wait for session ticket. We do try
* right after wolfSSL_connect/accept() finishes, but
* we might not have had session ticket at that time. */
if (!this.sessionStored) {
synchronized (ioLock) {
synchronized (ioLock) {
if (this.handshakeFinished && (ssl.getError(0) == 0) &&
!this.sessionStored) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"calling engineHelper.saveSession()");
int ret2 = this.engineHelper.saveSession();
Expand All @@ -1047,7 +1061,9 @@ else if (hs == SSLEngineResult.HandshakeStatus.NEED_WRAP &&
this.engineHelper.unsetVerifyCallback();
}

int err = ssl.getError(ret);
synchronized (ioLock) {
err = ssl.getError(ret);
}
if (ret < 0 &&
(err != WolfSSL.SSL_ERROR_WANT_READ) &&
(err != WolfSSL.SSL_ERROR_WANT_WRITE)) {
Expand Down Expand Up @@ -1080,6 +1096,18 @@ else if (hs == SSLEngineResult.HandshakeStatus.NEED_WRAP &&
SetHandshakeStatus(ret);
}

/* If client side and we have just received a TLS 1.3 session ticket,
* we should return FINISHED HandshakeStatus from unwrap() directly
* but not from getHandshakeStatus(). Keep track of if we have
* received ticket, so we only set/return this once */
synchronized (ioLock) {
if (this.getUseClientMode() && this.ssl.hasSessionTicket() &&
this.sessionTicketReceived == false) {
hs = SSLEngineResult.HandshakeStatus.FINISHED;
this.sessionTicketReceived = true;
}
}

if (extraDebugEnabled == true) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"==== [ exiting unwrap() ] ==================================");
Expand Down Expand Up @@ -1147,7 +1175,13 @@ else if (hs == SSLEngineResult.HandshakeStatus.NEED_WRAP &&
*/
private synchronized void SetHandshakeStatus(int ret) {

int err = ssl.getError(ret);
int err = 0;

/* Get current wolfSSL error, synchronize on ioLock in case I/O is
* happening and error state may change */
synchronized (ioLock) {
err = ssl.getError(ret);
}

/* Lock access to this.toSend and this.toRead */
synchronized (toSendLock) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,9 @@ public long getLastAccessedTime() {
* Invalidate this session
*/
public synchronized void invalidate() {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"SSLSession.invalidate() called, invalidating session");

this.valid = false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1813,7 +1813,7 @@ public void testProtocolTLSv10() throws Exception {
protocolConnectionTest("TLSv1");

System.out.print("\tTLS 1.0 extended Socket test");
protocolConnectionTestExtendedSocket("TLSv1.0");
protocolConnectionTestExtendedSocket("TLSv1");
}

@Test
Expand Down

0 comments on commit 2353670

Please sign in to comment.