nx_tls13_server_session_derive_traffic.nx source
↩ module page · 113 lines · 4533 B
1// nx_tls13_server_session_derive_traffic.nx -- 5th TLS server stone.
2//
3// After derive_hs_secrets produced the Handshake-Secret, derive the
4// per-direction handshake traffic secrets + their AEAD key + IV
5// per RFC 8446 ยง7.1:
6//
7// c_hs_traffic = Derive-Secret(HS, "c hs traffic", ClientHello..ServerHello)
8// s_hs_traffic = Derive-Secret(HS, "s hs traffic", ClientHello..ServerHello)
9// *_hs_key = HKDF-Expand-Label(*_hs_traffic, "key", "", aead_key_len)
10// *_hs_iv = HKDF-Expand-Label(*_hs_traffic, "iv", "", aead_iv_len)
11//
12// For ChaCha20-Poly1305: key=32 bytes, iv=12 bytes.
13//
14// This stone is the precondition for emit_ee_cert (next stone),
15// which must AEAD-encrypt the EncryptedExtensions + Certificate
16// messages under server_hs_key + server_hs_iv.
17//
18// State: requires EE_SENT (set by derive_hs_secrets); does not
19// advance state -- it's a continuation of the key-schedule
20// preparation. Subsequent emit_ee_cert advances state CERT_SENT.
21//
22// license_tier: ORIGINAL
23
24import "nx_syscalls.nx"
25import "nx_tls13.nx"
26import "nx_tls13_kdf.nx"
27import "nx_tls13_transcript.nx"
28import "nx_tls13_server_session.nx"
29
30const NX_TLS13_TRAFFIC_HASH_LEN: i64 = 32 // SHA-256 for ChaCha20-Poly1305
31const NX_TLS13_AEAD_KEY_LEN: i64 = 32 // ChaCha20 key length
32const NX_TLS13_AEAD_IV_LEN: i64 = 12 // AEAD nonce length
33
34func nx_tls13_server_session_derive_traffic(
35 session: *Tls13ServerSession
36) -> i64 {
37 if (session as i64) == 0 { return NX_TLS13_SSESSION_BAD_STATE }
38 // Precondition: handshake_secret has been derived (i.e., we're
39 // past derive_hs_secrets, which set state = EE_SENT).
40 if session.state != NX_TLS13_SSTATE_EE_SENT {
41 return NX_TLS13_SSESSION_BAD_STATE
42 }
43 if (session.handshake_secret as i64) == 0 {
44 return NX_TLS13_SSESSION_INTERNAL
45 }
46
47 // 1. Snapshot transcript hash over ClientHello..ServerHello.
48 let th: *u8 = sys_mmap(NX_TLS13_TRAFFIC_HASH_LEN)
49 let r_th: i64 = nx_tls13_transcript_snapshot(session.transcript, th)
50 if r_th != NX_TLS13_TX_VERDICT_OK { return NX_TLS13_SSESSION_INTERNAL }
51
52 // 2. Derive-Secret(HS, "c hs traffic", th) -> client_hs_traffic_secret
53 let c_label: *u8 = "c hs traffic"
54 let c_label_len: i64 = 12
55 let c_secret: *u8 = sys_mmap(NX_TLS13_TRAFFIC_HASH_LEN)
56 let r1: i64 = tls13_derive_secret(
57 session.handshake_secret,
58 c_label, c_label_len,
59 th, NX_TLS13_TRAFFIC_HASH_LEN,
60 c_secret)
61 if r1 != NX_TLS13_KDF_VERDICT_OK { return NX_TLS13_SSESSION_INTERNAL }
62 session.client_hs_traffic_secret = c_secret
63
64 // 3. Derive-Secret(HS, "s hs traffic", th) -> server_hs_traffic_secret
65 let s_label: *u8 = "s hs traffic"
66 let s_label_len: i64 = 12
67 let s_secret: *u8 = sys_mmap(NX_TLS13_TRAFFIC_HASH_LEN)
68 let r2: i64 = tls13_derive_secret(
69 session.handshake_secret,
70 s_label, s_label_len,
71 th, NX_TLS13_TRAFFIC_HASH_LEN,
72 s_secret)
73 if r2 != NX_TLS13_KDF_VERDICT_OK { return NX_TLS13_SSESSION_INTERNAL }
74 session.server_hs_traffic_secret = s_secret
75
76 // 4. Derive AEAD keys + IVs via HKDF-Expand-Label.
77 let key_label: *u8 = "key"
78 let iv_label: *u8 = "iv"
79 let empty: *u8 = sys_mmap(1)
80 // AEAD key length depends on the negotiated cipher: AES-128-GCM=16,
81 // ChaCha20-Poly1305=32. IV stays 12 for both.
82 let akl: i64 = nx_tls13_aead_key_len(session.cipher_suite)
83
84 let c_key: *u8 = sys_mmap(akl)
85 let r3: i64 = tls13_hkdf_expand_label(
86 c_secret, key_label, 3, empty, 0,
87 akl, c_key)
88 if r3 != NX_TLS13_KDF_VERDICT_OK { return NX_TLS13_SSESSION_INTERNAL }
89 session.client_hs_traffic_key = c_key
90
91 let c_iv: *u8 = sys_mmap(NX_TLS13_AEAD_IV_LEN)
92 let r4: i64 = tls13_hkdf_expand_label(
93 c_secret, iv_label, 2, empty, 0,
94 NX_TLS13_AEAD_IV_LEN, c_iv)
95 if r4 != NX_TLS13_KDF_VERDICT_OK { return NX_TLS13_SSESSION_INTERNAL }
96 session.client_hs_iv = c_iv
97
98 let s_key: *u8 = sys_mmap(akl)
99 let r5: i64 = tls13_hkdf_expand_label(
100 s_secret, key_label, 3, empty, 0,
101 akl, s_key)
102 if r5 != NX_TLS13_KDF_VERDICT_OK { return NX_TLS13_SSESSION_INTERNAL }
103 session.server_hs_traffic_key = s_key
104
105 let s_iv: *u8 = sys_mmap(NX_TLS13_AEAD_IV_LEN)
106 let r6: i64 = tls13_hkdf_expand_label(
107 s_secret, iv_label, 2, empty, 0,
108 NX_TLS13_AEAD_IV_LEN, s_iv)
109 if r6 != NX_TLS13_KDF_VERDICT_OK { return NX_TLS13_SSESSION_INTERNAL }
110 session.server_hs_iv = s_iv
111
112 return NX_TLS13_SSESSION_OK
113}