code wiki / (root) / nx_tls13_read_record_from_fd_loopback_test.nx

nx_tls13_read_record_from_fd_loopback_test.nx source

↩ module page · 125 lines · 4597 B

1// nx_tls13_read_record_from_fd_loopback_test.nx -- REAL happy- 2// path KAT for nx_tls13_read_record_from_fd over real TCP loopback. 3// 4// The existing nx_tls13_read_record_from_fd_test.nx preamble 5// explicitly documents that sys_pipe2 is unreliable in qemu so 6// the original test only exercises bounds-check + read-failure 7// paths. That left the primitive's HAPPY PATH (read a real 8// 5-byte TLS record header + body from a real bidirectional 9// socket) UNVERIFIED. 10// 11// This file closes that gap using the same fork+child socket 12// loopback pattern as nx_https_loopback_test (which has been 13// verified to work in qemu-riscv64-static), exercising ONLY the 14// record-reader primitive in isolation. 15// 16// Test shape: 17// 1. parent: socket + bind + listen on loopback port 18// 2. fork 19// 3. child: socket + connect; build a real TLS record bytes 20// (type=22 handshake, version 0x0303, payload "ABCDE"); 21// sys_write the 10-byte record + close. 22// 4. parent: accept; call nx_tls13_read_record_from_fd(accepted_fd, 23// out_buf, out_cap); verify 24// (a) return value == 10 (5 header + 5 payload) 25// (b) header bytes are correct (0x16 0x03 0x03 0x00 0x05) 26// (c) payload bytes are "ABCDE" 27// 5. parent waits for child + returns child's exit code OR a 28// verdict-specific code if anything mismatched 29// 30// expect_exit: 0 31// license_tier: ORIGINAL 32 33import "nx_syscalls.nx" 34import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host 35import "nx_tls13.nx" 36import "nx_tls13_read_record_from_fd.nx" 37 38const TEST_PORT: i64 = 19453 39 40func build_addr(out: *u8, port: i64) -> i64 { 41 out[0] = 2; out[1] = 0 42 out[2] = (port >> 8) & 0xff 43 out[3] = port & 0xff 44 out[4] = 127; out[5] = 0; out[6] = 0; out[7] = 1 45 var i: i64 = 8 46 while i < 16 { out[i] = 0; i = i + 1 } 47 return 16 48} 49 50// Child: connect to the loopback port + write a real TLS record. 51// Record = 5-byte header (type=22, version 0x0303, length=5) + 52// 5-byte payload "ABCDE" = 0x41 0x42 0x43 0x44 0x45. 53func child_send_record(addr: *u8) -> i64 { 54 var spin: i64 = 0 55 while spin < 200000 { spin = spin + 1 } 56 let cfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0) 57 if cfd < 0 { return 11 } 58 if nx_connect_bounded(cfd, addr, 16, NX_CONN_DEFAULT_MS) < 0 { return 12 } 59 60 let rec: *u8 = sys_mmap(16) 61 rec[0] = 0x16 // type=22 handshake 62 rec[1] = 0x03 // version high 63 rec[2] = 0x03 // version low 64 rec[3] = 0x00 // length high 65 rec[4] = 0x05 // length low 66 rec[5] = 0x41 // 'A' 67 rec[6] = 0x42 // 'B' 68 rec[7] = 0x43 // 'C' 69 rec[8] = 0x44 // 'D' 70 rec[9] = 0x45 // 'E' 71 let wn: i64 = sys_write(cfd, rec, 10) 72 if wn != 10 { return 13 } 73 sys_close(cfd) 74 return 0 75} 76 77// Parent: accept + call nx_tls13_read_record_from_fd + verify. 78func parent_read_and_verify(lfd: i64) -> i64 { 79 let scfd: i64 = sys_accept(lfd) 80 if scfd < 0 { return 21 } 81 82 let out: *u8 = sys_mmap(64) 83 let total: i64 = nx_tls13_read_record_from_fd(scfd, out, 64) 84 if total != 10 { return 22 } // 5 + 5 85 86 // Header verification 87 if (out[0] & 0xff) != 0x16 { return 23 } 88 if (out[1] & 0xff) != 0x03 { return 24 } 89 if (out[2] & 0xff) != 0x03 { return 25 } 90 if (out[3] & 0xff) != 0x00 { return 26 } 91 if (out[4] & 0xff) != 0x05 { return 27 } 92 93 // Payload verification 94 if (out[5] & 0xff) != 0x41 { return 28 } // 'A' 95 if (out[6] & 0xff) != 0x42 { return 29 } 96 if (out[7] & 0xff) != 0x43 { return 30 } 97 if (out[8] & 0xff) != 0x44 { return 31 } 98 if (out[9] & 0xff) != 0x45 { return 32 } // 'E' 99 100 sys_close(scfd) 101 return 0 102} 103 104func main() -> i64 { 105 let addr: *u8 = sys_mmap(16) 106 build_addr(addr, TEST_PORT) 107 let lfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0) 108 if lfd < 0 { return 1 } 109 if sys_bind(lfd, addr, 16) < 0 { return 2 } 110 if sys_listen(lfd, 4) < 0 { return 3 } 111 112 let pid: i64 = sys_fork() 113 if pid < 0 { return 4 } 114 115 if pid == 0 { 116 return child_send_record(addr) 117 } 118 119 let r: i64 = parent_read_and_verify(lfd) 120 if r != 0 { return r } 121 122 let status: *i64 = sys_mmap(8) as *i64 123 sys_wait4(pid, status, 0) 124 return wait_exit_code(*status) 125}