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