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