tls_parser/
tls_message.rs

1use alloc::{vec, vec::Vec};
2use nom::bytes::streaming::take;
3use nom::combinator::verify;
4use nom::error::{make_error, ErrorKind};
5use nom::number::streaming::{be_u16, be_u8};
6use nom::{Err, IResult};
7use nom_derive::Parse;
8
9use crate::tls_alert::*;
10use crate::tls_handshake::*;
11
12/// TLS plaintext message
13///
14/// Plaintext records can only be found during the handshake.
15#[derive(Clone, Debug, PartialEq)]
16pub enum TlsMessage<'a> {
17    Handshake(TlsMessageHandshake<'a>),
18    ChangeCipherSpec,
19    Alert(TlsMessageAlert),
20    ApplicationData(TlsMessageApplicationData<'a>),
21    Heartbeat(TlsMessageHeartbeat<'a>),
22}
23
24/// TLS application data
25///
26/// Since this message can only be sent after the handshake, data is
27/// stored as opaque.
28#[derive(Clone, Debug, PartialEq)]
29pub struct TlsMessageApplicationData<'a> {
30    pub blob: &'a [u8],
31}
32
33/// TLS heartbeat message, as defined in [RFC6520](https://tools.ietf.org/html/rfc6520)
34///
35/// Heartbeat messages should not be sent during handshake, but in practise
36/// they can (and this caused heartbleed).
37#[derive(Clone, Debug, PartialEq)]
38pub struct TlsMessageHeartbeat<'a> {
39    pub heartbeat_type: TlsHeartbeatMessageType,
40    pub payload_len: u16,
41    pub payload: &'a [u8],
42}
43
44/// Parse a TLS changecipherspec message
45// XXX add extra verification hdr.len == 1
46pub fn parse_tls_message_changecipherspec(i: &[u8]) -> IResult<&[u8], TlsMessage> {
47    let (i, _) = verify(be_u8, |&tag| tag == 0x01)(i)?;
48    Ok((i, TlsMessage::ChangeCipherSpec))
49}
50
51/// Parse a TLS alert message
52// XXX add extra verification hdr.len == 2
53pub fn parse_tls_message_alert(i: &[u8]) -> IResult<&[u8], TlsMessage> {
54    let (i, alert) = TlsMessageAlert::parse(i)?;
55    Ok((i, TlsMessage::Alert(alert)))
56}
57
58/// Parse a TLS applicationdata message
59///
60/// Read the entire input as applicationdata
61pub fn parse_tls_message_applicationdata(i: &[u8]) -> IResult<&[u8], TlsMessage> {
62    let msg = TlsMessage::ApplicationData(TlsMessageApplicationData { blob: i });
63    Ok((&[], msg))
64}
65
66/// Parse a TLS heartbeat message
67pub fn parse_tls_message_heartbeat(
68    i: &[u8],
69    tls_plaintext_len: u16,
70) -> IResult<&[u8], Vec<TlsMessage>> {
71    let (i, heartbeat_type) = TlsHeartbeatMessageType::parse(i)?;
72    let (i, payload_len) = be_u16(i)?;
73    if tls_plaintext_len < 3 {
74        return Err(Err::Error(make_error(i, ErrorKind::Verify)));
75    }
76    let (i, payload) = take(payload_len as usize)(i)?;
77    let v = vec![TlsMessage::Heartbeat(TlsMessageHeartbeat {
78        heartbeat_type,
79        payload_len,
80        payload,
81    })];
82    Ok((i, v))
83}