Skip to main content

ytls_server/server_ctx/
s_handshake.rs

1//! yTls Server Handshake Context
2
3use ytls_record::Content;
4use ytls_record::MsgType;
5use ytls_record::Record;
6
7mod r_server_hello;
8mod s_client_finished;
9mod s_client_hello;
10
11mod r_encrypted_extensions;
12mod r_server_certificate_verify;
13mod r_server_certificates;
14mod r_server_handshake_finished;
15
16use ytls_traits::CryptoConfig;
17use ytls_traits::{TlsLeftIn, TlsLeftOut};
18
19use ytls_traits::CryptoSha256HkdfExtractProcessor;
20use ytls_traits::CryptoSha256HkdfGenProcessor;
21use ytls_traits::CryptoSha256TranscriptProcessor;
22use ytls_traits::CryptoSha384TranscriptProcessor;
23use ytls_traits::CryptoX25519Processor;
24
25use ytls_keys::Tls13Keys;
26use ytls_traits::SecretStore;
27use ytls_traits::Tls13KeyScheduleApSha256;
28use ytls_traits::Tls13KeyScheduleDerivedSha256;
29use ytls_traits::Tls13KeyScheduleHandshakeSha256;
30use ytls_traits::Tls13KeyScheduleInit;
31
32use rand_core::CryptoRng;
33
34use crate::TlsServerCtxConfig;
35use crate::{CtxError, Rfc8446Error};
36
37use ytls_util::Nonce12;
38
39use ytls_keys::Tls13KeysHandshakeSha256;
40
41/// State machine context for yTLS Server
42pub struct ServerHandshakeCtx<Config, Crypto, Rng> {
43    /// Downstream config implementation
44    config: Config,
45    /// Downstream crypto implementation
46    crypto: Crypto,
47    /// Downstream rng implementation
48    rng: Rng,
49    /// Downstream found host through SNI
50    downstream_found_host: bool,
51    /// X25519 Group supported
52    group_x25519_supported: bool,
53    /// TLS_CHACHA20_POLY1305_SHA256 supported
54    chacha20_poly1305_sha256_supported: bool,
55    /// Ed25519 Signature Algorithm supported
56    sig_alg_ed25519_supported: bool,
57    /// TLS 1.3 supported
58    tls13_supported: bool,
59    /// Extended main secret used
60    extended_main_secret: bool,
61    /// Record size limit
62    record_size_limit: u16,
63    /// Signed Certificage Timestamps
64    signed_cert_ts: bool,
65    /// Sig alg RsaPkcs1Sha256 supported ?
66    sig_alg_rsa_pkcs1_sha256_supported: bool,
67
68    //--------------------------------------------
69    // TODO: Move all of the below away from here
70    //       some of these shoul get zeroized too
71    //       probably best to do through type state
72    //--------------------------------------------
73    /// Client supplied random
74    client_random: Option<[u8; 32]>,
75    /// Client X25519 pk
76    client_x25519_pk: Option<[u8; 32]>,
77    /// Client Session Id (max 100 bytes)
78    // TODO: handle this better.. this is wasteful - protocol is dumb wasting bytes here.
79    client_session_id: Option<[u8; 100]>,
80    /// Client Session Id len (max 100 bytes)
81    client_session_len: usize,
82    /// Curve25519 Public Key
83    public_key: Option<[u8; 32]>,
84    /// Handshake secrets
85    // TODO: move these to vault provider and make sure they get zeroized
86    /// Shared Secret
87    shared_secret: Option<[u8; 32]>,
88    /// Key Share for X25519
89    key_share: [u8; 36],
90    handshake_server_key: Option<[u8; 32]>,
91    handshake_client_key: Option<[u8; 32]>,
92    handshake_server_iv: Option<Nonce12>,
93    handshake_client_iv: Option<Nonce12>,
94    handshake_finished_server_key: Option<[u8; 32]>,
95    handshake_finished_client_key: Option<[u8; 32]>,
96
97    // TODO: get rid of these (atleast from here)
98    signature_cert_verify: Option<[u8; 100]>,
99    signature_cert_verify_len: usize,
100    /// cert verify ctx hash sha256
101    cert_verify_hash: Option<[u8; 32]>,
102    /// Client+Server hellos hash
103    hello_hash: Option<[u8; 32]>,
104    /// Handshake finished hash
105    hash_finished: Option<[u8; 32]>,
106
107    is_complete: bool,
108}
109
110impl<Config, Crypto, Rng> ServerHandshakeCtx<Config, Crypto, Rng>
111where
112    Config: TlsServerCtxConfig,
113    Crypto: CryptoConfig,
114    Rng: CryptoRng,
115{
116    /// New yTLS server context with the given configuration
117    pub fn with_required(config: Config, crypto: Crypto, rng: Rng) -> Self {
118        Self {
119            config,
120            crypto,
121            rng,
122            downstream_found_host: false,
123            group_x25519_supported: false,
124            chacha20_poly1305_sha256_supported: false,
125            sig_alg_ed25519_supported: false,
126            tls13_supported: false,
127            extended_main_secret: false,
128            record_size_limit: 0,
129            signed_cert_ts: false,
130            sig_alg_rsa_pkcs1_sha256_supported: false,
131            client_random: None,
132            client_x25519_pk: None,
133            client_session_id: None,
134            client_session_len: 0,
135            public_key: None,
136            shared_secret: None,
137            key_share: [0; 36],
138            handshake_server_key: None,
139            handshake_client_key: None,
140            handshake_server_iv: None,
141            handshake_client_iv: None,
142            handshake_finished_server_key: None,
143            handshake_finished_client_key: None,
144
145            cert_verify_hash: None,
146            hello_hash: None,
147            hash_finished: None,
148            signature_cert_verify: None,
149            signature_cert_verify_len: 0,
150
151            is_complete: false,
152        }
153    }
154}
155
156use ytls_traits::CtxApplicationProcessor;
157use ytls_traits::CtxHandshakeProcessor;
158use ytls_traits::HandshakeComplete;
159
160impl<Config, Crypto, Rng> CtxHandshakeProcessor for ServerHandshakeCtx<Config, Crypto, Rng>
161where
162    Config: TlsServerCtxConfig,
163    Crypto: CryptoConfig,
164    Rng: CryptoRng,
165{
166    type Error = CtxError;
167    /// Spin yTLS Server Handshake Context
168    #[inline]
169    fn spin_handshake<Li: TlsLeftIn, Lo: TlsLeftOut, Ks: SecretStore>(
170        &mut self,
171        li: &mut Li,
172        lo: &mut Lo,
173        ks: &mut Ks,
174    ) -> Result<Option<HandshakeComplete>, Self::Error> {
175        if self.is_complete {
176            return Ok(Some(HandshakeComplete));
177        }
178
179        let init_data = li.left_buf_in();
180        let init_len = init_data.len();
181        let mut data = init_data;
182
183        if init_len == 0 {
184            return Ok(None);
185        }
186
187        #[allow(unused_assignments)]
188        let mut consumed = 0;
189
190        loop {
191            let (rec, remaining) =
192                Record::parse_client(self, data).map_err(|e| CtxError::Record(e))?;
193
194            consumed = init_len - remaining.len();
195
196            // TODO: why is this still here?
197            if self.shared_secret.is_none() {
198                if let Some(pk) = self.client_x25519_pk {
199                    let x25519_ctx = self.crypto.x25519_init(&mut self.rng);
200                    self.public_key = Some(x25519_ctx.x25519_public_key());
201                    self.shared_secret = Some(x25519_ctx.x25519_shared_secret(&pk));
202                    self.key_share = self.key_share_x25519();
203                }
204            }
205
206            match rec.content() {
207                Content::ChangeCipherSpec => {
208                    // ignore
209                }
210                Content::ApplicationData => {
211                    let key = match self.handshake_client_key {
212                        Some(k) => k,
213                        None => return Err(CtxError::Bug(
214                            "Did not have client key for decrypting. Was supposed to be guarded.",
215                        )),
216                    };
217
218                    let nonce: [u8; 12] = match self.handshake_client_iv {
219                        None => return Err(CtxError::MissingHandshakeIv),
220                        Some(ref mut n) => match n.use_and_incr() {
221                            Some(cur) => cur,
222                            None => return Err(CtxError::ExhaustedIv),
223                        },
224                    };
225
226                    let cipher = Crypto::aead_chaha20poly1305(&key);
227
228                    let full_payload = rec.as_bytes();
229                    let full_payload_len = full_payload.len();
230
231                    let mut tag: [u8; 16] = [0; 16];
232
233                    let body_len = full_payload_len - 16;
234                    let mut body: [u8; 8192] = [0; 8192];
235
236                    body[0..body_len].copy_from_slice(&full_payload[0..body_len]);
237
238                    tag.copy_from_slice(&full_payload[body_len..body_len + 16]);
239
240                    let additional_data = rec.header_as_bytes();
241
242                    use ytls_traits::CryptoChaCha20Poly1305Processor;
243                    cipher
244                        .decrypt_in_place(&nonce, &additional_data, &mut body[0..body_len], &tag)
245                        .map_err(|_| CtxError::Rfc8446(Rfc8446Error::Decrypt))?;
246
247                    use ytls_record::{WrappedMsgType, WrappedRecord};
248                    let r = WrappedRecord::parse_client(&body[0..body_len])
249                        .map_err(|_| CtxError::Rfc8446(Rfc8446Error::Unexpected))?;
250
251                    use ytls_record::HandshakeMsg;
252
253                    match r.msg() {
254                        WrappedMsgType::Handshake(HandshakeMsg {
255                            msg: MsgType::ClientFinished(f),
256                            ..
257                        }) => {
258                            self.check_client_finished(&f)?;
259                            self.is_complete = true;
260                            break;
261                        }
262                        WrappedMsgType::Alert(_alert) => {
263                            // do nothing with it for now
264                        }
265                        _ => {
266                            return Err(CtxError::Rfc8446(Rfc8446Error::Unexpected));
267                        }
268                    }
269                }
270                Content::Handshake(content) => {
271                    let msg = content.msg();
272                    match msg {
273                        MsgType::ClientFinished(_) => {
274                            return Err(CtxError::Rfc8446(Rfc8446Error::Unexpected));
275                        }
276                        MsgType::ClientHello(_h) => {
277                            let shared_secret = match self.shared_secret {
278                                Some(s) => s,
279                                None => {
280                                    return Err(CtxError::Bug(
281                                        "Supposed to have shared secret and was not guarded.",
282                                    ))
283                                }
284                            };
285
286                            // TODO: move this to ctx (generalize)
287                            let mut transcript = Crypto::sha256_init();
288                            transcript.sha256_update(rec.as_bytes());
289                            self.do_server_hello(lo, &mut transcript)?;
290                            let mut transcript_more = transcript.sha256_fork();
291                            let hello_hash = transcript.sha256_finalize();
292
293                            self.hello_hash = Some(hello_hash);
294
295                            let k = Tls13Keys::<Crypto>::no_psk_with_crypto_and_sha256();
296                            let hs_k = k.dh_x25519(&shared_secret, &hello_hash);
297
298                            let mut server_handshake_iv: [u8; 12] = [0; 12];
299                            let mut server_handshake_key: [u8; 32] = [0; 32];
300                            let mut server_handshake_finished_key: [u8; 32] = [0; 32];
301                            hs_k.handshake_server_iv(&mut server_handshake_iv);
302                            hs_k.handshake_server_key(&mut server_handshake_key);
303                            hs_k.handshake_server_finished_key(&mut server_handshake_finished_key);
304
305                            self.handshake_server_key = Some(server_handshake_key);
306                            self.handshake_server_iv =
307                                Some(Nonce12::from_ks_iv(&server_handshake_iv));
308                            self.handshake_finished_server_key =
309                                Some(server_handshake_finished_key);
310
311                            let mut client_handshake_iv: [u8; 12] = [0; 12];
312                            let mut client_handshake_key: [u8; 32] = [0; 32];
313                            let mut client_handshake_finished_key: [u8; 32] = [0; 32];
314                            hs_k.handshake_client_iv(&mut client_handshake_iv);
315                            hs_k.handshake_client_key(&mut client_handshake_key);
316                            hs_k.handshake_client_finished_key(&mut client_handshake_finished_key);
317                            self.handshake_client_key = Some(client_handshake_key);
318                            self.handshake_client_iv =
319                                Some(Nonce12::from_ks_iv(&client_handshake_iv));
320                            self.handshake_finished_client_key =
321                                Some(client_handshake_finished_key);
322
323                            self.do_encrypted_extensions(lo, &mut transcript_more)?;
324
325                            self.do_server_certificates(lo, &mut transcript_more)?;
326
327                            self.do_server_certificate_verify(lo, &mut transcript_more)?;
328
329                            self.do_server_handshake_finished(lo, &mut transcript_more)?;
330
331                            let finish_handshake_hash =
332                                transcript_more.sha256_fork().sha256_finalize();
333                            self.hash_finished = Some(finish_handshake_hash);
334
335                            let ap_k = hs_k.finished_handshake(&finish_handshake_hash);
336
337                            let mut server_application_iv: [u8; 12] = [0; 12];
338                            let mut server_application_key: [u8; 32] = [0; 32];
339                            let mut client_application_iv: [u8; 12] = [0; 12];
340                            let mut client_application_key: [u8; 32] = [0; 32];
341
342                            ap_k.application_server_key(&mut server_application_key);
343                            ap_k.application_server_iv(&mut server_application_iv);
344                            ap_k.application_client_key(&mut client_application_key);
345
346                            ap_k.application_client_iv(&mut client_application_iv);
347
348                            ks.store_ap_client_key(&client_application_key);
349                            ks.store_ap_client_iv(&client_application_iv);
350                            ks.store_ap_server_key(&server_application_key);
351                            ks.store_ap_server_iv(&server_application_iv);
352                        }
353                        _ => return Err(CtxError::Rfc8446(Rfc8446Error::Unexpected)),
354                    }
355                }
356                Content::Alert(_alert) => {
357                    // do nothing with it for now
358                }
359            }
360
361            if remaining.len() == 0 {
362                break;
363            }
364
365            data = remaining;
366        }
367
368        li.left_buf_mark_discard_in(consumed);
369
370        if self.is_complete {
371            return Ok(Some(HandshakeComplete));
372        }
373
374        Ok(None)
375    }
376}