aboutsummaryrefslogtreecommitdiffstats
path: root/epan/crypt
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2009-05-22 17:38:21 +0000
committerGerald Combs <gerald@wireshark.org>2009-05-22 17:38:21 +0000
commit8ca33644e7f209a5fbfe8df6410b22122b3925c8 (patch)
tree94b5789d7751f62f7626e4bd6b64f32c4a074937 /epan/crypt
parent3e39be6ceabef6d9c7c94a0bfa96882b50a97dc1 (diff)
From Greg Schwendimann via bug 3156:
Airpdcap does not allow for more than one key to be stored for a pair of nodes. This means that when a device associates more than once the previous keys are lost. This is ok for the first pass as the newest key is all that is needed but when the user tries to click on a packet, to get the tree, which used a previous key all that is seen is the encrypted data. The attached patch stores previous associations in a linked list and will try all known keys before decided the packet can't be decrypted. The list of keys is garbage collected when a new capture is started. svn path=/trunk/; revision=28449
Diffstat (limited to 'epan/crypt')
-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 {