ytls_record/
wrapped.rs

1//! Wrapped Record
2
3use crate::error::RecordError;
4use ytls_traits::ServerApRecordProcessor;
5use ytls_traits::ServerWrappedRecordProcessor;
6
7#[derive(Debug, PartialEq)]
8pub enum WrappedContentType {
9    /// Change Cipher Spec
10    ChangeCipherSpec,
11    /// Alert
12    Alert,
13    /// Handshake
14    Handshake,
15    /// Application Data
16    ApplicationData,
17    /// Unknown
18    Unknown(u8),
19}
20
21impl From<WrappedContentType> for &'static str {
22    fn from(t: WrappedContentType) -> &'static str {
23        match t {
24            WrappedContentType::ChangeCipherSpec => "ChangeCipherSpec",
25            WrappedContentType::Alert => "Alert",
26            WrappedContentType::Handshake => "Handshake",
27            WrappedContentType::ApplicationData => "ApplicationData",
28            WrappedContentType::Unknown(_) => "Unknown",
29        }
30    }
31}
32
33impl From<u8> for WrappedContentType {
34    fn from(i: u8) -> Self {
35        match i {
36            20 => Self::ChangeCipherSpec,
37            21 => Self::Alert,
38            22 => Self::Handshake,
39            23 => Self::ApplicationData,
40            _ => Self::Unknown(i),
41        }
42    }
43}
44
45#[derive(Debug, PartialEq)]
46pub struct WrappedRecord<'r> {
47    raw_bytes: &'r [u8],
48    msg: WrappedMsgType<'r>,
49}
50
51#[derive(Debug, PartialEq)]
52pub enum WrappedMsgType<'r> {
53    ApplicationData,
54    Handshake(HandshakeMsg<'r>),
55    Alert(AlertMsg<'r>),
56}
57
58use crate::AlertMsg;
59use crate::HandshakeMsg;
60
61impl<'r> WrappedRecord<'r> {
62    #[inline]
63    pub fn msg(&self) -> &WrappedMsgType<'r> {
64        &self.msg
65    }
66    #[inline]
67    pub fn parse_server_ap<P: ServerApRecordProcessor>(
68        prc: &mut P,
69        wrapped_data: &'r [u8],
70    ) -> Result<WrappedRecord<'r>, RecordError> {
71        let w_len = wrapped_data.len();
72
73        let rec_type: WrappedContentType = wrapped_data[w_len - 1].into();
74        let raw_bytes = &wrapped_data[0..w_len - 1];
75
76        let msg: WrappedMsgType<'_> = match rec_type {
77            WrappedContentType::Handshake => {
78                let msg = HandshakeMsg::server_wrapped_ap_parse(prc, raw_bytes)?;
79                WrappedMsgType::Handshake(msg)
80            }
81            WrappedContentType::ApplicationData => WrappedMsgType::ApplicationData,
82            WrappedContentType::Alert => {
83                let (msg, _r_next) = AlertMsg::client_parse(raw_bytes)?;
84                WrappedMsgType::Alert(msg)
85            }
86            _ => {
87                return Err(RecordError::NotImplemented(
88                    rec_type.into(),
89                    "Wrapped::parse_server_ap",
90                ))
91            }
92        };
93        Ok(WrappedRecord { raw_bytes, msg })
94    }
95    #[inline]
96    pub fn parse_server<P: ServerWrappedRecordProcessor>(
97        prc: &mut P,
98        wrapped_data: &'r [u8],
99    ) -> Result<WrappedRecord<'r>, RecordError> {
100        let w_len = wrapped_data.len();
101
102        let rec_type: WrappedContentType = wrapped_data[w_len - 1].into();
103        let raw_bytes = &wrapped_data[0..w_len - 1];
104
105        let msg = match rec_type {
106            WrappedContentType::Handshake => {
107                let msg = HandshakeMsg::server_wrapped_hs_parse(prc, raw_bytes)?;
108                WrappedMsgType::Handshake(msg)
109            }
110            WrappedContentType::Alert => {
111                let (msg, _r_next) = AlertMsg::client_parse(raw_bytes)?;
112                WrappedMsgType::Alert(msg)
113            }
114            WrappedContentType::Unknown(_) => return Err(RecordError::Validity),
115            _ => {
116                return Err(RecordError::NotImplemented(
117                    rec_type.into(),
118                    "Wrapped::parse_server",
119                ))
120            }
121        };
122        Ok(WrappedRecord { raw_bytes, msg })
123    }
124    #[inline]
125    pub fn parse_client(wrapped_data: &'r [u8]) -> Result<WrappedRecord<'r>, RecordError> {
126        let w_len = wrapped_data.len();
127
128        let rec_type: WrappedContentType = wrapped_data[w_len - 1].into();
129        let raw_bytes = &wrapped_data[0..w_len - 1];
130
131        let msg = match rec_type {
132            WrappedContentType::Handshake => {
133                let msg = HandshakeMsg::client_wrapped_parse(raw_bytes)?;
134                WrappedMsgType::Handshake(msg)
135            }
136            WrappedContentType::Alert => {
137                let (msg, _r_next) = AlertMsg::client_parse(raw_bytes)?;
138                WrappedMsgType::Alert(msg)
139            }
140            WrappedContentType::Unknown(_) => return Err(RecordError::Validity),
141            _ => {
142                return Err(RecordError::NotImplemented(
143                    rec_type.into(),
144                    "Wrapped::parse_server_ap",
145                ))
146            }
147        };
148        Ok(WrappedRecord { raw_bytes, msg })
149    }
150}
151
152#[cfg(test)]
153mod test {
154    use super::*;
155    use hex_literal::hex;
156    use rstest::rstest;
157
158    use crate::ClientFinished;
159
160    #[rstest]
161    #[case(
162        &hex!("14000020a0210258e7c4402ab07807a1e61df4cf0ab58f828b26c6adf29654228ac0b66f16"),
163    )]
164    fn wrapped_ok(#[case] in_data: &[u8]) {
165        let r = WrappedRecord::parse_client(in_data);
166        insta::assert_debug_snapshot!(r);
167    }
168
169    #[rstest]
170    #[case(&hex!("7710"))]
171    #[case(&hex!("1410"))]
172    #[case(&hex!("140010"))]
173    #[case(&hex!("14000010"))]
174    fn wrapped_err(#[case] in_data: &[u8]) {
175        assert_eq!(
176            WrappedRecord::parse_client(in_data),
177            Err(RecordError::Validity)
178        );
179    }
180}