nx_tls13_handshake_tcp_test.nx source
↩ module page · 366 lines · 14479 B
1// nx_tls13_handshake_tcp_test.nx -- full TLS 1.3 client+server
2// handshake driven over real TCP sockets via fork loopback.
3//
4// Same state-machine sequence as nx_tls13_loopback_test (which runs
5// in-process), but each message hop crosses a real kernel socket.
6// Plaintext throughout (the AEAD record-protection layer is a
7// SEPARATE wrap exercised by nx_https_class_loopback_x86_64_smoke).
8//
9// This is the substrate-level proof that the client+server state
10// machines can drive a complete TLS 1.3 handshake to mutual
11// CONNECTED with byte-exact transcripts -- the prerequisite for
12// nx_https_get to make actual TLS calls.
13//
14// expect_exit: 0
15// license_tier: ORIGINAL
16
17import "nx_syscalls.nx"
18import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host
19import "nx_x25519.nx"
20import "nx_tls13.nx"
21import "nx_tls13_ext.nx"
22import "nx_tls13_hello.nx"
23import "nx_tls13_finished.nx"
24import "nx_tls13_transcript.nx"
25import "nx_tls13_handshake.nx"
26import "nx_tls13_schedule.nx"
27import "nx_tls13_client.nx"
28import "nx_tls13_server.nx"
29
30const TEST_PORT: i64 = 19443
31
32// Length-prefixed message framing: send a 4-byte BE length, then payload.
33func send_msg(fd: i64, buf: *u8, n: i64) -> i64 {
34 let hdr: *u8 = sys_mmap(8)
35 hdr[0] = (n >> 24) & 0xff
36 hdr[1] = (n >> 16) & 0xff
37 hdr[2] = (n >> 8) & 0xff
38 hdr[3] = n & 0xff
39 sys_write(fd, hdr, 4)
40 sys_write(fd, buf, n)
41 return n
42}
43
44func recv_msg(fd: i64, buf: *u8, cap: i64) -> i64 {
45 let hdr: *u8 = sys_mmap(8)
46 var got: i64 = 0
47 while got < 4 {
48 let r: i64 = sys_read(fd, hdr + got, 4 - got)
49 if r <= 0 { return 0 - 1 }
50 got = got + r
51 }
52 let n: i64 = ((hdr[0] & 0xff) << 24) | ((hdr[1] & 0xff) << 16)
53 | ((hdr[2] & 0xff) << 8) | (hdr[3] & 0xff)
54 if n > cap { return 0 - 2 }
55 got = 0
56 while got < n {
57 let r: i64 = sys_read(fd, buf + got, n - got)
58 if r <= 0 { return 0 - 3 }
59 got = got + r
60 }
61 return n
62}
63
64// Build an IPv4 sockaddr: family=2, port BE, addr 127.0.0.1, 8 zero bytes.
65func build_addr(out: *u8, port: i64) -> i64 {
66 out[0] = 2; out[1] = 0
67 out[2] = (port >> 8) & 0xff
68 out[3] = port & 0xff
69 out[4] = 127; out[5] = 0; out[6] = 0; out[7] = 1
70 var i: i64 = 8
71 while i < 16 { out[i] = 0; i = i + 1 }
72 return 16
73}
74
75func main() -> i64 {
76 let addr: *u8 = sys_mmap(16)
77 build_addr(addr, TEST_PORT)
78
79 let lfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
80 if lfd < 0 { return 1 }
81 if sys_bind(lfd, addr, 16) < 0 { return 2 }
82 if sys_listen(lfd, 4) < 0 { return 3 }
83
84 let pid: i64 = sys_fork()
85 if pid < 0 { return 4 }
86
87 if pid == 0 {
88 // ================== CLIENT ==================
89 // Spin briefly so parent reaches accept()
90 var spin: i64 = 0
91 while spin < 200000 { spin = spin + 1 }
92 let cfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
93 if cfd < 0 { return 10 }
94 if nx_connect_bounded(cfd, addr, 16, NX_CONN_DEFAULT_MS) < 0 { return 11 }
95
96 // Client X25519 keypair (RFC 8448 §3 client priv)
97 let c_priv: *u8 = sys_mmap(64)
98 c_priv[0]=0x49; c_priv[1]=0xaf; c_priv[2]=0x42; c_priv[3]=0xba
99 c_priv[4]=0x7f; c_priv[5]=0x99; c_priv[6]=0x94; c_priv[7]=0x85
100 c_priv[8]=0x2d; c_priv[9]=0x71; c_priv[10]=0x3e; c_priv[11]=0xf2
101 c_priv[12]=0x78; c_priv[13]=0x4b; c_priv[14]=0xcb; c_priv[15]=0xca
102 c_priv[16]=0xa7; c_priv[17]=0x91; c_priv[18]=0x1d; c_priv[19]=0xe2
103 c_priv[20]=0x6a; c_priv[21]=0xdc; c_priv[22]=0x56; c_priv[23]=0x42
104 c_priv[24]=0xcb; c_priv[25]=0x63; c_priv[26]=0x45; c_priv[27]=0x40
105 c_priv[28]=0xe7; c_priv[29]=0xea; c_priv[30]=0x50; c_priv[31]=0x05
106 let base: *u8 = sys_mmap(64)
107 base[0] = 9
108 var bi: i64 = 1
109 while bi < 32 { base[bi] = 0; bi = bi + 1 }
110 let c_pub: *u8 = sys_mmap(64)
111 x25519(c_priv, base, c_pub)
112
113 // Build + send ClientHello
114 let c_random: *u8 = sys_mmap(64)
115 var i: i64 = 0
116 while i < 32 { c_random[i] = 0xc0 + i; i = i + 1 }
117 let sni: *u8 = sys_mmap(16)
118 sni[0]=0x65; sni[1]=0x78; sni[2]=0x61; sni[3]=0x6d
119 sni[4]=0x70; sni[5]=0x6c; sni[6]=0x65; sni[7]=0x2e
120 sni[8]=0x63; sni[9]=0x6f; sni[10]=0x6d
121 let ch: *u8 = sys_mmap(1024)
122 let ch_len: i64 = tls13_client_hello_emit(c_random, sni, 11, c_pub, ch, 1024)
123 if ch_len < 0 { return 12 }
124 send_msg(cfd, ch, ch_len)
125
126 // Recv ServerHello
127 let sh: *u8 = sys_mmap(1024)
128 let sh_len: i64 = recv_msg(cfd, sh, 1024)
129 if sh_len < 0 { return 13 }
130
131 // Parse SH to recover server's pubkey
132 let p_lv: *i64 = sys_mmap(16) as *i64
133 let p_ro: *i64 = sys_mmap(16) as *i64
134 let p_cs: *i64 = sys_mmap(16) as *i64
135 let p_eo: *i64 = sys_mmap(16) as *i64
136 let p_el: *i64 = sys_mmap(16) as *i64
137 let pv: i64 = tls13_server_hello_parse(sh, sh_len, p_lv, p_ro, p_cs, p_eo, p_el)
138 if pv != NX_TLS13_HELLO_VERDICT_OK { return 14 }
139 // key_share data: group(2) + ke_len(2) + ke(32) -> pubkey starts at +4
140 let ks_off: *i64 = sys_mmap(16) as *i64
141 let ks_len: *i64 = sys_mmap(16) as *i64
142 let fv: i64 = tls13_ext_find(sh + (*p_eo), *p_el, EXT_KEY_SHARE, ks_off, ks_len)
143 if fv != NX_TLS13_HELLO_VERDICT_OK { return 15 }
144 let s_pub_recovered: *u8 = sh + (*p_eo) + (*ks_off) + 4
145
146 // Build transcript over CH + SH
147 let c_tx: *u8 = nx_tls13_transcript_new()
148 nx_tls13_transcript_update(c_tx, ch, ch_len)
149 nx_tls13_transcript_update(c_tx, sh, sh_len)
150 let c_th: *u8 = sys_mmap(64)
151 nx_tls13_transcript_snapshot(c_tx, c_th)
152
153 // Derive keys via orchestrator (uses X25519 internally)
154 let empty_hash: *u8 = sys_mmap(64)
155 empty_hash[0]=0xe3; empty_hash[1]=0xb0; empty_hash[2]=0xc4; empty_hash[3]=0x42
156 empty_hash[4]=0x98; empty_hash[5]=0xfc; empty_hash[6]=0x1c; empty_hash[7]=0x14
157 empty_hash[8]=0x9a; empty_hash[9]=0xfb; empty_hash[10]=0xf4; empty_hash[11]=0xc8
158 empty_hash[12]=0x99; empty_hash[13]=0x6f; empty_hash[14]=0xb9; empty_hash[15]=0x24
159 empty_hash[16]=0x27; empty_hash[17]=0xae; empty_hash[18]=0x41; empty_hash[19]=0xe4
160 empty_hash[20]=0x64; empty_hash[21]=0x9b; empty_hash[22]=0x93; empty_hash[23]=0x4c
161 empty_hash[24]=0xa4; empty_hash[25]=0x95; empty_hash[26]=0x99; empty_hash[27]=0x1b
162 empty_hash[28]=0x78; empty_hash[29]=0x52; empty_hash[30]=0xb8; empty_hash[31]=0x55
163
164 let c_hs: *u8 = sys_mmap(64)
165 let c_chts: *u8 = sys_mmap(64)
166 let c_shts: *u8 = sys_mmap(64)
167 let c_ck: *u8 = sys_mmap(64)
168 let c_civ: *u8 = sys_mmap(64)
169 let c_sk: *u8 = sys_mmap(64)
170 let c_siv: *u8 = sys_mmap(64)
171 tls13_handshake_compute_handshake_keys(
172 c_priv, s_pub_recovered, c_th, empty_hash,
173 c_hs, c_chts, c_shts, c_ck, c_civ, c_sk, c_siv
174 )
175
176 // Recv EE, Cert, CV, SF; dispatch each
177 let c_state: *i64 = sys_mmap(16) as *i64
178 *c_state = NX_TLS13_CSTATE_WAIT_EE
179 let c_out: *i64 = sys_mmap(16) as *i64
180
181 let buf: *u8 = sys_mmap(1024)
182 let n1: i64 = recv_msg(cfd, buf, 1024)
183 if n1 < 0 { return 20 }
184 if tls13_client_dispatch_handshake_message(*c_state, buf, n1, c_shts, c_tx, c_out) != NX_TLS13_CLIENT_VERDICT_OK { return 21 }
185 *c_state = *c_out
186
187 let n2: i64 = recv_msg(cfd, buf, 1024)
188 if n2 < 0 { return 22 }
189 if tls13_client_dispatch_handshake_message(*c_state, buf, n2, c_shts, c_tx, c_out) != NX_TLS13_CLIENT_VERDICT_OK { return 23 }
190 *c_state = *c_out
191
192 let n3: i64 = recv_msg(cfd, buf, 1024)
193 if n3 < 0 { return 24 }
194 if tls13_client_dispatch_handshake_message(*c_state, buf, n3, c_shts, c_tx, c_out) != NX_TLS13_CLIENT_VERDICT_OK { return 25 }
195 *c_state = *c_out
196
197 let n4: i64 = recv_msg(cfd, buf, 1024)
198 if n4 < 0 { return 26 }
199 if tls13_client_dispatch_handshake_message(*c_state, buf, n4, c_shts, c_tx, c_out) != NX_TLS13_CLIENT_VERDICT_OK { return 27 }
200 *c_state = *c_out
201 if *c_state != NX_TLS13_CSTATE_CONNECTED { return 28 }
202
203 // Emit and send Finished
204 let cf: *u8 = sys_mmap(64)
205 let cf_len: i64 = tls13_client_emit_finished(c_chts, c_tx, cf)
206 if cf_len != 36 { return 29 }
207 send_msg(cfd, cf, cf_len)
208
209 // Recv ACK byte from server (0 = handshake-complete-confirmed)
210 let ack: *u8 = sys_mmap(8)
211 let ar: i64 = sys_read(cfd, ack, 1)
212 if ar != 1 { return 30 }
213 if (ack[0] & 0xff) != 0x00 { return 31 }
214 sys_exit(0)
215 }
216
217 // ================== SERVER ==================
218 let cfd: i64 = sys_accept(lfd)
219 if cfd < 0 { return 5 }
220
221 // Server X25519 keypair (RFC 8448 §3 server priv)
222 let s_priv: *u8 = sys_mmap(64)
223 s_priv[0]=0xb1; s_priv[1]=0x58; s_priv[2]=0x0e; s_priv[3]=0xea
224 s_priv[4]=0xdf; s_priv[5]=0x6d; s_priv[6]=0xd5; s_priv[7]=0x89
225 s_priv[8]=0xb8; s_priv[9]=0xef; s_priv[10]=0x4f; s_priv[11]=0x2d
226 s_priv[12]=0x56; s_priv[13]=0x52; s_priv[14]=0x57; s_priv[15]=0x8c
227 s_priv[16]=0xc8; s_priv[17]=0x10; s_priv[18]=0xe9; s_priv[19]=0x98
228 s_priv[20]=0x01; s_priv[21]=0x91; s_priv[22]=0xec; s_priv[23]=0x8d
229 s_priv[24]=0x05; s_priv[25]=0x83; s_priv[26]=0x08; s_priv[27]=0xce
230 s_priv[28]=0xa2; s_priv[29]=0x16; s_priv[30]=0xa2; s_priv[31]=0x1e
231 let base2: *u8 = sys_mmap(64)
232 base2[0] = 9
233 var bbi: i64 = 1
234 while bbi < 32 { base2[bbi] = 0; bbi = bbi + 1 }
235 let s_pub: *u8 = sys_mmap(64)
236 x25519(s_priv, base2, s_pub)
237
238 // Recv + parse ClientHello
239 let ch: *u8 = sys_mmap(1024)
240 let ch_len: i64 = recv_msg(cfd, ch, 1024)
241 if ch_len < 0 { return 50 }
242
243 let p_ro: *i64 = sys_mmap(16) as *i64
244 let p_so: *i64 = sys_mmap(16) as *i64
245 let p_sl: *i64 = sys_mmap(16) as *i64
246 let p_eo: *i64 = sys_mmap(16) as *i64
247 let p_el: *i64 = sys_mmap(16) as *i64
248 let psv: i64 = tls13_server_parse_client_hello(ch, ch_len, p_ro, p_so, p_sl, p_eo, p_el)
249 if psv != NX_TLS13_SERVER_VERDICT_OK { return 51 }
250
251 let ks_off: *i64 = sys_mmap(16) as *i64
252 let ks_len: *i64 = sys_mmap(16) as *i64
253 let fv: i64 = tls13_ext_find(ch + (*p_eo), *p_el, EXT_KEY_SHARE, ks_off, ks_len)
254 if fv != NX_TLS13_HELLO_VERDICT_OK { return 52 }
255 let recovered_c_pub: *u8 = ch + (*p_eo) + (*ks_off) + 6
256
257 // Build + send ServerHello
258 let s_random: *u8 = sys_mmap(64)
259 var ri: i64 = 0
260 while ri < 32 { s_random[ri] = 0x70 + ri; ri = ri + 1 }
261 let sh: *u8 = sys_mmap(512)
262 let sh_len: i64 = tls13_server_emit_server_hello(s_random, ch + (*p_so), *p_sl, s_pub, sh, 512)
263 if sh_len < 0 { return 53 }
264 send_msg(cfd, sh, sh_len)
265
266 // Transcript over CH + SH
267 let s_tx: *u8 = nx_tls13_transcript_new()
268 nx_tls13_transcript_update(s_tx, ch, ch_len)
269 nx_tls13_transcript_update(s_tx, sh, sh_len)
270 let s_th: *u8 = sys_mmap(64)
271 nx_tls13_transcript_snapshot(s_tx, s_th)
272
273 let empty_hash: *u8 = sys_mmap(64)
274 empty_hash[0]=0xe3; empty_hash[1]=0xb0; empty_hash[2]=0xc4; empty_hash[3]=0x42
275 empty_hash[4]=0x98; empty_hash[5]=0xfc; empty_hash[6]=0x1c; empty_hash[7]=0x14
276 empty_hash[8]=0x9a; empty_hash[9]=0xfb; empty_hash[10]=0xf4; empty_hash[11]=0xc8
277 empty_hash[12]=0x99; empty_hash[13]=0x6f; empty_hash[14]=0xb9; empty_hash[15]=0x24
278 empty_hash[16]=0x27; empty_hash[17]=0xae; empty_hash[18]=0x41; empty_hash[19]=0xe4
279 empty_hash[20]=0x64; empty_hash[21]=0x9b; empty_hash[22]=0x93; empty_hash[23]=0x4c
280 empty_hash[24]=0xa4; empty_hash[25]=0x95; empty_hash[26]=0x99; empty_hash[27]=0x1b
281 empty_hash[28]=0x78; empty_hash[29]=0x52; empty_hash[30]=0xb8; empty_hash[31]=0x55
282
283 let s_hs: *u8 = sys_mmap(64)
284 let s_chts: *u8 = sys_mmap(64)
285 let s_shts: *u8 = sys_mmap(64)
286 let s_ck: *u8 = sys_mmap(64)
287 let s_civ: *u8 = sys_mmap(64)
288 let s_sk: *u8 = sys_mmap(64)
289 let s_siv: *u8 = sys_mmap(64)
290 tls13_handshake_compute_handshake_keys(
291 s_priv, recovered_c_pub, s_th, empty_hash,
292 s_hs, s_chts, s_shts, s_ck, s_civ, s_sk, s_siv
293 )
294
295 // Build EE/Cert/CV/SF identical to loopback_test (canned)
296 let ee: *u8 = sys_mmap(64)
297 ee[0] = HT_ENCRYPTED_EXTENSIONS & 0xff
298 ee[1]=0; ee[2]=0; ee[3]=2
299 ee[4]=0; ee[5]=0
300 let ee_len: i64 = 6
301
302 let cert: *u8 = sys_mmap(64)
303 cert[0] = HT_CERTIFICATE & 0xff
304 cert[1]=0; cert[2]=0; cert[3]=19
305 cert[4]=0
306 cert[5]=0; cert[6]=0; cert[7]=15
307 cert[8]=0; cert[9]=0; cert[10]=10
308 var ci: i64 = 0
309 while ci < 10 { cert[11+ci] = 0x30+ci; ci = ci + 1 }
310 cert[21]=0; cert[22]=0
311 let cert_len: i64 = 23
312
313 let cv: *u8 = sys_mmap(128)
314 cv[0] = HT_CERTIFICATE_VERIFY & 0xff
315 cv[1]=0; cv[2]=0; cv[3]=68
316 cv[4]=0x08; cv[5]=0x07
317 cv[6]=0; cv[7]=64
318 var cvi: i64 = 0
319 while cvi < 64 { cv[8+cvi] = 0x90 + (cvi & 0x0f); cvi = cvi + 1 }
320 let cv_len: i64 = 72
321
322 nx_tls13_transcript_update(s_tx, ee, ee_len)
323 nx_tls13_transcript_update(s_tx, cert, cert_len)
324 nx_tls13_transcript_update(s_tx, cv, cv_len)
325
326 let s_th_pre_sf: *u8 = sys_mmap(64)
327 nx_tls13_transcript_snapshot(s_tx, s_th_pre_sf)
328 let s_fk: *u8 = sys_mmap(64)
329 tls13_finished_key(s_shts, 32, s_fk)
330 let server_mac: *u8 = sys_mmap(64)
331 nx_tls13_finished_compute(s_fk, 32, s_th_pre_sf, 32, server_mac)
332 let sf: *u8 = sys_mmap(64)
333 sf[0] = HT_FINISHED & 0xff
334 sf[1]=0; sf[2]=0; sf[3]=32
335 var fi: i64 = 0
336 while fi < 32 { sf[4+fi] = server_mac[fi]; fi = fi + 1 }
337 let sf_len: i64 = 36
338
339 nx_tls13_transcript_update(s_tx, sf, sf_len)
340
341 // Send EE, Cert, CV, SF as four messages
342 send_msg(cfd, ee, ee_len)
343 send_msg(cfd, cert, cert_len)
344 send_msg(cfd, cv, cv_len)
345 send_msg(cfd, sf, sf_len)
346
347 // Recv client Finished
348 let cf: *u8 = sys_mmap(64)
349 let cf_len: i64 = recv_msg(cfd, cf, 64)
350 if cf_len < 0 { return 60 }
351
352 let s_out: *i64 = sys_mmap(16) as *i64
353 let v5: i64 = tls13_server_dispatch_client_finished(cf, cf_len, s_chts, s_tx, s_out)
354 if v5 != NX_TLS13_SERVER_VERDICT_OK { return 61 }
355 if *s_out != NX_TLS13_SSTATE_CONNECTED { return 62 }
356
357 // Send ACK
358 let ack: *u8 = sys_mmap(8)
359 ack[0] = 0
360 sys_write(cfd, ack, 1)
361
362 // Wait for child
363 let status: *i64 = sys_mmap(8) as *i64
364 sys_wait4(pid, status, 0)
365 return wait_exit_code(*status)
366}