tls_parser/
tls_handshake.rs

1use alloc::vec::Vec;
2use core::convert::TryInto;
3use core::fmt;
4use core::ops::Deref;
5use nom::branch::alt;
6use nom::bytes::streaming::take;
7use nom::combinator::{complete, cond, map, map_parser, opt, verify};
8use nom::error::{make_error, ErrorKind};
9use nom::multi::{length_count, length_data, many0};
10use nom::number::streaming::{be_u16, be_u24, be_u32, be_u8};
11use nom::{Err, IResult};
12use nom_derive::{NomBE, Parse};
13use rusticata_macros::newtype_enum;
14
15use crate::tls_ciphers::*;
16// use crate::tls_debug::*;
17use crate::tls_ec::*;
18use crate::tls_message::TlsMessage;
19
20/// Handshake type
21///
22/// Handshake types are defined in [RFC5246](https://tools.ietf.org/html/rfc5246) and
23/// the [IANA HandshakeType
24/// Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-7)
25#[derive(Clone, Copy, PartialEq, Eq, NomBE)]
26pub struct TlsHandshakeType(pub u8);
27
28newtype_enum! {
29impl debug TlsHandshakeType {
30    HelloRequest        = 0x00,
31    ClientHello         = 0x01,
32    ServerHello         = 0x02,
33    HelloVerifyRequest  = 0x03,
34    NewSessionTicket    = 0x04,
35    EndOfEarlyData      = 0x05,
36    HelloRetryRequest   = 0x06,
37    EncryptedExtensions = 0x08,
38    Certificate         = 0x0b,
39    ServerKeyExchange   = 0x0c,
40    CertificateRequest  = 0x0d,
41    ServerDone          = 0x0e,
42    CertificateVerify   = 0x0f,
43    ClientKeyExchange   = 0x10,
44    Finished            = 0x14,
45    CertificateURL      = 0x15,
46    CertificateStatus   = 0x16,
47    KeyUpdate           = 0x18,
48
49    NextProtocol        = 0x43,
50}
51}
52
53impl From<TlsHandshakeType> for u8 {
54    fn from(v: TlsHandshakeType) -> u8 {
55        v.0
56    }
57}
58
59/// TLS version
60///
61/// Only the TLS version defined in the TLS message header is meaningful, the
62/// version defined in the record should be ignored or set to TLS 1.0
63#[derive(Clone, Copy, Default, PartialEq, Eq, NomBE)]
64pub struct TlsVersion(pub u16);
65
66impl TlsVersion {
67    pub const fn to_be_bytes(&self) -> [u8; 2] {
68        self.0.to_be_bytes()
69    }
70}
71
72newtype_enum! {
73impl debug TlsVersion {
74    Ssl30        = 0x0300,
75    Tls10        = 0x0301,
76    Tls11        = 0x0302,
77    Tls12        = 0x0303,
78    Tls13        = 0x0304,
79
80    Tls13Draft18 = 0x7f12,
81    Tls13Draft19 = 0x7f13,
82    Tls13Draft20 = 0x7f14,
83    Tls13Draft21 = 0x7f15,
84    Tls13Draft22 = 0x7f16,
85    Tls13Draft23 = 0x7f17,
86
87    DTls10       = 0xfeff,
88    DTls11       = 0xfefe,
89    DTls12       = 0xfefd,
90}
91}
92
93impl From<TlsVersion> for u16 {
94    fn from(v: TlsVersion) -> u16 {
95        v.0
96    }
97}
98
99impl fmt::LowerHex for TlsVersion {
100    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101        write!(f, "{:x}", self.0)
102    }
103}
104
105/// Heartbeat type, as defined in [RFC6520](https://tools.ietf.org/html/rfc6520) section 3
106#[derive(Clone, Copy, PartialEq, Eq, NomBE)]
107pub struct TlsHeartbeatMessageType(pub u8);
108
109newtype_enum! {
110impl debug TlsHeartbeatMessageType {
111    HeartBeatRequest  = 0x1,
112    HeartBeatResponse = 0x2,
113}
114}
115
116impl From<TlsHeartbeatMessageType> for u8 {
117    fn from(v: TlsHeartbeatMessageType) -> u8 {
118        v.0
119    }
120}
121
122#[derive(Clone, Copy, Default, PartialEq, Eq, NomBE)]
123pub struct TlsCompressionID(pub u8);
124
125newtype_enum! {
126impl debug TlsCompressionID {
127    Null = 0x00,
128    Deflate = 0x01,
129}
130}
131
132impl From<TlsCompressionID> for u8 {
133    fn from(c: TlsCompressionID) -> u8 {
134        c.0
135    }
136}
137
138impl Deref for TlsCompressionID {
139    type Target = u8;
140    fn deref(&self) -> &Self::Target {
141        &self.0
142    }
143}
144
145impl AsRef<u8> for TlsCompressionID {
146    fn as_ref(&self) -> &u8 {
147        &self.0
148    }
149}
150
151#[derive(Clone, Copy, Default, PartialEq, Eq, NomBE)]
152pub struct TlsCipherSuiteID(pub u16);
153
154impl TlsCipherSuiteID {
155    pub fn get_ciphersuite(self) -> Option<&'static TlsCipherSuite> {
156        TlsCipherSuite::from_id(self.0)
157    }
158}
159
160impl From<TlsCipherSuiteID> for u16 {
161    fn from(c: TlsCipherSuiteID) -> u16 {
162        c.0
163    }
164}
165
166impl Deref for TlsCipherSuiteID {
167    type Target = u16;
168    fn deref(&self) -> &Self::Target {
169        &self.0
170    }
171}
172
173impl AsRef<u16> for TlsCipherSuiteID {
174    fn as_ref(&self) -> &u16 {
175        &self.0
176    }
177}
178
179impl fmt::Display for TlsCipherSuiteID {
180    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
181        write!(f, "{}", self.0)
182    }
183}
184
185impl fmt::Debug for TlsCipherSuiteID {
186    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
187        match TlsCipherSuite::from_id(self.0) {
188            Some(c) => write!(f, "0x{:04x}({})", self.0, c.name),
189            None => write!(f, "0x{:04x}(Unknown cipher)", self.0),
190        }
191    }
192}
193
194impl fmt::LowerHex for TlsCipherSuiteID {
195    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
196        write!(f, "{:x}", self.0)
197    }
198}
199
200/// A trait that both TLS & DTLS satisfy
201pub trait ClientHello<'a> {
202    /// TLS version of message
203    fn version(&self) -> TlsVersion;
204    fn random(&self) -> &'a [u8];
205    // Get the first part (4 bytes) of random
206    fn rand_time(&self) -> u32 {
207        self.random()
208            .try_into()
209            .map(u32::from_be_bytes)
210            .unwrap_or(0)
211    }
212    // Get the second part (28 bytes) of random
213    fn rand_bytes(&self) -> &'a [u8] {
214        self.random().get(4..).unwrap_or(&[])
215    }
216    fn session_id(&self) -> Option<&'a [u8]>;
217    /// A list of ciphers supported by client
218    fn ciphers(&self) -> &Vec<TlsCipherSuiteID>;
219    fn cipher_suites(&self) -> Vec<Option<&'static TlsCipherSuite>> {
220        self.ciphers()
221            .iter()
222            .map(|&x| x.get_ciphersuite())
223            .collect()
224    }
225    /// A list of compression methods supported by client
226    fn comp(&self) -> &Vec<TlsCompressionID>;
227    fn ext(&self) -> Option<&'a [u8]>;
228}
229
230/// TLS Client Hello (from TLS 1.0 to TLS 1.2)
231///
232/// Some fields are unparsed (for performance reasons), for ex to parse `ext`,
233/// call the [parse_tls_client_hello_extension](crate::parse_tls_client_hello_extension) function.
234#[derive(Clone, PartialEq)]
235pub struct TlsClientHelloContents<'a> {
236    /// TLS version of message
237    pub version: TlsVersion,
238    pub random: &'a [u8],
239    pub session_id: Option<&'a [u8]>,
240    /// A list of ciphers supported by client
241    pub ciphers: Vec<TlsCipherSuiteID>,
242    /// A list of compression methods supported by client
243    pub comp: Vec<TlsCompressionID>,
244
245    pub ext: Option<&'a [u8]>,
246}
247
248impl<'a> TlsClientHelloContents<'a> {
249    pub fn new(
250        v: u16,
251        random: &'a [u8],
252        sid: Option<&'a [u8]>,
253        c: Vec<TlsCipherSuiteID>,
254        co: Vec<TlsCompressionID>,
255        e: Option<&'a [u8]>,
256    ) -> Self {
257        TlsClientHelloContents {
258            version: TlsVersion(v),
259            random,
260            session_id: sid,
261            ciphers: c,
262            comp: co,
263            ext: e,
264        }
265    }
266
267    pub fn get_version(&self) -> TlsVersion {
268        self.version
269    }
270
271    pub fn get_ciphers(&self) -> Vec<Option<&'static TlsCipherSuite>> {
272        self.ciphers.iter().map(|&x| x.get_ciphersuite()).collect()
273    }
274}
275
276impl<'a> ClientHello<'a> for TlsClientHelloContents<'a> {
277    fn version(&self) -> TlsVersion {
278        self.version
279    }
280
281    fn random(&self) -> &'a [u8] {
282        self.random
283    }
284
285    fn session_id(&self) -> Option<&'a [u8]> {
286        self.session_id
287    }
288
289    fn ciphers(&self) -> &Vec<TlsCipherSuiteID> {
290        &self.ciphers
291    }
292
293    fn comp(&self) -> &Vec<TlsCompressionID> {
294        &self.comp
295    }
296
297    fn ext(&self) -> Option<&'a [u8]> {
298        self.ext
299    }
300}
301
302/// TLS Server Hello (from TLS 1.0 to TLS 1.2)
303#[derive(Clone, PartialEq)]
304pub struct TlsServerHelloContents<'a> {
305    pub version: TlsVersion,
306    pub random: &'a [u8],
307    pub session_id: Option<&'a [u8]>,
308    pub cipher: TlsCipherSuiteID,
309    pub compression: TlsCompressionID,
310
311    pub ext: Option<&'a [u8]>,
312}
313
314/// TLS Server Hello (TLS 1.3 draft 18)
315#[derive(Clone, PartialEq)]
316pub struct TlsServerHelloV13Draft18Contents<'a> {
317    pub version: TlsVersion,
318    pub random: &'a [u8],
319    pub cipher: TlsCipherSuiteID,
320
321    pub ext: Option<&'a [u8]>,
322}
323
324/// TLS Hello Retry Request (TLS 1.3)
325#[derive(Clone, PartialEq)]
326pub struct TlsHelloRetryRequestContents<'a> {
327    pub version: TlsVersion,
328    pub cipher: TlsCipherSuiteID,
329
330    pub ext: Option<&'a [u8]>,
331}
332
333impl<'a> TlsServerHelloContents<'a> {
334    pub fn new(
335        v: u16,
336        random: &'a [u8],
337        sid: Option<&'a [u8]>,
338        c: u16,
339        co: u8,
340        e: Option<&'a [u8]>,
341    ) -> Self {
342        TlsServerHelloContents {
343            version: TlsVersion(v),
344            random,
345            session_id: sid,
346            cipher: TlsCipherSuiteID(c),
347            compression: TlsCompressionID(co),
348            ext: e,
349        }
350    }
351
352    pub fn get_version(&self) -> TlsVersion {
353        self.version
354    }
355
356    pub fn get_cipher(&self) -> Option<&'static TlsCipherSuite> {
357        self.cipher.get_ciphersuite()
358    }
359}
360
361/// Session ticket, as defined in [RFC5077](https://tools.ietf.org/html/rfc5077)
362#[derive(Clone, Debug, PartialEq)]
363pub struct TlsNewSessionTicketContent<'a> {
364    pub ticket_lifetime_hint: u32,
365    pub ticket: &'a [u8],
366}
367
368/// A raw certificate, which should be a DER-encoded X.509 certificate.
369///
370/// See [RFC5280](https://tools.ietf.org/html/rfc5280) for X509v3 certificate format.
371#[derive(Clone, PartialEq)]
372pub struct RawCertificate<'a> {
373    pub data: &'a [u8],
374}
375
376/// The certificate chain, usually composed of the certificate, and all
377/// required certificate authorities.
378#[derive(Clone, Debug, PartialEq)]
379pub struct TlsCertificateContents<'a> {
380    pub cert_chain: Vec<RawCertificate<'a>>,
381}
382
383/// Certificate request, as defined in [RFC5246](https://tools.ietf.org/html/rfc5246) section 7.4.4
384///
385/// Note: TLS 1.2 adds SignatureAndHashAlgorithm (chapter 7.4.4) but do not declare it in A.4.2
386#[derive(Clone, Debug, PartialEq)]
387pub struct TlsCertificateRequestContents<'a> {
388    pub cert_types: Vec<u8>,
389    pub sig_hash_algs: Option<Vec<u16>>,
390    /// A list of DER-encoded distinguished names. See
391    /// [X.501](http://www.itu.int/rec/T-REC-X.501/en)
392    pub unparsed_ca: Vec<&'a [u8]>,
393}
394
395/// Server key exchange parameters
396///
397/// This is an opaque struct, since the content depends on the selected
398/// key exchange method.
399#[derive(Clone, PartialEq)]
400pub struct TlsServerKeyExchangeContents<'a> {
401    pub parameters: &'a [u8],
402}
403
404/// Client key exchange parameters
405///
406/// Content depends on the selected key exchange method.
407#[derive(Clone, PartialEq)]
408pub enum TlsClientKeyExchangeContents<'a> {
409    Dh(&'a [u8]),
410    Ecdh(ECPoint<'a>),
411    Unknown(&'a [u8]),
412}
413
414/// Certificate status response, as defined in [RFC6066](https://tools.ietf.org/html/rfc6066) section 8
415#[derive(Clone, Debug, PartialEq)]
416pub struct TlsCertificateStatusContents<'a> {
417    pub status_type: u8,
418    pub blob: &'a [u8],
419}
420
421/// Next protocol response, defined in
422/// [draft-agl-tls-nextprotoneg-03](https://tools.ietf.org/html/draft-agl-tls-nextprotoneg-03)
423#[derive(Clone, Debug, PartialEq)]
424pub struct TlsNextProtocolContent<'a> {
425    pub selected_protocol: &'a [u8],
426    pub padding: &'a [u8],
427}
428
429/// Key update request (TLS 1.3)
430#[derive(Copy, Clone, PartialEq, Eq)]
431pub struct KeyUpdateRequest(pub u8);
432
433newtype_enum! {
434impl KeyUpdateRequest {
435    NotRequested  = 0x0,
436    Requested     = 0x1,
437}
438}
439
440/// Generic handshake message
441#[derive(Clone, Debug, PartialEq)]
442pub enum TlsMessageHandshake<'a> {
443    HelloRequest,
444    ClientHello(TlsClientHelloContents<'a>),
445    ServerHello(TlsServerHelloContents<'a>),
446    ServerHelloV13Draft18(TlsServerHelloV13Draft18Contents<'a>),
447    NewSessionTicket(TlsNewSessionTicketContent<'a>),
448    EndOfEarlyData,
449    HelloRetryRequest(TlsHelloRetryRequestContents<'a>),
450    Certificate(TlsCertificateContents<'a>),
451    ServerKeyExchange(TlsServerKeyExchangeContents<'a>),
452    CertificateRequest(TlsCertificateRequestContents<'a>),
453    ServerDone(&'a [u8]),
454    CertificateVerify(&'a [u8]),
455    ClientKeyExchange(TlsClientKeyExchangeContents<'a>),
456    Finished(&'a [u8]),
457    CertificateStatus(TlsCertificateStatusContents<'a>),
458    NextProtocol(TlsNextProtocolContent<'a>),
459    KeyUpdate(u8),
460}
461
462/// Parse a HelloRequest handshake message
463pub fn parse_tls_handshake_msg_hello_request(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> {
464    Ok((i, TlsMessageHandshake::HelloRequest))
465}
466
467/// Parse handshake message contents for ClientHello
468///
469/// ```rust
470/// use tls_parser::*;
471///
472/// # pub fn do_stuff(bytes: &[u8]) {
473/// if let Ok((_, ch)) = parse_tls_handshake_client_hello(bytes) {
474///     println!("ClientHello TLS version: {}", ch.version);
475///     println!("  number of proposed ciphersuites: {}", ch.ciphers.len());
476/// }
477/// # }
478/// ```
479pub fn parse_tls_handshake_client_hello(i: &[u8]) -> IResult<&[u8], TlsClientHelloContents> {
480    let (i, version) = be_u16(i)?;
481    let (i, random) = take(32usize)(i)?;
482    let (i, sidlen) = verify(be_u8, |&n| n <= 32)(i)?;
483    let (i, sid) = cond(sidlen > 0, take(sidlen as usize))(i)?;
484    let (i, ciphers_len) = be_u16(i)?;
485    let (i, ciphers) = parse_cipher_suites(i, ciphers_len as usize)?;
486    let (i, comp_len) = be_u8(i)?;
487    let (i, comp) = parse_compressions_algs(i, comp_len as usize)?;
488    let (i, ext) = opt(complete(length_data(be_u16)))(i)?;
489    let content = TlsClientHelloContents::new(version, random, sid, ciphers, comp, ext);
490    Ok((i, content))
491}
492
493/// Parse a ClientHello handshake message
494///
495/// This function returns a [TlsMessageHandshake]. To get only the `ClientHello` contents, use the
496/// [parse_tls_handshake_client_hello] function.
497///
498/// ```rust
499/// use tls_parser::*;
500///
501/// # pub fn do_stuff(bytes: &[u8]) {
502/// if let Ok((_, TlsMessageHandshake::ClientHello(ch))) =
503///         parse_tls_handshake_msg_client_hello(bytes) {
504///     println!("ClientHello TLS version: {}", ch.version);
505///     println!("  number of proposed ciphersuites: {}", ch.ciphers.len());
506/// }
507/// # }
508/// ```
509pub fn parse_tls_handshake_msg_client_hello(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> {
510    map(
511        parse_tls_handshake_client_hello,
512        TlsMessageHandshake::ClientHello,
513    )(i)
514}
515
516pub(crate) fn parse_cipher_suites(i: &[u8], len: usize) -> IResult<&[u8], Vec<TlsCipherSuiteID>> {
517    if len == 0 {
518        return Ok((i, Vec::new()));
519    }
520    if len % 2 == 1 || len > i.len() {
521        return Err(Err::Error(make_error(i, ErrorKind::LengthValue)));
522    }
523    let v = (i[..len])
524        .chunks(2)
525        .map(|chunk| TlsCipherSuiteID((chunk[0] as u16) << 8 | chunk[1] as u16))
526        .collect();
527    Ok((&i[len..], v))
528}
529
530pub(crate) fn parse_compressions_algs(
531    i: &[u8],
532    len: usize,
533) -> IResult<&[u8], Vec<TlsCompressionID>> {
534    if len == 0 {
535        return Ok((i, Vec::new()));
536    }
537    if len > i.len() {
538        return Err(Err::Error(make_error(i, ErrorKind::LengthValue)));
539    }
540    let v = (i[..len]).iter().map(|&it| TlsCompressionID(it)).collect();
541    Ok((&i[len..], v))
542}
543
544pub(crate) fn parse_tls_versions(i: &[u8]) -> IResult<&[u8], Vec<TlsVersion>> {
545    let len = i.len();
546    if len == 0 {
547        return Ok((i, Vec::new()));
548    }
549    if len % 2 == 1 || len > i.len() {
550        return Err(Err::Error(make_error(i, ErrorKind::LengthValue)));
551    }
552    let v = (i[..len])
553        .chunks(2)
554        .map(|chunk| TlsVersion((chunk[0] as u16) << 8 | chunk[1] as u16))
555        .collect();
556    Ok((&i[len..], v))
557}
558
559fn parse_certs(i: &[u8]) -> IResult<&[u8], Vec<RawCertificate>> {
560    many0(complete(map(length_data(be_u24), |data| RawCertificate {
561        data,
562    })))(i)
563}
564
565fn parse_tls_handshake_msg_server_hello_tlsv12<const HAS_EXT: bool>(
566    i: &[u8],
567) -> IResult<&[u8], TlsMessageHandshake> {
568    map(
569        parse_tls_server_hello_tlsv12::<HAS_EXT>,
570        TlsMessageHandshake::ServerHello,
571    )(i)
572}
573
574pub(crate) fn parse_tls_server_hello_tlsv12<const HAS_EXT: bool>(
575    i: &[u8],
576) -> IResult<&[u8], TlsServerHelloContents> {
577    let (i, version) = be_u16(i)?;
578    let (i, random) = take(32usize)(i)?;
579    let (i, sidlen) = verify(be_u8, |&n| n <= 32)(i)?;
580    let (i, sid) = cond(sidlen > 0, take(sidlen as usize))(i)?;
581    let (i, cipher) = be_u16(i)?;
582    let (i, comp) = be_u8(i)?;
583    let (i, ext) = if HAS_EXT {
584        opt(complete(length_data(be_u16)))(i)?
585    } else {
586        (i, None)
587    };
588    let content = TlsServerHelloContents::new(version, random, sid, cipher, comp, ext);
589    Ok((i, content))
590}
591
592fn parse_tls_handshake_msg_server_hello_tlsv13draft18(
593    i: &[u8],
594) -> IResult<&[u8], TlsMessageHandshake> {
595    let (i, version) = TlsVersion::parse(i)?;
596    let (i, random) = take(32usize)(i)?;
597    let (i, cipher) = map(be_u16, TlsCipherSuiteID)(i)?;
598    let (i, ext) = opt(complete(length_data(be_u16)))(i)?;
599    let content = TlsServerHelloV13Draft18Contents {
600        version,
601        random,
602        cipher,
603        ext,
604    };
605    Ok((i, TlsMessageHandshake::ServerHelloV13Draft18(content)))
606}
607
608/// Parse handshake message contents for ServerHello (all TLS versions except 1.3 draft 18)
609///
610/// ```rust
611/// use tls_parser::*;
612///
613/// # pub fn do_stuff(bytes: &[u8]) {
614/// if let Ok((_, sh)) = parse_tls_handshake_server_hello(bytes) {
615///     println!("ServerHello TLS version: {}", sh.version);
616///     println!("  server chosen ciphersuites: {}", sh.cipher);
617/// }
618/// # }
619/// ```
620pub fn parse_tls_handshake_server_hello(i: &[u8]) -> IResult<&[u8], TlsServerHelloContents> {
621    let (_, version) = be_u16(i)?;
622    match version {
623        0x0303 => parse_tls_server_hello_tlsv12::<true>(i),
624        0x0302 => parse_tls_server_hello_tlsv12::<true>(i),
625        0x0301 => parse_tls_server_hello_tlsv12::<true>(i),
626        0x0300 => parse_tls_server_hello_tlsv12::<false>(i),
627        _ => Err(Err::Error(make_error(i, ErrorKind::Tag))),
628    }
629}
630
631/// Parse a ServerHello handshake message (all TLS versions)
632///
633/// This function returns a [TlsMessageHandshake]. To get only the `ServerHello` contents, use the
634/// [parse_tls_handshake_server_hello] function.
635///
636/// ```rust
637/// use tls_parser::*;
638///
639/// # pub fn do_stuff(bytes: &[u8]) {
640/// if let Ok((_, msg)) = parse_tls_handshake_msg_server_hello(bytes) {
641///     match msg {
642///         TlsMessageHandshake::ServerHello(sh) => {
643///             println!("ServerHello TLS version: {}", sh.version);
644///             println!("  server chosen ciphersuites: {}", sh.cipher);
645///         }
646///         TlsMessageHandshake::ServerHelloV13Draft18(sh) => {
647///             println!("ServerHello v1.3 draft 18 TLS version: {}", sh.version);
648///         }
649///         _ => {
650///             println!("Not a ServerHello");
651///         }
652///     }
653/// }
654/// # }
655/// ```
656pub fn parse_tls_handshake_msg_server_hello(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> {
657    let (_, version) = be_u16(i)?;
658    match version {
659        0x7f12 => parse_tls_handshake_msg_server_hello_tlsv13draft18(i),
660        0x0303 => parse_tls_handshake_msg_server_hello_tlsv12::<true>(i),
661        0x0302 => parse_tls_handshake_msg_server_hello_tlsv12::<true>(i),
662        0x0301 => parse_tls_handshake_msg_server_hello_tlsv12::<true>(i),
663        0x0300 => parse_tls_handshake_msg_server_hello_tlsv12::<false>(i),
664        _ => Err(Err::Error(make_error(i, ErrorKind::Tag))),
665    }
666}
667
668/// Parse a NewSessionTicket handshake message
669// RFC 5077   Stateless TLS Session Resumption
670pub fn parse_tls_handshake_msg_newsessionticket(
671    i: &[u8],
672    len: usize,
673) -> IResult<&[u8], TlsMessageHandshake> {
674    if len < 4 {
675        return Err(Err::Error(make_error(i, ErrorKind::Verify)));
676    }
677    let (i, ticket_lifetime_hint) = be_u32(i)?;
678    let (i, ticket) = take(len - 4)(i)?;
679    let content = TlsNewSessionTicketContent {
680        ticket_lifetime_hint,
681        ticket,
682    };
683    Ok((i, TlsMessageHandshake::NewSessionTicket(content)))
684}
685
686/// Parse a HelloRetryRequest handshake message
687pub fn parse_tls_handshake_msg_hello_retry_request(
688    i: &[u8],
689) -> IResult<&[u8], TlsMessageHandshake> {
690    let (i, version) = TlsVersion::parse(i)?;
691    let (i, cipher) = map(be_u16, TlsCipherSuiteID)(i)?;
692    let (i, ext) = opt(complete(length_data(be_u16)))(i)?;
693    let content = TlsHelloRetryRequestContents {
694        version,
695        cipher,
696        ext,
697    };
698    Ok((i, TlsMessageHandshake::HelloRetryRequest(content)))
699}
700
701pub(crate) fn parse_tls_certificate(i: &[u8]) -> IResult<&[u8], TlsCertificateContents> {
702    let (i, cert_len) = be_u24(i)?;
703    let (i, cert_chain) = map_parser(take(cert_len as usize), parse_certs)(i)?;
704    let content = TlsCertificateContents { cert_chain };
705    Ok((i, content))
706}
707
708/// Parse a Certificate handshake message
709pub fn parse_tls_handshake_msg_certificate(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> {
710    map(parse_tls_certificate, TlsMessageHandshake::Certificate)(i)
711}
712
713/// Parse a ServerKeyExchange handshake message
714pub fn parse_tls_handshake_msg_serverkeyexchange(
715    i: &[u8],
716    len: usize,
717) -> IResult<&[u8], TlsMessageHandshake> {
718    map(take(len), |ext| {
719        TlsMessageHandshake::ServerKeyExchange(TlsServerKeyExchangeContents { parameters: ext })
720    })(i)
721}
722
723/// Parse a ServerDone handshake message
724pub fn parse_tls_handshake_msg_serverdone(
725    i: &[u8],
726    len: usize,
727) -> IResult<&[u8], TlsMessageHandshake> {
728    map(take(len), TlsMessageHandshake::ServerDone)(i)
729}
730
731/// Parse a CertificateVerify handshake message
732pub fn parse_tls_handshake_msg_certificateverify(
733    i: &[u8],
734    len: usize,
735) -> IResult<&[u8], TlsMessageHandshake> {
736    map(take(len), TlsMessageHandshake::CertificateVerify)(i)
737}
738
739pub(crate) fn parse_tls_clientkeyexchange(
740    len: usize,
741) -> impl FnMut(&[u8]) -> IResult<&[u8], TlsClientKeyExchangeContents> {
742    move |i| map(take(len), TlsClientKeyExchangeContents::Unknown)(i)
743}
744
745/// Parse a ClientKeyExchange handshake message
746///
747/// This function does not known the data structure, so it will always return
748/// [TlsClientKeyExchangeContents::Unknown] with the raw data
749pub fn parse_tls_handshake_msg_clientkeyexchange(
750    i: &[u8],
751    len: usize,
752) -> IResult<&[u8], TlsMessageHandshake> {
753    map(
754        parse_tls_clientkeyexchange(len),
755        TlsMessageHandshake::ClientKeyExchange,
756    )(i)
757}
758
759fn parse_certrequest_nosigalg(i: &[u8]) -> IResult<&[u8], TlsCertificateRequestContents> {
760    let (i, cert_types) = length_count(be_u8, be_u8)(i)?;
761    let (i, ca_len) = be_u16(i)?;
762    let (i, unparsed_ca) =
763        map_parser(take(ca_len as usize), many0(complete(length_data(be_u16))))(i)?;
764    let content = TlsCertificateRequestContents {
765        cert_types,
766        // sig_hash_algs: Some(sig_hash_algs),
767        sig_hash_algs: None,
768        unparsed_ca,
769    };
770    Ok((i, content))
771}
772
773fn parse_certrequest_full(i: &[u8]) -> IResult<&[u8], TlsCertificateRequestContents> {
774    let (i, cert_types) = length_count(be_u8, be_u8)(i)?;
775    let (i, sig_hash_algs_len) = be_u16(i)?;
776    let (i, sig_hash_algs) =
777        map_parser(take(sig_hash_algs_len as usize), many0(complete(be_u16)))(i)?;
778    let (i, ca_len) = be_u16(i)?;
779    let (i, unparsed_ca) =
780        map_parser(take(ca_len as usize), many0(complete(length_data(be_u16))))(i)?;
781    let content = TlsCertificateRequestContents {
782        cert_types,
783        sig_hash_algs: Some(sig_hash_algs),
784        unparsed_ca,
785    };
786    Ok((i, content))
787}
788
789/// Parse a CertificateRequest handshake message
790pub fn parse_tls_handshake_certificaterequest(
791    i: &[u8],
792) -> IResult<&[u8], TlsCertificateRequestContents> {
793    alt((
794        complete(parse_certrequest_full),
795        complete(parse_certrequest_nosigalg),
796    ))(i)
797}
798
799/// Parse a CertificateRequest handshake message
800pub fn parse_tls_handshake_msg_certificaterequest(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> {
801    map(
802        parse_tls_handshake_certificaterequest,
803        TlsMessageHandshake::CertificateRequest,
804    )(i)
805}
806
807/// Parse a Finished handshake message
808pub fn parse_tls_handshake_msg_finished(
809    i: &[u8],
810    len: usize,
811) -> IResult<&[u8], TlsMessageHandshake> {
812    map(take(len), TlsMessageHandshake::Finished)(i)
813}
814
815/// Parse handshake message contents for CertificateStatus (\[RFC6066\])
816///
817/// If status_type == 0, blob is a OCSPResponse, as defined in [RFC2560](https://tools.ietf.org/html/rfc2560)
818///
819/// Note that the OCSPResponse object is DER-encoded.
820pub fn parse_tls_handshake_certificatestatus(
821    i: &[u8],
822) -> IResult<&[u8], TlsCertificateStatusContents> {
823    let (i, status_type) = be_u8(i)?;
824    let (i, blob) = length_data(be_u24)(i)?;
825    let content = TlsCertificateStatusContents { status_type, blob };
826    Ok((i, content))
827}
828
829/// Parse a CertificateStatus handshake message (\[RFC6066\])
830///
831/// If status_type == 0, blob is a OCSPResponse, as defined in [RFC2560](https://tools.ietf.org/html/rfc2560)
832///
833/// Note that the OCSPResponse object is DER-encoded.
834pub fn parse_tls_handshake_msg_certificatestatus(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> {
835    map(
836        parse_tls_handshake_certificatestatus,
837        TlsMessageHandshake::CertificateStatus,
838    )(i)
839}
840
841/// Parse handshake message contents for NextProtocol
842///
843/// NextProtocol handshake message, as defined in
844/// [draft-agl-tls-nextprotoneg-03](https://tools.ietf.org/html/draft-agl-tls-nextprotoneg-03)
845/// Deprecated in favour of ALPN.
846pub fn parse_tls_handshake_next_protocol(i: &[u8]) -> IResult<&[u8], TlsNextProtocolContent> {
847    let (i, selected_protocol) = length_data(be_u8)(i)?;
848    let (i, padding) = length_data(be_u8)(i)?;
849    let next_proto = TlsNextProtocolContent {
850        selected_protocol,
851        padding,
852    };
853    Ok((i, next_proto))
854}
855
856/// Parse a NextProtocol handshake message
857///
858/// NextProtocol handshake message, as defined in
859/// [draft-agl-tls-nextprotoneg-03](https://tools.ietf.org/html/draft-agl-tls-nextprotoneg-03)
860/// Deprecated in favour of ALPN.
861pub fn parse_tls_handshake_msg_next_protocol(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> {
862    map(
863        parse_tls_handshake_next_protocol,
864        TlsMessageHandshake::NextProtocol,
865    )(i)
866}
867
868/// Parse a KeyUpdate handshake message
869pub fn parse_tls_handshake_msg_key_update(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> {
870    map(be_u8, TlsMessageHandshake::KeyUpdate)(i)
871}
872
873/// Parse a TLS handshake message
874pub fn parse_tls_message_handshake(i: &[u8]) -> IResult<&[u8], TlsMessage> {
875    let (i, ht) = be_u8(i)?;
876    let (i, hl) = be_u24(i)?;
877    let (i, raw_msg) = take(hl)(i)?;
878    let (_, msg) = match TlsHandshakeType(ht) {
879        TlsHandshakeType::HelloRequest => parse_tls_handshake_msg_hello_request(raw_msg),
880        TlsHandshakeType::ClientHello => parse_tls_handshake_msg_client_hello(raw_msg),
881        TlsHandshakeType::ServerHello => parse_tls_handshake_msg_server_hello(raw_msg),
882        TlsHandshakeType::NewSessionTicket => {
883            parse_tls_handshake_msg_newsessionticket(raw_msg, hl as usize)
884        }
885        TlsHandshakeType::EndOfEarlyData => Ok((raw_msg, TlsMessageHandshake::EndOfEarlyData)),
886        TlsHandshakeType::HelloRetryRequest => parse_tls_handshake_msg_hello_retry_request(raw_msg),
887        TlsHandshakeType::Certificate => parse_tls_handshake_msg_certificate(raw_msg),
888        TlsHandshakeType::ServerKeyExchange => {
889            parse_tls_handshake_msg_serverkeyexchange(raw_msg, hl as usize)
890        }
891        TlsHandshakeType::CertificateRequest => parse_tls_handshake_msg_certificaterequest(raw_msg),
892        TlsHandshakeType::ServerDone => parse_tls_handshake_msg_serverdone(raw_msg, hl as usize),
893        TlsHandshakeType::CertificateVerify => {
894            parse_tls_handshake_msg_certificateverify(raw_msg, hl as usize)
895        }
896        TlsHandshakeType::ClientKeyExchange => {
897            parse_tls_handshake_msg_clientkeyexchange(raw_msg, hl as usize)
898        }
899        TlsHandshakeType::Finished => parse_tls_handshake_msg_finished(raw_msg, hl as usize),
900        // TlsHandshakeType::CertificateURL => parse_tls_handshake_msg_certificateurl(raw_msg),
901        TlsHandshakeType::CertificateStatus => parse_tls_handshake_msg_certificatestatus(raw_msg),
902        TlsHandshakeType::KeyUpdate => parse_tls_handshake_msg_key_update(raw_msg),
903        TlsHandshakeType::NextProtocol => parse_tls_handshake_msg_next_protocol(raw_msg),
904        _ => Err(Err::Error(make_error(i, ErrorKind::Switch))),
905    }?;
906    Ok((i, TlsMessage::Handshake(msg)))
907}