Skip to content

tls: refuse a compatibility CCS inside a fragmented handshake message - #8

Merged
atiernan merged 4 commits into
phase3/tls-handoverfrom
phase3/tls-ccs-fragments
Oct 27, 2026
Merged

atiernan merged 4 commits into
phase3/tls-handoverfrom
phase3/tls-ccs-fragments

Conversation

@atiernan

Copy link
Copy Markdown
Member

Fixes review finding 7 from #1. RFC 8446 §5.1 says handshake messages "MUST NOT be interleaved with other record types", but the connection dispatcher dropped a compatibility ChangeCipherSpec that arrived between two fragments of one handshake message. It now drops one only at a message boundary; inside a message it fails with unexpected_message.

This PR's base is phase3/tls-handover: the 19 unpushed commits from local phase3/tls plus the previous agent's uncommitted work, preserved as one WIP commit (0c3b7ef). See the TLS takeover plan, step 0.

Commits

  • 4c1c29f spec: compatibility_ccs_dropped / receive_compatibility_ccs (dispatcher_spec), ccs_record_ensures (dispatcher_contract), lemma_compatibility_ccs_not_dropped_mid_message, and mutation dispatcher-ccs-dropped-mid-message (expect: killed).
  • c7589a8 fix: exec.rs Frame::Ccs arm requires reassembler.at_message_boundary(). In the tests, the old test asserted the buggy drop, so it is replaced, and a new test covers the boundary case.
  • 23a5910 style: clears clippy/fmt failures that the WIP commit brought in (framing.rs unused argument → Ghost<bool>, ? in bootstrap.rs, checked get in tests/hello_bootstrap.rs).

Local results (per module, not a full verify)

  • connection::exec: 31 verified, 0 errors. connection::dispatcher_lemmas: 4 verified, 0 errors. connection::framing: 10 verified, 0 errors.
  • The mutation certificate was checked by hand: it verifies on the real spec and fails on the mutant. cargo xtask mutate has not been run.
  • cargo test -p clazel-tls passes. Strict clippy and cargo fmt --check are clean for clazel-tls.

Known failing (from the WIP base, not this PR)

  • hello::bootstrap does not verify, with or without this PR: assertion failures at about lines 395, 419 and 478, plus an rlimit in the function at about line 435. CI's clazel-tls crate job will fail on it.
  • Inconsistency to resolve: hello::bootstrap (spec line ~175, and tests/hello_bootstrap.rs) still drops a CCS between ServerHello fragments, citing RFC 8446 §5's "MUST simply drop it". That contradicts this fix. The two sections conflict for this case, so it needs one reading for the whole crate and a docs/ERRATA.md entry.

clazel-tls stays at tier 0. Full verification has not run yet.

🤖 Generated with Claude Code

atiernan and others added 3 commits October 26, 2026 15:01
RFC 8446 §5.1: handshake messages MUST NOT be interleaved with other
record types. Specify that a compatibility CCS is dropped only at a
handshake message boundary, state the record-level contract, and add a
certified mutation for dropping it mid-message.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ssage

RFC 8446 §5.1: drop the CCS only when the reassembler is at a message
boundary; otherwise fail with unexpected_message. The proof refines
receive_compatibility_ccs through ccs_record_ensures. The test that
asserted the old drop now expects the refusal, and a second test keeps
the boundary case dropped.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- framing: `is_empty_mode`'s mode argument is spec-only, so take it as
  `Ghost<bool>` (the pattern clazel-fetch uses) instead of an unused bool.
- bootstrap: use `?` for the ClientHello start result (clippy::question_mark).
- hello_bootstrap tests: checked `get` instead of slicing, and rustfmt.

hello::bootstrap's proof does not pass before or after this change
(assertion failures and an rlimit in its feed path); that is untouched here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@atiernan
atiernan marked this pull request as ready for review October 27, 2026 07:13
@atiernan
atiernan merged commit 96baecf into phase3/tls-handover Oct 27, 2026
26 of 27 checks passed
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