@@ -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 ("\t Test unwrap consumed != BUFFER_UNDERFLOW " );
3056+ System .out .print ("\t Test 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