Coverage Report

Created: 2026-03-31 07:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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