code wiki / (root) / nx_sni_extract_gate.nx

nx_sni_extract_gate.nx source

↩ module page · 61 lines · 3489 B

1// nx_sni_extract_gate.nx -- gate the SNI router's hostname extraction. Builds REAL ClientHello records via the 2// proven tls13_ext_emit_server_name and proves sni_extract_hostname recovers the host, plus trust-boundary 3// negatives (truncated, non-handshake). license_tier: ORIGINAL expect_exit: 0 4import "nx_syscalls.nx" 5import "nx_sni_extract.nx" 6import "nx_tls13_ext.nx" // tls13_ext_emit_server_name -- build a CH carrying a known SNI 7 8func 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 } 9func g_eq(a: *u8, an: i64, b: *u8, bn: i64) -> i64 { if an != bn { return 0 } var i: i64=0; while i<an { if a[i]!=b[i] { return 0 } i=i+1 } return 1 } 10func g_check(name: *u8, cond: i64) -> i64 { if cond==1 { g_puts(" ok " as *u8); g_puts(name); g_puts("\n" as *u8); return 0 } g_puts(" FAIL " as *u8); g_puts(name); g_puts("\n" as *u8); return 1 } 11 12// build a minimal ClientHello record carrying ONE SNI extension for `host`; return total bytes. 13func build_ch(host: *u8, host_len: i64, out: *u8) -> i64 { 14 let sni: *u8 = sys_mmap(512) 15 let sni_n: i64 = tls13_ext_emit_server_name(host, host_len, sni, 512) 16 if sni_n <= 0 { return 0 } 17 var o: i64 = 9 18 out[o]=3 as u8; out[o+1]=3 as u8; o=o+2 // client_version 0x0303 19 var i: i64=0; while i<32 { out[o]=0 as u8; o=o+1; i=i+1 } // random(32) 20 out[o]=0 as u8; o=o+1 // session_id_len=0 21 out[o]=0 as u8; out[o+1]=2 as u8; o=o+2; out[o]=0x13 as u8; out[o+1]=0x01 as u8; o=o+2 // cipher_suites len(2)+0x1301 22 out[o]=1 as u8; o=o+1; out[o]=0 as u8; o=o+1 // compression len(1)+null 23 out[o]=((sni_n>>8)&0xff) as u8; out[o+1]=(sni_n&0xff) as u8; o=o+2 // extensions_len 24 var j: i64=0; while j<sni_n { out[o]=sni[j]; o=o+1; j=j+1 } // the SNI extension 25 let body_len: i64 = o - 9 26 out[5]=0x01 as u8; out[6]=((body_len>>16)&0xff) as u8; out[7]=((body_len>>8)&0xff) as u8; out[8]=(body_len&0xff) as u8 // handshake hdr 27 let rec_len: i64 = 4 + body_len 28 out[0]=0x16 as u8; out[1]=3 as u8; out[2]=3 as u8; out[3]=((rec_len>>8)&0xff) as u8; out[4]=(rec_len&0xff) as u8 // record hdr 29 return o 30} 31 32func main() -> i64 { 33 g_puts("=== nx_sni_extract gate (SNI router hostname extraction) ===\n" as *u8) 34 var fails: i64 = 0 35 let ch: *u8 = sys_mmap(1024) 36 let out: *u8 = sys_mmap(512) 37 38 let h1: *u8 = "nishifamily.com" as *u8 39 let n1: i64 = build_ch(h1, 15, ch) 40 let r1: i64 = sni_extract_hostname(ch, n1, out, 512) 41 fails = fails + g_check("T1 nishifamily.com extracted (first-party personal)" as *u8, g_eq(out, r1, h1, 15)) 42 43 let h2: *u8 = "andelinwest.com" as *u8 44 let n2: i64 = build_ch(h2, 15, ch) 45 let r2: i64 = sni_extract_hostname(ch, n2, out, 512) 46 fails = fails + g_check("T2 andelinwest.com extracted (third-party client)" as *u8, g_eq(out, r2, h2, 15)) 47 48 let r3: i64 = sni_extract_hostname(ch, 20, out, 512) 49 var t3: i64=0; if r3==0 { t3=1 } 50 fails = fails + g_check("T3 truncated CH -> 0 (no false host at the boundary)" as *u8, t3) 51 52 let saved: i64 = ch[0] as i64 53 ch[0]=0x17 as u8 54 let r4: i64 = sni_extract_hostname(ch, n2, out, 512) 55 ch[0]=saved as u8 56 var t4: i64=0; if r4==0 { t4=1 } 57 fails = fails + g_check("T4 non-handshake record -> 0" as *u8, t4) 58 59 if fails==0 { g_puts("ALL GREEN (4/4)\n" as *u8); sys_exit(0); return 0 } 60 g_puts("HAD FAILURES\n" as *u8); sys_exit(1); return 1 61}