nx_tls13_frag_gate.nx source
↩ module page · 122 lines · 7183 B
1// nx_tls13_frag_gate.nx -- THE GATE FOR TLS REQUEST FRAGMENTATION ARITHMETIC, 2026-09-04.
2//
3// SUBJECT: nx_tls13_frag_max / nx_tls13_frag_len / nx_tls13_frag_count, in-process.
4//
5// WHY THIS GATE EXISTS AT ALL. Until today nx_https_req_complete wrote every request as ONE TLS
6// record, so the transport had a hard ~16 KB ceiling that callers wore as hand-picked body constants.
7// MEASURED: a 6,100-byte payload produced an 8,369-byte body and was refused while 5,900 passed, and
8// the sovereign content shipper could not send the 48,402-byte chunks its own server offered -- around
9// forty abandoned transfers had piled up over eleven days while each failure reported only
10// "post failed". Fragmenting fixed it. But that change is in a shared transport every HTTPS client in
11// this estate imports, and it goes live for each of them silently, on their NEXT REBUILD. A change
12// with that blast radius must be testable without a socket.
13//
14// WHY IT GATES PURE ARITHMETIC AND NOT A LIVE SEND, on its sibling nx_https_post_lib_gate precedent:
15// a gate that opens a socket goes RED when someone else network fails, and its RED then indicts this
16// code for another outage. The split was extracted out of the loop precisely so it could be walked
17// exhaustively here as integer arithmetic over one argument.
18//
19// THE LOAD-BEARING TOOTH IS THE PARTITION. Every off-by-one in a chunking loop either DROPS bytes or
20// DUPLICATES them, and both survive a boundary test that only checks counts. Asserting that the
21// fragment lengths SUM BACK TO the request length is the check that cannot be passed by a wrong split.
22//
23// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
24import "nx_syscalls.nx"
25import "nx_gate_verdict.nx"
26import "nx_tls13_record.nx"
27
28// Walks a request of req_len the way the writer does and returns the SUM of the fragment lengths.
29// Returns 0 - 1 if the walk fails to terminate within a generous bound, so a non-advancing split is a
30// named failure rather than a hang -- an unbounded loop and a wrong answer are the same to a caller.
31func fg_walk_sum(req_len: i64, maxsteps: i64) -> i64 {
32 var off: i64 = 0
33 var sum: i64 = 0
34 var steps: i64 = 0
35 while off < req_len {
36 if steps >= maxsteps { return 0 - 1 }
37 let f: i64 = nx_tls13_frag_len(req_len, off)
38 if f <= 0 { return 0 - 1 }
39 sum = sum + f
40 off = off + f
41 steps = steps + 1
42 }
43 return sum
44}
45// Largest fragment produced while walking req_len; 0 for an empty request.
46func fg_walk_max(req_len: i64, maxsteps: i64) -> i64 {
47 var off: i64 = 0
48 var big: i64 = 0
49 var steps: i64 = 0
50 while off < req_len {
51 if steps >= maxsteps { return 0 - 1 }
52 let f: i64 = nx_tls13_frag_len(req_len, off)
53 if f <= 0 { return 0 - 1 }
54 if f > big { big = f }
55 off = off + f
56 steps = steps + 1
57 }
58 return big
59}
60
61func main() -> i64 {
62 let ctr: *i64 = gv_ctr()
63 let m: i64 = nx_tls13_frag_max()
64
65 // The bound is the record layer own limit minus the content-type byte. If this ever drifts from
66 // NX_TLS13_MAX_INNER_PLAINTEXT the writer is emitting records a conforming peer must reject, and
67 // the failure would arrive as an opaque connection reset rather than as anything naming a size.
68 gv_check_eq("frag-max-is-the-record-layer-inner-limit-minus-the-content-type-byte" as *u8,
69 m, NX_TLS13_MAX_INNER_PLAINTEXT - 1, ctr)
70
71 // Counts across the boundary. m and m+1 are the pair that decides whether a full record is split.
72 gv_check_eq("count-of-an-EMPTY-request-is-ZERO-records (ceiling division of zero is the case every hand-rolled split gets wrong)" as *u8,
73 nx_tls13_frag_count(0), 0, ctr)
74 gv_check_eq("count-of-one-byte-is-ONE-record" as *u8, nx_tls13_frag_count(1), 1, ctr)
75 gv_check_eq("count-of-EXACTLY-frag-max-is-ONE-record-not-two" as *u8, nx_tls13_frag_count(m), 1, ctr)
76 gv_check_eq("count-of-frag-max-PLUS-ONE-is-TWO-records (the boundary the old single-record writer could not cross)" as *u8,
77 nx_tls13_frag_count(m + 1), 2, ctr)
78 gv_check_eq("count-of-exactly-two-full-records-is-TWO" as *u8, nx_tls13_frag_count(2 * m), 2, ctr)
79 gv_check_eq("count-of-two-full-records-plus-one-is-THREE" as *u8, nx_tls13_frag_count(2 * m + 1), 3, ctr)
80
81 // THE PARTITION MUST SUM. A split that drops or duplicates a byte passes every count test above.
82 let s1: i64 = fg_walk_sum(1, 8)
83 let s2: i64 = fg_walk_sum(m, 8)
84 let s3: i64 = fg_walk_sum(m + 1, 8)
85 let s4: i64 = fg_walk_sum(64769, 32) // the real chunk-request body size measured on the wire
86 let s5: i64 = fg_walk_sum(411108, 64) // the real 400 KB artifact shipped through this path
87 gv_check_eq("PARTITION-SUMS-at-one-byte" as *u8, s1, 1, ctr)
88 gv_check_eq("PARTITION-SUMS-at-exactly-frag-max" as *u8, s2, m, ctr)
89 gv_check_eq("PARTITION-SUMS-one-byte-past-frag-max (the split that drops or duplicates a byte fails HERE and nowhere else)" as *u8,
90 s3, m + 1, ctr)
91 gv_check_eq("PARTITION-SUMS-at-the-measured-64769-byte-chunk-request" as *u8, s4, 64769, ctr)
92 gv_check_eq("PARTITION-SUMS-at-the-measured-411108-byte-artifact" as *u8, s5, 411108, ctr)
93
94 // No fragment may exceed the limit, or the peer rejects the record.
95 gv_check_eq("no-fragment-of-the-411108-byte-walk-EXCEEDS-frag-max" as *u8, fg_walk_max(411108, 64), m, ctr)
96
97 // Past the end the split must return zero, or the writer loop never terminates.
98 gv_check_eq("frag-len-PAST-the-end-is-zero-so-the-writer-loop-terminates" as *u8,
99 nx_tls13_frag_len(100, 100), 0, ctr)
100 gv_check_eq("frag-len-of-an-EMPTY-request-is-zero" as *u8, nx_tls13_frag_len(0, 0), 0, ctr)
101
102 // neg-control: a NEGATIVE offset must not be treated as a valid position. Without this a caller
103 // arithmetic error becomes an out-of-bounds read of the request buffer rather than a refusal.
104 gv_check_eq("neg-control-a-negative-offset-yields-zero-not-a-bogus-length" as *u8,
105 nx_tls13_frag_len(100, 0 - 5), 0, ctr)
106 // neg-control: a negative request length is not a request.
107 gv_check_eq("neg-control-a-negative-request-length-is-ZERO-records" as *u8,
108 nx_tls13_frag_count(0 - 1), 0, ctr)
109
110 // ANTI-VACUITY: the 411108 walk must actually have taken more than one record, otherwise every
111 // partition tooth above passed on a single-fragment case and proves nothing about SPLITTING.
112 let nrec: i64 = nx_tls13_frag_count(411108)
113 gv_check("anti-vacuity-the-large-walk-really-DID-split-into-multiple-records (without this the partition teeth pass on a one-record case and say nothing about fragmentation)" as *u8,
114 (nrec > 1) as i64, ctr)
115
116 gv_kv("frag_max", m)
117 gv_kv("records_for_411108", nrec)
118 gv_kv("records_for_64769", nx_tls13_frag_count(64769))
119 gv_kv("walk_sum_411108", s5)
120 gv_kv("walk_max_fragment", fg_walk_max(411108, 64))
121 return gv_verdict("tls13_frag" as *u8, ctr, "the TLS request split is bounded by the record layer own inner-plaintext limit, terminates, and its fragments sum back to the request length" as *u8)
122}