nx_aw_mtls_inject_gate.nx source
↩ module page · 95 lines · 5978 B
1// nx_aw_mtls_inject_gate.nx -- gate the sovereign mTLS carrier's identity-injection TRUST BOUNDARY.
2// Proves the two security-floor invariants WITHOUT needing a Nishi mTLS client: the cert is only consulted
3// when auth==1, but the X-Nishi-Cert-Identity STRIP runs for every auth -> a no-cert/bad-cert client can
4// never smuggle a spoofed identity to the backend, and a clean request is forwarded byte-exact (never-
5// lockout). The real-CN inject (auth==1 with a parseable cert) is covered downstream by run_ecdsa_mtls's
6// loopback+interop gates feeding a real cert. license_tier: ORIGINAL expect_exit: 0
7import "nx_syscalls.nx"
8import "nx_aw_mtls_inject.nx"
9import "nx_mtls_identity.nx" // nx_mtls_mint_identity_cert + NX_MID_OK (gate: mint a REAL cert to inject)
10
11func g_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
12func g_len(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
13
14// does buf[0..n] contain the lowercase literal `lit` ANYWHERE (case-insensitive)?
15func g_has_ci(buf: *u8, n: i64, lit: *u8) -> i64 {
16 var i: i64 = 0
17 while i < n { if mi_ci_starts(buf, i, n, lit) == 1 { return 1 } i = i + 1 }
18 return 0
19}
20func g_eq(a: *u8, an: i64, b: *u8, bn: i64) -> i64 {
21 if an != bn { return 0 }
22 var i: i64 = 0; while i < an { if a[i] != b[i] { return 0 } i = i + 1 }
23 return 1
24}
25// returns 1 on FAILURE (so main can accumulate), 0 on ok
26func g_check(name: *u8, cond: i64) -> i64 {
27 if cond == 1 { g_puts(" ok " as *u8); g_puts(name); g_puts("\n" as *u8); return 0 }
28 g_puts(" FAIL " as *u8); g_puts(name); g_puts("\n" as *u8); return 1
29}
30
31func main() -> i64 {
32 g_puts("=== nx_aw_mtls_inject gate (trust-boundary strip + request-not-require) ===\n" as *u8)
33 let lit: *u8 = "x-nishi-cert-identity:" as *u8
34 let out: *u8 = sys_mmap(8192)
35 let dummy: *u8 = sys_mmap(16) // a non-null but unparseable "cert"; consulted only when auth==1
36 var fails: i64 = 0
37
38 // T1: auth==0, clean GET -> byte-exact passthrough (no header added)
39 let r1: *u8 = "GET /wiki/hub.html HTTP/1.1\r\nHost: nishifamily.com\r\n\r\n" as *u8
40 let n1: i64 = g_len(r1)
41 let o1: i64 = mtls_inject_identity(r1, n1, dummy, 0, 0, out, 8192)
42 fails = fails + g_check("T1 auth=0 clean GET -> byte-exact passthrough" as *u8, g_eq(out, o1, r1, n1))
43
44 // T2: auth==0, GET WITH a spoofed identity header -> STRIPPED (the critical anti-spoof)
45 let r2: *u8 = "GET /wiki/hub.html HTTP/1.1\r\nX-Nishi-Cert-Identity: deadbeefspoof\r\nHost: x\r\n\r\n" as *u8
46 let n2: i64 = g_len(r2)
47 let o2: i64 = mtls_inject_identity(r2, n2, dummy, 0, 0, out, 8192)
48 var t2: i64 = 0; if g_has_ci(out, o2, lit) == 0 { t2 = 1 }
49 fails = fails + g_check("T2 auth=0 spoofed header -> STRIPPED (no x-nishi-cert-identity survives)" as *u8, t2)
50 fails = fails + g_check("T2b legit Host header preserved through the strip" as *u8, g_has_ci(out, o2, "host:" as *u8))
51
52 // T3: auth=-1 (cert presented but verify FAILED) + spoof -> stripped, none injected
53 let o3: i64 = mtls_inject_identity(r2, n2, dummy, 0, 0 - 1, out, 8192)
54 var t3: i64 = 0; if g_has_ci(out, o3, lit) == 0 { t3 = 1 }
55 fails = fails + g_check("T3 auth=-1 bad cert + spoof -> STRIPPED, no identity" as *u8, t3)
56
57 // T4: auth==1 but cert is unparseable (idn==0) -> spoof stripped, NO false identity injected
58 let o4: i64 = mtls_inject_identity(r2, n2, dummy, 0, 1, out, 8192)
59 var t4: i64 = 0; if g_has_ci(out, o4, lit) == 0 { t4 = 1 }
60 fails = fails + g_check("T4 auth=1 unparseable cert -> spoof stripped, NO false identity" as *u8, t4)
61
62 // T5: POST whose BODY contains the header string -> body verbatim (strip is header-section only)
63 let r5: *u8 = "POST /x HTTP/1.1\r\nHost: x\r\n\r\nx-nishi-cert-identity: in-the-body\r\n" as *u8
64 let n5: i64 = g_len(r5)
65 let o5: i64 = mtls_inject_identity(r5, n5, dummy, 0, 0, out, 8192)
66 fails = fails + g_check("T5 body occurrence preserved (strip is header-only)" as *u8, g_has_ci(out, o5, lit))
67 fails = fails + g_check("T5b POST byte-exact passthrough (auth=0, no header in head)" as *u8, g_eq(out, o5, r5, n5))
68
69 // ---- positive path: a REAL minted client cert (CN = hex(uid)) ----
70 let ek: *u8 = sys_mmap(32); let uid: *u8 = sys_mmap(32)
71 var ii: i64 = 0; while ii < 32 { ek[ii] = 90 as u8; uid[ii] = ii as u8; ii = ii + 1 } // CN = hex(00 01 .. 1f)
72 let cert: *u8 = sys_mmap(4096); let clen: *i64 = (sys_mmap(8)) as *i64
73 let seed: *u8 = sys_mmap(32); let pub: *u8 = sys_mmap(32)
74 var minted: i64 = 0
75 if nx_mtls_mint_identity_cert(ek, uid, cert, 4096, clen, seed, pub) == NX_MID_OK { minted = 1 }
76 fails = fails + g_check("T6pre mint a real identity cert (CN=hex(uid))" as *u8, minted)
77 let want: *u8 = "x-nishi-cert-identity: 000102030405" as *u8 // header + first 12 hex chars (all digits = case-robust)
78
79 // T6: auth==1, REAL cert -> the cert Subject CN is extracted + injected as X-Nishi-Cert-Identity
80 let r6: *u8 = "GET /wiki/hub.html HTTP/1.1\r\nHost: x\r\n\r\n" as *u8
81 let n6: i64 = g_len(r6)
82 let o6: i64 = mtls_inject_identity(r6, n6, cert, clen[0], 1, out, 8192)
83 fails = fails + g_check("T6 auth=1 real cert -> CN injected as X-Nishi-Cert-Identity" as *u8, g_has_ci(out, o6, want))
84
85 // T7: REAL cert + a SPOOFED identity header -> spoof STRIPPED, the REAL CN injected (anti-spoof, positive path)
86 let r7: *u8 = "GET /x HTTP/1.1\r\nX-Nishi-Cert-Identity: ffffffffffff\r\nHost: x\r\n\r\n" as *u8
87 let n7: i64 = g_len(r7)
88 let o7: i64 = mtls_inject_identity(r7, n7, cert, clen[0], 1, out, 8192)
89 var t7: i64 = 0
90 if g_has_ci(out, o7, want) == 1 { if g_has_ci(out, o7, "ffffffffffff" as *u8) == 0 { t7 = 1 } }
91 fails = fails + g_check("T7 real cert + spoof -> spoof replaced by the REAL CN" as *u8, t7)
92
93 if fails == 0 { g_puts("ALL GREEN (10/10)\n" as *u8); sys_exit(0); return 0 }
94 g_puts("HAD FAILURES\n" as *u8); sys_exit(1); return 1
95}