nx_tls13_server_session_emit_ee.nx source
↩ module page · 109 lines · 3764 B
1// nx_tls13_server_session_emit_ee.nx -- 6th TLS server stone.
2//
3// Emits a minimal EncryptedExtensions handshake message,
4// AEAD-encrypted under server_hs_traffic_key + iv as a TLS 1.3
5// record (type=23 application_data wrapper).
6//
7// Inner content (handshake plaintext):
8// HT_ENCRYPTED_EXTENSIONS = 0x08 (1 byte)
9// body_len = 0x000002 (3 bytes, u24 big-endian)
10// extensions_list_len = 0x0000 (2 bytes; no EE extensions in v1)
11// Total = 6 bytes
12//
13// Record format (on wire):
14// header(5 bytes) type=0x17 (app_data) + version=0x0303 + length(2)
15// ciphertext (encrypted plaintext + inner type byte)
16// auth_tag(16 bytes)
17//
18// Precondition: state == EE_SENT (set by derive_hs_secrets;
19// indicates handshake keys are derived and EE is the next message).
20// Postcondition: state == CERT_SENT.
21//
22// license_tier: ORIGINAL
23
24import "nx_syscalls.nx"
25import "nx_tls13.nx"
26import "nx_tls13_record.nx"
27import "nx_tls13_transcript.nx"
28import "nx_tls13_server_session.nx"
29
30const NX_TLS13_EE_INNER_LEN: i64 = 6 // HT + u24 + ext_list_len
31const NX_TLS13_REC_HEADER: i64 = 5
32const NX_TLS13_REC_TAG: i64 = 16
33
34func nx_tls13_server_session_emit_ee(
35 session: *Tls13ServerSession,
36 out: *u8, out_cap: i64
37) -> i64 {
38 if (session as i64) == 0 { return 0 - NX_TLS13_SSESSION_BAD_STATE }
39 if (out as i64) == 0 { return 0 - NX_TLS13_SSESSION_BAD_STATE }
40 if session.state != NX_TLS13_SSTATE_EE_SENT {
41 return 0 - NX_TLS13_SSESSION_BAD_STATE
42 }
43 if (session.server_hs_traffic_key as i64) == 0 {
44 return 0 - NX_TLS13_SSESSION_INTERNAL
45 }
46 if (session.server_hs_iv as i64) == 0 {
47 return 0 - NX_TLS13_SSESSION_INTERNAL
48 }
49
50 // Build the 6-byte EncryptedExtensions plaintext.
51 let inner: *u8 = sys_mmap(NX_TLS13_EE_INNER_LEN)
52 inner[0] = HT_ENCRYPTED_EXTENSIONS & 0xff
53 inner[1] = 0 // body_len[0]
54 inner[2] = 0 // body_len[1]
55 inner[3] = 2 // body_len[2] = 2
56 inner[4] = 0 // ext_list_len[0]
57 inner[5] = 0 // ext_list_len[1] = 0
58
59 // record layout: header(5) + ct(6+1+pad) + tag(16) = ~28 bytes
60 let total_needed: i64 = NX_TLS13_REC_HEADER + NX_TLS13_EE_INNER_LEN + 1 + NX_TLS13_REC_TAG
61 if out_cap < total_needed { return 0 - NX_TLS13_SSESSION_BUF_OVERFLOW }
62
63 let header_buf: *u8 = sys_mmap(NX_TLS13_REC_HEADER)
64 let ct_len: i64 = NX_TLS13_EE_INNER_LEN + 1 // plaintext + inner type
65 let ct_buf: *u8 = sys_mmap(ct_len + 16)
66 let tag_buf: *u8 = sys_mmap(NX_TLS13_REC_TAG)
67
68 let rv: i64 = nx_tls13_record_encrypt_v2(
69 session.cipher_suite,
70 session.server_hs_traffic_key,
71 session.server_hs_iv,
72 session.server_seq,
73 inner, NX_TLS13_EE_INNER_LEN,
74 CT_HANDSHAKE,
75 0, // no padding
76 header_buf, ct_buf, tag_buf)
77 if rv != NX_TLS13_REC_VERDICT_OK {
78 return 0 - NX_TLS13_SSESSION_INTERNAL
79 }
80
81 // Write header + ct + tag to output buffer.
82 var w: i64 = 0
83 var i: i64 = 0
84 while i < NX_TLS13_REC_HEADER {
85 out[w + i] = header_buf[i]
86 i = i + 1
87 }
88 w = w + NX_TLS13_REC_HEADER
89 var j: i64 = 0
90 while j < ct_len {
91 out[w + j] = ct_buf[j]
92 j = j + 1
93 }
94 w = w + ct_len
95 var k: i64 = 0
96 while k < NX_TLS13_REC_TAG {
97 out[w + k] = tag_buf[k]
98 k = k + 1
99 }
100 w = w + NX_TLS13_REC_TAG
101
102 // Feed the PLAINTEXT EE handshake bytes into transcript hash.
103 // (Transcript captures handshake messages, not their AEAD records.)
104 nx_tls13_transcript_update(session.transcript, inner, NX_TLS13_EE_INNER_LEN)
105
106 session.server_seq = session.server_seq + 1
107 session.state = NX_TLS13_SSTATE_CERT_SENT
108 return w
109}