Skip to content

Commit dd461be

Browse files
committed
add unit test for consuming buffer underflow
1 parent dc58c0e commit dd461be

1 file changed

Lines changed: 122 additions & 0 deletions

File tree

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

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2926,6 +2926,128 @@ public void testBufferUnderflowPartialRecord()
29262926
pass("\t... passed");
29272927
}
29282928

2929+
@Test
2930+
public void testHandshakeUnwrapConsumedNotBufferUnderflow()
2931+
throws NoSuchProviderException, NoSuchAlgorithmException,
2932+
KeyManagementException, KeyStoreException,
2933+
CertificateException, IOException,
2934+
UnrecoverableKeyException {
2935+
2936+
System.out.print("\tTest unwrap consumed != BUFFER_UNDERFLOW");
2937+
2938+
if (!enabledProtocols.contains("TLSv1.3")) {
2939+
System.out.println("\t... skipped");
2940+
return;
2941+
}
2942+
2943+
SSLContext ctx13 = tf.createSSLContext("TLSv1.3", engineProvider);
2944+
SSLEngine server = ctx13.createSSLEngine();
2945+
SSLEngine client = ctx13.createSSLEngine("localhost", 11111);
2946+
2947+
server.setUseClientMode(false);
2948+
server.setNeedClientAuth(false);
2949+
client.setUseClientMode(true);
2950+
2951+
server.beginHandshake();
2952+
client.beginHandshake();
2953+
2954+
int packetBufSize = client.getSession().getPacketBufferSize();
2955+
int appBufSize = client.getSession().getApplicationBufferSize();
2956+
2957+
/* Wrap ClientHello */
2958+
ByteBuffer cliToSrv =
2959+
ByteBuffer.allocateDirect(packetBufSize);
2960+
ByteBuffer emptyApp = ByteBuffer.allocate(0);
2961+
SSLEngineResult result = client.wrap(emptyApp, cliToSrv);
2962+
if (result.getStatus() != SSLEngineResult.Status.OK) {
2963+
error("\t... failed");
2964+
fail("client wrap (ClientHello) failed: " +
2965+
result.getStatus());
2966+
}
2967+
cliToSrv.flip();
2968+
2969+
/* Server unwraps ClientHello */
2970+
ByteBuffer srvAppBuf =
2971+
ByteBuffer.allocateDirect(appBufSize);
2972+
result = server.unwrap(cliToSrv, srvAppBuf);
2973+
if (result.getStatus() != SSLEngineResult.Status.OK) {
2974+
error("\t... failed");
2975+
fail("server unwrap (ClientHello) failed: " +
2976+
result.getStatus());
2977+
}
2978+
2979+
/* Collect entire TLS 1.3 server first flight (ServerHello,
2980+
* optional Change Cipher Spec, encrypted flight). */
2981+
if (server.getHandshakeStatus() !=
2982+
HandshakeStatus.NEED_WRAP) {
2983+
error("\t... failed");
2984+
fail("expected server NEED_WRAP after ClientHello, " +
2985+
"got: " + server.getHandshakeStatus());
2986+
}
2987+
2988+
ByteBuffer srvFlight =
2989+
ByteBuffer.allocateDirect(packetBufSize * 4);
2990+
HandshakeStatus hs = server.getHandshakeStatus();
2991+
while (hs == HandshakeStatus.NEED_WRAP) {
2992+
ByteBuffer srvNet =
2993+
ByteBuffer.allocateDirect(packetBufSize);
2994+
result = server.wrap(emptyApp, srvNet);
2995+
if (result.getStatus() != SSLEngineResult.Status.OK) {
2996+
error("\t... failed");
2997+
fail("server wrap failed: " + result.getStatus());
2998+
}
2999+
srvNet.flip();
3000+
if (srvNet.remaining() > srvFlight.remaining()) {
3001+
error("\t... failed");
3002+
fail("server flight exceeded srvFlight capacity");
3003+
}
3004+
srvFlight.put(srvNet);
3005+
hs = server.getHandshakeStatus();
3006+
}
3007+
srvFlight.flip();
3008+
3009+
int total = srvFlight.remaining();
3010+
if (total < 2) {
3011+
error("\t... failed");
3012+
fail("server flight too small to split: " + total);
3013+
}
3014+
3015+
/* Feed the first half of the server flight to
3016+
* client.unwrap(). wolfSSL will consume these bytes through
3017+
* the I/O callback, exhaust the buffer, and return
3018+
* SSL_ERROR_WANT_READ. With the fix, BUFFER_UNDERFLOW must
3019+
* NOT be set because inRemaining > 0 (data was provided). */
3020+
int half = total / 2;
3021+
byte[] halfBytes = new byte[half];
3022+
srvFlight.get(halfBytes);
3023+
ByteBuffer firstHalf = ByteBuffer.wrap(halfBytes);
3024+
3025+
ByteBuffer cliAppBuf =
3026+
ByteBuffer.allocateDirect(appBufSize);
3027+
result = client.unwrap(firstHalf, cliAppBuf);
3028+
3029+
/* BUFFER_UNDERFLOW must not be returned when input was
3030+
* consumed - regression for inRemaining == 0 guard fix */
3031+
if (result.getStatus() ==
3032+
SSLEngineResult.Status.BUFFER_UNDERFLOW) {
3033+
error("\t... failed");
3034+
fail("unwrap() with consumed handshake data must not " +
3035+
"return BUFFER_UNDERFLOW (regression: inRemaining" +
3036+
" == 0 guard), bytesConsumed=" +
3037+
result.bytesConsumed());
3038+
}
3039+
3040+
/* Input was non-empty so at least some bytes must have
3041+
* been consumed */
3042+
if (result.bytesConsumed() == 0) {
3043+
error("\t... failed");
3044+
fail("unwrap() consumed 0 bytes from a non-empty " +
3045+
"handshake buffer");
3046+
}
3047+
3048+
pass("\t... passed");
3049+
}
3050+
29293051
@Test
29303052
public void testBufferOverflowSmallOutput()
29313053
throws NoSuchProviderException, NoSuchAlgorithmException,

0 commit comments

Comments
 (0)