Coverage Report

Created: 2025-07-11 07:47

/src/PcapPlusPlus/Packet++/header/IPSecLayer.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
/// @file
4
5
#include "Layer.h"
6
7
/// @namespace pcpp
8
/// @brief The main namespace for the PcapPlusPlus lib
9
namespace pcpp
10
{
11
  /// @struct ipsec_authentication_header
12
  /// Represents IPSec AuthenticationHeader (AH) structure
13
#pragma pack(push, 1)
14
  struct ipsec_authentication_header
15
  {
16
    /// Type of the next header
17
    uint8_t nextHeader;
18
    /// The length of the Authentication Header in 4-octet units, minus 2
19
    uint8_t payloadLen;
20
    /// Reserved
21
    uint16_t reserved;
22
    /// Security Parameters Index
23
    uint32_t spi;
24
    /// Sequence Number
25
    uint32_t sequenceNumber;
26
  };
27
#pragma pack(pop)
28
  static_assert(sizeof(ipsec_authentication_header) == 12, "ipsec_authentication_header size is not 12 bytes");
29
30
  /// @struct ipsec_esp
31
  /// Represents IPSec Encapsulating Security Payload (ESP) structure
32
#pragma pack(push, 1)
33
  struct ipsec_esp
34
  {
35
    /// Security Parameters Index
36
    uint32_t spi;
37
    /// Sequence Number
38
    uint32_t sequenceNumber;
39
  };
40
#pragma pack(pop)
41
  static_assert(sizeof(ipsec_esp) == 8, "ipsec_esp size is not 8 bytes");
42
43
  /// @class AuthenticationHeaderLayer
44
  /// Represents an IPSec AuthenticationHeader (AH) layer
45
  class AuthenticationHeaderLayer : public Layer
46
  {
47
  public:
48
    /// A constructor that creates the layer from an existing packet raw data
49
    /// @param[in] data A pointer to the raw data
50
    /// @param[in] dataLen Size of the data in bytes
51
    /// @param[in] prevLayer A pointer to the previous layer
52
    /// @param[in] packet A pointer to the Packet instance where layer will be stored in
53
    AuthenticationHeaderLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
54
2.38k
        : Layer(data, dataLen, prevLayer, packet, AuthenticationHeader)
55
2.38k
    {}
56
57
    /// Get a pointer to the raw AH header. Notice this points directly to the data, so every change will change the
58
    /// actual packet data
59
    /// @return A pointer to the ipsec_authentication_header
60
    ipsec_authentication_header* getAHHeader() const
61
5.15k
    {
62
5.15k
      return reinterpret_cast<ipsec_authentication_header*>(m_Data);
63
5.15k
    }
64
65
    /// @return The Security Parameters Index (SPI) field value
66
    uint32_t getSPI() const;
67
68
    /// @return The sequence number value
69
    uint32_t getSequenceNumber() const;
70
71
    /// @return The size of the Integrity Check Value (ICV)
72
    size_t getICVLength() const;
73
74
    /// @return A pointer to the raw data of the Integrity Check Value (ICV)
75
    uint8_t* getICVBytes() const;
76
77
    /// @return The value of the Integrity Check Value (ICV) as a hex string
78
    std::string getICVHexStream() const;
79
80
    /// A static method that validates the input data
81
    /// @param[in] data The pointer to the beginning of a byte stream of a AuthenticationHeader layer
82
    /// @param[in] dataLen The length of byte stream
83
    /// @return True if the data is valid and can represent an AuthenticationHeader layer
84
    static inline bool isDataValid(const uint8_t* data, size_t dataLen);
85
86
    // implement abstract methods
87
88
    /// @return The size of the AH header
89
    size_t getHeaderLen() const override
90
2.76k
    {
91
2.76k
      return static_cast<size_t>(4) * (getAHHeader()->payloadLen + 2);
92
2.76k
    }
93
94
    /// Currently identifies the following next layers: UdpLayer, TcpLayer, IPv4Layer, IPv6Layer and ESPLayer.
95
    /// Otherwise sets PayloadLayer
96
    void parseNextLayer() override;
97
98
    /// Does nothing for this layer
99
    void computeCalculateFields() override
100
380
    {}
101
102
    std::string toString() const override;
103
104
    OsiModelLayer getOsiModelLayer() const override
105
380
    {
106
380
      return OsiModelNetworkLayer;
107
380
    }
108
109
  private:
110
    // this layer supports parsing only
111
    AuthenticationHeaderLayer()
112
0
    {}
113
  };
114
115
  /// @class ESPLayer
116
  /// Represents an IPSec Encapsulating Security Payload (ESP) layer
117
  class ESPLayer : public Layer
118
  {
119
  public:
120
    /// A constructor that creates the layer from an existing packet raw data
121
    /// @param[in] data A pointer to the raw data
122
    /// @param[in] dataLen Size of the data in bytes
123
    /// @param[in] prevLayer A pointer to the previous layer
124
    /// @param[in] packet A pointer to the Packet instance where layer will be stored in
125
    ESPLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
126
1.52k
        : Layer(data, dataLen, prevLayer, packet, ESP)
127
1.52k
    {}
128
129
    ipsec_esp* getESPHeader() const
130
530
    {
131
530
      return reinterpret_cast<ipsec_esp*>(m_Data);
132
530
    }
133
134
    /// @return The Security Parameters Index (SPI) field value
135
    uint32_t getSPI() const;
136
137
    /// @return The sequence number value
138
    uint32_t getSequenceNumber() const;
139
140
    /// A static method that validates the input data
141
    /// @param[in] data The pointer to the beginning of a byte stream of a ESP layer
142
    /// @param[in] dataLen The length of byte stream
143
    /// @return True if the data is valid and can represent an ESP layer
144
    static inline bool isDataValid(const uint8_t* data, size_t dataLen);
145
146
    // implement abstract methods
147
148
    /// @return The size of the ESP header (8 bytes)
149
    size_t getHeaderLen() const override
150
1.78k
    {
151
1.78k
      return sizeof(ipsec_esp);
152
1.78k
    }
153
154
    /// The payload of an ESP layer is encrypted, hence the next layer is always a generic payload (PayloadLayer)
155
    void parseNextLayer() override;
156
157
    /// Does nothing for this layer
158
    void computeCalculateFields() override
159
265
    {}
160
161
    std::string toString() const override;
162
163
    OsiModelLayer getOsiModelLayer() const override
164
265
    {
165
265
      return OsiModelTransportLayer;
166
265
    }
167
168
  private:
169
    // this layer supports parsing only
170
    ESPLayer()
171
0
    {}
172
  };
173
174
  // implementation of inline methods
175
176
  bool AuthenticationHeaderLayer::isDataValid(const uint8_t* data, size_t dataLen)
177
2.53k
  {
178
2.53k
    if (dataLen < sizeof(ipsec_authentication_header))
179
0
      return false;
180
181
2.53k
    size_t payloadLen = 4 * (data[1] + 2);
182
2.53k
    if (payloadLen < sizeof(ipsec_authentication_header) || payloadLen > dataLen)
183
150
      return false;
184
185
2.38k
    return true;
186
2.53k
  }
187
188
  bool ESPLayer::isDataValid(const uint8_t* data, size_t dataLen)
189
1.52k
  {
190
1.52k
    return data && dataLen >= sizeof(ipsec_esp);
191
1.52k
  }
192
}  // namespace pcpp