/src/PcapPlusPlus/Packet++/header/SSLHandshake.h
Line | Count | Source |
1 | | #pragma once |
2 | | |
3 | | #include <utility> |
4 | | #include <type_traits> |
5 | | #include "SSLCommon.h" |
6 | | #include "PointerVector.h" |
7 | | #include "Asn1Codec.h" |
8 | | #include "X509Decoder.h" |
9 | | |
10 | | /// @file |
11 | | /// See detailed explanation of the TLS/SSL protocol support in PcapPlusPlus in SSLLayer.h |
12 | | |
13 | | /// @namespace pcpp |
14 | | /// @brief The main namespace for the PcapPlusPlus lib |
15 | | namespace pcpp |
16 | | { |
17 | | /// @class SSLCipherSuite |
18 | | /// Represents a cipher-suite and enables access all information about it such as all algorithms it encapsulates, |
19 | | /// its ID (as appears in the client-hello or server-hello messages), |
20 | | /// its name (e.g "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA") etc. PcapPlusPlus contains static instances of this type |
21 | | /// for all known cipher-suites and enables access to them through name or ID (see getCipherSuiteByID() and |
22 | | /// getCipherSuiteByName() ). List of cipher-suite was taken from here: |
23 | | /// http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml |
24 | | class SSLCipherSuite |
25 | | { |
26 | | public: |
27 | | /// A c'tor for this class, should never be used by a user |
28 | | /// @param[in] id Cipher-suite ID |
29 | | /// @param[in] keyExAlg Key-exchange algorithm used in this cipher-suite |
30 | | /// @param[in] authAlg Authentication algorithm used in this cipher-suite |
31 | | /// @param[in] symKeyAlg Symmetric key algorithm used in this cipher-suite |
32 | | /// @param[in] MACAlg MAC algorithm used in this cipher-suite |
33 | | /// @param[in] name String representation of this cipher-suite |
34 | | SSLCipherSuite(uint16_t id, SSLKeyExchangeAlgorithm keyExAlg, SSLAuthenticationAlgorithm authAlg, |
35 | | SSLSymetricEncryptionAlgorithm symKeyAlg, SSLHashingAlgorithm MACAlg, const char* name) |
36 | 658 | : m_Id(id), m_KeyExAlg(keyExAlg), m_AuthAlg(authAlg), m_SymKeyAlg(symKeyAlg), m_MACAlg(MACAlg), m_Name(name) |
37 | 658 | {} |
38 | | |
39 | | /// @return Cipher-suite ID |
40 | | uint16_t getID() const |
41 | 0 | { |
42 | 0 | return m_Id; |
43 | 0 | } |
44 | | |
45 | | /// @return String representation of this cipher-suite |
46 | | std::string asString() const |
47 | 0 | { |
48 | 0 | return m_Name; |
49 | 0 | } |
50 | | |
51 | | /// @return Key-exchange algorithm used in this cipher-suite |
52 | | SSLKeyExchangeAlgorithm getKeyExchangeAlg() const |
53 | 0 | { |
54 | 0 | return m_KeyExAlg; |
55 | 0 | } |
56 | | |
57 | | /// @return Authentication algorithm used in this cipher-suite |
58 | | SSLAuthenticationAlgorithm getAuthAlg() const |
59 | 0 | { |
60 | 0 | return m_AuthAlg; |
61 | 0 | } |
62 | | |
63 | | /// @return Symmetric key algorithm used in this cipher-suite |
64 | | SSLSymetricEncryptionAlgorithm getSymKeyAlg() const |
65 | 0 | { |
66 | 0 | return m_SymKeyAlg; |
67 | 0 | } |
68 | | |
69 | | /// @return MAC algorithm used in this cipher-suite |
70 | | SSLHashingAlgorithm getMACAlg() const |
71 | 0 | { |
72 | 0 | return m_MACAlg; |
73 | 0 | } |
74 | | |
75 | | /// A static method that returns a cipher-suite instance by ID |
76 | | /// @param[in] id Cipher-suite ID |
77 | | /// @return A cipher-suite instance matching this ID or nullptr if ID not found |
78 | | static SSLCipherSuite* getCipherSuiteByID(uint16_t id); |
79 | | |
80 | | /// A static method that returns a cipher-suite instance by name |
81 | | /// @param[in] name Cipher-suite name (e.g "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA") |
82 | | /// @return A cipher-suite instance matching this name or nullptr if name not found |
83 | | static SSLCipherSuite* getCipherSuiteByName(std::string name); |
84 | | |
85 | | private: |
86 | | uint16_t m_Id; |
87 | | SSLKeyExchangeAlgorithm m_KeyExAlg; |
88 | | SSLAuthenticationAlgorithm m_AuthAlg; |
89 | | SSLSymetricEncryptionAlgorithm m_SymKeyAlg; |
90 | | SSLHashingAlgorithm m_MACAlg; |
91 | | std::string m_Name; |
92 | | }; |
93 | | |
94 | | /// @class SSLExtension |
95 | | /// Represents a SSL/TLS extension. This is a base class that can represent any type of extension. Inherited classes |
96 | | /// may contain parsing logic for specific extensions. This class provides capabilities such as getting the |
97 | | /// extension type, length and viewing the extension data as raw (byte array) |
98 | | class SSLExtension |
99 | | { |
100 | | public: |
101 | | /// C'tor for this class |
102 | | /// @param[in] data The raw data for the extension |
103 | | /// @deprecated This constructor is deprecated because it uses an unbound memory span. Use the constructor with |
104 | | /// bounded span. |
105 | | PCPP_DEPRECATED("Unbound memory span. Use the constructor with bounded span.") |
106 | | explicit SSLExtension(uint8_t* data); |
107 | | |
108 | | /// @brief Constructs an SSLExtension that interprets the provided data as the raw bytes of the extension. |
109 | | /// |
110 | | /// The memory span defined by data and dataLen can be larger than the actual extension data. |
111 | | /// If so, only the bytes corresponding to the extension header (type and length fields) + [length] bytes of |
112 | | /// extension data will be parsed. The rest of the span will be ignored. |
113 | | /// |
114 | | /// The above behaviour allows variable length extensions to be parsed, as SSL extensions are laid out |
115 | | /// sequentially in memory on a payload. |
116 | | /// |
117 | | /// @param[in] data The raw data for the extension. |
118 | | /// @param[in] dataLen The length of the data in bytes. |
119 | | /// @throws std::invalid_argument if data is nullptr or if dataLen is smaller than the size of the extension |
120 | | /// header (type and length fields). |
121 | | SSLExtension(uint8_t* data, size_t dataLen); |
122 | | |
123 | 298k | virtual ~SSLExtension() = default; |
124 | | |
125 | | /// @return The type of the extension as enum |
126 | | SSLExtensionType getType() const; |
127 | | |
128 | | /// @return The type of the extension as a numeric value |
129 | | uint16_t getTypeAsInt() const; |
130 | | |
131 | | /// @return The length of the extension data in bytes (not including the type and length fields) |
132 | | uint16_t getLength() const; |
133 | | |
134 | | /// @return The total length of the extension, including type and length fields and the extension data field |
135 | | uint16_t getTotalLength() const; |
136 | | |
137 | | /// @return A pointer to the raw data of the extension |
138 | | uint8_t* getData() const; |
139 | | |
140 | | /// @brief A static method that tries to create an instance of a specific extension type. |
141 | | /// |
142 | | /// The factory method handles potential buffer overflows by validating that the data length of the span |
143 | | /// is sufficient to contain the extension header (type and length fields) and the extension data as specified |
144 | | /// in the length field. |
145 | | /// |
146 | | /// @tparam T The type of the extension to create. This type must be a class that inherits from SSLExtension. |
147 | | /// @param data Pointer to the raw data of the extension. |
148 | | /// @param dataLen Max length of the span to be parsed. |
149 | | /// @return The extension instance if the data buffer is valid, nullptr otherwise. |
150 | | template <typename T, typename std::enable_if_t<std::is_base_of<SSLExtension, T>::value, bool> = true> |
151 | | static std::unique_ptr<T> tryCreateExtension(uint8_t* data, size_t dataLen) |
152 | 312k | { |
153 | 312k | if (data == nullptr || dataLen < sizeof(SSLExtensionStruct)) |
154 | 0 | { |
155 | 0 | return nullptr; |
156 | 0 | } |
157 | | |
158 | 312k | auto* extStruct = reinterpret_cast<SSLExtensionStruct*>(data); |
159 | 312k | if (dataLen < sizeof(SSLExtensionStruct) + extStruct->getDataLength()) |
160 | 13.0k | { |
161 | 13.0k | return nullptr; |
162 | 13.0k | } |
163 | | |
164 | 298k | return std::make_unique<T>(data, dataLen); |
165 | 312k | } _ZN4pcpp12SSLExtension18tryCreateExtensionINS_32SSLServerNameIndicationExtensionETnNSt3__19enable_ifIXsr3std10is_base_ofIS0_T_EE5valueEbE4typeELb1EEENS3_10unique_ptrIS5_NS3_14default_deleteIS5_EEEEPhm Line | Count | Source | 152 | 102k | { | 153 | 102k | if (data == nullptr || dataLen < sizeof(SSLExtensionStruct)) | 154 | 0 | { | 155 | 0 | return nullptr; | 156 | 0 | } | 157 | | | 158 | 102k | auto* extStruct = reinterpret_cast<SSLExtensionStruct*>(data); | 159 | 102k | if (dataLen < sizeof(SSLExtensionStruct) + extStruct->getDataLength()) | 160 | 3.51k | { | 161 | 3.51k | return nullptr; | 162 | 3.51k | } | 163 | | | 164 | 98.5k | return std::make_unique<T>(data, dataLen); | 165 | 102k | } |
_ZN4pcpp12SSLExtension18tryCreateExtensionINS_29SSLSupportedVersionsExtensionETnNSt3__19enable_ifIXsr3std10is_base_ofIS0_T_EE5valueEbE4typeELb1EEENS3_10unique_ptrIS5_NS3_14default_deleteIS5_EEEEPhm Line | Count | Source | 152 | 6.51k | { | 153 | 6.51k | if (data == nullptr || dataLen < sizeof(SSLExtensionStruct)) | 154 | 0 | { | 155 | 0 | return nullptr; | 156 | 0 | } | 157 | | | 158 | 6.51k | auto* extStruct = reinterpret_cast<SSLExtensionStruct*>(data); | 159 | 6.51k | if (dataLen < sizeof(SSLExtensionStruct) + extStruct->getDataLength()) | 160 | 987 | { | 161 | 987 | return nullptr; | 162 | 987 | } | 163 | | | 164 | 5.53k | return std::make_unique<T>(data, dataLen); | 165 | 6.51k | } |
_ZN4pcpp12SSLExtension18tryCreateExtensionINS_27TLSSupportedGroupsExtensionETnNSt3__19enable_ifIXsr3std10is_base_ofIS0_T_EE5valueEbE4typeELb1EEENS3_10unique_ptrIS5_NS3_14default_deleteIS5_EEEEPhm Line | Count | Source | 152 | 15.8k | { | 153 | 15.8k | if (data == nullptr || dataLen < sizeof(SSLExtensionStruct)) | 154 | 0 | { | 155 | 0 | return nullptr; | 156 | 0 | } | 157 | | | 158 | 15.8k | auto* extStruct = reinterpret_cast<SSLExtensionStruct*>(data); | 159 | 15.8k | if (dataLen < sizeof(SSLExtensionStruct) + extStruct->getDataLength()) | 160 | 202 | { | 161 | 202 | return nullptr; | 162 | 202 | } | 163 | | | 164 | 15.6k | return std::make_unique<T>(data, dataLen); | 165 | 15.8k | } |
_ZN4pcpp12SSLExtension18tryCreateExtensionINS_25TLSECPointFormatExtensionETnNSt3__19enable_ifIXsr3std10is_base_ofIS0_T_EE5valueEbE4typeELb1EEENS3_10unique_ptrIS5_NS3_14default_deleteIS5_EEEEPhm Line | Count | Source | 152 | 17.3k | { | 153 | 17.3k | if (data == nullptr || dataLen < sizeof(SSLExtensionStruct)) | 154 | 0 | { | 155 | 0 | return nullptr; | 156 | 0 | } | 157 | | | 158 | 17.3k | auto* extStruct = reinterpret_cast<SSLExtensionStruct*>(data); | 159 | 17.3k | if (dataLen < sizeof(SSLExtensionStruct) + extStruct->getDataLength()) | 160 | 10 | { | 161 | 10 | return nullptr; | 162 | 10 | } | 163 | | | 164 | 17.3k | return std::make_unique<T>(data, dataLen); | 165 | 17.3k | } |
_ZN4pcpp12SSLExtension18tryCreateExtensionIS0_TnNSt3__19enable_ifIXsr3std10is_base_ofIS0_T_EE5valueEbE4typeELb1EEENS2_10unique_ptrIS4_NS2_14default_deleteIS4_EEEEPhm Line | Count | Source | 152 | 170k | { | 153 | 170k | if (data == nullptr || dataLen < sizeof(SSLExtensionStruct)) | 154 | 0 | { | 155 | 0 | return nullptr; | 156 | 0 | } | 157 | | | 158 | 170k | auto* extStruct = reinterpret_cast<SSLExtensionStruct*>(data); | 159 | 170k | if (dataLen < sizeof(SSLExtensionStruct) + extStruct->getDataLength()) | 160 | 8.37k | { | 161 | 8.37k | return nullptr; | 162 | 8.37k | } | 163 | | | 164 | 161k | return std::make_unique<T>(data, dataLen); | 165 | 170k | } |
|
166 | | |
167 | | protected: |
168 | | /// @struct SSLExtensionStruct |
169 | | /// Represents the common fields of the extension |
170 | | struct SSLExtensionStruct |
171 | | { |
172 | | /// Extension type |
173 | | uint16_t extensionType; |
174 | | /// Extension length |
175 | | uint16_t extensionDataLength; |
176 | | /// Extension data as raw (byte array) |
177 | | uint8_t extensionData[]; |
178 | | |
179 | | /// @brief Gets the extension length in host byte order |
180 | | uint16_t getDataLength() const; |
181 | | }; |
182 | | |
183 | | uint8_t* m_RawData; |
184 | | size_t m_RawDataLen; |
185 | | |
186 | | SSLExtensionStruct* getExtensionStruct() const |
187 | 724k | { |
188 | 724k | return reinterpret_cast<SSLExtensionStruct*>(m_RawData); |
189 | 724k | } |
190 | | }; |
191 | | |
192 | | /// @class SSLServerNameIndicationExtension |
193 | | /// Represents SSL/TLS Server Name Indication extension. Inherits from SSLExtension and add parsing of the hostname |
194 | | /// written in the extension data |
195 | | class SSLServerNameIndicationExtension : public SSLExtension |
196 | | { |
197 | | public: |
198 | | using SSLExtension::SSLExtension; |
199 | | |
200 | | /// @return The hostname written in the extension data |
201 | | std::string getHostName() const; |
202 | | }; |
203 | | |
204 | | /// @class SSLSupportedVersionsExtension |
205 | | /// Represents TLS Supported Versions extension. Inherits from SSLExtension and adds parsing of the list |
206 | | /// of supported versions mentioned in the extension data |
207 | | class SSLSupportedVersionsExtension : public SSLExtension |
208 | | { |
209 | | public: |
210 | | using SSLExtension::SSLExtension; |
211 | | |
212 | | /// @return The list of supported versions mentioned in the extension data |
213 | | std::vector<SSLVersion> getSupportedVersions() const; |
214 | | }; |
215 | | |
216 | | /// @class TLSSupportedGroupsExtension |
217 | | /// Represents TLS Supported Groups extension. Inherits from SSLExtension and adds parsing of the |
218 | | /// supported groups (Elliptic Curves) mentioned in the extension data |
219 | | class TLSSupportedGroupsExtension : public SSLExtension |
220 | | { |
221 | | public: |
222 | | using SSLExtension::SSLExtension; |
223 | | |
224 | | /// @return A vector of the supported groups (also known as "Elliptic Curves") |
225 | | std::vector<uint16_t> getSupportedGroups() const; |
226 | | }; |
227 | | |
228 | | /// @class TLSECPointFormatExtension |
229 | | /// Represents TLS EC (Elliptic Curves) Point Format extension. Inherits from SSLExtension and adds parsing of the |
230 | | /// EC point formats mentioned in the extension data |
231 | | class TLSECPointFormatExtension : public SSLExtension |
232 | | { |
233 | | public: |
234 | | using SSLExtension::SSLExtension; |
235 | | |
236 | | /// @return A vector of the elliptic curves point formats |
237 | | std::vector<uint8_t> getECPointFormatList() const; |
238 | | }; |
239 | | |
240 | | /// @class SSLx509Certificate |
241 | | /// Represents a x509v3 certificate. the SSLCertificateMessage class returns an instance of this class as the |
242 | | /// certificate. Currently this class doesn't do much as it doesn't parse the certificate. It only acts as container |
243 | | /// to the raw data and returns general info as data as raw, length, etc. In the future I may add full parsing of |
244 | | /// the certificate |
245 | | class SSLx509Certificate |
246 | | { |
247 | | public: |
248 | | /// C'tor for this class |
249 | | /// @param[in] data The raw data of the certificate |
250 | | /// @param[in] dataLen The length in bytes of the raw data |
251 | | /// @param[in] allDataExists Certificate messages usually spread on more than 1 packet. So a certificate is |
252 | | /// likely to split between 2 packets or more. This field indicates whether the raw data contains all |
253 | | /// certificate data of just a part of it |
254 | | SSLx509Certificate(uint8_t* data, size_t dataLen, bool allDataExists) |
255 | 25.9k | : m_Data(data), m_DataLen(dataLen), m_AllDataExists(allDataExists) |
256 | 25.9k | {} |
257 | | |
258 | | /// @return A pointer to the raw data |
259 | | uint8_t* getData() const |
260 | 0 | { |
261 | 0 | return m_Data; |
262 | 0 | } |
263 | | |
264 | | /// @return Raw data length |
265 | | size_t getDataLength() const |
266 | 0 | { |
267 | 0 | return m_DataLen; |
268 | 0 | } |
269 | | |
270 | | /// @return The root ASN.1 record of the certificate data. All the certificate data will be under this |
271 | | /// record. If the certificate data isn't complete, this method will return nullptr. If the Root ASN.1 record |
272 | | /// is malformed, an exception is thrown |
273 | | Asn1SequenceRecord* getRootAsn1Record(); |
274 | | |
275 | | /// Parse the certificate data as X509 certificate. If the certificate data isn't complete, this method will |
276 | | /// return nullptr |
277 | | /// @return A unique pointer to the parsed X509 certificate |
278 | | std::unique_ptr<X509Certificate> getX509Certificate(); |
279 | | |
280 | | /// Certificate messages usually spread on more than 1 packet. So a certificate is likely to split between 2 |
281 | | /// packets or more. This method provides an indication whether all certificate data exists or only part of it |
282 | | /// @return True if this data contains all certificate data, false otherwise |
283 | | bool allDataExists() const |
284 | 0 | { |
285 | 0 | return m_AllDataExists; |
286 | 0 | } |
287 | | |
288 | | private: |
289 | | std::unique_ptr<Asn1Record> m_Asn1Record; |
290 | | uint8_t* m_Data; |
291 | | size_t m_DataLen; |
292 | | bool m_AllDataExists; |
293 | | }; |
294 | | |
295 | | class SSLHandshakeLayer; |
296 | | |
297 | | /// @class SSLHandshakeMessage |
298 | | /// A base class for SSL/TLS handshake messages. This is an abstract class and cannot be instantiated. SSL/TLS |
299 | | /// handshake messages are contained in SSLHandshakeLayer, meaning a SSLHandshakeLayer instance can contain one or |
300 | | /// more SSLHandshakeMessage instances. For example: one SSLHandshakeLayer may contain a server-hello, certificate, |
301 | | /// server-key-exchange, and server-hello-done messages (although it's not such a common case, most handshake layers |
302 | | /// contain 1 handshake message only) |
303 | | class SSLHandshakeMessage |
304 | | { |
305 | | public: |
306 | 179k | virtual ~SSLHandshakeMessage() = default; |
307 | | |
308 | | /// A factory method for creating instances of handshake messages from raw data |
309 | | /// @param[in] data The raw data containing 1 handshake message |
310 | | /// @param[in] dataLen Raw data length in bytes |
311 | | /// @param[in] container A pointer to the SSLHandshakeLayer instance which will contain the created message. |
312 | | /// This parameter is required because the handshake message includes a pointer to its container |
313 | | static SSLHandshakeMessage* createHandshakeMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); |
314 | | |
315 | | /// @return The handshake message type |
316 | | virtual SSLHandshakeType getHandshakeType() const; |
317 | | |
318 | | /// @return The handshake message length in bytes. Notice that sometimes the handshake message is divided |
319 | | /// between several packets, in this case this method will return the length of part of the message in the |
320 | | /// current packet |
321 | | virtual size_t getMessageLength() const; |
322 | | |
323 | | /// @return True if current packet contains the entire message or false otherwise. This method is important |
324 | | /// because sometimes handshake messages are divided in consequent packets (happens a lot in certificate |
325 | | /// messages which usually contain several KB of data which is larger than standard packet size, so the message |
326 | | /// is divided between several packets) |
327 | | virtual bool isMessageComplete() const; |
328 | | |
329 | | /// @return A pointer to the SSLHandshakeLayer instance containing this message |
330 | | SSLHandshakeLayer* getContainingLayer() const |
331 | 0 | { |
332 | 0 | return m_Container; |
333 | 0 | } |
334 | | |
335 | | /// @return A string representation of the message type (e.g "Client Hello message") |
336 | | virtual std::string toString() const = 0; |
337 | | |
338 | | protected: |
339 | | SSLHandshakeMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); |
340 | | |
341 | | uint8_t* m_Data; |
342 | | size_t m_DataLen; |
343 | | SSLHandshakeLayer* m_Container; |
344 | | }; |
345 | | |
346 | | /// @class SSLClientHelloMessage |
347 | | /// Represents a client-hello message (type 1). Inherits from SSLHandshakeMessage and adds parsing of all fields |
348 | | /// of this message including the message extensions, cipher-suite list, etc. |
349 | | class SSLClientHelloMessage : public SSLHandshakeMessage |
350 | | { |
351 | | public: |
352 | | /// @struct ClientHelloTLSFingerprint |
353 | | /// A struct that contains all the elements needed for creating a Client Hello TLS fingerprinting: |
354 | | /// TLS version, a list of Cipher Suite IDs, a list of Extensions IDs, a list of support groups and a list of |
355 | | /// EC point formats. |
356 | | /// You can read more about this in SSLClientHelloMessage#generateTLSFingerprint(). |
357 | | /// This struct contains methods to extract the TLS fingerprint itself: toString() and toMD5() |
358 | | struct ClientHelloTLSFingerprint |
359 | | { |
360 | | /// TLS version |
361 | | uint16_t tlsVersion; |
362 | | /// A list of Cipher Suite IDs |
363 | | std::vector<uint16_t> cipherSuites; |
364 | | /// A list of extension IDs |
365 | | std::vector<uint16_t> extensions; |
366 | | /// A list of Suppotred Groups taken from the "supported groups" TLS extension (if exist in the message) |
367 | | std::vector<uint16_t> supportedGroups; |
368 | | /// A list of EC point formats taken from the "EC point formats" TLS extension (if exist in the message) |
369 | | std::vector<uint8_t> ecPointFormats; |
370 | | |
371 | | /// @return A string representing the TLS fingerprint, for example: |
372 | | /// <b>771,4866-4867-4865-255,0-11-10-35-22-23-13-43-45-51,29-23-30-25-24,0-1-2</b> |
373 | | /// |
374 | | /// This string has the following format: |
375 | | /// <b>TLSVersion,CipherSuiteIDs,ExtensionIDs,SupportedGroups,ECPointFormats</b> |
376 | | /// |
377 | | /// The extension IDs, supported groups and EC point formats are each separated by a "-". |
378 | | /// If the message doesn't include the "supported groups" or "EC point formats" extensions, they will be |
379 | | /// replaced by an empty string for example: <b>771,4866-4867-4865-255,0-11-10-35-22-23-13-43-45-51,,</b> |
380 | | std::string toString(); |
381 | | |
382 | | /// @return An MD5 hash of the string generated by toString() |
383 | | std::string toMD5(); |
384 | | |
385 | | /// @return A pair of the string and MD5 hash (string is first, MD5 is second). |
386 | | /// If you want both this method is more efficient than calling toString() and toMD5() separately |
387 | | std::pair<std::string, std::string> toStringAndMD5(); |
388 | | }; |
389 | | |
390 | | /// C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and shouldn't |
391 | | /// be used by a user |
392 | | /// @param[in] data The message as raw data |
393 | | /// @param[in] dataLen Message raw data length in bytes |
394 | | /// @param[in] container The SSL handshake layer which shall contain this message |
395 | | SSLClientHelloMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); |
396 | | |
397 | 32.8k | ~SSLClientHelloMessage() override = default; |
398 | | |
399 | | /// @return A struct containing common fields for client-hello and server-hello messages. Notice this points |
400 | | /// directly to the data, so every change will change the actual packet data |
401 | | ssl_tls_client_server_hello* getClientHelloHeader() const |
402 | 12.0k | { |
403 | 12.0k | return reinterpret_cast<ssl_tls_client_server_hello*>(m_Data); |
404 | 12.0k | } |
405 | | |
406 | | /// @return Handshake SSL/TLS version (notice it may be different than SSLLayer#getRecordVersion(). Each |
407 | | /// client-hello or server-hello message has both record version and handshake version and they may differ from |
408 | | /// one another) |
409 | | SSLVersion getHandshakeVersion() const; |
410 | | |
411 | | /// @return Session ID length in bytes. If server-hello message doesn't include session ID 0 will be returned |
412 | | uint8_t getSessionIDLength() const; |
413 | | |
414 | | /// @return Session ID as byte array. If server-hello message doesn't include session ID nullptr will be |
415 | | /// returned |
416 | | uint8_t* getSessionID() const; |
417 | | |
418 | | /// @return The number of cipher-suites included in this message |
419 | | int getCipherSuiteCount() const; |
420 | | |
421 | | /// Get a pointer to a cipher-suite by index. The cipher-suites are numbered according to their order of |
422 | | /// appearance in the message. If index is out of bounds (less than 0 or larger than total amount of cipher |
423 | | /// suites) nullptr will be returned. nullptr will also be returned if the cipher-suite ID is unknown. If you |
424 | | /// still want to get the cipher-suite ID you can use getCipherSuiteID() |
425 | | /// @param[in] index The index of the cipher-suite to return |
426 | | /// @return The pointer to the cipher-suite object or nullptr if index is out of bounds |
427 | | SSLCipherSuite* getCipherSuite(int index) const; |
428 | | |
429 | | /// Get the cipher-suite ID by index. This method just parses the ID from the client-hello message and returns |
430 | | /// it. To get more information on the cipher-suite you can use the getCipherSuite() method |
431 | | /// @param[in] index The index of the cipher-suite to return |
432 | | /// @param[out] isValid Set to "true" if parsing succeeded and the return value is valid or "false" if: |
433 | | /// (1) the index is out-of-bounds (less than 0 or larger than total amount of cipher suites) or (2) the parsing |
434 | | /// failed. If the value is "false" the return value can be ignored |
435 | | /// @return The cipher-suite ID if "isValid" is set to "true". If "isValid" is set to "false" the return value |
436 | | /// can be ignored |
437 | | uint16_t getCipherSuiteID(int index, bool& isValid) const; |
438 | | |
439 | | /// @return The value of the compression method byte |
440 | | uint8_t getCompressionMethodsValue() const; |
441 | | |
442 | | /// @return The number of extensions in this message |
443 | | int getExtensionCount() const; |
444 | | |
445 | | /// @return The size (in bytes) of all extensions data in this message. Extracted from the "extensions length" |
446 | | /// field |
447 | | uint16_t getExtensionsLength() const; |
448 | | |
449 | | /// Get a pointer to an extension by index. The extensions are numbered according to their order of appearance |
450 | | /// in the message. If index is out of bounds (less than 0 or larger than total amount of extensions) nullptr |
451 | | /// will be returned |
452 | | /// @param[in] index The index of the extension to return |
453 | | /// @return The pointer to the extension or nullptr if index is out of bounds |
454 | | SSLExtension* getExtension(int index) const; |
455 | | |
456 | | /// Get a pointer to an extension by numeric type field. Every extension has a 2-byte numeric value representing |
457 | | /// its type (for example: renegotiation info extension type is 0x1ff). This method gets the type and returns a |
458 | | /// pointer to the extension object |
459 | | /// @param[in] type The 2-byte numeric type of the extension |
460 | | /// @return A pointer to the extension object of nullptr if this type doesn't exist in this message |
461 | | SSLExtension* getExtensionOfType(uint16_t type) const; |
462 | | |
463 | | /// Get a pointer to an extension by its enum type |
464 | | /// @param[in] type The type of extension to return |
465 | | /// @return A pointer to the extension object or nullptr if this type doesn't exist in this message |
466 | | SSLExtension* getExtensionOfType(SSLExtensionType type) const; |
467 | | |
468 | | /// Get a pointer to an extension by its class type. This is a templated method that is used with the type of |
469 | | /// the requested extension and returns the first extension instance of this type |
470 | | /// @return A pointer to the extension object or nullptr if this extension type doesn't exist in this message |
471 | | template <class TExtension> TExtension* getExtensionOfType() const; |
472 | | |
473 | | /// TLS fingerprinting is a way to identify client applications using the details in the TLS Client Hello |
474 | | /// packet. It was initially introduced by Lee Brotherston in his 2015 research: |
475 | | /// <https://blog.squarelemon.com/tls-fingerprinting/> This implementation of TLS fingerprint is a C++ version |
476 | | /// of Salesforce's JA3 open source project (originally written in Python and Zeek): |
477 | | /// <https://engineering.salesforce.com/tls-fingerprinting-with-ja3-and-ja3s-247362855967> |
478 | | /// @return A SSLClientHelloMessage#ClientHelloTLSFingerprint struct that contains all the elements needed for |
479 | | /// creating a TLS fingerprint out of this Client Hello message. This struct has also methods to extract the TLS |
480 | | /// fingerprint itself in a string or MD5 formats |
481 | | ClientHelloTLSFingerprint generateTLSFingerprint() const; |
482 | | |
483 | | // implement abstract methods |
484 | | |
485 | | std::string toString() const override; |
486 | | |
487 | | private: |
488 | | PointerVector<SSLExtension> m_ExtensionList; |
489 | | }; |
490 | | |
491 | | /// @class SSLServerHelloMessage |
492 | | /// Represents SSL/TLS server-hello message (type 2). Inherits from SSLHandshakeMessage and adds parsing of all |
493 | | /// fields of this message including the message extensions, cipher-suite, etc. |
494 | | class SSLServerHelloMessage : public SSLHandshakeMessage |
495 | | { |
496 | | public: |
497 | | /// @struct ServerHelloTLSFingerprint |
498 | | /// A struct that contains all the elements needed for creating a Server Hello TLS fingerprinting: |
499 | | /// TLS version, Cipher Suite ID, and a list of Extensions IDs. |
500 | | /// You can read more about this in SSLServerHelloMessage#generateTLSFingerprint(). |
501 | | /// This struct contains methods to extract the TLS fingerprint itself: toString() and toMD5() |
502 | | struct ServerHelloTLSFingerprint |
503 | | { |
504 | | /// TLS version |
505 | | uint16_t tlsVersion; |
506 | | /// Cipher Suite ID |
507 | | uint16_t cipherSuite; |
508 | | /// A list of extension IDs |
509 | | std::vector<uint16_t> extensions; |
510 | | |
511 | | /// @return A string representing the TLS fingerprint, for example: <b>771,49195,65281-16-11</b> |
512 | | /// |
513 | | /// This string has the following format: <b>TLSVersion,Cipher,Extensions</b> |
514 | | /// |
515 | | /// The extension ID are separated with a "-" |
516 | | std::string toString(); |
517 | | |
518 | | /// @return An MD5 hash of the string generated by toString() |
519 | | std::string toMD5(); |
520 | | |
521 | | /// @return A pair of the string and MD5 hash (string is first, MD5 is second). |
522 | | /// If you want both this method is more efficient than calling toString() and toMD5() separately |
523 | | std::pair<std::string, std::string> toStringAndMD5(); |
524 | | }; |
525 | | |
526 | | /// C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and shouldn't |
527 | | /// be used by a user |
528 | | /// @param[in] data The message as raw data |
529 | | /// @param[in] dataLen Message raw data length in bytes |
530 | | /// @param[in] container The SSL handshake layer which shall contain this message |
531 | | SSLServerHelloMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); |
532 | | |
533 | 30.3k | ~SSLServerHelloMessage() override = default; |
534 | | |
535 | | /// @return A struct containing common fields for client-hello and server-hello messages. Notice this points |
536 | | /// directly to the data, so every change will change the actual packet data |
537 | | ssl_tls_client_server_hello* getServerHelloHeader() const |
538 | 8.91k | { |
539 | 8.91k | return reinterpret_cast<ssl_tls_client_server_hello*>(m_Data); |
540 | 8.91k | } |
541 | | |
542 | | /// @return Handshake SSL/TLS version (notice it may be different than SSLLayer#getRecordVersion(). Each |
543 | | /// client-hello or server-hello message has both record version and handshake version and they may differ from |
544 | | /// one another). |
545 | | /// |
546 | | /// <b>NOTE:</b> for TLS 1.3 the handshake version written in ssl_tls_client_server_hello::handshakeVersion is |
547 | | /// still TLS 1.2, so a special check is made here see if a SupportedVersions extension exists and if so extract |
548 | | /// the version from it. This is the most straight-forward way to detect TLS 1.3. |
549 | | SSLVersion getHandshakeVersion() const; |
550 | | |
551 | | /// @return Session ID length in bytes. If server-hello message doesn't include session ID 0 will be returned |
552 | | uint8_t getSessionIDLength() const; |
553 | | |
554 | | /// @return Session ID as byte array. If server-hello message doesn't include session ID nullptr will be |
555 | | /// returned |
556 | | uint8_t* getSessionID() const; |
557 | | |
558 | | /// @return A pointer to the cipher suite encapsulated in this message (server-hello message contains one |
559 | | /// cipher-suite, the one that will be used to for encryption between client and server). May return nullptr |
560 | | /// if the parsing of the message failed or the cipher-suite ID is unknown. If you still want to get the |
561 | | /// cipher-suite ID you can use the getCipherSuiteID() method |
562 | | SSLCipherSuite* getCipherSuite() const; |
563 | | |
564 | | /// Get the cipher-suite ID. This method just parses the ID from the server-hello message and returns it. |
565 | | /// To get more information on the cipher-suite you can use the getCipherSuite() method |
566 | | /// @param[out] isValid Set to "true" if parsing succeeded and the return value is valid or "false" otherwise. |
567 | | /// If the value is "false" the return value can be ignored |
568 | | /// @return The cipher-suite ID if "isValid" is set to "true". If "isValid" is set to "false" the return value |
569 | | /// can be ignored |
570 | | uint16_t getCipherSuiteID(bool& isValid) const; |
571 | | |
572 | | /// @return The value of the compression method byte |
573 | | uint8_t getCompressionMethodsValue() const; |
574 | | |
575 | | /// @return The number of extensions in this message |
576 | | int getExtensionCount() const; |
577 | | |
578 | | /// @return The size (in bytes) of all extensions data in this message. Extracted from the "extensions length" |
579 | | /// field |
580 | | uint16_t getExtensionsLength() const; |
581 | | |
582 | | /// Get a pointer to an extension by index. The extensions are numbered according to their order of appearance |
583 | | /// in the message. If index is out of bounds (less than 0 or larger than total amount of extensions) nullptr |
584 | | /// will be returned |
585 | | /// @param[in] index The index of the extension to return |
586 | | /// @return The pointer to the extension or nullptr if index is out of bounds |
587 | | SSLExtension* getExtension(int index) const; |
588 | | |
589 | | /// Get a pointer to an extension by numeric type field. Every extension has a 2-byte numeric value representing |
590 | | /// its type (for example: renegotiation info extension type is 0x1ff). This method gets the type and returns a |
591 | | /// pointer to the extension object |
592 | | /// @param[in] type The 2-byte numeric type of the extension |
593 | | /// @return A pointer to the extension object of nullptr if this type doesn't exist in this message |
594 | | SSLExtension* getExtensionOfType(uint16_t type) const; |
595 | | |
596 | | /// Get a pointer to an extension by its enum type |
597 | | /// @param[in] type The type of extension to return |
598 | | /// @return A pointer to the extension object or nullptr if this type doesn't exist in this message |
599 | | SSLExtension* getExtensionOfType(SSLExtensionType type) const; |
600 | | |
601 | | /// Get a pointer to an extension by its class type. This is a templated method that is used with the type of |
602 | | /// the requested extension and returns the first extension instance of this type |
603 | | /// @return A pointer to the extension object or nullptr if this extension type doesn't exist in this message |
604 | | template <class TExtension> TExtension* getExtensionOfType() const; |
605 | | |
606 | | /// ServerHello TLS fingerprinting is a way to fingerprint TLS Server Hello messages. In conjunction with |
607 | | /// ClientHello TLS fingerprinting it can assist in identifying specific client-server communication (for |
608 | | /// example: a malware connecting to its backend server). |
609 | | /// ServerHello TLS fingerprinting was introduced in Salesforce's JA3S open source project: |
610 | | /// <https://engineering.salesforce.com/tls-fingerprinting-with-ja3-and-ja3s-247362855967> |
611 | | /// This implementation is a C++ version of Salesforce's JAS3 (originally written in Python and Zeek) |
612 | | /// @return A SSLServerHelloMessage#ServerHelloTLSFingerprint struct that contains all the elements needed for |
613 | | /// creating a TLS fingerprint out of this Server Hello message. This struct has also methods to extract the TLS |
614 | | /// fingerprint itself in a string or MD5 formats |
615 | | ServerHelloTLSFingerprint generateTLSFingerprint() const; |
616 | | |
617 | | // implement abstract methods |
618 | | |
619 | | std::string toString() const override; |
620 | | |
621 | | private: |
622 | | PointerVector<SSLExtension> m_ExtensionList; |
623 | | }; |
624 | | |
625 | | /// @class SSLCertificateMessage |
626 | | /// Represents SSL/TLS certificate message (type 11). Inherits from SSLHandshakeMessage and adds parsing |
627 | | /// functionality such as extracting the certificates data. Notice that in most cases this message is spread over |
628 | | /// more than 1 packet as its size is too big for a single packet. So SSLCertificateMessage instance will be created |
629 | | /// just for the first part of the message - the one encapsulated in the first packet. Other parts (encapsulated in |
630 | | /// the following packets) won't be recognized as SSLCertificateMessage messages |
631 | | class SSLCertificateMessage : public SSLHandshakeMessage |
632 | | { |
633 | | public: |
634 | | /// C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be |
635 | | /// used by a user |
636 | | /// @param[in] data The message as raw data |
637 | | /// @param[in] dataLen Message raw data length in bytes |
638 | | /// @param[in] container The SSL handshake layer which shall contain this message |
639 | | SSLCertificateMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); |
640 | | |
641 | 10.3k | ~SSLCertificateMessage() override = default; |
642 | | |
643 | | /// @return The number of certificates encapsulated in this message (as written in the 'length' field of the |
644 | | /// message). Notice that because the message may spread over several packets, not all certificates will |
645 | | /// necessarily be in this packet. So, for example, there may be a case where this method return 3 (message |
646 | | /// contains 3 certificates) but this message actually contains only 1 certificate as the other 2 are spread |
647 | | /// over the other packets |
648 | | int getNumOfCertificates() const; |
649 | | |
650 | | /// Get a certificate by index |
651 | | /// @param[in] index The index of the certificate to retrieve |
652 | | /// @return A pointer to the certificate object. Notice that if index < 0 or index > num of certificates |
653 | | /// encapsulated in current packet a nullptr value will be returned |
654 | | SSLx509Certificate* getCertificate(int index) const; |
655 | | |
656 | | // implement abstract methods |
657 | | |
658 | | std::string toString() const override; |
659 | | |
660 | | private: |
661 | | PointerVector<SSLx509Certificate> m_CertificateList; |
662 | | }; |
663 | | |
664 | | /// @class SSLHelloRequestMessage |
665 | | /// Represents SSL/TLS hello-request message (type 0). This message has no additional payload except for the common |
666 | | /// payload described in SSLHandshakeMessage |
667 | | class SSLHelloRequestMessage : public SSLHandshakeMessage |
668 | | { |
669 | | public: |
670 | | /// C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be |
671 | | /// used by a user |
672 | | /// @param[in] data The message as raw data |
673 | | /// @param[in] dataLen Message raw data length in bytes |
674 | | /// @param[in] container The SSL handshake layer which shall contain this message |
675 | | SSLHelloRequestMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) |
676 | 27.0k | : SSLHandshakeMessage(data, dataLen, container) |
677 | 27.0k | {} |
678 | | |
679 | | ~SSLHelloRequestMessage() override = default; |
680 | | |
681 | | // implement abstract methods |
682 | | |
683 | | std::string toString() const override; |
684 | | }; |
685 | | |
686 | | /// @class SSLServerKeyExchangeMessage |
687 | | /// Represents SSL/TLS server-key-exchange message (type 12). Inherits from SSLHandshakeMessage and adds parsing |
688 | | /// functionality such as getting the server key exchange params as raw data (parsing of this may be added in the |
689 | | /// future) |
690 | | class SSLServerKeyExchangeMessage : public SSLHandshakeMessage |
691 | | { |
692 | | public: |
693 | | /// C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be |
694 | | /// used by a user |
695 | | /// @param[in] data The message as raw data |
696 | | /// @param[in] dataLen Message raw data length in bytes |
697 | | /// @param[in] container The SSL handshake layer which shall contain this message |
698 | | SSLServerKeyExchangeMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) |
699 | 5.68k | : SSLHandshakeMessage(data, dataLen, container) |
700 | 5.68k | {} |
701 | | |
702 | | ~SSLServerKeyExchangeMessage() override = default; |
703 | | |
704 | | /// @return A pointer to the raw data of the server key exchange params. Currently this data can only returned |
705 | | /// as raw, parsing may be added in the future. Notice that if the message is spread over more than 1 packet in |
706 | | /// a way params doesn't exist in the first packet, nullptr will be returned |
707 | | uint8_t* getServerKeyExchangeParams() const; |
708 | | |
709 | | /// @return The size of the params field. Notice that if the message is spread over more than 1 packet in a way |
710 | | /// the ssl_tls_handshake_layer cannot be parsed from the packet, 0 will be returned. Also, if only part of the |
711 | | /// params exist in current packet (and the rest are on consequent packets), the size that will be returned is |
712 | | /// the size of the part that exists in the current packet (and not total size of params) |
713 | | size_t getServerKeyExchangeParamsLength() const; |
714 | | |
715 | | // implement abstract methods |
716 | | |
717 | | std::string toString() const override; |
718 | | }; |
719 | | |
720 | | /// @class SSLClientKeyExchangeMessage |
721 | | /// Represents SSL/TLS client-key-exchange message (type 16). Inherits from SSLHandshakeMessage and adds parsing |
722 | | /// functionality such as getting the server key exchange params as raw data (parsing of this may be added in the |
723 | | /// future) |
724 | | class SSLClientKeyExchangeMessage : public SSLHandshakeMessage |
725 | | { |
726 | | public: |
727 | | /// C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be |
728 | | /// used by a user |
729 | | /// @param[in] data The message as raw data |
730 | | /// @param[in] dataLen Message raw data length in bytes |
731 | | /// @param[in] container The SSL handshake layer which shall contain this message |
732 | | SSLClientKeyExchangeMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) |
733 | 3.04k | : SSLHandshakeMessage(data, dataLen, container) |
734 | 3.04k | {} |
735 | | |
736 | | ~SSLClientKeyExchangeMessage() override = default; |
737 | | |
738 | | /// @return A pointer to the raw data of the server key exchange params. Currently this data can only be |
739 | | /// returned as raw, parsing may be added in the future. Notice that if the message is spread over more than 1 |
740 | | /// packet in a way params doesn't exist in the first packet, nullptr will be returned |
741 | | uint8_t* getClientKeyExchangeParams() const; |
742 | | |
743 | | /// @return The size of the params field. Notice that if the message is spread over more than 1 packet in a way |
744 | | /// the ssl_tls_handshake_layer cannot be parsed from the packet, 0 will be returned. Also, if only part of the |
745 | | /// params exist in current packet (and the rest are on consequent packets), the size that will be returned is |
746 | | /// the size of the part that exists in the current packet (and not the total size of params) |
747 | | size_t getClientKeyExchangeParamsLength() const; |
748 | | |
749 | | // implement abstract methods |
750 | | |
751 | | std::string toString() const override; |
752 | | }; |
753 | | |
754 | | /// @class SSLCertificateRequestMessage |
755 | | /// Represents SSL/TLS certificate-request message (type 13). Inherits from SSLHandshakeMessage and adds parsing |
756 | | /// functionality such as retrieving client certificate types and authority data |
757 | | class SSLCertificateRequestMessage : public SSLHandshakeMessage |
758 | | { |
759 | | public: |
760 | | /// C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be |
761 | | /// used by a user |
762 | | /// @param[in] data The message as raw data |
763 | | /// @param[in] dataLen Message raw data length in bytes |
764 | | /// @param[in] container The SSL handshake layer which shall contain this message |
765 | | SSLCertificateRequestMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); |
766 | | |
767 | 16.6k | ~SSLCertificateRequestMessage() override = default; |
768 | | |
769 | | /// @return A reference to a vector containing all client certificate types exist in this message |
770 | | std::vector<SSLClientCertificateType>& getCertificateTypes(); |
771 | | |
772 | | /// @return A pointer to the certificate authority data as raw data (byte array). Parsing of this data may be |
773 | | /// added in the future. Notice that if this message is spread over several packets in a way none of the |
774 | | /// certificate authority data exists in this packet, nullptr will be returned |
775 | | uint8_t* getCertificateAuthorityData() const; |
776 | | |
777 | | /// @return The length of certificate authority data returned by getCertificateAuthorityData(). Notice that if |
778 | | /// this message is spread over several packets in a way none of certificate authority data exists in the |
779 | | /// current packet, 0 will be returned. Also, if some of the data exists in the consequent packets, the length |
780 | | /// that will be returned is the length of data exists in the current packet only (and not the total length) |
781 | | size_t getCertificateAuthorityLength() const; |
782 | | |
783 | | // implement abstract methods |
784 | | |
785 | | std::string toString() const override; |
786 | | |
787 | | private: |
788 | | std::vector<SSLClientCertificateType> m_ClientCertificateTypes; |
789 | | }; |
790 | | |
791 | | /// @class SSLServerHelloDoneMessage |
792 | | /// Represents SSL/TLS server-hello-done message (type 14). This message has no additional payload except for the |
793 | | /// common payload described in SSLHandshakeMessage |
794 | | class SSLServerHelloDoneMessage : public SSLHandshakeMessage |
795 | | { |
796 | | public: |
797 | | /// C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be |
798 | | /// used by a user |
799 | | /// @param[in] data The message as raw data |
800 | | /// @param[in] dataLen Message raw data length in bytes |
801 | | /// @param[in] container The SSL handshake layer which shall contain this message |
802 | | SSLServerHelloDoneMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) |
803 | 1.69k | : SSLHandshakeMessage(data, dataLen, container) |
804 | 1.69k | {} |
805 | | |
806 | | ~SSLServerHelloDoneMessage() override = default; |
807 | | |
808 | | // implement abstract methods |
809 | | |
810 | | std::string toString() const override; |
811 | | }; |
812 | | |
813 | | /// @class SSLCertificateVerifyMessage |
814 | | /// Represents SSL/TLS certificate-verify message (type 15). Inherits from SSLHandshakeMessage and adds parsing |
815 | | /// functionality such as retrieving signed hash data as raw data (parsing may be added in the future) |
816 | | /// @todo This message type wasn't tested in unit-tests |
817 | | class SSLCertificateVerifyMessage : public SSLHandshakeMessage |
818 | | { |
819 | | public: |
820 | | /// C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be |
821 | | /// used by a user |
822 | | /// @param[in] data The message as raw data |
823 | | /// @param[in] dataLen Message raw data length in bytes |
824 | | /// @param[in] container The SSL handshake layer which shall contain this message |
825 | | SSLCertificateVerifyMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) |
826 | 1.03k | : SSLHandshakeMessage(data, dataLen, container) |
827 | 1.03k | {} |
828 | | |
829 | | ~SSLCertificateVerifyMessage() override = default; |
830 | | |
831 | | /// @return A pointer to the signed hash data as raw data (byte array). Parsing of this data may be added |
832 | | /// in the future. Notice that if this message is spread over several packets in a way none of the signed hash |
833 | | /// data exists in this packet, nullptr will be returned |
834 | | uint8_t* getSignedHash() const; |
835 | | |
836 | | /// @return The length of signed hash data returned by getSignedHash(). Notice that if this message is spread |
837 | | /// over several packets in a way none of this data exists in the current packet, 0 will be returned. Also, if |
838 | | /// some of the data exists in the consequent packets, the length that will be returned will be the length of |
839 | | /// data exists in the current packet only (and not the total length) |
840 | | size_t getSignedHashLength() const; |
841 | | |
842 | | // implement abstract methods |
843 | | |
844 | | std::string toString() const override; |
845 | | }; |
846 | | |
847 | | /// @class SSLFinishedMessage |
848 | | /// Represents SSL/TLS finished message (type 20). Inherits from SSLHandshakeMessage and adds parsing |
849 | | /// functionality such as retrieving signed hash data as raw data (parsing may be added in the future) |
850 | | /// @todo This message type wasn't tested in unit-tests |
851 | | class SSLFinishedMessage : public SSLHandshakeMessage |
852 | | { |
853 | | public: |
854 | | /// C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be |
855 | | /// used by a user |
856 | | /// @param[in] data The message as raw data |
857 | | /// @param[in] dataLen Message raw data length in bytes |
858 | | /// @param[in] container The SSL handshake layer which shall contain this message |
859 | | SSLFinishedMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) |
860 | 1.15k | : SSLHandshakeMessage(data, dataLen, container) |
861 | 1.15k | {} |
862 | | |
863 | | ~SSLFinishedMessage() override = default; |
864 | | |
865 | | /// @return A pointer to the signed hash data as raw data (byte array). Parsing of this data may be added |
866 | | /// in the future. Notice that if this message is spread over several packets in a way none of the signed hash |
867 | | /// data exists in this packet, nullptr will be returned |
868 | | uint8_t* getSignedHash() const; |
869 | | |
870 | | /// @return The length of signed hash data returned by getSignedHash(). Notice that if the message is spread |
871 | | /// over several packets in a way none of this data exists in the current packet, 0 will be returned. Also, if |
872 | | /// some of the data exists in the consequent packets, the length that will be returned will be the length of |
873 | | /// data exists in the current packet only (and not the total length) |
874 | | size_t getSignedHashLength() const; |
875 | | |
876 | | // implement abstract methods |
877 | | |
878 | | std::string toString() const override; |
879 | | }; |
880 | | |
881 | | /// @class SSLNewSessionTicketMessage |
882 | | /// Represents SSL/TLS new-session-ticket message (type 4). Inherits from SSLHandshakeMessage and adds parsing |
883 | | /// functionality such as retrieving session ticket data as raw data (parsing may be added in the future) |
884 | | class SSLNewSessionTicketMessage : public SSLHandshakeMessage |
885 | | { |
886 | | public: |
887 | | /// C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be |
888 | | /// used by a user |
889 | | /// @param[in] data The message as raw data |
890 | | /// @param[in] dataLen Message raw data length in bytes |
891 | | /// @param[in] container The SSL handshake layer which shall contain this message |
892 | | SSLNewSessionTicketMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) |
893 | 2.17k | : SSLHandshakeMessage(data, dataLen, container) |
894 | 2.17k | {} |
895 | | |
896 | | ~SSLNewSessionTicketMessage() override = default; |
897 | | |
898 | | /// @return A pointer to the session ticket data as raw data (byte array). Parsing of this data may be added |
899 | | /// in the future. Notice that if this message is spread over several packets in a way none of the signed hash |
900 | | /// data exists in current packet, nullptr will be returned |
901 | | uint8_t* getSessionTicketData() const; |
902 | | |
903 | | /// @return The length of session ticket data returned by getSessionTicketData(). Notice that if this message is |
904 | | /// spread over several packets in a way none of this data exists in the current packet, 0 will be returned. |
905 | | /// Also, if some of the data exist in the consequent packets, the length that will be returned will be the |
906 | | /// length of the data existing in the current packet only (and not the total length) |
907 | | size_t getSessionTicketDataLength() const; |
908 | | |
909 | | // implement abstract methods |
910 | | |
911 | | std::string toString() const override; |
912 | | }; |
913 | | |
914 | | /// @class SSLUnknownMessage |
915 | | /// Represents an unknown type of message or an encrypted message that PcapPlusPlus can't determine its type. In |
916 | | /// these cases length can't always be determined from the message itself (especially if the message is encrypted), |
917 | | /// so the length of this message will always be the size counted from message start until the end of the layer |
918 | | class SSLUnknownMessage : public SSLHandshakeMessage |
919 | | { |
920 | | public: |
921 | | /// C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be |
922 | | /// used by a user |
923 | | /// @param[in] data The message as raw data |
924 | | /// @param[in] dataLen Message raw data length in bytes |
925 | | /// @param[in] container The SSL handshake layer which shall contain this message |
926 | | SSLUnknownMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) |
927 | 47.3k | : SSLHandshakeMessage(data, dataLen, container) |
928 | 47.3k | {} |
929 | | |
930 | | ~SSLUnknownMessage() override = default; |
931 | | |
932 | | // implement virtual and abstract methods |
933 | | |
934 | | /// @return Always ::SSL_HANDSHAKE_UNKNOWN (overridden from SSLHandshakeMessage) |
935 | | SSLHandshakeType getHandshakeType() const override; |
936 | | |
937 | | /// @return The length of the data from message start until the end of the layer. Since it's an unknown type |
938 | | /// or an encrypted message the length parsed from the message can't be guaranteed to be the correct length. |
939 | | /// That's why the length returned is the size until the end of the layer |
940 | | size_t getMessageLength() const override; |
941 | | |
942 | | std::string toString() const override; |
943 | | }; |
944 | | |
945 | | template <class TExtension> TExtension* SSLClientHelloMessage::getExtensionOfType() const |
946 | 24.0k | { |
947 | 24.0k | size_t vecSize = m_ExtensionList.size(); |
948 | 129k | for (size_t i = 0; i < vecSize; i++) |
949 | 115k | { |
950 | 115k | SSLExtension* curElem = const_cast<SSLExtension*>(m_ExtensionList.at(i)); |
951 | 115k | if (dynamic_cast<TExtension*>(curElem) != nullptr) |
952 | 9.75k | return static_cast<TExtension*>(curElem); |
953 | 115k | } |
954 | | |
955 | 14.2k | return nullptr; |
956 | 24.0k | } pcpp::SSLServerNameIndicationExtension* pcpp::SSLClientHelloMessage::getExtensionOfType<pcpp::SSLServerNameIndicationExtension>() const Line | Count | Source | 946 | 6.00k | { | 947 | 6.00k | size_t vecSize = m_ExtensionList.size(); | 948 | 12.4k | for (size_t i = 0; i < vecSize; i++) | 949 | 9.47k | { | 950 | 9.47k | SSLExtension* curElem = const_cast<SSLExtension*>(m_ExtensionList.at(i)); | 951 | 9.47k | if (dynamic_cast<TExtension*>(curElem) != nullptr) | 952 | 3.05k | return static_cast<TExtension*>(curElem); | 953 | 9.47k | } | 954 | | | 955 | 2.95k | return nullptr; | 956 | 6.00k | } |
pcpp::SSLSupportedVersionsExtension* pcpp::SSLClientHelloMessage::getExtensionOfType<pcpp::SSLSupportedVersionsExtension>() const Line | Count | Source | 946 | 6.00k | { | 947 | 6.00k | size_t vecSize = m_ExtensionList.size(); | 948 | 52.5k | for (size_t i = 0; i < vecSize; i++) | 949 | 47.2k | { | 950 | 47.2k | SSLExtension* curElem = const_cast<SSLExtension*>(m_ExtensionList.at(i)); | 951 | 47.2k | if (dynamic_cast<TExtension*>(curElem) != nullptr) | 952 | 711 | return static_cast<TExtension*>(curElem); | 953 | 47.2k | } | 954 | | | 955 | 5.29k | return nullptr; | 956 | 6.00k | } |
pcpp::TLSSupportedGroupsExtension* pcpp::SSLClientHelloMessage::getExtensionOfType<pcpp::TLSSupportedGroupsExtension>() const Line | Count | Source | 946 | 6.00k | { | 947 | 6.00k | size_t vecSize = m_ExtensionList.size(); | 948 | 32.2k | for (size_t i = 0; i < vecSize; i++) | 949 | 29.1k | { | 950 | 29.1k | SSLExtension* curElem = const_cast<SSLExtension*>(m_ExtensionList.at(i)); | 951 | 29.1k | if (dynamic_cast<TExtension*>(curElem) != nullptr) | 952 | 2.96k | return static_cast<TExtension*>(curElem); | 953 | 29.1k | } | 954 | | | 955 | 3.04k | return nullptr; | 956 | 6.00k | } |
pcpp::TLSECPointFormatExtension* pcpp::SSLClientHelloMessage::getExtensionOfType<pcpp::TLSECPointFormatExtension>() const Line | Count | Source | 946 | 6.00k | { | 947 | 6.00k | size_t vecSize = m_ExtensionList.size(); | 948 | 32.2k | for (size_t i = 0; i < vecSize; i++) | 949 | 29.2k | { | 950 | 29.2k | SSLExtension* curElem = const_cast<SSLExtension*>(m_ExtensionList.at(i)); | 951 | 29.2k | if (dynamic_cast<TExtension*>(curElem) != nullptr) | 952 | 3.02k | return static_cast<TExtension*>(curElem); | 953 | 29.2k | } | 954 | | | 955 | 2.98k | return nullptr; | 956 | 6.00k | } |
|
957 | | |
958 | | template <class TExtension> TExtension* SSLServerHelloMessage::getExtensionOfType() const |
959 | 14.1k | { |
960 | 14.1k | size_t vecSize = m_ExtensionList.size(); |
961 | 26.7k | for (size_t i = 0; i < vecSize; i++) |
962 | 13.7k | { |
963 | 13.7k | SSLExtension* curElem = const_cast<SSLExtension*>(m_ExtensionList.at(i)); |
964 | 13.7k | if (dynamic_cast<TExtension*>(curElem) != nullptr) |
965 | 1.13k | return static_cast<TExtension*>(curElem); |
966 | 13.7k | } |
967 | | |
968 | 13.0k | return nullptr; |
969 | 14.1k | } pcpp::SSLServerNameIndicationExtension* pcpp::SSLServerHelloMessage::getExtensionOfType<pcpp::SSLServerNameIndicationExtension>() const Line | Count | Source | 959 | 4.71k | { | 960 | 4.71k | size_t vecSize = m_ExtensionList.size(); | 961 | 8.22k | for (size_t i = 0; i < vecSize; i++) | 962 | 4.12k | { | 963 | 4.12k | SSLExtension* curElem = const_cast<SSLExtension*>(m_ExtensionList.at(i)); | 964 | 4.12k | if (dynamic_cast<TExtension*>(curElem) != nullptr) | 965 | 616 | return static_cast<TExtension*>(curElem); | 966 | 4.12k | } | 967 | | | 968 | 4.09k | return nullptr; | 969 | 4.71k | } |
pcpp::SSLSupportedVersionsExtension* pcpp::SSLServerHelloMessage::getExtensionOfType<pcpp::SSLSupportedVersionsExtension>() const Line | Count | Source | 959 | 9.42k | { | 960 | 9.42k | size_t vecSize = m_ExtensionList.size(); | 961 | 18.5k | for (size_t i = 0; i < vecSize; i++) | 962 | 9.61k | { | 963 | 9.61k | SSLExtension* curElem = const_cast<SSLExtension*>(m_ExtensionList.at(i)); | 964 | 9.61k | if (dynamic_cast<TExtension*>(curElem) != nullptr) | 965 | 518 | return static_cast<TExtension*>(curElem); | 966 | 9.61k | } | 967 | | | 968 | 8.90k | return nullptr; | 969 | 9.42k | } |
|
970 | | } // namespace pcpp |