nx_tls13_server_session_emit_sh_test.nx source
↩ module page · 130 lines · 5029 B
1// nx_tls13_server_session_emit_sh_test.nx -- verify server emits a
2// ServerHello bytes that the existing CLIENT parser consumes (round-
3// trip), and that the session advances CH_RECEIVED -> SH_SENT.
4//
5// Closed-form invariants:
6// (a) Wrong-state session (INIT) -> BAD_STATE
7// (b) After recv_ch + emit_sh: state == SH_SENT + n > 0
8// (c) Client's tls13_server_hello_parse consumes our SH bytes
9// cleanly (positive verdict)
10// (d) Parsed legacy_version == 0x0303
11// (e) Parsed cipher_suite == TLS_CHACHA20_POLY1305_SHA256 (0x1303)
12// (f) Server's emitted random appears at the byte offset the
13// parser reports
14// (g) Extensions blob contains supported_versions(43) + key_share(51)
15// (h) Calling emit_sh again -> BAD_STATE (state moved past CH_RECEIVED)
16//
17// expect_exit: 0
18// license_tier: ORIGINAL
19
20import "nx_syscalls.nx"
21import "nx_x25519.nx"
22import "nx_x25519_ephemeral.nx"
23import "nx_tls13.nx"
24import "nx_tls13_hello.nx"
25import "nx_tls13_server_session.nx"
26import "nx_tls13_server_session_recv_ch.nx"
27import "nx_tls13_server_session_emit_sh.nx"
28
29func main() -> i64 {
30 // ----- Build client side: priv key + ClientHello -----
31 let cli_priv: *u8 = sys_mmap(32)
32 let cli_pub: *u8 = sys_mmap(32)
33 let cli_rand: *u8 = sys_mmap(32)
34 var i: i64 = 0
35 while i < 32 {
36 cli_priv[i] = ((i + 17) & 0xff) as u8
37 cli_rand[i] = ((i + 50) & 0xff) as u8
38 i = i + 1
39 }
40 x25519_keypair_public(cli_priv, cli_pub)
41
42 let sni: *u8 = "nishifamily.com"
43 let sni_len: i64 = 15
44 let ch_cap: i64 = 1024
45 let ch_buf: *u8 = sys_mmap(ch_cap)
46 let ch_n: i64 = tls13_client_hello_emit(cli_rand, sni, sni_len, cli_pub, ch_buf, ch_cap)
47 if ch_n <= 0 { return 5 }
48
49 // ----- Build server session -----
50 let srv_priv: *u8 = sys_mmap(32)
51 let srv_rand: *u8 = sys_mmap(32)
52 var k: i64 = 0
53 while k < 32 {
54 srv_priv[k] = ((k + 80) & 0xff) as u8
55 srv_rand[k] = ((k + 70) & 0xff) as u8
56 k = k + 1
57 }
58 let s: *Tls13ServerSession = nx_tls13_server_session_new(srv_rand, srv_priv)
59 if (s as i64) == 0 { return 6 }
60
61 // ----- (a) emit_sh in wrong state (INIT) -> BAD_STATE -----
62 let bad_buf: *u8 = sys_mmap(512)
63 let r_wrong: i64 = nx_tls13_server_session_emit_sh(s, bad_buf, 512)
64 let expect_bad: i64 = 0 - NX_TLS13_SSESSION_BAD_STATE
65 if r_wrong != expect_bad { return 10 }
66
67 // ----- recv_ch -----
68 let r_rc: i64 = nx_tls13_server_session_recv_ch(s, ch_buf, ch_n)
69 if r_rc != NX_TLS13_SSESSION_OK { return 15 }
70 if s.state != NX_TLS13_SSTATE_CH_RECEIVED { return 16 }
71
72 // ----- (b) emit_sh -----
73 let sh_cap: i64 = 512
74 let sh_buf: *u8 = sys_mmap(sh_cap)
75 let n: i64 = nx_tls13_server_session_emit_sh(s, sh_buf, sh_cap)
76 if n <= 0 { return 20 }
77 if s.state != NX_TLS13_SSTATE_SH_SENT { return 21 }
78
79 // ----- (c) Client parser round-trip -----
80 // STALE-TEST HEAL 2026-06-10: emit_sh writes a 5-byte TLS record
81 // header then the handshake body (required by real clients; see
82 // emit_sh preamble). This test predated that and parsed from
83 // offset 0 -> silently RED since the header landed. Parse the
84 // BODY (+5), like the wire peer does.
85 let sh_body: *u8 = sh_buf + 5
86 let body_n: i64 = n - 5
87 let pv_box: *i64 = sys_mmap(8) as *i64
88 let rand_off_box: *i64 = sys_mmap(8) as *i64
89 let cs_box: *i64 = sys_mmap(8) as *i64
90 let eo_box: *i64 = sys_mmap(8) as *i64
91 let el_box: *i64 = sys_mmap(8) as *i64
92 let parse_v: i64 = tls13_server_hello_parse(sh_body, body_n,
93 pv_box, rand_off_box, cs_box, eo_box, el_box)
94 if parse_v != NX_TLS13_HELLO_VERDICT_OK { return 30 }
95
96 // ----- (d) legacy_version -----
97 if *pv_box != TLS_LEGACY_VERSION { return 40 }
98
99 // ----- (e) cipher_suite -----
100 if *cs_box != NX_TLS13_CS_CHACHA20_POLY1305_SHA256 { return 50 }
101
102 // ----- (f) Server random matches at reported offset -----
103 let ro: i64 = *rand_off_box
104 var rmatch: i64 = 1
105 var ri: i64 = 0
106 while ri < 32 {
107 if sh_body[ro + ri] != srv_rand[ri] { rmatch = 0 }
108 ri = ri + 1
109 }
110 if rmatch != 1 { return 60 }
111
112 // ----- (g) Extensions blob contains supported_versions + key_share -----
113 let eo: i64 = *eo_box
114 let el: i64 = *el_box
115 let sv_off_box: *i64 = sys_mmap(8) as *i64
116 let sv_len_box: *i64 = sys_mmap(8) as *i64
117 let sv_v: i64 = tls13_ext_find(sh_body + eo, el, EXT_SUPPORTED_VERSIONS, sv_off_box, sv_len_box)
118 if sv_v != NX_TLS13_HELLO_VERDICT_OK { return 70 }
119 let ks_off_box: *i64 = sys_mmap(8) as *i64
120 let ks_len_box: *i64 = sys_mmap(8) as *i64
121 let ks_v: i64 = tls13_ext_find(sh_body + eo, el, EXT_KEY_SHARE, ks_off_box, ks_len_box)
122 if ks_v != NX_TLS13_HELLO_VERDICT_OK { return 71 }
123
124 // ----- (h) Calling emit_sh again -> BAD_STATE -----
125 let r_again: i64 = nx_tls13_server_session_emit_sh(s, sh_buf, sh_cap)
126 let expect_again: i64 = 0 - NX_TLS13_SSESSION_BAD_STATE
127 if r_again != expect_again { return 80 }
128
129 return 0
130}