/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 | 1.42k | : Layer(data, dataLen, prevLayer, packet, AuthenticationHeader) |
55 | 1.42k | {} |
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 | 3.13k | { |
62 | 3.13k | return reinterpret_cast<ipsec_authentication_header*>(m_Data); |
63 | 3.13k | } |
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 | 1.70k | { |
91 | 1.70k | return static_cast<size_t>(4) * (getAHHeader()->payloadLen + 2); |
92 | 1.70k | } |
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 | 285 | {} |
101 | | |
102 | | std::string toString() const override; |
103 | | |
104 | | OsiModelLayer getOsiModelLayer() const override |
105 | 285 | { |
106 | 285 | return OsiModelNetworkLayer; |
107 | 285 | } |
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 | 95 | : Layer(data, dataLen, prevLayer, packet, ESP) |
154 | 95 | {} |
155 | | |
156 | | ipsec_esp* getESPHeader() const |
157 | 38 | { |
158 | 38 | return reinterpret_cast<ipsec_esp*>(m_Data); |
159 | 38 | } |
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 | 114 | { |
178 | 114 | return sizeof(ipsec_esp); |
179 | 114 | } |
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 | 19 | {} |
187 | | |
188 | | std::string toString() const override; |
189 | | |
190 | | OsiModelLayer getOsiModelLayer() const override |
191 | 19 | { |
192 | 19 | return OsiModelTransportLayer; |
193 | 19 | } |
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 | 1.42k | { |
229 | 1.42k | if (dataLen < sizeof(ipsec_authentication_header)) |
230 | 0 | return false; |
231 | | |
232 | 1.42k | size_t payloadLen = 4 * (data[1] + 2); |
233 | 1.42k | if (payloadLen < sizeof(ipsec_authentication_header) || payloadLen > dataLen) |
234 | 6 | return false; |
235 | | |
236 | 1.42k | return true; |
237 | 1.42k | } |
238 | | |
239 | | bool ESPLayer::isDataValid(const uint8_t* data, size_t dataLen) |
240 | 95 | { |
241 | 95 | return data && dataLen >= sizeof(ipsec_esp); |
242 | 95 | } |
243 | | } // namespace pcpp |