code wiki / (root) / nx_tls13_server_session_app_data_test.nx

nx_tls13_server_session_app_data_test.nx source

↩ module page · 203 lines · 7407 B

1// nx_tls13_server_session_app_data_test.nx -- round-trip the app 2// data layer on a CONNECTED session. Server sends payload, server 3// also "receives" a client-encrypted payload (built using the same 4// shared keys for the smoke). 5// 6// Closed-form invariants: 7// (a) Wrong state -> negative 8// (b) Drive through full handshake to CONNECTED 9// (c) app_send returns positive byte count, output starts 0x17 10// (d) server_app_seq increments 11// (e) Build a synthetic client app record + app_recv returns 12// exact plaintext (bit-for-bit match) 13// (f) client_app_seq increments 14// (g) Decrypting a tampered record -> PROTOCOL_ERR; seq NOT advanced 15// 16// expect_exit: 0 17// license_tier: ORIGINAL 18 19import "nx_syscalls.nx" 20import "nx_x25519.nx" 21import "nx_x25519_ephemeral.nx" 22import "nx_hmac.nx" 23import "nx_tls13.nx" 24import "nx_tls13_hello.nx" 25import "nx_tls13_kdf.nx" 26import "nx_tls13_record.nx" 27import "nx_tls13_transcript.nx" 28import "nx_tls13_server_session.nx" 29import "nx_tls13_server_session_recv_ch.nx" 30import "nx_tls13_server_session_emit_sh.nx" 31import "nx_tls13_server_session_derive_hs.nx" 32import "nx_tls13_server_session_derive_traffic.nx" 33import "nx_tls13_server_session_emit_ee.nx" 34import "nx_tls13_server_session_emit_sf.nx" 35import "nx_tls13_server_session_recv_cf.nx" 36import "nx_tls13_server_session_app_data.nx" 37 38func build_client_app_record( 39 cli_app_key: *u8, cli_app_iv: *u8, cli_app_seq: i64, 40 payload: *u8, payload_len: i64, 41 out: *u8, out_cap: i64 42) -> i64 { 43 let header: *u8 = sys_mmap(5) 44 let ct: *u8 = sys_mmap(payload_len + 17) 45 let tag: *u8 = sys_mmap(16) 46 let rv: i64 = nx_tls13_record_encrypt( 47 cli_app_key, cli_app_iv, cli_app_seq, 48 payload, payload_len, 49 CT_APPLICATION_DATA, 0, 50 header, ct, tag) 51 if rv != NX_TLS13_REC_VERDICT_OK { return -1 } 52 53 let total: i64 = 5 + payload_len + 1 + 16 54 if total > out_cap { return -1 } 55 var w: i64 = 0 56 var hi: i64 = 0 57 while hi < 5 { out[w + hi] = header[hi]; hi = hi + 1 } 58 w = w + 5 59 var ci: i64 = 0 60 while ci < payload_len + 1 { out[w + ci] = ct[ci]; ci = ci + 1 } 61 w = w + payload_len + 1 62 var ti: i64 = 0 63 while ti < 16 { out[w + ti] = tag[ti]; ti = ti + 1 } 64 return w + 16 65} 66 67func main() -> i64 { 68 let cli_priv: *u8 = sys_mmap(32) 69 let cli_pub: *u8 = sys_mmap(32) 70 let cli_rand: *u8 = sys_mmap(32) 71 var i: i64 = 0 72 while i < 32 { 73 cli_priv[i] = ((i + 17) & 0xff) as u8 74 cli_rand[i] = ((i + 50) & 0xff) as u8 75 i = i + 1 76 } 77 x25519_keypair_public(cli_priv, cli_pub) 78 let ch_buf: *u8 = sys_mmap(1024) 79 let ch_n: i64 = tls13_client_hello_emit(cli_rand, "nishifamily.com", 15, cli_pub, ch_buf, 1024) 80 if ch_n <= 0 { return 5 } 81 82 let srv_priv: *u8 = sys_mmap(32) 83 let srv_rand: *u8 = sys_mmap(32) 84 var k: i64 = 0 85 while k < 32 { 86 srv_priv[k] = ((k + 80) & 0xff) as u8 87 srv_rand[k] = ((k + 70) & 0xff) as u8 88 k = k + 1 89 } 90 let s: *Tls13ServerSession = nx_tls13_server_session_new(srv_rand, srv_priv) 91 92 // ===== (a) Wrong state ===== 93 let bad_buf: *u8 = sys_mmap(512) 94 let r_wrong: i64 = nx_tls13_server_session_app_send(s, ch_buf, 10, bad_buf, 512) 95 let exp_bad: i64 = 0 - NX_TLS13_SSESSION_BAD_STATE 96 if r_wrong != exp_bad { return 10 } 97 98 // ===== Drive through full handshake to CONNECTED ===== 99 nx_tls13_server_session_recv_ch(s, ch_buf, ch_n) 100 let sh_buf: *u8 = sys_mmap(512) 101 nx_tls13_server_session_emit_sh(s, sh_buf, 512) 102 nx_tls13_server_session_derive_hs_secrets(s) 103 nx_tls13_server_session_derive_traffic(s) 104 let ee_buf: *u8 = sys_mmap(256) 105 nx_tls13_server_session_emit_ee(s, ee_buf, 256) 106 let sf_buf: *u8 = sys_mmap(256) 107 nx_tls13_server_session_emit_sf(s, sf_buf, 256) 108 109 // Build client Finished using shared keys 110 let finished_label: *u8 = "finished" 111 let empty: *u8 = sys_mmap(1) 112 let finished_key_c: *u8 = sys_mmap(32) 113 tls13_hkdf_expand_label(s.client_hs_traffic_secret, finished_label, 8, 114 empty, 0, 32, finished_key_c) 115 let th: *u8 = sys_mmap(32) 116 nx_tls13_transcript_snapshot(s.transcript, th) 117 let verify_data: *u8 = sys_mmap(32) 118 hmac_sha256(finished_key_c, 32, th, 32, verify_data) 119 let cf_rec: *u8 = sys_mmap(256) 120 121 // Inline-build client Finished 122 let inner_len: i64 = 36 123 let inner: *u8 = sys_mmap(inner_len) 124 inner[0] = HT_FINISHED & 0xff 125 inner[1] = 0 126 inner[2] = 0 127 inner[3] = 32 128 var vi: i64 = 0 129 while vi < 32 { inner[4 + vi] = verify_data[vi]; vi = vi + 1 } 130 let cf_hdr: *u8 = sys_mmap(5) 131 let cf_ct: *u8 = sys_mmap(inner_len + 17) 132 let cf_tag: *u8 = sys_mmap(16) 133 nx_tls13_record_encrypt( 134 s.client_hs_traffic_key, s.client_hs_iv, s.client_seq, 135 inner, inner_len, CT_HANDSHAKE, 0, 136 cf_hdr, cf_ct, cf_tag) 137 var w_cf: i64 = 0 138 var c_hi: i64 = 0 139 while c_hi < 5 { cf_rec[w_cf + c_hi] = cf_hdr[c_hi]; c_hi = c_hi + 1 } 140 w_cf = w_cf + 5 141 var c_ci: i64 = 0 142 while c_ci < inner_len + 1 { cf_rec[w_cf + c_ci] = cf_ct[c_ci]; c_ci = c_ci + 1 } 143 w_cf = w_cf + inner_len + 1 144 var c_ti: i64 = 0 145 while c_ti < 16 { cf_rec[w_cf + c_ti] = cf_tag[c_ti]; c_ti = c_ti + 1 } 146 let cf_total: i64 = w_cf + 16 147 148 nx_tls13_server_session_recv_cf(s, cf_rec, cf_total) 149 if s.state != NX_TLS13_SSTATE_CONNECTED { return 20 } 150 151 // ===== (c) app_send ===== 152 let payload_a: *u8 = "GET /index.html HTTP/1.1\r\nHost: nishifamily.com\r\n\r\n" 153 var pa_len: i64 = 0 154 while payload_a[pa_len] != 0 { pa_len = pa_len + 1 } 155 let send_buf: *u8 = sys_mmap(512) 156 let n_send: i64 = nx_tls13_server_session_app_send(s, payload_a, pa_len, send_buf, 512) 157 if n_send <= 0 { return 30 } 158 if send_buf[0] != 0x17 { return 31 } // app_data record header 159 160 // ===== (d) server_app_seq increments ===== 161 if s.server_app_seq != 1 { return 40 } 162 163 // ===== (e) Build synthetic client app record + recv ===== 164 let payload_b: *u8 = "HTTP/1.1 200 OK\r\n\r\nHello from substrate" 165 var pb_len: i64 = 0 166 while payload_b[pb_len] != 0 { pb_len = pb_len + 1 } 167 let cli_rec: *u8 = sys_mmap(256) 168 let cli_n: i64 = build_client_app_record( 169 s.client_app_traffic_key, s.client_app_iv, s.client_app_seq, 170 payload_b, pb_len, cli_rec, 256) 171 if cli_n <= 0 { return 50 } 172 173 let recv_buf: *u8 = sys_mmap(512) 174 let n_recv: i64 = nx_tls13_server_session_app_recv(s, cli_rec, cli_n, recv_buf, 512) 175 if n_recv != pb_len { return 51 } 176 177 // Bit-for-bit match 178 var bi: i64 = 0 179 var ok: i64 = 1 180 while bi < pb_len { 181 if recv_buf[bi] != payload_b[bi] { ok = 0 } 182 bi = bi + 1 183 } 184 if ok != 1 { return 52 } 185 186 // ===== (f) client_app_seq increments ===== 187 if s.client_app_seq != 1 { return 60 } 188 189 // ===== (g) Tampered record -> PROTOCOL_ERR + seq NOT advanced ===== 190 let bad_cli_rec: *u8 = sys_mmap(256) 191 var ti2: i64 = 0 192 while ti2 < cli_n { bad_cli_rec[ti2] = cli_rec[ti2]; ti2 = ti2 + 1 } 193 // Flip a byte in the ciphertext (not the header) 194 bad_cli_rec[10] = (bad_cli_rec[10] as i64 ^ 0xff) as u8 195 196 let save_seq: i64 = s.client_app_seq 197 let r_bad: i64 = nx_tls13_server_session_app_recv(s, bad_cli_rec, cli_n, recv_buf, 512) 198 let exp_pe: i64 = 0 - NX_TLS13_SSESSION_PROTOCOL_ERR 199 if r_bad != exp_pe { return 70 } 200 if s.client_app_seq != save_seq { return 71 } 201 202 return 0 203}