ytls_record/record/
handshake.rs

1//! Handhsake Record
2
3use ytls_traits::ClientHelloProcessor;
4use ytls_traits::ServerApRecordProcessor;
5use ytls_traits::ServerRecordProcessor;
6use ytls_traits::ServerWrappedRecordProcessor;
7
8mod extensions;
9pub use extensions::Extensions;
10mod cipher_suites;
11pub use cipher_suites::CipherSuites;
12
13mod client_hello;
14pub use client_hello::ClientHello;
15
16mod server_hello;
17pub use server_hello::ServerHello;
18
19mod server_certificate;
20pub use server_certificate::ServerCertificate;
21
22mod server_certificate_verify;
23pub use server_certificate_verify::ServerCertificateVerify;
24
25mod client_finished;
26pub use client_finished::ClientFinished;
27
28mod server_finished;
29pub use server_finished::ServerFinished;
30
31use crate::error::RecordError;
32
33use zerocopy::byteorder::network_endian::U16 as N16;
34use zerocopy::{Immutable, IntoBytes, KnownLayout, TryFromBytes, Unaligned};
35
36#[derive(Debug, PartialEq)]
37pub enum HandshakeType {
38    ClientHello,
39    ServerHello,
40    NewSessionTicket,
41    EndOfEarlyData,
42    EncryptedExtensions,
43    Certificate,
44    CertificateRequest,
45    CertificateVerify,
46    Finished,
47    KeyUpdate,
48    MessageHash,
49    Unknown(u8),
50}
51
52impl From<HandshakeType> for &'static str {
53    fn from(t: HandshakeType) -> &'static str {
54        match t {
55            HandshakeType::ClientHello => "ClientHello",
56            HandshakeType::ServerHello => "ServerHello",
57            HandshakeType::NewSessionTicket => "NewSessionTicket",
58            HandshakeType::EndOfEarlyData => "EndOfEarlyData",
59            HandshakeType::EncryptedExtensions => "EncryptedExtensins",
60            HandshakeType::Certificate => "Certificate",
61            HandshakeType::CertificateRequest => "CertificateRequest",
62            HandshakeType::CertificateVerify => "CertificateVerify",
63            HandshakeType::Finished => "Finished",
64            HandshakeType::KeyUpdate => "KeyUpdate",
65            HandshakeType::MessageHash => "MessageHash",
66            HandshakeType::Unknown(_) => "Unknown",
67        }
68    }
69}
70
71impl From<u8> for HandshakeType {
72    fn from(s: u8) -> HandshakeType {
73        match s {
74            1 => Self::ClientHello,
75            2 => Self::ServerHello,
76            4 => Self::NewSessionTicket,
77            5 => Self::EndOfEarlyData,
78            8 => Self::EncryptedExtensions,
79            11 => Self::Certificate,
80            13 => Self::CertificateRequest,
81            15 => Self::CertificateVerify,
82            20 => Self::Finished,
83            24 => Self::KeyUpdate,
84            254 => Self::MessageHash,
85            _ => Self::Unknown(s),
86        }
87    }
88}
89
90#[derive(Debug, PartialEq)]
91pub enum MsgType<'r> {
92    ClientHello(ClientHello<'r>),
93    ServerHello(ServerHello<'r>),
94    ClientFinished(ClientFinished<'r>),
95    EncryptedExtensions,
96    ServerCertificate,
97    ServerCertificateVerify,
98    ServerFinished,
99    NewSessionTicket,
100}
101
102#[derive(Debug, PartialEq)]
103pub struct HandshakeMsg<'r> {
104    pub req_ctx: Option<u8>,
105    pub msg: MsgType<'r>,
106}
107
108#[inline]
109fn parse_header(mut rest: &[u8]) -> Result<(HandshakeType, Option<u8>, usize, &[u8]), RecordError> {
110    let msg_type_raw = rest.split_off(..1).ok_or(RecordError::Size)?;
111
112    let msg_type: HandshakeType = msg_type_raw[0].into();
113
114    if let HandshakeType::Unknown(_) = msg_type {
115        return Err(RecordError::Validity);
116    }
117
118    let mut req_ctx: Option<u8> = None;
119
120    if let HandshakeType::Certificate = msg_type {
121        let req_ctx_t = rest.split_off(..1).ok_or(RecordError::Size)?;
122        req_ctx = Some(req_ctx_t[0]);
123    }
124
125    let msg_len_b = rest.split_off(..3).ok_or(RecordError::Size)?;
126
127    let msg_len = u32::from_be_bytes([0, msg_len_b[0], msg_len_b[1], msg_len_b[2]]);
128
129    Ok((msg_type, req_ctx, msg_len as usize, rest))
130}
131
132impl<'r> HandshakeMsg<'r> {
133    /// The inner Message
134    pub fn msg(&'r self) -> &'r MsgType<'r> {
135        &self.msg
136    }
137    /// Parse Server Wrapped Record (Application phase)
138    #[inline]
139    pub fn server_wrapped_ap_parse<P: ServerApRecordProcessor>(
140        _prc: &mut P,
141        bytes: &'r [u8],
142    ) -> Result<Self, RecordError> {
143        let (msg_type, req_ctx, _msg_len, _rest) = parse_header(bytes)?;
144
145        let msg: MsgType<'_> = match msg_type {
146            HandshakeType::NewSessionTicket => MsgType::NewSessionTicket,
147            _ => {
148                return Err(RecordError::NotImplemented(
149                    msg_type.into(),
150                    "HandshakeMsg::client_wrapped_ap_parse",
151                ))
152            }
153        };
154        Ok(Self { req_ctx, msg })
155    }
156    /// Parse Server Wrapped Record (Handshake phase)
157    #[inline]
158    pub fn server_wrapped_hs_parse<P: ServerWrappedRecordProcessor>(
159        prc: &mut P,
160        bytes: &'r [u8],
161    ) -> Result<Self, RecordError> {
162        let (msg_type, req_ctx, _msg_len, rest) = parse_header(bytes)?;
163
164        let msg = match msg_type {
165            HandshakeType::EncryptedExtensions => {
166                // TODO: support these
167                match rest {
168                    &[0, 0] => {}
169                    _ => return Err(RecordError::Validity),
170                }
171                MsgType::EncryptedExtensions
172            }
173            HandshakeType::Certificate => {
174                ServerCertificate::parse_wrapped(prc, rest)?;
175                MsgType::ServerCertificate
176            }
177            HandshakeType::CertificateVerify => {
178                ServerCertificateVerify::parse_wrapped(prc, rest)?;
179                MsgType::ServerCertificateVerify
180            }
181            HandshakeType::Finished => {
182                ServerFinished::parse_wrapped(prc, rest)?;
183                MsgType::ServerFinished
184            }
185            _ => {
186                return Err(RecordError::NotImplemented(
187                    msg_type.into(),
188                    "HandshakeMsg::server_wrapped_parse",
189                ))
190            }
191        };
192
193        Ok(Self { req_ctx, msg })
194    }
195    /// Parse Client Wrapped Record
196    pub fn client_wrapped_parse(bytes: &'r [u8]) -> Result<Self, RecordError> {
197        let (msg_type, req_ctx, _msg_len, rest) = parse_header(bytes)?;
198
199        let msg = match msg_type {
200            HandshakeType::ClientHello => return Err(RecordError::NotAllowed),
201            HandshakeType::Finished => {
202                let c_finished = ClientFinished::parse_wrapped(rest)?;
203                MsgType::ClientFinished(c_finished)
204            }
205            _ => {
206                return Err(RecordError::NotImplemented(
207                    msg_type.into(),
208                    "HandshakeMsg::client_wrapped_parse",
209                ))
210            }
211        };
212
213        Ok(Self { req_ctx, msg })
214    }
215    /// Parse Server Record
216    pub fn server_parse<P: ServerRecordProcessor>(
217        prc: &mut P,
218        bytes: &'r [u8],
219    ) -> Result<(Self, &'r [u8]), RecordError> {
220        let (msg_type, req_ctx, _msg_len, rest) = parse_header(bytes)?;
221
222        let (msg, rest_next) = match msg_type {
223            HandshakeType::ServerHello => {
224                let (s_hello, r_next) = ServerHello::parse(prc, rest)?;
225                (MsgType::ServerHello(s_hello), r_next)
226            }
227            _ => {
228                return Err(RecordError::NotImplemented(
229                    msg_type.into(),
230                    "HandshakeMsg::server_parse",
231                ))
232            }
233        };
234
235        Ok((Self { req_ctx, msg }, rest_next))
236    }
237    /// Parse Client Record
238    pub fn client_parse<P: ClientHelloProcessor>(
239        prc: &mut P,
240        bytes: &'r [u8],
241    ) -> Result<(Self, &'r [u8]), RecordError> {
242        let (msg_type, req_ctx, _msg_len, rest) = parse_header(bytes)?;
243
244        let (msg, rest_next) = match msg_type {
245            HandshakeType::ClientHello => {
246                let (c_hello, r_next) = ClientHello::parse(prc, rest)?;
247                (MsgType::ClientHello(c_hello), r_next)
248            }
249            _ => {
250                return Err(RecordError::NotImplemented(
251                    msg_type.into(),
252                    "HandshakeMsg::client_parse",
253                ))
254            }
255        };
256
257        Ok((Self { req_ctx, msg }, rest_next))
258    }
259}