aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
Diffstat (limited to 'epan')
-rw-r--r--epan/crypt/airpdcap.c54
1 files changed, 41 insertions, 13 deletions
diff --git a/epan/crypt/airpdcap.c b/epan/crypt/airpdcap.c
index 051ee6cf82..1d920c6ff3 100644
--- a/epan/crypt/airpdcap.c
+++ b/epan/crypt/airpdcap.c
@@ -282,6 +282,16 @@ typedef struct {
#define EAPKEY_MIC_LEN 16 /* length of the MIC key for EAPoL_Key packet's MIC using MD5 */
#define NONCE_LEN 32
+#define TKIP_GROUP_KEY_LEN 32
+#define CCMP_GROUP_KEY_LEN 16
+/* Minimum size of the key bytes payload for a TKIP group key in an M3 message*/
+#define TKIP_GROUP_KEYBYTES_LEN ( sizeof(RSN_IE) + 8 + TKIP_GROUP_KEY_LEN + 6 ) /* 72 */
+/* arbitrary upper limit */
+#define TKIP_GROUP_KEYBYTES_LEN_MAX ( TKIP_GROUP_KEYBYTES_LEN + 28 )
+/* Minimum size of the key bytes payload for a TKIP group key in a group key message */
+#define TKIP_GROUP_KEYBYTES_LEN_GKEY (8 + 8 + TKIP_GROUP_KEY_LEN ) /* 48 */
+/* size of CCMP key bytes payload */
+#define CCMP_GROUP_KEYBYTES_LEN ( sizeof(RSN_IE) + 8 + CCMP_GROUP_KEY_LEN + 6 ) /* 56 */
typedef struct {
guint8 type;
guint8 key_information[2]; /* Make this an array to avoid alignment issues */
@@ -293,10 +303,11 @@ typedef struct {
guint8 key_id[8];
guint8 key_mic[EAPKEY_MIC_LEN];
guint8 key_data_len[2]; /* Make this an array rather than a U16 to avoid alignment shifting */
- guint8 ie[sizeof(RSN_IE)]; /* Make this an array to avoid alignment issues */
+ guint8 ie[TKIP_GROUP_KEYBYTES_LEN_MAX]; /* Make this an array to avoid alignment issues */
} EAPOL_RSN_KEY, * P_EAPOL_RSN_KEY;
-
-
+#define RSN_KEY_WITHOUT_KEYBYTES_LEN sizeof(EAPOL_RSN_KEY)-TKIP_GROUP_KEYBYTES_LEN_MAX
+/* Minimum possible group key msg size (group key msg using CCMP as cipher)*/
+#define GROUP_KEY_PAYLOAD_LEN_MIN RSN_KEY_WITHOUT_KEYBYTES_LEN+CCMP_GROUP_KEY_LEN
/* A note about some limitations with the WPA decryption:
@@ -334,7 +345,7 @@ decrypted version. Then Wireshark wouldn't have to decrypt packets on the fly i
static void
-AirPDcapDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decryption_key, PAIRPDCAP_SEC_ASSOCIATION sa)
+AirPDcapDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decryption_key, PAIRPDCAP_SEC_ASSOCIATION sa, gboolean group_hshake)
{
guint8 new_key[32];
guint8 key_version;
@@ -345,7 +356,7 @@ AirPDcapDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decryption
/* 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. */
/* Preparation for decrypting the group key - determine group key data length */
- /* depending on whether it's a TKIP or AES encryption key */
+ /* depending on whether the pairwise key is TKIP or AES encryption key */
key_version = AIRPDCAP_EAP_KEY_DESCR_VER(pEAPKey->key_information[1]);
if (key_version == AIRPDCAP_WPA_KEY_VER_NOT_CCMP){
/* TKIP */
@@ -354,7 +365,8 @@ AirPDcapDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decryption
/* AES */
key_len = pntoh16(pEAPKey->key_data_len);
}
- if (key_len > sizeof(RSN_IE) || key_len == 0) { /* Don't read past the end of pEAPKey->ie */
+
+ if (key_len > TKIP_GROUP_KEYBYTES_LEN_MAX || key_len == 0) { /* Don't read past the end of pEAPKey->ie */
return;
}
@@ -370,6 +382,13 @@ AirPDcapDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decryption
memcpy(new_key+16, decryption_key, 16);
DEBUG_DUMP("FullDecrKey:", new_key, 32);
+ /* 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. */
+ /* In WPA2 its a little more tricky as the M3 keybytes contain an RSN_IE, but the group handshake */
+ /* does not. Also there are other (variable length) items in the keybytes which we need to account */
+ /* for to determine the true key length, and thus the group cipher. */
+
if (key_version == AIRPDCAP_WPA_KEY_VER_NOT_CCMP){
guint8 dummy[256];
/* TKIP key */
@@ -377,6 +396,11 @@ AirPDcapDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decryption
/* group key is decrypted using RC4. Concatenate the IV with the 16 byte EK (PTK+16) to get the decryption key */
rc4_state_struct rc4_state;
+
+ /* The WPA group key just contains the GTK bytes so deducing the type is straightforward */
+ /* Note - WPA M3 doesn't contain a group key so we'll only be here for the group handshake */
+ sa->wpa.key_ver = (key_len >=TKIP_GROUP_KEY_LEN)?AIRPDCAP_WPA_KEY_VER_NOT_CCMP:AIRPDCAP_WPA_KEY_VER_AES_CCMP;
+
crypt_rc4_init(&rc4_state, new_key, sizeof(new_key));
/* Do dummy 256 iterations of the RC4 algorithm (per 802.11i, Draft 3.0, p. 97 line 6) */
@@ -390,6 +414,13 @@ AirPDcapDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decryption
guint16 key_index;
guint8 *decrypted_data;
+ /* If this EAPOL frame is part of a separate group key handshake then this contains no */
+ /* RSN IE, so we can deduct that from the calculation. */
+ if (group_hshake)
+ sa->wpa.key_ver = (key_len >= (TKIP_GROUP_KEYBYTES_LEN_GKEY))?AIRPDCAP_WPA_KEY_VER_NOT_CCMP:AIRPDCAP_WPA_KEY_VER_AES_CCMP;
+ else
+ sa->wpa.key_ver = (key_len >= (TKIP_GROUP_KEYBYTES_LEN))?AIRPDCAP_WPA_KEY_VER_NOT_CCMP:AIRPDCAP_WPA_KEY_VER_AES_CCMP;
+
/* This storage is needed for the AES_unwrap function */
decrypted_data = (guint8 *) g_malloc(key_len);
@@ -429,7 +460,6 @@ AirPDcapDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decryption
/* 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 AirPDcapRsnaMng(). The WPA key materials are actually in the .wpa structure */
sa->validKey = TRUE;
- sa->wpa.key_ver = key_version;
/* 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 */
/* AirPDcapRsnaMng() function will extract the right piece of the GTK for decryption. (The first 16 bytes of the GTK are used for decryption.) */
@@ -458,7 +488,6 @@ AirPDcapGetSaPtr(
return &ctx->sa[sa_index];
}
-#define GROUP_KEY_PAYLOAD_LEN (8+4+sizeof(EAPOL_RSN_KEY))
static INT AirPDcapScanForGroupKey(
PAIRPDCAP_CONTEXT ctx,
const guint8 *data,
@@ -484,10 +513,9 @@ static INT AirPDcapScanForGroupKey(
#ifdef _DEBUG
CHAR msgbuf[255];
#endif
-
AIRPDCAP_DEBUG_TRACE_START("AirPDcapScanForGroupKey");
- if (mac_header_len + GROUP_KEY_PAYLOAD_LEN < tot_len) {
+ if (mac_header_len + GROUP_KEY_PAYLOAD_LEN_MIN > tot_len) {
AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapScanForGroupKey", "Message too short", AIRPDCAP_DEBUG_LEVEL_3);
return AIRPDCAP_RET_NO_VALID_HANDSHAKE;
}
@@ -512,7 +540,7 @@ static INT AirPDcapScanForGroupKey(
/* get and check the body length (IEEE 802.1X-2004, pg. 25) */
bodyLength=pntoh16(data+offset+2);
- if ((tot_len-offset-4) < bodyLength) {
+ if ((tot_len-offset-4) > bodyLength) {
AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapScanForGroupKey", "EAPOL body too short", AIRPDCAP_DEBUG_LEVEL_3);
return AIRPDCAP_RET_NO_VALID_HANDSHAKE;
}
@@ -585,7 +613,7 @@ static INT AirPDcapScanForGroupKey(
}
/* Extract the group key and install it in the SA */
- AirPDcapDecryptWPABroadcastKey(pEAPKey, sta_sa->wpa.ptk+16, sa);
+ AirPDcapDecryptWPABroadcastKey(pEAPKey, sta_sa->wpa.ptk+16, sa, TRUE);
}else{
AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapScanForGroupKey", "Skipping: not an EAPOL packet", AIRPDCAP_DEBUG_LEVEL_3);
@@ -1448,7 +1476,7 @@ AirPDcapRsna4WHandshake(
if (broadcast_sa == NULL){
return AIRPDCAP_RET_UNSUCCESS;
}
- AirPDcapDecryptWPABroadcastKey(pEAPKey, sa->wpa.ptk+16, broadcast_sa);
+ AirPDcapDecryptWPABroadcastKey(pEAPKey, sa->wpa.ptk+16, broadcast_sa, FALSE);
}
return AIRPDCAP_RET_SUCCESS_HANDSHAKE;