Skip to content

REALITY.5 follow-up cleanups (MessageTooLarge/u24_len, pre-write signing-key, partial-record splice, group-29 test)#88

Merged
vxfemboy merged 27 commits into
mainfrom
feat/reality-5-followup-cleanups
Jul 19, 2026
Merged

REALITY.5 follow-up cleanups (MessageTooLarge/u24_len, pre-write signing-key, partial-record splice, group-29 test)#88
vxfemboy merged 27 commits into
mainfrom
feat/reality-5-followup-cleanups

Conversation

@vxfemboy

Copy link
Copy Markdown
Member

REALITY.5 follow-up cleanups

Stacked on #87 (REALITY.5d). Base is feat/reality-5d-wire-server-flight; merge after #87. Clears the non-blocking follow-ups accumulated across the REALITY.5 stack (the ones you asked to fix — this deliberately leaves exact-leaf-length padding out, keeping the natural-leaf decision, and leaves P256/P384 + HelloRetryRequest as its own milestone #84).

yip-utls

  • Error::MessageTooLargeemit_server_flight's handshake-message u24 length guards were reusing the record-layer handshake::Error::RecordTooLarge; a dedicated message-framing variant reads clearer.
  • u24_len(usize) -> Result<[u8;3], Error> — extracts the u32::try_from + > 0xFF_FFFF ceiling check that was duplicated across the handshake-message / CertificateEntry / certificate_list length prefixes, guarding the real u24 ceiling (not just u32::MAX). Unit-tested at the boundaries (0, 1, mid, exactly 0xFF_FFFF, one over).

yip-rendezvous — fail-safe + camouflage

  • Hoist the CertVerify signing-key load pre-write (tls_front.rs) — SigningKey::from_pkcs8_der now runs above the ServerHello write, so its (unreachable — the same PKCS#8 already parsed as an rcgen KeyPair) failure splices rather than drops, keeping every fallible step on the pre-write side of the fail-safe boundary.
  • Splice partial-record stalls (reality_io.rs) — read_first_tls_record now enforces the HANDSHAKE_TIMEOUT deadline itself (per read via timeout_at, an absolute deadline — slowloris-safe) instead of the caller wrapping it in a cancelling timeout(). A client that stalls after sending a partial record now yields the consumed bytes as Passthrough → spliced to dest (a real upstream holds a half-sent record and answers), rather than being dropped (a mild timing distinguisher). A zero-byte connection still drops (Empty). New test: partial-then-stall over a real socket, writer held open, asserts the exact consumed prefix is replayed.

Tests

  • Group-29 dest end-to-end test — an X25519-only cert source (set_curves_list("X25519")) forces the captured template to key_share_group == 29, so the authed path feeds the standalone 0x001d share (not the 4588 tail) into emit_server_hello; a real verify=on client must still complete the hand-rolled handshake and verify the 4b binding. Deterministic, independent of which hybrid groups the BoringSSL version supports (the 4588 path is covered by the netns money test). start_reality_front_with gains a cert_src parameter (both existing callers updated).
  • netns nit — dropped a redundant dump_logs on the wrong-pbk FAIL branch of run-netns-reality-5d.sh (it cat'd the stale good-run log, not the wrong-pbk run's).

Deferred (intentionally not here)

Review (sonnet): Approved — all six match intent; the security-sensitive read-timeout change is slowloris-safe (absolute deadline) with a genuine test; no unsafe/as/bare-#[allow]. 70 yip-utls + 86 yip-rendezvous tests green, clippy clean.

vxfemboy added 26 commits July 17, 2026 17:57
…rver-side stream

Record-framing fidelity (match record_lengths exactly + leaf sized to dest by
5d; EE/CertVerify/Finished natural size absorbed into TLS record padding).
Role-agnostic RealityStream (egress/ingress). sign_certificate_verify mirrors
4b's verifier; emit_server_flight seals EE/Cert/CertVerify/Finished under 5b
handshake keys; record_seal_padded new primitive. Fail-safe to splice on
over-capacity/malformed template. yip-utls only; 5d wires + forges leaf.
Reviewer: p256 SigningKey signs with SHA-256 internally + 4b hard-pins the
scheme, so the signer needs no suite (caller uses it only for the transcript
hash). Cleaner helper API.
server_hs_traffic / record_seal_padded / sign_certificate_verify /
emit_server_flight (greedy record-framing to record_lengths, fail-safe
FlightTooLarge) / role-agnostic RealityStream (egress/ingress) / serve +
drive the connect_verify_* round-trip suite through 5c as the gate.
…he relay

Replace BoringSSL SslAcceptor on the authed REALITY path with 5b emit_server_hello
+ 5c serve. Natural forged leaf (no exact leaf_der_len padding, user decision);
parse+thread the 4588-tail x25519; genericize handle_connection over the stream;
splice pre-write / drop post-write fail-safe boundary; OS-CSPRNG rng; serve bounded
by HANDSHAKE_TIMEOUT. netns money test = real verify=on client through 5d relay.
Last PR of REALITY.5. yip-rendezvous.
Parser 4588-x25519-tail / genericize handle_connection chain / authed-path
rewrite (splice pre-write, drop post-write) + reality_cert cleanup / netns
money test. Threads info through the decision tuple; r.certs/r.dest; deps
(p256/getrandom/rcgen) already present.
… the hand-rolled relay

Forks run-netns-reality-relay.sh into a focused run-netns-reality-5d.sh
proving the REALITY.5d wiring end-to-end: a real yipd client dialing
reality://...&verify=on completes the relay's hand-rolled server flight
(tls_front::run_reality_conn's Decision::Accept branch — 5b emit_server_hello
+ 5c emit_server_flight/serve, replacing the old BoringSSL SslAcceptor),
verifies the REALITY.4b binding against the forged leaf, and tunnels to a
peer THROUGH the relay (relay-forwarded>0). A wrong-pbk client gets no
tunnel: the relay's seal-open fails so it splices to --reality-dest
pre-ServerHello-write, never entering the hand-rolled emit path.

Ran under sudo twice, exit 0 both times: verify=on ping succeeded
(relay-forwarded=2106), wrong-pbk ping failed with no retry-storm (1
verification attempt in ~16s).

Wired into .github/workflows/integration.yml alongside the sibling
run-netns-reality-relay.sh step, same job/binaries.
…w-up)

emit_server_flight's handshake-message/CertificateEntry/certificate_list u24
length guards reused handshake::Error::RecordTooLarge (a record-layer variant)
and duplicated the u32::try_from + >0xFF_FFFF ceiling check 3x. Extract
u24_len(usize)->Result<[u8;3],Error> guarding the real u24 ceiling, returning
the message-framing-layer Error::MessageTooLarge. Unit-tested.
…ice partial-record stalls (5d follow-ups)

- Move p256 SigningKey::from_pkcs8_der above the ServerHello write so its
  (unreachable) failure splices, keeping every fallible step on the pre-write
  side of the fail-safe boundary.
- read_first_tls_record now enforces the HANDSHAKE_TIMEOUT deadline itself
  (per read via timeout_at) instead of the caller wrapping it in a cancelling
  timeout(). A client that stalls AFTER a partial record now yields the
  consumed bytes as Passthrough → spliced to dest (a real upstream holds a
  half-sent record), not dropped. Only a zero-byte connection drops (Empty).
…in netns wrong-pbk branch (follow-ups)

- reality_authed_group29_dest_client_verify_succeeds: an X25519-only cert
  source forces the captured template to key_share_group=29, so the authed
  path feeds the standalone 0x001d share (not the 4588 tail) into
  emit_server_hello; a verify=on client must still complete + verify the 4b
  binding. Deterministic, independent of BoringSSL's hybrid-group support.
- start_reality_front_with takes the cert_src addr (2 callers updated).
- netns wrong-pbk FAIL branch: drop the redundant dump_logs (it cats the
  stale good-run LOG_A, not LOG_A_WRONG).
@vxfemboy
vxfemboy changed the base branch from feat/reality-5d-wire-server-flight to main July 19, 2026 01:00
@vxfemboy
vxfemboy merged commit 8bfbd0c into main Jul 19, 2026
9 checks passed
@vxfemboy
vxfemboy deleted the feat/reality-5-followup-cleanups branch July 19, 2026 01:19
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