Coverage Report

Created: 2025-07-18 07:14

/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
4.10k
        : Layer(data, dataLen, prevLayer, packet, AuthenticationHeader)
55
4.10k
    {}
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
8.84k
    {
62
8.84k
      return reinterpret_cast<ipsec_authentication_header*>(m_Data);
63
8.84k
    }
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
4.75k
    {
91
4.75k
      return static_cast<size_t>(4) * (getAHHeader()->payloadLen + 2);
92
4.75k
    }
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
652
    {}
101
102
    std::string toString() const override;
103
104
    OsiModelLayer getOsiModelLayer() const override
105
652
    {
106
652
      return OsiModelNetworkLayer;
107
652
    }
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
2.82k
        : Layer(data, dataLen, prevLayer, packet, ESP)
127
2.82k
    {}
128
129
    ipsec_esp* getESPHeader() const
130
980
    {
131
980
      return reinterpret_cast<ipsec_esp*>(m_Data);
132
980
    }
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
3.31k
    {
151
3.31k
      return sizeof(ipsec_esp);
152
3.31k
    }
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
490
    {}
160
161
    std::string toString() const override;
162
163
    OsiModelLayer getOsiModelLayer() const override
164
490
    {
165
490
      return OsiModelTransportLayer;
166
490
    }
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
4.35k
  {
178
4.35k
    if (dataLen < sizeof(ipsec_authentication_header))
179
0
      return false;
180
181
4.35k
    size_t payloadLen = 4 * (data[1] + 2);
182
4.35k
    if (payloadLen < sizeof(ipsec_authentication_header) || payloadLen > dataLen)
183
256
      return false;
184
185
4.10k
    return true;
186
4.35k
  }
187
188
  bool ESPLayer::isDataValid(const uint8_t* data, size_t dataLen)
189
2.90k
  {
190
2.90k
    return data && dataLen >= sizeof(ipsec_esp);
191
2.90k
  }
192
}  // namespace pcpp