cf4c0552e7
Add support for decrypting GCMP/GCMP-256 encrypted IEEE 802.11 traffic Bug: 16197 Change-Id: I907d772665141c8be10a9f4a187bd76594c8d2e4 Reviewed-on: https://code.wireshark.org/review/36346 Petri-Dish: Peter Wu <peter@lekensteyn.nl> Tested-by: Petri Dish Buildbot Reviewed-by: Peter Wu <peter@lekensteyn.nl>
112 lines
2.8 KiB
C
112 lines
2.8 KiB
C
/* 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 <glib.h>
|
|
#include <wsutil/wsgcrypt.h>
|
|
|
|
/****************************************************************************/
|
|
/* Internal definitions */
|
|
|
|
/****************************************************************************/
|
|
/* Internal macros */
|
|
|
|
#define READ_6(b0, b1, b2, b3, b4, b5) \
|
|
((((guint64)((guint16)((b4 << 0) | (b5 << 8)))) << 32) | \
|
|
((guint32)((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,
|
|
guint64 pn,
|
|
guint8 nonce[12])
|
|
{
|
|
/* Nonce: A2 | PN */
|
|
DOT11DECRYPT_ADDR_COPY(nonce, wh->addr2);
|
|
nonce[6] = (guint8)(pn >> 40);
|
|
nonce[7] = (guint8)(pn >> 32);
|
|
nonce[8] = (guint8)(pn >> 24);
|
|
nonce[9] = (guint8)(pn >> 16);
|
|
nonce[10] = (guint8)(pn >> 8);
|
|
nonce[11] = (guint8)(pn >> 0);
|
|
}
|
|
|
|
int Dot11DecryptGcmpDecrypt(
|
|
guint8 *m,
|
|
int mac_header_len,
|
|
int len,
|
|
guint8 *TK1,
|
|
int tk_len)
|
|
{
|
|
PDOT11DECRYPT_MAC_FRAME wh;
|
|
guint8 aad[30];
|
|
guint8 nonce[12];
|
|
guint8 mic[16];
|
|
ssize_t data_len;
|
|
size_t aad_len;
|
|
int z = mac_header_len;
|
|
gcry_cipher_hd_t handle;
|
|
guint64 pn;
|
|
guint8 *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;
|
|
}
|