Skip to content

Prevent TLS 1.2 Handshake Messages from Entering TLS 1.3 Post-Handshake Path #5624

@kaukabrizvi

Description

@kaukabrizvi

Problem:

In #5614, incorrect handshake-completion detection (see related issue #5625) in the Rust harness caused a TLS 1.2 handshake to exit early, leaving the server’s final TLS 1.2 Finished message unread. When application data was then received, s2n-tls misclassified the remaining TLS 1.2 handshake bytes as a TLS 1.3 post-handshake message and entered the post-handshake receive path (s2n_post_handshake_recv()), resulting in S2N_ERR_BAD_MESSAGE.

TLS 1.2 has no post-handshake messages.
s2n-tls should never route TLS 1.2 handshake fragments through TLS 1.3 post-handshake logic. If the application attempts to send/receive application data before handshake messages are fully consumed, s2n-tls should return a clearer and more appropriate error (e.g., “unexpected application data before handshake completion”).

This issue exists independently of the Rust harness bug; the routing logic should defensively prevent TLS 1.2 from ever entering the TLS 1.3 post-handshake path.

Need By Date:

N/A

Solution:

Update s2n_post_handshake_recv() to ensure we are negotiating TLS 1.3 before performing any post-handshake message processing. We already perform this protocol-version check on the send path:

if (conn->actual_protocol_version < S2N_TLS13) {

If a send record arrives with record_type = TLS_HANDSHAKE while negotiating TLS 1.2, and the handshake is not yet complete, s2n-tls should:

  • Return an error indicating that application data was received before the handshake was finished.

Architectural Notes

  • Which versions of TLS will this impact?
  • TLS 1.2 (fixes incorrect routing).

Requirements / Acceptance Criteria:

A complete solution should:

  • Ensure the post-handshake receive path executes only when negotiating TLS 1.3.
  • Prevent TLS 1.2 handshake fragments from being routed through TLS 1.3 post-handshake logic.
  • Return a clear and correct error when application data is processed before all handshake messages are consumed.
  • Preserve correct behavior for legitimate TLS 1.3 post-handshake messages (KeyUpdate, NewSessionTicket).
  • Include tests covering TLS 1.2 handshake with leftover bytes + attempted application data
  • RFC links: N/A
  • Related Issues: Link any relevant issues
  • Will the Usage Guide or other documentation need to be updated? N/A
  • Testing: Add a unit test that sends application data before handshake completion and verify the correct error is returned.
    • Will this change trigger SAW changes? None expected.
    • Should this change be fuzz tested? N/A

Out of scope:

Is there anything the solution will intentionally NOT address?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions