1use crate::error::RecordError;
4use ytls_traits::ServerApRecordProcessor;
5use ytls_traits::ServerWrappedRecordProcessor;
6
7#[derive(Debug, PartialEq)]
8pub enum WrappedContentType {
9 ChangeCipherSpec,
11 Alert,
13 Handshake,
15 ApplicationData,
17 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}