Coverage Report

Created: 2024-02-25 06:29

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