Coverage Report

Created: 2025-07-11 07:47

/src/PcapPlusPlus/Packet++/src/WireGuardLayer.cpp
Line
Count
Source (jump to first uncovered line)
1
#define LOG_MODULE PacketLogModuleWireGuardLayer
2
3
#include "UdpLayer.h"
4
#include "WireGuardLayer.h"
5
#include "EndianPortable.h"
6
#include <iomanip>
7
8
namespace pcpp
9
{
10
  WireGuardLayer* WireGuardLayer::parseWireGuardLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
11
430
  {
12
430
    if (dataLen < sizeof(WireGuardLayer::wg_common_header))
13
0
      return nullptr;
14
430
    wg_common_header* wgHeader = reinterpret_cast<wg_common_header*>(data);
15
16
430
    switch (wgHeader->messageType)
17
430
    {
18
75
    case static_cast<uint8_t>(WireGuardMessageType::HandshakeInitiation):
19
75
      return new WireGuardHandshakeInitiationLayer(data, dataLen, prevLayer, packet);
20
55
    case static_cast<uint8_t>(WireGuardMessageType::HandshakeResponse):
21
55
      return new WireGuardHandshakeResponseLayer(data, dataLen, prevLayer, packet);
22
5
    case static_cast<uint8_t>(WireGuardMessageType::CookieReply):
23
5
      return new WireGuardCookieReplyLayer(data, dataLen, prevLayer, packet);
24
295
    case static_cast<uint8_t>(WireGuardMessageType::TransportData):
25
295
      return new WireGuardTransportDataLayer(data, dataLen, prevLayer, packet);
26
0
    default:
27
0
      return nullptr;
28
430
    }
29
430
  }
30
31
  std::string WireGuardLayer::getMessageTypeAsString() const
32
172
  {
33
172
    uint32_t messageType = getMessageType();
34
172
    switch (messageType)
35
172
    {
36
30
    case static_cast<uint8_t>(WireGuardMessageType::HandshakeInitiation):
37
30
      return "Handshake Initiation";
38
22
    case static_cast<uint8_t>(WireGuardMessageType::HandshakeResponse):
39
22
      return "Handshake Response";
40
2
    case static_cast<uint8_t>(WireGuardMessageType::CookieReply):
41
2
      return "Cookie Reply";
42
118
    case static_cast<uint8_t>(WireGuardMessageType::TransportData):
43
118
      return "Transport Data";
44
0
    default:
45
0
      return "Unknown";
46
172
    }
47
172
  }
48
49
  std::string WireGuardLayer::toString() const
50
172
  {
51
172
    return "WireGuard Layer, " + getMessageTypeAsString() + " message";
52
172
  }
53
54
  size_t WireGuardLayer::getHeaderLen() const
55
86
  {
56
86
    return m_DataLen;
57
86
  }
58
59
  uint8_t WireGuardLayer::getMessageType() const
60
172
  {
61
172
    return getBasicHeader()->messageType;
62
172
  }
63
64
  uint32_t WireGuardLayer::getReserved() const
65
0
  {
66
0
    uint32_t reservedValue = 0;
67
0
    memcpy(&reservedValue, getBasicHeader()->reserved, 3);
68
0
    return be32toh(reservedValue);
69
0
  }
70
71
  void WireGuardLayer::setReserved(const std::array<uint8_t, 3>& reserved)
72
0
  {
73
0
    wg_common_header* msg = reinterpret_cast<wg_common_header*>(m_Data);
74
0
    memcpy(msg->reserved, reserved.data(), 3);
75
0
  }
76
77
  bool WireGuardLayer::isDataValid(const uint8_t* data, size_t dataLen)
78
445
  {
79
445
    if (dataLen < sizeof(WireGuardLayer::wg_common_header))
80
0
      return false;
81
82
445
    uint8_t messageType = data[0];
83
445
    return messageType >= static_cast<uint8_t>(WireGuardLayer::WireGuardMessageType::HandshakeInitiation) &&
84
445
           messageType <= static_cast<uint8_t>(WireGuardLayer::WireGuardMessageType::TransportData);
85
445
  }
86
87
  // ~~~~~~~~~~~~~~~~~~~~
88
  // WireGuardHandshakeInitiationLayer
89
  // ~~~~~~~~~~~~~~~~~~~~
90
91
  WireGuardHandshakeInitiationLayer::WireGuardHandshakeInitiationLayer(uint32_t senderIndex,
92
                                                                       const uint8_t initiatorEphemeral[32],
93
                                                                       const uint8_t encryptedInitiatorStatic[48],
94
                                                                       const uint8_t encryptedTimestamp[28],
95
                                                                       const uint8_t mac1[16], const uint8_t mac2[16])
96
0
  {
97
0
    const size_t messageLen = sizeof(wg_handshake_initiation);
98
0
    m_DataLen = messageLen;
99
0
    m_Data = new uint8_t[messageLen];
100
0
    memset(m_Data, 0, messageLen);
101
102
0
    wg_handshake_initiation* msg = reinterpret_cast<wg_handshake_initiation*>(m_Data);
103
104
0
    msg->messageType = static_cast<uint8_t>(WireGuardMessageType::HandshakeInitiation);
105
0
    memset(msg->reserved, 0, 3);
106
0
    msg->senderIndex = htobe32(senderIndex);
107
108
0
    memcpy(msg->initiatorEphemeral, initiatorEphemeral, 32);
109
0
    memcpy(msg->encryptedInitiatorStatic, encryptedInitiatorStatic, 48);
110
0
    memcpy(msg->encryptedTimestamp, encryptedTimestamp, 28);
111
0
    memcpy(msg->mac1, mac1, 16);
112
0
    memcpy(msg->mac2, mac2, 16);
113
114
0
    m_Protocol = WireGuard;
115
0
  }
116
117
  uint32_t WireGuardHandshakeInitiationLayer::getSenderIndex() const
118
0
  {
119
0
    return be32toh(getHandshakeInitiationHeader()->senderIndex);
120
0
  }
121
122
  std::array<uint8_t, 32> WireGuardHandshakeInitiationLayer::getInitiatorEphemeral() const
123
0
  {
124
0
    std::array<uint8_t, 32> ephemeralArray;
125
0
    memcpy(ephemeralArray.data(), getHandshakeInitiationHeader()->initiatorEphemeral, 32);
126
0
    return ephemeralArray;
127
0
  }
128
129
  std::array<uint8_t, 48> WireGuardHandshakeInitiationLayer::getEncryptedInitiatorStatic() const
130
0
  {
131
0
    std::array<uint8_t, 48> initArray;
132
0
    memcpy(initArray.data(), getHandshakeInitiationHeader()->encryptedInitiatorStatic, 48);
133
0
    return initArray;
134
0
  }
135
136
  std::array<uint8_t, 28> WireGuardHandshakeInitiationLayer::getEncryptedTimestamp() const
137
0
  {
138
0
    std::array<uint8_t, 28> tsArray;
139
0
    memcpy(tsArray.data(), getHandshakeInitiationHeader()->encryptedTimestamp, 28);
140
0
    return tsArray;
141
0
  }
142
143
  std::array<uint8_t, 16> WireGuardHandshakeInitiationLayer::getMac1() const
144
0
  {
145
0
    std::array<uint8_t, 16> mac1Array;
146
0
    memcpy(mac1Array.data(), getHandshakeInitiationHeader()->mac1, 16);
147
0
    return mac1Array;
148
0
  }
149
150
  std::array<uint8_t, 16> WireGuardHandshakeInitiationLayer::getMac2() const
151
0
  {
152
0
    std::array<uint8_t, 16> mac2Array;
153
0
    memcpy(mac2Array.data(), getHandshakeInitiationHeader()->mac2, 16);
154
0
    return mac2Array;
155
0
  }
156
157
  void WireGuardHandshakeInitiationLayer::setSenderIndex(uint32_t senderIndex)
158
0
  {
159
0
    wg_handshake_initiation* msg = reinterpret_cast<wg_handshake_initiation*>(m_Data);
160
0
    msg->senderIndex = htobe32(senderIndex);
161
0
  }
162
163
  void WireGuardHandshakeInitiationLayer::setInitiatorEphemeral(const std::array<uint8_t, 32>& initiatorEphemeral)
164
0
  {
165
0
    wg_handshake_initiation* msg = reinterpret_cast<wg_handshake_initiation*>(m_Data);
166
0
    memcpy(msg->initiatorEphemeral, initiatorEphemeral.data(), 32);
167
0
  }
168
169
  void WireGuardHandshakeInitiationLayer::setEncryptedInitiatorStatic(
170
      const std::array<uint8_t, 48>& encryptedInitiatorStatic)
171
0
  {
172
0
    wg_handshake_initiation* msg = reinterpret_cast<wg_handshake_initiation*>(m_Data);
173
0
    memcpy(msg->encryptedInitiatorStatic, encryptedInitiatorStatic.data(), 48);
174
0
  }
175
176
  void WireGuardHandshakeInitiationLayer::setEncryptedTimestamp(const std::array<uint8_t, 28>& encryptedTimestamp)
177
0
  {
178
0
    wg_handshake_initiation* msg = reinterpret_cast<wg_handshake_initiation*>(m_Data);
179
0
    memcpy(msg->encryptedTimestamp, encryptedTimestamp.data(), 28);
180
0
  }
181
182
  void WireGuardHandshakeInitiationLayer::setMac1(const std::array<uint8_t, 16>& mac1)
183
0
  {
184
0
    wg_handshake_initiation* msg = reinterpret_cast<wg_handshake_initiation*>(m_Data);
185
0
    memcpy(msg->mac1, mac1.data(), 16);
186
0
  }
187
188
  void WireGuardHandshakeInitiationLayer::setMac2(const std::array<uint8_t, 16>& mac2)
189
0
  {
190
0
    wg_handshake_initiation* msg = reinterpret_cast<wg_handshake_initiation*>(m_Data);
191
0
    memcpy(msg->mac2, mac2.data(), 16);
192
0
  }
193
194
  // ~~~~~~~~~~~~~~~~~~~~
195
  // WireGuardHandshakeResponseLayer
196
  // ~~~~~~~~~~~~~~~~~~~~
197
198
  WireGuardHandshakeResponseLayer::WireGuardHandshakeResponseLayer(uint32_t senderIndex, uint32_t receiverIndex,
199
                                                                   const uint8_t responderEphemeral[32],
200
                                                                   const uint8_t encryptedEmpty[16],
201
                                                                   const uint8_t mac1[16], const uint8_t mac2[16])
202
0
  {
203
0
    const size_t messageLen = sizeof(wg_handshake_response);
204
0
    m_DataLen = messageLen;
205
0
    m_Data = new uint8_t[messageLen];
206
0
    wg_handshake_response* msg = reinterpret_cast<wg_handshake_response*>(m_Data);
207
208
0
    msg->messageType = static_cast<uint8_t>(WireGuardMessageType::HandshakeResponse);
209
0
    memset(msg->reserved, 0, 3);
210
0
    msg->senderIndex = htobe32(senderIndex);
211
0
    msg->receiverIndex = htobe32(receiverIndex);
212
0
    memcpy(msg->responderEphemeral, responderEphemeral, 32);
213
0
    memcpy(msg->encryptedEmpty, encryptedEmpty, 16);
214
0
    memcpy(msg->mac1, mac1, 16);
215
0
    memcpy(msg->mac2, mac2, 16);
216
217
0
    m_Protocol = WireGuard;
218
0
  }
219
220
  uint32_t WireGuardHandshakeResponseLayer::getSenderIndex() const
221
0
  {
222
0
    return be32toh(getHandshakeResponseHeader()->senderIndex);
223
0
  }
224
225
  uint32_t WireGuardHandshakeResponseLayer::getReceiverIndex() const
226
0
  {
227
0
    return be32toh(getHandshakeResponseHeader()->receiverIndex);
228
0
  }
229
230
  std::array<uint8_t, 32> WireGuardHandshakeResponseLayer::getResponderEphemeral() const
231
0
  {
232
0
    std::array<uint8_t, 32> responderEphemeralArray;
233
0
    memcpy(responderEphemeralArray.data(), getHandshakeResponseHeader()->responderEphemeral, 32);
234
0
    return responderEphemeralArray;
235
0
  }
236
237
  std::array<uint8_t, 16> WireGuardHandshakeResponseLayer::getEncryptedEmpty() const
238
0
  {
239
0
    std::array<uint8_t, 16> encryptedEmptyArray;
240
0
    memcpy(encryptedEmptyArray.data(), getHandshakeResponseHeader()->encryptedEmpty, 16);
241
0
    return encryptedEmptyArray;
242
0
  }
243
244
  std::array<uint8_t, 16> WireGuardHandshakeResponseLayer::getMac1() const
245
0
  {
246
0
    std::array<uint8_t, 16> mac1Array;
247
0
    memcpy(mac1Array.data(), getHandshakeResponseHeader()->mac1, 16);
248
0
    return mac1Array;
249
0
  }
250
251
  std::array<uint8_t, 16> WireGuardHandshakeResponseLayer::getMac2() const
252
0
  {
253
0
    std::array<uint8_t, 16> mac2Array;
254
0
    memcpy(mac2Array.data(), getHandshakeResponseHeader()->mac2, 16);
255
0
    return mac2Array;
256
0
  }
257
258
  void WireGuardHandshakeResponseLayer::setSenderIndex(uint32_t senderIndex)
259
0
  {
260
261
0
    wg_handshake_response* msg = reinterpret_cast<wg_handshake_response*>(m_Data);
262
0
    msg->senderIndex = htobe32(senderIndex);
263
0
  }
264
265
  void WireGuardHandshakeResponseLayer::setReceiverIndex(uint32_t receiverIndex)
266
0
  {
267
0
    wg_handshake_response* msg = reinterpret_cast<wg_handshake_response*>(m_Data);
268
0
    msg->receiverIndex = htobe32(receiverIndex);
269
0
  }
270
271
  void WireGuardHandshakeResponseLayer::setResponderEphemeral(const std::array<uint8_t, 32>& responderEphemeral)
272
0
  {
273
0
    wg_handshake_response* msg = reinterpret_cast<wg_handshake_response*>(m_Data);
274
0
    memcpy(msg->responderEphemeral, responderEphemeral.data(), 32);
275
0
  }
276
277
  void WireGuardHandshakeResponseLayer::setEncryptedEmpty(const std::array<uint8_t, 16>& encryptedEmpty)
278
0
  {
279
0
    wg_handshake_response* msg = reinterpret_cast<wg_handshake_response*>(m_Data);
280
0
    memcpy(msg->encryptedEmpty, encryptedEmpty.data(), 16);
281
0
  }
282
283
  void WireGuardHandshakeResponseLayer::setMac1(const std::array<uint8_t, 16>& mac1)
284
0
  {
285
0
    wg_handshake_response* msg = reinterpret_cast<wg_handshake_response*>(m_Data);
286
0
    memcpy(msg->mac1, mac1.data(), 16);
287
0
  }
288
289
  void WireGuardHandshakeResponseLayer::setMac2(const std::array<uint8_t, 16>& mac2)
290
0
  {
291
0
    wg_handshake_response* msg = reinterpret_cast<wg_handshake_response*>(m_Data);
292
0
    memcpy(msg->mac2, mac2.data(), 16);
293
0
  }
294
295
  // ~~~~~~~~~~~~~~~~~~~~
296
  // WireGuardCookieReplyLayer
297
  // ~~~~~~~~~~~~~~~~~~~~
298
299
  WireGuardCookieReplyLayer::WireGuardCookieReplyLayer(uint32_t receiverIndex, const uint8_t nonce[24],
300
                                                       const uint8_t encryptedCookie[32])
301
0
  {
302
0
    const size_t messageLen = sizeof(wg_cookie_reply);
303
0
    m_DataLen = messageLen;
304
0
    m_Data = new uint8_t[messageLen];
305
0
    memset(m_Data, 0, messageLen);
306
307
0
    wg_cookie_reply* msg = reinterpret_cast<wg_cookie_reply*>(m_Data);
308
309
0
    msg->messageType = static_cast<uint8_t>(WireGuardMessageType::CookieReply);
310
0
    memset(msg->reserved, 0, 3);
311
0
    msg->receiverIndex = htobe32(receiverIndex);
312
0
    memcpy(msg->nonce, nonce, 24);
313
0
    memcpy(msg->encryptedCookie, encryptedCookie, 32);
314
315
0
    m_Protocol = WireGuard;
316
0
  }
317
318
  uint32_t WireGuardCookieReplyLayer::getReceiverIndex() const
319
0
  {
320
0
    return be32toh(getCookieReplyHeader()->receiverIndex);
321
0
  }
322
323
  std::array<uint8_t, 24> WireGuardCookieReplyLayer::getNonce() const
324
0
  {
325
0
    std::array<uint8_t, 24> nonceArray;
326
0
    memcpy(nonceArray.data(), getCookieReplyHeader()->nonce, 24);
327
0
    return nonceArray;
328
0
  }
329
330
  std::array<uint8_t, 32> WireGuardCookieReplyLayer::getEncryptedCookie() const
331
0
  {
332
0
    std::array<uint8_t, 32> encryptedCookieArray;
333
0
    memcpy(encryptedCookieArray.data(), getCookieReplyHeader()->encryptedCookie, 32);
334
0
    return encryptedCookieArray;
335
0
  }
336
337
  void WireGuardCookieReplyLayer::setReceiverIndex(uint32_t receiverIndex)
338
0
  {
339
0
    wg_cookie_reply* msg = reinterpret_cast<wg_cookie_reply*>(m_Data);
340
0
    msg->receiverIndex = htobe32(receiverIndex);
341
0
  }
342
343
  void WireGuardCookieReplyLayer::setNonce(const std::array<uint8_t, 24>& nonce)
344
0
  {
345
0
    wg_cookie_reply* msg = reinterpret_cast<wg_cookie_reply*>(m_Data);
346
0
    memcpy(msg->nonce, nonce.data(), 24);
347
0
  }
348
349
  void WireGuardCookieReplyLayer::setEncryptedCookie(const std::array<uint8_t, 32>& encryptedCookie)
350
0
  {
351
0
    wg_cookie_reply* msg = reinterpret_cast<wg_cookie_reply*>(m_Data);
352
0
    memcpy(msg->encryptedCookie, encryptedCookie.data(), 32);
353
0
  }
354
355
  // ~~~~~~~~~~~~~~~~~~~~
356
  // WireGuardTransportDataLayer
357
  // ~~~~~~~~~~~~~~~~~~~~
358
359
  WireGuardTransportDataLayer::WireGuardTransportDataLayer(uint32_t receiverIndex, uint64_t counter,
360
                                                           const uint8_t* encryptedData, size_t encryptedDataLen)
361
0
  {
362
0
    const size_t messageLen = sizeof(wg_transport_data) + encryptedDataLen;
363
0
    m_DataLen = messageLen;
364
0
    m_Data = new uint8_t[messageLen];
365
0
    memset(m_Data, 0, messageLen);
366
367
0
    wg_transport_data* msg = reinterpret_cast<wg_transport_data*>(m_Data);
368
369
0
    msg->messageType = static_cast<uint8_t>(WireGuardMessageType::TransportData);
370
0
    memset(msg->reserved, 0, 3);
371
0
    msg->receiverIndex = htobe32(receiverIndex);
372
0
    msg->counter = htobe64(counter);
373
0
    memcpy(m_Data + sizeof(wg_transport_data), encryptedData, encryptedDataLen);
374
375
0
    m_Protocol = WireGuard;
376
0
  }
377
378
  uint32_t WireGuardTransportDataLayer::getReceiverIndex() const
379
0
  {
380
0
    return be32toh(getTransportHeader()->receiverIndex);
381
0
  }
382
383
  uint64_t WireGuardTransportDataLayer::getCounter() const
384
0
  {
385
0
    return be64toh(getTransportHeader()->counter);
386
0
  }
387
388
  const uint8_t* WireGuardTransportDataLayer::getEncryptedData() const
389
0
  {
390
0
    return getTransportHeader()->encryptedData;
391
0
  }
392
393
  void WireGuardTransportDataLayer::setReceiverIndex(uint32_t receiverIndex)
394
0
  {
395
0
    wg_transport_data* msg = reinterpret_cast<wg_transport_data*>(m_Data);
396
0
    msg->receiverIndex = htobe32(receiverIndex);
397
0
  }
398
399
  void WireGuardTransportDataLayer::setCounter(uint64_t counter)
400
0
  {
401
0
    wg_transport_data* msg = reinterpret_cast<wg_transport_data*>(m_Data);
402
0
    msg->counter = htobe64(counter);
403
0
  }
404
405
  void WireGuardTransportDataLayer::setEncryptedData(const uint8_t* encryptedData, size_t encryptedDataLen)
406
0
  {
407
0
    wg_transport_data* msg = reinterpret_cast<wg_transport_data*>(m_Data);
408
0
    memcpy(msg->encryptedData, encryptedData, encryptedDataLen);
409
0
  }
410
411
}  // namespace pcpp