@@ -2845,6 +2845,86 @@ static int Tls13PTARecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
28452845}
28462846#endif
28472847
2848+ /* Test that when a TLS 1.3 client sends a ClientHello with an empty
2849+ * legacy_session_id (indicating no middlebox compatibility), the server
2850+ * should NOT send a ChangeCipherSpec message. Per RFC 8446 Appendix D.4,
2851+ * the server only sends CCS if the client's ClientHello contains a
2852+ * non-empty session_id.
2853+ *
2854+ * This test reproduces the bug reported in GitHub issue #9156 where
2855+ * wolfSSL server always sends CCS when compiled with
2856+ * WOLFSSL_TLS13_MIDDLEBOX_COMPAT, regardless of the client's session_id.
2857+ */
2858+ int test_tls13_middlebox_compat_empty_session_id (void )
2859+ {
2860+ EXPECT_DECLS ;
2861+ #if defined(WOLFSSL_TLS13 ) && defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT ) && \
2862+ defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES ) && \
2863+ !defined(NO_WOLFSSL_CLIENT ) && !defined(NO_WOLFSSL_SERVER )
2864+ WOLFSSL_CTX * ctx_c = NULL ;
2865+ WOLFSSL_CTX * ctx_s = NULL ;
2866+ WOLFSSL * ssl_c = NULL ;
2867+ WOLFSSL * ssl_s = NULL ;
2868+ struct test_memio_ctx test_ctx ;
2869+ int i ;
2870+ int found_ccs = 0 ;
2871+
2872+ XMEMSET (& test_ctx , 0 , sizeof (test_ctx ));
2873+ ExpectIntEQ (test_memio_setup (& test_ctx , & ctx_c , & ctx_s , & ssl_c , & ssl_s ,
2874+ wolfTLSv1_3_client_method , wolfTLSv1_3_server_method ), 0 );
2875+
2876+ /* Disable middlebox compatibility on the client so it sends an empty
2877+ * legacy_session_id in ClientHello. The server should respect this and
2878+ * NOT send a ChangeCipherSpec. */
2879+ if (EXPECT_SUCCESS ()) {
2880+ ssl_c -> options .tls13MiddleBoxCompat = 0 ;
2881+ }
2882+
2883+ /* Client sends ClientHello with empty session ID */
2884+ ExpectIntNE (wolfSSL_connect (ssl_c ), WOLFSSL_SUCCESS );
2885+ ExpectIntEQ (wolfSSL_get_error (ssl_c ,
2886+ WC_NO_ERR_TRACE (WOLFSSL_FATAL_ERROR )), WOLFSSL_ERROR_WANT_READ );
2887+
2888+ /* Server processes ClientHello and sends its flight:
2889+ * ServerHello, EncryptedExtensions, Certificate, CertVerify, Finished
2890+ * (and potentially an unwanted CCS) */
2891+ ExpectIntNE (wolfSSL_accept (ssl_s ), WOLFSSL_SUCCESS );
2892+ ExpectIntEQ (wolfSSL_get_error (ssl_s ,
2893+ WC_NO_ERR_TRACE (WOLFSSL_FATAL_ERROR )), WOLFSSL_ERROR_WANT_READ );
2894+
2895+ /* Now examine the server's output (stored in c_buff, since the server
2896+ * writes to the client's read buffer). Scan through TLS records looking
2897+ * for a ChangeCipherSpec record (content type 0x14 = 20). */
2898+ if (EXPECT_SUCCESS ()) {
2899+ i = 0 ;
2900+ while (i + 5 <= test_ctx .c_len ) {
2901+ byte content_type = test_ctx .c_buff [i ];
2902+ int record_len = (test_ctx .c_buff [i + 3 ] << 8 ) |
2903+ test_ctx .c_buff [i + 4 ];
2904+
2905+ if (content_type == 20 ) { /* change_cipher_spec */
2906+ found_ccs = 1 ;
2907+ break ;
2908+ }
2909+
2910+ /* Move to next TLS record: 5 byte header + payload */
2911+ i += 5 + record_len ;
2912+ }
2913+ }
2914+
2915+ /* The server should NOT have sent CCS since the client's ClientHello
2916+ * had an empty legacy_session_id. If found_ccs is 1, this demonstrates
2917+ * the bug from issue #9156. */
2918+ ExpectIntEQ (found_ccs , 0 );
2919+
2920+ wolfSSL_free (ssl_c );
2921+ wolfSSL_free (ssl_s );
2922+ wolfSSL_CTX_free (ctx_c );
2923+ wolfSSL_CTX_free (ctx_s );
2924+ #endif
2925+ return EXPECT_RESULT ();
2926+ }
2927+
28482928int test_tls13_plaintext_alert (void )
28492929{
28502930 EXPECT_DECLS ;
0 commit comments