aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/crypt/airpdcap.c78
-rw-r--r--epan/crypt/airpdcap_system.h9
2 files changed, 61 insertions, 26 deletions
diff --git a/epan/crypt/airpdcap.c b/epan/crypt/airpdcap.c
index bf59e1d15b..1c076881cd 100644
--- a/epan/crypt/airpdcap.c
+++ b/epan/crypt/airpdcap.c
@@ -990,7 +990,8 @@ AirPDcapRsnaMng(
AIRPDCAP_SEC_ASSOCIATION *sa,
INT offset)
{
- INT ret_value;
+ INT ret_value=1;
+ UCHAR *try_data;
if (sa->key==NULL) {
AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "No key associated", AIRPDCAP_DEBUG_LEVEL_3);
@@ -1000,34 +1001,53 @@ AirPDcapRsnaMng(
AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "Key not yet valid", AIRPDCAP_DEBUG_LEVEL_3);
return AIRPDCAP_RET_UNSUCCESS;
}
- if (sa->wpa.key_ver==1) {
- /* CCMP -> HMAC-MD5 is the EAPOL-Key MIC, RC4 is the EAPOL-Key encryption algorithm */
- AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "TKIP", AIRPDCAP_DEBUG_LEVEL_3);
- DEBUG_DUMP("ptk", sa->wpa.ptk, 64);
- DEBUG_DUMP("ptk portion used", AIRPDCAP_GET_TK(sa->wpa.ptk), 16);
+ /* allocate a temp buffer for the decryption loop */
+ try_data=ep_alloc(*decrypt_len);
- ret_value=AirPDcapTkipDecrypt(decrypt_data+offset, *decrypt_len-offset, decrypt_data+AIRPDCAP_TA_OFFSET, AIRPDCAP_GET_TK(sa->wpa.ptk));
- if (ret_value){
- AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "TKIP failed!", AIRPDCAP_DEBUG_LEVEL_3);
- return ret_value;
- }
+ /* start of loop added by GCS */
+ for(/* sa */; sa != NULL && ret_value == 1 ;sa=sa->next) {
- AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "TKIP DECRYPTED!!!", AIRPDCAP_DEBUG_LEVEL_3);
- /* remove MIC (8bytes) and ICV (4bytes) from the end of packet */
- *decrypt_len-=12;
- } else {
- /* AES-CCMP -> HMAC-SHA1-128 is the EAPOL-Key MIC, AES wep_key wrap is the EAPOL-Key encryption algorithm */
- AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "CCMP", AIRPDCAP_DEBUG_LEVEL_3);
+ /* copy the encrypted data into a temp buffer */
+ memcpy(try_data, decrypt_data, *decrypt_len);
+
+ if (sa->wpa.key_ver==1) {
+ /* CCMP -> HMAC-MD5 is the EAPOL-Key MIC, RC4 is the EAPOL-Key encryption algorithm */
+ AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "TKIP", AIRPDCAP_DEBUG_LEVEL_3);
+
+ DEBUG_DUMP("ptk", sa->wpa.ptk, 64);
+ DEBUG_DUMP("ptk portion used", AIRPDCAP_GET_TK(sa->wpa.ptk), 16);
- ret_value=AirPDcapCcmpDecrypt(decrypt_data, mac_header_len, (INT)*decrypt_len, AIRPDCAP_GET_TK(sa->wpa.ptk));
- if (ret_value)
- return ret_value;
+ ret_value=AirPDcapTkipDecrypt(try_data+offset, *decrypt_len-offset, try_data+AIRPDCAP_TA_OFFSET, AIRPDCAP_GET_TK(sa->wpa.ptk));
+ if (ret_value){
+ AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "TKIP failed!", AIRPDCAP_DEBUG_LEVEL_3);
+ continue;
+ }
- AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "CCMP DECRYPTED!!!", AIRPDCAP_DEBUG_LEVEL_3);
- /* remove MIC (8bytes) from the end of packet */
- *decrypt_len-=8;
+ AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "TKIP DECRYPTED!!!", AIRPDCAP_DEBUG_LEVEL_3);
+ /* remove MIC (8bytes) and ICV (4bytes) from the end of packet */
+ *decrypt_len-=12;
+ } else {
+ /* AES-CCMP -> HMAC-SHA1-128 is the EAPOL-Key MIC, AES wep_key wrap is the EAPOL-Key encryption algorithm */
+ AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "CCMP", AIRPDCAP_DEBUG_LEVEL_3);
+
+ ret_value=AirPDcapCcmpDecrypt(try_data, mac_header_len, (INT)*decrypt_len, AIRPDCAP_GET_TK(sa->wpa.ptk));
+ if (ret_value)
+ continue;
+
+ AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "CCMP DECRYPTED!!!", AIRPDCAP_DEBUG_LEVEL_3);
+ /* remove MIC (8bytes) from the end of packet */
+ *decrypt_len-=8;
+ }
}
+ /* end of loop */
+
+ /* non of the keys workd */
+ if(sa == NULL)
+ return ret_value;
+
+ /* copy the decrypted data into the decrypt buffer GCS*/
+ memcpy(decrypt_data, try_data, *decrypt_len);
/* remove protection bit */
decrypt_data[1]&=0xBF;
@@ -1035,7 +1055,7 @@ AirPDcapRsnaMng(
/* remove TKIP/CCMP header */
offset = mac_header_len;
*decrypt_len-=8;
- memcpy(decrypt_data+offset, decrypt_data+offset+8, *decrypt_len-offset);
+ memmove(decrypt_data+offset, decrypt_data+offset+8, *decrypt_len-offset);
if (key!=NULL) {
memcpy(key, sa->key, sizeof(AIRPDCAP_KEY_ITEM));
@@ -1156,6 +1176,7 @@ AirPDcapRsna4WHandshake(
INT offset)
{
AIRPDCAP_KEY_ITEM *tmp_key, pkt_key;
+ AIRPDCAP_SEC_ASSOCIATION *tmp_sa;
INT key_index;
INT ret_value=1;
UCHAR useCache=FALSE;
@@ -1171,7 +1192,14 @@ AirPDcapRsna4WHandshake(
return AIRPDCAP_RET_NO_VALID_HANDSHAKE;
}
- /* TODO timeouts? reauthentication? */
+ /* TODO timeouts? */
+
+ /* This saves the sa since we are reauthenticating which will overwrite our current sa GCS*/
+ if(sa->handshake == 4) {
+ tmp_sa=se_alloc(sizeof(AIRPDCAP_SEC_ASSOCIATION));
+ memcpy(tmp_sa, sa, sizeof(AIRPDCAP_SEC_ASSOCIATION));
+ sa->next=tmp_sa;
+ }
/* TODO consider key-index */
diff --git a/epan/crypt/airpdcap_system.h b/epan/crypt/airpdcap_system.h
index 6ce1a434a5..c53b90078e 100644
--- a/epan/crypt/airpdcap_system.h
+++ b/epan/crypt/airpdcap_system.h
@@ -125,9 +125,14 @@ typedef struct _AIRPDCAP_SEC_ASSOCIATION_ID {
} AIRPDCAP_SEC_ASSOCIATION_ID, *PAIRPDCAP_SEC_ASSOCIATION_ID;
typedef struct _AIRPDCAP_SEC_ASSOCIATION {
+ /* This is for reassociations. A linked list of old security
+ * associations is kept. GCS
+ */
+ struct _AIRPDCAP_SEC_ASSOCIATION* next;
+
/**
* This flag define whether this item is used or not. Accepted
- * values are TRUE and FALSE
+ * values are TRUE and FALSE
*/
UINT8 used;
AIRPDCAP_SEC_ASSOCIATION_ID saId;
@@ -144,6 +149,8 @@ typedef struct _AIRPDCAP_SEC_ASSOCIATION {
UCHAR ptk[AIRPDCAP_WPA_PTK_LEN]; /* session key used in decryption algorithm */
} wpa;
+
+
} AIRPDCAP_SEC_ASSOCIATION, *PAIRPDCAP_SEC_ASSOCIATION;
typedef struct _AIRPDCAP_CONTEXT {