nx_tls13_cert_cache_gate.nx source
↩ module page · 96 lines · 5555 B
1// nx_tls13_cert_cache_gate.nx -- proves the additive cert-validation CACHE in nx_tls13_client_validate_certificate:
2// a byte-identical cached cert short-circuits to OK (skipping the ECDSA chain crypto), ANY mismatch / no-cache runs
3// full validation, and the presented cert is captured to cert_out (bounded, no overflow). The test cert is
4// DELIBERATELY INVALID -- so a cache-hit returning OK conclusively proves the pipeline was skipped, and a
5// cache-miss returning non-OK proves it was NOT. GREEN + exit 0 iff all pass. license_tier: ORIGINAL expect_exit: 0
6import "nx_tls13_client_validate_certificate.nx" // TlsValidationContext + validator + transitive syscalls/pipeline
7import "nx_syscalls.nx"
8import "nx_gate_verdict.nx"
9
10func cg_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
11func cg_putn(v: i64) -> i64 {
12 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 }
13 var m: i64 = v; if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
14 let d: *u8 = sys_mmap(24); var k: i64 = 0
15 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
16 var j: i64 = k - 1
17 while j >= 0 { sys_write(1, ((d as i64)+j) as *u8, 1); j = j - 1 }
18 return 0
19}
20func cg_memeq(a: *u8, an: i64, b: *u8, bn: i64) -> i64 {
21 if an != bn { return 0 }
22 var i: i64 = 0
23 while i < an { if a[i] != b[i] { return 0 } i = i + 1 }
24 return 1
25}
26func cg_row(name: *u8, ok: i64) -> i64 {
27 if ok == 1 { cg_puts(" PASS " as *u8) } else { cg_puts(" FAIL " as *u8) }
28 cg_puts(name); cg_puts("\n" as *u8)
29 return ok
30}
31
32func main() -> i64 {
33 cg_puts("tls cert-validation cache gate (fast-path skip on byte-exact match; miss/none => full validate; bounded capture)\n" as *u8)
34 // DELIBERATELY INVALID Certificate messages (full validation must reject them). No real trust store needed:
35 // the pipeline rejects an invalid cert at PARSE, before it dereferences ctx.store -- so ctx.store stays 0 (zeroed
36 // mmap) and is never touched. Keeps the gate self-contained (no certdata dep) while still hitting the reject path.
37 let certX: *u8 = sys_mmap(64); var xi: i64 = 0
38 while xi < 40 { certX[xi] = (0x41 + (xi % 26)) as u8; xi = xi + 1 }
39 let lenX: i64 = 40
40 let certY: *u8 = sys_mmap(64); var yi: i64 = 0
41 while yi < 40 { certY[yi] = (0x61 + (yi % 26)) as u8; yi = yi + 1 }
42
43 let sni: *u8 = "nishifamily.com" as *u8
44 let ctx: *TlsValidationContext = sys_mmap(128) as *TlsValidationContext
45 ctx.sni_host = sni; ctx.sni_host_len = 15; ctx.now_epoch = 1750000000
46 // store + cache fields are 0 from the zeroed mmap -> cache inactive for T1
47
48 var pass: i64 = 0
49 let total: i64 = 5
50
51 // T1 NEG-CONTROL: no cache -> full validation -> the invalid cert is REJECTED (proves the pipeline runs + rejects)
52 let v_none: i64 = nx_tls13_client_validate_certificate(certX, lenX, ctx)
53 var t1: i64 = 0
54 if v_none != NX_TLS13_CLIENT_CV_OK { t1 = 1 }
55 pass = pass + cg_row("T1 NEG no-cache: invalid cert -> full validation REJECTS (verdict != OK)\x00" as *u8, t1)
56
57 // T2: cache HIT (cached == certX) -> OK, despite the SAME cert being rejected in T1 -> proves the skip
58 ctx.cached_cert = certX; ctx.cached_cert_len = lenX
59 let v_hit: i64 = nx_tls13_client_validate_certificate(certX, lenX, ctx)
60 var t2: i64 = 0
61 if v_hit == NX_TLS13_CLIENT_CV_OK { t2 = 1 }
62 pass = pass + cg_row("T2 cache HIT: byte-identical cached cert -> OK (chain crypto SKIPPED; same cert T1 rejected)\x00" as *u8, t2)
63
64 // T3 NEG: cache MISS (cached = a DIFFERENT cert) -> falls through to full validation -> REJECTED
65 ctx.cached_cert = certY; ctx.cached_cert_len = 40
66 let v_miss: i64 = nx_tls13_client_validate_certificate(certX, lenX, ctx)
67 var t3: i64 = 0
68 if v_miss != NX_TLS13_CLIENT_CV_OK { t3 = 1 }
69 pass = pass + cg_row("T3 NEG cache MISS: different cached cert -> full validation REJECTS (no false accept)\x00" as *u8, t3)
70
71 // T4: cert_out capture -> the presented cert is copied out byte-exact + length set
72 let cob: *u8 = sys_mmap(256)
73 ctx.cached_cert_len = 0; ctx.cert_out = cob; ctx.cert_out_cap = 256
74 let _cap4: i64 = nx_tls13_client_validate_certificate(certX, lenX, ctx)
75 var t4: i64 = 0
76 if ctx.cert_out_len == lenX { if cg_memeq(cob, lenX, certX, lenX) == 1 { t4 = 1 } }
77 pass = pass + cg_row("T4 capture: presented cert copied to cert_out byte-exact + cert_out_len set\x00" as *u8, t4)
78
79 // T5 NEG: cert_out too small -> NOT written, cert_out_len == 0 (no overflow)
80 ctx.cert_out = cob; ctx.cert_out_cap = 10
81 let _cap5: i64 = nx_tls13_client_validate_certificate(certX, lenX, ctx)
82 var t5: i64 = 0
83 if ctx.cert_out_len == 0 { t5 = 1 }
84 pass = pass + cg_row("T5 NEG capture overflow: cap < cert -> cert_out_len=0, nothing written (bounded)\x00" as *u8, t5)
85
86 cg_puts("nx_tls13_cert_cache_gate pass=" as *u8); cg_putn(pass); cg_puts("/" as *u8); cg_putn(total); cg_puts("\n" as *u8)
87 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
88 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
89 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
90 let ctr__dry: *i64 = gv_ctr()
91 ctr__dry[0] = pass
92 ctr__dry[1] = total
93 let rc__dry: i64 = gv_verdict("TLS13-CERT-CACHE-GATE" as *u8, ctr__dry, "cache fast-path skips only on byte-exact match; miss/none full-validate; capture bounded" as *u8)
94 sys_exit(rc__dry)
95 return rc__dry
96}