Coverage Report

Created: 2026-11-12 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/header/WireGuardLayer.h
Line
Count
Source
1
#pragma once
2
3
#include "Layer.h"
4
#include "IpAddress.h"
5
#include "MacAddress.h"
6
7
/// @file
8
9
/// @namespace pcpp
10
/// @brief The main namespace for the PcapPlusPlus lib
11
namespace pcpp
12
{
13
  /// @class WireGuardLayer
14
  /// Represents a WireGuard protocol layer
15
  class WireGuardLayer : public Layer
16
  {
17
  protected:
18
#pragma pack(push, 1)
19
    /// @struct wg_common_header
20
    /// Represents the common header for all WireGuard message types
21
    struct wg_common_header
22
    {
23
      /// Message type field
24
      uint8_t messageType;
25
      /// Reserved field (3 bytes)
26
      uint8_t reserved[3];
27
    };
28
#pragma pack(pop)
29
    static_assert(sizeof(wg_common_header) == 4, "wg_common_header size is not 4 bytes");
30
31
    wg_common_header* getBasicHeader() const
32
0
    {
33
0
      return reinterpret_cast<wg_common_header*>(m_Data);
34
0
    }
35
36
0
    WireGuardLayer() = default;
37
38
  public:
39
    /// WireGuard message types
40
    enum class WireGuardMessageType
41
    {
42
      /// Unknown Initiation message
43
      Unknown = 0,
44
      /// Handshake Initiation message
45
      HandshakeInitiation = 1,
46
      /// Handshake Response message
47
      HandshakeResponse = 2,
48
      /// Cookie Reply message
49
      CookieReply = 3,
50
      /// Transport Data message
51
      TransportData = 4
52
    };
53
54
    /// Constructs a WireGuardLayer object.
55
    /// @param data Pointer to the raw data representing the WireGuard layer
56
    /// @param dataLen Length of the data
57
    /// @param prevLayer Pointer to the previous layer in the packet (if any)
58
    /// @param packet Pointer to the packet this layer belongs to
59
    WireGuardLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
60
0
        : Layer(data, dataLen, prevLayer, packet, WireGuard)
61
0
    {}
62
63
    /// Checks if the given port numbers are WireGuard ports.
64
    /// @param portSrc The source port number to check
65
    /// @param portDst The destination port number to check
66
    /// @return True if either port matches the WireGuard port (51820), false otherwise
67
    static bool isWireGuardPorts(uint16_t portSrc, uint16_t portDst)
68
0
    {
69
0
      return (portSrc == 51820 || portDst == 51820);
70
0
    }
71
72
    /// Checks if the given data represents a WireGuard message.
73
    /// @param data Pointer to the raw data
74
    /// @param dataLen Length of the data
75
    /// @return True if the data starts with a valid WireGuard message type, false otherwise
76
    static bool isDataValid(const uint8_t* data, size_t dataLen);
77
78
    /// Parses the raw data into a WireGuard layer.
79
    /// @param data Pointer to the raw data
80
    /// @param dataLen Length of the data
81
    /// @param prevLayer Pointer to the previous layer
82
    /// @param packet Pointer to the packet
83
    /// @return A pointer to the parsed WireGuardLayer, or nullptr if parsing fails
84
    static WireGuardLayer* parseWireGuardLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
85
86
    /// @return String representation of the message type.
87
    std::string getMessageTypeAsString() const;
88
89
    /// @return The message type as an unsigned 32-bit integer.
90
    uint8_t getMessageType() const;
91
92
    /// @return The reserved field as a 32-bit integer.
93
    uint32_t getReserved() const;
94
95
    /// @param reserved The reserved field to set as a An array containing the 3-byte.
96
    void setReserved(const std::array<uint8_t, 3>& reserved);
97
98
    /// Does nothing for this layer (WireGuard layer is always last)
99
    void parseNextLayer() override
100
0
    {}
101
102
    /// @return Size of the header in bytes.
103
    size_t getHeaderLen() const override;
104
105
    /// No fields to compute or update, so this method is left empty.
106
    void computeCalculateFields() override
107
0
    {}
108
109
    /// Converts the WireGuard layer to a string representation.
110
    /// @return String representation of the WireGuard layer
111
    std::string toString() const override;
112
113
    /// @return OSI model layer corresponding to the Network layer
114
    OsiModelLayer getOsiModelLayer() const override
115
0
    {
116
0
      return OsiModelNetworkLayer;
117
0
    }
118
119
    /// @return The message type as a WireGuardMessageType enum value.
120
    virtual WireGuardMessageType getWireGuardMessageType() const
121
0
    {
122
0
      return WireGuardMessageType::Unknown;
123
0
    }
124
125
    /// @struct SerializedFields
126
    /// Fields written by WireGuardLayer's serializeLayer(), in addition to
127
    /// Layer::SerializedFields.
128
    struct SerializedFields : Layer::SerializedFields
129
    {
130
      /// @return All field descriptors for WireGuardLayer
131
      static std::vector<FieldDescriptor> all()
132
0
      {
133
0
        auto result = Layer::SerializedFields::all();
134
0
        std::initializer_list<FieldDescriptor> extra{ MessageType, MessageTypeName };
135
0
        std::copy(extra.begin(), extra.end(), std::back_inserter(result));
136
0
        return result;
137
0
      }
138
139
      /// @brief Field descriptor for the raw message type value, written as a number.
140
      static const FieldDescriptor MessageType;
141
142
      /// @brief Field descriptor for the message type name, written as a string.
143
      static const FieldDescriptor MessageTypeName;
144
145
      // cppcheck-suppress duplInheritedMember
146
      /// Maximum field ID used by WireGuardLayer
147
      static constexpr uint16_t MaxID = Layer::SerializedFields::MaxID + 2;
148
    };
149
150
  protected:
151
    void serializeLayer(ObjectScope& serializer) const override;
152
  };
153
154
  /// @class WireGuardHandshakeInitiationLayer
155
  /// Represents the Handshake Initiation message layer
156
  class WireGuardHandshakeInitiationLayer : public WireGuardLayer
157
  {
158
  private:
159
#pragma pack(push, 1)
160
    /// @struct wg_handshake_initiation
161
    /// Represents the Handshake Initiation message structure
162
    typedef struct wg_handshake_initiation : wg_common_header
163
    {
164
      /// Sender index
165
      uint32_t senderIndex;
166
      /// Initiator's ephemeral public key
167
      uint8_t initiatorEphemeral[32];
168
      /// Encrypted initiator's static key
169
      uint8_t encryptedInitiatorStatic[48];
170
      /// Encrypted timestamp
171
      uint8_t encryptedTimestamp[28];
172
      /// MAC1 field
173
      uint8_t mac1[16];
174
      /// MAC2 field
175
      uint8_t mac2[16];
176
    } wg_handshake_initiation;
177
#pragma pack(pop)
178
    wg_handshake_initiation* getHandshakeInitiationHeader() const
179
0
    {
180
0
      return reinterpret_cast<wg_handshake_initiation*>(getBasicHeader());
181
0
    }
182
183
  public:
184
    /// A constructor that creates the layer from an existing packet raw data
185
    /// @param[in] data A pointer to the raw data
186
    /// @param[in] dataLen Size of the data in bytes
187
    /// @param[in] prevLayer A pointer to the previous layer
188
    /// @param[in] packet A pointer to the Packet instance where layer will be stored in
189
    WireGuardHandshakeInitiationLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
190
0
        : WireGuardLayer(data, dataLen, prevLayer, packet)
191
0
    {}
192
193
    /// A static method that checks whether a byte stream is long enough to hold a WireGuard Handshake Initiation
194
    /// message
195
    /// @param[in] data A pointer to the beginning of the message
196
    /// @param[in] dataLen The length of the byte stream
197
    /// @return True if the data is at least as long as the fixed part of the message, false otherwise
198
    static bool isDataValid(const uint8_t* data, size_t dataLen)
199
0
    {
200
0
      return data != nullptr && dataLen >= sizeof(wg_handshake_initiation);
201
0
    }
202
203
    /// A constructor that creates a new Handshake Initiation message
204
    /// @param[in] senderIndex The sender's index
205
    /// @param[in] initiatorEphemeral The initiator's ephemeral public key
206
    /// @param[in] encryptedInitiatorStatic The encrypted initiator's static key
207
    /// @param[in] encryptedTimestamp The encrypted timestamp
208
    /// @param[in] mac1 The MAC1 field
209
    /// @param[in] mac2 The MAC2 field
210
    WireGuardHandshakeInitiationLayer(uint32_t senderIndex, const uint8_t initiatorEphemeral[32],
211
                                      const uint8_t encryptedInitiatorStatic[48],
212
                                      const uint8_t encryptedTimestamp[28], const uint8_t mac1[16],
213
                                      const uint8_t mac2[16]);
214
215
    /// @return The sender index as a 32-bit integer.
216
    uint32_t getSenderIndex() const;
217
218
    /// @return An array containing the initiator's ephemeral public key.
219
    std::array<uint8_t, 32> getInitiatorEphemeral() const;
220
221
    /// @return An array containing the encrypted initiator's static key.
222
    std::array<uint8_t, 48> getEncryptedInitiatorStatic() const;
223
224
    /// @return An array containing the encrypted timestamp.
225
    std::array<uint8_t, 28> getEncryptedTimestamp() const;
226
227
    /// @return An array containing the MAC1 field.
228
    std::array<uint8_t, 16> getMac1() const;
229
230
    /// @return An array containing the MAC2 field.
231
    std::array<uint8_t, 16> getMac2() const;
232
233
    /// @param senderIndex A 32-bit integer representing the sender index.
234
    void setSenderIndex(uint32_t senderIndex);
235
236
    /// @param initiatorEphemeral An array containing the 32-byte initiator ephemeral public key.
237
    void setInitiatorEphemeral(const std::array<uint8_t, 32>& initiatorEphemeral);
238
239
    /// @param encryptedInitiatorStatic An array containing the 48-byte encrypted initiator's static key.
240
    void setEncryptedInitiatorStatic(const std::array<uint8_t, 48>& encryptedInitiatorStatic);
241
242
    /// @param encryptedTimestamp An array containing the 28-byte encrypted timestamp.
243
    void setEncryptedTimestamp(const std::array<uint8_t, 28>& encryptedTimestamp);
244
245
    /// @param mac1 An array containing the 16-byte MAC1 field.
246
    void setMac1(const std::array<uint8_t, 16>& mac1);
247
248
    /// @param mac2 An array containing the 16-byte MAC2 field.
249
    void setMac2(const std::array<uint8_t, 16>& mac2);
250
251
    // implement abstract methods
252
253
    /// @return WireGuardMessageType enum value indicating HandshakeInitiation.
254
    WireGuardMessageType getWireGuardMessageType() const override
255
0
    {
256
0
      return WireGuardMessageType::HandshakeInitiation;
257
0
    }
258
259
    /// @struct SerializedFields
260
    /// Fields written by WireGuardHandshakeInitiationLayer's serializeLayer(), in addition to
261
    /// WireGuardLayer::SerializedFields.
262
    struct SerializedFields : WireGuardLayer::SerializedFields
263
    {
264
      /// @return All field descriptors for WireGuardHandshakeInitiationLayer
265
      static std::vector<FieldDescriptor> all()
266
0
      {
267
0
        auto result = WireGuardLayer::SerializedFields::all();
268
0
        std::initializer_list<FieldDescriptor> extra{
269
0
          SenderIndex, InitiatorEphemeral, EncryptedInitiatorStatic, EncryptedTimestamp, Mac1, Mac2
270
0
        };
271
0
        std::copy(extra.begin(), extra.end(), std::back_inserter(result));
272
0
        return result;
273
0
      }
274
275
      /// @brief Field descriptor for the sender index, written as a hex value.
276
      static const FieldDescriptor SenderIndex;
277
278
      /// @brief Field descriptor for the 32-byte initiator ephemeral public key, written as a hex string with no
279
      /// separators.
280
      static const FieldDescriptor InitiatorEphemeral;
281
282
      /// @brief Field descriptor for the 48-byte encrypted initiator static key, written as a hex string with no
283
      /// separators.
284
      static const FieldDescriptor EncryptedInitiatorStatic;
285
286
      /// @brief Field descriptor for the 28-byte encrypted timestamp, written as a hex string with no separators.
287
      static const FieldDescriptor EncryptedTimestamp;
288
289
      /// @brief Field descriptor for the 16-byte MAC1, written as a hex string with no separators.
290
      static const FieldDescriptor Mac1;
291
292
      /// @brief Field descriptor for the 16-byte MAC2, written as a hex string with no separators.
293
      static const FieldDescriptor Mac2;
294
    };
295
296
  protected:
297
    void serializeLayer(ObjectScope& serializer) const override;
298
  };
299
300
  /// @class WireGuardHandshakeResponseLayer
301
  /// Represents a Handshake Response message
302
  class WireGuardHandshakeResponseLayer : public WireGuardLayer
303
  {
304
  private:
305
#pragma pack(push, 1)
306
    /// @struct wg_handshake_response
307
    /// Represents the Handshake Response message structure
308
    typedef struct wg_handshake_response : wg_common_header
309
    {
310
      /// Sender index
311
      uint32_t senderIndex;
312
      /// Receiver index
313
      uint32_t receiverIndex;
314
      /// Responder's ephemeral public key
315
      uint8_t responderEphemeral[32];
316
      /// Encrypted empty field
317
      uint8_t encryptedEmpty[16];
318
      /// MAC1 field
319
      uint8_t mac1[16];
320
      /// MAC2 field
321
      uint8_t mac2[16];
322
    } wg_handshake_response;
323
#pragma pack(pop)
324
325
    wg_handshake_response* getHandshakeResponseHeader() const
326
0
    {
327
0
      return reinterpret_cast<wg_handshake_response*>(getBasicHeader());
328
0
    }
329
330
  public:
331
    /// A constructor that creates the layer from an existing packet raw data
332
    /// @param[in] data A pointer to the raw data
333
    /// @param[in] dataLen Size of the data in bytes
334
    /// @param[in] prevLayer A pointer to the previous layer
335
    /// @param[in] packet A pointer to the Packet instance where layer will be stored in
336
    WireGuardHandshakeResponseLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
337
0
        : WireGuardLayer(data, dataLen, prevLayer, packet)
338
0
    {}
339
340
    /// A static method that checks whether a byte stream is long enough to hold a WireGuard Handshake Response
341
    /// message
342
    /// @param[in] data A pointer to the beginning of the message
343
    /// @param[in] dataLen The length of the byte stream
344
    /// @return True if the data is at least as long as the fixed part of the message, false otherwise
345
    static bool isDataValid(const uint8_t* data, size_t dataLen)
346
0
    {
347
0
      return data != nullptr && dataLen >= sizeof(wg_handshake_response);
348
0
    }
349
350
    /// A constructor that creates a new Handshake Response message
351
    /// @param[in] senderIndex The sender index
352
    /// @param[in] receiverIndex The receiver index
353
    /// @param[in] responderEphemeral The responder's ephemeral public key
354
    /// @param[in] encryptedEmpty The encrypted empty field
355
    /// @param[in] mac1 The MAC1 field
356
    /// @param[in] mac2 The MAC2 field
357
    WireGuardHandshakeResponseLayer(uint32_t senderIndex, uint32_t receiverIndex,
358
                                    const uint8_t responderEphemeral[32], const uint8_t encryptedEmpty[16],
359
                                    const uint8_t mac1[16], const uint8_t mac2[16]);
360
361
    /// @return The sender index as a 32-bit unsigned integer.
362
    uint32_t getSenderIndex() const;
363
364
    /// @return The receiver index as a 32-bit unsigned integer.
365
    uint32_t getReceiverIndex() const;
366
367
    /// @return The responder's ephemeral public key as an array of 32 bytes.
368
    std::array<uint8_t, 32> getResponderEphemeral() const;
369
370
    /// @return The encrypted empty field as an array of 16 bytes.
371
    std::array<uint8_t, 16> getEncryptedEmpty() const;
372
373
    /// @return The MAC1 field as an array of 16 bytes.
374
    std::array<uint8_t, 16> getMac1() const;
375
376
    /// @return The MAC2 field as an array of 16 bytes.
377
    std::array<uint8_t, 16> getMac2() const;
378
379
    /// @param senderIndex A 32-bit unsigned integer representing the sender index.
380
    void setSenderIndex(uint32_t senderIndex);
381
382
    /// @param receiverIndex A 32-bit unsigned integer representing the receiver index.
383
    void setReceiverIndex(uint32_t receiverIndex);
384
385
    /// @param responderEphemeral An array containing the 32-byte responder ephemeral public key.
386
    void setResponderEphemeral(const std::array<uint8_t, 32>& responderEphemeral);
387
388
    /// @param encryptedEmpty An array containing the 16-byte encrypted empty field.
389
    void setEncryptedEmpty(const std::array<uint8_t, 16>& encryptedEmpty);
390
391
    /// @param mac1 An array containing the 16-byte MAC1 field.
392
    void setMac1(const std::array<uint8_t, 16>& mac1);
393
394
    /// @param mac2 An array containing the 16-byte MAC2 field.
395
    void setMac2(const std::array<uint8_t, 16>& mac2);
396
397
    // implement abstract methods
398
399
    /// @return The message type as a WireGuardMessageType enum value.
400
    WireGuardMessageType getWireGuardMessageType() const override
401
0
    {
402
0
      return WireGuardMessageType::HandshakeResponse;
403
0
    }
404
405
    /// @struct SerializedFields
406
    /// Fields written by WireGuardHandshakeResponseLayer's serializeLayer(), in addition to
407
    /// WireGuardLayer::SerializedFields.
408
    struct SerializedFields : WireGuardLayer::SerializedFields
409
    {
410
      /// @return All field descriptors for WireGuardHandshakeResponseLayer
411
      static std::vector<FieldDescriptor> all()
412
0
      {
413
0
        auto result = WireGuardLayer::SerializedFields::all();
414
0
        std::initializer_list<FieldDescriptor> extra{ SenderIndex,    ReceiverIndex, ResponderEphemeral,
415
0
                                                    EncryptedEmpty, Mac1,          Mac2 };
416
0
        std::copy(extra.begin(), extra.end(), std::back_inserter(result));
417
0
        return result;
418
0
      }
419
420
      /// @brief Field descriptor for the sender index, written as a hex value.
421
      static const FieldDescriptor SenderIndex;
422
423
      /// @brief Field descriptor for the receiver index, written as a hex value.
424
      static const FieldDescriptor ReceiverIndex;
425
426
      /// @brief Field descriptor for the 32-byte responder ephemeral public key, written as a hex string with no
427
      /// separators.
428
      static const FieldDescriptor ResponderEphemeral;
429
430
      /// @brief Field descriptor for the 16-byte encrypted empty field, written as a hex string with no
431
      /// separators.
432
      static const FieldDescriptor EncryptedEmpty;
433
434
      /// @brief Field descriptor for the 16-byte MAC1, written as a hex string with no separators.
435
      static const FieldDescriptor Mac1;
436
437
      /// @brief Field descriptor for the 16-byte MAC2, written as a hex string with no separators.
438
      static const FieldDescriptor Mac2;
439
    };
440
441
  protected:
442
    void serializeLayer(ObjectScope& serializer) const override;
443
  };
444
445
  /// @class WireGuardCookieReplyLayer
446
  /// Represents a Cookie Reply message
447
  class WireGuardCookieReplyLayer : public WireGuardLayer
448
  {
449
  private:
450
#pragma pack(push, 1)
451
    /// @struct wg_cookie_reply
452
    /// Represents the Cookie Reply message structure
453
    typedef struct wg_cookie_reply : wg_common_header
454
    {
455
      /// Receiver index
456
      uint32_t receiverIndex;
457
      /// Nonce field
458
      uint8_t nonce[24];
459
      /// Encrypted cookie
460
      uint8_t encryptedCookie[32];
461
    } wg_cookie_reply;
462
#pragma pack(pop)
463
464
    wg_cookie_reply* getCookieReplyHeader() const
465
0
    {
466
0
      return reinterpret_cast<wg_cookie_reply*>(getBasicHeader());
467
0
    }
468
469
  public:
470
    /// A constructor that creates the layer from an existing packet raw data
471
    /// @param[in] data A pointer to the raw data
472
    /// @param[in] dataLen Size of the data in bytes
473
    /// @param[in] prevLayer A pointer to the previous layer
474
    /// @param[in] packet A pointer to the Packet instance where layer will be stored in
475
    WireGuardCookieReplyLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
476
0
        : WireGuardLayer(data, dataLen, prevLayer, packet)
477
0
    {}
478
479
    /// A static method that checks whether a byte stream is long enough to hold a WireGuard Cookie Reply message
480
    /// @param[in] data A pointer to the beginning of the message
481
    /// @param[in] dataLen The length of the byte stream
482
    /// @return True if the data is at least as long as the fixed part of the message, false otherwise
483
    static bool isDataValid(const uint8_t* data, size_t dataLen)
484
0
    {
485
0
      return data != nullptr && dataLen >= sizeof(wg_cookie_reply);
486
0
    }
487
488
    /// A constructor that creates a new Cookie Reply message
489
    /// @param[in] receiverIndex The receiver index
490
    /// @param[in] nonce The nonce field
491
    /// @param[in] encryptedCookie The encrypted cookie
492
    WireGuardCookieReplyLayer(uint32_t receiverIndex, const uint8_t nonce[24], const uint8_t encryptedCookie[32]);
493
494
    /// @return The receiver index as a 32-bit unsigned integer.
495
    uint32_t getReceiverIndex() const;
496
497
    /// @return The nonce field as an array of 24 bytes.
498
    std::array<uint8_t, 24> getNonce() const;
499
500
    /// @return The encrypted cookie as an array of 32 bytes.
501
    std::array<uint8_t, 32> getEncryptedCookie() const;
502
503
    /// @param receiverIndex A 32-bit unsigned integer representing the receiver index.
504
    void setReceiverIndex(uint32_t receiverIndex);
505
506
    /// @param nonce An array containing the 24-byte nonce field.
507
    void setNonce(const std::array<uint8_t, 24>& nonce);
508
509
    /// @param encryptedCookie An array containing the 32-byte encrypted cookie.
510
    void setEncryptedCookie(const std::array<uint8_t, 32>& encryptedCookie);
511
512
    // implement abstract methods
513
514
    /// @return The message type as a WireGuardMessageType enum value.
515
    WireGuardMessageType getWireGuardMessageType() const override
516
0
    {
517
0
      return WireGuardMessageType::CookieReply;
518
0
    }
519
520
    /// @struct SerializedFields
521
    /// Fields written by WireGuardCookieReplyLayer's serializeLayer(), in addition to
522
    /// WireGuardLayer::SerializedFields.
523
    struct SerializedFields : WireGuardLayer::SerializedFields
524
    {
525
      /// @return All field descriptors for WireGuardCookieReplyLayer
526
      static std::vector<FieldDescriptor> all()
527
0
      {
528
0
        auto result = WireGuardLayer::SerializedFields::all();
529
0
        std::initializer_list<FieldDescriptor> extra{ ReceiverIndex, Nonce, EncryptedCookie };
530
0
        std::copy(extra.begin(), extra.end(), std::back_inserter(result));
531
0
        return result;
532
0
      }
533
534
      /// @brief Field descriptor for the receiver index, written as a hex value.
535
      static const FieldDescriptor ReceiverIndex;
536
537
      /// @brief Field descriptor for the 24-byte nonce, written as a hex string with no separators.
538
      static const FieldDescriptor Nonce;
539
540
      /// @brief Field descriptor for the 32-byte encrypted cookie, written as a hex string with no separators.
541
      static const FieldDescriptor EncryptedCookie;
542
    };
543
544
  protected:
545
    void serializeLayer(ObjectScope& serializer) const override;
546
  };
547
548
  /// @class WireGuardTransportDataLayer
549
  /// Represents a Transport Data message
550
  class WireGuardTransportDataLayer : public WireGuardLayer
551
  {
552
  private:
553
#pragma pack(push, 1)
554
    /// @struct wg_transport_data
555
    /// Represents the Transport Data message structure
556
    typedef struct wg_transport_data : wg_common_header
557
    {
558
      /// Receiver index
559
      uint32_t receiverIndex;
560
      /// Counter field
561
      uint64_t counter;
562
      /// Flexible array member for encrypted data
563
      uint8_t encryptedData[0];
564
    } wg_transport_data;
565
#pragma pack(pop)
566
567
    wg_transport_data* getTransportHeader() const
568
0
    {
569
0
      return reinterpret_cast<wg_transport_data*>(getBasicHeader());
570
0
    }
571
572
  public:
573
    /// A constructor that creates the layer from an existing packet raw data
574
    /// @param[in] data A pointer to the raw data
575
    /// @param[in] dataLen Size of the data in bytes
576
    /// @param[in] prevLayer A pointer to the previous layer
577
    /// @param[in] packet A pointer to the Packet instance where layer will be stored in
578
    WireGuardTransportDataLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
579
0
        : WireGuardLayer(data, dataLen, prevLayer, packet)
580
0
    {}
581
582
    /// A static method that checks whether a byte stream is long enough to hold a WireGuard Transport Data message
583
    /// @param[in] data A pointer to the beginning of the message
584
    /// @param[in] dataLen The length of the byte stream
585
    /// @return True if the data is at least as long as the fixed part of the message, false otherwise
586
    static bool isDataValid(const uint8_t* data, size_t dataLen)
587
0
    {
588
0
      return data != nullptr && dataLen >= sizeof(wg_transport_data);
589
0
    }
590
591
    /// A constructor that creates a new Transport Data message
592
    /// @param[in] receiverIndex The receiver index
593
    /// @param[in] counter The counter field
594
    /// @param[in] encryptedData The encrypted data
595
    /// @param[in] encryptedDataLen The length of the encrypted data
596
    WireGuardTransportDataLayer(uint32_t receiverIndex, uint64_t counter, const uint8_t* encryptedData,
597
                                size_t encryptedDataLen);
598
599
    /// @return The receiver index as a 32-bit unsigned integer.
600
    uint32_t getReceiverIndex() const;
601
602
    /// @return The counter field as a 64-bit unsigned integer.
603
    uint64_t getCounter() const;
604
605
    /// @return A pointer to the encrypted data field.
606
    const uint8_t* getEncryptedData() const;
607
608
    /// @param receiverIndex A 32-bit unsigned integer representing the receiver index.
609
    void setReceiverIndex(uint32_t receiverIndex);
610
611
    /// @param counter A 64-bit unsigned integer representing the counter field.
612
    void setCounter(uint64_t counter);
613
614
    /// Set the encrypted data, extending or shortening the layer to fit it
615
    /// @param encryptedData A pointer to the encrypted data.
616
    /// @param encryptedDataLen The length of the encrypted data.
617
    void setEncryptedData(const uint8_t* encryptedData, size_t encryptedDataLen);
618
619
    // implement abstract methods
620
621
    /// @return The message type as a WireGuardMessageType enum value.
622
    WireGuardMessageType getWireGuardMessageType() const override
623
0
    {
624
0
      return WireGuardMessageType::TransportData;
625
0
    }
626
627
    /// @struct SerializedFields
628
    /// Fields written by WireGuardTransportDataLayer's serializeLayer(), in addition to
629
    /// WireGuardLayer::SerializedFields.
630
    struct SerializedFields : WireGuardLayer::SerializedFields
631
    {
632
      /// @return All field descriptors for WireGuardTransportDataLayer
633
      static std::vector<FieldDescriptor> all()
634
0
      {
635
0
        auto result = WireGuardLayer::SerializedFields::all();
636
0
        std::initializer_list<FieldDescriptor> extra{ ReceiverIndex, Counter };
637
0
        std::copy(extra.begin(), extra.end(), std::back_inserter(result));
638
0
        return result;
639
0
      }
640
641
      /// @brief Field descriptor for the receiver index, written as a hex value.
642
      static const FieldDescriptor ReceiverIndex;
643
644
      /// @brief Field descriptor for the counter (nonce), written as a number.
645
      static const FieldDescriptor Counter;
646
    };
647
648
  protected:
649
    void serializeLayer(ObjectScope& serializer) const override;
650
  };
651
}  // namespace pcpp