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<u8> for WrappedContentType {
22    fn from(i: u8) -> Self {
23        match i {
24            20 => Self::ChangeCipherSpec,
25            21 => Self::Alert,
26            22 => Self::Handshake,
27            23 => Self::ApplicationData,
28            _ => Self::Unknown(i),
29        }
30    }
31}
32
33#[derive(Debug, PartialEq)]
34pub struct WrappedRecord<'r> {
35    raw_bytes: &'r [u8],
36    msg: WrappedMsgType<'r>,
37}
38
39#[derive(Debug, PartialEq)]
40pub enum WrappedMsgType<'r> {
41    ApplicationData,
42    Handshake(HandshakeMsg<'r>),
43    Alert(AlertMsg<'r>),
44}
45
46use crate::AlertMsg;
47use crate::HandshakeMsg;
48
49impl<'r> WrappedRecord<'r> {
50    #[inline]
51    pub fn msg(&self) -> &WrappedMsgType<'r> {
52        &self.msg
53    }
54    #[inline]
55    pub fn parse_server_ap<P: ServerApRecordProcessor>(
56        prc: &mut P,
57        wrapped_data: &'r [u8],
58    ) -> Result<WrappedRecord<'r>, RecordError> {
59        let w_len = wrapped_data.len();
60
61        let rec_type: WrappedContentType = wrapped_data[w_len - 1].into();
62        let raw_bytes = &wrapped_data[0..w_len - 1];
63
64        let msg: WrappedMsgType<'_> = match rec_type {
65            WrappedContentType::Handshake => {
66                let msg = HandshakeMsg::server_wrapped_ap_parse(prc, raw_bytes)?;
67                WrappedMsgType::Handshake(msg)
68            }
69            WrappedContentType::ApplicationData => WrappedMsgType::ApplicationData,
70            WrappedContentType::Alert => {
71                let (msg, _r_next) = AlertMsg::client_parse(raw_bytes)?;
72                WrappedMsgType::Alert(msg)
73            }
74            _ => todo!("Missing {:?}", rec_type),
75        };
76        Ok(WrappedRecord { raw_bytes, msg })
77    }
78    #[inline]
79    pub fn parse_server<P: ServerWrappedRecordProcessor>(
80        prc: &mut P,
81        wrapped_data: &'r [u8],
82    ) -> Result<WrappedRecord<'r>, RecordError> {
83        let w_len = wrapped_data.len();
84
85        let rec_type: WrappedContentType = wrapped_data[w_len - 1].into();
86        let raw_bytes = &wrapped_data[0..w_len - 1];
87
88        let msg = match rec_type {
89            WrappedContentType::Handshake => {
90                let msg = HandshakeMsg::server_wrapped_hs_parse(prc, raw_bytes)?;
91                WrappedMsgType::Handshake(msg)
92            }
93            WrappedContentType::Alert => {
94                let (msg, _r_next) = AlertMsg::client_parse(raw_bytes)?;
95                WrappedMsgType::Alert(msg)
96            }
97            WrappedContentType::Unknown(_) => return Err(RecordError::Validity),
98            _ => todo!("Missing {:?}", rec_type),
99        };
100        Ok(WrappedRecord { raw_bytes, msg })
101    }
102    #[inline]
103    pub fn parse_client(wrapped_data: &'r [u8]) -> Result<WrappedRecord<'r>, RecordError> {
104        let w_len = wrapped_data.len();
105
106        let rec_type: WrappedContentType = wrapped_data[w_len - 1].into();
107        let raw_bytes = &wrapped_data[0..w_len - 1];
108
109        let msg = match rec_type {
110            WrappedContentType::Handshake => {
111                let msg = HandshakeMsg::client_wrapped_parse(raw_bytes)?;
112                WrappedMsgType::Handshake(msg)
113            }
114            WrappedContentType::Alert => {
115                let (msg, _r_next) = AlertMsg::client_parse(raw_bytes)?;
116                WrappedMsgType::Alert(msg)
117            }
118            WrappedContentType::Unknown(_) => return Err(RecordError::Validity),
119            _ => todo!("Missing {:?}", rec_type),
120        };
121        Ok(WrappedRecord { raw_bytes, msg })
122    }
123}
124
125#[cfg(test)]
126mod test {
127    use super::*;
128    use hex_literal::hex;
129    use rstest::rstest;
130
131    use crate::ClientFinished;
132
133    #[rstest]
134    #[case(
135        &hex!("14000020a0210258e7c4402ab07807a1e61df4cf0ab58f828b26c6adf29654228ac0b66f16"),
136    )]
137    fn wrapped_ok(#[case] in_data: &[u8]) {
138        let r = WrappedRecord::parse_client(in_data);
139        insta::assert_debug_snapshot!(r);
140    }
141
142    #[rstest]
143    #[case(&hex!("7710"))]
144    #[case(&hex!("1410"))]
145    #[case(&hex!("140010"))]
146    #[case(&hex!("14000010"))]
147    fn wrapped_err(#[case] in_data: &[u8]) {
148        assert_eq!(
149            WrappedRecord::parse_client(in_data),
150            Err(RecordError::Validity)
151        );
152    }
153}