Skip to content

Supposed middlebox-compat client build still sends an empty legacy_session_id #11012

Description

@LiD0209

Supposed middlebox-compat client build still sends an empty legacy_session_id

Problem Description

The cmake-mingw-examples-psk-mbox client artifact still emits a TLS 1.3 ClientHello whose legacy_session_id length is 0. If this artifact is meant to implement RFC 8446 compatibility mode, that wire behavior is inconsistent with the RFC requirement to send a non-empty 32-byte value for a non-resumption client.

Standard Requirement

In compatibility mode (see Appendix D.4),
this field MUST be non-empty, so a client not offering a
pre-TLS 1.3 session MUST generate a new 32-byte value.

Interpretation:

If a client build is operating in TLS 1.3 compatibility mode, its initial ClientHello must not carry a zero-length legacy_session_id.

Relevant Source Code

The concrete serialization logic lives in
src/tls13.c.

src/tls13.c:4544-4580

static void GetTls13SessionId(WOLFSSL* ssl, byte* output, word32* idx)
{
    if (ssl->session->sessionIDSz > 0) {
        /* Session resumption for old versions of protocol. */
        ...
    }
    else {
    #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT
        if (ssl->options.tls13MiddleBoxCompat) {
            if (output != NULL)
                output[*idx] = ID_LEN;
            (*idx)++;
            if (output != NULL)
                XMEMCPY(output + *idx, ssl->arrays->clientRandom, ID_LEN);
            *idx += ID_LEN;
        }
        else
    #endif
        {
            /* TLS v1.3 does not use session id - 0 length. */
            if (output != NULL)
                output[*idx] = 0;
            (*idx)++;
        }
    }
}

This path is the direct decision point for whether the ClientHello carries a 32-byte legacy_session_id or a zero-length one.

Runtime Evidence

Capture 1: produced mbox example client

  • Target: client.exe
  • Command: client.exe -h 127.0.0.1 -p 12345 -v 4 -d
  • Harness: local TCP listener that accepted one connection and recorded the first TLS record from the client.

Observed result:

  • Captured bytes: 513
  • legacy_session_id length byte at ClientHello offset 43: 0
  • First bytes:
16 03 03 01 fc 01 00 01 f8 03 03 6b c8 4b 19 f7 6c e4 c8 90 e8 b4 b9 55
a3 37 d4 ed 0f 14 c2 d0 54 d1 aa 2d 4c 23 f6 26 7a 8f 9a 00 00 36 ...

The byte after the 32-byte ClientHello random is 00, so the emitted legacy_session_id vector is empty.

Capture 2: minimal library-linked probe

Observed result:

initial_middlebox=0
initial_dtls=0
initial_session_id_sz=0
connect_ret=-1
connect_err=2
post_middlebox=0
captured_sends=1
captured_len=1426
captured_sid_len=0

This independent probe reproduces the same observable behavior: the produced client-side library emits an empty legacy_session_id.

Inconsistency Reason

The purported middlebox-compatible client artifact does not place a 32-byte legacy_session_id on the wire. Its first ClientHello uses a zero-length vector instead.

Decision Reason

This is a concrete wire-level divergence in the produced mbox artifact. The artifact that is supposed to represent compatibility-mode behavior still sends an empty legacy_session_id.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions