nx_tls13_client_session_emit_finished_test.nx source
↩ module page · 88 lines · 4155 B
1// nx_tls13_client_session_emit_finished_test.nx -- KAT for
2// step 3c.4: emit + encrypt client Finished.
3//
4// Full happy-path of the underlying tls13_client_emit_finished +
5// nx_tls13_record_encrypt round-trip is proven by the shipped
6// nx_tls13_loopback_test. This KAT verifies the WRAPPER's
7// contract surface:
8// - state guards (must be at WAIT_CLIENT_FIN)
9// - buf-overflow guard (need at least 58 bytes)
10// - client_seq increments on every call
11// - state advances to WAIT_APP_KEYS on success, preserved on
12// state-guard failure
13// - sealed verdict gate
14//
15// expect_exit: 0
16// license_tier: ORIGINAL
17
18import "nx_syscalls.nx"
19import "nx_tls13.nx"
20import "nx_tls13_client_session.nx"
21import "nx_tls13_client_session_emit_finished.nx"
22
23func main() -> i64 {
24 let client_random: *u8 = sys_mmap(32)
25 var i: i64 = 0
26 while i < 32 { client_random[i] = (0xC0 + i) as u8; i = i + 1 }
27 let priv: *u8 = sys_mmap(32)
28 i = 0
29 while i < 32 { priv[i] = (0x40 + i) as u8; i = i + 1 }
30
31 // ---- Test A: emit_finished from INIT state -> BAD_STATE ----
32 let s1: *Tls13ClientSession = nx_tls13_client_session_new(client_random, priv)
33 let buf: *u8 = sys_mmap(128)
34 let v_a: i64 = nx_tls13_client_session_emit_finished(s1, buf, 128)
35 if v_a != (0 - NX_TLS13_EMIT_CF_BAD_STATE) { return 1 }
36 // State unchanged on failure
37 if s1.state != NX_TLS13_CSESSION_STATE_INIT { return 2 }
38 // client_seq unchanged on state-guard failure (we never reached encrypt)
39 if s1.client_seq != 0 { return 3 }
40
41 // ---- Test B: emit_finished from WAIT_APP_KEYS -> BAD_STATE ----
42 s1.state = NX_TLS13_CSESSION_STATE_WAIT_APP_KEYS
43 if nx_tls13_client_session_emit_finished(s1, buf, 128) != (0 - NX_TLS13_EMIT_CF_BAD_STATE) { return 5 }
44 if s1.state != NX_TLS13_CSESSION_STATE_WAIT_APP_KEYS { return 6 }
45
46 // ---- Test C: emit_finished with tiny buf -> BUF_OVERFLOW ----
47 s1.state = NX_TLS13_CSESSION_STATE_WAIT_CLIENT_FIN
48 let tiny_buf: *u8 = sys_mmap(32)
49 if nx_tls13_client_session_emit_finished(s1, tiny_buf, 32) != (0 - NX_TLS13_EMIT_CF_BUF_OVERFLOW) { return 10 }
50 // State preserved on cap failure
51 if s1.state != NX_TLS13_CSESSION_STATE_WAIT_CLIENT_FIN { return 11 }
52 if s1.client_seq != 0 { return 12 }
53
54 // ---- Test D: emit_finished happy path returns 58 bytes ----
55 // We need a valid client_hs_traffic_secret + key + iv for the
56 // encrypt to produce output. The session_new() call mmap'd
57 // these (zeros). HMAC over zero secret + ChaCha20 over zero
58 // key + zero IV both produce DETERMINISTIC output (HMAC is
59 // well-defined for any key length including all-zero;
60 // ChaCha20-Poly1305 likewise). So even with all-zero crypto
61 // state the round-trip is byte-deterministic.
62 let buf2: *u8 = sys_mmap(128)
63 let v_d: i64 = nx_tls13_client_session_emit_finished(s1, buf2, 128)
64 if v_d != NX_TLS13_CF_RECORD_BYTES { return 20 } // 58
65 // State advances to WAIT_APP_KEYS
66 if s1.state != NX_TLS13_CSESSION_STATE_WAIT_APP_KEYS { return 21 }
67 // client_seq increments by 1
68 if s1.client_seq != 1 { return 22 }
69 // Record header: TLSCiphertext byte = 23 (application_data)
70 if (buf2[0] & 0xff) != 0x17 { return 23 }
71 // Legacy version 0x03 0x03
72 if (buf2[1] & 0xff) != 0x03 { return 24 }
73 if (buf2[2] & 0xff) != 0x03 { return 25 }
74 // Record length field = 58 - 5 = 53 (= 37 inner + 16 tag)
75 let rec_len: i64 = ((buf2[3] & 0xff) << 8) | (buf2[4] & 0xff)
76 if rec_len != 53 { return 26 }
77
78 // ---- Test E: sealed verdict gate ----
79 if nx_tls13_emit_cf_verdict_is_valid(NX_TLS13_EMIT_CF_OK) != 1 { return 30 }
80 if nx_tls13_emit_cf_verdict_is_valid(NX_TLS13_EMIT_CF_BAD_STATE) != 1 { return 31 }
81 if nx_tls13_emit_cf_verdict_is_valid(NX_TLS13_EMIT_CF_BUF_OVERFLOW) != 1 { return 32 }
82 if nx_tls13_emit_cf_verdict_is_valid(NX_TLS13_EMIT_CF_INTERNAL) != 1 { return 33 }
83 if nx_tls13_emit_cf_verdict_is_valid(NX_TLS13_EMIT_CF_VERDICT_N) != 0 { return 34 }
84 if nx_tls13_emit_cf_verdict_is_valid(0) != 0 { return 35 }
85 if nx_tls13_emit_cf_verdict_is_valid(0 - 1) != 0 { return 36 }
86
87 return 0
88}