code wiki / (root) / nx_aw_mtls_inject_gate.nx

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}