webrtc_sniffer/dtls/
handshake.rs

1use std::fmt;
2
3use nom::{
4    bytes::complete::take,
5    combinator::map,
6    error::{Error, ErrorKind},
7    multi::many0,
8    number::complete::{be_u16, be_u24, be_u8},
9    Err, IResult, Parser,
10};
11
12pub struct HandshakeMessage {
13    pub length: u32,
14    pub message_seq: u16,
15    pub fragment_offset: u32,
16    pub fragment_length: u32,
17    pub inner: HandshakeInner,
18}
19
20pub enum HandshakeInner {
21    ClientHello(ClientHello),
22    ServerHello(ServerHello),
23    HelloVerifyRequest(HelloVerifyRequest),
24    Certificates(Certificates),
25    ServerKeyExchange(ServerKeyExchange),
26    CertificateRequest(u8),
27    ServerHelloDone,
28    CertificateVerify(u8),
29    ClientKeyExchange(ClientKeyExchange),
30    Finished,
31}
32
33impl fmt::Display for HandshakeInner {
34    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35        match self {
36            Self::ClientHello(msg) => write!(f, "ClientHello({msg})"),
37            Self::ServerHello(msg) => write!(f, "ServerHello({msg})"),
38            Self::HelloVerifyRequest(msg) => write!(f, "HelloVerifyRequest({msg})"),
39            Self::Certificates(msg) => write!(f, "Certificates({msg})"),
40            Self::ServerKeyExchange(msg) => write!(f, "ServerKeyExchange({msg})"),
41            Self::CertificateRequest(msg) => write!(f, "CertificateRequest({msg})"),
42            Self::ServerHelloDone => write!(f, "ServerHelloDone"),
43            Self::CertificateVerify(msg) => write!(f, "CertificateVerify({msg})"),
44            Self::ClientKeyExchange(msg) => write!(f, "ClientKeyExchange({msg})"),
45            Self::Finished => write!(f, "Finished"),
46        }
47    }
48}
49
50impl HandshakeMessage {
51    pub fn parse(input: &[u8]) -> IResult<&[u8], Self> {
52        let (input, discriminant) = be_u8(input)?;
53        let (input, length) = be_u24(input)?;
54        let (input, message_seq) = be_u16(input)?;
55        let (input, fragment_offset) = be_u24(input)?;
56        let (input, fragment_length) = be_u24(input)?;
57        let (input, inner) = match discriminant {
58            1 => map(ClientHello::parse, HandshakeInner::ClientHello).parse(input),
59            2 => map(ServerHello::parse, HandshakeInner::ServerHello).parse(input),
60            3 => map(
61                HelloVerifyRequest::parse,
62                HandshakeInner::HelloVerifyRequest,
63            )
64            .parse(input),
65            11 => map(Certificates::parse, HandshakeInner::Certificates).parse(input),
66            12 => map(ServerKeyExchange::parse, HandshakeInner::ServerKeyExchange).parse(input),
67            13 => Ok((input, HandshakeInner::CertificateRequest(0))),
68            14 => Ok((input, HandshakeInner::ServerHelloDone)),
69            15 => Ok((input, HandshakeInner::CertificateVerify(0))),
70            16 => map(ClientKeyExchange::parse, HandshakeInner::ClientKeyExchange).parse(input),
71            20 => Ok((input, HandshakeInner::Finished)),
72            _ => Err(Err::Error(Error::new(input, ErrorKind::Alt))),
73        }?;
74        Ok((
75            input,
76            HandshakeMessage {
77                length,
78                message_seq,
79                fragment_offset,
80                fragment_length,
81                inner,
82            },
83        ))
84    }
85}
86
87pub struct ClientHello {
88    pub random: [u8; 32],
89    pub session_id: Vec<u8>,
90    pub cookie: Vec<u8>,
91    pub cipher_suites: Vec<u16>,
92    pub compression_methods: Vec<u8>,
93    pub extensions: Vec<Extension>,
94}
95
96impl fmt::Display for ClientHello {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        write!(
99            f,
100            "random={}, session_id=\"{}\", cookie=\"{}\", cipher_suites={:?}, compression_methods={:?}",
101            hex::encode(self.random),
102            hex::encode(&self.session_id),
103            hex::encode(&self.cookie),
104            self.cipher_suites,
105            self.compression_methods,
106        )
107    }
108}
109
110impl ClientHello {
111    fn parse(input: &[u8]) -> IResult<&[u8], Self> {
112        let (input, legacy_record_version) = be_u16(input)?;
113        if legacy_record_version != 0xFEFD {
114            return Err(Err::Error(Error::new(input, ErrorKind::Alt)));
115        }
116        let (input, random) = take(32usize)(input)?;
117        let random = <[u8; 32]>::try_from(random).expect("cannot fail");
118        let (input, l) = be_u8(input)?;
119        let (input, bytes) = take(l as usize)(input)?;
120        let session_id = bytes.to_vec();
121        let (input, l) = be_u8(input)?;
122        let (input, bytes) = take(l as usize)(input)?;
123        let cookie = bytes.to_vec();
124        let (input, l) = be_u16(input)?;
125        let (input, bytes) = take(l as usize)(input)?;
126        let (_, cipher_suites) = many0(be_u16).parse(bytes)?;
127        let (input, compression_methods_len) = be_u8(input)?;
128        let (input, bytes) = take(compression_methods_len as usize)(input)?;
129        let compression_methods = bytes.to_vec();
130        let (input, l) = be_u16(input)?;
131        let (input, bytes) = take(l as usize)(input)?;
132        let (_, extensions) = many0(Extension::parse).parse(bytes)?;
133
134        Ok((
135            input,
136            ClientHello {
137                random,
138                session_id,
139                cookie,
140                cipher_suites,
141                compression_methods,
142                extensions,
143            },
144        ))
145    }
146}
147
148pub struct ServerHello {
149    pub random: [u8; 32],
150    pub session_id: Vec<u8>,
151    pub cipher_suite: u16,
152    pub compression_method: u8,
153    pub extensions: Vec<Extension>,
154}
155
156impl fmt::Display for ServerHello {
157    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158        write!(
159            f,
160            "random={}, session_id=\"{}\", cipher_suite={}, compression_method={}",
161            hex::encode(self.random),
162            hex::encode(&self.session_id),
163            self.cipher_suite,
164            self.compression_method,
165        )
166    }
167}
168
169impl ServerHello {
170    fn parse(input: &[u8]) -> IResult<&[u8], Self> {
171        let (input, legacy_record_version) = be_u16(input)?;
172        if legacy_record_version != 0xFEFD {
173            return Err(Err::Error(Error::new(input, ErrorKind::Alt)));
174        }
175        let (input, random) = take(32usize)(input)?;
176        let random = <[u8; 32]>::try_from(random).expect("cannot fail");
177        let (input, l) = be_u8(input)?;
178        let (input, bytes) = take(l as usize)(input)?;
179        let session_id = bytes.to_vec();
180        let (input, cipher_suite) = be_u16(input)?;
181        let (input, compression_method) = be_u8(input)?;
182        let (input, l) = be_u16(input)?;
183        let (input, bytes) = take(l as usize)(input)?;
184        let (_, extensions) = many0(Extension::parse).parse(bytes)?;
185
186        Ok((
187            input,
188            ServerHello {
189                random,
190                session_id,
191                cipher_suite,
192                compression_method,
193                extensions,
194            },
195        ))
196    }
197}
198
199pub struct HelloVerifyRequest {
200    pub cookie: Vec<u8>,
201}
202
203impl fmt::Display for HelloVerifyRequest {
204    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
205        write!(f, "cookie={}", hex::encode(&self.cookie),)
206    }
207}
208
209impl HelloVerifyRequest {
210    fn parse(input: &[u8]) -> IResult<&[u8], Self> {
211        let (input, legacy_record_version) = be_u16(input)?;
212        if legacy_record_version != 0xFEFD {
213            return Err(Err::Error(Error::new(input, ErrorKind::Alt)));
214        }
215
216        let (input, l) = be_u8(input)?;
217        let (input, bytes) = take(l as usize)(input)?;
218        let cookie = bytes.to_vec();
219
220        Ok((input, HelloVerifyRequest { cookie }))
221    }
222}
223
224pub struct Extension {}
225
226impl Extension {
227    fn parse(input: &[u8]) -> IResult<&[u8], Self> {
228        let _ = be_u8(input)?;
229        Ok((&[], Extension {}))
230    }
231}
232
233pub struct Certificates(pub Vec<Certificate>);
234
235impl fmt::Display for Certificates {
236    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
237        for certificate in &self.0 {
238            write!(f, "certificate({certificate})")?;
239        }
240        Ok(())
241    }
242}
243
244impl Certificates {
245    fn parse(input: &[u8]) -> IResult<&[u8], Self> {
246        let (input, length) = be_u24(input)?;
247        let (input, bytes) = take(length as usize)(input)?;
248        let (_, certificates) = many0(Certificate::parse).parse(bytes)?;
249        Ok((input, Certificates(certificates)))
250    }
251}
252
253pub struct Certificate {
254    pub data: Vec<u8>,
255}
256
257impl fmt::Display for Certificate {
258    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
259        write!(f, "{}", hex::encode(&self.data))
260    }
261}
262
263impl Certificate {
264    fn parse(input: &[u8]) -> IResult<&[u8], Self> {
265        let (input, length) = be_u24(input)?;
266        let (input, bytes) = take(length as usize)(input)?;
267        let data = bytes.to_vec();
268
269        Ok((input, Certificate { data }))
270    }
271}
272
273pub struct ServerKeyExchange {
274    // pub curve_type: u8,
275    pub curve_name: u16,
276    pub public_key: Vec<u8>,
277    pub signature_hash_algorithm: u8,
278    pub signature_algorithm: u8,
279    pub signature: Vec<u8>,
280}
281
282impl fmt::Display for ServerKeyExchange {
283    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
284        write!(
285            f,
286            "curve_name={}, pk={}, sig_alg=({},{}), sig={}",
287            self.curve_name,
288            hex::encode(&self.public_key),
289            self.signature_hash_algorithm,
290            self.signature_algorithm,
291            hex::encode(&self.signature)
292        )
293    }
294}
295
296impl ServerKeyExchange {
297    fn parse(input: &[u8]) -> IResult<&[u8], Self> {
298        let (input, curve_type) = be_u8(input)?;
299        if curve_type != 3 {
300            return Err(Err::Failure(Error::new(input, ErrorKind::Alt)));
301        }
302        let (input, curve_name) = be_u16(input)?;
303
304        let (input, l) = be_u8(input)?;
305        let (input, bytes) = take(l as usize)(input)?;
306        let public_key = bytes.to_vec();
307
308        let (input, signature_hash_algorithm) = be_u8(input)?;
309        let (input, signature_algorithm) = be_u8(input)?;
310
311        let (input, l) = be_u16(input)?;
312        let (input, bytes) = take(l as usize)(input)?;
313        let signature = bytes.to_vec();
314
315        Ok((
316            input,
317            ServerKeyExchange {
318                curve_name,
319                public_key,
320                signature_hash_algorithm,
321                signature_algorithm,
322                signature,
323            },
324        ))
325    }
326}
327
328pub struct ClientKeyExchange {
329    pub public_key: Vec<u8>,
330}
331
332impl fmt::Display for ClientKeyExchange {
333    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
334        write!(f, "pk={}", hex::encode(&self.public_key),)
335    }
336}
337
338impl ClientKeyExchange {
339    fn parse(input: &[u8]) -> IResult<&[u8], Self> {
340        let (input, l) = be_u8(input)?;
341        let (input, bytes) = take(l as usize)(input)?;
342        let public_key = bytes.to_vec();
343
344        Ok((input, ClientKeyExchange { public_key }))
345    }
346}