Skip to content

fix(tls13): Reject oversized Finished messages via exact length check - #6040

Open
alexw91 wants to merge 1 commit into
aws:mainfrom
alexw91:tls13-int-truncation
Open

fix(tls13): Reject oversized Finished messages via exact length check#6040
alexw91 wants to merge 1 commit into
aws:mainfrom
alexw91:tls13-int-truncation

Conversation

@alexw91

@alexw91 alexw91 commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Goal

Reject TLS 1.3 Finished messages whose length does not exactly match the negotiated HMAC output size.

Why

s2n_stuffer_data_available returns uint32_t but the result was stored in a uint8_t. A Finished message with hash_size + 256 trailing bytes wraps back to hash_size, bypassing length validation. This silently corrupts the handshake transcript hash and breaks session resumption state.

How

  • Change uint8_t length to uint32_t length in both s2n_tls13_client_finished_recv and s2n_tls13_server_finished_recv.
  • Move s2n_tls13_connection_keys initialization before the length check so keys.size is available.
  • Replace S2N_ERROR_IF(length == 0, ...) with POSIX_ENSURE_EQ(length, keys.size), an exact match per RFC 8446 §4.4.4.

Callouts

The existing "+1 byte" test already passed before this fix because 33 != 32 without truncation. The new test targets the specific wrap-around at +256 bytes that the uint8_t allowed through.

Testing

New unit test.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

s2n_stuffer_data_available returns uint32_t but the result was stored
in a uint8_t, silently truncating values above 255. A Finished message
with hash_size + 256 trailing bytes wraps back to hash_size, bypassing
the length validation and corrupting the handshake transcript hash.

Move s2n_tls13_connection_keys initialization before the length check
and replace the permissive "length != 0" guard with an exact equality
check against keys.size (the expected HMAC output length per RFC 8446
§4.4.4). Apply the same fix to both client and server finished_recv.

Add a regression test that writes hash_size + 256 bytes into the
handshake stuffer and asserts the receive function rejects it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant