REALITY.5b: byte-matching ServerHello emission + server key schedule (4588+X25519, round-trip proven)#85
Closed
vxfemboy wants to merge 7 commits into
Closed
Conversation
…server key schedule (4588+X25519)
…ate + X25519, 4588/29)
…ver key schedule (round-trip proven)
…p-4588 server KEX)
…onflated sourcing (5b review)
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.
REALITY.5b — byte-matching ServerHello emission + server key schedule
Stacked on #83 (REALITY.5a). Base is
feat/reality-5a-dest-flight-capture; review the 5b delta here, merge after #83. PR 2 of 4 for REALITY.5 (#76).The server-side counterpart to REALITY.2's client. Given the
desttemplate captured in 5a, the relay emits a byte-matching ServerHello — structurally identical todest's (cipher, ordered extensions incl. GREASE, chosen group) but keyed on the relay's own ephemeral, so the relay holds the session keys. A passive DPI byte-matches the cleartext ServerHello;dest's realkey_share/randomare per-connection random too, so substituting the relay's own values is indistinguishable.What's here
yip-utls::server::server_key_share— the relay's server-side KEX.Decapsulate) + X25519 DH;server_key_share = ct(1088) ‖ x25519_pub(32),shared = mlkem_ss ‖ x25519_ss— the same combiner order the client uses.Err(UnsupportedGroup)(5d degrades to splice-only; P256/P384 + HelloRetryRequest deferred to REALITY: P256/P384 server-side KEX + HelloRetryRequest support (evaluate whether it's worth it) #84).yip-utls::server::emit_server_hello— rebuilds the ServerHello verbatim from the capturedServerHelloShape, substituting only a fresh 32-byte random, the client'slegacy_session_idecho, and thekey_shareext body (the relay's own). Derives handshake keys over transcript = ClientHello ‖ ServerHello via REALITY.2'sderive_handshake_keys(reused unchanged).yip-rendezvous::reality—ClientHelloInfo.key_share_mlkem_ekextracted from the group-4588 key_share entry (mlkem_ek(1184) ‖ x25519(32)), fail-closed on a hostile/malformed ClientHello. This is what 5d feeds toemit_server_hello.Correctness gate: the round-trip
The proof is a genuine round-trip (not a tautology): a test client — REALITY.2's own
parse_server_hello+ the client KEX (decapsulate/DH, separate RNGs) +derive_handshake_keys— parses the relay's emitted ServerHello and derives the byte-identicalHandshakeKeys, for both 4588 and X25519. If the combiner order or X25519 direction were wrong, no keys would match. Plus a byte-match test asserting only random/session_id/key_share differ from the template (GREASE and extension order preserved).Scope / non-goals
tls_frontwiring (5d) here — additive, server-side only.5d hand-off notes
…‖ x25519(32)tail), not the standalone0x001dentry. Safe within 5b because yip's own client reuses one ephemeral across both shares; 5d must either thread the 4588-tail x25519 through or assert that invariant. Fails closed (dead session), no security downgrade, if ever violated.server_key_share'srngdrives ML-KEM encapsulation + the X25519 ephemeral; 5d must wire an OS-CSPRNG-backedRandomSource.Tests
server_key_shareshapes/secret-lengths for 4588 + 29; unsupported group + missing ek →Err.emit_server_helloround-trips (4588 + 29) with identical keys; byte-match except substituted fields; u24 body / u16 ext length guards.parse_client_helloextracts the 1184-byte mlkem_ek; wrong-length 4588 entry →None; distinct x25519 in the two entries proveskey_share_x25519stays sourced from0x001d.Final whole-branch review (opus): READY TO MERGE — KEX verified end-to-end, every network-reachable path fail-closed, ServerHello byte-fidelity preserved,
forbid-unsafe/ noas/ no bare#[allow].