1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
/* dot11decrypt_gcmp.c
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
/****************************************************************************/
/* File includes */
#include "config.h"
#include "dot11decrypt_debug.h"
#include "dot11decrypt_int.h"
#include "dot11decrypt_system.h"
#include "dot11decrypt_util.h"
#include <wsutil/wsgcrypt.h>
/****************************************************************************/
/* Internal definitions */
/****************************************************************************/
/* Internal macros */
#define READ_6(b0, b1, b2, b3, b4, b5) \
((((uint64_t)((uint16_t)((b4 << 0) | (b5 << 8)))) << 32) | \
((uint32_t)((b0 << 0) | (b1 << 8) | (b2 << 16) | (b3 << 24))))
/****************************************************************************/
/* Internal function prototypes declarations */
/****************************************************************************/
/* Function definitions */
/* From IEEE 802.11 2016 Chapter 12.5.5.3.4 Construct GCM nonce */
static void
gcmp_construct_nonce(
PDOT11DECRYPT_MAC_FRAME wh,
uint64_t pn,
uint8_t nonce[12])
{
/* Nonce: A2 | PN */
DOT11DECRYPT_ADDR_COPY(nonce, wh->addr2);
nonce[6] = (uint8_t)(pn >> 40);
nonce[7] = (uint8_t)(pn >> 32);
nonce[8] = (uint8_t)(pn >> 24);
nonce[9] = (uint8_t)(pn >> 16);
nonce[10] = (uint8_t)(pn >> 8);
nonce[11] = (uint8_t)(pn >> 0);
}
int Dot11DecryptGcmpDecrypt(
uint8_t *m,
int mac_header_len,
int len,
uint8_t *TK1,
int tk_len)
{
PDOT11DECRYPT_MAC_FRAME wh;
uint8_t aad[30];
uint8_t nonce[12];
uint8_t mic[16];
ssize_t data_len;
size_t aad_len;
int z = mac_header_len;
gcry_cipher_hd_t handle;
uint64_t pn;
uint8_t *ivp = m + z;
wh = (PDOT11DECRYPT_MAC_FRAME )m;
data_len = len - (z + DOT11DECRYPT_GCMP_HEADER + sizeof(mic));
if (data_len < 1) {
return 0;
}
memcpy(mic, m + len - sizeof(mic), sizeof(mic));
pn = READ_6(ivp[0], ivp[1], ivp[4], ivp[5], ivp[6], ivp[7]);
gcmp_construct_nonce(wh, pn, nonce);
dot11decrypt_construct_aad(wh, aad, &aad_len);
if (gcry_cipher_open(&handle, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_GCM, 0)) {
return 1;
}
if (gcry_cipher_setkey(handle, TK1, tk_len)) {
goto err_out;
}
if (gcry_cipher_setiv(handle, nonce, sizeof(nonce))) {
goto err_out;
}
if (gcry_cipher_authenticate(handle, aad, aad_len)) {
goto err_out;
}
if (gcry_cipher_decrypt(handle, m + z + DOT11DECRYPT_GCMP_HEADER, data_len, NULL, 0)) {
goto err_out;
}
if (gcry_cipher_checktag(handle, mic, sizeof(mic))) {
goto err_out;
}
/* TODO replay check (IEEE 802.11i-2004, pg. 62) */
/* TODO PN must be incremental (IEEE 802.11i-2004, pg. 62) */
gcry_cipher_close(handle);
return 0;
err_out:
gcry_cipher_close(handle);
return 1;
}
|