dot11decrypt: Export Dot11DecryptDecryptKeyData function

Simplify the still quite complex Dot11DecryptScanEapolForKeys function
and further reduce frame parsing inside Dot11Decrypt engine. This is
done by breaking out the EAPOL keydata decryption step into a new
function Dot11DecryptDecryptKeyData to be called from dissector.

After this Dot11DecryptScanEapolForKeys can now focus on one
task, to scan for keys in (unencrypted) EAPOL key frames.

With keydata decryption step separated from the broadcast
key parsing step the dissectors' GTK parsing can replace
the Dot11Decrypt internal RSN GTK TAG parsing.

Change-Id: I3b89f40586b8b7dbe2ff74cfc30761010d5b80bc
Reviewed-on: https://code.wireshark.org/review/35022
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
Mikael Kanstrup 2019-11-06 13:10:01 +01:00 committed by Anders Broman
parent 4222603a50
commit 820e1c9bee
3 changed files with 224 additions and 201 deletions

View File

@ -161,10 +161,7 @@ static INT Dot11DecryptRsna4WHandshake(
PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
const guint8 *eapol_raw,
DOT11DECRYPT_SEC_ASSOCIATION *sa,
const guint tot_len,
UCHAR *decrypt_data,
guint *decrypt_len,
PDOT11DECRYPT_KEY_ITEM key);
const guint tot_len);
/**
* It checks whether the specified key is corrected or not.
@ -201,6 +198,12 @@ static INT Dot11DecryptGetSa(
DOT11DECRYPT_SEC_ASSOCIATION_ID *id)
;
static PDOT11DECRYPT_SEC_ASSOCIATION
Dot11DecryptGetSaPtr(
PDOT11DECRYPT_CONTEXT ctx,
DOT11DECRYPT_SEC_ASSOCIATION_ID *id)
;
static INT Dot11DecryptStoreSa(
PDOT11DECRYPT_CONTEXT ctx,
DOT11DECRYPT_SEC_ASSOCIATION_ID *id)
@ -375,20 +378,30 @@ Dot11DecryptRc4KeyData(const guint8 *decryption_key, guint decryption_key_len,
return decrypted_key;
}
/* XXX - what if this doesn't get the key? */
static INT
Dot11DecryptDecryptWPABroadcastKey(PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
guint8 *decryption_key,
PDOT11DECRYPT_SEC_ASSOCIATION sa,
guint8 *decrypted_data, guint *decrypted_len)
INT
Dot11DecryptDecryptKeyData(PDOT11DECRYPT_CONTEXT ctx,
PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
const UCHAR bssid[DOT11DECRYPT_MAC_LEN],
const UCHAR sta[DOT11DECRYPT_MAC_LEN],
UCHAR *decrypted_data, guint *decrypted_len,
PDOT11DECRYPT_KEY_ITEM key)
{
guint8 key_version;
const guint8 *key_data;
guint8 *decrypted_key = NULL;
guint16 key_bytes_len = 0; /* Length of the total key data field */
guint16 key_len; /* Actual group key length */
static DOT11DECRYPT_KEY_ITEM dummy_key; /* needed in case Dot11DecryptRsnaMng() wants the key structure */
DOT11DECRYPT_SEC_ASSOCIATION *tmp_sa;
DOT11DECRYPT_SEC_ASSOCIATION_ID id;
PDOT11DECRYPT_SEC_ASSOCIATION sa;
/* search for a cached Security Association for current BSSID and AP */
memcpy(id.bssid, bssid, DOT11DECRYPT_MAC_LEN);
memcpy(id.sta, sta, DOT11DECRYPT_MAC_LEN);
sa = Dot11DecryptGetSaPtr(ctx, &id);
if (sa == NULL || !sa->validKey) {
DEBUG_PRINT_LINE("No valid SA for BSSID found", DEBUG_LEVEL_3);
return DOT11DECRYPT_RET_UNSUCCESS;
}
guint8 *decryption_key = sa->wpa.ptk + 16; /* KEK */
/* We skip verifying the MIC of the key. If we were implementing a WPA supplicant we'd want to verify, but for a sniffer it's not needed. */
@ -404,7 +417,7 @@ Dot11DecryptDecryptWPABroadcastKey(PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
/* AES keys must be at least 128 bits = 16 bytes. */
if (key_bytes_len < 16) {
return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
return DOT11DECRYPT_RET_UNSUCCESS;
}
} else {
/* XXX Ideally group cipher suite type from EAPOL message 2 of 4 should be used to */
@ -413,14 +426,14 @@ Dot11DecryptDecryptWPABroadcastKey(PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
key_bytes_len = eapol_parsed->key_data_len;
if (key_bytes_len < 16) {
return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
return DOT11DECRYPT_RET_UNSUCCESS;
}
}
if ((key_bytes_len < GROUP_KEY_MIN_LEN) ||
(eapol_parsed->len < EAPOL_RSN_KEY_LEN) ||
(key_bytes_len > eapol_parsed->len - EAPOL_RSN_KEY_LEN)) {
return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
return DOT11DECRYPT_RET_UNSUCCESS;
}
/* Encrypted key is in the information element field of the EAPOL key packet */
@ -430,11 +443,6 @@ Dot11DecryptDecryptWPABroadcastKey(PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
DEBUG_DUMP("KeyIV:", eapol_parsed->key_iv, 16);
DEBUG_DUMP("decryption_key:", decryption_key, 16);
/* We are rekeying, save old sa */
tmp_sa=(DOT11DECRYPT_SEC_ASSOCIATION *)g_malloc(sizeof(DOT11DECRYPT_SEC_ASSOCIATION));
memcpy(tmp_sa, sa, sizeof(DOT11DECRYPT_SEC_ASSOCIATION));
sa->next=tmp_sa;
/* As we have no concept of the prior association request at this point, we need to deduce the */
/* group key cipher from the length of the key bytes. In WPA this is straightforward as the */
/* keybytes just contain the GTK, and the GTK is only in the group handshake, NOT the M3. */
@ -459,10 +467,9 @@ Dot11DecryptDecryptWPABroadcastKey(PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
DEBUG_DUMP("FullDecrKey:", new_key, 32);
data = Dot11DecryptRc4KeyData(new_key, 32, key_data, key_bytes_len);
if (!data) {
return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
return DOT11DECRYPT_RET_UNSUCCESS;
}
memcpy(decrypted_data, data, key_bytes_len);
decrypted_key = decrypted_data;
g_free(data);
} else {
/* Ideally AKM from EAPOL message 2 of 4 should be used to determine Key-wrap algoritm to use */
@ -470,90 +477,21 @@ Dot11DecryptDecryptWPABroadcastKey(PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
/* algorithm so no AKM lookup is needed. */
/* AES CCMP key */
guint8 key_found;
guint8 key_length;
guint16 key_index;
guint8 *data;
/* Unwrap the key; the result is key_bytes_len in length */
data = AES_unwrap(decryption_key, 16, key_data, key_bytes_len);
if (!data) {
return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
return DOT11DECRYPT_RET_UNSUCCESS;
}
key_bytes_len -= 8; /* AES-WRAP adds 8 bytes */
memcpy(decrypted_data, data, key_bytes_len);
g_free(data);
/* With WPA2 what we get after Broadcast Key decryption is an actual RSN structure.
The key itself is stored as a GTK KDE
WPA2 IE (1 byte) id = 0xdd, length (1 byte), GTK OUI (4 bytes), key index (1 byte) and 1 reserved byte. Thus we have to
pass pointer to the actual key with 8 bytes offset */
key_found = FALSE;
key_index = 0;
/* Parse Key data until we found GTK KDE */
/* GTK KDE = 00-0F-AC 01 */
while(key_index < (key_bytes_len - 6) && !key_found){
guint8 rsn_id;
guint32 type;
/* Get RSN ID */
rsn_id = decrypted_data[key_index];
type = ((decrypted_data[key_index + 2] << 24) +
(decrypted_data[key_index + 3] << 16) +
(decrypted_data[key_index + 4] << 8) +
(decrypted_data[key_index + 5]));
if (rsn_id == 0xdd && type == 0x000fac01) {
key_found = TRUE;
} else {
key_index += decrypted_data[key_index+1]+2;
}
}
if (key_found){
if (decrypted_data[key_index+1] <= 6) {
return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
}
key_length = decrypted_data[key_index+1] - 6;
if (key_index+8 >= key_bytes_len ||
key_length > key_bytes_len - key_index - 8) {
return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
}
/* Skip over the GTK header info */
decrypted_key = decrypted_data + key_index + 8;
} else {
return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
}
if (key_length == TKIP_GROUP_KEY_LEN)
sa->wpa.key_ver = DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP;
else
sa->wpa.key_ver = DOT11DECRYPT_WPA_KEY_VER_AES_CCMP;
}
key_len = (sa->wpa.key_ver==DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP)?TKIP_GROUP_KEY_LEN:CCMP_GROUP_KEY_LEN;
if (key_len > key_bytes_len) {
/* the key required for this protocol is longer than the key that we just calculated */
return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
}
Dot11DecryptCopyKey(sa, key);
*decrypted_len = key_bytes_len;
/* Decrypted key is now in szEncryptedKey with len of key_len */
DEBUG_DUMP("Broadcast key:", decrypted_key, key_len);
/* Load the proper key material info into the SA */
sa->key = &dummy_key; /* we just need key to be not null because it is checked in Dot11DecryptRsnaMng(). The WPA key materials are actually in the .wpa structure */
sa->validKey = TRUE;
/* Since this is a GTK and its size is only 32 bytes (vs. the 64 byte size of a PTK), we fake it and put it in at a 32-byte offset so the */
/* Dot11DecryptRsnaMng() function will extract the right piece of the GTK for decryption. (The first 16 bytes of the GTK are used for decryption.) */
memset(sa->wpa.ptk, 0, sizeof(sa->wpa.ptk));
memcpy(sa->wpa.ptk+32, decrypted_key, key_len);
return DOT11DECRYPT_RET_SUCCESS_HANDSHAKE;
return DOT11DECRYPT_RET_SUCCESS;
}
@ -697,21 +635,55 @@ INT Dot11DecryptScanTdlsForKeys(
return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
}
static INT
Dot11DecryptCopyBroadcastKey(
PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
PDOT11DECRYPT_SEC_ASSOCIATION broadcast_sa)
{
DOT11DECRYPT_SEC_ASSOCIATION *tmp_sa;
/* We are rekeying, save old sa */
/* TODO Avoid creating SA first time as we're not really rekeying. */
tmp_sa = (DOT11DECRYPT_SEC_ASSOCIATION *)g_malloc(sizeof(DOT11DECRYPT_SEC_ASSOCIATION));
memcpy(tmp_sa, broadcast_sa, sizeof(DOT11DECRYPT_SEC_ASSOCIATION));
broadcast_sa->next = tmp_sa;
if (!eapol_parsed->gtk || eapol_parsed->gtk_len == 0) {
DEBUG_PRINT_LINE("No broadcast key found", DEBUG_LEVEL_3);
return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
}
if (eapol_parsed->gtk_len > DOT11DECRYPT_WPA_PTK_LEN - 32) {
DEBUG_PRINT_LINE("Broadcast key too large", DEBUG_LEVEL_3);
return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
}
if (eapol_parsed->gtk_len == TKIP_GROUP_KEY_LEN) {
broadcast_sa->wpa.key_ver = DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP;
} else {
broadcast_sa->wpa.key_ver = DOT11DECRYPT_WPA_KEY_VER_AES_CCMP;
}
broadcast_sa->validKey = TRUE;
DEBUG_DUMP("Broadcast key:", eapol_parsed->gtk, eapol_parsed->gtk_len);
/* Since this is a GTK and its size is only 32 bytes (vs. the 64 byte size of a PTK),
* we fake it and put it in at a 32-byte offset so the Dot11DecryptRsnaMng() function
* will extract the right piece of the GTK for decryption. (The first 16 bytes of the
* GTK are used for decryption.) */
memset(broadcast_sa->wpa.ptk, 0, sizeof(broadcast_sa->wpa.ptk));
memcpy(broadcast_sa->wpa.ptk + 32, eapol_parsed->gtk, eapol_parsed->gtk_len);
return DOT11DECRYPT_RET_SUCCESS_HANDSHAKE;
}
static int
Dot11DecryptGroupHandshake(
PDOT11DECRYPT_CONTEXT ctx,
PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
const UCHAR bssid[DOT11DECRYPT_MAC_LEN],
const UCHAR sta[DOT11DECRYPT_MAC_LEN],
const guint tot_len,
UCHAR *decrypt_data,
guint *decrypt_len,
PDOT11DECRYPT_KEY_ITEM key)
const guint tot_len)
{
DOT11DECRYPT_SEC_ASSOCIATION_ID id;
PDOT11DECRYPT_SEC_ASSOCIATION broadcast_sa;
PDOT11DECRYPT_SEC_ASSOCIATION sta_sa;
if (GROUP_KEY_PAYLOAD_LEN_MIN > tot_len) {
DEBUG_PRINT_LINE("Message too short for Group Key", DEBUG_LEVEL_3);
@ -733,18 +705,7 @@ Dot11DecryptGroupHandshake(
if (broadcast_sa == NULL){
return DOT11DECRYPT_RET_REQ_DATA;
}
/* Get the SA for the STA, since we need its pairwise key to decrpyt the group key */
memcpy(id.sta, sta, DOT11DECRYPT_MAC_LEN);
sta_sa = Dot11DecryptGetSaPtr(ctx, &id);
if (sta_sa == NULL){
return DOT11DECRYPT_RET_REQ_DATA;
}
/* Try to extract the group key and install it in the SA */
Dot11DecryptCopyKey(sta_sa, key); /* save key used for decrypting broadcast key */
return Dot11DecryptDecryptWPABroadcastKey(eapol_parsed, sta_sa->wpa.ptk + 16,
broadcast_sa, decrypt_data, decrypt_len);
return Dot11DecryptCopyBroadcastKey(eapol_parsed, broadcast_sa);
}
INT Dot11DecryptScanEapolForKeys(
@ -753,10 +714,7 @@ INT Dot11DecryptScanEapolForKeys(
const guint8 *eapol_raw,
const guint tot_len,
const UCHAR bssid[DOT11DECRYPT_MAC_LEN],
const UCHAR sta[DOT11DECRYPT_MAC_LEN],
UCHAR *decrypt_data,
guint *decrypt_len,
PDOT11DECRYPT_KEY_ITEM key)
const UCHAR sta[DOT11DECRYPT_MAC_LEN])
{
DOT11DECRYPT_SEC_ASSOCIATION_ID id;
PDOT11DECRYPT_SEC_ASSOCIATION sa;
@ -790,12 +748,10 @@ INT Dot11DecryptScanEapolForKeys(
case DOT11DECRYPT_HS_MSG_TYPE_4WHS_3:
case DOT11DECRYPT_HS_MSG_TYPE_4WHS_4:
return Dot11DecryptRsna4WHandshake(ctx, eapol_parsed, eapol_raw,
sa, tot_len,
decrypt_data, decrypt_len, key);
sa, tot_len);
case DOT11DECRYPT_HS_MSG_TYPE_GHS_1:
return Dot11DecryptGroupHandshake(ctx, eapol_parsed,
bssid, sta, tot_len,
decrypt_data, decrypt_len, key);
bssid, tot_len);
case DOT11DECRYPT_HS_MSG_TYPE_INVALID:
default:
DEBUG_PRINT_LINE("Invalid message type", DEBUG_LEVEL_3);
@ -1344,10 +1300,7 @@ Dot11DecryptRsna4WHandshake(
PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
const guint8 *eapol_raw,
DOT11DECRYPT_SEC_ASSOCIATION *sa,
const guint tot_len,
UCHAR *decrypt_data,
guint *decrypt_len,
PDOT11DECRYPT_KEY_ITEM key)
const guint tot_len)
{
DOT11DECRYPT_KEY_ITEM *tmp_key, *tmp_pkt_key, pkt_key;
DOT11DECRYPT_SEC_ASSOCIATION *tmp_sa;
@ -1545,10 +1498,8 @@ Dot11DecryptRsna4WHandshake(
if (broadcast_sa == NULL){
return DOT11DECRYPT_RET_REQ_DATA;
}
Dot11DecryptCopyKey(sa, key); /* save key used for decrypting broadcast key */
return Dot11DecryptDecryptWPABroadcastKey(eapol_parsed, sa->wpa.ptk + 16, broadcast_sa,
decrypt_data, decrypt_len);
}
return Dot11DecryptCopyBroadcastKey(eapol_parsed, broadcast_sa);
}
}
/* message 4 */

View File

@ -165,6 +165,8 @@ typedef struct _DOT11DECRYPT_EAPOL_PARSED {
guint8 *nonce;
guint8 *mic;
guint16 mic_len;
guint8 *gtk;
guint16 gtk_len;
} DOT11DECRYPT_EAPOL_PARSED, *PDOT11DECRYPT_EAPOL_PARSED;
/************************************************************************/
@ -223,12 +225,40 @@ extern INT Dot11DecryptDecryptPacket(
PDOT11DECRYPT_KEY_ITEM key)
;
/**
* This will try to decrypt the encrypted keydata field of an EAPOL KEY frame.
* @param ctx [IN] Pointer to the current context
* @param eapol_parsed [IN] Extracted/Parsed pieces of eapol frame
* @param bssid [IN] bssid of AP
* @param sta [IN] sta MAC address
* @param decrypted_data [OUT] Pointer to a buffer that will contain
* decrypted data. Must have room for at least DOT11DECRYPT_EAPOL_MAX_LEN bytes.
* @param decrypted_len [OUT] Length of decrypted data.
* @param key [OUT] Pointer to a preallocated key structure containing
* the key used during the decryption process (if done). If this parameter
* is set to NULL, the key will be not returned.
* @return
* - DOT11DECRYPT_RET_SUCCESS: Decryption has been done (decrypt_data and
* decrypt_length will contain the packet data decrypted and the length of
* the new packet)
* - DOT11DECRYPT_RET_UNSUCCESS: Generic unspecified error (decrypt_data
* and decrypt_length will be not modified).
*/
extern INT
Dot11DecryptDecryptKeyData(PDOT11DECRYPT_CONTEXT ctx,
PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
const UCHAR bssid[DOT11DECRYPT_MAC_LEN],
const UCHAR sta[DOT11DECRYPT_MAC_LEN],
UCHAR *decrypted_data, guint *decrypted_len,
PDOT11DECRYPT_KEY_ITEM key)
;
/**
* This will try to extract keys from an EAPOL frame and add corresponding
* SAs to current context. If the EAPOL frame keydata is encrypted the
* function will try to decrypt it (using already known keys) first before
* extracting further keys. If keydata hard to be decrypted the decrypted
* data will be in decrypt_data buffer.
* SAs to current context. eapol_parsed must contain the already parsed EAPOL
* key frame and for frames that contain encrypted EAPOL keydata the keydata
* must first be decrypted with Dot11DecryptDecryptKeyData before calling this
* function.
* @param ctx [IN] Pointer to the current context
* @param eapol_parsed [IN] Extracted/Parsed pieces of eapol frame
* @param eapol_raw [IN] Pointer to a buffer with an EAPOL frame
@ -249,17 +279,10 @@ extern INT Dot11DecryptDecryptPacket(
* - DOT11DECRYPT_RET_UNSUCCESS: Generic unspecified error (decrypt_data
* and decrypt_length will be not modified).
* - DOT11DECRYPT_RET_SUCCESS_HANDSHAKE: An eapol handshake packet was successfuly parsed
* and key information extracted. The decrypted eapol keydata is copied to
* decrypt_data with keydata len in decrypt_len. key param will contain ptk
* used to decrypt eapol keydata.
* and key information extracted.
* - DOT11DECRYPT_RET_NO_VALID_HANDSHAKE: The handshake is invalid or was not used
* for some reason. For encrypted packets decryption was still successful.
* @note
* The decrypted buffer should be allocated for a size equal or greater
* than the EAPOL keydata buffer size. Before decryption process original
* data is copied in the buffer pointed by decrypt_data not to modify the
* original packet.
* @note
* This function is not thread-safe when used in parallel with context
* management functions on the same context.
*/
@ -269,10 +292,7 @@ extern INT Dot11DecryptScanEapolForKeys(
const guint8 *eapol_raw,
const guint tot_len,
const UCHAR bssid[DOT11DECRYPT_MAC_LEN],
const UCHAR sta[DOT11DECRYPT_MAC_LEN],
UCHAR *decrypt_data,
guint *decrypt_len,
PDOT11DECRYPT_KEY_ITEM key)
const UCHAR sta[DOT11DECRYPT_MAC_LEN])
;
/**

View File

@ -226,6 +226,13 @@ ieee_80211_add_tagged_parameters(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, int tagged_parameters_len, int ftype,
association_sanity_check_t *association_sanity_check);
static void
save_proto_data(tvbuff_t *tvb, packet_info *pinfo, int offset, size_t size, int key);
static void
save_proto_data_value(packet_info *pinfo, guint value, int key);
static void try_scan_tdls_keys(tvbuff_t *tvb, packet_info *pinfo, int offset);
static tvbuff_t *
@ -269,6 +276,8 @@ typedef struct mimo_control
#define KEY_IV_KEY 16
#define KEY_DATA_KEY 17
#define KEY_DATA_LEN_KEY 18
#define GTK_KEY 19
#define GTK_LEN_KEY 20
/* ************************************************************************* */
/* Define some very useful macros that are used to analyze frame types etc. */
@ -13793,7 +13802,8 @@ dissect_vendor_ie_wfa(packet_info *pinfo, proto_item *item, tvbuff_t *tag_tvb)
}
static void
dissect_vendor_ie_rsn(proto_item * item, proto_tree * tree, tvbuff_t * tvb, int offset, guint32 tag_len)
dissect_vendor_ie_rsn(proto_item * item, proto_tree * tree, tvbuff_t * tvb,
int offset, guint32 tag_len, packet_info *pinfo)
{
switch(tvb_get_guint8(tvb, offset)){
@ -13811,6 +13821,8 @@ dissect_vendor_ie_rsn(proto_item * item, proto_tree * tree, tvbuff_t * tvb, int
offset += 1;
proto_tree_add_item(tree, hf_ieee80211_rsn_ie_gtk_key, tvb, offset, tag_len - 3, ENC_NA);
proto_item_append_text(item, ": RSN GTK");
save_proto_data(tvb, pinfo, offset, tag_len - 3, GTK_KEY);
save_proto_data_value(pinfo, tag_len - 3, GTK_LEN_KEY);
break;
}
case 4:
@ -19976,7 +19988,7 @@ ieee80211_tag_vendor_specific_ie(tvbuff_t *tvb, packet_info *pinfo, proto_tree *
dissect_vendor_ie_wpawme(tree, tvb, pinfo, offset, tag_vs_len, field_data->ftype);
break;
case OUI_RSN:
dissect_vendor_ie_rsn(field_data->item_tag, tree, tvb, offset, tag_vs_len);
dissect_vendor_ie_rsn(field_data->item_tag, tree, tvb, offset, tag_vs_len, pinfo);
break;
case OUI_PRE11N:
dissect_vendor_ie_ht(tvb, pinfo, tree, offset, field_data->item_tag, field_data->item_tag_length, tag_vs_len);
@ -25673,57 +25685,70 @@ keydata_padding_len(tvbuff_t *tvb)
}
static void
try_scan_eapol_keys(packet_info *pinfo, DOT11DECRYPT_HS_MSG_TYPE msg_type)
get_eapol_parsed(packet_info *pinfo, PDOT11DECRYPT_EAPOL_PARSED eapol_parsed)
{
guint32 dec_caplen = 0;
if (!eapol_parsed) {
return;
}
proto_eapol_key_frame_t *eapol_key =
(proto_eapol_key_frame_t *)p_get_proto_data(pinfo->pool, pinfo, proto_eapol,
EAPOL_KEY_FRAME_KEY);
if (!eapol_key) {
return;
}
eapol_parsed->len = eapol_key->len;
eapol_parsed->key_type = eapol_key->type;
eapol_parsed->key_version = (guint8)
GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_wlan, KEY_VERSION_KEY));
eapol_parsed->key_len = (guint16)
GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_wlan, KEY_LEN_KEY));
eapol_parsed->key_iv = (guint8 *)p_get_proto_data(pinfo->pool, pinfo, proto_wlan, KEY_IV_KEY);
eapol_parsed->key_data = (guint8 *)p_get_proto_data(pinfo->pool, pinfo, proto_wlan, KEY_DATA_KEY);
eapol_parsed->key_data_len = (guint16)
GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_wlan, KEY_DATA_LEN_KEY));
eapol_parsed->nonce = (guint8 *)p_get_proto_data(pinfo->pool, pinfo, proto_wlan, NONCE_KEY);
eapol_parsed->group_cipher = (guint8)
GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_wlan, GROUP_CIPHER_KEY));
eapol_parsed->cipher = (guint8)
GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_wlan, CIPHER_KEY));
eapol_parsed->akm = (guint8)
GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_wlan, AKM_KEY));
eapol_parsed->mic = (guint8 *)p_get_proto_data(pinfo->pool, pinfo, proto_wlan, MIC_KEY);
eapol_parsed->mic_len =
GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_wlan, MIC_LEN_KEY));
eapol_parsed->gtk = (guint8 *)p_get_proto_data(pinfo->pool, pinfo, proto_wlan, GTK_KEY);
eapol_parsed->gtk_len = (guint16)
GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_wlan, GTK_LEN_KEY));
}
static void
try_decrypt_keydata(packet_info *pinfo)
{
guint32 dec_caplen;
guchar dec_data[DOT11DECRYPT_EAPOL_MAX_LEN];
DOT11DECRYPT_EAPOL_PARSED eapol_parsed;
DOT11DECRYPT_KEY_ITEM used_key;
if (!enable_decryption) {
return;
}
proto_eapol_key_frame_t *eapol_key =
(proto_eapol_key_frame_t *)p_get_proto_data(pinfo->pool, pinfo, proto_eapol,
EAPOL_KEY_FRAME_KEY);
guint8 *bssid = (guint8 *)p_get_proto_data(pinfo->pool, pinfo, proto_wlan, BSSID_KEY);
guint8 *sta = (guint8 *)p_get_proto_data(pinfo->pool, pinfo, proto_wlan, STA_KEY);
DOT11DECRYPT_EAPOL_PARSED eapol_parsed;
memset(&eapol_parsed, 0, sizeof(eapol_parsed));
eapol_parsed.msg_type = msg_type;
eapol_parsed.len = eapol_key->len;
eapol_parsed.key_type = eapol_key->type;
eapol_parsed.key_version = (guint8)
GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_wlan, KEY_VERSION_KEY));
eapol_parsed.key_len = (guint16)
GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_wlan, KEY_LEN_KEY));
eapol_parsed.key_iv = (guint8 *)p_get_proto_data(pinfo->pool, pinfo, proto_wlan, KEY_IV_KEY);
eapol_parsed.key_data = (guint8 *)p_get_proto_data(pinfo->pool, pinfo, proto_wlan, KEY_DATA_KEY);
eapol_parsed.key_data_len = (guint16)
GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_wlan, KEY_DATA_LEN_KEY));
eapol_parsed.nonce = (guint8 *)p_get_proto_data(pinfo->pool, pinfo, proto_wlan, NONCE_KEY);
eapol_parsed.group_cipher = (guint8)
GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_wlan, GROUP_CIPHER_KEY));
eapol_parsed.cipher = (guint8)
GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_wlan, CIPHER_KEY));
eapol_parsed.akm = (guint8)
GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_wlan, AKM_KEY));
eapol_parsed.mic = (guint8 *)p_get_proto_data(pinfo->pool, pinfo, proto_wlan, MIC_KEY);
eapol_parsed.mic_len =
GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_wlan, MIC_LEN_KEY));
if (!eapol_key || !bssid || !sta) {
if (!bssid || !sta) {
return;
}
gint ret = Dot11DecryptScanEapolForKeys(&dot11decrypt_ctx,
&eapol_parsed,
eapol_key->data, eapol_key->len,
bssid, sta,
dec_data, &dec_caplen,
&used_key);
if (ret == DOT11DECRYPT_RET_SUCCESS_HANDSHAKE && dec_caplen > 0) {
memset(&eapol_parsed, 0, sizeof(eapol_parsed));
get_eapol_parsed(pinfo, &eapol_parsed);
gint ret = Dot11DecryptDecryptKeyData(&dot11decrypt_ctx,
&eapol_parsed,
bssid, sta,
dec_data, &dec_caplen,
&used_key);
if (ret == DOT11DECRYPT_RET_SUCCESS && dec_caplen > 0) {
proto_eapol_keydata_t *eapol = wmem_new(wmem_file_scope(), proto_eapol_keydata_t);
eapol->used_key = used_key;
eapol->keydata_len = dec_caplen;
@ -25734,6 +25759,35 @@ try_scan_eapol_keys(packet_info *pinfo, DOT11DECRYPT_HS_MSG_TYPE msg_type)
}
}
static void
try_scan_eapol_keys(packet_info *pinfo, DOT11DECRYPT_HS_MSG_TYPE msg_type)
{
DOT11DECRYPT_EAPOL_PARSED eapol_parsed;
if (!enable_decryption) {
return;
}
proto_eapol_key_frame_t *eapol_key =
(proto_eapol_key_frame_t *)p_get_proto_data(pinfo->pool, pinfo, proto_eapol,
EAPOL_KEY_FRAME_KEY);
guint8 *bssid = (guint8 *)p_get_proto_data(pinfo->pool, pinfo, proto_wlan, BSSID_KEY);
guint8 *sta = (guint8 *)p_get_proto_data(pinfo->pool, pinfo, proto_wlan, STA_KEY);
if (!eapol_key || !bssid || !sta) {
return;
}
memset(&eapol_parsed, 0, sizeof(eapol_parsed));
get_eapol_parsed(pinfo, &eapol_parsed);
eapol_parsed.msg_type = msg_type;
Dot11DecryptScanEapolForKeys(&dot11decrypt_ctx,
&eapol_parsed,
eapol_key->data, eapol_key->len,
bssid, sta);
}
static int
dissect_wlan_rsna_eapol_wpa_or_rsn_key(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
@ -25834,7 +25888,6 @@ dissect_wlan_rsna_eapol_wpa_or_rsn_key(tvbuff_t *tvb, packet_info *pinfo, proto_
proto_item_set_generated(ti);
guint16 keydes_version = tvb_get_ntohs(tvb, offset) & KEY_INFO_KEYDES_VERSION_MASK;
guint16 key_encrypted = tvb_get_ntohs(tvb, offset) & KEY_INFO_ENCRYPTED_KEY_DATA_MASK;
save_proto_data_value(pinfo, keydes_version, KEY_VERSION_KEY);
proto_tree_add_bitmask_with_flags(tree, tvb, offset, hf_wlan_rsna_eapol_wpa_keydes_keyinfo,
ett_keyinfo, wlan_rsna_eapol_wpa_keydes_keyinfo,
@ -25879,14 +25932,6 @@ dissect_wlan_rsna_eapol_wpa_or_rsn_key(tvbuff_t *tvb, packet_info *pinfo, proto_
if (eapol_data_len != 0) {
save_proto_data(tvb, pinfo, offset, eapol_data_len, KEY_DATA_KEY);
}
if (!pinfo->fd->visited && key_encrypted && msg_type != DOT11DECRYPT_HS_MSG_TYPE_INVALID) {
/* Key data is encrypted so let dot11decrypt engine decrypt and extract the keys
* If successful the SA is stored in dot11decrypt context and decrypted key data
* is available in EAPOL_KEY proto data.
*/
try_scan_eapol_keys(pinfo, msg_type);
}
if (eapol_data_len != 0) {
ti = proto_tree_add_item(tree, hf_wlan_rsna_eapol_wpa_keydes_data,
tvb, offset, eapol_data_len, ENC_NA);
@ -25894,10 +25939,14 @@ dissect_wlan_rsna_eapol_wpa_or_rsn_key(tvbuff_t *tvb, packet_info *pinfo, proto_
!(keyinfo & KEY_INFO_KEY_TYPE_MASK)) {
/* RSN: EAPOL-Key Key Data is encrypted.
* WPA: Group Keys use encrypted Key Data.
* Decryption engine has already tried to decrypt this. If decrypted it's
* stored in EAPOL_KEY proto data.
* IEEE 802.11i-2004 8.5.2.
* Let decryption engine try to decrypt this and if successful it's
* stored in EAPOL_KEY proto data.
*/
if (!pinfo->fd->visited) {
try_decrypt_keydata(pinfo);
}
proto_eapol_keydata_t *eapol;
eapol = (proto_eapol_keydata_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_wlan, EAPOL_KEY);
@ -25910,6 +25959,8 @@ dissect_wlan_rsna_eapol_wpa_or_rsn_key(tvbuff_t *tvb, packet_info *pinfo, proto_
if (keydes_version == KEYDES_VER_TYPE1) {
add_new_data_source(pinfo, next_tvb, "Decrypted RC4 keydata");
save_proto_data(next_tvb, pinfo, 0, keydata_len, GTK_KEY);
save_proto_data_value(pinfo, keydata_len, GTK_LEN_KEY);
} else {
add_new_data_source(pinfo, next_tvb, "Decrypted AES keydata");
int padding_len = keydata_padding_len(next_tvb);
@ -25940,8 +25991,9 @@ dissect_wlan_rsna_eapol_wpa_or_rsn_key(tvbuff_t *tvb, packet_info *pinfo, proto_
-1, NULL);
}
}
if (!pinfo->fd->visited && !key_encrypted && msg_type != DOT11DECRYPT_HS_MSG_TYPE_INVALID) {
/* Key data was not encrypted so let dot11decrypt engine extract the keys now that
if (!pinfo->fd->visited && msg_type != DOT11DECRYPT_HS_MSG_TYPE_INVALID) {
/* Key data at this pointer was either not encrypted or dot11decrypt
* engine has tried to decrypt keydata. Try to extract the keys now that
* all fields from the EAPOL frame have been parsed.
*/
try_scan_eapol_keys(pinfo, msg_type);