nx_tls13_server_full_handshake_test.nx source
↩ module page · 225 lines · 9084 B
1// nx_tls13_server_full_handshake_test.nx -- end-to-end integration
2// smoke composing ALL 10 TLS server stones in ONE authenticated
3// handshake. Proves the substrate's complete TLS 1.3 server-side
4// pipeline works in pure NishiLang.
5//
6// The 10-stone authenticated flow:
7//
8// client ClientHello bytes
9// -> [stone 2] recv_ch state INIT -> CH_RECEIVED
10// [stone 3] emit_sh -> SH_SENT
11// [stone 4] derive_hs_secrets -> EE_SENT (placeholder)
12// [stone 5] derive_traffic (no state change)
13// [stone 6] emit_ee -> CERT_SENT
14// [stone 6.5] emit_certificate (state stays CERT_SENT)
15// [stone 7.5] emit_cv -> CV_SENT
16// [stone 7] emit_sf -> SF_SENT
17// <- client Finished bytes (constructed using shared keys)
18// [stone 8] recv_cf + derive_app -> CONNECTED
19//
20// Asserts at every step:
21// - State transition correct
22// - server_seq / client_seq tracking correct
23// - Each emit returns positive byte count + 0x17 (app_data) header
24// - Final state CONNECTED + master_secret + 6 app-traffic buffers
25//
26// expect_exit: 0
27// license_tier: ORIGINAL
28
29import "nx_syscalls.nx"
30import "nx_x25519.nx"
31import "nx_x25519_ephemeral.nx"
32import "nx_hmac.nx"
33import "nx_tls13.nx"
34import "nx_tls13_hello.nx"
35import "nx_tls13_kdf.nx"
36import "nx_tls13_record.nx"
37import "nx_tls13_transcript.nx"
38import "nx_tls13_server_session.nx"
39import "nx_tls13_server_session_recv_ch.nx"
40import "nx_tls13_server_session_emit_sh.nx"
41import "nx_tls13_server_session_derive_hs.nx"
42import "nx_tls13_server_session_derive_traffic.nx"
43import "nx_tls13_server_session_emit_ee.nx"
44import "nx_tls13_server_session_emit_certificate.nx"
45import "nx_tls13_server_session_emit_cv.nx"
46import "nx_tls13_server_session_emit_sf.nx"
47import "nx_tls13_server_session_recv_cf.nx"
48
49// Helper from recv_cf_test pattern: build client Finished record
50// using the shared c_hs_traffic_key + iv + transcript.
51func build_client_finished(
52 cli_hs_key: *u8, cli_hs_iv: *u8, cli_seq: i64,
53 verify_data: *u8,
54 out: *u8, out_cap: i64
55) -> i64 {
56 let inner_len: i64 = 36
57 let inner: *u8 = sys_mmap(inner_len)
58 inner[0] = HT_FINISHED & 0xff
59 inner[1] = 0
60 inner[2] = 0
61 inner[3] = 32
62 var i: i64 = 0
63 while i < 32 { inner[4 + i] = verify_data[i]; i = i + 1 }
64 let header: *u8 = sys_mmap(5)
65 let ct: *u8 = sys_mmap(inner_len + 17)
66 let tag: *u8 = sys_mmap(16)
67 let rv: i64 = nx_tls13_record_encrypt(
68 cli_hs_key, cli_hs_iv, cli_seq,
69 inner, inner_len,
70 CT_HANDSHAKE, 0,
71 header, ct, tag)
72 if rv != NX_TLS13_REC_VERDICT_OK { return -1 }
73 let total: i64 = 5 + inner_len + 1 + 16
74 if total > out_cap { return -1 }
75 var w: i64 = 0
76 var hi: i64 = 0
77 while hi < 5 { out[w + hi] = header[hi]; hi = hi + 1 }
78 w = w + 5
79 var ci: i64 = 0
80 while ci < inner_len + 1 { out[w + ci] = ct[ci]; ci = ci + 1 }
81 w = w + inner_len + 1
82 var ti: i64 = 0
83 while ti < 16 { out[w + ti] = tag[ti]; ti = ti + 1 }
84 return w + 16
85}
86
87func main() -> i64 {
88 // ========== CLIENT SETUP ==========
89 let cli_priv: *u8 = sys_mmap(32)
90 let cli_pub: *u8 = sys_mmap(32)
91 let cli_rand: *u8 = sys_mmap(32)
92 var i: i64 = 0
93 while i < 32 {
94 cli_priv[i] = ((i + 17) & 0xff) as u8
95 cli_rand[i] = ((i + 50) & 0xff) as u8
96 i = i + 1
97 }
98 x25519_keypair_public(cli_priv, cli_pub)
99
100 let ch_buf: *u8 = sys_mmap(1024)
101 let ch_n: i64 = tls13_client_hello_emit(
102 cli_rand, "nishifamily.com", 15, cli_pub, ch_buf, 1024)
103 if ch_n <= 0 { return 5 }
104
105 // ========== SERVER SETUP ==========
106 let srv_priv: *u8 = sys_mmap(32)
107 let srv_rand: *u8 = sys_mmap(32)
108 let srv_ecdsa: *u8 = sys_mmap(32)
109 var k: i64 = 0
110 while k < 32 {
111 srv_priv[k] = ((k + 80) & 0xff) as u8
112 srv_rand[k] = ((k + 70) & 0xff) as u8
113 srv_ecdsa[k] = ((k + 100) & 0xff) as u8
114 k = k + 1
115 }
116 let s: *Tls13ServerSession = nx_tls13_server_session_new(srv_rand, srv_priv)
117 if (s as i64) == 0 { return 10 }
118 if s.state != NX_TLS13_SSTATE_INIT { return 11 }
119
120 // ========== STONE 2: recv_ch ==========
121 let r2: i64 = nx_tls13_server_session_recv_ch(s, ch_buf, ch_n)
122 if r2 != NX_TLS13_SSESSION_OK { return 20 }
123 if s.state != NX_TLS13_SSTATE_CH_RECEIVED { return 21 }
124 if (s.client_x25519_pub as i64) == 0 { return 22 }
125
126 // ========== STONE 3: emit_sh ==========
127 let sh_buf: *u8 = sys_mmap(512)
128 let n_sh: i64 = nx_tls13_server_session_emit_sh(s, sh_buf, 512)
129 if n_sh <= 0 { return 30 }
130 if s.state != NX_TLS13_SSTATE_SH_SENT { return 31 }
131 // STALE-TEST HEAL 2026-06-10: emit_sh writes record header (5B)
132 // then body; HT_SERVER_HELLO is at offset 5, record type 22 at 0.
133 if sh_buf[0] != (22 as u8) { return 33 } // record: Handshake
134 if sh_buf[5] != 0x02 { return 32 } // HT_SERVER_HELLO
135
136 // ========== STONE 4: derive_hs_secrets ==========
137 let r4: i64 = nx_tls13_server_session_derive_hs_secrets(s)
138 if r4 != NX_TLS13_SSESSION_OK { return 40 }
139 if s.state != NX_TLS13_SSTATE_EE_SENT { return 41 }
140 if (s.handshake_secret as i64) == 0 { return 42 }
141
142 // ========== STONE 5: derive_traffic ==========
143 let r5: i64 = nx_tls13_server_session_derive_traffic(s)
144 if r5 != NX_TLS13_SSESSION_OK { return 50 }
145 if (s.client_hs_traffic_secret as i64) == 0 { return 51 }
146 if (s.server_hs_traffic_secret as i64) == 0 { return 52 }
147 if (s.client_hs_traffic_key as i64) == 0 { return 53 }
148 if (s.server_hs_traffic_key as i64) == 0 { return 54 }
149 if (s.client_hs_iv as i64) == 0 { return 55 }
150 if (s.server_hs_iv as i64) == 0 { return 56 }
151
152 // ========== STONE 6: emit_ee ==========
153 let ee_buf: *u8 = sys_mmap(256)
154 let n_ee: i64 = nx_tls13_server_session_emit_ee(s, ee_buf, 256)
155 if n_ee <= 0 { return 60 }
156 if s.state != NX_TLS13_SSTATE_CERT_SENT { return 61 }
157 if ee_buf[0] != 0x17 { return 62 }
158 if s.server_seq != 1 { return 63 }
159
160 // ========== STONE 6.5: emit_certificate ==========
161 let fake_cert: *u8 = sys_mmap(96)
162 var ci: i64 = 0
163 while ci < 96 {
164 fake_cert[ci] = ((ci + 50) & 0xff) as u8
165 ci = ci + 1
166 }
167 let cert_buf: *u8 = sys_mmap(512)
168 let n_cert: i64 = nx_tls13_server_session_emit_certificate(s, fake_cert, 96, cert_buf, 512)
169 if n_cert <= 0 { return 65 }
170 if s.state != NX_TLS13_SSTATE_CERT_SENT { return 66 } // unchanged
171 if cert_buf[0] != 0x17 { return 67 }
172 if s.server_seq != 2 { return 68 }
173
174 // ========== STONE 7.5: emit_cv ==========
175 let cv_buf: *u8 = sys_mmap(512)
176 let n_cv: i64 = nx_tls13_server_session_emit_cv(s, srv_ecdsa, cv_buf, 512)
177 if n_cv <= 0 { return 70 }
178 if s.state != NX_TLS13_SSTATE_CV_SENT { return 71 }
179 if cv_buf[0] != 0x17 { return 72 }
180 if s.server_seq != 3 { return 73 }
181
182 // ========== STONE 7: emit_sf ==========
183 let sf_buf: *u8 = sys_mmap(256)
184 let n_sf: i64 = nx_tls13_server_session_emit_sf(s, sf_buf, 256)
185 if n_sf <= 0 { return 80 }
186 if s.state != NX_TLS13_SSTATE_SF_SENT { return 81 }
187 if sf_buf[0] != 0x17 { return 82 }
188 if s.server_seq != 4 { return 83 }
189
190 // ========== CONSTRUCT CLIENT FINISHED ==========
191 let finished_label: *u8 = "finished"
192 let empty: *u8 = sys_mmap(1)
193 let finished_key_c: *u8 = sys_mmap(32)
194 tls13_hkdf_expand_label(
195 s.client_hs_traffic_secret,
196 finished_label, 8, empty, 0,
197 32, finished_key_c)
198 let th: *u8 = sys_mmap(32)
199 nx_tls13_transcript_snapshot(s.transcript, th)
200 let verify_data: *u8 = sys_mmap(32)
201 hmac_sha256(finished_key_c, 32, th, 32, verify_data)
202
203 let cf_rec: *u8 = sys_mmap(256)
204 let n_cf: i64 = build_client_finished(
205 s.client_hs_traffic_key, s.client_hs_iv, s.client_seq,
206 verify_data, cf_rec, 256)
207 if n_cf <= 0 { return 90 }
208
209 // ========== STONE 8: recv_cf + derive_app ==========
210 let r8: i64 = nx_tls13_server_session_recv_cf(s, cf_rec, n_cf)
211 if r8 != NX_TLS13_SSESSION_OK { return 100 }
212 if s.state != NX_TLS13_SSTATE_CONNECTED { return 101 }
213 if s.client_seq != 1 { return 102 }
214
215 // App keys derived
216 if (s.master_secret as i64) == 0 { return 110 }
217 if (s.client_app_traffic_secret as i64) == 0 { return 111 }
218 if (s.server_app_traffic_secret as i64) == 0 { return 112 }
219 if (s.client_app_traffic_key as i64) == 0 { return 113 }
220 if (s.server_app_traffic_key as i64) == 0 { return 114 }
221 if (s.client_app_iv as i64) == 0 { return 115 }
222 if (s.server_app_iv as i64) == 0 { return 116 }
223
224 return 0
225}