diff --git a/epan/crypt/dot11decrypt.c b/epan/crypt/dot11decrypt.c index e73d046a3a..4feaae03df 100644 --- a/epan/crypt/dot11decrypt.c +++ b/epan/crypt/dot11decrypt.c @@ -75,7 +75,6 @@ /****************************************************************************/ - /****************************************************************************/ /* Macro definitions */ @@ -159,14 +158,14 @@ static INT Dot11DecryptWepMng( static INT Dot11DecryptRsna4WHandshake( PDOT11DECRYPT_CONTEXT ctx, - DOT11DECRYPT_HS_MSG_TYPE msg_type, - const UCHAR *data, + PDOT11DECRYPT_EAPOL_PARSED eapol_parsed, + const guint8 *eapol_raw, DOT11DECRYPT_SEC_ASSOCIATION *sa, - INT offset, const guint tot_len, UCHAR *decrypt_data, guint *decrypt_len, PDOT11DECRYPT_KEY_ITEM key); + /** * It checks whether the specified key is corrected or not. * @note @@ -285,25 +284,9 @@ extern "C" { const guint8 broadcast_mac[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -#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 -typedef struct { - guint8 type; - guint8 key_information[2]; /* Make this an array to avoid alignment issues */ - guint8 key_length[2]; /* Make this an array to avoid alignment issues */ - guint8 replay_counter[8]; - guint8 key_nonce[NONCE_LEN]; - guint8 key_iv[16]; - guint8 key_sequence_counter[8]; /* also called the RSC */ - 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 */ -} EAPOL_RSN_KEY, * P_EAPOL_RSN_KEY; - typedef void (*DOT11DECRYPT_PTK_DERIVE_FUNC)( DOT11DECRYPT_SEC_ASSOCIATION *sa, const UCHAR pmk[32], @@ -312,10 +295,13 @@ typedef void (*DOT11DECRYPT_PTK_DERIVE_FUNC)( UCHAR *ptk, int hash_algo); +#define EAPOL_RSN_KEY_LEN 95 + /* Minimum possible key data size (at least one GTK KDE with CCMP key) */ #define GROUP_KEY_MIN_LEN 8 + CCMP_GROUP_KEY_LEN /* Minimum possible group key msg size (group key msg using CCMP as cipher)*/ -#define GROUP_KEY_PAYLOAD_LEN_MIN sizeof(EAPOL_RSN_KEY) + GROUP_KEY_MIN_LEN +#define GROUP_KEY_PAYLOAD_LEN_MIN \ + (EAPOL_RSN_KEY_LEN + GROUP_KEY_MIN_LEN) static void Dot11DecryptCopyKey(PDOT11DECRYPT_SEC_ASSOCIATION sa, PDOT11DECRYPT_KEY_ITEM key) @@ -391,10 +377,10 @@ Dot11DecryptRc4KeyData(const guint8 *decryption_key, guint decryption_key_len, /* XXX - what if this doesn't get the key? */ static INT -Dot11DecryptDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decryption_key, - PDOT11DECRYPT_SEC_ASSOCIATION sa, guint eapol_len, - guint8 *decrypted_data, - guint *decrypted_len) +Dot11DecryptDecryptWPABroadcastKey(PDOT11DECRYPT_EAPOL_PARSED eapol_parsed, + guint8 *decryption_key, + PDOT11DECRYPT_SEC_ASSOCIATION sa, + guint8 *decrypted_data, guint *decrypted_len) { guint8 key_version; const guint8 *key_data; @@ -408,13 +394,13 @@ Dot11DecryptDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decrypt /* Preparation for decrypting the group key - determine group key data length */ /* depending on whether the pairwise key is TKIP or AES encryption key */ - key_version = DOT11DECRYPT_EAP_KEY_DESCR_VER(pEAPKey->key_information[1]); + key_version = eapol_parsed->key_version; if (key_version == DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP){ /* TKIP */ - key_bytes_len = pntoh16(pEAPKey->key_length); + key_bytes_len = eapol_parsed->key_len; }else if (key_version == DOT11DECRYPT_WPA_KEY_VER_AES_CCMP){ /* AES */ - key_bytes_len = pntoh16(pEAPKey->key_data_len); + key_bytes_len = eapol_parsed->key_data_len; /* AES keys must be at least 128 bits = 16 bytes. */ if (key_bytes_len < 16) { @@ -424,7 +410,7 @@ Dot11DecryptDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decrypt /* XXX Ideally group cipher suite type from EAPOL message 2 of 4 should be used to */ /* determine key size. As we currently have no way to do this lookup check that key */ /* is at least 16 bytes (IEEE802.11-2016 Table 12-4 Cipher suite key lengths) */ - key_bytes_len = pntoh16(pEAPKey->key_data_len); + key_bytes_len = eapol_parsed->key_data_len; if (key_bytes_len < 16) { return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE; @@ -432,16 +418,16 @@ Dot11DecryptDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decrypt } if ((key_bytes_len < GROUP_KEY_MIN_LEN) || - (eapol_len < sizeof(EAPOL_RSN_KEY)) || - (key_bytes_len > eapol_len - sizeof(EAPOL_RSN_KEY))) { + (eapol_parsed->len < EAPOL_RSN_KEY_LEN) || + (key_bytes_len > eapol_parsed->len - EAPOL_RSN_KEY_LEN)) { return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE; } /* Encrypted key is in the information element field of the EAPOL key packet */ - key_data = (const guint8 *)pEAPKey + sizeof(EAPOL_RSN_KEY); + key_data = eapol_parsed->key_data; DEBUG_DUMP("Encrypted Broadcast key:", key_data, key_bytes_len); - DEBUG_DUMP("KeyIV:", pEAPKey->key_iv, 16); + DEBUG_DUMP("KeyIV:", eapol_parsed->key_iv, 16); DEBUG_DUMP("decryption_key:", decryption_key, 16); /* We are rekeying, save old sa */ @@ -468,7 +454,7 @@ Dot11DecryptDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decrypt sa->wpa.key_ver = (key_bytes_len >=TKIP_GROUP_KEY_LEN)?DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP:DOT11DECRYPT_WPA_KEY_VER_AES_CCMP; /* Build the full decryption key based on the IV and part of the pairwise key */ - memcpy(new_key, pEAPKey->key_iv, 16); + memcpy(new_key, eapol_parsed->key_iv, 16); memcpy(new_key+16, decryption_key, 16); DEBUG_DUMP("FullDecrKey:", new_key, 32); data = Dot11DecryptRc4KeyData(new_key, 32, key_data, key_bytes_len); @@ -542,7 +528,6 @@ Dot11DecryptDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decrypt } 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 @@ -714,68 +699,33 @@ INT Dot11DecryptScanTdlsForKeys( INT Dot11DecryptScanEapolForKeys( PDOT11DECRYPT_CONTEXT ctx, - DOT11DECRYPT_HS_MSG_TYPE msg_type, - const guint8 *data, + PDOT11DECRYPT_EAPOL_PARSED eapol_parsed, + 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 -) + PDOT11DECRYPT_KEY_ITEM key) { - guint tot_len_left; - guint bodyLength; DOT11DECRYPT_SEC_ASSOCIATION_ID id; PDOT11DECRYPT_SEC_ASSOCIATION sta_sa; PDOT11DECRYPT_SEC_ASSOCIATION sa; - guint offset = 0; - - const EAPOL_RSN_KEY *pEAPKey; /* Callers provide these guarantees, so let's make them explicit. */ DISSECTOR_ASSERT(tot_len <= DOT11DECRYPT_EAPOL_MAX_LEN); - offset = 0; - tot_len_left = tot_len; - DEBUG_PRINT_LINE("Authentication: EAPOL packet", DEBUG_LEVEL_3); - if (tot_len_left < 4) { - DEBUG_PRINT_LINE("Not EAPOL-Key", DEBUG_LEVEL_3); - return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE; - } - - - /* get and check the body length (IEEE 802.1X-2004, pg. 25) */ - bodyLength=pntoh16(data+offset+2); - if (((tot_len_left-4) < bodyLength) || (bodyLength < sizeof(EAPOL_RSN_KEY))) { /* Only check if frame is long enough for eapol header, ignore tailing garbage, see bug 9065 */ - DEBUG_PRINT_LINE("EAPOL body too short", DEBUG_LEVEL_3); - return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE; - } - - /* skip EAPOL MPDU and go to the first byte of the body */ - offset+=4; - tot_len_left-=4; - - pEAPKey = (const EAPOL_RSN_KEY *) (data+offset); - - if (tot_len_left < 1) { - DEBUG_PRINT_LINE("Not EAPOL-Key", DEBUG_LEVEL_3); - return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE; - } /* check if the key descriptor type is valid (IEEE 802.1X-2004, pg. 27) */ - if (/*pEAPKey->type!=0x1 &&*/ /* RC4 Key Descriptor Type (deprecated) */ - pEAPKey->type != DOT11DECRYPT_RSN_WPA2_KEY_DESCRIPTOR && /* IEEE 802.11 Key Descriptor Type (WPA2) */ - pEAPKey->type != DOT11DECRYPT_RSN_WPA_KEY_DESCRIPTOR) /* 254 = RSN_KEY_DESCRIPTOR - WPA, */ + if (/*eapol_parsed->key_type!=0x1 &&*/ /* RC4 Key Descriptor Type (deprecated) */ + eapol_parsed->key_type != DOT11DECRYPT_RSN_WPA2_KEY_DESCRIPTOR && /* IEEE 802.11 Key Descriptor Type (WPA2) */ + eapol_parsed->key_type != DOT11DECRYPT_RSN_WPA_KEY_DESCRIPTOR) /* 254 = RSN_KEY_DESCRIPTOR - WPA, */ { DEBUG_PRINT_LINE("Not valid key descriptor type", DEBUG_LEVEL_3); return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE; } - /* start with descriptor body */ - offset+=1; - /* 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); @@ -786,7 +736,7 @@ INT Dot11DecryptScanEapolForKeys( } /* It could be a Pairwise Key exchange, check */ - if (Dot11DecryptRsna4WHandshake(ctx, msg_type, data, sa, offset, tot_len, + if (Dot11DecryptRsna4WHandshake(ctx, eapol_parsed, eapol_raw, sa, tot_len, decrypt_data, decrypt_len, key) == DOT11DECRYPT_RET_SUCCESS_HANDSHAKE) { return DOT11DECRYPT_RET_SUCCESS_HANDSHAKE; @@ -797,7 +747,7 @@ INT Dot11DecryptScanEapolForKeys( return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE; } - if (msg_type != DOT11DECRYPT_HS_MSG_TYPE_GHS_1){ + if (eapol_parsed->msg_type != DOT11DECRYPT_HS_MSG_TYPE_GHS_1){ DEBUG_PRINT_LINE("Not Group handshake message 1", DEBUG_LEVEL_3); return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE; @@ -820,9 +770,9 @@ INT Dot11DecryptScanEapolForKeys( } /* 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(pEAPKey, sta_sa->wpa.ptk+16, sa, tot_len-offset+1, - decrypt_data, decrypt_len)); + Dot11DecryptCopyKey(sa, key); /* save key used for decrypting broadcast key */ + return Dot11DecryptDecryptWPABroadcastKey(eapol_parsed, sta_sa->wpa.ptk + 16, + sa, decrypt_data, decrypt_len); } INT Dot11DecryptDecryptPacket( @@ -1358,97 +1308,13 @@ Dot11DecryptWepMng( return DOT11DECRYPT_RET_SUCCESS; } -static int -Dot11DecryptGetRsne( - const EAPOL_RSN_KEY *pEAPKey, - const guint tot_len, - int *group_cipher, - int *cipher, - int *akm) -{ - guint16 key_data_len = pntoh16(&pEAPKey->key_data_len); - int offset = 0; - int offset_rsne; - int i; - guint16 count; - const guint8 *data = ((const guint8 *)pEAPKey) + sizeof(EAPOL_RSN_KEY); -#ifdef DOT11DECRYPT_DEBUG -#define MSGBUF_LEN 255 - CHAR msgbuf[MSGBUF_LEN]; -#endif - - if (key_data_len + sizeof(EAPOL_RSN_KEY) > tot_len) { - key_data_len = (guint16)(tot_len - sizeof(EAPOL_RSN_KEY)); - } - - while (offset < key_data_len - 2) { - guint8 element_id = data[offset]; - guint8 length = data[offset + 1]; - - switch (element_id) { - case 48: /* RSN (802.11-2016 9.4.2.35) */ - offset_rsne = offset + 2; - offset_rsne += 2; /* version */ - if (DOT11DECRYPT_IEEE80211_OUI(data + offset_rsne)) { - *group_cipher = data[offset_rsne + 3]; - } - offset_rsne += 4; /* Group Cipher Suite */ - - if (offset_rsne + 1 >= key_data_len) { - break; - } - count = pletoh16(data + offset_rsne); - offset_rsne += 2; /* Pairwise Ciper Suite Count */ - - if (offset_rsne + 4 * count >= key_data_len) { - break;; - } - for (i = 0; i < count; i++) { - if (DOT11DECRYPT_IEEE80211_OUI(data + offset_rsne + 4 * i)) { - *cipher = data[offset_rsne + 4 * i + 3]; - break; - } - } - offset_rsne += 4 * count; /* Pairwise Cipher Suites */ - - count = pletoh16(data + offset_rsne); - offset_rsne += 2; /* AKM Suite Count */ - - if (offset_rsne + 4 * count >= key_data_len) { - break; - } - for (i = 0; i < count; i++) { - if (DOT11DECRYPT_IEEE80211_OUI(data + offset_rsne + 4 * i)) { - *akm = data[offset_rsne + 4 * i + 3]; - break; - } - } - - /* RSN OUI */ -#ifdef DOT11DECRYPT_DEBUG - g_snprintf(msgbuf, MSGBUF_LEN, "Pairwise Cipher: %d, Group Cipher: %d AKM: %d", - *cipher, *group_cipher, *akm); - DEBUG_PRINT_LINE(msgbuf, DEBUG_LEVEL_3); -#endif /* DOT11DECRYPT_DEBUG */ - return 0; - } - if (!length) { - break; - } - offset += length; - } - DEBUG_PRINT_LINE("RSNE not found or parse failed", DEBUG_LEVEL_3); - return -1; -} - /* Refer to IEEE 802.11i-2004, 8.5.3, pag. 85 */ static INT Dot11DecryptRsna4WHandshake( PDOT11DECRYPT_CONTEXT ctx, - DOT11DECRYPT_HS_MSG_TYPE msg_type, - const UCHAR *data, + PDOT11DECRYPT_EAPOL_PARSED eapol_parsed, + const guint8 *eapol_raw, DOT11DECRYPT_SEC_ASSOCIATION *sa, - INT offset, const guint tot_len, UCHAR *decrypt_data, guint *decrypt_len, @@ -1460,19 +1326,14 @@ Dot11DecryptRsna4WHandshake( INT ret_value=1; UCHAR useCache=FALSE; UCHAR eapol[DOT11DECRYPT_EAPOL_MAX_LEN]; - USHORT eapol_len; if (sa->key!=NULL) useCache=TRUE; - if (tot_len-offset < 2) { - DEBUG_PRINT_LINE("Too short to determine the message type", DEBUG_LEVEL_5); - return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE; - } - - /* a 4-way handshake packet use a Pairwise key type (IEEE 802.11i-2004, pg. 79) */ - if (DOT11DECRYPT_EAP_KEY(data[offset+1])!=1) { - DEBUG_PRINT_LINE("Group/STAKey message (not used)", DEBUG_LEVEL_5); + if (eapol_parsed->len > DOT11DECRYPT_EAPOL_MAX_LEN || + eapol_parsed->key_len > DOT11DECRYPT_EAPOL_MAX_LEN || + eapol_parsed->key_data_len > DOT11DECRYPT_EAPOL_MAX_LEN) { + DEBUG_PRINT_LINE("Too large EAPOL frame and/or key data", DEBUG_LEVEL_5); return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE; } @@ -1487,8 +1348,7 @@ Dot11DecryptRsna4WHandshake( /* manage 4-way handshake packets; this step completes the 802.1X authentication process (IEEE 802.11i-2004, pag. 85) */ /* message 1: Authenticator->Supplicant (Sec=0, Mic=0, Ack=1, Inst=0, Key=1(pairwise), KeyRSC=0, Nonce=ANonce, MIC=0) */ - if (msg_type == DOT11DECRYPT_HS_MSG_TYPE_4WHS_1) - { + if (eapol_parsed->msg_type == DOT11DECRYPT_HS_MSG_TYPE_4WHS_1) { DEBUG_PRINT_LINE("4-way handshake message 1", DEBUG_LEVEL_3); /* On reception of Message 1, the Supplicant determines whether the Key Replay Counter field value has been */ @@ -1505,14 +1365,14 @@ Dot11DecryptRsna4WHandshake( } /* save ANonce (from authenticator) to derive the PTK with the SNonce (from the 2 message) */ - if (tot_len-(offset+12) < 32) { - DEBUG_PRINT_LINE("Too short to contain ANonce", DEBUG_LEVEL_5); + if (!eapol_parsed->nonce) { + DEBUG_PRINT_LINE("ANonce missing", DEBUG_LEVEL_5); return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE; } - memcpy(sa->wpa.nonce, data+offset+12, 32); + memcpy(sa->wpa.nonce, eapol_parsed->nonce, 32); /* get the Key Descriptor Version (to select algorithm used in decryption -CCMP or TKIP-) */ - sa->wpa.key_ver=DOT11DECRYPT_EAP_KEY_DESCR_VER(data[offset+1]); + sa->wpa.key_ver = eapol_parsed->key_version; sa->handshake=1; @@ -1520,7 +1380,7 @@ Dot11DecryptRsna4WHandshake( } /* message 2|4: Supplicant->Authenticator (Sec=0|1, Mic=1, Ack=0, Inst=0, Key=1(pairwise), KeyRSC=0, Nonce=SNonce|0, MIC=MIC(KCK,EAPOL)) */ - if (msg_type == DOT11DECRYPT_HS_MSG_TYPE_4WHS_2) { + if (eapol_parsed->msg_type == DOT11DECRYPT_HS_MSG_TYPE_4WHS_2) { DEBUG_PRINT_LINE("4-way handshake message 2", DEBUG_LEVEL_3); /* On reception of Message 2, the Authenticator checks that the key replay counter corresponds to the */ @@ -1529,8 +1389,8 @@ Dot11DecryptRsna4WHandshake( /* the Authenticator silently discards Message 2. */ /* -> not checked; the Supplicant will send another message 2 (hopefully!) */ - if (tot_len - (offset + 12) < 32) { - DEBUG_PRINT_LINE("Too short to contain SNonce", DEBUG_LEVEL_5); + if (!eapol_parsed->nonce) { + DEBUG_PRINT_LINE("SNonce missing", DEBUG_LEVEL_5); return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE; } @@ -1570,39 +1430,28 @@ Dot11DecryptRsna4WHandshake( } else { tmp_pkt_key = tmp_key; } + memcpy(eapol, eapol_raw, tot_len); - /* verify the MIC (compare the MIC in the packet included in this message with a MIC calculated with the PTK) */ - eapol_len=pntoh16(data+offset-3)+4; - if ((guint)(tot_len-(offset-5)) < (eapol_lenkey_version; int akm = -1; int cipher = -1; if (key_version == 0) { /* PTK derivation is based on Authentication Key Management Type */ - int group_cipher = -1; - Dot11DecryptGetRsne((const EAPOL_RSN_KEY *)(data + offset - 1), - tot_len - (offset - 1), - &group_cipher, &cipher, &akm); + akm = eapol_parsed->akm; + cipher = eapol_parsed->cipher; } - /* derive the PTK from the BSSID, STA MAC, PMK, SNonce, ANonce */ Dot11DecryptDerivePtk(sa, /* authenticator nonce, bssid, station mac */ tmp_pkt_key->KeyData.Wpa.Psk, /* PSK == PMK */ - data+offset+12, /* supplicant nonce */ + eapol_parsed->nonce, /* supplicant nonce */ key_version, akm, cipher); - DEBUG_DUMP("TK", DOT11DECRYPT_GET_TK(sa->wpa.ptk), 16); ret_value=Dot11DecryptRsnaMicCheck(eapol, /* eapol frame (header also) */ - eapol_len, /* eapol frame length */ + tot_len, /* eapol frame length */ sa->wpa.ptk, /* Key Confirmation Key */ key_version, /* EAPOL-Key description version */ akm); @@ -1644,8 +1493,7 @@ Dot11DecryptRsna4WHandshake( } /* message 3: Authenticator->Supplicant (Sec=1, Mic=1, Ack=1, Inst=0/1, Key=1(pairwise), KeyRSC=???, Nonce=ANonce, MIC=1) */ - if (msg_type == DOT11DECRYPT_HS_MSG_TYPE_4WHS_3) { - const EAPOL_RSN_KEY *pEAPKey; + if (eapol_parsed->msg_type == DOT11DECRYPT_HS_MSG_TYPE_4WHS_3) { DEBUG_PRINT_LINE("4-way handshake message 3", DEBUG_LEVEL_3); /* On reception of Message 3, the Supplicant silently discards the message if the Key Replay Counter field */ @@ -1656,8 +1504,7 @@ Dot11DecryptRsna4WHandshake( /* If using WPA2 PSK, message 3 will contain an RSN for the group key (GTK KDE). In order to properly support decrypting WPA2-PSK packets, we need to parse this to get the group key. */ - pEAPKey = (const EAPOL_RSN_KEY *)(&(data[offset-1])); - if (pEAPKey->type == DOT11DECRYPT_RSN_WPA2_KEY_DESCRIPTOR){ + if (eapol_parsed->key_type == DOT11DECRYPT_RSN_WPA2_KEY_DESCRIPTOR) { PDOT11DECRYPT_SEC_ASSOCIATION broadcast_sa; DOT11DECRYPT_SEC_ASSOCIATION_ID id; @@ -1670,13 +1517,13 @@ Dot11DecryptRsna4WHandshake( return DOT11DECRYPT_RET_REQ_DATA; } Dot11DecryptCopyKey(sa, key); /* save key used for decrypting broadcast key */ - return (Dot11DecryptDecryptWPABroadcastKey(pEAPKey, sa->wpa.ptk+16, broadcast_sa, tot_len-offset+1, - decrypt_data, decrypt_len)); + return Dot11DecryptDecryptWPABroadcastKey(eapol_parsed, sa->wpa.ptk + 16, broadcast_sa, + decrypt_data, decrypt_len); } } /* message 4 */ - if (msg_type == DOT11DECRYPT_HS_MSG_TYPE_4WHS_4) { + if (eapol_parsed->msg_type == DOT11DECRYPT_HS_MSG_TYPE_4WHS_4) { /* TODO "Note that when the 4-Way Handshake is first used Message 4 is sent in the clear." */ /* TODO check MIC and Replay Counter */ diff --git a/epan/crypt/dot11decrypt_system.h b/epan/crypt/dot11decrypt_system.h index b7a18dc60a..19200a0f86 100644 --- a/epan/crypt/dot11decrypt_system.h +++ b/epan/crypt/dot11decrypt_system.h @@ -150,6 +150,23 @@ typedef enum _DOT11DECRYPT_HS_MSG_TYPE { DOT11DECRYPT_HS_MSG_TYPE_GHS_2 } DOT11DECRYPT_HS_MSG_TYPE; +typedef struct _DOT11DECRYPT_EAPOL_PARSED { + DOT11DECRYPT_HS_MSG_TYPE msg_type; + guint16 len; + guint8 key_type; + guint8 key_version; + guint16 key_len; + guint8 *key_iv; + guint8 *key_data; + guint16 key_data_len; + guint8 group_cipher; + guint8 cipher; + guint8 akm; + guint8 *nonce; + guint8 *mic; + guint16 mic_len; +} DOT11DECRYPT_EAPOL_PARSED, *PDOT11DECRYPT_EAPOL_PARSED; + /************************************************************************/ /* Function prototype declarations */ @@ -213,8 +230,8 @@ extern INT Dot11DecryptDecryptPacket( * extracting further keys. If keydata hard to be decrypted the decrypted * data will be in decrypt_data buffer. * @param ctx [IN] Pointer to the current context - * @param msg_type [IN] Handshake message type - * @param data [IN] Pointer to a buffer with an EAPOL frame + * @param eapol_parsed [IN] Extracted/Parsed pieces of eapol frame + * @param eapol_raw [IN] Pointer to a buffer with an EAPOL frame * @param tot_len [IN] Total length of the EAPOL frame * @param bssid [IN] bssid of AP * @param sta [IN] sta MAC address @@ -248,8 +265,8 @@ extern INT Dot11DecryptDecryptPacket( */ extern INT Dot11DecryptScanEapolForKeys( PDOT11DECRYPT_CONTEXT ctx, - DOT11DECRYPT_HS_MSG_TYPE msg_type, - const guint8 *data, + PDOT11DECRYPT_EAPOL_PARSED eapol_parsed, + const guint8 *eapol_raw, const guint tot_len, const UCHAR bssid[DOT11DECRYPT_MAC_LEN], const UCHAR sta[DOT11DECRYPT_MAC_LEN], diff --git a/epan/dissectors/packet-eapol.c b/epan/dissectors/packet-eapol.c index d41eed93f3..2ca5c39315 100644 --- a/epan/dissectors/packet-eapol.c +++ b/epan/dissectors/packet-eapol.c @@ -121,6 +121,7 @@ dissect_eapol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U /* Save eapol key type packets for IEEE 802.11 dissector */ if (!pinfo->fd->visited && eapol_type == EAPOL_KEY) { proto_eapol_key_frame_t *key_frame = wmem_new(pinfo->pool, proto_eapol_key_frame_t); + key_frame->type = 0; key_frame->len = len; key_frame->data = (guint8 *)wmem_alloc(pinfo->pool, len); tvb_memcpy(tvb, key_frame->data, 0, len); @@ -148,6 +149,16 @@ dissect_eapol_key(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, void* proto_tree_add_item(eapol_tree, hf_eapol_keydes_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; next_tvb = tvb_new_subset_remaining(tvb, offset); + + /* Save keydesc_type for IEEE 802.11 dissector */ + if (!pinfo->fd->visited) { + proto_eapol_key_frame_t *key_frame = (proto_eapol_key_frame_t *) + p_get_proto_data(pinfo->pool, pinfo, proto_eapol, EAPOL_KEY_FRAME_KEY); + if (key_frame) { + key_frame->type = keydesc_type; + } + } + if (!dissector_try_uint_new(eapol_keydes_type_dissector_table, keydesc_type, next_tvb, pinfo, eapol_tree, FALSE, NULL)) { diff --git a/epan/dissectors/packet-eapol.h b/epan/dissectors/packet-eapol.h index 2e9651b0aa..f64ce36165 100644 --- a/epan/dissectors/packet-eapol.h +++ b/epan/dissectors/packet-eapol.h @@ -28,6 +28,7 @@ extern int proto_eapol; #define EAPOL_KEY_FRAME_KEY 0 typedef struct { guint len; + guint8 type; /* eapol.keydes.type */ guint8 *data; } proto_eapol_key_frame_t; diff --git a/epan/dissectors/packet-ieee80211.c b/epan/dissectors/packet-ieee80211.c index eef8ed1500..86a97b2248 100644 --- a/epan/dissectors/packet-ieee80211.c +++ b/epan/dissectors/packet-ieee80211.c @@ -258,6 +258,18 @@ typedef struct mimo_control #define ASSOC_COUNTER_KEY 5 #define STA_KEY 6 #define BSSID_KEY 7 +#define NONCE_KEY 8 +#define GROUP_CIPHER_KEY 9 +#define CIPHER_KEY 10 +#define AKM_KEY 11 +#define MIC_KEY 12 +#define MIC_LEN_KEY 13 +#define KEY_VERSION_KEY 14 +#define KEY_LEN_KEY 15 +#define KEY_IV_KEY 16 +#define KEY_DATA_KEY 17 +#define KEY_DATA_LEN_KEY 18 + /* ************************************************************************* */ /* Define some very useful macros that are used to analyze frame types etc. */ /* ************************************************************************* */ @@ -14523,6 +14535,20 @@ static gboolean is_ft_akm_suite(guint32 akm_suite) } } +static void +save_proto_data(tvbuff_t *tvb, packet_info *pinfo, int offset, size_t size, int key) +{ + guint8 *data = (guint8 *)wmem_alloc(pinfo->pool, size); + tvb_memcpy(tvb, data, offset, size); + p_add_proto_data(pinfo->pool, pinfo, proto_wlan, key, data); +} + +static void +save_proto_data_value(packet_info *pinfo, guint value, int key) +{ + p_add_proto_data(pinfo->pool, pinfo, proto_wlan, key, GUINT_TO_POINTER(value)); +} + /* * 7.3.2.25 RSNE information element. Common format with OSEN except the * verison... should refactor @@ -14567,6 +14593,7 @@ dissect_rsn_ie(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, if (tvb_get_ntoh24(tvb, offset) == OUI_RSN) { proto_tree_add_item(rsn_gcs_tree, hf_ieee80211_rsn_gcs_80211_type, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN); + save_proto_data_value(pinfo, tvb_get_guint8(tvb, offset + 3), GROUP_CIPHER_KEY); } else { proto_tree_add_item(rsn_gcs_tree, hf_ieee80211_rsn_gcs_type, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN); } @@ -14600,6 +14627,7 @@ dissect_rsn_ie(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, { proto_tree_add_item(rsn_sub_pcs_tree, hf_ieee80211_rsn_pcs_80211_type, tvb, offset+3, 1, ENC_LITTLE_ENDIAN); proto_item_append_text(rsn_pcs_item, " %s", rsn_pcs_return(tvb_get_ntohl(tvb, offset))); + save_proto_data_value(pinfo, tvb_get_guint8(tvb, offset + 3), CIPHER_KEY); } else { proto_tree_add_item(rsn_sub_pcs_tree, hf_ieee80211_rsn_pcs_type, tvb, offset+3, 1, ENC_LITTLE_ENDIAN); } @@ -14639,6 +14667,7 @@ dissect_rsn_ie(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, { proto_tree_add_item(rsn_sub_akms_tree, hf_ieee80211_rsn_akms_80211_type, tvb, offset+3, 1, ENC_LITTLE_ENDIAN); proto_item_append_text(rsn_akms_item, " %s", rsn_akms_return(tvb_get_ntohl(tvb, offset))); + save_proto_data_value(pinfo, tvb_get_guint8(tvb, offset + 3), AKM_KEY); packet_data->last_akm_suite = tvb_get_ntohl(tvb, offset); if (association_sanity_check) { @@ -23705,18 +23734,6 @@ crc32_802_tvb_padded(tvbuff_t *tvb, guint hdr_len, guint hdr_size, guint len) return (c_crc); } -static void save_bssid(tvbuff_t *tvb, packet_info *pinfo, int offset) { - guint8 *data = (guint8 *)wmem_alloc(pinfo->pool, 6); - tvb_memcpy(tvb, data, offset, 6); - p_add_proto_data(pinfo->pool, pinfo, proto_wlan, BSSID_KEY, data); -} - -static void save_sta(tvbuff_t *tvb, packet_info *pinfo, int offset) { - guint8 *data = (guint8 *)wmem_alloc(pinfo->pool, 6); - tvb_memcpy(tvb, data, offset, 6); - p_add_proto_data(pinfo->pool, pinfo, proto_wlan, STA_KEY, data); -} - typedef enum { ENCAP_802_2, ENCAP_IPX, @@ -24472,7 +24489,7 @@ dissect_ieee80211_common(tvbuff_t *tvb, packet_info *pinfo, /* for tap */ set_address_tvb(&whdr->bssid, wlan_bssid_address_type, 6, tvb, bssid_offset); /* for dot11decrypt */ - save_bssid(tvb, pinfo, bssid_offset); + save_proto_data(tvb, pinfo, bssid_offset, 6, BSSID_KEY); } if (src_offset) { @@ -24490,7 +24507,7 @@ dissect_ieee80211_common(tvbuff_t *tvb, packet_info *pinfo, /* for dot11decrypt */ if (sta_addr_offset > 0) { - save_sta(tvb, pinfo, sta_addr_offset); + save_proto_data(tvb, pinfo, sta_addr_offset, 6, STA_KEY); } seq_control = tvb_get_letohs(tvb, 22); @@ -25671,12 +25688,37 @@ try_scan_eapol_keys(packet_info *pinfo, DOT11DECRYPT_HS_MSG_TYPE msg_type) 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) { return; } gint ret = Dot11DecryptScanEapolForKeys(&dot11decrypt_ctx, - msg_type, + &eapol_parsed, eapol_key->data, eapol_key->len, bssid, sta, dec_data, &dec_caplen, @@ -25716,6 +25758,7 @@ dissect_wlan_rsna_eapol_wpa_or_rsn_key(tvbuff_t *tvb, packet_info *pinfo, proto_ }; guint16 eapol_data_offset = 76; /* 92 - 16 */ guint16 eapol_key_mic_len = determine_mic_len(pinfo, FALSE); + save_proto_data_value(pinfo, eapol_key_mic_len, MIC_LEN_KEY); eapol_data_offset += eapol_key_mic_len; DOT11DECRYPT_HS_MSG_TYPE msg_type = DOT11DECRYPT_HS_MSG_TYPE_INVALID; @@ -25790,15 +25833,9 @@ dissect_wlan_rsna_eapol_wpa_or_rsn_key(tvbuff_t *tvb, packet_info *pinfo, proto_ } proto_item_set_generated(ti); - if (!pinfo->fd->visited && msg_type != DOT11DECRYPT_HS_MSG_TYPE_INVALID) { - /* Let dot11decrypt engine extract keys from 4-way handshake frames - * If there's encrypted key data (GTK) present in eapol frame the - * decrypted key data is stored in EAPOL_KEY proto data. - */ - try_scan_eapol_keys(pinfo, msg_type); - } - 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, ENC_BIG_ENDIAN, BMT_NO_APPEND); @@ -25806,15 +25843,19 @@ dissect_wlan_rsna_eapol_wpa_or_rsn_key(tvbuff_t *tvb, packet_info *pinfo, proto_ proto_tree_add_item(tree, hf_wlan_rsna_eapol_keydes_key_len, tvb, offset, 2, ENC_BIG_ENDIAN); + save_proto_data_value(pinfo, tvb_get_ntohs(tvb, offset), KEY_LEN_KEY); offset += 2; proto_tree_add_item(tree, hf_wlan_rsna_eapol_keydes_replay_counter, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; proto_tree_add_item(tree, hf_wlan_rsna_eapol_wpa_keydes_nonce, tvb, offset, 32, ENC_NA); + save_proto_data(tvb, pinfo, offset, 32, NONCE_KEY); + offset += 32; proto_tree_add_item(tree, hf_wlan_rsna_eapol_keydes_key_iv, tvb, offset, 16, ENC_NA); + save_proto_data(tvb, pinfo, offset, 16, KEY_IV_KEY); offset += 16; proto_tree_add_item(tree, hf_wlan_rsna_eapol_wpa_keydes_rsc, tvb, offset, 8, ENC_NA); @@ -25826,12 +25867,26 @@ dissect_wlan_rsna_eapol_wpa_or_rsn_key(tvbuff_t *tvb, packet_info *pinfo, proto_ if (eapol_key_mic_len > 0) { proto_tree_add_item(tree, hf_wlan_rsna_eapol_wpa_keydes_mic, tvb, offset, eapol_key_mic_len, ENC_NA); + save_proto_data(tvb, pinfo, offset, eapol_key_mic_len, MIC_KEY); offset += eapol_key_mic_len; } proto_tree_add_item(tree, hf_wlan_rsna_eapol_wpa_keydes_data_len, tvb, offset, 2, ENC_BIG_ENDIAN); + save_proto_data_value(pinfo, tvb_get_ntohs(tvb, offset), KEY_DATA_LEN_KEY); offset += 2; + + 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); @@ -25885,6 +25940,12 @@ 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 + * all fields from the EAPOL frame have been parsed. + */ + try_scan_eapol_keys(pinfo, msg_type); + } return tvb_captured_length(tvb); }