nx_tls13_auth_test.nx source
↩ module page · 238 lines · 10048 B
1// nx_tls13_auth_test.nx -- KAT for EncryptedExtensions + Certificate
2// + CertificateVerify parsers.
3//
4// Hand-builds known-shape handshake messages, parses them, verifies
5// every extracted offset/length is correct. Tampered headers
6// rejected with the right verdict.
7//
8// expect_exit: 0
9// license_tier: ORIGINAL
10
11import "nx_syscalls.nx"
12import "nx_tls13.nx"
13import "nx_tls13_auth.nx"
14
15func main() -> i64 {
16 let buf: *u8 = sys_mmap(512)
17 let p_off: *i64 = sys_mmap(16) as *i64
18 let p_len: *i64 = sys_mmap(16) as *i64
19 let p_ctx_off: *i64 = sys_mmap(16) as *i64
20 let p_ctx_len: *i64 = sys_mmap(16) as *i64
21 let p_cert_off: *i64 = sys_mmap(16) as *i64
22 let p_cert_len: *i64 = sys_mmap(16) as *i64
23 let p_ce_off: *i64 = sys_mmap(16) as *i64
24 let p_ce_len: *i64 = sys_mmap(16) as *i64
25 let p_chain: *i64 = sys_mmap(16) as *i64
26 let p_scheme: *i64 = sys_mmap(16) as *i64
27
28 // ---- Test A: EncryptedExtensions with empty extensions list ----
29 // Body: ext_list_len(2)=0 -> total body 2 bytes
30 buf[0] = HT_ENCRYPTED_EXTENSIONS & 0xff
31 buf[1] = 0; buf[2] = 0; buf[3] = 2 // body_len = 2
32 buf[4] = 0; buf[5] = 0 // ext_list_len = 0
33 let v1: i64 = tls13_parse_encrypted_extensions(buf, 6, p_off, p_len)
34 if v1 != NX_TLS13_AUTH_VERDICT_OK { return 1 }
35 if *p_off != 6 { return 2 }
36 if *p_len != 0 { return 3 }
37
38 // ---- Test B: EncryptedExtensions with 5-byte extension blob ----
39 buf[0] = HT_ENCRYPTED_EXTENSIONS & 0xff
40 buf[1] = 0; buf[2] = 0; buf[3] = 7 // body_len = 7
41 buf[4] = 0; buf[5] = 5 // ext_list_len = 5
42 buf[6]=0xAA; buf[7]=0xBB; buf[8]=0xCC; buf[9]=0xDD; buf[10]=0xEE
43 let v2: i64 = tls13_parse_encrypted_extensions(buf, 11, p_off, p_len)
44 if v2 != NX_TLS13_AUTH_VERDICT_OK { return 4 }
45 if *p_off != 6 { return 5 }
46 if *p_len != 5 { return 6 }
47 // Recovered byte at offset *p_off
48 if (buf[*p_off] & 0xff) != 0xAA { return 7 }
49 if (buf[(*p_off) + 4] & 0xff) != 0xEE { return 8 }
50
51 // ---- Test C: EE with wrong msg_type rejected ----
52 buf[0] = HT_FINISHED & 0xff
53 let v3: i64 = tls13_parse_encrypted_extensions(buf, 11, p_off, p_len)
54 if v3 != NX_TLS13_AUTH_VERDICT_BAD_HEADER { return 9 }
55
56 // ---- Test D: EE truncated body rejected ----
57 buf[0] = HT_ENCRYPTED_EXTENSIONS & 0xff
58 buf[1] = 0; buf[2] = 0; buf[3] = 100 // claims 100-byte body
59 let v4: i64 = tls13_parse_encrypted_extensions(buf, 6, p_off, p_len)
60 if v4 != NX_TLS13_AUTH_VERDICT_TRUNCATED { return 10 }
61
62 // ---- Test E: Certificate with empty req_ctx + 1 cert (10 bytes) + empty ext ----
63 // Body:
64 // ctx_len(1) = 0
65 // chain_len(3)
66 // cert_len(3) = 10
67 // cert_data(10)
68 // cert_exts_len(2) = 0
69 // First-entry size = 3 + 10 + 2 + 0 = 15. chain_len = 15.
70 // Body = 1 + 3 + 15 = 19.
71 buf[0] = HT_CERTIFICATE & 0xff
72 buf[1] = 0; buf[2] = 0; buf[3] = 19 // body_len = 19
73 buf[4] = 0 // ctx_len = 0
74 buf[5] = 0; buf[6] = 0; buf[7] = 15 // chain_len = 15
75 buf[8] = 0; buf[9] = 0; buf[10] = 10 // cert_len = 10
76 // cert bytes at offsets 11..20
77 var i: i64 = 0
78 while i < 10 {
79 buf[11 + i] = 0x30 + i
80 i = i + 1
81 }
82 buf[21] = 0; buf[22] = 0 // ext_len = 0
83 let total: i64 = 23
84 let v5: i64 = tls13_parse_certificate_chain_first(
85 buf, total,
86 p_ctx_off, p_ctx_len,
87 p_cert_off, p_cert_len,
88 p_ce_off, p_ce_len,
89 p_chain
90 )
91 if v5 != NX_TLS13_AUTH_VERDICT_OK { return 20 }
92 if *p_ctx_len != 0 { return 21 }
93 if *p_chain != 15 { return 22 }
94 if *p_cert_off != 11 { return 23 }
95 if *p_cert_len != 10 { return 24 }
96 if (buf[*p_cert_off] & 0xff) != 0x30 { return 25 }
97 if (buf[(*p_cert_off) + 9] & 0xff) != 0x39 { return 26 }
98 if *p_ce_off != 23 { return 27 }
99 if *p_ce_len != 0 { return 28 }
100
101 // ---- Test F: Certificate truncated ----
102 // Claim 1000-byte body but provide only 19 actual bytes
103 buf[3] = 200
104 let v6: i64 = tls13_parse_certificate_chain_first(
105 buf, 30,
106 p_ctx_off, p_ctx_len,
107 p_cert_off, p_cert_len,
108 p_ce_off, p_ce_len,
109 p_chain
110 )
111 if v6 != NX_TLS13_AUTH_VERDICT_TRUNCATED { return 30 }
112 // restore body_len
113 buf[3] = 19
114
115 // ---- Test G: Certificate with empty chain rejected ----
116 buf[5] = 0; buf[6] = 0; buf[7] = 0 // chain_len = 0
117 // need to also fix body_len to skip the would-be cert
118 buf[3] = 4 // body = ctx(1) + chain_len(3) = 4
119 let v7: i64 = tls13_parse_certificate_chain_first(
120 buf, 8,
121 p_ctx_off, p_ctx_len,
122 p_cert_off, p_cert_len,
123 p_ce_off, p_ce_len,
124 p_chain
125 )
126 if v7 != NX_TLS13_AUTH_VERDICT_EMPTY_CHAIN { return 35 }
127
128 // ---- Test H: CertificateVerify with ed25519 + 64-byte sig ----
129 buf[0] = HT_CERTIFICATE_VERIFY & 0xff
130 buf[1] = 0; buf[2] = 0; buf[3] = 68 // body_len = 2 + 2 + 64
131 buf[4] = 0x08; buf[5] = 0x07 // scheme = ed25519
132 buf[6] = 0; buf[7] = 64 // sig_len = 64
133 i = 0
134 while i < 64 {
135 buf[8 + i] = 0x70 + i
136 i = i + 1
137 }
138 let v8: i64 = tls13_parse_certificate_verify(
139 buf, 72,
140 p_scheme, p_cert_off, p_cert_len
141 )
142 if v8 != NX_TLS13_AUTH_VERDICT_OK { return 40 }
143 if *p_scheme != 0x0807 { return 41 } // ed25519
144 if *p_cert_off != 8 { return 42 }
145 if *p_cert_len != 64 { return 43 }
146 if (buf[*p_cert_off] & 0xff) != 0x70 { return 44 }
147 if (buf[(*p_cert_off) + 63] & 0xff) != 0xaf { return 45 } // 0x70 + 63 = 0xaf
148
149 // ---- Test I: CertificateVerify truncated ----
150 let v9: i64 = tls13_parse_certificate_verify(
151 buf, 10,
152 p_scheme, p_cert_off, p_cert_len
153 )
154 if v9 != NX_TLS13_AUTH_VERDICT_TRUNCATED { return 50 }
155
156 // ---- Test J: oversize body rejected (>16384) ----
157 buf[0] = HT_ENCRYPTED_EXTENSIONS & 0xff
158 buf[1] = 0xff; buf[2] = 0xff; buf[3] = 0xff // claims 16M body
159 let v10: i64 = tls13_parse_encrypted_extensions(buf, 6, p_off, p_len)
160 if v10 != NX_TLS13_AUTH_VERDICT_TOO_LONG { return 60 }
161
162 // ---- Test K: verdict gate ----
163 if nx_tls13_auth_verdict_is_valid(NX_TLS13_AUTH_VERDICT_OK) != 1 { return 70 }
164 if nx_tls13_auth_verdict_is_valid(NX_TLS13_AUTH_VERDICT_N) != 0 { return 71 }
165 if nx_tls13_auth_verdict_is_valid(0 - 1) != 0 { return 72 }
166
167 // ---- Test L: tls13_parse_certificate_chain_all with 3 entries ----
168 // Build a 3-cert Certificate message:
169 // handshake header: 0x0B + 3-byte body length (= 64)
170 // body:
171 // 1-byte ctx len = 0
172 // 3-byte chain_total_len = 60
173 // entry 1: 3-byte cert_len=10 + 10 cert bytes + 2-byte ext=0 + 0 ext bytes
174 // entry 2: 3-byte cert_len=15 + 15 + 2 ext header
175 // entry 3: 3-byte cert_len=20 + 20 + 2 ext header
176 let m: *u8 = sys_mmap(256)
177 m[0] = HT_CERTIFICATE & 0xff
178 m[1] = 0; m[2] = 0; m[3] = 64 // body length 64
179 m[4] = 0 // ctx_len = 0
180 m[5] = 0; m[6] = 0; m[7] = 60 // chain_total_len = 60
181 // entry 1 (3+10+2 = 15 bytes total in chain space)
182 m[8] = 0; m[9] = 0; m[10] = 10 // cert_len = 10
183 // 10 cert bytes at [11..21]
184 var k: i64 = 0
185 while k < 10 { m[11 + k] = (0xA0 + k) as u8; k = k + 1 }
186 m[21] = 0; m[22] = 0 // ext_list_len = 0
187 // entry 2 starts at 23 (3+15+2 = 20 bytes)
188 m[23] = 0; m[24] = 0; m[25] = 15 // cert_len = 15
189 k = 0
190 while k < 15 { m[26 + k] = (0xB0 + k) as u8; k = k + 1 }
191 m[41] = 0; m[42] = 0
192 // entry 3 starts at 43 (3+20+2 = 25 bytes)
193 m[43] = 0; m[44] = 0; m[45] = 20 // cert_len = 20
194 k = 0
195 while k < 20 { m[46 + k] = (0xC0 + k) as u8; k = k + 1 }
196 m[66] = 0; m[67] = 0
197
198 let chain_offs: *u8 = sys_mmap(8 * 8) // 8-slot i64 array
199 let chain_lens: *u8 = sys_mmap(8 * 8)
200 let n_certs_p: *i64 = sys_mmap(16) as *i64
201 let v_all: i64 = tls13_parse_certificate_chain_all(
202 m, 68, chain_offs as *i64, chain_lens as *i64, n_certs_p, 8)
203 if v_all != NX_TLS13_AUTH_VERDICT_OK { return 80 }
204 if *n_certs_p != 3 { return 81 }
205 let offs: *i64 = chain_offs as *i64
206 let lens: *i64 = chain_lens as *i64
207 if offs[0] != 11 { return 82 }
208 if lens[0] != 10 { return 83 }
209 if offs[1] != 26 { return 84 }
210 if lens[1] != 15 { return 85 }
211 if offs[2] != 46 { return 86 }
212 if lens[2] != 20 { return 87 }
213 // Verify byte content of first byte of each cert
214 if (m[offs[0]] & 0xff) != 0xA0 { return 88 }
215 if (m[offs[1]] & 0xff) != 0xB0 { return 89 }
216 if (m[offs[2]] & 0xff) != 0xC0 { return 90 }
217
218 // ---- Test M: too-many-certs cap ----
219 // Re-call with max_certs=2 -- should fail before reading 3rd entry.
220 let v_full: i64 = tls13_parse_certificate_chain_all(
221 m, 68, chain_offs as *i64, chain_lens as *i64, n_certs_p, 2)
222 if v_full != NX_TLS13_AUTH_VERDICT_TOO_MANY_CERTS { return 100 }
223
224 // ---- Test N: max_certs=0 rejected ----
225 let v_zero: i64 = tls13_parse_certificate_chain_all(
226 m, 68, chain_offs as *i64, chain_lens as *i64, n_certs_p, 0)
227 if v_zero != NX_TLS13_AUTH_VERDICT_TOO_MANY_CERTS { return 101 }
228
229 // ---- Test O: empty chain rejected ----
230 let me: *u8 = sys_mmap(32)
231 me[0] = HT_CERTIFICATE & 0xff
232 me[1] = 0; me[2] = 0; me[3] = 4
233 me[4] = 0 // ctx_len = 0
234 me[5] = 0; me[6] = 0; me[7] = 0 // chain_total_len = 0
235 if tls13_parse_certificate_chain_all(me, 8, chain_offs as *i64, chain_lens as *i64, n_certs_p, 8) != NX_TLS13_AUTH_VERDICT_EMPTY_CHAIN { return 110 }
236
237 return 0
238}