code wiki / (root) / nx_tls13_handshake_tcp_test.nx

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}