nx_tls13_server_session_app_data.nx source
↩ module page · 150 lines · 5494 B
1// nx_tls13_server_session_app_data.nx -- application-data layer for
2// a CONNECTED Tls13ServerSession.
3//
4// After the handshake completes (state CONNECTED), the session has
5// derived application traffic keys for both directions:
6// server_app_traffic_key + server_app_iv (for what WE send)
7// client_app_traffic_key + client_app_iv (for what we RECEIVE)
8//
9// Sequence numbers RESET to 0 for the app-data phase per RFC 8446
10// §5.3. This file ships:
11//
12// nx_tls13_server_session_app_send(session, payload, len, out, cap)
13// Encrypts payload as a TLS application_data record under
14// server_app_*; increments server_app_seq; returns bytes written.
15//
16// nx_tls13_server_session_app_recv(session, record, rec_len, out, cap)
17// Decrypts a TLS record under client_app_*; validates record type
18// is APPLICATION_DATA inside; writes plaintext to out; increments
19// client_app_seq; returns plaintext byte count.
20//
21// This is the substrate primitive HTTPS callers use after handshake
22// to actually serve request/response bytes.
23//
24// license_tier: ORIGINAL
25
26import "nx_syscalls.nx"
27import "nx_tls13.nx"
28import "nx_tls13_record.nx"
29import "nx_tls13_server_session.nx"
30
31const NX_TLS13_APP_REC_HEADER: i64 = 5
32const NX_TLS13_APP_REC_TAG: i64 = 16
33
34func nx_tls13_server_session_app_send(
35 session: *Tls13ServerSession,
36 payload: *u8, payload_len: i64,
37 out: *u8, out_cap: i64
38) -> i64 {
39 if (session as i64) == 0 { return 0 - NX_TLS13_SSESSION_BAD_STATE }
40 if (out as i64) == 0 { return 0 - NX_TLS13_SSESSION_BAD_STATE }
41 if (payload as i64) == 0 { return 0 - NX_TLS13_SSESSION_BAD_STATE }
42 if payload_len < 0 { return 0 - NX_TLS13_SSESSION_BAD_STATE }
43 if session.state != NX_TLS13_SSTATE_CONNECTED {
44 return 0 - NX_TLS13_SSESSION_BAD_STATE
45 }
46 if (session.server_app_traffic_key as i64) == 0 {
47 return 0 - NX_TLS13_SSESSION_INTERNAL
48 }
49
50 let total_needed: i64 = NX_TLS13_APP_REC_HEADER + payload_len + 1 + NX_TLS13_APP_REC_TAG
51 if out_cap < total_needed { return 0 - NX_TLS13_SSESSION_BUF_OVERFLOW }
52
53 let header_buf: *u8 = sys_mmap(NX_TLS13_APP_REC_HEADER)
54 let ct_buf: *u8 = sys_mmap(payload_len + 17)
55 let tag_buf: *u8 = sys_mmap(NX_TLS13_APP_REC_TAG)
56
57 let rv: i64 = nx_tls13_record_encrypt_v2(
58 session.cipher_suite,
59 session.server_app_traffic_key,
60 session.server_app_iv,
61 session.server_app_seq,
62 payload, payload_len,
63 CT_APPLICATION_DATA, // inner type = application data
64 0, // no padding
65 header_buf, ct_buf, tag_buf)
66 if rv != NX_TLS13_REC_VERDICT_OK {
67 return 0 - NX_TLS13_SSESSION_INTERNAL
68 }
69
70 var w: i64 = 0
71 var hi: i64 = 0
72 while hi < NX_TLS13_APP_REC_HEADER {
73 out[w + hi] = header_buf[hi]
74 hi = hi + 1
75 }
76 w = w + NX_TLS13_APP_REC_HEADER
77 let ct_len: i64 = payload_len + 1 // payload + inner type byte
78 var ci: i64 = 0
79 while ci < ct_len {
80 out[w + ci] = ct_buf[ci]
81 ci = ci + 1
82 }
83 w = w + ct_len
84 var ti: i64 = 0
85 while ti < NX_TLS13_APP_REC_TAG {
86 out[w + ti] = tag_buf[ti]
87 ti = ti + 1
88 }
89 w = w + NX_TLS13_APP_REC_TAG
90
91 session.server_app_seq = session.server_app_seq + 1
92 return w
93}
94
95func nx_tls13_server_session_app_recv(
96 session: *Tls13ServerSession,
97 record: *u8, record_len: i64,
98 out: *u8, out_cap: i64
99) -> i64 {
100 if (session as i64) == 0 { return 0 - NX_TLS13_SSESSION_BAD_STATE }
101 if (record as i64) == 0 { return 0 - NX_TLS13_SSESSION_BAD_STATE }
102 if (out as i64) == 0 { return 0 - NX_TLS13_SSESSION_BAD_STATE }
103 if session.state != NX_TLS13_SSTATE_CONNECTED {
104 return 0 - NX_TLS13_SSESSION_BAD_STATE
105 }
106 if (session.client_app_traffic_key as i64) == 0 {
107 return 0 - NX_TLS13_SSESSION_INTERNAL
108 }
109 if record_len < NX_TLS13_APP_REC_HEADER + 1 + NX_TLS13_APP_REC_TAG {
110 return 0 - NX_TLS13_SSESSION_PROTOCOL_ERR
111 }
112
113 let header: *u8 = record
114 if header[0] != 0x17 { // app_data record wrapper type
115 return 0 - NX_TLS13_SSESSION_PROTOCOL_ERR
116 }
117
118 let body_len: i64 = ((header[3] as i64) << 8) | (header[4] as i64)
119 if NX_TLS13_APP_REC_HEADER + body_len > record_len {
120 return 0 - NX_TLS13_SSESSION_PROTOCOL_ERR
121 }
122 let ct_len: i64 = body_len - NX_TLS13_APP_REC_TAG
123 if ct_len < 1 { return 0 - NX_TLS13_SSESSION_PROTOCOL_ERR }
124 let ct: *u8 = (((record as i64) + NX_TLS13_APP_REC_HEADER)) as *u8
125 let tag: *u8 = (((record as i64) + NX_TLS13_APP_REC_HEADER + ct_len)) as *u8
126
127 if out_cap < ct_len { return 0 - NX_TLS13_SSESSION_BUF_OVERFLOW }
128 let real_ct_box: *i64 = sys_mmap(8) as *i64
129 let real_len_box: *i64 = sys_mmap(8) as *i64
130
131 let rv: i64 = nx_tls13_record_decrypt_v2(
132 session.cipher_suite,
133 session.client_app_traffic_key,
134 session.client_app_iv,
135 session.client_app_seq,
136 header, ct, ct_len, tag,
137 out, real_ct_box, real_len_box)
138 if rv != NX_TLS13_REC_VERDICT_OK {
139 return 0 - NX_TLS13_SSESSION_PROTOCOL_ERR
140 }
141 // Real content type should be APPLICATION_DATA per RFC 8446 §5.5.
142 // (Mid-stream handshake messages like KeyUpdate are possible but
143 // we don't handle them in v1.)
144 if *real_ct_box != CT_APPLICATION_DATA {
145 return 0 - NX_TLS13_SSESSION_PROTOCOL_ERR
146 }
147
148 session.client_app_seq = session.client_app_seq + 1
149 return *real_len_box
150}