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}