Coverage Report

Created: 2026-10-17 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/header/IPSecLayer.h
Line
Count
Source
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
0
        : Layer(data, dataLen, prevLayer, packet, AuthenticationHeader)
55
0
    {}
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
0
    {
62
0
      return reinterpret_cast<ipsec_authentication_header*>(m_Data);
63
0
    }
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
0
    {
91
0
      return static_cast<size_t>(4) * (getAHHeader()->payloadLen + 2);
92
0
    }
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
0
    {}
101
102
    std::string toString() const override;
103
104
    OsiModelLayer getOsiModelLayer() const override
105
0
    {
106
0
      return OsiModelNetworkLayer;
107
0
    }
108
109
    /// @struct SerializedFields
110
    /// Fields written by AuthenticationHeaderLayer's serializeLayer(), in addition to
111
    /// Layer::SerializedFields.
112
    struct SerializedFields : Layer::SerializedFields
113
    {
114
      /// @return All field descriptors for AuthenticationHeaderLayer
115
      static std::vector<FieldDescriptor> all()
116
0
      {
117
0
        auto result = Layer::SerializedFields::all();
118
0
        std::initializer_list<FieldDescriptor> extra{ SPI, SequenceNumber, ICV };
119
0
        std::copy(extra.begin(), extra.end(), std::back_inserter(result));
120
0
        return result;
121
0
      }
122
123
      /// @brief Field descriptor for the Security Parameters Index (SPI), written as a hex value.
124
      static const FieldDescriptor SPI;
125
126
      /// @brief Field descriptor for the sequence number, written as a number.
127
      static const FieldDescriptor SequenceNumber;
128
129
      /// @brief Field descriptor for the Integrity Check Value (ICV), written as a hex string.
130
      static const FieldDescriptor ICV;
131
    };
132
133
  protected:
134
    void serializeLayer(ObjectScope& serializer) const override;
135
136
  private:
137
    // this layer supports parsing only
138
    AuthenticationHeaderLayer()
139
0
    {}
140
  };
141
142
  /// @class ESPLayer
143
  /// Represents an IPSec Encapsulating Security Payload (ESP) layer
144
  class ESPLayer : public Layer
145
  {
146
  public:
147
    /// A constructor that creates the layer from an existing packet raw data
148
    /// @param[in] data A pointer to the raw data
149
    /// @param[in] dataLen Size of the data in bytes
150
    /// @param[in] prevLayer A pointer to the previous layer
151
    /// @param[in] packet A pointer to the Packet instance where layer will be stored in
152
    ESPLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
153
0
        : Layer(data, dataLen, prevLayer, packet, ESP)
154
0
    {}
155
156
    ipsec_esp* getESPHeader() const
157
0
    {
158
0
      return reinterpret_cast<ipsec_esp*>(m_Data);
159
0
    }
160
161
    /// @return The Security Parameters Index (SPI) field value
162
    uint32_t getSPI() const;
163
164
    /// @return The sequence number value
165
    uint32_t getSequenceNumber() const;
166
167
    /// A static method that validates the input data
168
    /// @param[in] data The pointer to the beginning of a byte stream of a ESP layer
169
    /// @param[in] dataLen The length of byte stream
170
    /// @return True if the data is valid and can represent an ESP layer
171
    static inline bool isDataValid(const uint8_t* data, size_t dataLen);
172
173
    // implement abstract methods
174
175
    /// @return The size of the ESP header (8 bytes)
176
    size_t getHeaderLen() const override
177
0
    {
178
0
      return sizeof(ipsec_esp);
179
0
    }
180
181
    /// The payload of an ESP layer is encrypted, hence the next layer is always a generic payload (PayloadLayer)
182
    void parseNextLayer() override;
183
184
    /// Does nothing for this layer
185
    void computeCalculateFields() override
186
0
    {}
187
188
    std::string toString() const override;
189
190
    OsiModelLayer getOsiModelLayer() const override
191
0
    {
192
0
      return OsiModelTransportLayer;
193
0
    }
194
195
    /// @struct SerializedFields
196
    /// Fields written by ESPLayer's serializeLayer(), in addition to
197
    /// Layer::SerializedFields.
198
    struct SerializedFields : Layer::SerializedFields
199
    {
200
      /// @return All field descriptors for ESPLayer
201
      static std::vector<FieldDescriptor> all()
202
0
      {
203
0
        auto result = Layer::SerializedFields::all();
204
0
        std::initializer_list<FieldDescriptor> extra{ SPI, SequenceNumber };
205
0
        std::copy(extra.begin(), extra.end(), std::back_inserter(result));
206
0
        return result;
207
0
      }
208
209
      /// @brief Field descriptor for the Security Parameters Index (SPI), written as a hex value.
210
      static const FieldDescriptor SPI;
211
212
      /// @brief Field descriptor for the sequence number, written as a number.
213
      static const FieldDescriptor SequenceNumber;
214
    };
215
216
  protected:
217
    void serializeLayer(ObjectScope& serializer) const override;
218
219
  private:
220
    // this layer supports parsing only
221
    ESPLayer()
222
0
    {}
223
  };
224
225
  // implementation of inline methods
226
227
  bool AuthenticationHeaderLayer::isDataValid(const uint8_t* data, size_t dataLen)
228
0
  {
229
0
    if (dataLen < sizeof(ipsec_authentication_header))
230
0
      return false;
231
232
0
    size_t payloadLen = 4 * (data[1] + 2);
233
0
    if (payloadLen < sizeof(ipsec_authentication_header) || payloadLen > dataLen)
234
0
      return false;
235
236
0
    return true;
237
0
  }
238
239
  bool ESPLayer::isDataValid(const uint8_t* data, size_t dataLen)
240
0
  {
241
0
    return data && dataLen >= sizeof(ipsec_esp);
242
0
  }
243
}  // namespace pcpp