Skip to content

Commit ed375eb

Browse files
committed
update regression test to better test when inRemaining == 0 and add on additional continuation bytes testing
1 parent 2348699 commit ed375eb

2 files changed

Lines changed: 94 additions & 27 deletions

File tree

src/java/com/wolfssl/provider/jsse/WolfSSLEngine.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ public class WolfSSLEngine extends SSLEngine {
110110

111111
/* session stored (WOLFSSL_SESSION), relevant on client side */
112112
private boolean sessionStored = false;
113+
/* Skip record header peek in next unwrap, continue same TLS record */
113114
private boolean contPartialRecord = false;
114115

115116
/* TLS 1.3 session ticket received (on client side) */

src/test/com/wolfssl/provider/jsse/test/WolfSSLEngineTest.java

Lines changed: 93 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3047,13 +3047,13 @@ public void testBufferUnderflowPartialRecord()
30473047
}
30483048

30493049
@Test
3050-
public void testHandshakeUnwrapConsumedNotBufferUnderflow()
3050+
public void testHandshakeUnwrapIncrementalStatus()
30513051
throws NoSuchProviderException, NoSuchAlgorithmException,
30523052
KeyManagementException, KeyStoreException,
30533053
CertificateException, IOException,
30543054
UnrecoverableKeyException {
30553055

3056-
System.out.print("\tTest unwrap consumed != BUFFER_UNDERFLOW");
3056+
System.out.print("\tTest unwrap incremental status");
30573057

30583058
if (!enabledProtocols.contains("TLSv1.3")) {
30593059
System.out.println("\t... skipped");
@@ -3127,42 +3127,108 @@ public void testHandshakeUnwrapConsumedNotBufferUnderflow()
31273127
srvFlight.flip();
31283128

31293129
int total = srvFlight.remaining();
3130-
if (total < 2) {
3130+
/* Parse first TLS record header to find exact boundary:
3131+
* type[1] + version[2] + length[2] = 5 bytes. */
3132+
if (total < 5) {
31313133
error("\t... failed");
3132-
fail("server flight too small to split: " + total);
3134+
fail("server flight too small: " + total);
3135+
}
3136+
int firstRecPayload =
3137+
((srvFlight.get(srvFlight.position() + 3) & 0xFF) << 8)
3138+
| (srvFlight.get(srvFlight.position() + 4) & 0xFF);
3139+
int firstRecordLen = 5 + firstRecPayload;
3140+
if (total < firstRecordLen) {
3141+
error("\t... failed");
3142+
fail("first TLS record exceeds server flight");
31333143
}
31343144

3135-
/* Feed the first half of the server flight to
3136-
* client.unwrap(). wolfSSL will consume these bytes through
3137-
* the I/O callback, exhaust the buffer, and return
3138-
* SSL_ERROR_WANT_READ. With the fix, BUFFER_UNDERFLOW must
3139-
* NOT be set because inRemaining > 0 (data was provided). */
3140-
int half = total / 2;
3141-
byte[] halfBytes = new byte[half];
3142-
srvFlight.get(halfBytes);
3143-
ByteBuffer firstHalf = ByteBuffer.wrap(halfBytes);
3145+
/* Feed exactly the first TLS record to client.unwrap().
3146+
* Peek confirms it is complete, DoHandshake() runs,
3147+
* wolfSSL consumes all bytes and returns WANT_READ. */
3148+
byte[] firstRecBytes = new byte[firstRecordLen];
3149+
srvFlight.get(firstRecBytes);
3150+
ByteBuffer firstRecord = ByteBuffer.wrap(firstRecBytes);
31443151

31453152
ByteBuffer cliAppBuf =
31463153
ByteBuffer.allocateDirect(appBufSize);
3147-
result = client.unwrap(firstHalf, cliAppBuf);
3154+
result = client.unwrap(firstRecord, cliAppBuf);
31483155

3149-
/* BUFFER_UNDERFLOW must not be returned when input was
3150-
* consumed - regression for inRemaining == 0 guard fix */
3151-
if (result.getStatus() ==
3152-
SSLEngineResult.Status.BUFFER_UNDERFLOW) {
3156+
/* wolfSSL processed first record but needs more data:
3157+
* status must be OK, not BUFFER_UNDERFLOW. */
3158+
if (result.getStatus() != SSLEngineResult.Status.OK) {
31533159
error("\t... failed");
3154-
fail("unwrap() with consumed handshake data must not " +
3155-
"return BUFFER_UNDERFLOW (regression: inRemaining" +
3156-
" == 0 guard), bytesConsumed=" +
3157-
result.bytesConsumed());
3160+
fail("expected Status.OK, got: " +
3161+
result.getStatus());
31583162
}
31593163

3160-
/* Input was non-empty so at least some bytes must have
3161-
* been consumed */
3162-
if (result.bytesConsumed() == 0) {
3164+
/* Handshake needs more data to continue. */
3165+
if (result.getHandshakeStatus() !=
3166+
SSLEngineResult.HandshakeStatus.NEED_UNWRAP) {
31633167
error("\t... failed");
3164-
fail("unwrap() consumed 0 bytes from a non-empty " +
3165-
"handshake buffer");
3168+
fail("expected NEED_UNWRAP, got: " +
3169+
result.getHandshakeStatus());
3170+
}
3171+
3172+
/* All bytes consumed via I/O callback. */
3173+
if (result.bytesConsumed() != firstRecordLen) {
3174+
error("\t... failed");
3175+
fail("expected " + firstRecordLen + " bytes " +
3176+
"consumed, got: " + result.bytesConsumed());
3177+
}
3178+
3179+
/* No application data produced during handshake. */
3180+
if (result.bytesProduced() != 0) {
3181+
error("\t... failed");
3182+
fail("expected 0 bytes produced, got: " +
3183+
result.bytesProduced());
3184+
}
3185+
3186+
/*
3187+
* The first unwrap set contPartialRecord=true because wolfSSL
3188+
* exhausted firstRecord and returned WANT_READ. On this call,
3189+
* peek is skipped and DoHandshake() receives raw continuation
3190+
* bytes. inRemaining > 0 must suppress BUFFER_UNDERFLOW. */
3191+
int contLen = Math.min(3, srvFlight.remaining());
3192+
if (contLen > 0) {
3193+
byte[] contBytes = new byte[contLen];
3194+
srvFlight.get(contBytes);
3195+
ByteBuffer contBuf = ByteBuffer.wrap(contBytes);
3196+
ByteBuffer cliAppBuf2 =
3197+
ByteBuffer.allocateDirect(appBufSize);
3198+
result = client.unwrap(contBuf, cliAppBuf2);
3199+
3200+
/* wolfSSL consumed continuation bytes, needs more:
3201+
* must be Status.OK, not BUFFER_UNDERFLOW. */
3202+
if (result.getStatus() !=
3203+
SSLEngineResult.Status.OK) {
3204+
error("\t... failed");
3205+
fail("expected Status.OK for continuation " +
3206+
"bytes, got: " + result.getStatus());
3207+
}
3208+
3209+
/* Handshake still needs more data. */
3210+
if (result.getHandshakeStatus() !=
3211+
SSLEngineResult.HandshakeStatus.NEED_UNWRAP) {
3212+
error("\t... failed");
3213+
fail("expected NEED_UNWRAP for continuation " +
3214+
"bytes, got: " +
3215+
result.getHandshakeStatus());
3216+
}
3217+
3218+
/* All continuation bytes consumed. */
3219+
if (result.bytesConsumed() != contLen) {
3220+
error("\t... failed");
3221+
fail("expected " + contLen + " continuation " +
3222+
"bytes consumed, got: " +
3223+
result.bytesConsumed());
3224+
}
3225+
3226+
/* No application data produced. */
3227+
if (result.bytesProduced() != 0) {
3228+
error("\t... failed");
3229+
fail("expected 0 bytes produced, got: " +
3230+
result.bytesProduced());
3231+
}
31663232
}
31673233

31683234
pass("\t... passed");

0 commit comments

Comments
 (0)