1use ytls_record::Content;
4use ytls_record::MsgType;
5use ytls_record::Record;
6
7use ytls_traits::CryptoConfig;
8use ytls_traits::{TlsLeftIn, TlsLeftOut};
9
10use ytls_traits::CryptoSha256TranscriptProcessor;
11use ytls_traits::CryptoX25519Processor;
15
16use ytls_keys::Tls13Keys;
17use ytls_traits::SecretStore;
18use ytls_traits::Tls13KeyScheduleApSha256;
19use ytls_traits::Tls13KeyScheduleDerivedSha256;
20use ytls_traits::Tls13KeyScheduleHandshakeSha256;
21use ytls_traits::Tls13KeyScheduleInit;
22
23use rand_core::CryptoRng;
24
25use crate::TlsClientCtxConfig;
26use crate::{CtxError, Rfc8446Error};
27
28use ytls_util::Nonce12;
29
30use ytls_ctx::HandshakeOrder;
31use ytls_keys::Tls13KeysHandshakeSha256;
32
33mod c_client_hello;
34
35mod c_client_finished;
36mod p_server_hello;
37mod p_wrapped;
38use p_server_hello::{ServerHello, ServerRecord};
39
40pub struct ClientHandshakeCtx<Config, Crypto: CryptoConfig, Rng> {
42 config: Config,
44 crypto: Crypto,
46 rng: Rng,
48
49 cur: HandshakeOrder,
50
51 transcript: Crypto::Hasher,
52 x25519: Option<Crypto::X25519>,
53
54 handshake_client_key: Option<[u8; 32]>,
55 handshake_client_iv: Option<Nonce12>,
56 handshake_server_key: Option<[u8; 32]>,
57 handshake_server_iv: Option<Nonce12>,
58
59 handshake_finished_server_key: Option<[u8; 32]>,
60 handshake_finished_client_key: Option<[u8; 32]>,
61
62 key_schedule: Option<([u8; 32], [u8; 32], [u8; 32])>,
63
64 is_complete: bool,
65}
66
67impl<Config, Crypto, Rng> ClientHandshakeCtx<Config, Crypto, Rng>
68where
69 Config: TlsClientCtxConfig,
70 Crypto: CryptoConfig,
71 Rng: CryptoRng,
72{
73 pub fn with_required(config: Config, crypto: Crypto, mut rng: Rng) -> Self {
75 let x25519 = Crypto::ecdhe_x25519(&mut rng);
76
77 Self {
78 config,
79 crypto,
80 rng,
81
82 cur: HandshakeOrder::default(),
83 transcript: Crypto::hasher_sha256(),
84 x25519: Some(x25519),
85
86 handshake_client_key: None,
87 handshake_client_iv: None,
88 handshake_server_key: None,
89 handshake_server_iv: None,
90
91 handshake_finished_server_key: None,
92 handshake_finished_client_key: None,
93
94 key_schedule: None,
95
96 is_complete: false,
97 }
98 }
99}
100
101use ytls_traits::CtxHandshakeProcessor;
102use ytls_traits::HandshakeComplete;
103
104impl<Config, Crypto, Rng> CtxHandshakeProcessor for ClientHandshakeCtx<Config, Crypto, Rng>
105where
106 Config: TlsClientCtxConfig,
107 Crypto: CryptoConfig,
108 Rng: CryptoRng,
109{
110 type Error = CtxError;
111 #[inline]
113 fn spin_handshake<Li: TlsLeftIn, Lo: TlsLeftOut, Ks: SecretStore>(
114 &mut self,
115 li: &mut Li,
116 lo: &mut Lo,
117 ks: &mut Ks,
118 ) -> Result<Option<HandshakeComplete>, Self::Error> {
119 if self.is_complete {
120 return Ok(Some(HandshakeComplete));
121 }
122
123 if self.cur.cur_is_created() {
124 self.do_client_hello(lo)?;
125 self.cur = HandshakeOrder::ClientHello;
126 }
127
128 let init_data = li.left_buf_in();
129 let init_len = init_data.len();
130 let mut data = init_data;
131
132 #[allow(unused_assignments)]
133 let mut consumed = 0;
134
135 loop {
136 if data.len() == 0 {
137 break;
138 }
139
140 let mut prc = ServerRecord::default();
141
142 let (rec, remaining) =
143 Record::parse_server(&mut prc, data).map_err(|e| CtxError::Record(e))?;
144
145 consumed = init_len - remaining.len();
146
147 match rec.content() {
148 Content::ChangeCipherSpec => {
149 }
152 Content::ApplicationData => {
153 match self.cur {
154 HandshakeOrder::ServerHello => {}
155 HandshakeOrder::ServerCertificates => {}
156 HandshakeOrder::ServerCertificateVerify => {}
157 HandshakeOrder::ServerFinished => {}
158 _ => return Err(CtxError::Rfc8446(Rfc8446Error::Unexpected)),
159 }
160
161 let key = match self.handshake_server_key {
162 Some(k) => k,
163 None => {
164 return Err(CtxError::Bug(
165 "Expected to have Server Key by now and was not guarded.",
166 ))
167 }
168 };
169
170 let nonce: [u8; 12] = match self.handshake_server_iv {
171 None => {
172 return Err(CtxError::Bug(
173 "Expected to have Server Iv by now and was not guarded.",
174 ))
175 }
176 Some(ref mut n) => match n.use_and_incr() {
177 Some(cur) => cur,
178 None => return Err(CtxError::ExhaustedIv),
179 },
180 };
181
182 let cipher = Crypto::aead_chaha20poly1305(&key);
183
184 let full_payload = rec.as_bytes();
185 let full_payload_len = full_payload.len();
186
187 let mut tag: [u8; 16] = [0; 16];
188
189 let body_len = full_payload_len - 16;
190 let mut body: [u8; 8192] = [0; 8192];
191
192 body[0..body_len].copy_from_slice(&full_payload[0..body_len]);
193
194 tag.copy_from_slice(&full_payload[body_len..body_len + 16]);
195
196 let additional_data = rec.header_as_bytes();
197
198 use ytls_traits::CryptoChaCha20Poly1305Processor;
199 cipher
200 .decrypt_in_place(&nonce, &additional_data, &mut body[0..body_len], &tag)
201 .map_err(|_| CtxError::Rfc8446(Rfc8446Error::Decrypt))?;
202
203 use ytls_record::{WrappedMsgType, WrappedRecord};
204 let r = WrappedRecord::parse_server(self, &body[0..body_len])
205 .map_err(|_| CtxError::Rfc8446(Rfc8446Error::Unexpected))?;
206
207 let hashing_body = &body[0..body_len - 1];
208
209 use ytls_record::HandshakeMsg;
210
211 match r.msg() {
212 WrappedMsgType::Alert(_alert) => {
213 }
215 WrappedMsgType::Handshake(HandshakeMsg {
216 msg: MsgType::EncryptedExtensions,
217 ..
218 }) => {
219 self.transcript.sha256_update(hashing_body);
221 }
222 WrappedMsgType::Handshake(HandshakeMsg {
223 msg: MsgType::ServerCertificate,
224 req_ctx: Some(0),
225 }) => {
226 self.transcript.sha256_update(hashing_body);
227 }
228 WrappedMsgType::Handshake(HandshakeMsg {
229 msg: MsgType::ServerCertificateVerify,
230 ..
231 }) => {
232 self.transcript.sha256_update(hashing_body);
233 }
234 WrappedMsgType::Handshake(HandshakeMsg {
235 msg: MsgType::ServerFinished,
236 ..
237 }) => {
238 self.transcript.sha256_update(hashing_body);
239
240 let finish_hasher = self.transcript.sha256_fork();
241
242 self.do_client_handshake_finished(lo)?;
243
244 let hs_k: Tls13KeysHandshakeSha256<Crypto> = match self.key_schedule {
245 Some(secrets) => Tls13KeysHandshakeSha256::from_secrets(
246 secrets.0, secrets.1, secrets.2,
247 ),
248 None => {
249 return Err(CtxError::Bug(
250 "Key schedule was not guarded for finish.",
251 ))
252 }
253 };
254
255 let finish_handshake_hash = finish_hasher.sha256_finalize();
256
257 let ap_k = hs_k.finished_handshake(&finish_handshake_hash);
258
259 let mut server_application_iv: [u8; 12] = [0; 12];
260 let mut server_application_key: [u8; 32] = [0; 32];
261 let mut client_application_iv: [u8; 12] = [0; 12];
262 let mut client_application_key: [u8; 32] = [0; 32];
263
264 ap_k.application_server_key(&mut server_application_key);
265 ap_k.application_server_iv(&mut server_application_iv);
266 ap_k.application_client_key(&mut client_application_key);
267 ap_k.application_client_iv(&mut client_application_iv);
268
269 ks.store_ap_client_key(&client_application_key);
270 ks.store_ap_client_iv(&client_application_iv);
271 ks.store_ap_server_key(&server_application_key);
272 ks.store_ap_server_iv(&server_application_iv);
273
274 self.is_complete = true;
275 }
276 _ => {
277 return Err(CtxError::Rfc8446(Rfc8446Error::Unexpected));
278 }
279 }
280 }
281 Content::Handshake(content) => {
282 let msg = content.msg();
283
284 match msg {
285 MsgType::ServerHello(_h) => {
286 if self.cur != HandshakeOrder::ClientHello {
287 return Err(CtxError::Rfc8446(Rfc8446Error::Unexpected));
288 }
289
290 let server_pk = match prc.server_hello.pk_x25519 {
291 Some(pk) => pk,
292 None => return Err(CtxError::Rfc8446(Rfc8446Error::Unexpected)),
293 };
294
295 let mut x25519: Option<Crypto::X25519> = None;
296 core::mem::swap(&mut x25519, &mut self.x25519);
297
298 let x25519 = match x25519 {
299 Some(x) => x,
300 None => return Err(CtxError::Rfc8446(Rfc8446Error::Unexpected)),
301 };
302
303 let shared_secret = x25519.x25519_shared_secret(&server_pk);
304
305 self.transcript.sha256_update(rec.as_bytes());
306 let hello_transcript = self.transcript.sha256_fork();
307 let hello_hash = hello_transcript.sha256_finalize();
308
309 let k = Tls13Keys::<Crypto>::no_psk_with_crypto_and_sha256();
310 let hs_k = k.dh_x25519(&shared_secret, &hello_hash);
311 let mut server_handshake_iv: [u8; 12] = [0; 12];
312 let mut server_handshake_key: [u8; 32] = [0; 32];
313 let mut server_handshake_finished_key: [u8; 32] = [0; 32];
314 hs_k.handshake_server_iv(&mut server_handshake_iv);
315 hs_k.handshake_server_key(&mut server_handshake_key);
316 hs_k.handshake_server_finished_key(&mut server_handshake_finished_key);
317
318 self.handshake_server_key = Some(server_handshake_key);
319 self.handshake_server_iv =
320 Some(Nonce12::from_ks_iv(&server_handshake_iv));
321 self.handshake_finished_server_key =
322 Some(server_handshake_finished_key);
323
324 let mut client_handshake_iv: [u8; 12] = [0; 12];
325 let mut client_handshake_key: [u8; 32] = [0; 32];
326 let mut client_handshake_finished_key: [u8; 32] = [0; 32];
327 hs_k.handshake_client_iv(&mut client_handshake_iv);
328 hs_k.handshake_client_key(&mut client_handshake_key);
329 hs_k.handshake_client_finished_key(&mut client_handshake_finished_key);
330 self.handshake_client_key = Some(client_handshake_key);
331 self.handshake_client_iv =
332 Some(Nonce12::from_ks_iv(&client_handshake_iv));
333 self.handshake_finished_client_key =
334 Some(client_handshake_finished_key);
335
336 self.key_schedule = Some(hs_k.into_secrets());
337
338 self.cur = HandshakeOrder::ServerHello;
339 }
340 _ => {
341 return Err(CtxError::Rfc8446(Rfc8446Error::Unexpected));
342 }
343 }
344 }
345 Content::Alert(_alert) => {
346 }
348 }
349
350 if remaining.len() == 0 {
351 break;
352 }
353
354 data = remaining;
355 }
356
357 li.left_buf_mark_discard_in(consumed);
358
359 if self.is_complete {
360 return Ok(Some(HandshakeComplete));
361 }
362
363 Ok(None)
364 }
365}