code wiki / (root) / nx_tls12_hello_test.nx

nx_tls12_hello_test.nx source

↩ module page · 80 lines · 3328 B

1// nx_tls12_hello_test.nx -- KAT for the TLS 1.2 ClientHello emitter (rung 1, no network). 2// Emits a CH for SNI "example.com" with a fixed random and asserts the wire structure byte-for-byte: 3// out[0]=1 (ClientHello) ; out[4..5]=0x0303 (TLS 1.2) ; out[38]=0 (empty session_id) ; 4// out[39..40]=0x0008 (cipher_suites list len) ; out[41..42]=0xC02B (first suite) ; 5// handshake length field (out[1..3]) == ret-4 ; SNI host bytes present. 6// VIZSLA-style gate: prints ROW/PASS, exit 0 iff all rows pass. license_tier: ORIGINAL 7import "nx_syscalls.nx" 8import "nx_tls12_hello.nx" 9 10func tg_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 11func tg_p(s: *u8) -> i64 { sys_write(1, s, tg_slen(s)); return 0 } 12func tg_row(name: *u8, pass: i64) -> i64 { 13 tg_p("ROW " as *u8); tg_p(name) 14 if pass == 1 { tg_p(" PASS\n" as *u8) } else { tg_p(" FAIL\n" as *u8) } 15 return pass 16} 17func tg_contains(buf: *u8, n: i64, needle: *u8) -> i64 { 18 let m: i64 = tg_slen(needle) 19 if m == 0 { return 0 } 20 var i: i64 = 0 21 while i + m <= n { 22 var ok: i64 = 1 23 var j: i64 = 0 24 while j < m { if buf[i + j] != needle[j] { ok = 0; j = m } else { j = j + 1 } } 25 if ok == 1 { return 1 } 26 i = i + 1 27 } 28 return 0 29} 30 31func main() -> i64 { 32 tg_p("=== TLS12 CLIENTHELLO KAT ===\n" as *u8) 33 let rnd: *u8 = sys_mmap(64) 34 var i: i64 = 0 35 while i < 32 { rnd[i] = (0x40 + i) as u8; i = i + 1 } // fixed deterministic random 36 let sni: *u8 = "example.com\x00" as *u8 37 let out: *u8 = sys_mmap(2048) 38 let ret: i64 = tls12_client_hello_emit(rnd, sni, 11, out, 2048) 39 40 var pass: i64 = 0 41 var r: i64 = 0 42 43 if ret > 0 { r = 1 } else { r = 0 } 44 pass = pass + tg_row("emit-ok" as *u8, r) 45 46 r = 0; if ret > 0 { if (out[0] & 0xff) == 1 { r = 1 } } 47 pass = pass + tg_row("type-clienthello" as *u8, r) 48 49 r = 0; if ret > 0 { if (out[4] & 0xff) == 3 { if (out[5] & 0xff) == 3 { r = 1 } } } 50 pass = pass + tg_row("version-0x0303" as *u8, r) 51 52 r = 0; if ret > 0 { if (out[38] & 0xff) == 0 { r = 1 } } 53 pass = pass + tg_row("session-id-empty" as *u8, r) 54 55 r = 0; if ret > 0 { if (out[39] & 0xff) == 0 { if (out[40] & 0xff) == 8 { r = 1 } } } 56 pass = pass + tg_row("cipher-list-len-8" as *u8, r) 57 58 r = 0; if ret > 0 { if (out[41] & 0xff) == 0xC0 { if (out[42] & 0xff) == 0x2B { r = 1 } } } 59 pass = pass + tg_row("first-suite-c02b" as *u8, r) 60 61 r = 0 62 if ret > 0 { 63 let body: i64 = ret - 4 64 let hlen: i64 = ((out[1] & 0xff) << 16) | ((out[2] & 0xff) << 8) | (out[3] & 0xff) 65 if hlen == body { r = 1 } 66 } 67 pass = pass + tg_row("hs-length-field" as *u8, r) 68 69 r = 0; if ret > 0 { if tg_contains(out, ret, "example.com" as *u8) == 1 { r = 1 } } 70 pass = pass + tg_row("sni-host-present" as *u8, r) 71 72 tg_p("TLS12-HELLO-KAT rows=8 pass=" as *u8) 73 let pbuf: *u8 = sys_mmap(16) 74 var pv: i64 = pass 75 if pv == 0 { pbuf[0] = 48 as u8; sys_write(1, pbuf, 1) } 76 else { var k: i64 = 0; let t: *u8 = sys_mmap(16); while pv > 0 { t[k] = (48 + (pv % 10)) as u8; pv = pv / 10; k = k + 1 } var j: i64 = 0; while j < k { pbuf[j] = t[k-1-j]; j = j + 1 } sys_write(1, pbuf, k) } 77 if pass == 8 { tg_p(" verdict=GREEN\n" as *u8); return 0 } 78 tg_p(" verdict=RED\n" as *u8) 79 return 1 80}