ipsec_parser/
esp.rs

1use crate::ikev2::IkeV2Header;
2use crate::ikev2_parser::parse_ikev2_header;
3use nom::bytes::streaming::take;
4use nom::combinator::rest;
5use nom::number::streaming::be_u32;
6use nom::IResult;
7
8/// Encapsulating Security Payload Packet Format
9///
10/// Defined in [RFC2406](https://tools.ietf.org/html/rfc2406) section 2
11#[derive(Debug)]
12pub struct ESPHeader<'a> {
13    pub spi_index: &'a [u8],
14    pub seq: u32,
15    pub data: &'a [u8],
16}
17
18/// UDP-encapsulated Packet Formats
19///
20/// Defined in [RFC3948](https://tools.ietf.org/html/rfc3948) section 2
21#[derive(Debug)]
22pub enum ESPData<'a> {
23    ESP(ESPHeader<'a>),
24    IKE(IkeV2Header),
25}
26
27/// Parse an encapsulated ESP packet
28///
29/// The type of encapsulated data depends on the first field (`spi_index`): 0 is a forbidden SPI
30/// index, and indicates that the header is an IKE header.
31/// Any other value indicates an ESP header.
32///
33/// *Note: input is entirely consumed*
34pub fn parse_esp_encapsulated(i: &[u8]) -> IResult<&[u8], ESPData> {
35    if be_u32(i)?.1 == 0 {
36        parse_ikev2_header(i).map(|x| (x.0, ESPData::IKE(x.1)))
37    } else {
38        parse_esp_header(i).map(|x| (x.0, ESPData::ESP(x.1)))
39    }
40}
41
42/// Parse an ESP packet
43///
44/// The ESP header contains:
45///
46/// - the SPI index
47/// - the sequence number
48/// - the payload data (which can be encrypted)
49///
50/// *Note: input is entirely consumed*
51pub fn parse_esp_header(i: &[u8]) -> IResult<&[u8], ESPHeader> {
52    let (i, spi_index) = take(4usize)(i)?;
53    let (i, seq) = be_u32(i)?;
54    let (i, data) = rest(i)?;
55    let hdr = ESPHeader {
56        spi_index,
57        seq,
58        data,
59    };
60    Ok((i, hdr))
61}