Coverage Report

Created: 2023-01-17 06:15

/src/PcapPlusPlus/Packet++/header/SSLLayer.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef PACKETPP_SSL_LAYER
2
#define PACKETPP_SSL_LAYER
3
4
#include "PointerVector.h"
5
#include "Layer.h"
6
#include "SSLCommon.h"
7
#include "SSLHandshake.h"
8
9
/**
10
 * @file
11
 * This file as well as SSLCommon.h and SSLHandshake.h provide structures that represent SSL/TLS protocol.
12
 * Main features:
13
 * - All common SSL/TLS version are supported from SSL 3.0 to TLS 1.3
14
 * - All SSL/TLS message types are supported (at least the message types that are not encrypted)
15
 * - More than 300 cipher-suites are supported
16
 * - Only parsing capabilities exist, editing and creation of messages are not supported
17
 * - X509 certificate parsing is not supported
18
 *
19
 * <BR><BR>
20
 *
21
 * __SSL Records:__   <BR>
22
 *
23
 * The SSL/TLS protocol has 4 types of records:
24
 * - Handshake record type
25
 * - Change cipher spec record type
26
 * - Alert record type
27
 * - Application data record type
28
 *
29
 * Each record type corresponds to a layer class, and these classes inherit from one base class which is pcpp::SSLLayer.
30
 * The pcpp::SSLLayer is an abstract class which cannot be instantiated. Only its 4 derived classes can be instantiated.
31
 * This means you'll never see a layer of type pcpp::SSLLayer, you'll only see the type of the derived classes.
32
 * A basic class diagram looks like this:
33
  @verbatim
34
                                 +----------------------------+
35
                             +---|     SSLHandshakeLayer      | ===> Handshake record type
36
                             |   +----------------------------+
37
                             |
38
                             |   +----------------------------+
39
                             +---|  SSLChangeCipherSpecLayer  | ===> Change cipher spec record type
40
                             |   +----------------------------+
41
                             |
42
  +------------+             |   +----------------------------+
43
  |  SSLLayer  |-------------+---|      SSLAlertLayer         | ===> Alert record type
44
  | (abstract) |             |   +----------------------------+
45
  +------------+             |
46
                             |   +----------------------------+
47
                             +---|   SSLApplicationDataLayer  | ===> Application data record type
48
                                 +----------------------------+
49
50
  @endverbatim
51
 *
52
 * A single packet may include several SSL/TLS records, meaning several layer instances of these types, for example:
53
 *
54
  @verbatim
55
56
            +--------------------------+
57
            |          EthLayer        |
58
            +--------------------------+
59
            |          IPv4Layer       |
60
            +--------------------------+
61
            |          TcpLayer        |
62
            +--------------------------+
63
            |    SSLHandshakeLayer     | \
64
            +--------------------------+  \
65
            | SSLChangeCipherSpecLayer | -------- 3 SSL/TLS records in the same packet!
66
            +--------------------------+  /
67
            |    SSLHandshakeLayer     | /
68
            +--------------------------+
69
70
  @endverbatim
71
 *
72
 * <BR><BR>
73
 *
74
 * __SSL/TLS Handshake records:__    <BR>
75
 *
76
 * The SSL/TLS handshake records are the most complex ones. These type of records encapsulate all messages between
77
 * client and server during SSL/TLS connection establishment. To accomplish that a SSL/TLS handshake record holds
78
 * zero or more handshake messages (usually it holds 1 message). These messages form the handshake negotiation between
79
 * the client and the server. There are several types of handshake messages. Some of the are sent from client to server
80
 * and some from server to client. PcapPlusPlus supports 11 of these types (definitely the most common ones). For each
81
 * message there is a designated class which parses the message and exposes its attributes in an easy-to-use manner.
82
 * Here are the list of supported messages:
83
 * - Client-hello
84
 * - Server-hello
85
 * - Certificate
86
 * - Hello-request
87
 * - Server-key-exchange
88
 * - Client-key-exchange
89
 * - Certificate-request
90
 * - Server-hello-done
91
 * - Certificate-verify
92
 * - Finished
93
 * - New-session-ticket
94
 *
95
 * All handshake messages classes inherit from a base abstract class: pcpp::SSLHandshakeMessage which cannot be instantiated.
96
 * Also, all of them reside in SSLHandshake.h. Following is a simple diagram of these classes:
97
 *
98
 @verbatim
99
100
                                          SSLHandshakeMessage
101
                                             |
102
 +-------------------------------+           |--- SSLClientHelloMessage        ==> Client-hello message
103
 |       SSLHandshakeLayer       |           |
104
 +-------------------------------+           |--- SSLServerHelloMessage        ==> Server-hello message
105
 | -List of SSLHandshakeMessage  |           |
106
 |     Message1                  |           |---SSLCertificateMessage         ==> Certificate message
107
 |     Message2                  |           |
108
 |     ...                       |           |---SSLHelloRequestMessage        ==> Hello-request message
109
 |                               |           |
110
 +-------------------------------+           |---SSLServerKeyExchangeMessage   ==> Server-key-exchange message
111
                                             |
112
                                             |---SSLClientKeyExchangeMessage   ==> Client-key-exchange message
113
                                             |
114
                                             |---SSLCertificateRequestMessage  ==> Certificate-request message
115
                                             |
116
                                             |---SSLServerHelloDoneMessage     ==> Server-hello-done message
117
                                             |
118
                                             |---SSLCertificateVerifyMessage   ==> Certificate-verify message
119
                                             |
120
                                             |---SSLFinishedMessage            ==> Finished message
121
                                             |
122
                                             |---SSLNewSessionTicketMessage    ==> New-session-ticket message
123
124
 @endverbatim
125
 *
126
 * In addition, for all handshake messages which aren't supported in PcapPlusPlus or for encrypted handshake messages
127
 * There is another class: pcpp::SSLUnknownMessage
128
 *
129
 * <BR><BR>
130
 *
131
 * __Cipher suites:__    <BR>
132
 *
133
 * Cipher suites are named combinations of authentication, encryption, message authentication code (MAC) and key exchange
134
 * algorithms used to negotiate the security settings for a network connection using SSL/TLS.
135
 * There are many known cipher-suites. PcapPlusPlus support above 300 of them, according to this list:
136
 * http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml
137
 * There is a designated class in PcapPlusPlus called pcpp::SSLCipherSuite which represents the cipher-suites and provides
138
 * access to their attributes. Then there is a static instance of this class for each one of the supported cipher-suites.
139
 * This means there are 300+ static instances of pcpp::SSLCipherSuite representing the different cipher suites. The user can
140
 * access them through static methods in pcpp::SSLCipherSuite or from client-hello and server-hello messages where they appear
141
 *
142
 * <BR><BR>
143
 *
144
 * __SSL/TLS extensions:__    <BR>
145
 *
146
 * SSL/TLS handshake messages, specifically client-hello and server-hello usually include extensions. There are various
147
 * types of extensions - some are more broadly used, some are less. In PcapPlusPlus there is a base class for all
148
 * extensions: pcpp::SSLExtension. This class is instantiable and represents a generic extension, which means extension data
149
 * isn't parsed and given to the user as raw data. Currently there are only two extension that are fully parsed which are
150
 * server-name-indication (pcpp::SSLServerNameIndicationExtension) and SupportedVersions (pcpp::SSLSupportedVersionsExtension).
151
 * Both inherit from pcpp::SSLExtension and add additional parsing relevant for the specific extension.
152
 * All other extensions aren't parsed and are represented by instance of pcpp::SSLExtension.
153
 * Access to extensions is done through the handshake messages classes, specifically pcpp::SSLClientHelloMessage and pcpp::SSLServerHelloMessage
154
 */
155
156
157
/**
158
 * \namespace pcpp
159
 * \brief The main namespace for the PcapPlusPlus lib
160
 */
161
namespace pcpp
162
{
163
164
  /**
165
   * @class SSLLayer
166
   * The base class for the 4 record type classes. Each record type is represented as a layer. See SSLLayer.h for
167
   * detailed explanation of the TLS/SSL protocol support in PcapPlusPlus.
168
   * This class provides the common functionality used by all record types and also contains static methods for identifying
169
   * an creating SSL/TLS record type layers
170
   */
171
  class SSLLayer : public Layer
172
  {
173
  public:
174
175
    /**
176
     * A static method that checks whether the port is considered as SSL/TLS
177
     * @param[in] port The port number to be checked
178
     */
179
    static inline bool isSSLPort(uint16_t port);
180
181
    /**
182
     * A static methods that gets raw data of a layer and checks whether this data is a SSL/TLS record or not. This check is
183
     * done using the source/dest port and matching of a legal record type in the raw data. The list of ports identified
184
     * as SSL/TLS is hard-coded and includes the following ports:
185
     * - Port 443 [HTTPS]
186
     * - Port 261 [NSIIOPS]
187
     * - Port 448 [DDM-SSL]
188
     * - Port 563 [NNTPS]
189
     * - Port 614 [SSHELL]
190
     * - Port 465 [SMTPS]
191
     * - Port 636 [LDAPS]
192
     * - Port 989 [FTPS - data]
193
     * - Port 990 [FTPS - control]
194
     * - Port 992 [Telnet over TLS/SSL]
195
     * - Port 993 [IMAPS]
196
     * - Port 994 [IRCS]
197
     * - Port 995 [POP3S]
198
     * @param[in] srcPort The source port of the packet that contains the raw data. Source port (or dest port) are a
199
     * criteria to identify SSL/TLS packets
200
     * @param[in] dstPort The dest port of the packet that contains the raw data. Dest port (or source port) are a
201
     * criteria to identify SSL/TLS packets
202
     * @param[in] data The data to check
203
     * @param[in] dataLen Length (in bytes) of the data
204
     * @param[in] ignorePorts SSL/TLS ports are only relevant for parsing the first SSL/TLS message, but are not relevant
205
     * for parsing subsequent messages. This parameter can be set to "true" to skip SSL/TLS ports check. This is an
206
     * optional parameter and its default is "false"
207
     */
208
    static bool IsSSLMessage(uint16_t srcPort, uint16_t dstPort, uint8_t* data, size_t dataLen, bool ignorePorts = false);
209
210
    /**
211
     * A static method that creates SSL/TLS layers by raw data. This method parses the raw data, finds if and which
212
     * SSL/TLS record it is and creates the corresponding record layer. It's the responsibility of the user to free
213
     * the created object when done using it
214
     * @param[in] data A pointer to the raw data
215
     * @param[in] dataLen Size of the data in bytes
216
     * @param[in] prevLayer A pointer to the previous layer
217
     * @param[in] packet A pointer to the Packet instance where layer will be stored in
218
     * @return A pointer to the newly created record layer. If no SSL/TLS record could be identified from the raw data
219
     * NULL is returned
220
     */
221
    static SSLLayer* createSSLMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
222
223
    /**
224
     * Get a pointer to the record header. Notice this points directly to the data, so every change will change the actual packet data
225
     * @return A pointer to the @ref ssl_tls_record_layer
226
     */
227
30.2k
    ssl_tls_record_layer* getRecordLayer() const { return (ssl_tls_record_layer*)m_Data; }
228
229
    /**
230
     * @return The SSL/TLS version used in this record (parsed from the record)
231
     */
232
    SSLVersion getRecordVersion() const;
233
234
    /**
235
     * @return The SSL/TLS record type as parsed from the record
236
     */
237
    SSLRecordType getRecordType() const;
238
239
    // implement abstract methods
240
241
    /**
242
     * @return The record size as extracted from the record data (in ssl_tls_record_layer#length)
243
     */
244
    size_t getHeaderLen() const;
245
246
    /**
247
     * Several SSL/TLS records can reside in a single packets. So this method checks the remaining data and if it's
248
     * identified as SSL/TLS it creates another SSL/TLS record layer as the next layer
249
     */
250
    void parseNextLayer();
251
252
18.3k
    OsiModelLayer getOsiModelLayer() const { return OsiModelPresentationLayer; }
253
254
  protected:
255
18.3k
    SSLLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = SSL; }
256
257
  }; // class SSLLayer
258
259
260
  /**
261
   * @class SSLHandshakeLayer
262
   * Represents SSL/TLS handshake layer. This layer may contain one or more handshake messages (all of them inherit from
263
   * the base class SSLHandshakeMessage) which are the SSL/TLS handshake message sent between a client and a server until
264
   * they establish a secure connection (e.g client-hello, server-hello, certificate, client-key-exchange,
265
   * server-key-exchange, etc.). Usually this layer will contain just one message (as the first example below
266
   * demonstrates). But there are cases a layer may contain more than 1 message. To better explain this layer structure
267
   * we'll use 2 examples. The first will be client-hello message. The layer structure will look like this:
268
    @verbatim
269
270
        |------------------- SSLHandshakeLayer ----------------------|
271
        +----------------------+-------------------------------------+
272
        | ssl_tls_record_layer |       SSLClientHelloMessage         |
273
        |        struct        |                                     |
274
        +----------------------+-------------------------------------+
275
         /     |       \               |          \         \      \
276
        /    version    \      |   handshake       \         \      \
277
       /     TLS1_0      \            type          \         \     rest of
278
      type                  \    | SSL_CLIENT_HELLO    \         \    message fields...
279
    SSL_HANDSHAKE           length                   handshake      \
280
      (22)                 xxx   |                  version      message
281
                             TLS1_2      length
282
                   |                                yyy
283
    @endverbatim
284
285
   * Second example is a multiple-message handshake layer comprises of server-hello, certificate and server-key-exchange
286
   * messages:
287
288
    @verbatim
289
290
        |---------------------------------------------- SSLHandshakeLayer -----------------------------------------------------|
291
        +----------------------+-------------------------------------+---------------------------+-----------------------------+
292
        | ssl_tls_record_layer |       SSLServerHelloMessage         |   SSLCertificateMessage   | SSLServerKeyExchangeMessage |
293
        |        struct        |                                     |                           |                             |
294
        +----------------------+-------------------------------------+---------------------------+-----------------------------+
295
         /     |       \               |          \         \               |           \               |            \
296
        /    version    \      |   handshake       \        rest of  |      |          rest      |      |            rest
297
       /     TLS1_0      \            type          \       message      handshake   of fields...   handshake    of fields...
298
      type                  \    | SSL_SERVER_HELLO    \      fields...|     type                  |     type
299
    SSL_HANDSHAKE           length                   handshake             SSL_CERTIFICATE             SSL_SERVER_KEY_EXCHANGE
300
      (22)                 xxx   |               version,length        |                           |
301
302
                   |                                     |                           |
303
304
    @endverbatim
305
   */
306
  class SSLHandshakeLayer: public SSLLayer
307
  {
308
  public:
309
310
    /**
311
     * C'tor for this class that creates the layer from an existing packet raw data
312
     * @param[in] data A pointer to the raw data
313
     * @param[in] dataLen Size of the data in bytes
314
     * @param[in] prevLayer A pointer to the previous layer
315
     * @param[in] packet A pointer to the Packet instance where layer will be stored in
316
     */
317
    SSLHandshakeLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
318
319
    /**
320
     * @return The number of messages in this layer instance
321
     */
322
0
    size_t getHandshakeMessagesCount() const { return m_MessageList.size(); }
323
324
    /**
325
     * Get a pointer to an handshake message by index. The message are numbered according to their order of appearance
326
     * in the layer. If index is out of bounds (less than 0 or larger than total amount of message) NULL will be
327
     * returned
328
     * @param[in] index The index of the message to return
329
     * @return The pointer to the message object or NULL if index is out of bounds
330
     */
331
    SSLHandshakeMessage* getHandshakeMessageAt(int index) const;
332
333
    /**
334
     * A templated method to get a message of a certain type. If no message of such type is found, NULL is returned
335
     * @return A pointer to the message of the requested type, NULL if not found
336
     */
337
    template<class THandshakeMessage>
338
    THandshakeMessage* getHandshakeMessageOfType() const;
339
340
    /**
341
     * A templated method to get the first message of a certain type, starting to search from a certain message.
342
     * For example: if the layer looks like: HelloRequest(1) -> HelloRequest(2)
343
     * and the user put HelloRequest(1) as a parameter and wishes to search for an HelloRequest message, the
344
     * HelloRequest(2) will be returned.<BR>
345
     * If no layer of such type is found, NULL is returned
346
     * @param[in] after A pointer to the message to start search from
347
     * @return A pointer to the message of the requested type, NULL if not found
348
     */
349
    template<class THandshakeMessage>
350
    THandshakeMessage* getNextHandshakeMessageOfType(const SSLHandshakeMessage* after) const;
351
352
    // implement abstract methods
353
354
    std::string toString() const;
355
356
    /**
357
     * There are no calculated fields for this layer
358
     */
359
0
    void computeCalculateFields() {}
360
361
  private:
362
    PointerVector<SSLHandshakeMessage> m_MessageList;
363
  }; // class SSLHandshakeLayer
364
365
366
  /**
367
   * @class SSLChangeCipherSpecLayer
368
   * Represents SSL/TLS change-cipher-spec layer. This layer has no additional fields besides common fields described in
369
   * SSLLayer
370
   */
371
  class SSLChangeCipherSpecLayer : public SSLLayer
372
  {
373
  public:
374
375
    /**
376
     * C'tor for this class that creates the layer from an existing packet raw data
377
     * @param[in] data A pointer to the raw data
378
     * @param[in] dataLen Size of the data in bytes
379
     * @param[in] prevLayer A pointer to the previous layer
380
     * @param[in] packet A pointer to the Packet instance where layer will be stored in
381
     */
382
    SSLChangeCipherSpecLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
383
1.60k
      : SSLLayer(data, dataLen, prevLayer, packet) {}
384
385
0
    ~SSLChangeCipherSpecLayer() {}
386
387
    // implement abstract methods
388
389
    std::string toString() const;
390
391
    /**
392
     * There are no calculated fields for this layer
393
     */
394
0
    void computeCalculateFields() {}
395
  }; // class SSLChangeCipherSpecLayer
396
397
398
  /**
399
   * @class SSLAlertLayer
400
   * Represents SSL/TLS alert layer. Inherits from SSLLayer and adds parsing functionality such as retrieving the alert
401
   * level and description
402
   */
403
  class SSLAlertLayer : public SSLLayer
404
  {
405
  public:
406
407
    /**
408
     * C'tor for this class that creates the layer from an existing packet raw data
409
     * @param[in] data A pointer to the raw data
410
     * @param[in] dataLen Size of the data in bytes
411
     * @param[in] prevLayer A pointer to the previous layer
412
     * @param[in] packet A pointer to the Packet instance where layer will be stored in
413
     */
414
    SSLAlertLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
415
1.74k
      : SSLLayer(data, dataLen, prevLayer, packet) {}
416
417
0
    ~SSLAlertLayer() {}
418
419
    /**
420
     * @return SSL/TLS alert level. Will return ::SSL_ALERT_LEVEL_ENCRYPTED if alert is encrypted
421
     */
422
    SSLAlertLevel getAlertLevel() const;
423
424
    /**
425
     * @return SSL/TLS alert description. Will return ::SSL_ALERT_ENCRYPTED if alert is encrypted
426
     */
427
    SSLAlertDescription getAlertDescription();
428
429
    // implement abstract methods
430
431
    std::string toString() const;
432
433
    /**
434
     * There are no calculated fields for this layer
435
     */
436
0
    void computeCalculateFields() {}
437
  }; // class SSLAlertLayer
438
439
440
  /**
441
   * @class SSLApplicationDataLayer
442
   * Represents SSL/TLS application data layer. This message contains the encrypted data transferred from client to
443
   * server and vice-versa after the SSL/TLS handshake was completed successfully
444
   */
445
  class SSLApplicationDataLayer : public SSLLayer
446
  {
447
  public:
448
449
    /**
450
     * C'tor for this class that creates the layer from an existing packet raw data
451
     * @param[in] data A pointer to the raw data
452
     * @param[in] dataLen Size of the data in bytes
453
     * @param[in] prevLayer A pointer to the previous layer
454
     * @param[in] packet A pointer to the Packet instance where layer will be stored in
455
     */
456
    SSLApplicationDataLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
457
3.05k
      : SSLLayer(data, dataLen, prevLayer, packet) {}
458
459
0
    ~SSLApplicationDataLayer() {}
460
461
    /**
462
     * @return A pointer to the encrypted data. This data can be decrypted only if you have the symmetric key
463
     * that was agreed between the client and the server during SSL/TLS handshake process
464
     */
465
    uint8_t* getEncryptedData() const;
466
467
    /**
468
     * @return The length in bytes of the encrypted data returned in getEncryptedData()
469
     */
470
    size_t getEncryptedDataLen() const;
471
472
    // implement abstract methods
473
474
    std::string toString() const;
475
476
    /**
477
     * There are no calculated fields for this layer
478
     */
479
0
    void computeCalculateFields() {}
480
  }; // class SSLApplicationDataLayer
481
482
483
  template<class THandshakeMessage>
484
  THandshakeMessage* SSLHandshakeLayer::getHandshakeMessageOfType() const
485
  {
486
    size_t vecSize = m_MessageList.size();
487
    for (size_t i = 0; i < vecSize; i++)
488
    {
489
      SSLHandshakeMessage* curElem = const_cast<SSLHandshakeMessage*>(m_MessageList.at(i));
490
       if (dynamic_cast<THandshakeMessage*>(curElem) != NULL)
491
         return (THandshakeMessage*)curElem;
492
    }
493
494
    // element not found
495
    return NULL;
496
  } // getHandshakeMessageOfType
497
498
499
  template<class THandshakeMessage>
500
  THandshakeMessage* SSLHandshakeLayer::getNextHandshakeMessageOfType(const SSLHandshakeMessage* after) const
501
  {
502
    size_t vecSize = m_MessageList.size();
503
    size_t afterIndex;
504
505
    // find the index of "after"
506
    for (afterIndex = 0; afterIndex < vecSize; afterIndex++)
507
    {
508
      SSLHandshakeMessage* curElem = const_cast<SSLHandshakeMessage*>(m_MessageList.at(afterIndex));
509
      if (curElem == after)
510
        break;
511
    }
512
513
    // "after" not found
514
    if (afterIndex == vecSize)
515
      return NULL;
516
517
    for (size_t i = afterIndex+1; i < vecSize; i++)
518
    {
519
      SSLHandshakeMessage* curElem = const_cast<SSLHandshakeMessage*>(m_MessageList.at(i));
520
       if (dynamic_cast<THandshakeMessage*>(curElem) != NULL)
521
         return (THandshakeMessage*)curElem;
522
    }
523
524
    // element not found
525
    return NULL;
526
  } // getNextHandshakeMessageOfType
527
528
529
  // implementation of inline methods
530
531
  bool SSLLayer::isSSLPort(uint16_t port)
532
236k
  {
533
236k
    if (port == 443) // HTTPS, this is likely case
534
1.14k
      return true;
535
536
235k
    switch (port)
537
235k
    {
538
2.68k
    case 261: // NSIIOPS
539
3.93k
    case 448: // DDM-SSL
540
5.10k
    case 465: // SMTPS
541
6.00k
    case 563: // NNTPS
542
6.34k
    case 614: // SSHELL
543
6.69k
    case 636: // LDAPS
544
7.10k
    case 989: // FTPS - data
545
11.2k
    case 990: // FTPS - control
546
11.7k
    case 992: // Telnet over TLS/SSL
547
12.0k
    case 993: // IMAPS
548
12.6k
    case 994: // IRCS
549
14.2k
    case 995: // POP3S
550
14.2k
      return true;
551
220k
    default:
552
220k
      return false;
553
235k
    }
554
235k
  } // isSSLPort
555
556
} // namespace pcpp
557
558
#endif /* PACKETPP_SSL_LAYER */