Coverage Report

Created: 2023-01-17 06:15

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