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}