code wiki / (root) / nx_tls13_client_session_recv_sh_test.nx

nx_tls13_client_session_recv_sh_test.nx source

↩ module page · 217 lines · 9729 B

1// nx_tls13_client_session_recv_sh_test.nx -- KAT for step 3c.2: 2// recv ServerHello + derive handshake keys. 3// 4// expect_exit: 0 5// license_tier: ORIGINAL 6 7import "nx_syscalls.nx" 8import "nx_tls13.nx" 9import "nx_tls13_client_session.nx" 10import "nx_tls13_client_session_recv_sh.nx" 11 12// Build a minimal synthetic ServerHello message with just a 13// key_share extension carrying an X25519 keyshare. Returns total 14// bytes written. 15// 16// Layout (body inside the 4-byte handshake header is 80 bytes): 17// legacy_version (2) = 0x03 0x03 18// server_random (32) = caller-supplied or pattern 19// session_id_len (1) = 0 20// cipher_suite (2) = 0x13 0x01 (TLS_AES_128_GCM_SHA256) 21// compression (1) = 0 22// ext_list_len (2) = 40 23// extensions (40): 24// key_share (40 bytes): 25// ext_type (2) = 0x00 0x33 (EXT_KEY_SHARE = 51) 26// ext_data_len (2) = 36 27// group (2) = 0x00 0x1D (X25519 = 29) 28// ke_len (2) = 0x00 0x20 (32) 29// ke (32) = server's X25519 pubkey 30func build_sh(out: *u8, server_random: *u8, server_pub: *u8) -> i64 { 31 out[0] = HT_SERVER_HELLO & 0xff 32 // body length = 80 33 out[1] = 0; out[2] = 0; out[3] = 80 34 // legacy_version = 0x03 0x03 35 out[4] = 0x03; out[5] = 0x03 36 // server_random 37 var i: i64 = 0 38 while i < 32 { out[6 + i] = server_random[i]; i = i + 1 } 39 // session_id_len = 0 40 out[38] = 0 41 // cipher_suite = TLS_CHACHA20_POLY1305_SHA256 (0x13 0x03) 42 out[39] = 0x13; out[40] = 0x03 43 // compression_method = 0 44 out[41] = 0 45 // ext_list_len = 40 46 out[42] = 0; out[43] = 40 47 // key_share extension 48 out[44] = 0; out[45] = 0x33 // ext_type = 51 = EXT_KEY_SHARE 49 out[46] = 0; out[47] = 36 // ext_data_len = 36 50 out[48] = 0; out[49] = 0x1D // group = 29 = X25519 51 out[50] = 0; out[51] = 32 // ke_len = 32 52 i = 0 53 while i < 32 { out[52 + i] = server_pub[i]; i = i + 1 } 54 return 84 // 4 (hdr) + 80 (body) 55} 56 57func main() -> i64 { 58 // ---- Build a fresh client session ---- 59 let client_random: *u8 = sys_mmap(32) 60 var i: i64 = 0 61 while i < 32 { client_random[i] = (0xC0 + i) as u8; i = i + 1 } 62 63 let priv: *u8 = sys_mmap(32) 64 i = 0 65 while i < 32 { priv[i] = (0x40 + i) as u8; i = i + 1 } 66 67 let s: *Tls13ClientSession = nx_tls13_client_session_new(client_random, priv) 68 69 // Emit CH first so state advances to CH_SENT (recv_sh requires it). 70 let sni: *u8 = sys_mmap(32) 71 sni[0]=0x65; sni[1]=0x78; sni[2]=0x61 72 sni[3]=0x6D; sni[4]=0x70; sni[5]=0x6C; sni[6]=0x65 // "example" 73 let ch_buf: *u8 = sys_mmap(512) 74 let ch_n: i64 = nx_tls13_client_session_emit_ch(s, sni, 7, ch_buf, 512) 75 if ch_n < 0 { return 1 } 76 if s.state != NX_TLS13_CSESSION_STATE_CH_SENT { return 2 } 77 78 // ---- Test A: well-formed SH -> OK + state advances to WAIT_EE ---- 79 let server_random: *u8 = sys_mmap(32) 80 i = 0 81 while i < 32 { server_random[i] = (0x70 + i) as u8; i = i + 1 } 82 let server_pub: *u8 = sys_mmap(32) 83 i = 0 84 while i < 32 { server_pub[i] = (0xA0 + i) as u8; i = i + 1 } 85 let sh: *u8 = sys_mmap(128) 86 let sh_n: i64 = build_sh(sh, server_random, server_pub) 87 if sh_n != 84 { return 3 } 88 89 let v_a: i64 = nx_tls13_client_session_recv_sh(s, sh, sh_n) 90 if v_a != NX_TLS13_RECV_SH_OK { return 10 } 91 if s.state != NX_TLS13_CSESSION_STATE_WAIT_EE { return 11 } 92 93 // server_x25519_pub copied byte-exact 94 i = 0 95 while i < 32 { 96 if (s.server_x25519_pub[i] & 0xff) != (0xA0 + i) { return 20 + i } 97 i = i + 1 98 } 99 100 // Sequence numbers reset 101 if s.client_seq != 0 { return 60 } 102 if s.server_seq != 0 { return 61 } 103 104 // Derived keys are non-zero (proves the cascade ran) 105 var hs_acc: i64 = 0 106 i = 0 107 while i < 32 { hs_acc = hs_acc | (s.handshake_secret[i] & 0xff); i = i + 1 } 108 if hs_acc == 0 { return 70 } 109 var c_hk_acc: i64 = 0 110 i = 0 111 while i < 32 { c_hk_acc = c_hk_acc | (s.client_hs_traffic_key[i] & 0xff); i = i + 1 } 112 if c_hk_acc == 0 { return 71 } 113 var s_hk_acc: i64 = 0 114 i = 0 115 while i < 32 { s_hk_acc = s_hk_acc | (s.server_hs_traffic_key[i] & 0xff); i = i + 1 } 116 if s_hk_acc == 0 { return 72 } 117 var c_iv_acc: i64 = 0 118 i = 0 119 while i < 12 { c_iv_acc = c_iv_acc | (s.client_hs_iv[i] & 0xff); i = i + 1 } 120 if c_iv_acc == 0 { return 73 } 121 var s_iv_acc: i64 = 0 122 i = 0 123 while i < 12 { s_iv_acc = s_iv_acc | (s.server_hs_iv[i] & 0xff); i = i + 1 } 124 if s_iv_acc == 0 { return 74 } 125 126 // Client + server HS keys MUST differ (RFC 8446: independent 127 // Derive-Secret calls under different labels) 128 var keys_match: i64 = 1 129 i = 0 130 while i < 32 { 131 if (s.client_hs_traffic_key[i] & 0xff) != (s.server_hs_traffic_key[i] & 0xff) { 132 keys_match = 0 133 i = 32 // break 134 } else { i = i + 1 } 135 } 136 if keys_match == 1 { return 80 } 137 138 // ---- Test B: recv_sh from non-CH_SENT state -> BAD_STATE ---- 139 // (Session already in WAIT_EE after Test A) 140 let v_b: i64 = nx_tls13_client_session_recv_sh(s, sh, sh_n) 141 if v_b != NX_TLS13_RECV_SH_BAD_STATE { return 90 } 142 143 // ---- Test C: SH with bad msg type -> BAD_FORMAT ---- 144 let s2: *Tls13ClientSession = nx_tls13_client_session_new(client_random, priv) 145 nx_tls13_client_session_emit_ch(s2, sni, 7, ch_buf, 512) 146 let bad_sh: *u8 = sys_mmap(128) 147 build_sh(bad_sh, server_random, server_pub) 148 bad_sh[0] = 0x99 // wrong msg type 149 let v_c: i64 = nx_tls13_client_session_recv_sh(s2, bad_sh, 84) 150 if v_c != NX_TLS13_RECV_SH_BAD_FORMAT { return 100 } 151 // state must remain CH_SENT on failure 152 if s2.state != NX_TLS13_CSESSION_STATE_CH_SENT { return 101 } 153 154 // ---- Test D: SH with no key_share ext -> NO_KEYSHARE ---- 155 let s3: *Tls13ClientSession = nx_tls13_client_session_new(client_random, priv) 156 nx_tls13_client_session_emit_ch(s3, sni, 7, ch_buf, 512) 157 let sh_no_ks: *u8 = sys_mmap(128) 158 sh_no_ks[0] = HT_SERVER_HELLO & 0xff 159 sh_no_ks[1] = 0; sh_no_ks[2] = 0; sh_no_ks[3] = 42 // body = 42 160 sh_no_ks[4] = 0x03; sh_no_ks[5] = 0x03 // legacy_version 161 var ji: i64 = 0 162 while ji < 32 { sh_no_ks[6 + ji] = 0x70; ji = ji + 1 } // server_random 163 sh_no_ks[38] = 0 // session_id_len 164 sh_no_ks[39] = 0x13; sh_no_ks[40] = 0x03 // cipher 165 sh_no_ks[41] = 0 // compression 166 sh_no_ks[42] = 0; sh_no_ks[43] = 2 // ext_list_len = 2 167 sh_no_ks[44] = 0; sh_no_ks[45] = 0x2B // ext_type = 0x002B (supported_versions, NOT keyshare) 168 let v_d: i64 = nx_tls13_client_session_recv_sh(s3, sh_no_ks, 46) 169 // The build above has bad ext layout; expect either BAD_FORMAT or NO_KEYSHARE. 170 if v_d != NX_TLS13_RECV_SH_NO_KEYSHARE { 171 if v_d != NX_TLS13_RECV_SH_BAD_FORMAT { return 110 } 172 } 173 174 // ---- Test E: SH with wrong group (not X25519) -> BAD_GROUP ---- 175 // B4-P256-KEYSHARE: secp256r1 (0x0017) is now a SUPPORTED group, 176 // so the unsupported-group probe uses secp384r1 (0x0018). 177 let s4: *Tls13ClientSession = nx_tls13_client_session_new(client_random, priv) 178 nx_tls13_client_session_emit_ch(s4, sni, 7, ch_buf, 512) 179 let sh_wrong_grp: *u8 = sys_mmap(128) 180 build_sh(sh_wrong_grp, server_random, server_pub) 181 sh_wrong_grp[48] = 0; sh_wrong_grp[49] = 0x18 // group = 0x0018 (secp384r1, unsupported) 182 let v_e: i64 = nx_tls13_client_session_recv_sh(s4, sh_wrong_grp, 84) 183 if v_e != NX_TLS13_RECV_SH_BAD_GROUP { return 120 } 184 185 // ---- Test E2: secp256r1 group, x25519-length body (32) ---- 186 // Accepted group, wrong key_exchange length -> BAD_KEYSHARE_LEN. 187 let s4b: *Tls13ClientSession = nx_tls13_client_session_new(client_random, priv) 188 nx_tls13_client_session_emit_ch(s4b, sni, 7, ch_buf, 512) 189 let sh_p256_short: *u8 = sys_mmap(128) 190 build_sh(sh_p256_short, server_random, server_pub) 191 sh_p256_short[48] = 0; sh_p256_short[49] = 0x17 // group = secp256r1 192 let v_e2: i64 = nx_tls13_client_session_recv_sh(s4b, sh_p256_short, 84) 193 if v_e2 != NX_TLS13_RECV_SH_BAD_KEYSHARE_LEN { return 121 } 194 195 // ---- Test F: SH with wrong keyshare length -> BAD_KEYSHARE_LEN ---- 196 let s5: *Tls13ClientSession = nx_tls13_client_session_new(client_random, priv) 197 nx_tls13_client_session_emit_ch(s5, sni, 7, ch_buf, 512) 198 let sh_wrong_len: *u8 = sys_mmap(128) 199 build_sh(sh_wrong_len, server_random, server_pub) 200 sh_wrong_len[50] = 0; sh_wrong_len[51] = 16 // ke_len = 16 (wrong; X25519 needs 32) 201 let v_f: i64 = nx_tls13_client_session_recv_sh(s5, sh_wrong_len, 84) 202 if v_f != NX_TLS13_RECV_SH_BAD_KEYSHARE_LEN { return 130 } 203 204 // ---- Test G: verdict gate ---- 205 if nx_tls13_recv_sh_verdict_is_valid(NX_TLS13_RECV_SH_OK) != 1 { return 140 } 206 if nx_tls13_recv_sh_verdict_is_valid(NX_TLS13_RECV_SH_BAD_STATE) != 1 { return 141 } 207 if nx_tls13_recv_sh_verdict_is_valid(NX_TLS13_RECV_SH_BAD_FORMAT) != 1 { return 142 } 208 if nx_tls13_recv_sh_verdict_is_valid(NX_TLS13_RECV_SH_NO_KEYSHARE) != 1 { return 143 } 209 if nx_tls13_recv_sh_verdict_is_valid(NX_TLS13_RECV_SH_BAD_GROUP) != 1 { return 144 } 210 if nx_tls13_recv_sh_verdict_is_valid(NX_TLS13_RECV_SH_BAD_KEYSHARE_LEN) != 1 { return 145 } 211 if nx_tls13_recv_sh_verdict_is_valid(NX_TLS13_RECV_SH_INTERNAL) != 1 { return 146 } 212 if nx_tls13_recv_sh_verdict_is_valid(NX_TLS13_RECV_SH_VERDICT_N) != 0 { return 147 } 213 if nx_tls13_recv_sh_verdict_is_valid(0) != 0 { return 148 } 214 if nx_tls13_recv_sh_verdict_is_valid(0 - 1) != 0 { return 149 } 215 216 return 0 217}