Implement and harden DTLS 1.2 Connection ID (RFC 9146)#104
Draft
jaredwolff wants to merge 1 commit intoalgesten:mainfrom
Draft
Implement and harden DTLS 1.2 Connection ID (RFC 9146)#104jaredwolff wants to merge 1 commit intoalgesten:mainfrom
jaredwolff wants to merge 1 commit intoalgesten:mainfrom
Conversation
Contributor
Author
Diff against
|
| Area | Code | Comments | Blank | Total+ | Net |
|---|---|---|---|---|---|
src/ |
1,399 | 1,021 | 148 | 2,568 | +2,419 |
tests/ |
2,234 | 485 | 440 | 3,159 | +3,059 |
README.md |
— | — | — | 21 | +21 |
| Total | 3,633 | 1,506 | 588 | 5,748 | +5,499 |
- Tests-to-code ratio: 1.60 : 1 (by code lines)
- Comment share of non-blank src additions: 42% — RFC rationale, not noise
Files touched (top by modification weight)
| File | +Lines | -Lines |
|---|---|---|
src/dtls12/incoming.rs |
898 | 30 |
src/dtls12/engine.rs |
365 | 37 |
src/config.rs |
253 | 3 |
src/dtls12/message/client_hello.rs |
185 | 5 |
src/crypto/dtls_aead.rs |
153 | 6 |
src/dtls12/server.rs |
131 | 6 |
src/dtls12/client.rs |
105 | 3 |
src/dtls13/client.rs |
90 | 10 |
src/dtls12/message/server_hello.rs |
73 | 4 |
src/lib.rs |
70 | 0 |
src/error.rs |
51 | 0 |
src/dtls12/message/extensions/connection_id.rs |
97 | 0 (new file) |
tests/dtls12/cid.rs |
2,404 | 0 (new file) |
4ed8cfb to
326e4b1
Compare
Adds DTLS 1.2 Connection ID (RFC 9146) with record-layer hardening and adjacent DTLS 1.3 (RFC 9147) / RFC 5246 / RFC 8446 extension-handling gaps closed. Record-layer hardening (RFC 9146 / RFC 6347 §4.1.2): - Wire CID constant-time compared and threaded into AAD (not the cached copy); wire version bytes likewise threaded through the AAD. - Malformed record boundaries, too-short AEAD records, and the 2^14 inner-plaintext ceiling all silent-drop per §4.1.2.7, symmetric with the send-side guard. - Epoch-0 `tls12_cid` rejected at DTLSRecord::parse; legacy-framed epoch-1 records rejected when inbound CID is expected. - Pre-CCS CID records cleartext-filtered against the negotiated inbound CID before entering queue_rx, closing a spray DoS vector. - Replay window updates only after AEAD success AND CID inner-type unwrap succeeds — peer-bug inner types no longer consume sequence slots. CID state model: - Single private `CidState` enum replaces separate `our_cid`/`peer_cid` fields so valid combinations are unrepresentable outside the module. - Per-direction activation: outbound armed at negotiation, inbound flipped live only after the peer's ChangeCipherSpec. Extension parser and HVR cookie: - Duplicate extensions (supported and unknown) rejected fail-closed via a 64-codepoint tracker with `try_push(...).map_err(...)?`, including a defense-in-depth ExtensionVec dedup pass. - HVR cookie HMAC binds the raw offered-CID extension bytes with a 0x00/0x01 marker, catching CH1/CH2 CID swap attempts. - Stateful `offered_cid` flag on dtls13::Client replaces the earlier config-based proxy so the direct `Dtls::new_13` path still rejects unsolicited `0x0036` echoes per RFC 8446 §4.2. Outbound sizing and lifetimes: - Shared `Engine::outbound_record_overhead` keeps create_handshake fragmentation in sync with CID + AEAD overhead. - New errors: `Error::Oversized`, `Error::MtuTooSmall`, `Error::SequenceNumberExhausted`; 2^14 plaintext ceiling enforced both sides; 48-bit sequence wrap surfaced distinctly from payload size failures. Auto-mode: - Hybrid ClientHello now emits `connection_id(0x0036)` when configured, so CH1/CH2 carry identical CID bytes and the stateless cookie binds once. - DTLS 1.3 client silent-accepts a server echo only when its own ClientHello on the wire solicited `0x0036`. - DTLS 1.3 server and client explicitly log-ignore `0x0036` per RFC. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
326e4b1 to
006873e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds DTLS 1.2 Connection ID (RFC 9146) with record-layer hardening and adjacent DTLS 1.3 (RFC 9147) / RFC 5246 / RFC 8446 extension-handling gaps closed.
Record-layer hardening (RFC 9146 / RFC 6347 §4.1.2):
tls12_cidrejected at DTLSRecord::parse; legacy-framed epoch-1 records rejected when inbound CID is expected.CID state model:
CidStateenum replaces separateour_cid/peer_cidfields so valid combinations are unrepresentable outside the module.Extension parser and HVR cookie:
try_push(...).map_err(...)?, including a defense-in-depth ExtensionVec dedup pass.offered_cidflag on dtls13::Client replaces the earlier config-based proxy so the directDtls::new_13path still rejects unsolicited0x0036echoes per RFC 8446 §4.2.Outbound sizing and lifetimes:
Engine::outbound_record_overheadkeeps create_handshake fragmentation in sync with CID + AEAD overhead.Error::Oversized,Error::MtuTooSmall,Error::SequenceNumberExhausted; 2^14 plaintext ceiling enforced both sides; 48-bit sequence wrap surfaced distinctly from payload size failures.Auto-mode:
connection_id(0x0036)when configured, so CH1/CH2 carry identical CID bytes and the stateless cookie binds once.0x0036.0x0036per RFC.