code wiki / (root) / nx_tls13_server_session_emit_sh_test.nx

nx_tls13_server_session_emit_sh_test.nx source

↩ module page · 130 lines · 5029 B

1// nx_tls13_server_session_emit_sh_test.nx -- verify server emits a 2// ServerHello bytes that the existing CLIENT parser consumes (round- 3// trip), and that the session advances CH_RECEIVED -> SH_SENT. 4// 5// Closed-form invariants: 6// (a) Wrong-state session (INIT) -> BAD_STATE 7// (b) After recv_ch + emit_sh: state == SH_SENT + n > 0 8// (c) Client's tls13_server_hello_parse consumes our SH bytes 9// cleanly (positive verdict) 10// (d) Parsed legacy_version == 0x0303 11// (e) Parsed cipher_suite == TLS_CHACHA20_POLY1305_SHA256 (0x1303) 12// (f) Server's emitted random appears at the byte offset the 13// parser reports 14// (g) Extensions blob contains supported_versions(43) + key_share(51) 15// (h) Calling emit_sh again -> BAD_STATE (state moved past CH_RECEIVED) 16// 17// expect_exit: 0 18// license_tier: ORIGINAL 19 20import "nx_syscalls.nx" 21import "nx_x25519.nx" 22import "nx_x25519_ephemeral.nx" 23import "nx_tls13.nx" 24import "nx_tls13_hello.nx" 25import "nx_tls13_server_session.nx" 26import "nx_tls13_server_session_recv_ch.nx" 27import "nx_tls13_server_session_emit_sh.nx" 28 29func main() -> i64 { 30 // ----- Build client side: priv key + ClientHello ----- 31 let cli_priv: *u8 = sys_mmap(32) 32 let cli_pub: *u8 = sys_mmap(32) 33 let cli_rand: *u8 = sys_mmap(32) 34 var i: i64 = 0 35 while i < 32 { 36 cli_priv[i] = ((i + 17) & 0xff) as u8 37 cli_rand[i] = ((i + 50) & 0xff) as u8 38 i = i + 1 39 } 40 x25519_keypair_public(cli_priv, cli_pub) 41 42 let sni: *u8 = "nishifamily.com" 43 let sni_len: i64 = 15 44 let ch_cap: i64 = 1024 45 let ch_buf: *u8 = sys_mmap(ch_cap) 46 let ch_n: i64 = tls13_client_hello_emit(cli_rand, sni, sni_len, cli_pub, ch_buf, ch_cap) 47 if ch_n <= 0 { return 5 } 48 49 // ----- Build server session ----- 50 let srv_priv: *u8 = sys_mmap(32) 51 let srv_rand: *u8 = sys_mmap(32) 52 var k: i64 = 0 53 while k < 32 { 54 srv_priv[k] = ((k + 80) & 0xff) as u8 55 srv_rand[k] = ((k + 70) & 0xff) as u8 56 k = k + 1 57 } 58 let s: *Tls13ServerSession = nx_tls13_server_session_new(srv_rand, srv_priv) 59 if (s as i64) == 0 { return 6 } 60 61 // ----- (a) emit_sh in wrong state (INIT) -> BAD_STATE ----- 62 let bad_buf: *u8 = sys_mmap(512) 63 let r_wrong: i64 = nx_tls13_server_session_emit_sh(s, bad_buf, 512) 64 let expect_bad: i64 = 0 - NX_TLS13_SSESSION_BAD_STATE 65 if r_wrong != expect_bad { return 10 } 66 67 // ----- recv_ch ----- 68 let r_rc: i64 = nx_tls13_server_session_recv_ch(s, ch_buf, ch_n) 69 if r_rc != NX_TLS13_SSESSION_OK { return 15 } 70 if s.state != NX_TLS13_SSTATE_CH_RECEIVED { return 16 } 71 72 // ----- (b) emit_sh ----- 73 let sh_cap: i64 = 512 74 let sh_buf: *u8 = sys_mmap(sh_cap) 75 let n: i64 = nx_tls13_server_session_emit_sh(s, sh_buf, sh_cap) 76 if n <= 0 { return 20 } 77 if s.state != NX_TLS13_SSTATE_SH_SENT { return 21 } 78 79 // ----- (c) Client parser round-trip ----- 80 // STALE-TEST HEAL 2026-06-10: emit_sh writes a 5-byte TLS record 81 // header then the handshake body (required by real clients; see 82 // emit_sh preamble). This test predated that and parsed from 83 // offset 0 -> silently RED since the header landed. Parse the 84 // BODY (+5), like the wire peer does. 85 let sh_body: *u8 = sh_buf + 5 86 let body_n: i64 = n - 5 87 let pv_box: *i64 = sys_mmap(8) as *i64 88 let rand_off_box: *i64 = sys_mmap(8) as *i64 89 let cs_box: *i64 = sys_mmap(8) as *i64 90 let eo_box: *i64 = sys_mmap(8) as *i64 91 let el_box: *i64 = sys_mmap(8) as *i64 92 let parse_v: i64 = tls13_server_hello_parse(sh_body, body_n, 93 pv_box, rand_off_box, cs_box, eo_box, el_box) 94 if parse_v != NX_TLS13_HELLO_VERDICT_OK { return 30 } 95 96 // ----- (d) legacy_version ----- 97 if *pv_box != TLS_LEGACY_VERSION { return 40 } 98 99 // ----- (e) cipher_suite ----- 100 if *cs_box != NX_TLS13_CS_CHACHA20_POLY1305_SHA256 { return 50 } 101 102 // ----- (f) Server random matches at reported offset ----- 103 let ro: i64 = *rand_off_box 104 var rmatch: i64 = 1 105 var ri: i64 = 0 106 while ri < 32 { 107 if sh_body[ro + ri] != srv_rand[ri] { rmatch = 0 } 108 ri = ri + 1 109 } 110 if rmatch != 1 { return 60 } 111 112 // ----- (g) Extensions blob contains supported_versions + key_share ----- 113 let eo: i64 = *eo_box 114 let el: i64 = *el_box 115 let sv_off_box: *i64 = sys_mmap(8) as *i64 116 let sv_len_box: *i64 = sys_mmap(8) as *i64 117 let sv_v: i64 = tls13_ext_find(sh_body + eo, el, EXT_SUPPORTED_VERSIONS, sv_off_box, sv_len_box) 118 if sv_v != NX_TLS13_HELLO_VERDICT_OK { return 70 } 119 let ks_off_box: *i64 = sys_mmap(8) as *i64 120 let ks_len_box: *i64 = sys_mmap(8) as *i64 121 let ks_v: i64 = tls13_ext_find(sh_body + eo, el, EXT_KEY_SHARE, ks_off_box, ks_len_box) 122 if ks_v != NX_TLS13_HELLO_VERDICT_OK { return 71 } 123 124 // ----- (h) Calling emit_sh again -> BAD_STATE ----- 125 let r_again: i64 = nx_tls13_server_session_emit_sh(s, sh_buf, sh_cap) 126 let expect_again: i64 = 0 - NX_TLS13_SSESSION_BAD_STATE 127 if r_again != expect_again { return 80 } 128 129 return 0 130}