Skip to content

Commit 10ca06c

Browse files
authored
Merge pull request #9769 from anhu/midbox
Middle box compatibility compliance.
2 parents 1b05b26 + c3c9acc commit 10ca06c

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed

src/tls13.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6859,6 +6859,14 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
68596859
XMEMCPY(ssl->session->sessionID, input + args->idx, sessIdSz);
68606860
args->idx += sessIdSz;
68616861

6862+
#ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT
6863+
/* RFC 8446 Appendix D.4: server MUST only send CCS if the client's
6864+
* ClientHello contains a non-empty legacy_session_id. */
6865+
if (sessIdSz == 0) {
6866+
ssl->options.tls13MiddleBoxCompat = 0;
6867+
}
6868+
#endif
6869+
68626870
#ifdef WOLFSSL_DTLS13
68636871
/* legacy_cookie */
68646872
if (ssl->options.dtls) {

tests/api/test_tls13.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
28482928
int test_tls13_plaintext_alert(void)
28492929
{
28502930
EXPECT_DECLS;

tests/api/test_tls13.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ int test_tls13_sg_missing(void);
3636
int test_tls13_ks_missing(void);
3737
int test_tls13_duplicate_extension(void);
3838
int test_key_share_mismatch(void);
39+
int test_tls13_middlebox_compat_empty_session_id(void);
3940
int test_tls13_plaintext_alert(void);
4041

4142
#define TEST_TLS13_DECLS \
@@ -51,6 +52,7 @@ int test_tls13_plaintext_alert(void);
5152
TEST_DECL_GROUP("tls13", test_tls13_ks_missing), \
5253
TEST_DECL_GROUP("tls13", test_tls13_duplicate_extension), \
5354
TEST_DECL_GROUP("tls13", test_key_share_mismatch), \
55+
TEST_DECL_GROUP("tls13", test_tls13_middlebox_compat_empty_session_id), \
5456
TEST_DECL_GROUP("tls13", test_tls13_plaintext_alert)
5557

5658
#endif /* WOLFCRYPT_TEST_TLS13_H */

0 commit comments

Comments
 (0)