code wiki / (root) / nx_tls13_aead_record_tcp_test.nx

nx_tls13_aead_record_tcp_test.nx source

↩ module page · 150 lines · 5084 B

1// nx_tls13_aead_record_tcp_test.nx -- send + recv ONE AEAD-protected 2// TLS 1.3 record over real TCP via fork loopback (RV64/qemu). 3// 4// Uses nx_tls13_record_encrypt/decrypt directly with hard-coded key 5// and IV. Proves the AEAD record layer works over real kernel 6// sockets on RV64 -- the missing piece needed to combine with the 7// already-passing nx_tls13_handshake_tcp test for full encrypted 8// HTTPS-class traffic. 9// 10// Keeps every function small per F6 friction-catalog discipline. 11// 12// expect_exit: 0 13// license_tier: ORIGINAL 14 15import "nx_syscalls.nx" 16import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host 17import "nx_tls13_record.nx" 18 19const TEST_PORT: i64 = 19445 20 21func build_addr(out: *u8, port: i64) -> i64 { 22 out[0] = 2; out[1] = 0 23 out[2] = (port >> 8) & 0xff 24 out[3] = port & 0xff 25 out[4] = 127; out[5] = 0; out[6] = 0; out[7] = 1 26 var i: i64 = 8 27 while i < 16 { out[i] = 0; i = i + 1 } 28 return 16 29} 30 31func setup_key_iv(key_out: *u8, iv_out: *u8) -> i64 { 32 var i: i64 = 0 33 while i < 32 { key_out[i] = (0x40 + i) & 0xff; i = i + 1 } 34 i = 0 35 while i < 12 { iv_out[i] = (0xa0 + i) & 0xff; i = i + 1 } 36 return 0 37} 38 39// Read N bytes from fd into buf (looping on partial reads). 40func read_n(fd: i64, buf: *u8, n: i64) -> i64 { 41 var got: i64 = 0 42 while got < n { 43 let r: i64 = sys_read(fd, buf + got, n - got) 44 if r <= 0 { return 0 - 1 } 45 got = got + r 46 } 47 return got 48} 49 50// Send one encrypted handshake-type record (inner type = 22). 51func send_record(fd: i64, key: *u8, iv: *u8, seq: i64, payload: *u8, payload_len: i64) -> i64 { 52 let hdr: *u8 = sys_mmap(16) 53 let ct: *u8 = sys_mmap(payload_len + 64) 54 let tag: *u8 = sys_mmap(16) 55 let vrd: i64 = nx_tls13_record_encrypt(key, iv, seq, payload, payload_len, 22, 0, hdr, ct, tag) 56 if vrd != NX_TLS13_REC_VERDICT_OK { return 0 - 1 } 57 sys_write(fd, hdr, 5) 58 sys_write(fd, ct, payload_len + 1) 59 sys_write(fd, tag, 16) 60 return 0 61} 62 63// Recv one encrypted record, decrypt to out, return plaintext bytes. 64func recv_record(fd: i64, key: *u8, iv: *u8, seq: i64, out: *u8, out_cap: i64) -> i64 { 65 let hdr: *u8 = sys_mmap(16) 66 if read_n(fd, hdr, 5) < 0 { return 0 - 1 } 67 let total: i64 = ((hdr[3] & 0xff) << 8) | (hdr[4] & 0xff) 68 if total < 17 { return 0 - 2 } 69 let ct_len: i64 = total - 16 70 let buf: *u8 = sys_mmap(total + 16) 71 if read_n(fd, buf, total) < 0 { return 0 - 3 } 72 let tag: *u8 = sys_mmap(16) 73 var ti: i64 = 0 74 while ti < 16 { tag[ti] = buf[ct_len + ti]; ti = ti + 1 } 75 let rct: *i64 = sys_mmap(8) as *i64 76 let rln: *i64 = sys_mmap(8) as *i64 77 let vrd: i64 = nx_tls13_record_decrypt(key, iv, seq, hdr, buf, ct_len, tag, out, rct, rln) 78 if vrd != NX_TLS13_REC_VERDICT_OK { return 0 - 4 } 79 return rln[0] 80} 81 82// Child runs the encrypted send + recv roundtrip. 83func run_client(cfd: i64) -> i64 { 84 let key: *u8 = sys_mmap(32) 85 let iv: *u8 = sys_mmap(16) 86 setup_key_iv(key, iv) 87 88 let msg: *u8 = sys_mmap(16) 89 msg[0]=0x50; msg[1]=0x49; msg[2]=0x4e; msg[3]=0x47 // "PING" 90 let s: i64 = send_record(cfd, key, iv, 0, msg, 4) 91 if s != 0 { return 10 } 92 93 let reply: *u8 = sys_mmap(64) 94 let n: i64 = recv_record(cfd, key, iv, 0, reply, 64) 95 if n != 4 { return 20 + (0 - n) } 96 if (reply[0] & 0xff) != 0x50 { return 30 } // 'P' 97 if (reply[1] & 0xff) != 0x4f { return 31 } // 'O' 98 if (reply[2] & 0xff) != 0x4e { return 32 } // 'N' 99 if (reply[3] & 0xff) != 0x47 { return 33 } // 'G' 100 return 0 101} 102 103// Parent: recv encrypted PING, send encrypted PONG. 104func run_server(cfd: i64) -> i64 { 105 let key: *u8 = sys_mmap(32) 106 let iv: *u8 = sys_mmap(16) 107 setup_key_iv(key, iv) 108 109 let in_buf: *u8 = sys_mmap(64) 110 let n: i64 = recv_record(cfd, key, iv, 0, in_buf, 64) 111 if n != 4 { return 40 + (0 - n) } 112 if (in_buf[0] & 0xff) != 0x50 { return 50 } // 'P' 113 if (in_buf[3] & 0xff) != 0x47 { return 51 } // 'G' of PING 114 115 let reply: *u8 = sys_mmap(16) 116 reply[0]=0x50; reply[1]=0x4f; reply[2]=0x4e; reply[3]=0x47 // "PONG" 117 let s: i64 = send_record(cfd, key, iv, 0, reply, 4) 118 if s != 0 { return 60 } 119 return 0 120} 121 122func main() -> i64 { 123 let addr: *u8 = sys_mmap(16) 124 build_addr(addr, TEST_PORT) 125 let lfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0) 126 if lfd < 0 { return 1 } 127 if sys_bind(lfd, addr, 16) < 0 { return 2 } 128 if sys_listen(lfd, 4) < 0 { return 3 } 129 130 let pid: i64 = sys_fork() 131 if pid < 0 { return 4 } 132 133 if pid == 0 { 134 var spin: i64 = 0 135 while spin < 200000 { spin = spin + 1 } 136 let ccfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0) 137 if ccfd < 0 { return 5 } 138 if nx_connect_bounded(ccfd, addr, 16, NX_CONN_DEFAULT_MS) < 0 { return 6 } 139 return run_client(ccfd) 140 } 141 142 let scfd: i64 = sys_accept(lfd) 143 if scfd < 0 { return 7 } 144 let sr: i64 = run_server(scfd) 145 if sr != 0 { return sr } 146 147 let status: *i64 = sys_mmap(8) as *i64 148 sys_wait4(pid, status, 0) 149 return wait_exit_code(*status) 150}