code wiki / (root) / nx_https_loopback_test.nx

nx_https_loopback_test.nx source

↩ module page · 570 lines · 20511 B

1// nx_https_loopback_test.nx -- HTTPS-class fork loopback over real 2// TCP that does the FULL TLS 1.3 handshake AND exchanges an HTTP/1.1 3// GET / 200 OK pair as AEAD-encrypted records inside the established 4// session. 5// 6// This is the "browser substrate" end-to-end smoke: every byte on 7// the wire is bit-identical to what real HTTPS produces (handshake 8// + cipher records). Only the cert chain validation is stubbed 9// (server's hand-built cert/cv blobs accepted unconditionally). 10// 11// Built per F6 friction-catalog discipline. 12// 13// expect_exit: 0 14// license_tier: ORIGINAL 15 16import "nx_syscalls.nx" 17import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host 18import "nx_x25519.nx" 19import "nx_tls13.nx" 20import "nx_tls13_ext.nx" 21import "nx_tls13_hello.nx" 22import "nx_tls13_finished.nx" 23import "nx_tls13_transcript.nx" 24import "nx_tls13_handshake.nx" 25import "nx_tls13_schedule.nx" 26import "nx_tls13_client.nx" 27import "nx_tls13_server.nx" 28import "nx_tls13_record.nx" 29 30const HPORT: i64 = 19447 31 32// ---- low-level frame helpers (same as nx_tls13_full_tcp) ---- 33 34func hbuild_addr(out: *u8, port: i64) -> i64 { 35 out[0] = 2; out[1] = 0 36 out[2] = (port >> 8) & 0xff 37 out[3] = port & 0xff 38 out[4] = 127; out[5] = 0; out[6] = 0; out[7] = 1 39 var i: i64 = 8 40 while i < 16 { out[i] = 0; i = i + 1 } 41 return 16 42} 43 44func hread_n(fd: i64, buf: *u8, n: i64) -> i64 { 45 var got: i64 = 0 46 while got < n { 47 let r: i64 = sys_read(fd, buf + got, n - got) 48 if r <= 0 { return 0 - 1 } 49 got = got + r 50 } 51 return got 52} 53 54func hsend_plain(fd: i64, buf: *u8, n: i64) -> i64 { 55 let hdr: *u8 = sys_mmap(8) 56 hdr[0] = (n >> 24) & 0xff 57 hdr[1] = (n >> 16) & 0xff 58 hdr[2] = (n >> 8) & 0xff 59 hdr[3] = n & 0xff 60 sys_write(fd, hdr, 4) 61 sys_write(fd, buf, n) 62 return n 63} 64 65func hrecv_plain(fd: i64, buf: *u8, cap: i64) -> i64 { 66 let hdr: *u8 = sys_mmap(8) 67 if hread_n(fd, hdr, 4) < 0 { return 0 - 1 } 68 let n: i64 = ((hdr[0] & 0xff) << 24) | ((hdr[1] & 0xff) << 16) | ((hdr[2] & 0xff) << 8) | (hdr[3] & 0xff) 69 if n > cap { return 0 - 2 } 70 if hread_n(fd, buf, n) < 0 { return 0 - 3 } 71 return n 72} 73 74// Send/recv AEAD app-data record (inner type=23 = application_data). 75func hsend_app(fd: i64, key: *u8, iv: *u8, seq: i64, p: *u8, plen: i64) -> i64 { 76 let hdr: *u8 = sys_mmap(16) 77 let ct: *u8 = sys_mmap(plen + 64) 78 let tag: *u8 = sys_mmap(16) 79 let vrd: i64 = nx_tls13_record_encrypt(key, iv, seq, p, plen, 23, 0, hdr, ct, tag) 80 if vrd != NX_TLS13_REC_VERDICT_OK { return 0 - 1 } 81 sys_write(fd, hdr, 5) 82 sys_write(fd, ct, plen + 1) 83 sys_write(fd, tag, 16) 84 return 0 85} 86 87func hrecv_app(fd: i64, key: *u8, iv: *u8, seq: i64, out: *u8, out_cap: i64) -> i64 { 88 let hdr: *u8 = sys_mmap(16) 89 if hread_n(fd, hdr, 5) < 0 { return 0 - 1 } 90 let total: i64 = ((hdr[3] & 0xff) << 8) | (hdr[4] & 0xff) 91 if total < 17 { return 0 - 2 } 92 let ct_len: i64 = total - 16 93 let buf: *u8 = sys_mmap(total + 16) 94 if hread_n(fd, buf, total) < 0 { return 0 - 3 } 95 let tag: *u8 = sys_mmap(16) 96 var ti: i64 = 0 97 while ti < 16 { tag[ti] = buf[ct_len + ti]; ti = ti + 1 } 98 let rct: *i64 = sys_mmap(8) as *i64 99 let rln: *i64 = sys_mmap(8) as *i64 100 let vrd: i64 = nx_tls13_record_decrypt(key, iv, seq, hdr, buf, ct_len, tag, out, rct, rln) 101 if vrd != NX_TLS13_REC_VERDICT_OK { return 0 - 4 } 102 return rln[0] 103} 104 105// Same handshake-type AEAD send/recv as full_tcp (inner type=22). 106func hsend_aead(fd: i64, key: *u8, iv: *u8, seq: i64, p: *u8, plen: i64) -> i64 { 107 let hdr: *u8 = sys_mmap(16) 108 let ct: *u8 = sys_mmap(plen + 64) 109 let tag: *u8 = sys_mmap(16) 110 let vrd: i64 = nx_tls13_record_encrypt(key, iv, seq, p, plen, 22, 0, hdr, ct, tag) 111 if vrd != NX_TLS13_REC_VERDICT_OK { return 0 - 1 } 112 sys_write(fd, hdr, 5) 113 sys_write(fd, ct, plen + 1) 114 sys_write(fd, tag, 16) 115 return 0 116} 117 118func hrecv_aead(fd: i64, key: *u8, iv: *u8, seq: i64, out: *u8, out_cap: i64) -> i64 { 119 let hdr: *u8 = sys_mmap(16) 120 if hread_n(fd, hdr, 5) < 0 { return 0 - 1 } 121 let total: i64 = ((hdr[3] & 0xff) << 8) | (hdr[4] & 0xff) 122 if total < 17 { return 0 - 2 } 123 let ct_len: i64 = total - 16 124 let buf: *u8 = sys_mmap(total + 16) 125 if hread_n(fd, buf, total) < 0 { return 0 - 3 } 126 let tag: *u8 = sys_mmap(16) 127 var ti: i64 = 0 128 while ti < 16 { tag[ti] = buf[ct_len + ti]; ti = ti + 1 } 129 let rct: *i64 = sys_mmap(8) as *i64 130 let rln: *i64 = sys_mmap(8) as *i64 131 let vrd: i64 = nx_tls13_record_decrypt(key, iv, seq, hdr, buf, ct_len, tag, out, rct, rln) 132 if vrd != NX_TLS13_REC_VERDICT_OK { return 0 - 4 } 133 return rln[0] 134} 135 136// ---- bundle + setup helpers ---- 137 138func halloc_bundle() -> *u8 { 139 let bundle: *u8 = sys_mmap(64) 140 let bp: *i64 = bundle as *i64 141 var i: i64 = 0 142 while i < 7 { 143 let buf: *u8 = sys_mmap(64) 144 bp[i] = buf as i64 145 i = i + 1 146 } 147 return bundle 148} 149 150func hbundle_ptr(bundle: *u8, slot: i64) -> *u8 { 151 let bp: *i64 = bundle as *i64 152 return bp[slot] as *u8 153} 154 155func hsetup_keypair(priv: *u8, pub: *u8) -> i64 { 156 let base: *u8 = sys_mmap(64) 157 base[0] = 9 158 var bi: i64 = 1 159 while bi < 32 { base[bi] = 0; bi = bi + 1 } 160 x25519(priv, base, pub) 161 return 0 162} 163 164// Deterministic 32-byte fill from base byte; X25519 private keys use 165// the upper 5 bits cleared / bit 254 set RFC 7748 clamp, applied by 166// the X25519 layer -- any 32 bytes are valid input. 167func hfill_priv(out: *u8, base: i64) -> i64 { 168 var i: i64 = 0 169 while i < 32 { out[i] = (base + i * 3) & 0xff; i = i + 1 } 170 return 32 171} 172 173func hfill_empty_hash(out: *u8) -> i64 { 174 out[0]=0xe3; out[1]=0xb0; out[2]=0xc4; out[3]=0x42 175 out[4]=0x98; out[5]=0xfc; out[6]=0x1c; out[7]=0x14 176 out[8]=0x9a; out[9]=0xfb; out[10]=0xf4; out[11]=0xc8 177 out[12]=0x99; out[13]=0x6f; out[14]=0xb9; out[15]=0x24 178 out[16]=0x27; out[17]=0xae; out[18]=0x41; out[19]=0xe4 179 out[20]=0x64; out[21]=0x9b; out[22]=0x93; out[23]=0x4c 180 out[24]=0xa4; out[25]=0x95; out[26]=0x99; out[27]=0x1b 181 out[28]=0x78; out[29]=0x52; out[30]=0xb8; out[31]=0x55 182 return 32 183} 184 185func hfill_random(out: *u8, base: i64) -> i64 { 186 var i: i64 = 0 187 while i < 32 { out[i] = (base + i) & 0xff; i = i + 1 } 188 return 32 189} 190 191func hderive_keys(my_priv: *u8, peer_pub: *u8, th: *u8, eh: *u8, bundle: *u8) -> i64 { 192 let hs: *u8 = hbundle_ptr(bundle, 0) 193 let chts: *u8 = hbundle_ptr(bundle, 1) 194 let shts: *u8 = hbundle_ptr(bundle, 2) 195 let ck: *u8 = hbundle_ptr(bundle, 3) 196 let civ: *u8 = hbundle_ptr(bundle, 4) 197 let sk: *u8 = hbundle_ptr(bundle, 5) 198 let siv: *u8 = hbundle_ptr(bundle, 6) 199 tls13_handshake_compute_handshake_keys(my_priv, peer_pub, th, eh, hs, chts, shts, ck, civ, sk, siv) 200 return 0 201} 202 203func hemit_send_ch(fd: i64, c_pub: *u8, ch_out: *u8, ch_cap: i64) -> i64 { 204 let c_random: *u8 = sys_mmap(64) 205 hfill_random(c_random, 0xc0) 206 let sni: *u8 = sys_mmap(16) 207 sni[0]=0x65; sni[1]=0x78; sni[2]=0x61; sni[3]=0x6d 208 sni[4]=0x70; sni[5]=0x6c; sni[6]=0x65; sni[7]=0x2e 209 sni[8]=0x63; sni[9]=0x6f; sni[10]=0x6d 210 let n: i64 = tls13_client_hello_emit(c_random, sni, 11, c_pub, ch_out, ch_cap) 211 if n < 0 { return n } 212 hsend_plain(fd, ch_out, n) 213 return n 214} 215 216func hparse_sh_get_pub(sh: *u8, sh_len: i64, pub_out: *i64) -> i64 { 217 let p_lv: *i64 = sys_mmap(16) as *i64 218 let p_ro: *i64 = sys_mmap(16) as *i64 219 let p_cs: *i64 = sys_mmap(16) as *i64 220 let p_eo: *i64 = sys_mmap(16) as *i64 221 let p_el: *i64 = sys_mmap(16) as *i64 222 let pv: i64 = tls13_server_hello_parse(sh, sh_len, p_lv, p_ro, p_cs, p_eo, p_el) 223 if pv != NX_TLS13_HELLO_VERDICT_OK { return pv } 224 let ks_off: *i64 = sys_mmap(16) as *i64 225 let ks_len: *i64 = sys_mmap(16) as *i64 226 let fv: i64 = tls13_ext_find(sh + p_eo[0], p_el[0], EXT_KEY_SHARE, ks_off, ks_len) 227 if fv != NX_TLS13_HELLO_VERDICT_OK { return fv } 228 pub_out[0] = ((sh as i64) + p_eo[0] + ks_off[0] + 4) 229 return 0 230} 231 232func hparse_ch_get_pub(ch: *u8, ch_len: i64, sid_o: *i64, sid_l: *i64, pub_out: *i64) -> i64 { 233 let p_ro: *i64 = sys_mmap(16) as *i64 234 let p_eo: *i64 = sys_mmap(16) as *i64 235 let p_el: *i64 = sys_mmap(16) as *i64 236 let pv: i64 = tls13_server_parse_client_hello(ch, ch_len, p_ro, sid_o, sid_l, p_eo, p_el) 237 if pv != NX_TLS13_SERVER_VERDICT_OK { return pv } 238 let ks_off: *i64 = sys_mmap(16) as *i64 239 let ks_len: *i64 = sys_mmap(16) as *i64 240 let fv: i64 = tls13_ext_find(ch + p_eo[0], p_el[0], EXT_KEY_SHARE, ks_off, ks_len) 241 if fv != NX_TLS13_HELLO_VERDICT_OK { return fv } 242 pub_out[0] = ((ch as i64) + p_eo[0] + ks_off[0] + 6) 243 return 0 244} 245 246func hbuild_th(ch: *u8, ch_len: i64, sh: *u8, sh_len: i64, th_out: *u8, tx_out: *i64) -> i64 { 247 let tx: *u8 = nx_tls13_transcript_new() 248 nx_tls13_transcript_update(tx, ch, ch_len) 249 nx_tls13_transcript_update(tx, sh, sh_len) 250 nx_tls13_transcript_snapshot(tx, th_out) 251 tx_out[0] = tx as i64 252 return 0 253} 254 255func haead_dispatch(fd: i64, key: *u8, iv: *u8, seq: i64, st: i64, shts: *u8, tx: *u8) -> i64 { 256 let buf: *u8 = sys_mmap(1024) 257 let n: i64 = hrecv_aead(fd, key, iv, seq, buf, 1024) 258 if n < 0 { return n } 259 let c_out: *i64 = sys_mmap(16) as *i64 260 let vrd: i64 = tls13_client_dispatch_handshake_message(st, buf, n, shts, tx, c_out) 261 if vrd != NX_TLS13_CLIENT_VERDICT_OK { return 0 - 100 } 262 return c_out[0] 263} 264 265// ---- canned EE/Cert/CV + SF compute (same as full_tcp) ---- 266 267func hbuild_canned(ee: *u8, cert: *u8, cv: *u8) -> i64 { 268 ee[0] = HT_ENCRYPTED_EXTENSIONS & 0xff 269 ee[1]=0; ee[2]=0; ee[3]=2; ee[4]=0; ee[5]=0 270 271 cert[0] = HT_CERTIFICATE & 0xff 272 cert[1]=0; cert[2]=0; cert[3]=19 273 cert[4]=0; cert[5]=0; cert[6]=0; cert[7]=15 274 cert[8]=0; cert[9]=0; cert[10]=10 275 var i: i64 = 0 276 while i < 10 { cert[11+i] = 0x30+i; i = i + 1 } 277 cert[21]=0; cert[22]=0 278 279 cv[0] = HT_CERTIFICATE_VERIFY & 0xff 280 cv[1]=0; cv[2]=0; cv[3]=68 281 cv[4]=0x08; cv[5]=0x07 282 cv[6]=0; cv[7]=64 283 var j: i64 = 0 284 while j < 64 { cv[8+j] = 0x90 + (j & 0x0f); j = j + 1 } 285 return 0 286} 287 288func hcompute_sf(tx: *u8, shts: *u8, sf_out: *u8) -> i64 { 289 let pre: *u8 = sys_mmap(64) 290 nx_tls13_transcript_snapshot(tx, pre) 291 let fk: *u8 = sys_mmap(64) 292 tls13_finished_key(shts, 32, fk) 293 let mac: *u8 = sys_mmap(64) 294 nx_tls13_finished_compute(fk, 32, pre, 32, mac) 295 sf_out[0] = HT_FINISHED & 0xff 296 sf_out[1]=0; sf_out[2]=0; sf_out[3]=32 297 var i: i64 = 0 298 while i < 32 { sf_out[4+i] = mac[i]; i = i + 1 } 299 return 36 300} 301 302func hserver_send_flight(fd: i64, bundle: *u8, tx: *u8) -> i64 { 303 let sk: *u8 = hbundle_ptr(bundle, 5) 304 let siv: *u8 = hbundle_ptr(bundle, 6) 305 let shts: *u8 = hbundle_ptr(bundle, 2) 306 307 let ee: *u8 = sys_mmap(64) 308 let cert: *u8 = sys_mmap(64) 309 let cv: *u8 = sys_mmap(128) 310 hbuild_canned(ee, cert, cv) 311 nx_tls13_transcript_update(tx, ee, 6) 312 nx_tls13_transcript_update(tx, cert, 23) 313 nx_tls13_transcript_update(tx, cv, 72) 314 315 let sf: *u8 = sys_mmap(64) 316 let sf_len: i64 = hcompute_sf(tx, shts, sf) 317 nx_tls13_transcript_update(tx, sf, sf_len) 318 319 if hsend_aead(fd, sk, siv, 0, ee, 6) != 0 { return 80 } 320 if hsend_aead(fd, sk, siv, 1, cert, 23) != 0 { return 81 } 321 if hsend_aead(fd, sk, siv, 2, cv, 72) != 0 { return 82 } 322 if hsend_aead(fd, sk, siv, 3, sf, 36) != 0 { return 83 } 323 return 0 324} 325 326func hserver_recv_cf(fd: i64, bundle: *u8, tx: *u8) -> i64 { 327 let ck: *u8 = hbundle_ptr(bundle, 3) 328 let civ: *u8 = hbundle_ptr(bundle, 4) 329 let chts: *u8 = hbundle_ptr(bundle, 1) 330 let cf: *u8 = sys_mmap(64) 331 let n: i64 = hrecv_aead(fd, ck, civ, 0, cf, 64) 332 if n != 36 { return 90 } 333 let s_out: *i64 = sys_mmap(16) as *i64 334 let vrd: i64 = tls13_server_dispatch_client_finished(cf, n, chts, tx, s_out) 335 if vrd != NX_TLS13_SERVER_VERDICT_OK { return 91 } 336 if s_out[0] != NX_TLS13_SSTATE_CONNECTED { return 92 } 337 return 0 338} 339 340// ---- HTTP exchange after handshake ---- 341 342func hbuild_http_get(out: *u8) -> i64 { 343 out[0]=0x47; out[1]=0x45; out[2]=0x54; out[3]=0x20 // GET 344 out[4]=0x2f; out[5]=0x20 // / 345 out[6]=0x48; out[7]=0x54; out[8]=0x54; out[9]=0x50 // HTTP 346 out[10]=0x2f; out[11]=0x31; out[12]=0x2e; out[13]=0x31 // /1.1 347 out[14]=0x0d; out[15]=0x0a // \r\n 348 out[16]=0x48; out[17]=0x6f; out[18]=0x73; out[19]=0x74 // Host 349 out[20]=0x3a; out[21]=0x20 // : 350 out[22]=0x6c; out[23]=0x6f; out[24]=0x63; out[25]=0x61 // loca 351 out[26]=0x6c; out[27]=0x68; out[28]=0x6f; out[29]=0x73 // lhos 352 out[30]=0x74 // t 353 out[31]=0x0d; out[32]=0x0a; out[33]=0x0d; out[34]=0x0a // \r\n\r\n 354 return 35 355} 356 357func hbuild_http_200(out: *u8) -> i64 { 358 out[0]=0x48; out[1]=0x54; out[2]=0x54; out[3]=0x50 359 out[4]=0x2f; out[5]=0x31; out[6]=0x2e; out[7]=0x31 360 out[8]=0x20; out[9]=0x32; out[10]=0x30; out[11]=0x30 361 out[12]=0x20; out[13]=0x4f; out[14]=0x4b 362 out[15]=0x0d; out[16]=0x0a 363 out[17]=0x43; out[18]=0x6f; out[19]=0x6e; out[20]=0x74 364 out[21]=0x65; out[22]=0x6e; out[23]=0x74; out[24]=0x2d 365 out[25]=0x4c; out[26]=0x65; out[27]=0x6e; out[28]=0x67 366 out[29]=0x74; out[30]=0x68; out[31]=0x3a; out[32]=0x20 367 out[33]=0x35 368 out[34]=0x0d; out[35]=0x0a 369 out[36]=0x0d; out[37]=0x0a 370 out[38]=0x68; out[39]=0x65; out[40]=0x6c; out[41]=0x6c 371 out[42]=0x6f 372 return 43 373} 374 375// Client setup: produce private key + ephemeral pub key. 376func hclient_setup(out_pub: *u8) -> *u8 { 377 let c_priv: *u8 = sys_mmap(64) 378 hfill_priv(c_priv, 0x40) 379 hsetup_keypair(c_priv, out_pub) 380 return c_priv 381} 382 383// Client exchange CH/SH, return server-pub via slot, ch_len/sh_len via slots. 384func hclient_xchg_hello(cfd: i64, c_pub: *u8, ch: *u8, sh: *u8, lens: *i64, pub_slot: *i64) -> i64 { 385 let ch_len: i64 = hemit_send_ch(cfd, c_pub, ch, 1024) 386 if ch_len < 0 { return 12 } 387 let sh_len: i64 = hrecv_plain(cfd, sh, 1024) 388 if sh_len < 0 { return 13 } 389 if hparse_sh_get_pub(sh, sh_len, pub_slot) != 0 { return 14 } 390 lens[0] = ch_len; lens[1] = sh_len 391 return 0 392} 393 394func run_client_http(cfd: i64, ck: *u8, civ: *u8, sk: *u8, siv: *u8) -> i64 { 395 // Client sends encrypted HTTP GET with client-key seq=1 396 // (seq 0 already used for the encrypted CF). 397 let req: *u8 = sys_mmap(64) 398 let req_len: i64 = hbuild_http_get(req) 399 if hsend_app(cfd, ck, civ, 1, req, req_len) != 0 { return 70 } 400 401 // Client recvs encrypted HTTP response with server-key seq=4 402 // (seq 0..3 used for the encrypted EE/Cert/CV/SF). 403 let resp: *u8 = sys_mmap(4096) 404 let n: i64 = hrecv_app(cfd, sk, siv, 4, resp, 4096) 405 if n < 12 { return 71 } 406 if (resp[0] & 0xff) != 0x48 { return 72 } // 'H' 407 if (resp[9] & 0xff) != 0x32 { return 73 } // '2' 408 if (resp[10] & 0xff) != 0x30 { return 74 } // '0' 409 if (resp[11] & 0xff) != 0x30 { return 75 } // '0' 410 return 0 411} 412 413func run_client_after_keys(cfd: i64, bundle: *u8, tx: *u8) -> i64 { 414 let sk: *u8 = hbundle_ptr(bundle, 5) 415 let siv: *u8 = hbundle_ptr(bundle, 6) 416 let ck: *u8 = hbundle_ptr(bundle, 3) 417 let civ: *u8 = hbundle_ptr(bundle, 4) 418 let chts: *u8 = hbundle_ptr(bundle, 1) 419 let shts: *u8 = hbundle_ptr(bundle, 2) 420 421 let s1: i64 = haead_dispatch(cfd, sk, siv, 0, NX_TLS13_CSTATE_WAIT_EE, shts, tx) 422 if s1 < 0 { return 20 } 423 let s2: i64 = haead_dispatch(cfd, sk, siv, 1, s1, shts, tx) 424 if s2 < 0 { return 30 } 425 let s3: i64 = haead_dispatch(cfd, sk, siv, 2, s2, shts, tx) 426 if s3 < 0 { return 40 } 427 let s4: i64 = haead_dispatch(cfd, sk, siv, 3, s3, shts, tx) 428 if s4 < 0 { return 50 } 429 if s4 != NX_TLS13_CSTATE_CONNECTED { return 60 } 430 431 let cf: *u8 = sys_mmap(64) 432 let cf_len: i64 = tls13_client_emit_finished(chts, tx, cf) 433 if cf_len != 36 { return 61 } 434 if hsend_aead(cfd, ck, civ, 0, cf, cf_len) != 0 { return 62 } 435 436 return run_client_http(cfd, ck, civ, sk, siv) 437} 438 439// Client side: full handshake then encrypted HTTP exchange. 440func run_https_client(cfd: i64) -> i64 { 441 let c_pub: *u8 = sys_mmap(64) 442 let c_priv: *u8 = hclient_setup(c_pub) 443 let ch: *u8 = sys_mmap(1024) 444 let sh: *u8 = sys_mmap(1024) 445 let lens: *i64 = sys_mmap(16) as *i64 446 let pub_slot: *i64 = sys_mmap(8) as *i64 447 let rc: i64 = hclient_xchg_hello(cfd, c_pub, ch, sh, lens, pub_slot) 448 if rc != 0 { return rc } 449 let th: *u8 = sys_mmap(64) 450 let tx_slot: *i64 = sys_mmap(8) as *i64 451 hbuild_th(ch, lens[0], sh, lens[1], th, tx_slot) 452 let eh: *u8 = sys_mmap(64) 453 hfill_empty_hash(eh) 454 let bundle: *u8 = halloc_bundle() 455 let s_pub: *u8 = pub_slot[0] as *u8 456 let tx: *u8 = tx_slot[0] as *u8 457 hderive_keys(c_priv, s_pub, th, eh, bundle) 458 return run_client_after_keys(cfd, bundle, tx) 459} 460 461// Server side: full handshake then encrypted HTTP exchange. 462// Compose key derivation + flight + recv + http into one step, 463// taking a pre-built ServerContext blob. Each helper stays small. 464// 465// ServerCtx layout (8 ptrs): 0=s_priv, 1=c_pub, 2=tx, 3=bundle. 466 467func run_server_http(cfd: i64, bundle: *u8) -> i64 { 468 let sk: *u8 = hbundle_ptr(bundle, 5) 469 let siv: *u8 = hbundle_ptr(bundle, 6) 470 let ck: *u8 = hbundle_ptr(bundle, 3) 471 let civ: *u8 = hbundle_ptr(bundle, 4) 472 473 // Server recvs encrypted HTTP request with client-key seq=1. 474 let req: *u8 = sys_mmap(4096) 475 let n: i64 = hrecv_app(cfd, ck, civ, 1, req, 4096) 476 if n < 14 { return 110 } 477 if (req[0] & 0xff) != 0x47 { return 111 } // 'G' 478 if (req[6] & 0xff) != 0x48 { return 112 } // 'H' 479 480 // Server sends encrypted HTTP 200 with server-key seq=4. 481 let resp: *u8 = sys_mmap(64) 482 let resp_len: i64 = hbuild_http_200(resp) 483 if hsend_app(cfd, sk, siv, 4, resp, resp_len) != 0 { return 113 } 484 return 0 485} 486 487func run_server_after_sh(cfd: i64, ctx: *i64) -> i64 { 488 let s_priv: *u8 = ctx[0] as *u8 489 let c_pub: *u8 = ctx[1] as *u8 490 let tx: *u8 = ctx[2] as *u8 491 let bundle: *u8 = ctx[3] as *u8 492 493 let eh: *u8 = sys_mmap(64) 494 hfill_empty_hash(eh) 495 let th: *u8 = sys_mmap(64) 496 nx_tls13_transcript_snapshot(tx, th) 497 hderive_keys(s_priv, c_pub, th, eh, bundle) 498 499 let fr: i64 = hserver_send_flight(cfd, bundle, tx) 500 if fr != 0 { return fr } 501 let cr: i64 = hserver_recv_cf(cfd, bundle, tx) 502 if cr != 0 { return cr } 503 return run_server_http(cfd, bundle) 504} 505 506func run_https_server(cfd: i64) -> i64 { 507 let s_priv: *u8 = sys_mmap(64) 508 hfill_priv(s_priv, 0x80) 509 let s_pub: *u8 = sys_mmap(64) 510 hsetup_keypair(s_priv, s_pub) 511 512 let ch: *u8 = sys_mmap(1024) 513 let ch_len: i64 = hrecv_plain(cfd, ch, 1024) 514 if ch_len < 0 { return 100 } 515 516 let sid_o: *i64 = sys_mmap(16) as *i64 517 let sid_l: *i64 = sys_mmap(16) as *i64 518 let cpub_slot: *i64 = sys_mmap(8) as *i64 519 if hparse_ch_get_pub(ch, ch_len, sid_o, sid_l, cpub_slot) != 0 { return 101 } 520 let c_pub: *u8 = cpub_slot[0] as *u8 521 522 let s_random: *u8 = sys_mmap(64) 523 hfill_random(s_random, 0x70) 524 let sh: *u8 = sys_mmap(512) 525 let sh_len: i64 = tls13_server_emit_server_hello(s_random, ch + sid_o[0], sid_l[0], s_pub, sh, 512) 526 if sh_len < 0 { return 103 } 527 hsend_plain(cfd, sh, sh_len) 528 529 let th: *u8 = sys_mmap(64) 530 let tx_slot: *i64 = sys_mmap(8) as *i64 531 hbuild_th(ch, ch_len, sh, sh_len, th, tx_slot) 532 533 let bundle: *u8 = halloc_bundle() 534 let ctx: *i64 = sys_mmap(64) as *i64 535 ctx[0] = s_priv as i64 536 ctx[1] = c_pub as i64 537 ctx[2] = tx_slot[0] 538 ctx[3] = bundle as i64 539 return run_server_after_sh(cfd, ctx) 540} 541 542func main() -> i64 { 543 let addr: *u8 = sys_mmap(16) 544 hbuild_addr(addr, HPORT) 545 let lfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0) 546 if lfd < 0 { return 1 } 547 if sys_bind(lfd, addr, 16) < 0 { return 2 } 548 if sys_listen(lfd, 4) < 0 { return 3 } 549 550 let pid: i64 = sys_fork() 551 if pid < 0 { return 4 } 552 553 if pid == 0 { 554 var spin: i64 = 0 555 while spin < 200000 { spin = spin + 1 } 556 let ccfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0) 557 if ccfd < 0 { return 5 } 558 if nx_connect_bounded(ccfd, addr, 16, NX_CONN_DEFAULT_MS) < 0 { return 6 } 559 return run_https_client(ccfd) 560 } 561 562 let scfd: i64 = sys_accept(lfd) 563 if scfd < 0 { return 7 } 564 let sr: i64 = run_https_server(scfd) 565 if sr != 0 { return sr } 566 567 let status: *i64 = sys_mmap(8) as *i64 568 sys_wait4(pid, status, 0) 569 return wait_exit_code(*status) 570}