diff options
30 files changed, 1843 insertions, 1988 deletions
diff --git a/Makefile.am b/Makefile.am index 8bf2a6b243..974de3205c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -312,6 +312,7 @@ tshark_additional_libs = \ wiretap/libwiretap.la \ epan/libwireshark.la + # This is the automake dependency variable for the executable tshark_DEPENDENCIES = \ $(wireshark_optional_objects) \ @@ -712,12 +713,12 @@ else install-exec-hook: endif -DIST_SUBDIRS = asn1 codecs doc epan gtk help packaging plugins tools wiretap +DIST_SUBDIRS = asn1 codecs doc airpdcap epan gtk help packaging plugins tools wiretap if HAVE_PLUGINS -SUBDIRS = tools wiretap doc epan plugins packaging help @wireshark_SUBDIRS@ +SUBDIRS = tools wiretap doc airpdcap epan plugins packaging help @wireshark_SUBDIRS@ else -SUBDIRS = tools wiretap doc epan packaging help @wireshark_SUBDIRS@ +SUBDIRS = tools wiretap doc airpdcap epan packaging help @wireshark_SUBDIRS@ endif wireshark.1: doc/wireshark.pod AUTHORS-SHORT-FORMAT @@ -83,12 +83,7 @@ typedef struct _AirpcapDeviceDescription PCHAR Description; /* Device description */ } AirpcapDeviceDescription, *PAirpcapDeviceDescription; -#define MAX_ENCRYPTION_KEYS 64 -#define WEP_KEY_MAX_SIZE 32 /* Maximum size of a WEP key, in bytes. This is the size of an entry in the */ - /* AirpcapWepKeysCollection structure */ - - #ifndef __MINGW32__ #pragma pack(push) #pragma pack(1) diff --git a/airpcap_loader.c b/airpcap_loader.c index bd5c9c1d9f..cf3f1e80f8 100644 --- a/airpcap_loader.c +++ b/airpcap_loader.c @@ -42,16 +42,17 @@ #include <epan/packet.h> #include <epan/prefs.h> #include <epan/prefs-int.h> +#include <epan/crypt/wep-wpadefs.h> #include "capture_ui_utils.h" #include "simple_dialog.h" +/* AirPDcap */ +#include "airpdcap/airpdcap_ws.h" + #include <airpcap.h> #include "airpcap_loader.h" -/* AirPDcap */ -#include "../airpdcap/airpdcap_ws.h" - /* * We load dinamically the dag library in order link it only when * it's present on the system @@ -109,8 +110,8 @@ airpcap_if_info_t *airpcap_if_active = NULL; /* WLAN preferences pointer */ module_t *wlan_prefs = NULL; -/* - * Callback used by the load_wlan_keys() routine in order to read a WEP decryption key +/* + * Callback used by the load_wlan_keys() routine in order to read a WEP decryption key */ static guint get_wep_key(pref_t *pref, gpointer ud _U_) @@ -395,8 +396,8 @@ fake_info_if = airpcap_driver_fake_if_info_new(); if(fake_info_if == NULL) return FALSE; -/* - * XXX - When WPA will be supported, change this to: keys_in_list = g_list_length(key_list); +/* + * XXX - When WPA will be supported, change this to: keys_in_list = g_list_length(key_list); * but right now we will have to count only the WEP keys (or we will have a malloc-mess :-) ) */ n = g_list_length(key_list); @@ -428,8 +429,8 @@ if(!KeysCollection) */ KeysCollection->nKeys = keys_in_list; -/* - * XXX - If we have, let's say, six keys, the first three are WEP, then two are WPA, and the +/* + * XXX - If we have, let's say, six keys, the first three are WEP, then two are WPA, and the * last is WEP, we have to scroll the whole list (n) but increment the array counter only * when a WEP key is found (y) .. When WPA will be supported by the driver, I'll have to change * this @@ -440,7 +441,7 @@ for(i = 0; i < n; i++) { /* Retrieve the Item corresponding to the i-th key */ key_item = (decryption_key_t*)g_list_nth_data(key_list,i); - + /* * XXX - The AIRPDCAP_KEY_TYPE_WEP is the only supportd right now! * We will have to modify the AirpcapKey structure in order to @@ -2018,7 +2019,7 @@ for(i=0;i<n2;i++) } /* - * XXX - END : Remove from START to END when the WPA/WPA2 decryption will be implemented in + * XXX - END : Remove from START to END when the WPA/WPA2 decryption will be implemented in * the Driver */ @@ -2389,7 +2390,7 @@ decryption_key_t *dk; if(input_string == NULL) return NULL; -/* +/* * Parse the input_string. It should be in the form <key type>:<key data>[:<ssid>] * XXX - For backward compatibility, the a WEP key can be just a string of hexadecimal * characters (if WEP key is wrong, null will be returned...). @@ -2407,7 +2408,7 @@ if(n == 0) return NULL; } -/* +/* * 'n' contains the number of tokens. If the key string is correct, we should have * 2 or 3 tokens... If we have 1 token, it can be an 'old style' WEP key... check for it... */ @@ -2471,9 +2472,9 @@ if(n == 1) /* There were at least 2 tokens... copy the type value */ type = g_strdup(tokens[0]); -/* -* The second token is the key (right now it doesn't matter -* if it is a passphrase or an hexadecimal one) +/* +* The second token is the key (right now it doesn't matter +* if it is a passphrase or an hexadecimal one) */ key = g_strdup(tokens[1]); @@ -2492,7 +2493,7 @@ else ssid = NULL; } -/* +/* * Now the initial key string has been divided in two/three tokens... let's see * which kind of key it is, and if it is the correct form */ @@ -2623,7 +2624,7 @@ else if(g_strcasecmp(type,STRING_KEY_TYPE_WPA_PWD) == 0) /* WPA key *//* If the /* * XXX - Maybe we need some check on the characters? I'm not sure if only standard ASCII are ok... - */ + */ if( ((ssid_string->len) > WPA_SSID_MAX_CHAR_SIZE) || ((ssid_string->len) < WPA_SSID_MIN_CHAR_SIZE)) { g_string_free(key_string, TRUE); @@ -2645,9 +2646,9 @@ else if(g_strcasecmp(type,STRING_KEY_TYPE_WPA_PWD) == 0) /* WPA key *//* If the dk->type = AIRPDCAP_KEY_TYPE_WPA_PWD; dk->key = g_string_new(key); dk->bits = 256; /* This is the lenght of the array pf bytes that will be generated using key+ssid ...*/ - if(ssid != NULL) + if(ssid != NULL) dk->ssid = g_string_new(ssid); - else + else dk->ssid = NULL; g_string_free(key_string, TRUE); diff --git a/airpcap_loader.h b/airpcap_loader.h index 70a28465dc..84766c90e3 100644 --- a/airpcap_loader.h +++ b/airpcap_loader.h @@ -34,63 +34,13 @@ #define AIRPCAP_CHANNEL_ANY_NAME "ANY" -/* - * WEP_KEY_MAX_SIZE is in bytes, but each byte is rapresented in strings with an ascii char - * 4 bit are needed to store an exadecimal number, 8 bit to store a char... - */ -#define WEP_KEY_MAX_CHAR_SIZE (WEP_KEY_MAX_SIZE*2) - -/* - * WEP_KEY_MAX_SIZE is in bytes, this is in bits... - */ -#define WEP_KEY_MAX_BIT_SIZE (WEP_KEY_MAX_SIZE*8) - -#define WEP_KEY_MIN_CHAR_SIZE 2 -#define WEP_KEY_MIN_BIT_SIZE 8 - -/* - * XXX - The next #define should probably be moved in airpcap.h, - * near WEP_KEY_MAX_SIZE ... - */ -#define WPA_KEY_MAX_SIZE 63 /* 63 chars followed by a '\0' */ - -#define WPA_KEY_MAX_CHAR_SIZE (WPA_KEY_MAX_SIZE*1) -#define WPA_KEY_MAX_BIT_SIZE (WPA_KEY_MAX_SIZE*8) -#define WPA_KEY_MIN_CHAR_SIZE 8 -#define WPA_KEY_MIN_BIT_SIZE (WPA_KEY_MIN_CHAR_SIZE*8) - -/* - * XXX - The next #define should probably be moved in airpcap.h, - * near WEP_KEY_MAX_SIZE ... - */ -#define WPA_SSID_MAX_SIZE 32 - -#define WPA_SSID_MAX_CHAR_SIZE (WPA_SSID_MAX_SIZE*1) -#define WPA_SSID_MAX_BIT_SIZE (WPA_SSID_MAX_SIZE*8) -#define WPA_SSID_MIN_CHAR_SIZE 0 -#define WPA_SSID_MIN_BIT_SIZE (WPA_SSID_MIN_CHAR_SIZE*8) - -/* - * User can enter the binary PSK, instead of the passphrase+ssid... - */ -#define WPA_PSK_KEY_SIZE 32 /* Fixed size, 32 bytes (256bit) */ -#define WPA_PSK_KEY_CHAR_SIZE (WPA_PSK_KEY_SIZE*2) -#define WPA_PSK_KEY_BIT_SIZE (WPA_PSK_KEY_SIZE*8) - #define AIRPCAP_WEP_KEY_STRING "WEP" /* - * XXX - WPA_PWD is the passphrase+ssid and WPA-PSK is the hexadecimal key + * XXX - WPA_PWD is the passphrase+ssid and WPA-PSK is the hexadecimal key */ #define AIRPCAP_WPA_PWD_KEY_STRING "WPA-PWD" #define AIRPCAP_WPA_BIN_KEY_STRING "WPA-PSK" -/* - * Key string defines - */ -#define STRING_KEY_TYPE_WEP "wep" -#define STRING_KEY_TYPE_WPA_PWD "wpa-pwd" -#define STRING_KEY_TYPE_WPA_PSK "wpa-psk" - #define AIRPCAP_DLL_OK 0 #define AIRPCAP_DLL_OLD 1 #define AIRPCAP_DLL_ERROR 2 @@ -152,16 +102,6 @@ typedef struct { } airpcap_if_info_t; /* - * Struct to store infos about a specific decryption key. - */ -typedef struct { - GString *key; - GString *ssid; - guint bits; - guint type; -} decryption_key_t; - -/* * Struct used to store infos to pass to the preferences manager callbacks */ typedef struct { @@ -480,13 +420,13 @@ write_wlan_driver_wep_keys_to_regitry(GList* key_list); void airpcap_if_clear_decryption_settings(airpcap_if_info_t* info_if); -/* +/* * Function used to save to the preference file the Decryption Keys. */ int save_wlan_driver_wep_keys(); -/* +/* * Function used to save to the preference file the Decryption Keys. */ int diff --git a/airpdcap/Makefile.am b/airpdcap/Makefile.am index 5d7d27bc48..fc50901c83 100644 --- a/airpdcap/Makefile.am +++ b/airpdcap/Makefile.am @@ -21,32 +21,24 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +include Makefile.common -noinst_LIBRARIES = airpdcap.a +noinst_LIBRARIES = \ + libairpdcap.a + +DISTCLEANFILES = \ + libairpdcap.a CLEANFILES = \ - airpdcap.a \ + libairpdcap.a \ *~ MAINTAINERCLEANFILES = \ Makefile.in -airpdcap_a_SOURCES = \ - airpdcap.c \ - airpdcap_ccmp.c airpdcap_ccmp.h \ - airpdcap_debug.c airpdcap_debug.h \ - airpdcap_md5.c airpdcap_md5.h \ - airpdcap_rijndael.c airpdcap_rijndael.h \ - airpdcap_sha1.c airpdcap_sha1.h \ - airpdcap_tkip.c airpdcap_tkip.h \ - airpdcap_wep.c airpdcap_wep.h \ - airpdcap_interop.h \ - airpdcap_ws.h \ - airpdcap_types.h \ - airpdcap_user.h \ - airpdcap_system.h - -airpdcap_a_DEPENDENCIES = +libairpdcap_a_SOURCES = \ + $(LIBAIRPDCAP_SRC) \ + $(LIBAIRPDCAP_INCLUDES) EXTRA_DIST = \ Makefile.nmake diff --git a/airpdcap/Makefile.nmake b/airpdcap/Makefile.nmake index 10cadce94f..e2f5f4bd54 100644 --- a/airpdcap/Makefile.nmake +++ b/airpdcap/Makefile.nmake @@ -7,7 +7,7 @@ include ..\config.nmake ############### no need to modify below this line ######### -CFLAGS=-DHAVE_CONFIG_H -DHAVE_WIRESHARK $(GLIB_CFLAGS) -D_U_="" $(LOCAL_CFLAGS) +CFLAGS=-DHAVE_CONFIG_H $(GLIB_CFLAGS) -D_U_="" $(LOCAL_CFLAGS) .c.obj:: $(CC) $(CFLAGS) -Fd.\ -c $< diff --git a/airpdcap/airpdcap.c b/airpdcap/airpdcap.c index 7f7d8dd3d0..ce220ac472 100644 --- a/airpdcap/airpdcap.c +++ b/airpdcap/airpdcap.c @@ -4,13 +4,10 @@ #include "airpdcap_system.h" #include "airpdcap_int.h" -#include "airpdcap_tkip.h" -#include "airpdcap_ccmp.h" #include "airpdcap_wep.h" #include "airpdcap_sha1.h" -#include "airpdcap_md5.h" -#include "airpdcap_debug.h" +#include "airpdcap_debug.h" /* */ /******************************************************************************/ @@ -20,36 +17,35 @@ #define AIRPDCAP_SHA_DIGEST_LEN 20 /* EAPOL definitions */ -/*! -/brief -Length of the EAPOL-Key key confirmation key (KCK) used to calculate MIC over EAPOL frame and validate an EAPOL packet (128 bits) -*/ +/** + * Length of the EAPOL-Key key confirmation key (KCK) used to calculate + * MIC over EAPOL frame and validate an EAPOL packet (128 bits) + */ #define AIRPDCAP_WPA_KCK_LEN 16 -/*! -/brief -Offset of the Key MIC in the EAPOL packet body -*/ +/** + *Offset of the Key MIC in the EAPOL packet body + */ #define AIRPDCAP_WPA_MICKEY_OFFSET 77 -/*! -/brief -Maximum length of the EAPOL packet (it depends on the maximum MAC frame size) -*/ +/** + * Maximum length of the EAPOL packet (it depends on the maximum MAC + * frame size) + */ #define AIRPDCAP_WPA_MAX_EAPOL_LEN 4095 -/*! -/brief -EAPOL Key Descriptor Version 1, used for all EAPOL-Key frames to and from a STA when neither the -group nor pairwise ciphers are CCMP for Key Descriptor 1. -/note -Defined in 802.11i-2004, page 78 -*/ +/** + * EAPOL Key Descriptor Version 1, used for all EAPOL-Key frames to and + * from a STA when neither the group nor pairwise ciphers are CCMP for + * Key Descriptor 1. + * @note + * Defined in 802.11i-2004, page 78 + */ #define AIRPDCAP_WPA_KEY_VER_CCMP 1 -/*! -/brief -EAPOL Key Descriptor Version 2, used for all EAPOL-Key frames to and from a STA when either the -pairwise or the group cipher is AES-CCMP for Key Descriptor 2. -/note -Defined in 802.11i-2004, page 78 -*/ +/** + * EAPOL Key Descriptor Version 2, used for all EAPOL-Key frames to and + * from a STA when either the pairwise or the group cipher is AES-CCMP + * for Key Descriptor 2. + * /note + * Defined in 802.11i-2004, page 78 + */ #define AIRPDCAP_WPA_KEY_VER_AES_CCMP 2 /* */ /******************************************************************************/ @@ -77,154 +73,137 @@ extern const UINT32 crc32_table[256]; extern "C" { #endif - /*! - /brief - It is a step of the PBKDF2 (specifically the PKCS #5 v2.0) defined in the RFC 2898 to derive a key (used as PMK in WPA) - - /param password - [IN] pointer to a password (sequence of between 8 and 63 ASCII encoded characters) - - /param ssid - [IN] pointer to the SSID string encoded in max 32 ASCII encoded characters - - /param iterations - [IN] times to hash the password (4096 for WPA) - - /param count - [IN] ??? - - /param output - [OUT] pointer to a preallocated buffer of AIRPDCAP_SHA_DIGEST_LEN characters that will contain a part of the key - */ - INT AirPDcapRsnaPwd2PskStep( - const CHAR *password, - const CHAR *ssid, - const size_t ssidLength, - const INT iterations, - const INT count, - UCHAR *output) - ; - - /*! - /brief - It calculates the passphrase-to-PSK mapping reccomanded for use with RSNAs. This implementation uses the PBKDF2 method defined in the RFC 2898. - - /param password - [IN] pointer to a password (sequence of between 8 and 63 ASCII encoded characters) - - /param ssid - [IN] pointer to the SSID string encoded in max 32 ASCII encoded characters - - /param output - [OUT] calculated PSK (to use as PMK in WPA) - - /note - Described in 802.11i-2004, page 165 - */ - INT AirPDcapRsnaPwd2Psk( - const CHAR *password, - const CHAR *ssid, - const size_t ssidLength, - UCHAR *output) - ; - - INT AirPDcapRsnaMng( - UCHAR *decrypt_data, - size_t *decrypt_len, - PAIRPDCAP_KEY_ITEM key, - AIRPDCAP_SEC_ASSOCIATION *sa, - INT offset, - UINT8 fcsPresent) - ; - - INT AirPDcapWepMng( - PAIRPDCAP_CONTEXT ctx, - UCHAR *decrypt_data, - size_t *decrypt_len, - PAIRPDCAP_KEY_ITEM key, - AIRPDCAP_SEC_ASSOCIATION *sa, - INT offset, - UINT8 fcsPresent) - ; - - INT AirPDcapRsna4WHandshake( - PAIRPDCAP_CONTEXT ctx, - const UCHAR *data, - AIRPDCAP_SEC_ASSOCIATION *sa, - PAIRPDCAP_KEY_ITEM key, - INT offset) - ; - ; - /*! - /brief - It checks whether the specified key is corrected or not. - /note - For a standard WEP key the length will be changed to the standard length, and the type changed in a generic WEP key. - - /param key - [IN] pointer to the key to validate - - /return - - TRUE: the key contains valid fields and values - - FALSE: the key has some invalid field or value - */ - INT AirPDcapValidateKey( - PAIRPDCAP_KEY_ITEM key) - ; - - INT AirPDcapRsnaMicCheck( - UCHAR *eapol, - const USHORT eapol_len, - const UCHAR KCK[AIRPDCAP_WPA_KCK_LEN], - const USHORT key_ver) - ; - - /*! - /brief it gets the index of the Security Association structure for the specified BSSID and STA MAC address - /param ctx - [IN] pointer to the current context - /param id - [IN] id of the association (composed by BSSID and MAC of the station) - /return - - index of the Security Association structure if found - - -1, if the specified addresses pair BSSID-STA MAC has not been found - */ - INT AirPDcapGetSa( - PAIRPDCAP_CONTEXT ctx, - AIRPDCAP_SEC_ASSOCIATION_ID *id) - ; - - INT AirPDcapFreeSa( - PAIRPDCAP_CONTEXT ctx, - INT index) /* index of the structure to free */ - ; - - INT AirPDcapStoreSa( - PAIRPDCAP_CONTEXT ctx, - AIRPDCAP_SEC_ASSOCIATION_ID *id) - ; - - UCHAR * AirPDcapGetStaAddress( - PAIRPDCAP_MAC_FRAME frame) - ; - - UCHAR * AirPDcapGetBssidAddress( - PAIRPDCAP_MAC_FRAME frame) - ; - - void AirPDcapRsnaPrfX( - AIRPDCAP_SEC_ASSOCIATION *sa, - const UCHAR pmk[32], - const UCHAR snonce[32], - const INT x, /* for TKIP 512, for CCMP 384 */ - UCHAR *ptk) - ; - - INT AirPDcapAlgCrc32( - UCHAR *buf, - size_t nr, - ULONG *cval) - ; +/** + * It is a step of the PBKDF2 (specifically the PKCS #5 v2.0) defined in + * the RFC 2898 to derive a key (used as PMK in WPA) + * @param password [IN] pointer to a password (sequence of between 8 and + * 63 ASCII encoded characters) + * @param ssid [IN] pointer to the SSID string encoded in max 32 ASCII + * encoded characters + * @param iterations [IN] times to hash the password (4096 for WPA) + * @param count [IN] ??? + * @param output [OUT] pointer to a preallocated buffer of + * AIRPDCAP_SHA_DIGEST_LEN characters that will contain a part of the key + */ +INT AirPDcapRsnaPwd2PskStep( + const CHAR *password, + const CHAR *ssid, + const size_t ssidLength, + const INT iterations, + const INT count, + UCHAR *output) + ; + +/** + * It calculates the passphrase-to-PSK mapping reccomanded for use with + * RSNAs. This implementation uses the PBKDF2 method defined in the RFC + * 2898. + * @param password [IN] pointer to a password (sequence of between 8 and + * 63 ASCII encoded characters) + * @param ssid [IN] pointer to the SSID string encoded in max 32 ASCII + * encoded characters + * @param output [OUT] calculated PSK (to use as PMK in WPA) + * @note + * Described in 802.11i-2004, page 165 + */ +INT AirPDcapRsnaPwd2Psk( + const CHAR *password, + const CHAR *ssid, + const size_t ssidLength, + UCHAR *output) + ; + +INT AirPDcapRsnaMng( + UCHAR *decrypt_data, + size_t *decrypt_len, + PAIRPDCAP_KEY_ITEM key, + AIRPDCAP_SEC_ASSOCIATION *sa, + INT offset, + UINT8 fcsPresent) + ; + +INT AirPDcapWepMng( + PAIRPDCAP_CONTEXT ctx, + UCHAR *decrypt_data, + size_t *decrypt_len, + PAIRPDCAP_KEY_ITEM key, + AIRPDCAP_SEC_ASSOCIATION *sa, + INT offset, + UINT8 fcsPresent) + ; + +INT AirPDcapRsna4WHandshake( + PAIRPDCAP_CONTEXT ctx, + const UCHAR *data, + AIRPDCAP_SEC_ASSOCIATION *sa, + PAIRPDCAP_KEY_ITEM key, + INT offset) + ; +/** + * It checks whether the specified key is corrected or not. + * @note + * For a standard WEP key the length will be changed to the standard + * length, and the type changed in a generic WEP key. + * @param key [IN] pointer to the key to validate + * @return + * - TRUE: the key contains valid fields and values + * - FALSE: the key has some invalid field or value + */ +INT AirPDcapValidateKey( + PAIRPDCAP_KEY_ITEM key) + ; + +INT AirPDcapRsnaMicCheck( + UCHAR *eapol, + const USHORT eapol_len, + const UCHAR KCK[AIRPDCAP_WPA_KCK_LEN], + const USHORT key_ver) + ; + +/** + * @param ctx [IN] pointer to the current context + * @param id [IN] id of the association (composed by BSSID and MAC of + * the station) + * @return + * - index of the Security Association structure if found + * - -1, if the specified addresses pair BSSID-STA MAC has not been found + */ +INT AirPDcapGetSa( + PAIRPDCAP_CONTEXT ctx, + AIRPDCAP_SEC_ASSOCIATION_ID *id) + ; + +INT AirPDcapFreeSa( + PAIRPDCAP_CONTEXT ctx, + INT index) /* index of the structure to free */ + ; + +INT AirPDcapStoreSa( + PAIRPDCAP_CONTEXT ctx, + AIRPDCAP_SEC_ASSOCIATION_ID *id) + ; + +UCHAR * AirPDcapGetStaAddress( + PAIRPDCAP_MAC_FRAME frame) + ; + +UCHAR * AirPDcapGetBssidAddress( + PAIRPDCAP_MAC_FRAME frame) + ; + +void AirPDcapRsnaPrfX( + AIRPDCAP_SEC_ASSOCIATION *sa, + const UCHAR pmk[32], + const UCHAR snonce[32], + const INT x, /* for TKIP 512, for CCMP 384 */ + UCHAR *ptk) + ; + +INT AirPDcapAlgCrc32( + UCHAR *buf, + size_t nr, + ULONG *cval) + ; #ifdef __cplusplus } @@ -238,349 +217,350 @@ extern "C" { #ifdef __cplusplus extern "C" { #endif - INT AirPDcapPacketProcess( - PAIRPDCAP_CONTEXT ctx, - const UCHAR *data, - const size_t len, - UCHAR *decrypt_data, - size_t *decrypt_len, - PAIRPDCAP_KEY_ITEM key, - UINT8 fcsPresent, - UINT8 radioTapPresent, - UINT8 mngHandshake, - UINT8 mngDecrypt) - { - size_t mac_header_len; - UCHAR *address; - AIRPDCAP_SEC_ASSOCIATION_ID id; - INT index; - PAIRPDCAP_SEC_ASSOCIATION sa; - INT offset; - UINT16 bodyLength; + +INT AirPDcapPacketProcess( + PAIRPDCAP_CONTEXT ctx, + const UCHAR *data, + const size_t len, + UCHAR *decrypt_data, + size_t *decrypt_len, + PAIRPDCAP_KEY_ITEM key, + UINT8 fcsPresent, + UINT8 radioTapPresent, + UINT8 mngHandshake, + UINT8 mngDecrypt) +{ + size_t mac_header_len; + UCHAR *address; + AIRPDCAP_SEC_ASSOCIATION_ID id; + INT index; + PAIRPDCAP_SEC_ASSOCIATION sa; + INT offset; + UINT16 bodyLength; #ifdef _DEBUG - CHAR msgbuf[255]; + CHAR msgbuf[255]; #endif - AIRPDCAP_DEBUG_TRACE_START("AirPDcapPacketProcess"); - - if (ctx==NULL) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "NULL context", AIRPDCAP_DEBUG_LEVEL_5); - AIRPDCAP_DEBUG_TRACE_END("AirPDcapPacketProcess"); - return AIRPDCAP_RET_UNSUCCESS; - } - if (data==NULL || len==0) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "NULL data or length=0", AIRPDCAP_DEBUG_LEVEL_5); - AIRPDCAP_DEBUG_TRACE_END("AirPDcapPacketProcess"); - return AIRPDCAP_RET_UNSUCCESS; - } - - if (radioTapPresent) - offset=AIRPDCAP_RADIOTAP_HEADER_LEN; - else - offset=0; - - /* check if the packet is of data type */ - /* TODO consider packets send on an ad-hoc net (QoS) */ - if (AIRPDCAP_TYPE(data[offset])!=AIRPDCAP_TYPE_DATA) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "not data packet", AIRPDCAP_DEBUG_LEVEL_5); - return AIRPDCAP_RET_NO_DATA; - } - - /* check correct packet size, to avoid wrong elaboration of encryption algorithms */ - mac_header_len=AIRPDCAP_HEADER_LEN(data[offset+1]); - if (len < (UINT)(mac_header_len+AIRPDCAP_CRYPTED_DATA_MINLEN)) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "minimum length violated", AIRPDCAP_DEBUG_LEVEL_5); - return AIRPDCAP_RET_WRONG_DATA_SIZE; - } - - /* get BSSID */ - if ( (address=AirPDcapGetBssidAddress((PAIRPDCAP_MAC_FRAME)(data+offset))) != NULL) { - memcpy(id.bssid, address, AIRPDCAP_MAC_LEN); + AIRPDCAP_DEBUG_TRACE_START("AirPDcapPacketProcess"); + + if (ctx==NULL) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "NULL context", AIRPDCAP_DEBUG_LEVEL_5); + AIRPDCAP_DEBUG_TRACE_END("AirPDcapPacketProcess"); + return AIRPDCAP_RET_UNSUCCESS; + } + if (data==NULL || len==0) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "NULL data or length=0", AIRPDCAP_DEBUG_LEVEL_5); + AIRPDCAP_DEBUG_TRACE_END("AirPDcapPacketProcess"); + return AIRPDCAP_RET_UNSUCCESS; + } + + if (radioTapPresent) + offset=AIRPDCAP_RADIOTAP_HEADER_LEN; + else + offset=0; + + /* check if the packet is of data type */ + /* TODO consider packets send on an ad-hoc net (QoS) */ + if (AIRPDCAP_TYPE(data[offset])!=AIRPDCAP_TYPE_DATA) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "not data packet", AIRPDCAP_DEBUG_LEVEL_5); + return AIRPDCAP_RET_NO_DATA; + } + + /* check correct packet size, to avoid wrong elaboration of encryption algorithms */ + mac_header_len=AIRPDCAP_HEADER_LEN(data[offset+1]); + if (len < (UINT)(mac_header_len+AIRPDCAP_CRYPTED_DATA_MINLEN)) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "minimum length violated", AIRPDCAP_DEBUG_LEVEL_5); + return AIRPDCAP_RET_WRONG_DATA_SIZE; + } + + /* get BSSID */ + if ( (address=AirPDcapGetBssidAddress((PAIRPDCAP_MAC_FRAME)(data+offset))) != NULL) { + memcpy(id.bssid, address, AIRPDCAP_MAC_LEN); #ifdef _DEBUG - sprintf(msgbuf, "BSSID: %2X.%2X.%2X.%2X.%2X.%2X\t", id.bssid[0],id.bssid[1],id.bssid[2],id.bssid[3],id.bssid[4],id.bssid[5]); + sprintf(msgbuf, "BSSID: %2X.%2X.%2X.%2X.%2X.%2X\t", id.bssid[0],id.bssid[1],id.bssid[2],id.bssid[3],id.bssid[4],id.bssid[5]); #endif - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", msgbuf, AIRPDCAP_DEBUG_LEVEL_3); - } else { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "BSSID not found", AIRPDCAP_DEBUG_LEVEL_5); - return AIRPDCAP_RET_REQ_DATA; - } - - /* get STA address */ - if ( (address=AirPDcapGetStaAddress((PAIRPDCAP_MAC_FRAME)(data+offset))) != NULL) { - memcpy(id.sta, address, AIRPDCAP_MAC_LEN); + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", msgbuf, AIRPDCAP_DEBUG_LEVEL_3); + } else { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "BSSID not found", AIRPDCAP_DEBUG_LEVEL_5); + return AIRPDCAP_RET_REQ_DATA; + } + + /* get STA address */ + if ( (address=AirPDcapGetStaAddress((PAIRPDCAP_MAC_FRAME)(data+offset))) != NULL) { + memcpy(id.sta, address, AIRPDCAP_MAC_LEN); #ifdef _DEBUG - sprintf(msgbuf, "ST_MAC: %2X.%2X.%2X.%2X.%2X.%2X\t", id.sta[0],id.sta[1],id.sta[2],id.sta[3],id.sta[4],id.sta[5]); + sprintf(msgbuf, "ST_MAC: %2X.%2X.%2X.%2X.%2X.%2X\t", id.sta[0],id.sta[1],id.sta[2],id.sta[3],id.sta[4],id.sta[5]); #endif - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", msgbuf, AIRPDCAP_DEBUG_LEVEL_3); - } else { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "SA not found", AIRPDCAP_DEBUG_LEVEL_5); - return AIRPDCAP_RET_REQ_DATA; - } - - /* search for a cached Security Association for current BSSID and station MAC */ - if ((index=AirPDcapGetSa(ctx, &id))==-1) { - /* create a new Security Association */ - if ((index=AirPDcapStoreSa(ctx, &id))==-1) { - return AIRPDCAP_RET_UNSUCCESS; - } - } - - /* get the Security Association structure */ - sa=&ctx->sa[index]; - - /* cache offset in the packet data (to scan encryption data) */ - offset+=AIRPDCAP_HEADER_LEN(data[offset+1]); - - /* check if data is encrypted (use the WEP bit in the Frame Control field) */ - if (AIRPDCAP_WEP(data[1])==0) - { - if (mngHandshake) { - /* data is sent in cleartext, check if is an authentication message or end the process */ - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Unencrypted data", AIRPDCAP_DEBUG_LEVEL_3); - - /* check if the packet as an LLC header and the packet is 802.1X authentication (IEEE 802.1X-2004, pg. 24) */ - if (data[offset]==0xAA && /* DSAP=SNAP */ - data[offset+1]==0xAA && /* SSAP=SNAP */ - data[offset+2]==0x03 && /* Control field=Unnumbered frame */ - data[offset+3]==0x00 && /* Org. code=encaps. Ethernet */ - data[offset+4]==0x00 && - data[offset+5]==0x00 && - data[offset+6]==0x88 && /* Type: 802.1X authentication */ - data[offset+7]==0x8E) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Authentication: EAPOL packet", AIRPDCAP_DEBUG_LEVEL_3); - - /* skip LLC header */ - offset+=8; - - /* check the version of the EAPOL protocol used (IEEE 802.1X-2004, pg. 24) */ - /* TODO EAPOL protocol version to check? */ - /*if (data[offset]!=2) { - AIRPDCAP_DEBUG_PRINT_LINE("EAPOL protocol version not recognized", AIRPDCAP_DEBUG_LEVEL_5); - return AIRPDCAP_RET_NO_VALID_HANDSHAKE; - }*/ - - /* check if the packet is a EAPOL-Key (0x03) (IEEE 802.1X-2004, pg. 25) */ - if (data[offset+1]!=3) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Not EAPOL-Key", AIRPDCAP_DEBUG_LEVEL_5); - return AIRPDCAP_RET_NO_VALID_HANDSHAKE; - } - - /* get and check the body length (IEEE 802.1X-2004, pg. 25) */ - bodyLength=ntohs(*(UINT16 *)(data+offset+2)); - if (((len-offset-4)!=bodyLength && !fcsPresent) || ((len-offset-8)!=bodyLength && fcsPresent)) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "EAPOL body not valid (wrong length)", AIRPDCAP_DEBUG_LEVEL_5); - return AIRPDCAP_RET_NO_VALID_HANDSHAKE; - } - - /* skip EAPOL MPDU and go to the first byte of the body */ - offset+=4; - - /* check if the key descriptor type is valid (IEEE 802.1X-2004, pg. 27) */ - if (/*data[offset]!=0x1 &&*/ /* RC4 Key Descriptor Type (deprecated) */ - data[offset]!=0x2 && /* IEEE 802.11 Key Descriptor Type */ - data[offset]!=0xFE) /* TODO what's this value??? */ - { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Not valid key descriptor type", AIRPDCAP_DEBUG_LEVEL_5); - return AIRPDCAP_RET_NO_VALID_HANDSHAKE; - } - - /* start with descriptor body */ - offset+=1; - - /* manage the 4-way handshake to define the key */ - return AirPDcapRsna4WHandshake(ctx, data, sa, key, offset); - } else { - /* cleartext message, not authentication */ - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "No authentication data", AIRPDCAP_DEBUG_LEVEL_5); - return AIRPDCAP_RET_NO_DATA_ENCRYPTED; - } - } - } else { - if (mngDecrypt) { - - if (decrypt_data==NULL) - return AIRPDCAP_RET_UNSUCCESS; - - /* create new header and data to modify */ - *decrypt_len=len; - memcpy(decrypt_data, data, *decrypt_len); - - /* encrypted data */ - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Encrypted data", AIRPDCAP_DEBUG_LEVEL_3); - - if (fcsPresent) - /* remove from next computation FCS */ - *decrypt_len-=4; - - /* check the Extension IV to distinguish between WEP encryption and WPA encryption */ - /* refer to IEEE 802.11i-2004, 8.2.1.2, pag.35 for WEP, */ - /* IEEE 802.11i-2004, 8.3.2.2, pag. 45 for TKIP, */ - /* IEEE 802.11i-2004, 8.3.3.2, pag. 57 for CCMP */ - if (AIRPDCAP_EXTIV(data[offset+3])==0) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "WEP encryption", AIRPDCAP_DEBUG_LEVEL_3); - return AirPDcapWepMng(ctx, decrypt_data, decrypt_len, key, sa, offset, fcsPresent); - } else { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "TKIP or CCMP encryption", AIRPDCAP_DEBUG_LEVEL_3); - return AirPDcapRsnaMng(decrypt_data, decrypt_len, key, sa, offset, fcsPresent); - } - } - } - - return AIRPDCAP_RET_UNSUCCESS; - } - - INT AirPDcapSetKeys( - PAIRPDCAP_CONTEXT ctx, - AIRPDCAP_KEY_ITEM keys[], - const size_t keys_nr) - { - INT i; - INT success; - AIRPDCAP_DEBUG_TRACE_START("AirPDcapSetKeys"); - - if (ctx==NULL || keys==NULL) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "NULL context or NULL keys array", AIRPDCAP_DEBUG_LEVEL_3); - AIRPDCAP_DEBUG_TRACE_END("AirPDcapSetKeys"); - return 0; - } - - if (keys_nr>AIRPDCAP_MAX_KEYS_NR) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Keys number greater than maximum", AIRPDCAP_DEBUG_LEVEL_3); - AIRPDCAP_DEBUG_TRACE_END("AirPDcapSetKeys"); - return 0; - } - - /* clean keys collection before setting new ones */ - AirPDcapCleanKeys(ctx); - - /* check and insert keys */ - for (i=0, success=0; i<(INT)keys_nr; i++) { - if (AirPDcapValidateKey(keys+i)==TRUE) { - if (keys[i].KeyType==AIRPDCAP_KEY_TYPE_WPA_PWD) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Set a WPA-PWD key", AIRPDCAP_DEBUG_LEVEL_4); - AirPDcapRsnaPwd2Psk(keys[i].KeyData.Wpa.UserPwd.Passphrase, keys[i].KeyData.Wpa.UserPwd.Ssid, keys[i].KeyData.Wpa.UserPwd.SsidLen, keys[i].KeyData.Wpa.Psk); - } + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", msgbuf, AIRPDCAP_DEBUG_LEVEL_3); + } else { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "SA not found", AIRPDCAP_DEBUG_LEVEL_5); + return AIRPDCAP_RET_REQ_DATA; + } + + /* search for a cached Security Association for current BSSID and station MAC */ + if ((index=AirPDcapGetSa(ctx, &id))==-1) { + /* create a new Security Association */ + if ((index=AirPDcapStoreSa(ctx, &id))==-1) { + return AIRPDCAP_RET_UNSUCCESS; + } + } + + /* get the Security Association structure */ + sa=&ctx->sa[index]; + + /* cache offset in the packet data (to scan encryption data) */ + offset+=AIRPDCAP_HEADER_LEN(data[offset+1]); + + /* check if data is encrypted (use the WEP bit in the Frame Control field) */ + if (AIRPDCAP_WEP(data[1])==0) + { + if (mngHandshake) { + /* data is sent in cleartext, check if is an authentication message or end the process */ + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Unencrypted data", AIRPDCAP_DEBUG_LEVEL_3); + + /* check if the packet as an LLC header and the packet is 802.1X authentication (IEEE 802.1X-2004, pg. 24) */ + if (data[offset]==0xAA && /* DSAP=SNAP */ + data[offset+1]==0xAA && /* SSAP=SNAP */ + data[offset+2]==0x03 && /* Control field=Unnumbered frame */ + data[offset+3]==0x00 && /* Org. code=encaps. Ethernet */ + data[offset+4]==0x00 && + data[offset+5]==0x00 && + data[offset+6]==0x88 && /* Type: 802.1X authentication */ + data[offset+7]==0x8E) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Authentication: EAPOL packet", AIRPDCAP_DEBUG_LEVEL_3); + + /* skip LLC header */ + offset+=8; + + /* check the version of the EAPOL protocol used (IEEE 802.1X-2004, pg. 24) */ + /* TODO EAPOL protocol version to check? */ + /*if (data[offset]!=2) { + AIRPDCAP_DEBUG_PRINT_LINE("EAPOL protocol version not recognized", AIRPDCAP_DEBUG_LEVEL_5); + return AIRPDCAP_RET_NO_VALID_HANDSHAKE; + }*/ + + /* check if the packet is a EAPOL-Key (0x03) (IEEE 802.1X-2004, pg. 25) */ + if (data[offset+1]!=3) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Not EAPOL-Key", AIRPDCAP_DEBUG_LEVEL_5); + return AIRPDCAP_RET_NO_VALID_HANDSHAKE; + } + + /* get and check the body length (IEEE 802.1X-2004, pg. 25) */ + bodyLength=ntohs(*(UINT16 *)(data+offset+2)); + if (((len-offset-4)!=bodyLength && !fcsPresent) || ((len-offset-8)!=bodyLength && fcsPresent)) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "EAPOL body not valid (wrong length)", AIRPDCAP_DEBUG_LEVEL_5); + return AIRPDCAP_RET_NO_VALID_HANDSHAKE; + } + + /* skip EAPOL MPDU and go to the first byte of the body */ + offset+=4; + + /* check if the key descriptor type is valid (IEEE 802.1X-2004, pg. 27) */ + if (/*data[offset]!=0x1 &&*/ /* RC4 Key Descriptor Type (deprecated) */ + data[offset]!=0x2 && /* IEEE 802.11 Key Descriptor Type */ + data[offset]!=0xFE) /* TODO what's this value??? */ + { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Not valid key descriptor type", AIRPDCAP_DEBUG_LEVEL_5); + return AIRPDCAP_RET_NO_VALID_HANDSHAKE; + } + + /* start with descriptor body */ + offset+=1; + + /* manage the 4-way handshake to define the key */ + return AirPDcapRsna4WHandshake(ctx, data, sa, key, offset); + } else { + /* cleartext message, not authentication */ + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "No authentication data", AIRPDCAP_DEBUG_LEVEL_5); + return AIRPDCAP_RET_NO_DATA_ENCRYPTED; + } + } + } else { + if (mngDecrypt) { + + if (decrypt_data==NULL) + return AIRPDCAP_RET_UNSUCCESS; + + /* create new header and data to modify */ + *decrypt_len=len; + memcpy(decrypt_data, data, *decrypt_len); + + /* encrypted data */ + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Encrypted data", AIRPDCAP_DEBUG_LEVEL_3); + + if (fcsPresent) + /* remove from next computation FCS */ + *decrypt_len-=4; + + /* check the Extension IV to distinguish between WEP encryption and WPA encryption */ + /* refer to IEEE 802.11i-2004, 8.2.1.2, pag.35 for WEP, */ + /* IEEE 802.11i-2004, 8.3.2.2, pag. 45 for TKIP, */ + /* IEEE 802.11i-2004, 8.3.3.2, pag. 57 for CCMP */ + if (AIRPDCAP_EXTIV(data[offset+3])==0) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "WEP encryption", AIRPDCAP_DEBUG_LEVEL_3); + return AirPDcapWepMng(ctx, decrypt_data, decrypt_len, key, sa, offset, fcsPresent); + } else { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "TKIP or CCMP encryption", AIRPDCAP_DEBUG_LEVEL_3); + return AirPDcapRsnaMng(decrypt_data, decrypt_len, key, sa, offset, fcsPresent); + } + } + } + + return AIRPDCAP_RET_UNSUCCESS; +} + +INT AirPDcapSetKeys( + PAIRPDCAP_CONTEXT ctx, + AIRPDCAP_KEY_ITEM keys[], + const size_t keys_nr) +{ + INT i; + INT success; + AIRPDCAP_DEBUG_TRACE_START("AirPDcapSetKeys"); + + if (ctx==NULL || keys==NULL) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "NULL context or NULL keys array", AIRPDCAP_DEBUG_LEVEL_3); + AIRPDCAP_DEBUG_TRACE_END("AirPDcapSetKeys"); + return 0; + } + + if (keys_nr>AIRPDCAP_MAX_KEYS_NR) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Keys number greater than maximum", AIRPDCAP_DEBUG_LEVEL_3); + AIRPDCAP_DEBUG_TRACE_END("AirPDcapSetKeys"); + return 0; + } + + /* clean keys collection before setting new ones */ + AirPDcapCleanKeys(ctx); + + /* check and insert keys */ + for (i=0, success=0; i<(INT)keys_nr; i++) { + if (AirPDcapValidateKey(keys+i)==TRUE) { + if (keys[i].KeyType==AIRPDCAP_KEY_TYPE_WPA_PWD) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Set a WPA-PWD key", AIRPDCAP_DEBUG_LEVEL_4); + AirPDcapRsnaPwd2Psk(keys[i].KeyData.Wpa.UserPwd.Passphrase, keys[i].KeyData.Wpa.UserPwd.Ssid, keys[i].KeyData.Wpa.UserPwd.SsidLen, keys[i].KeyData.Wpa.Psk); + } #ifdef _DEBUG - else if (keys[i].KeyType==AIRPDCAP_KEY_TYPE_WPA_PMK) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Set a WPA-PMK key", AIRPDCAP_DEBUG_LEVEL_4); - } else if (keys[i].KeyType==AIRPDCAP_KEY_TYPE_WEP) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Set a WEP key", AIRPDCAP_DEBUG_LEVEL_4); - } else { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Set a key", AIRPDCAP_DEBUG_LEVEL_4); - } + else if (keys[i].KeyType==AIRPDCAP_KEY_TYPE_WPA_PMK) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Set a WPA-PMK key", AIRPDCAP_DEBUG_LEVEL_4); + } else if (keys[i].KeyType==AIRPDCAP_KEY_TYPE_WEP) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Set a WEP key", AIRPDCAP_DEBUG_LEVEL_4); + } else { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Set a key", AIRPDCAP_DEBUG_LEVEL_4); + } #endif - ctx->keys[success].KeyType=keys[i].KeyType; - memcpy(&ctx->keys[success].KeyData, &keys[i].KeyData, sizeof(keys[i].KeyData)); - - success++; - } - } - - ctx->keys_nr=success; - - AIRPDCAP_DEBUG_TRACE_END("AirPDcapSetKeys"); - return success; - } - - INT AirPDcapCleanKeys( - PAIRPDCAP_CONTEXT ctx) - { - INT i; - AIRPDCAP_DEBUG_TRACE_START("AirPDcapCleanKeys"); - - if (ctx==NULL) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapCleanKeys", "NULL context", AIRPDCAP_DEBUG_LEVEL_5); - AIRPDCAP_DEBUG_TRACE_END("AirPDcapCleanKeys"); - return 0; - } - - for (i=0; i<AIRPDCAP_MAX_KEYS_NR; i++) { - memset(&ctx->keys[i], 0, sizeof(AIRPDCAP_KEY_ITEM)); - } - - ctx->keys_nr=0; - - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapCleanKeys", "Keys collection cleaned!", AIRPDCAP_DEBUG_LEVEL_5); - AIRPDCAP_DEBUG_TRACE_END("AirPDcapCleanKeys"); - - return i; - } - - INT AirPDcapGetKeys( - const PAIRPDCAP_CONTEXT ctx, - AIRPDCAP_KEY_ITEM keys[], - const size_t keys_nr) - { - UINT i; - UINT j; - AIRPDCAP_DEBUG_TRACE_START("AirPDcapGetKeys"); - - if (ctx==NULL) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapGetKeys", "NULL context", AIRPDCAP_DEBUG_LEVEL_5); - AIRPDCAP_DEBUG_TRACE_END("AirPDcapGetKeys"); - return 0; - } else if (keys==NULL) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapGetKeys", "NULL keys array", AIRPDCAP_DEBUG_LEVEL_5); - AIRPDCAP_DEBUG_TRACE_END("AirPDcapGetKeys"); - return (INT)ctx->keys_nr; - } else { - for (i=0, j=0; i<ctx->keys_nr && i<keys_nr && i<AIRPDCAP_MAX_KEYS_NR; i++) { - keys[j].KeyType=ctx->keys[i].KeyType; - memcpy(&keys[j].KeyData, &ctx->keys[i].KeyData, sizeof(keys[j].KeyData)); - j++; - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapGetKeys", "Got a key", AIRPDCAP_DEBUG_LEVEL_5); - } - - AIRPDCAP_DEBUG_TRACE_END("AirPDcapGetKeys"); - return j; - } - } - - INT AirPDcapInitContext( - PAIRPDCAP_CONTEXT ctx) - { - AIRPDCAP_DEBUG_TRACE_START("AirPDcapInitContext"); - - if (ctx==NULL) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapInitContext", "NULL context", AIRPDCAP_DEBUG_LEVEL_5); - AIRPDCAP_DEBUG_TRACE_END("AirPDcapInitContext"); - return AIRPDCAP_RET_UNSUCCESS; - } - - AirPDcapCleanKeys(ctx); - - ctx->first_free_index=0; - ctx->index=-1; - ctx->last_stored_index=-1; - - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapInitContext", "Context initialized!", AIRPDCAP_DEBUG_LEVEL_5); - AIRPDCAP_DEBUG_TRACE_END("AirPDcapInitContext"); - return AIRPDCAP_RET_SUCCESS; - } - - INT AirPDcapDestroyContext( - PAIRPDCAP_CONTEXT ctx) - { - AIRPDCAP_DEBUG_TRACE_START("AirPDcapDestroyContext"); - - if (ctx==NULL) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapDestroyContext", "NULL context", AIRPDCAP_DEBUG_LEVEL_5); - AIRPDCAP_DEBUG_TRACE_END("AirPDcapDestroyContext"); - return AIRPDCAP_RET_UNSUCCESS; - } - - AirPDcapCleanKeys(ctx); - - ctx->first_free_index=0; - ctx->index=-1; - ctx->last_stored_index=-1; - - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapDestroyContext", "Context destroyed!", AIRPDCAP_DEBUG_LEVEL_5); - AIRPDCAP_DEBUG_TRACE_END("AirPDcapDestroyContext"); - return AIRPDCAP_RET_SUCCESS; - } + ctx->keys[success].KeyType=keys[i].KeyType; + memcpy(&ctx->keys[success].KeyData, &keys[i].KeyData, sizeof(keys[i].KeyData)); + + success++; + } + } + + ctx->keys_nr=success; + + AIRPDCAP_DEBUG_TRACE_END("AirPDcapSetKeys"); + return success; +} + +INT AirPDcapCleanKeys( + PAIRPDCAP_CONTEXT ctx) +{ + INT i; + AIRPDCAP_DEBUG_TRACE_START("AirPDcapCleanKeys"); + + if (ctx==NULL) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapCleanKeys", "NULL context", AIRPDCAP_DEBUG_LEVEL_5); + AIRPDCAP_DEBUG_TRACE_END("AirPDcapCleanKeys"); + return 0; + } + + for (i=0; i<AIRPDCAP_MAX_KEYS_NR; i++) { + memset(&ctx->keys[i], 0, sizeof(AIRPDCAP_KEY_ITEM)); + } + + ctx->keys_nr=0; + + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapCleanKeys", "Keys collection cleaned!", AIRPDCAP_DEBUG_LEVEL_5); + AIRPDCAP_DEBUG_TRACE_END("AirPDcapCleanKeys"); + + return i; +} + +INT AirPDcapGetKeys( + const PAIRPDCAP_CONTEXT ctx, + AIRPDCAP_KEY_ITEM keys[], + const size_t keys_nr) +{ + UINT i; + UINT j; + AIRPDCAP_DEBUG_TRACE_START("AirPDcapGetKeys"); + + if (ctx==NULL) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapGetKeys", "NULL context", AIRPDCAP_DEBUG_LEVEL_5); + AIRPDCAP_DEBUG_TRACE_END("AirPDcapGetKeys"); + return 0; + } else if (keys==NULL) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapGetKeys", "NULL keys array", AIRPDCAP_DEBUG_LEVEL_5); + AIRPDCAP_DEBUG_TRACE_END("AirPDcapGetKeys"); + return (INT)ctx->keys_nr; + } else { + for (i=0, j=0; i<ctx->keys_nr && i<keys_nr && i<AIRPDCAP_MAX_KEYS_NR; i++) { + keys[j].KeyType=ctx->keys[i].KeyType; + memcpy(&keys[j].KeyData, &ctx->keys[i].KeyData, sizeof(keys[j].KeyData)); + j++; + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapGetKeys", "Got a key", AIRPDCAP_DEBUG_LEVEL_5); + } + + AIRPDCAP_DEBUG_TRACE_END("AirPDcapGetKeys"); + return j; + } +} + +INT AirPDcapInitContext( + PAIRPDCAP_CONTEXT ctx) +{ + AIRPDCAP_DEBUG_TRACE_START("AirPDcapInitContext"); + + if (ctx==NULL) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapInitContext", "NULL context", AIRPDCAP_DEBUG_LEVEL_5); + AIRPDCAP_DEBUG_TRACE_END("AirPDcapInitContext"); + return AIRPDCAP_RET_UNSUCCESS; + } + + AirPDcapCleanKeys(ctx); + + ctx->first_free_index=0; + ctx->index=-1; + ctx->last_stored_index=-1; + + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapInitContext", "Context initialized!", AIRPDCAP_DEBUG_LEVEL_5); + AIRPDCAP_DEBUG_TRACE_END("AirPDcapInitContext"); + return AIRPDCAP_RET_SUCCESS; +} + +INT AirPDcapDestroyContext( + PAIRPDCAP_CONTEXT ctx) +{ + AIRPDCAP_DEBUG_TRACE_START("AirPDcapDestroyContext"); + + if (ctx==NULL) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapDestroyContext", "NULL context", AIRPDCAP_DEBUG_LEVEL_5); + AIRPDCAP_DEBUG_TRACE_END("AirPDcapDestroyContext"); + return AIRPDCAP_RET_UNSUCCESS; + } + + AirPDcapCleanKeys(ctx); + + ctx->first_free_index=0; + ctx->index=-1; + ctx->last_stored_index=-1; + + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapDestroyContext", "Context destroyed!", AIRPDCAP_DEBUG_LEVEL_5); + AIRPDCAP_DEBUG_TRACE_END("AirPDcapDestroyContext"); + return AIRPDCAP_RET_SUCCESS; +} #ifdef __cplusplus } @@ -595,756 +575,756 @@ extern "C" { extern "C" { #endif - INT AirPDcapRsnaMng( - UCHAR *decrypt_data, - size_t *decrypt_len, - PAIRPDCAP_KEY_ITEM key, - AIRPDCAP_SEC_ASSOCIATION *sa, - INT offset, - UINT8 fcsPresent) - { - INT ret_value; - ULONG crc; - - if (sa->key==NULL) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "No key associated", AIRPDCAP_DEBUG_LEVEL_3); - return AIRPDCAP_RET_REQ_DATA; - } - if (sa->validKey==FALSE) { - 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); - - ret_value=AirPDcapTkipDecrypt(decrypt_data+offset, *decrypt_len-offset, decrypt_data+AIRPDCAP_TA_OFFSET, AIRPDCAP_GET_TK(sa->wpa.ptk)); - if (ret_value) - return ret_value; - - 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(decrypt_data, (INT)*decrypt_len, AIRPDCAP_GET_TK(sa->wpa.ptk)); - if (ret_value) - return ret_value; - - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "CCMP DECRYPTED!!!", AIRPDCAP_DEBUG_LEVEL_3); - /* remove MIC (8bytes) from the end of packet */ - *decrypt_len-=8; - } - - /* remove protection bit */ - decrypt_data[1]&=0xBF; - - /* remove TKIP/CCMP header */ - offset=AIRPDCAP_HEADER_LEN(decrypt_data[1]); - *decrypt_len-=8; - memcpy(decrypt_data+offset, decrypt_data+offset+8, *decrypt_len-offset); - - if (fcsPresent) { - /* calculate FCS */ - AirPDcapAlgCrc32(decrypt_data, *decrypt_len, &crc); - *(unsigned long*)(decrypt_data+*decrypt_len)=crc; - - /* add FCS in packet */ - *decrypt_len+=4; - } - - if (key!=NULL) { - memcpy(key, sa->key, sizeof(AIRPDCAP_KEY_ITEM)); - - if (sa->wpa.key_ver==AIRPDCAP_WPA_KEY_VER_CCMP) - key->KeyType=AIRPDCAP_KEY_TYPE_TKIP; - else if (sa->wpa.key_ver==AIRPDCAP_WPA_KEY_VER_AES_CCMP) - key->KeyType=AIRPDCAP_KEY_TYPE_CCMP; - } - - return AIRPDCAP_RET_SUCCESS; - } - - INT AirPDcapWepMng( - PAIRPDCAP_CONTEXT ctx, - UCHAR *decrypt_data, - size_t *decrypt_len, - PAIRPDCAP_KEY_ITEM key, - AIRPDCAP_SEC_ASSOCIATION *sa, - INT offset, - UINT8 fcsPresent) - { - UCHAR wep_key[AIRPDCAP_WEP_KEY_MAXLEN+AIRPDCAP_WEP_IVLEN]; - size_t keylen; - INT ret_value=1; - ULONG crc; - INT key_index; - AIRPDCAP_KEY_ITEM *tmp_key; - UINT8 useCache=FALSE; - - if (sa->key!=NULL) - useCache=TRUE; - - for (key_index=0; key_index<(INT)ctx->keys_nr; key_index++) { - /* use the cached one, or try all keys */ - if (!useCache) { - tmp_key=&ctx->keys[key_index]; - } else { - if (sa->key!=NULL && sa->key->KeyType==AIRPDCAP_KEY_TYPE_WEP) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "Try cached WEP key...", AIRPDCAP_DEBUG_LEVEL_3); - tmp_key=sa->key; - } else { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "Cached key is not valid, try another WEP key...", AIRPDCAP_DEBUG_LEVEL_3); - tmp_key=&ctx->keys[key_index]; - } - } - - /* obviously, try only WEP keys... */ - if (tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WEP) - { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "Try WEP key...", AIRPDCAP_DEBUG_LEVEL_3); - - memset(wep_key, 0, sizeof(wep_key)); - - /* Costruct the WEP seed: copy the IV in first 3 bytes and then the WEP key (refer to 802-11i-2004, 8.2.1.4.3, pag. 36) */ - memcpy(wep_key, decrypt_data+AIRPDCAP_HEADER_LEN(decrypt_data[1]), AIRPDCAP_WEP_IVLEN); - keylen=tmp_key->KeyData.Wep.WepKeyLen; - memcpy(wep_key+AIRPDCAP_WEP_IVLEN, tmp_key->KeyData.Wep.WepKey, keylen); - - ret_value=AirPDcapWepDecrypt(wep_key, - keylen+AIRPDCAP_WEP_IVLEN, - decrypt_data + (AIRPDCAP_HEADER_LEN(decrypt_data[1])+AIRPDCAP_WEP_IVLEN+AIRPDCAP_WEP_KIDLEN), - *decrypt_len-(AIRPDCAP_HEADER_LEN(decrypt_data[1])+AIRPDCAP_WEP_IVLEN+AIRPDCAP_WEP_KIDLEN+AIRPDCAP_CRC_LEN)); - - } - - if (!ret_value && tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WEP) { - /* the tried key is the correct one, cached in the Security Association */ - - sa->key=tmp_key; - - if (key!=NULL) { - memcpy(key, &sa->key, sizeof(AIRPDCAP_KEY_ITEM)); - key->KeyType=AIRPDCAP_KEY_TYPE_WEP; - } - - break; - } else { - /* the cached key was not valid, try other keys */ - - if (useCache==TRUE) { - useCache=FALSE; - key_index--; - } - } - } - - if (ret_value) - return ret_value; - - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "WEP DECRYPTED!!!", AIRPDCAP_DEBUG_LEVEL_3); - - /* remove ICV (4bytes) from the end of packet */ - *decrypt_len-=4; - - /* remove protection bit */ - decrypt_data[1]&=0xBF; - - /* remove IC header */ - offset=AIRPDCAP_HEADER_LEN(decrypt_data[1]); - *decrypt_len-=4; - memcpy(decrypt_data+offset, decrypt_data+offset+AIRPDCAP_WEP_IVLEN+AIRPDCAP_WEP_KIDLEN, *decrypt_len-offset); - - if (fcsPresent) { - /* calculate FCS and append it at the end of the decrypted packet */ - AirPDcapAlgCrc32(decrypt_data, *decrypt_len, &crc); - *(unsigned long*)(decrypt_data+*decrypt_len)=crc; - - /* add FCS in packet */ - *decrypt_len += 4; - } - - return AIRPDCAP_RET_SUCCESS; - } - - /* Refer to IEEE 802.11i-2004, 8.5.3, pag. 85 */ - INT AirPDcapRsna4WHandshake( - PAIRPDCAP_CONTEXT ctx, - const UCHAR *data, - AIRPDCAP_SEC_ASSOCIATION *sa, - PAIRPDCAP_KEY_ITEM key, - INT offset) - { - AIRPDCAP_KEY_ITEM *tmp_key; - INT key_index; - INT ret_value=1; - UCHAR useCache=FALSE; - UCHAR eapol[AIRPDCAP_EAPOL_MAX_LEN]; - USHORT eapol_len; - - if (sa->key!=NULL) - useCache=TRUE; - - /* a 4-way handshake packet use a Pairwise key type (IEEE 802.11i-2004, pg. 79) */ - if (AIRPDCAP_EAP_KEY(data[offset+1])!=1) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "Group/STAKey message (not used)", AIRPDCAP_DEBUG_LEVEL_5); - return AIRPDCAP_RET_NO_VALID_HANDSHAKE; - } - - /* TODO timeouts? reauthentication? */ - - /* TODO consider key-index */ - - /* TODO considera Deauthentications */ - - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake...", AIRPDCAP_DEBUG_LEVEL_5); - - /* 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 (AIRPDCAP_EAP_INST(data[offset+1])==0 && - AIRPDCAP_EAP_ACK(data[offset+1])==1 && - AIRPDCAP_EAP_MIC(data[offset])==0) - { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 1", AIRPDCAP_DEBUG_LEVEL_3); - - /* On reception of Message 1, the Supplicant determines whether the Key Replay Counter field value has been */ - /* used before with the current PMKSA. If the Key Replay Counter field value is less than or equal to the current */ - /* local value, the Supplicant discards the message. */ - /* -> not checked, the Authenticator will be send another Message 1 (hopefully!) */ - - /* save ANonce (from authenticator) to derive the PTK with the SNonce (from the 2 message) */ - memcpy(sa->wpa.nonce, data+offset+12, 32); - - /* get the Key Descriptor Version (to select algorithm used in decryption -CCMP or TKIP-) */ - sa->wpa.key_ver=AIRPDCAP_EAP_KEY_DESCR_VER(data[offset+1]); - - sa->handshake=1; - - return AIRPDCAP_RET_SUCCESS_HANDSHAKE; - } - - /* 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 (AIRPDCAP_EAP_INST(data[offset+1])==0 && - AIRPDCAP_EAP_ACK(data[offset+1])==0 && - AIRPDCAP_EAP_MIC(data[offset])==1) - { - if (AIRPDCAP_EAP_SEC(data[offset])==0) { - - /* PATCH: some implementations set secure bit to 0 also in the 4th message */ - /* to recognize which message is this check if wep_key data lenght is 0 */ - /* in the 4th message */ - if (*(UINT16 *)(data+offset+92)!=0) { - /* message 2 */ - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 2", AIRPDCAP_DEBUG_LEVEL_3); - - /* On reception of Message 2, the Authenticator checks that the key replay counter corresponds to the */ - /* outstanding Message 1. If not, it silently discards the message. */ - /* If the calculated MIC does not match the MIC that the Supplicant included in the EAPOL-Key frame, */ - /* the Authenticator silently discards Message 2. */ - /* -> not checked; the Supplicant will send another message 2 (hopefully!) */ - - /* now you can derive the PTK */ - for (key_index=0; key_index<(INT)ctx->keys_nr || sa->key!=NULL; key_index++) { - /* use the cached one, or try all keys */ - if (!useCache) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "Try WPA key...", AIRPDCAP_DEBUG_LEVEL_3); - tmp_key=&ctx->keys[key_index]; - } else { - /* there is a cached key in the security association, if it's a WPA key try it... */ - if (sa->key!=NULL && - sa->key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PWD || - sa->key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PSK || - sa->key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PMK) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "Try cached WPA key...", AIRPDCAP_DEBUG_LEVEL_3); - tmp_key=sa->key; - } else { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "Cached key is of a wrong type, try WPA key...", AIRPDCAP_DEBUG_LEVEL_3); - tmp_key=&ctx->keys[key_index]; - } - } - - /* obviously, try only WPA keys... */ - if (tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PWD || - tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PSK || - tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PMK) - { - /* derive the PTK from the BSSID, STA MAC, PMK, SNonce, ANonce */ - AirPDcapRsnaPrfX(sa, /* authenticator nonce, bssid, station mac */ - tmp_key->KeyData.Wpa.Pmk, /* PMK */ - data+offset+12, /* supplicant nonce */ - 512, - sa->wpa.ptk); - - /* verify the MIC (compare the MIC in the packet included in this message with a MIC calculated with the PTK) */ - eapol_len=(USHORT)(ntohs(*(UINT16 *)(data+offset-3))+4); - memcpy(eapol, &data[offset-5], (eapol_len<AIRPDCAP_EAPOL_MAX_LEN?eapol_len:AIRPDCAP_EAPOL_MAX_LEN)); - ret_value=AirPDcapRsnaMicCheck(eapol, /* eapol frame (header also) */ - eapol_len, /* eapol frame length */ - sa->wpa.ptk, /* Key Confirmation Key */ - AIRPDCAP_EAP_KEY_DESCR_VER(data[offset+1])); /* EAPOL-Key description version */ - - /* If the MIC is valid, the Authenticator checks that the RSN information element bit-wise matches */ - /* that from the (Re)Association Request message. */ - /* i) TODO If these are not exactly the same, the Authenticator uses MLME-DEAUTHENTICATE.request */ - /* primitive to terminate the association. */ - /* ii) If they do match bit-wise, the Authenticator constructs Message 3. */ - } - - if (!ret_value && - (tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PWD || - tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PSK || - tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PMK)) - { - /* the temporary key is the correct one, cached in the Security Association */ - - sa->key=tmp_key; - - if (key!=NULL) { - memcpy(key, &tmp_key, sizeof(AIRPDCAP_KEY_ITEM)); - if (AIRPDCAP_EAP_KEY_DESCR_VER(data[offset+1])==AIRPDCAP_WPA_KEY_VER_CCMP) - key->KeyType=AIRPDCAP_KEY_TYPE_TKIP; - else if (AIRPDCAP_EAP_KEY_DESCR_VER(data[offset+1])==AIRPDCAP_WPA_KEY_VER_AES_CCMP) - key->KeyType=AIRPDCAP_KEY_TYPE_CCMP; - } - - break; - } else { - /* the cached key was not valid, try other keys */ - - if (useCache==TRUE) { - useCache=FALSE; - key_index--; - } - } - } - - if (ret_value) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "handshake step failed", AIRPDCAP_DEBUG_LEVEL_3); - return ret_value; - } - - sa->handshake=2; - - return AIRPDCAP_RET_SUCCESS_HANDSHAKE; - } else { - /* message 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 */ - /* On reception of Message 4, the Authenticator verifies that the Key Replay Counter field value is one */ - /* that it used on this 4-Way Handshake; if it is not, it silently discards the message. */ - /* If the calculated MIC does not match the MIC that the Supplicant included in the EAPOL-Key frame, the */ - /* Authenticator silently discards Message 4. */ - - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 4 (patched)", AIRPDCAP_DEBUG_LEVEL_3); - - sa->handshake=4; - - sa->validKey=TRUE; - - return AIRPDCAP_RET_SUCCESS_HANDSHAKE; - } - /* END OF PATCH */ - /* */ - } else { - /* message 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 */ - /* On reception of Message 4, the Authenticator verifies that the Key Replay Counter field value is one */ - /* that it used on this 4-Way Handshake; if it is not, it silently discards the message. */ - /* If the calculated MIC does not match the MIC that the Supplicant included in the EAPOL-Key frame, the */ - /* Authenticator silently discards Message 4. */ - - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 4", AIRPDCAP_DEBUG_LEVEL_3); - - sa->handshake=4; - - sa->validKey=TRUE; - - return AIRPDCAP_RET_SUCCESS_HANDSHAKE; - } - } - - /* message 3: Authenticator->Supplicant (Sec=1, Mic=1, Ack=1, Inst=0/1, Key=1(pairwise), KeyRSC=???, Nonce=ANonce, MIC=1) */ - if (AIRPDCAP_EAP_ACK(data[offset+1])==1 && - AIRPDCAP_EAP_MIC(data[offset])==1) - { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 3", AIRPDCAP_DEBUG_LEVEL_3); - - /* On reception of Message 3, the Supplicant silently discards the message if the Key Replay Counter field */ - /* value has already been used or if the ANonce value in Message 3 differs from the ANonce value in Message 1. */ - /* -> not checked, the Authenticator will send another message 3 (hopefully!) */ - - /* TODO check page 88 (RNS) */ - - return AIRPDCAP_RET_SUCCESS_HANDSHAKE; - } - - return AIRPDCAP_RET_UNSUCCESS; - } - - INT AirPDcapRsnaMicCheck( - UCHAR *eapol, - const USHORT eapol_len, - const UCHAR KCK[AIRPDCAP_WPA_KCK_LEN], - const USHORT key_ver) - { - UCHAR mic[AIRPDCAP_WPA_MICKEY_LEN]; - UCHAR c_mic[20]; /* MIC 16 byte, the HMAC-SHA1 use a buffer of 20 bytes */ - - /* copy the MIC from the EAPOL packet */ - memcpy(mic, eapol+AIRPDCAP_WPA_MICKEY_OFFSET+4, AIRPDCAP_WPA_MICKEY_LEN); - - /* set to 0 the MIC in the EAPOL packet (to calculate the MIC) */ - memset(eapol+AIRPDCAP_WPA_MICKEY_OFFSET+4, 0, AIRPDCAP_WPA_MICKEY_LEN); - - if (key_ver==AIRPDCAP_WPA_KEY_VER_CCMP) { - /* use HMAC-MD5 for the EAPOL-Key MIC */ - AirPDcapAlgHmacMd5((UCHAR *)KCK, AIRPDCAP_WPA_KCK_LEN, eapol, eapol_len, c_mic); - } else if (key_ver==AIRPDCAP_WPA_KEY_VER_AES_CCMP) { - /* use HMAC-SHA1-128 for the EAPOL-Key MIC */ - AirPDcapAlgHmacSha1(KCK, AIRPDCAP_WPA_KCK_LEN, eapol, eapol_len, c_mic); - } else - /* key descriptor version not recognized */ - return AIRPDCAP_RET_UNSUCCESS; - - /* compare calculated MIC with the Key MIC and return result (0 means success) */ - return memcmp(mic, c_mic, AIRPDCAP_WPA_MICKEY_LEN); - } - - INT AirPDcapValidateKey( - PAIRPDCAP_KEY_ITEM key) - { - size_t len; - UCHAR ret=TRUE; - AIRPDCAP_DEBUG_TRACE_START("AirPDcapValidateKey"); - - if (key==NULL) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapValidateKey", "NULL key", AIRPDCAP_DEBUG_LEVEL_5); - AIRPDCAP_DEBUG_TRACE_START("AirPDcapValidateKey"); - return FALSE; - } - - switch (key->KeyType) { - case AIRPDCAP_KEY_TYPE_WEP: - /* check key size limits */ - len=key->KeyData.Wep.WepKeyLen; - if (len<AIRPDCAP_WEP_KEY_MINLEN || len>AIRPDCAP_WEP_KEY_MAXLEN) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapValidateKey", "WEP key: key length not accepted", AIRPDCAP_DEBUG_LEVEL_5); - ret=FALSE; - } - break; - - case AIRPDCAP_KEY_TYPE_WEP_40: - /* set the standard length and use a generic WEP key type */ - key->KeyData.Wep.WepKeyLen=AIRPDCAP_WEP_40_KEY_LEN; - key->KeyType=AIRPDCAP_KEY_TYPE_WEP; - break; - - case AIRPDCAP_KEY_TYPE_WEP_104: - /* set the standard length and use a generic WEP key type */ - key->KeyData.Wep.WepKeyLen=AIRPDCAP_WEP_104_KEY_LEN; - key->KeyType=AIRPDCAP_KEY_TYPE_WEP; - break; - - case AIRPDCAP_KEY_TYPE_WPA_PWD: - /* check passphrase and SSID size limits */ - len=strlen(key->KeyData.Wpa.UserPwd.Passphrase); - if (len<AIRPDCAP_WPA_PASSPHRASE_MIN_LEN || len>AIRPDCAP_WPA_PASSPHRASE_MAX_LEN) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapValidateKey", "WPA-PWD key: passphrase length not accepted", AIRPDCAP_DEBUG_LEVEL_5); - ret=FALSE; - } - - len=key->KeyData.Wpa.UserPwd.SsidLen; - if (len<AIRPDCAP_WPA_SSID_MIN_LEN || len>AIRPDCAP_WPA_SSID_MAX_LEN) { - AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapValidateKey", "WPA-PWD key: ssid length not accepted", AIRPDCAP_DEBUG_LEVEL_5); - ret=FALSE; - } - - break; - - case AIRPDCAP_KEY_TYPE_WPA_PSK: - break; - - case AIRPDCAP_KEY_TYPE_WPA_PMK: - break; - - default: - ret=FALSE; - } - - AIRPDCAP_DEBUG_TRACE_END("AirPDcapValidateKey"); - return ret; - } - - INT AirPDcapGetSa( - PAIRPDCAP_CONTEXT ctx, - AIRPDCAP_SEC_ASSOCIATION_ID *id) - { - INT index; - - if (ctx->last_stored_index!=-1) { - /* at least one association was stored */ - /* search for the association from last_stored_index to 0 (most recent added) */ - for (index=ctx->last_stored_index; index>=0; index--) { - if (ctx->sa[index].used) { - if (memcmp(id, &(ctx->sa[index].saId), sizeof(AIRPDCAP_SEC_ASSOCIATION_ID))==0) { - ctx->index=index; - return index; - } - } - } - } - - return -1; - } - - INT AirPDcapFreeSa( - PAIRPDCAP_CONTEXT ctx, - INT index) /* index of the structure to free */ - { - /* set the structure as free (the reset will be done in AIRPDCAP_store_sta_info) */ - ctx->sa[index].used=0; - - /* set the first_free_index to avoid free blocks in the middle */ - if (index<ctx->first_free_index) - ctx->first_free_index=index; - - /* decrement the last_stored_index if this was the last stored block */ - if (index==ctx->last_stored_index) - ctx->last_stored_index--; - - /* if the list is empty, set the index */ - if (ctx->last_stored_index==-1) - ctx->index=-1; - - return ctx->index; - } - - INT AirPDcapStoreSa( - PAIRPDCAP_CONTEXT ctx, - AIRPDCAP_SEC_ASSOCIATION_ID *id) - { - INT last_free; - - if (ctx->sa[ctx->first_free_index].used) { - /* last addition was in the middle of the array (and the first_free_index was just incremented by 1) */ - /* search for a free space from the first_free_index to AIRPDCAP_STA_INFOS_NR (to avoid free blocks in */ - /* the middle) */ - for (last_free=ctx->first_free_index; last_free<AIRPDCAP_MAX_SEC_ASSOCIATIONS_NR; last_free++) - if (!ctx->sa[last_free].used) - break; - - if (last_free>=AIRPDCAP_MAX_SEC_ASSOCIATIONS_NR) { - /* there is no empty space available. FAILURE */ - return -1; - } - - /* store first free space index */ - ctx->first_free_index=last_free; - } - - /* use this info */ - ctx->index=ctx->first_free_index; - - /* reset the info structure */ - memset(ctx->sa+ctx->index, 0, sizeof(AIRPDCAP_SEC_ASSOCIATION)); - - ctx->sa[ctx->index].used=1; - - /* set the info structure */ - memcpy(&(ctx->sa[ctx->index].saId), id, sizeof(AIRPDCAP_SEC_ASSOCIATION_ID)); - - /* increment by 1 the first_free_index (heuristic) */ - ctx->first_free_index++; - - /* set the last_stored_index if the added index is greater the the last_stored_index */ - if (ctx->index > ctx->last_stored_index) - ctx->last_stored_index=ctx->index; - - return ctx->index; - } - - UCHAR * AirPDcapGetStaAddress( - PAIRPDCAP_MAC_FRAME frame) - { - if (AIRPDCAP_TO_DS(frame->fc[1])==0) { - if (AIRPDCAP_FROM_DS(frame->fc[1])==0) - return NULL; - else - return frame->addr1; - } else { - if (AIRPDCAP_FROM_DS(frame->fc[1])==0) - return frame->addr2; - else - return NULL; - } - } - - UCHAR * AirPDcapGetBssidAddress( - PAIRPDCAP_MAC_FRAME frame) - { - if (AIRPDCAP_TO_DS(frame->fc[1])==0) { - if (AIRPDCAP_FROM_DS(frame->fc[1])==0) - return frame->addr3; - else - return frame->addr2; - } else { - if (AIRPDCAP_FROM_DS(frame->fc[1])==0) - return frame->addr1; - else - return NULL; - } - } - - /* Function used to derive the PTK. Refer to IEEE 802.11I-2004, pag. 74 */ - void AirPDcapRsnaPrfX( - AIRPDCAP_SEC_ASSOCIATION *sa, - const UCHAR pmk[32], - const UCHAR snonce[32], - const INT x, /* for TKIP 512, for CCMP 384 */ - UCHAR *ptk) - { - UINT8 i; - UCHAR R[100]; - INT offset=sizeof("Pairwise key expansion"); - - memset(R, 0, 100); - - memcpy(R, "Pairwise key expansion", offset); - - /* Min(AA, SPA) || Max(AA, SPA) */ - if (memcmp(sa->saId.sta, sa->saId.bssid, AIRPDCAP_MAC_LEN) < 0) - { - memcpy(R + offset, sa->saId.sta, AIRPDCAP_MAC_LEN); - memcpy(R + offset+AIRPDCAP_MAC_LEN, sa->saId.bssid, AIRPDCAP_MAC_LEN); - } - else - { - memcpy(R + offset, sa->saId.bssid, AIRPDCAP_MAC_LEN); - memcpy(R + offset+AIRPDCAP_MAC_LEN, sa->saId.sta, AIRPDCAP_MAC_LEN); - } - - offset+=AIRPDCAP_MAC_LEN*2; - - /* Min(ANonce,SNonce) || Max(ANonce,SNonce) */ - if( memcmp(snonce, sa->wpa.nonce, 32) < 0 ) - { - memcpy(R + offset, snonce, 32); - memcpy(R + offset + 32, sa->wpa.nonce, 32); - } - else - { - memcpy(R + offset, sa->wpa.nonce, 32); - memcpy(R + offset + 32, snonce, 32); - } - - offset+=32*2; - - for(i = 0; i < (x+159)/160; i++) - { - R[offset] = i; - AirPDcapAlgHmacSha1(pmk, 32, R, 100, ptk + i * 20); - } - } - - INT AirPDcapRsnaPwd2PskStep( - const CHAR *password, - const CHAR *ssid, - const size_t ssidLength, - const INT iterations, - const INT count, - UCHAR *output) - { - UCHAR digest[36], digest1[AIRPDCAP_SHA_DIGEST_LEN]; - INT i, j; - - /* U1 = PRF(P, S || INT(i)) */ - memcpy(digest, ssid, ssidLength); - digest[ssidLength] = (UCHAR)((count>>24) & 0xff); - digest[ssidLength+1] = (UCHAR)((count>>16) & 0xff); - digest[ssidLength+2] = (UCHAR)((count>>8) & 0xff); - digest[ssidLength+3] = (UCHAR)(count & 0xff); - AirPDcapAlgHmacSha1((UCHAR *)password, strlen(password), digest, ssidLength+4, digest1); - - /* output = U1 */ - memcpy(output, digest1, AIRPDCAP_SHA_DIGEST_LEN); - for (i = 1; i < iterations; i++) { - /* Un = PRF(P, Un-1) */ - AirPDcapAlgHmacSha1((UCHAR *)password, strlen(password), digest1, AIRPDCAP_SHA_DIGEST_LEN, digest); - - memcpy(digest1, digest, AIRPDCAP_SHA_DIGEST_LEN); - /* output = output xor Un */ - for (j = 0; j < AIRPDCAP_SHA_DIGEST_LEN; j++) { - output[j] ^= digest[j]; - } - } - - return AIRPDCAP_RET_SUCCESS; - } - - INT AirPDcapRsnaPwd2Psk( - const CHAR *password, - const CHAR *ssid, - const size_t ssidLength, - UCHAR *output) - { - UCHAR m_output[AIRPDCAP_WPA_PSK_LEN]; - - memset(m_output, 0, AIRPDCAP_WPA_PSK_LEN); - - memset(m_output, 0, 40); - - AirPDcapRsnaPwd2PskStep(password, ssid, ssidLength, 4096, 1, m_output); - AirPDcapRsnaPwd2PskStep(password, ssid, ssidLength, 4096, 2, &m_output[AIRPDCAP_SHA_DIGEST_LEN]); - - memcpy(output, m_output, AIRPDCAP_WPA_PSK_LEN); - - return 0; - } - - /**************************************************************************/ - /* The following code come from freeBSD and implements the AUTODIN II - /* polynomial used by 802.11. - /* It can be used to calculate multicast address hash indices. - /* It assumes that the low order bits will be transmitted first, - /* and consequently the low byte should be sent first when - /* the crc computation is finished. The crc should be complemented - /* before transmission. - /* The variable corresponding to the macro argument "crc" should - /* be an unsigned long and should be preset to all ones for Ethernet - /* use. An error-free packet will leave 0xDEBB20E3 in the crc. - /**************************************************************************/ - INT AirPDcapAlgCrc32( - UCHAR *buf, - size_t nr, - ULONG *cval) - { - ULONG crc32_total = 0 ; - ULONG crc = ~(ULONG)0; - UCHAR *p ; - size_t len; - - len = 0 ; - crc32_total = ~crc32_total ; - - for(len += nr, p = buf; nr--; ++p) - { - CRC(crc, *p) ; - CRC(crc32_total, *p) ; - } - - *cval = ~crc ; - crc32_total = ~crc32_total ; - - return 0; - } +INT AirPDcapRsnaMng( + UCHAR *decrypt_data, + size_t *decrypt_len, + PAIRPDCAP_KEY_ITEM key, + AIRPDCAP_SEC_ASSOCIATION *sa, + INT offset, + UINT8 fcsPresent) +{ + INT ret_value; + ULONG crc; + + if (sa->key==NULL) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "No key associated", AIRPDCAP_DEBUG_LEVEL_3); + return AIRPDCAP_RET_REQ_DATA; + } + if (sa->validKey==FALSE) { + 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); + + ret_value=AirPDcapTkipDecrypt(decrypt_data+offset, *decrypt_len-offset, decrypt_data+AIRPDCAP_TA_OFFSET, AIRPDCAP_GET_TK(sa->wpa.ptk)); + if (ret_value) + return ret_value; + + 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(decrypt_data, (INT)*decrypt_len, AIRPDCAP_GET_TK(sa->wpa.ptk)); + if (ret_value) + return ret_value; + + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "CCMP DECRYPTED!!!", AIRPDCAP_DEBUG_LEVEL_3); + /* remove MIC (8bytes) from the end of packet */ + *decrypt_len-=8; + } + + /* remove protection bit */ + decrypt_data[1]&=0xBF; + + /* remove TKIP/CCMP header */ + offset=AIRPDCAP_HEADER_LEN(decrypt_data[1]); + *decrypt_len-=8; + memcpy(decrypt_data+offset, decrypt_data+offset+8, *decrypt_len-offset); + + if (fcsPresent) { + /* calculate FCS */ + AirPDcapAlgCrc32(decrypt_data, *decrypt_len, &crc); + *(unsigned long*)(decrypt_data+*decrypt_len)=crc; + + /* add FCS in packet */ + *decrypt_len+=4; + } + + if (key!=NULL) { + memcpy(key, sa->key, sizeof(AIRPDCAP_KEY_ITEM)); + + if (sa->wpa.key_ver==AIRPDCAP_WPA_KEY_VER_CCMP) + key->KeyType=AIRPDCAP_KEY_TYPE_TKIP; + else if (sa->wpa.key_ver==AIRPDCAP_WPA_KEY_VER_AES_CCMP) + key->KeyType=AIRPDCAP_KEY_TYPE_CCMP; + } + + return AIRPDCAP_RET_SUCCESS; +} + +INT AirPDcapWepMng( + PAIRPDCAP_CONTEXT ctx, + UCHAR *decrypt_data, + size_t *decrypt_len, + PAIRPDCAP_KEY_ITEM key, + AIRPDCAP_SEC_ASSOCIATION *sa, + INT offset, + UINT8 fcsPresent) +{ + UCHAR wep_key[AIRPDCAP_WEP_KEY_MAXLEN+AIRPDCAP_WEP_IVLEN]; + size_t keylen; + INT ret_value=1; + ULONG crc; + INT key_index; + AIRPDCAP_KEY_ITEM *tmp_key; + UINT8 useCache=FALSE; + + if (sa->key!=NULL) + useCache=TRUE; + + for (key_index=0; key_index<(INT)ctx->keys_nr; key_index++) { + /* use the cached one, or try all keys */ + if (!useCache) { + tmp_key=&ctx->keys[key_index]; + } else { + if (sa->key!=NULL && sa->key->KeyType==AIRPDCAP_KEY_TYPE_WEP) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "Try cached WEP key...", AIRPDCAP_DEBUG_LEVEL_3); + tmp_key=sa->key; + } else { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "Cached key is not valid, try another WEP key...", AIRPDCAP_DEBUG_LEVEL_3); + tmp_key=&ctx->keys[key_index]; + } + } + + /* obviously, try only WEP keys... */ + if (tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WEP) + { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "Try WEP key...", AIRPDCAP_DEBUG_LEVEL_3); + + memset(wep_key, 0, sizeof(wep_key)); + + /* Costruct the WEP seed: copy the IV in first 3 bytes and then the WEP key (refer to 802-11i-2004, 8.2.1.4.3, pag. 36) */ + memcpy(wep_key, decrypt_data+AIRPDCAP_HEADER_LEN(decrypt_data[1]), AIRPDCAP_WEP_IVLEN); + keylen=tmp_key->KeyData.Wep.WepKeyLen; + memcpy(wep_key+AIRPDCAP_WEP_IVLEN, tmp_key->KeyData.Wep.WepKey, keylen); + + ret_value=AirPDcapWepDecrypt(wep_key, + keylen+AIRPDCAP_WEP_IVLEN, + decrypt_data + (AIRPDCAP_HEADER_LEN(decrypt_data[1])+AIRPDCAP_WEP_IVLEN+AIRPDCAP_WEP_KIDLEN), + *decrypt_len-(AIRPDCAP_HEADER_LEN(decrypt_data[1])+AIRPDCAP_WEP_IVLEN+AIRPDCAP_WEP_KIDLEN+AIRPDCAP_CRC_LEN)); + + } + + if (!ret_value && tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WEP) { + /* the tried key is the correct one, cached in the Security Association */ + + sa->key=tmp_key; + + if (key!=NULL) { + memcpy(key, &sa->key, sizeof(AIRPDCAP_KEY_ITEM)); + key->KeyType=AIRPDCAP_KEY_TYPE_WEP; + } + + break; + } else { + /* the cached key was not valid, try other keys */ + + if (useCache==TRUE) { + useCache=FALSE; + key_index--; + } + } + } + + if (ret_value) + return ret_value; + + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "WEP DECRYPTED!!!", AIRPDCAP_DEBUG_LEVEL_3); + + /* remove ICV (4bytes) from the end of packet */ + *decrypt_len-=4; + + /* remove protection bit */ + decrypt_data[1]&=0xBF; + + /* remove IC header */ + offset=AIRPDCAP_HEADER_LEN(decrypt_data[1]); + *decrypt_len-=4; + memcpy(decrypt_data+offset, decrypt_data+offset+AIRPDCAP_WEP_IVLEN+AIRPDCAP_WEP_KIDLEN, *decrypt_len-offset); + + if (fcsPresent) { + /* calculate FCS and append it at the end of the decrypted packet */ + AirPDcapAlgCrc32(decrypt_data, *decrypt_len, &crc); + *(unsigned long*)(decrypt_data+*decrypt_len)=crc; + + /* add FCS in packet */ + *decrypt_len += 4; + } + + return AIRPDCAP_RET_SUCCESS; +} + +/* Refer to IEEE 802.11i-2004, 8.5.3, pag. 85 */ +INT AirPDcapRsna4WHandshake( + PAIRPDCAP_CONTEXT ctx, + const UCHAR *data, + AIRPDCAP_SEC_ASSOCIATION *sa, + PAIRPDCAP_KEY_ITEM key, + INT offset) +{ + AIRPDCAP_KEY_ITEM *tmp_key; + INT key_index; + INT ret_value=1; + UCHAR useCache=FALSE; + UCHAR eapol[AIRPDCAP_EAPOL_MAX_LEN]; + USHORT eapol_len; + + if (sa->key!=NULL) + useCache=TRUE; + + /* a 4-way handshake packet use a Pairwise key type (IEEE 802.11i-2004, pg. 79) */ + if (AIRPDCAP_EAP_KEY(data[offset+1])!=1) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "Group/STAKey message (not used)", AIRPDCAP_DEBUG_LEVEL_5); + return AIRPDCAP_RET_NO_VALID_HANDSHAKE; + } + + /* TODO timeouts? reauthentication? */ + + /* TODO consider key-index */ + + /* TODO considera Deauthentications */ + + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake...", AIRPDCAP_DEBUG_LEVEL_5); + + /* 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 (AIRPDCAP_EAP_INST(data[offset+1])==0 && + AIRPDCAP_EAP_ACK(data[offset+1])==1 && + AIRPDCAP_EAP_MIC(data[offset])==0) + { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 1", AIRPDCAP_DEBUG_LEVEL_3); + + /* On reception of Message 1, the Supplicant determines whether the Key Replay Counter field value has been */ + /* used before with the current PMKSA. If the Key Replay Counter field value is less than or equal to the current */ + /* local value, the Supplicant discards the message. */ + /* -> not checked, the Authenticator will be send another Message 1 (hopefully!) */ + + /* save ANonce (from authenticator) to derive the PTK with the SNonce (from the 2 message) */ + memcpy(sa->wpa.nonce, data+offset+12, 32); + + /* get the Key Descriptor Version (to select algorithm used in decryption -CCMP or TKIP-) */ + sa->wpa.key_ver=AIRPDCAP_EAP_KEY_DESCR_VER(data[offset+1]); + + sa->handshake=1; + + return AIRPDCAP_RET_SUCCESS_HANDSHAKE; + } + + /* 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 (AIRPDCAP_EAP_INST(data[offset+1])==0 && + AIRPDCAP_EAP_ACK(data[offset+1])==0 && + AIRPDCAP_EAP_MIC(data[offset])==1) + { + if (AIRPDCAP_EAP_SEC(data[offset])==0) { + + /* PATCH: some implementations set secure bit to 0 also in the 4th message */ + /* to recognize which message is this check if wep_key data lenght is 0 */ + /* in the 4th message */ + if (*(UINT16 *)(data+offset+92)!=0) { + /* message 2 */ + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 2", AIRPDCAP_DEBUG_LEVEL_3); + + /* On reception of Message 2, the Authenticator checks that the key replay counter corresponds to the */ + /* outstanding Message 1. If not, it silently discards the message. */ + /* If the calculated MIC does not match the MIC that the Supplicant included in the EAPOL-Key frame, */ + /* the Authenticator silently discards Message 2. */ + /* -> not checked; the Supplicant will send another message 2 (hopefully!) */ + + /* now you can derive the PTK */ + for (key_index=0; key_index<(INT)ctx->keys_nr || sa->key!=NULL; key_index++) { + /* use the cached one, or try all keys */ + if (!useCache) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "Try WPA key...", AIRPDCAP_DEBUG_LEVEL_3); + tmp_key=&ctx->keys[key_index]; + } else { + /* there is a cached key in the security association, if it's a WPA key try it... */ + if (sa->key!=NULL && + sa->key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PWD || + sa->key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PSK || + sa->key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PMK) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "Try cached WPA key...", AIRPDCAP_DEBUG_LEVEL_3); + tmp_key=sa->key; + } else { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "Cached key is of a wrong type, try WPA key...", AIRPDCAP_DEBUG_LEVEL_3); + tmp_key=&ctx->keys[key_index]; + } + } + + /* obviously, try only WPA keys... */ + if (tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PWD || + tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PSK || + tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PMK) + { + /* derive the PTK from the BSSID, STA MAC, PMK, SNonce, ANonce */ + AirPDcapRsnaPrfX(sa, /* authenticator nonce, bssid, station mac */ + tmp_key->KeyData.Wpa.Pmk, /* PMK */ + data+offset+12, /* supplicant nonce */ + 512, + sa->wpa.ptk); + + /* verify the MIC (compare the MIC in the packet included in this message with a MIC calculated with the PTK) */ + eapol_len=(USHORT)(ntohs(*(UINT16 *)(data+offset-3))+4); + memcpy(eapol, &data[offset-5], (eapol_len<AIRPDCAP_EAPOL_MAX_LEN?eapol_len:AIRPDCAP_EAPOL_MAX_LEN)); + ret_value=AirPDcapRsnaMicCheck(eapol, /* eapol frame (header also) */ + eapol_len, /* eapol frame length */ + sa->wpa.ptk, /* Key Confirmation Key */ + AIRPDCAP_EAP_KEY_DESCR_VER(data[offset+1])); /* EAPOL-Key description version */ + + /* If the MIC is valid, the Authenticator checks that the RSN information element bit-wise matches */ + /* that from the (Re)Association Request message. */ + /* i) TODO If these are not exactly the same, the Authenticator uses MLME-DEAUTHENTICATE.request */ + /* primitive to terminate the association. */ + /* ii) If they do match bit-wise, the Authenticator constructs Message 3. */ + } + + if (!ret_value && + (tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PWD || + tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PSK || + tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PMK)) + { + /* the temporary key is the correct one, cached in the Security Association */ + + sa->key=tmp_key; + + if (key!=NULL) { + memcpy(key, &tmp_key, sizeof(AIRPDCAP_KEY_ITEM)); + if (AIRPDCAP_EAP_KEY_DESCR_VER(data[offset+1])==AIRPDCAP_WPA_KEY_VER_CCMP) + key->KeyType=AIRPDCAP_KEY_TYPE_TKIP; + else if (AIRPDCAP_EAP_KEY_DESCR_VER(data[offset+1])==AIRPDCAP_WPA_KEY_VER_AES_CCMP) + key->KeyType=AIRPDCAP_KEY_TYPE_CCMP; + } + + break; + } else { + /* the cached key was not valid, try other keys */ + + if (useCache==TRUE) { + useCache=FALSE; + key_index--; + } + } + } + + if (ret_value) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "handshake step failed", AIRPDCAP_DEBUG_LEVEL_3); + return ret_value; + } + + sa->handshake=2; + + return AIRPDCAP_RET_SUCCESS_HANDSHAKE; + } else { + /* message 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 */ + /* On reception of Message 4, the Authenticator verifies that the Key Replay Counter field value is one */ + /* that it used on this 4-Way Handshake; if it is not, it silently discards the message. */ + /* If the calculated MIC does not match the MIC that the Supplicant included in the EAPOL-Key frame, the */ + /* Authenticator silently discards Message 4. */ + + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 4 (patched)", AIRPDCAP_DEBUG_LEVEL_3); + + sa->handshake=4; + + sa->validKey=TRUE; + + return AIRPDCAP_RET_SUCCESS_HANDSHAKE; + } + /* END OF PATCH */ + /* */ + } else { + /* message 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 */ + /* On reception of Message 4, the Authenticator verifies that the Key Replay Counter field value is one */ + /* that it used on this 4-Way Handshake; if it is not, it silently discards the message. */ + /* If the calculated MIC does not match the MIC that the Supplicant included in the EAPOL-Key frame, the */ + /* Authenticator silently discards Message 4. */ + + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 4", AIRPDCAP_DEBUG_LEVEL_3); + + sa->handshake=4; + + sa->validKey=TRUE; + + return AIRPDCAP_RET_SUCCESS_HANDSHAKE; + } + } + + /* message 3: Authenticator->Supplicant (Sec=1, Mic=1, Ack=1, Inst=0/1, Key=1(pairwise), KeyRSC=???, Nonce=ANonce, MIC=1) */ + if (AIRPDCAP_EAP_ACK(data[offset+1])==1 && + AIRPDCAP_EAP_MIC(data[offset])==1) + { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 3", AIRPDCAP_DEBUG_LEVEL_3); + + /* On reception of Message 3, the Supplicant silently discards the message if the Key Replay Counter field */ + /* value has already been used or if the ANonce value in Message 3 differs from the ANonce value in Message 1. */ + /* -> not checked, the Authenticator will send another message 3 (hopefully!) */ + + /* TODO check page 88 (RNS) */ + + return AIRPDCAP_RET_SUCCESS_HANDSHAKE; + } + + return AIRPDCAP_RET_UNSUCCESS; +} + +INT AirPDcapRsnaMicCheck( + UCHAR *eapol, + const USHORT eapol_len, + const UCHAR KCK[AIRPDCAP_WPA_KCK_LEN], + const USHORT key_ver) +{ + UCHAR mic[AIRPDCAP_WPA_MICKEY_LEN]; + UCHAR c_mic[20]; /* MIC 16 byte, the HMAC-SHA1 use a buffer of 20 bytes */ + + /* copy the MIC from the EAPOL packet */ + memcpy(mic, eapol+AIRPDCAP_WPA_MICKEY_OFFSET+4, AIRPDCAP_WPA_MICKEY_LEN); + + /* set to 0 the MIC in the EAPOL packet (to calculate the MIC) */ + memset(eapol+AIRPDCAP_WPA_MICKEY_OFFSET+4, 0, AIRPDCAP_WPA_MICKEY_LEN); + + if (key_ver==AIRPDCAP_WPA_KEY_VER_CCMP) { + /* use HMAC-MD5 for the EAPOL-Key MIC */ + AirPDcapAlgHmacMd5((UCHAR *)KCK, AIRPDCAP_WPA_KCK_LEN, eapol, eapol_len, c_mic); + } else if (key_ver==AIRPDCAP_WPA_KEY_VER_AES_CCMP) { + /* use HMAC-SHA1-128 for the EAPOL-Key MIC */ + AirPDcapAlgHmacSha1(KCK, AIRPDCAP_WPA_KCK_LEN, eapol, eapol_len, c_mic); + } else + /* key descriptor version not recognized */ + return AIRPDCAP_RET_UNSUCCESS; + + /* compare calculated MIC with the Key MIC and return result (0 means success) */ + return memcmp(mic, c_mic, AIRPDCAP_WPA_MICKEY_LEN); +} + +INT AirPDcapValidateKey( + PAIRPDCAP_KEY_ITEM key) +{ + size_t len; + UCHAR ret=TRUE; + AIRPDCAP_DEBUG_TRACE_START("AirPDcapValidateKey"); + + if (key==NULL) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapValidateKey", "NULL key", AIRPDCAP_DEBUG_LEVEL_5); + AIRPDCAP_DEBUG_TRACE_START("AirPDcapValidateKey"); + return FALSE; + } + + switch (key->KeyType) { +case AIRPDCAP_KEY_TYPE_WEP: + /* check key size limits */ + len=key->KeyData.Wep.WepKeyLen; + if (len<AIRPDCAP_WEP_KEY_MINLEN || len>AIRPDCAP_WEP_KEY_MAXLEN) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapValidateKey", "WEP key: key length not accepted", AIRPDCAP_DEBUG_LEVEL_5); + ret=FALSE; + } + break; + +case AIRPDCAP_KEY_TYPE_WEP_40: + /* set the standard length and use a generic WEP key type */ + key->KeyData.Wep.WepKeyLen=AIRPDCAP_WEP_40_KEY_LEN; + key->KeyType=AIRPDCAP_KEY_TYPE_WEP; + break; + +case AIRPDCAP_KEY_TYPE_WEP_104: + /* set the standard length and use a generic WEP key type */ + key->KeyData.Wep.WepKeyLen=AIRPDCAP_WEP_104_KEY_LEN; + key->KeyType=AIRPDCAP_KEY_TYPE_WEP; + break; + +case AIRPDCAP_KEY_TYPE_WPA_PWD: + /* check passphrase and SSID size limits */ + len=strlen(key->KeyData.Wpa.UserPwd.Passphrase); + if (len<AIRPDCAP_WPA_PASSPHRASE_MIN_LEN || len>AIRPDCAP_WPA_PASSPHRASE_MAX_LEN) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapValidateKey", "WPA-PWD key: passphrase length not accepted", AIRPDCAP_DEBUG_LEVEL_5); + ret=FALSE; + } + + len=key->KeyData.Wpa.UserPwd.SsidLen; + if (len<AIRPDCAP_WPA_SSID_MIN_LEN || len>AIRPDCAP_WPA_SSID_MAX_LEN) { + AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapValidateKey", "WPA-PWD key: ssid length not accepted", AIRPDCAP_DEBUG_LEVEL_5); + ret=FALSE; + } + + break; + +case AIRPDCAP_KEY_TYPE_WPA_PSK: + break; + +case AIRPDCAP_KEY_TYPE_WPA_PMK: + break; + +default: + ret=FALSE; + } + + AIRPDCAP_DEBUG_TRACE_END("AirPDcapValidateKey"); + return ret; +} + +INT AirPDcapGetSa( + PAIRPDCAP_CONTEXT ctx, + AIRPDCAP_SEC_ASSOCIATION_ID *id) +{ + INT index; + + if (ctx->last_stored_index!=-1) { + /* at least one association was stored */ + /* search for the association from last_stored_index to 0 (most recent added) */ + for (index=ctx->last_stored_index; index>=0; index--) { + if (ctx->sa[index].used) { + if (memcmp(id, &(ctx->sa[index].saId), sizeof(AIRPDCAP_SEC_ASSOCIATION_ID))==0) { + ctx->index=index; + return index; + } + } + } + } + + return -1; +} + +INT AirPDcapFreeSa( + PAIRPDCAP_CONTEXT ctx, + INT index) /* index of the structure to free */ +{ + /* set the structure as free (the reset will be done in AIRPDCAP_store_sta_info) */ + ctx->sa[index].used=0; + + /* set the first_free_index to avoid free blocks in the middle */ + if (index<ctx->first_free_index) + ctx->first_free_index=index; + + /* decrement the last_stored_index if this was the last stored block */ + if (index==ctx->last_stored_index) + ctx->last_stored_index--; + + /* if the list is empty, set the index */ + if (ctx->last_stored_index==-1) + ctx->index=-1; + + return ctx->index; +} + +INT AirPDcapStoreSa( + PAIRPDCAP_CONTEXT ctx, + AIRPDCAP_SEC_ASSOCIATION_ID *id) +{ + INT last_free; + + if (ctx->sa[ctx->first_free_index].used) { + /* last addition was in the middle of the array (and the first_free_index was just incremented by 1) */ + /* search for a free space from the first_free_index to AIRPDCAP_STA_INFOS_NR (to avoid free blocks in */ + /* the middle) */ + for (last_free=ctx->first_free_index; last_free<AIRPDCAP_MAX_SEC_ASSOCIATIONS_NR; last_free++) + if (!ctx->sa[last_free].used) + break; + + if (last_free>=AIRPDCAP_MAX_SEC_ASSOCIATIONS_NR) { + /* there is no empty space available. FAILURE */ + return -1; + } + + /* store first free space index */ + ctx->first_free_index=last_free; + } + + /* use this info */ + ctx->index=ctx->first_free_index; + + /* reset the info structure */ + memset(ctx->sa+ctx->index, 0, sizeof(AIRPDCAP_SEC_ASSOCIATION)); + + ctx->sa[ctx->index].used=1; + + /* set the info structure */ + memcpy(&(ctx->sa[ctx->index].saId), id, sizeof(AIRPDCAP_SEC_ASSOCIATION_ID)); + + /* increment by 1 the first_free_index (heuristic) */ + ctx->first_free_index++; + + /* set the last_stored_index if the added index is greater the the last_stored_index */ + if (ctx->index > ctx->last_stored_index) + ctx->last_stored_index=ctx->index; + + return ctx->index; +} + +UCHAR * AirPDcapGetStaAddress( + PAIRPDCAP_MAC_FRAME frame) +{ + if (AIRPDCAP_TO_DS(frame->fc[1])==0) { + if (AIRPDCAP_FROM_DS(frame->fc[1])==0) + return NULL; + else + return frame->addr1; + } else { + if (AIRPDCAP_FROM_DS(frame->fc[1])==0) + return frame->addr2; + else + return NULL; + } +} + +UCHAR * AirPDcapGetBssidAddress( + PAIRPDCAP_MAC_FRAME frame) +{ + if (AIRPDCAP_TO_DS(frame->fc[1])==0) { + if (AIRPDCAP_FROM_DS(frame->fc[1])==0) + return frame->addr3; + else + return frame->addr2; + } else { + if (AIRPDCAP_FROM_DS(frame->fc[1])==0) + return frame->addr1; + else + return NULL; + } +} + +/* Function used to derive the PTK. Refer to IEEE 802.11I-2004, pag. 74 */ +void AirPDcapRsnaPrfX( + AIRPDCAP_SEC_ASSOCIATION *sa, + const UCHAR pmk[32], + const UCHAR snonce[32], + const INT x, /* for TKIP 512, for CCMP 384 */ + UCHAR *ptk) +{ + UINT8 i; + UCHAR R[100]; + INT offset=sizeof("Pairwise key expansion"); + + memset(R, 0, 100); + + memcpy(R, "Pairwise key expansion", offset); + + /* Min(AA, SPA) || Max(AA, SPA) */ + if (memcmp(sa->saId.sta, sa->saId.bssid, AIRPDCAP_MAC_LEN) < 0) + { + memcpy(R + offset, sa->saId.sta, AIRPDCAP_MAC_LEN); + memcpy(R + offset+AIRPDCAP_MAC_LEN, sa->saId.bssid, AIRPDCAP_MAC_LEN); + } + else + { + memcpy(R + offset, sa->saId.bssid, AIRPDCAP_MAC_LEN); + memcpy(R + offset+AIRPDCAP_MAC_LEN, sa->saId.sta, AIRPDCAP_MAC_LEN); + } + + offset+=AIRPDCAP_MAC_LEN*2; + + /* Min(ANonce,SNonce) || Max(ANonce,SNonce) */ + if( memcmp(snonce, sa->wpa.nonce, 32) < 0 ) + { + memcpy(R + offset, snonce, 32); + memcpy(R + offset + 32, sa->wpa.nonce, 32); + } + else + { + memcpy(R + offset, sa->wpa.nonce, 32); + memcpy(R + offset + 32, snonce, 32); + } + + offset+=32*2; + + for(i = 0; i < (x+159)/160; i++) + { + R[offset] = i; + AirPDcapAlgHmacSha1(pmk, 32, R, 100, ptk + i * 20); + } +} + +INT AirPDcapRsnaPwd2PskStep( + const CHAR *password, + const CHAR *ssid, + const size_t ssidLength, + const INT iterations, + const INT count, + UCHAR *output) +{ + UCHAR digest[36], digest1[AIRPDCAP_SHA_DIGEST_LEN]; + INT i, j; + + /* U1 = PRF(P, S || INT(i)) */ + memcpy(digest, ssid, ssidLength); + digest[ssidLength] = (UCHAR)((count>>24) & 0xff); + digest[ssidLength+1] = (UCHAR)((count>>16) & 0xff); + digest[ssidLength+2] = (UCHAR)((count>>8) & 0xff); + digest[ssidLength+3] = (UCHAR)(count & 0xff); + AirPDcapAlgHmacSha1((UCHAR *)password, strlen(password), digest, ssidLength+4, digest1); + + /* output = U1 */ + memcpy(output, digest1, AIRPDCAP_SHA_DIGEST_LEN); + for (i = 1; i < iterations; i++) { + /* Un = PRF(P, Un-1) */ + AirPDcapAlgHmacSha1((UCHAR *)password, strlen(password), digest1, AIRPDCAP_SHA_DIGEST_LEN, digest); + + memcpy(digest1, digest, AIRPDCAP_SHA_DIGEST_LEN); + /* output = output xor Un */ + for (j = 0; j < AIRPDCAP_SHA_DIGEST_LEN; j++) { + output[j] ^= digest[j]; + } + } + + return AIRPDCAP_RET_SUCCESS; +} + +INT AirPDcapRsnaPwd2Psk( + const CHAR *password, + const CHAR *ssid, + const size_t ssidLength, + UCHAR *output) +{ + UCHAR m_output[AIRPDCAP_WPA_PSK_LEN]; + + memset(m_output, 0, AIRPDCAP_WPA_PSK_LEN); + + memset(m_output, 0, 40); + + AirPDcapRsnaPwd2PskStep(password, ssid, ssidLength, 4096, 1, m_output); + AirPDcapRsnaPwd2PskStep(password, ssid, ssidLength, 4096, 2, &m_output[AIRPDCAP_SHA_DIGEST_LEN]); + + memcpy(output, m_output, AIRPDCAP_WPA_PSK_LEN); + + return 0; +} + +/***************************************************************************/ +/* The following code come from freeBSD and implements the AUTODIN II */ +/* polynomial used by 802.11. */ +/* It can be used to calculate multicast address hash indices. */ +/* It assumes that the low order bits will be transmitted first, */ +/* and consequently the low byte should be sent first when */ +/* the crc computation is finished. The crc should be complemented */ +/* before transmission. */ +/* The variable corresponding to the macro argument "crc" should */ +/* be an unsigned long and should be preset to all ones for Ethernet */ +/* use. An error-free packet will leave 0xDEBB20E3 in the crc. */ +/***************************************************************************/ +INT AirPDcapAlgCrc32( + UCHAR *buf, + size_t nr, + ULONG *cval) +{ + ULONG crc32_total = 0 ; + ULONG crc = ~(ULONG)0; + UCHAR *p ; + size_t len; + + len = 0 ; + crc32_total = ~crc32_total ; + + for(len += nr, p = buf; nr--; ++p) + { + CRC(crc, *p) ; + CRC(crc32_total, *p) ; + } + + *cval = ~crc ; + crc32_total = ~crc32_total ; + + return 0; +} #ifdef __cplusplus } diff --git a/airpdcap/airpdcap_ccmp.c b/airpdcap/airpdcap_ccmp.c index b3cc2a77bb..5dfa85a8f6 100644 --- a/airpdcap/airpdcap_ccmp.c +++ b/airpdcap/airpdcap_ccmp.c @@ -4,10 +4,9 @@ #include "airpdcap_system.h" #include "airpdcap_int.h" -#include "airpdcap_ccmp.h" #include "airpdcap_rijndael.h" -#include "airpdcap_debug.h" +#include "airpdcap_debug.h" /* */ /******************************************************************************/ @@ -37,14 +36,14 @@ /* Internal macros */ /* */ #define CCMP_DECRYPT(_i, _b, _b0, _pos, _a, _len) { \ - /* Decrypt, with counter */ \ - _b0[14] = (UINT8)((_i >> 8) & 0xff); \ - _b0[15] = (UINT8)(_i & 0xff); \ - rijndael_encrypt(&key, _b0, _b); \ - xor_block(_pos, _b, _len); \ - /* Authentication */ \ - xor_block(_a, _pos, _len); \ - rijndael_encrypt(&key, _a, _a); \ + /* Decrypt, with counter */ \ + _b0[14] = (UINT8)((_i >> 8) & 0xff); \ + _b0[15] = (UINT8)(_i & 0xff); \ + rijndael_encrypt(&key, _b0, _b); \ + xor_block(_pos, _b, _len); \ + /* Authentication */ \ + xor_block(_a, _pos, _len); \ + rijndael_encrypt(&key, _a, _a); \ } #define AIRPDCAP_ADDR_COPY(dst,src) memcpy(dst,src,AIRPDCAP_MAC_LEN) @@ -55,8 +54,8 @@ /* Internal function prototypes declarations */ /* */ static void ccmp_init_blocks( - rijndael_ctx *ctx, -PAIRPDCAP_MAC_FRAME wh, + rijndael_ctx *ctx, + PAIRPDCAP_MAC_FRAME wh, UINT64 pn, size_t dlen, UINT8 b0[AES_BLOCK_LEN], @@ -71,12 +70,12 @@ PAIRPDCAP_MAC_FRAME wh, /* Function definitions */ /* */ static __inline UINT64 READ_6( - UINT8 b0, - UINT8 b1, - UINT8 b2, - UINT8 b3, - UINT8 b4, - UINT8 b5) + UINT8 b0, + UINT8 b1, + UINT8 b2, + UINT8 b3, + UINT8 b4, + UINT8 b5) { UINT32 iv32 = (b0 << 0) | (b1 << 8) | (b2 << 16) | (b3 << 24); UINT16 iv16 = (UINT16)((b4 << 0) | (b5 << 8)); @@ -84,8 +83,8 @@ static __inline UINT64 READ_6( } static void ccmp_init_blocks( - rijndael_ctx *ctx, -PAIRPDCAP_MAC_FRAME wh, + rijndael_ctx *ctx, + PAIRPDCAP_MAC_FRAME wh, UINT64 pn, size_t dlen, UINT8 b0[AES_BLOCK_LEN], @@ -189,9 +188,9 @@ PAIRPDCAP_MAC_FRAME wh, } INT AirPDcapCcmpDecrypt( - UINT8 *m, - INT len, - UCHAR TK1[16]) + UINT8 *m, + INT len, + UCHAR TK1[16]) { PAIRPDCAP_MAC_FRAME wh; UINT8 aad[2 * AES_BLOCK_LEN]; diff --git a/airpdcap/airpdcap_ccmp.h b/airpdcap/airpdcap_ccmp.h index 1a5f50ae65..e69de29bb2 100644 --- a/airpdcap/airpdcap_ccmp.h +++ b/airpdcap/airpdcap_ccmp.h @@ -1,23 +0,0 @@ -#ifndef _AIRPDCAP_CCMP -#define _AIRPDCAP_CCMP - -/******************************************************************************/ -/* File includes */ -/* */ -#include "airpdcap_interop.h" -/* */ -/* */ -/******************************************************************************/ - -/******************************************************************************/ -/* External function prototypes declarations */ -/* */ -INT AirPDcapCcmpDecrypt( - UINT8 *m, - INT len, - UCHAR TK1[16]) - ; -/* */ -/******************************************************************************/ - -#endif
\ No newline at end of file diff --git a/airpdcap/airpdcap_debug.c b/airpdcap/airpdcap_debug.c index 21edadcfd8..6b6125ef5c 100644 --- a/airpdcap/airpdcap_debug.c +++ b/airpdcap/airpdcap_debug.c @@ -1,7 +1,7 @@ /******************************************************************************/ /* File includes */ /* */ -#include "airpdcap_debug.h" +#include "airpdcap_debug.h" /* */ /******************************************************************************/ @@ -18,4 +18,4 @@ extern "C" { } #endif -#endif
\ No newline at end of file +#endif diff --git a/airpdcap/airpdcap_debug.h b/airpdcap/airpdcap_debug.h index 1ff582c6ab..c41caaeef7 100644 --- a/airpdcap/airpdcap_debug.h +++ b/airpdcap/airpdcap_debug.h @@ -67,4 +67,4 @@ void print_debug_line(CHAR *function, CHAR *msg, INT level); #endif /* ?defined _DEBUG */ -#endif /* ?defined _AIRPDCAP_DEBUG_H */
\ No newline at end of file +#endif /* ?defined _AIRPDCAP_DEBUG_H */ diff --git a/airpdcap/airpdcap_int.h b/airpdcap/airpdcap_int.h index dd52a98532..6424be6731 100644 --- a/airpdcap/airpdcap_int.h +++ b/airpdcap/airpdcap_int.h @@ -15,7 +15,7 @@ /* IEEE 802.11 packet type values */ #define AIRPDCAP_TYPE_MANAGEMENT 0 #define AIRPDCAP_TYPE_CONTROL 1 -#define AIRPDCAP_TYPE_DATA 2 +#define AIRPDCAP_TYPE_DATA 2 /* Min length of encrypted data (TKIP=25bytes, CCMP=21bytes) */ #define AIRPDCAP_CRYPTED_DATA_MINLEN 21 @@ -110,4 +110,4 @@ typedef struct _AIRPDCAP_MAC_FRAME_ADDR4_QOS { /* */ /******************************************************************************/ -#endif
\ No newline at end of file +#endif diff --git a/airpdcap/airpdcap_interop.h b/airpdcap/airpdcap_interop.h index e596b3a580..e398bf21bf 100644 --- a/airpdcap/airpdcap_interop.h +++ b/airpdcap/airpdcap_interop.h @@ -1,40 +1,64 @@ #ifndef _AIRPDCAP_INTEROP_H #define _AIRPDCAP_INTEROP_H -#ifdef HAVE_WIRESHARK -/* built with Wireshark */ +/** + * Cast data types commonly used in Windows (e.g. UINT16) to theirf + * GLib equivalents. + */ + +#include <glib.h> +#include <string.h> + +#ifndef INT +typedef gint INT; +#endif + +#ifndef UINT +typedef guint UINT; +#endif #ifndef UINT8 -typedef unsigned char UINT8; +typedef guint8 UINT8; #endif #ifndef UINT16 -typedef unsigned short UINT16; +typedef guint16 UINT16; #endif -#ifdef _WIN32 -/* built with Win32 */ - -#include <windows.h> +#ifndef UINT32 +typedef guint32 UINT32; +#endif -#else -/* build without Win32 */ +#ifndef UINT64 +typedef guint64 UINT64; +#endif -#endif /* ? _WIN32 */ +#ifndef USHORT +typedef gushort USHORT; +#endif -#else -/* built without Wireshark */ +#ifndef ULONG +typedef gulong ULONG; +#endif -#ifdef _WIN32 -/* built with Win32 */ +#ifndef ULONGLONG +typedef guint64 ULONGLONG; +#endif -#include <windows.h> +#ifndef CHAR +typedef gchar CHAR; +#endif -#else -/* build without Win32 */ +#ifndef UCHAR +typedef guchar UCHAR; +#endif -#endif /* ? _WIN32 */ +#ifndef size_t +typedef gsize size_t; +#endif -#endif /* ? _WIRESHARK */ +#ifndef ntohs +#define ntohs(value) g_ntohs(value) +#endif -#endif /* ? _AIRPDCAP_INTEROP_H */
\ No newline at end of file +#endif /* _AIRPDCAP_INTEROP_H */ diff --git a/airpdcap/airpdcap_md5.c b/airpdcap/airpdcap_md5.c index 182bc6a50e..aa7a6727ac 100644 --- a/airpdcap/airpdcap_md5.c +++ b/airpdcap/airpdcap_md5.c @@ -4,8 +4,6 @@ #include "airpdcap_system.h" #include "airpdcap_int.h" -#include "airpdcap_md5.h" - #include "airpdcap_debug.h" /* */ /******************************************************************************/ @@ -101,37 +99,37 @@ static UCHAR PADDING[64] = { /* Internal function prototypes declarations */ /* */ void MD5Final( - UCHAR digest[16], - MD5_CTX *context) - ; + UCHAR digest[16], + MD5_CTX *context) + ; void MD5Update( - MD5_CTX *context, - UCHAR *input, - UINT inputLen) - ; + MD5_CTX *context, + UCHAR *input, + UINT inputLen) + ; void MD5Init( - MD5_CTX *context) - ; + MD5_CTX *context) + ; static void MD5_memset( - UCHAR *output, - INT value, - UINT len) - ; + UCHAR *output, + INT value, + UINT len) + ; static void MD5_memcpy( - UCHAR *output, - UCHAR *input, - UINT len) - ; + UCHAR *output, + UCHAR *input, + UINT len) + ; static void Decode( - ULONG *output, - UCHAR *input, - UINT len) - ; + ULONG *output, + UCHAR *input, + UINT len) + ; static void Encode( - UCHAR *output, - ULONG *input, - UINT len) - ; + UCHAR *output, + ULONG *input, + UINT len) + ; /* */ /******************************************************************************/ @@ -142,9 +140,9 @@ static void Encode( a multiple of 4. */ static void Encode( - UCHAR *output, - ULONG *input, - UINT len) + UCHAR *output, + ULONG *input, + UINT len) { UINT i, j; @@ -160,9 +158,9 @@ static void Encode( a multiple of 4. */ static void Decode( - ULONG *output, - UCHAR *input, - UINT len) + ULONG *output, + UCHAR *input, + UINT len) { UINT i, j; @@ -175,9 +173,9 @@ static void Decode( */ static void MD5_memcpy( - UCHAR *output, - UCHAR *input, - UINT len) + UCHAR *output, + UCHAR *input, + UINT len) { UINT i; @@ -188,9 +186,9 @@ static void MD5_memcpy( /* Note: Replace "for loop" with standard memset if possible. */ static void MD5_memset( - UCHAR *output, - INT value, - UINT len) + UCHAR *output, + INT value, + UINT len) { UINT i; @@ -201,8 +199,8 @@ static void MD5_memset( /* MD5 basic transformation. Transforms state based on block. */ static void MD5Transform( - ULONG state[4], - UCHAR block[64]) + ULONG state[4], + UCHAR block[64]) { ULONG a = state[0], b = state[1], c = state[2], d = state[3], x[16]; @@ -293,7 +291,7 @@ static void MD5Transform( /* MD5 initialization. Begins an MD5 operation, writing a new context. */ void MD5Init( - MD5_CTX *context) + MD5_CTX *context) { memset(context, 0, sizeof(context)); @@ -311,9 +309,9 @@ operation, processing another message block, and updating the context. */ void MD5Update( - MD5_CTX *context, - UCHAR *input, - UINT inputLen) + MD5_CTX *context, + UCHAR *input, + UINT inputLen) { UINT i, index, partLen; @@ -353,8 +351,8 @@ void MD5Update( the message digest and zeroizing the context. */ void MD5Final( - UCHAR digest[16], - MD5_CTX *context) + UCHAR digest[16], + MD5_CTX *context) { UCHAR bits[8]; UINT index, padLen; @@ -380,11 +378,11 @@ void MD5Final( } void AirPDcapAlgHmacMd5( - UCHAR *key, /* pointer to authentication key */ - INT key_len, /* length of authentication key */ - const UCHAR *text, /* pointer to data stream */ - const INT text_len, /* length of data stream */ - UCHAR *digest) /* caller digest to be filled in */ + UCHAR *key, /* pointer to authentication key */ + INT key_len, /* length of authentication key */ + const UCHAR *text, /* pointer to data stream */ + const INT text_len, /* length of data stream */ + UCHAR *digest) /* caller digest to be filled in */ { MD5_CTX context; UCHAR k_ipad[65]; /* inner padding - diff --git a/airpdcap/airpdcap_md5.h b/airpdcap/airpdcap_md5.h index 0a58e31cca..e69de29bb2 100644 --- a/airpdcap/airpdcap_md5.h +++ b/airpdcap/airpdcap_md5.h @@ -1,25 +0,0 @@ -#ifndef _AIRPDCAP_MD5 -#define _AIRPDCAP_MD5 - -/******************************************************************************/ -/* File includes */ -/* */ -#include "airpdcap_interop.h" -/* */ -/* */ -/******************************************************************************/ - -/******************************************************************************/ -/* External function prototypes declarations */ -/* */ -void AirPDcapAlgHmacMd5( - UCHAR *key, /* pointer to authentication key */ - INT key_len, /* length of authentication key */ - const UCHAR *text, /* pointer to data stream */ - const INT text_len, /* length of data stream */ - UCHAR *digest) /* caller digest to be filled in */ - ; -/* */ -/******************************************************************************/ - -#endif
\ No newline at end of file diff --git a/airpdcap/airpdcap_rijndael.c b/airpdcap/airpdcap_rijndael.c index cb5755961b..c024a2da35 100644 --- a/airpdcap/airpdcap_rijndael.c +++ b/airpdcap/airpdcap_rijndael.c @@ -33,23 +33,23 @@ /* Internal function prototypes declarations */ /* */ INT rijndaelKeySetupEnc( - UINT32 rk[/*4*(Nr + 1)*/], - const UINT8 cipherKey[], - INT keyBits) - ; + UINT32 rk[/*4*(Nr + 1)*/], + const UINT8 cipherKey[], + INT keyBits) + ; INT rijndaelKeySetupDec( - UINT32 rk[/*4*(Nr + 1)*/], - const UINT8 cipherKey[], - INT keyBits) - ; + UINT32 rk[/*4*(Nr + 1)*/], + const UINT8 cipherKey[], + INT keyBits) + ; void rijndaelEncrypt( - const UINT32 rk[/*4*(Nr + 1)*/], - INT Nr, - const UINT8 pt[16], - UINT8 ct[16]) - ; + const UINT32 rk[/*4*(Nr + 1)*/], + INT Nr, + const UINT8 pt[16], + UINT8 ct[16]) + ; /* */ /******************************************************************************/ @@ -741,9 +741,9 @@ static const UINT32 rcon[] = { /* Fuction definitions */ /* */ INT rijndaelKeySetupEnc( - UINT32 rk[/*4*(Nr + 1)*/], - const UINT8 cipherKey[], - INT keyBits) + UINT32 rk[/*4*(Nr + 1)*/], + const UINT8 cipherKey[], + INT keyBits) { INT i = 0; UINT32 temp; @@ -829,9 +829,9 @@ INT rijndaelKeySetupEnc( } INT rijndaelKeySetupDec( - UINT32 rk[/*4*(Nr + 1)*/], - const UINT8 cipherKey[], - INT keyBits) + UINT32 rk[/*4*(Nr + 1)*/], + const UINT8 cipherKey[], + INT keyBits) { INT Nr, i, j; UINT32 temp; @@ -873,9 +873,9 @@ INT rijndaelKeySetupDec( } void rijndael_set_key( - rijndael_ctx *ctx, - const u_char *key, - INT bits) + rijndael_ctx *ctx, + const UCHAR *key, + INT bits) { ctx->Nr = rijndaelKeySetupEnc(ctx->ek, key, bits); @@ -883,10 +883,10 @@ void rijndael_set_key( } void rijndaelEncrypt( - const UINT32 rk[/*4*(Nr + 1)*/], - INT Nr, - const UINT8 pt[16], - UINT8 ct[16]) + const UINT32 rk[/*4*(Nr + 1)*/], + INT Nr, + const UINT8 pt[16], + UINT8 ct[16]) { UINT32 s0, s1, s2, s3, t0, t1, t2, t3; #ifndef FULL_UNROLL @@ -1069,12 +1069,12 @@ void rijndaelEncrypt( } void rijndael_encrypt( - const rijndael_ctx *ctx, - const UCHAR *src, - UCHAR *dst) + const rijndael_ctx *ctx, + const UCHAR *src, + UCHAR *dst) { rijndaelEncrypt(ctx->ek, ctx->Nr, src, dst); } /* */ -/******************************************************************************/
\ No newline at end of file +/******************************************************************************/ diff --git a/airpdcap/airpdcap_rijndael.h b/airpdcap/airpdcap_rijndael.h index 7219fcda9f..b113c84643 100644 --- a/airpdcap/airpdcap_rijndael.h +++ b/airpdcap/airpdcap_rijndael.h @@ -36,17 +36,17 @@ typedef struct s_rijndael_ctx { /* External function prototypes declarations */ /* */ void rijndael_encrypt( - const rijndael_ctx *ctx, - const UCHAR *src, - UCHAR *dst) - ; + const rijndael_ctx *ctx, + const UCHAR *src, + UCHAR *dst) + ; void rijndael_set_key( - rijndael_ctx *ctx, - const u_char *key, - INT bits) - ; + rijndael_ctx *ctx, + const UCHAR *key, + INT bits) + ; /* */ /******************************************************************************/ @@ -54,9 +54,9 @@ void rijndael_set_key( /* External function definition */ /* */ static __inline void xor_block( - UINT8 *b, - const UINT8 *a, - size_t len) + UINT8 *b, + const UINT8 *a, + size_t len) { INT i; for (i = 0; i < (INT)len; i++) @@ -65,4 +65,4 @@ static __inline void xor_block( /* */ /******************************************************************************/ -#endif
\ No newline at end of file +#endif diff --git a/airpdcap/airpdcap_sha1.c b/airpdcap/airpdcap_sha1.c index d280e0b2c8..b49fe0d0a8 100644 --- a/airpdcap/airpdcap_sha1.c +++ b/airpdcap/airpdcap_sha1.c @@ -3,7 +3,7 @@ /* */ #include "airpdcap_sha1.h" -#include "airpdcap_debug.h" +#include "airpdcap_debug.h" /* */ /******************************************************************************/ @@ -66,12 +66,12 @@ static UINT32 _K[] = { 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 }; #define S(n, x) (((x) << (n)) | ((x) >> (32 - n))) -#define PUTPAD(x) { \ +#define PUTPAD(x) { \ ctxt->m.b8[(COUNT % 64)] = (x); \ - COUNT++; \ - COUNT %= 64; \ - if (COUNT % 64 == 0) \ - sha1_step(ctxt); \ + COUNT++; \ + COUNT %= 64; \ + if (COUNT % 64 == 0) \ + sha1_step(ctxt); \ } /* */ /******************************************************************************/ @@ -80,19 +80,19 @@ static UINT32 _K[] = { 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 }; /* Function prototypes used internally */ /* */ void sha1_init( - SHA1_CONTEXT *ctxt) - ; + SHA1_CONTEXT *ctxt) + ; void sha1_result( - SHA1_CONTEXT *ctxt, - UCHAR *digest0) - ; + SHA1_CONTEXT *ctxt, + UCHAR *digest0) + ; void sha1_pad( - SHA1_CONTEXT *ctxt) - ; + SHA1_CONTEXT *ctxt) + ; static void sha1_step( - SHA1_CONTEXT *ctxt) - ; + SHA1_CONTEXT *ctxt) + ; /* */ /******************************************************************************/ @@ -104,7 +104,7 @@ static void sha1_step( /* */ /* Note: copied from FreeBSD source code, RELENG 6, sys/crypto/sha1.c, 176 */ void sha1_init( - SHA1_CONTEXT *ctxt) + SHA1_CONTEXT *ctxt) { memset(ctxt, 0, sizeof(SHA1_CONTEXT)); H(0) = 0x67452301; @@ -116,9 +116,9 @@ void sha1_init( /* Note: copied from FreeBSD source code, RELENG 6, sys/crypto/sha1.c, 223 */ void sha1_loop( - SHA1_CONTEXT *ctxt, - const UCHAR *input, - size_t len) + SHA1_CONTEXT *ctxt, + const UCHAR *input, + size_t len) { size_t gaplen; size_t gapstart; @@ -143,7 +143,7 @@ void sha1_loop( /* Note: copied from FreeBSD source code, RELENG 6, sys/crypto/sha1.c, 91 */ static void sha1_step( - SHA1_CONTEXT *ctxt) + SHA1_CONTEXT *ctxt) { UINT32 a, b, c, d, e; size_t t, s; @@ -224,7 +224,7 @@ static void sha1_step( /* Note: copied from FreeBSD source code, RELENG 6, sys/crypto/sha1.c, 188 */ void sha1_pad( - SHA1_CONTEXT *ctxt) + SHA1_CONTEXT *ctxt) { size_t padlen; /*pad length in bytes*/ size_t padstart; @@ -253,8 +253,8 @@ void sha1_pad( /* Note: copied from FreeBSD source code, RELENG 6, sys/crypto/sha1.c, 251 */ void sha1_result( - SHA1_CONTEXT *ctxt, - UCHAR *digest0) + SHA1_CONTEXT *ctxt, + UCHAR *digest0) { UINT8 *digest; @@ -274,11 +274,11 @@ void sha1_result( } void AirPDcapAlgHmacSha1( - const UCHAR *key_len, - const size_t keylen, - UCHAR *buffer, - const size_t digest_len, - UCHAR digest[20]) + const UCHAR *key_len, + const size_t keylen, + UCHAR *buffer, + const size_t digest_len, + UCHAR digest[20]) { //INT i; //SHA1_CONTEXT ictx; @@ -338,33 +338,6 @@ void AirPDcapAlgHmacSha1( sha1_loop(&octx, tmp, 20); sha1_result(&octx, digest); - //INT i; - //SHA1_CONTEXT sha1ctx; - //UCHAR k_ipad[64]; - //UCHAR k_opad[64]; - //UCHAR tmp[20]; - - //memset(k_ipad, 0, sizeof(k_ipad)); - //memset(k_opad, 0, sizeof(k_opad)); - - //memcpy(k_ipad, key_len, keylen); - //memcpy(k_opad, key_len, keylen); - - //for(i = 0; i<64; i++) - //{ - // k_ipad[i] ^= HMAC_IPAD_VAL; - // k_opad[i] ^= HMAC_OPAD_VAL; - //} - - //sha1_init(&sha1ctx); - //sha1_loop(&sha1ctx, k_ipad, 64); - //sha1_loop(&sha1ctx, buffer, digest_len); - //sha1_result(&sha1ctx, tmp); - - //sha1_init(&sha1ctx); - //sha1_loop(&sha1ctx, k_opad, 64); - //sha1_loop(&sha1ctx, tmp, 20); - //sha1_result(&sha1ctx, digest); } /* */ -/******************************************************************************/
\ No newline at end of file +/******************************************************************************/ diff --git a/airpdcap/airpdcap_sha1.h b/airpdcap/airpdcap_sha1.h index c696a0b698..87ebfb643d 100644 --- a/airpdcap/airpdcap_sha1.h +++ b/airpdcap/airpdcap_sha1.h @@ -22,14 +22,7 @@ /******************************************************************************/ /* External function prototypes declarations */ /* */ -void AirPDcapAlgHmacSha1( - const UCHAR *key_len, - const size_t keylen, - UCHAR *buffer, - const size_t digest_len, - UCHAR digest[20]) - ; /* */ /******************************************************************************/ -#endif
\ No newline at end of file +#endif diff --git a/airpdcap/airpdcap_system.h b/airpdcap/airpdcap_system.h index 28a7c2cf69..4c8d42bc59 100644 --- a/airpdcap/airpdcap_system.h +++ b/airpdcap/airpdcap_system.h @@ -21,41 +21,43 @@ #define FALSE 0 #endif -#define AIRPDCAP_RET_SUCCESS 0 -#define AIRPDCAP_RET_UNSUCCESS 1 +#define AIRPDCAP_RET_SUCCESS 0 +#define AIRPDCAP_RET_UNSUCCESS 1 -#define AIRPDCAP_RET_NO_DATA 1 -#define AIRPDCAP_RET_WRONG_DATA_SIZE 2 -#define AIRPDCAP_RET_REQ_DATA 3 -#define AIRPDCAP_RET_NO_VALID_HANDSHAKE 4 -#define AIRPDCAP_RET_NO_DATA_ENCRYPTED 5 +#define AIRPDCAP_RET_NO_DATA 1 +#define AIRPDCAP_RET_WRONG_DATA_SIZE 2 +#define AIRPDCAP_RET_REQ_DATA 3 +#define AIRPDCAP_RET_NO_VALID_HANDSHAKE 4 +#define AIRPDCAP_RET_NO_DATA_ENCRYPTED 5 -#define AIRPDCAP_RET_SUCCESS_HANDSHAKE -1 +#define AIRPDCAP_RET_SUCCESS_HANDSHAKE -1 -#define AIRPDCAP_MAX_KEYS_NR 64 +#define AIRPDCAP_MAX_KEYS_NR 64 #define AIRPDCAP_MAX_SEC_ASSOCIATIONS_NR 256 /* Decryption algorithms fields size definition (bytes) */ -#define AIRPDCAP_WPA_NONCE_LEN 32 -#define AIRPDCAP_WPA_PTK_LEN 64 /* TKIP uses 48 bytes, CCMP uses 64 bytes */ -#define AIRPDCAP_WPA_MICKEY_LEN 16 +#define AIRPDCAP_WPA_NONCE_LEN 32 +#define AIRPDCAP_WPA_PTK_LEN 64 /* TKIP uses 48 bytes, CCMP uses 64 bytes */ +#define AIRPDCAP_WPA_MICKEY_LEN 16 -#define AIRPDCAP_WEP_128_KEY_LEN 16 /* 128 bits */ +#define AIRPDCAP_WEP_128_KEY_LEN 16 /* 128 bits */ /* General 802.11 constants */ -#define AIRPDCAP_MAC_LEN 6 -#define AIRPDCAP_RADIOTAP_HEADER_LEN 24 +#define AIRPDCAP_MAC_LEN 6 +#define AIRPDCAP_RADIOTAP_HEADER_LEN 24 #define AIRPDCAP_EAPOL_MAX_LEN 1024 +#define AIRPDCAP_TK_LEN 16 + /* Max length of capture data */ -#define AIRPDCAP_MAX_CAPLEN 8192 +#define AIRPDCAP_MAX_CAPLEN 8192 -#define AIRPDCAP_WEP_IVLEN 3 /* 24bit */ -#define AIRPDCAP_WEP_KIDLEN 1 /* 1 octet */ -#define AIRPDCAP_WEP_ICV 4 -#define AIRPDCAP_WEP_HEADER AIRPDCAP_WEP_IVLEN + AIRPDCAP_WEP_KIDLEN -#define AIRPDCAP_WEP_TRAILER AIRPDCAP_WEP_ICV +#define AIRPDCAP_WEP_IVLEN 3 /* 24bit */ +#define AIRPDCAP_WEP_KIDLEN 1 /* 1 octet */ +#define AIRPDCAP_WEP_ICV 4 +#define AIRPDCAP_WEP_HEADER AIRPDCAP_WEP_IVLEN + AIRPDCAP_WEP_KIDLEN +#define AIRPDCAP_WEP_TRAILER AIRPDCAP_WEP_ICV /* * 802.11i defines an extended IV for use with non-WEP ciphers. @@ -64,19 +66,19 @@ * EXTIV bit is likewise set but the 8 bytes represent the * CCMP header rather than IV+extended-IV. */ -#define AIRPDCAP_RSNA_EXTIV 0x20 -#define AIRPDCAP_RSNA_EXTIVLEN 4 /* extended IV length */ -#define AIRPDCAP_RSNA_MICLEN 8 /* trailing MIC */ +#define AIRPDCAP_RSNA_EXTIV 0x20 +#define AIRPDCAP_RSNA_EXTIVLEN 4 /* extended IV length */ +#define AIRPDCAP_RSNA_MICLEN 8 /* trailing MIC */ -#define AIRPDCAP_RSNA_HEADER AIRPDCAP_WEP_HEADER + AIRPDCAP_RSNA_EXTIVLEN +#define AIRPDCAP_RSNA_HEADER AIRPDCAP_WEP_HEADER + AIRPDCAP_RSNA_EXTIVLEN -#define AIRPDCAP_CCMP_HEADER AIRPDCAP_RSNA_HEADER -#define AIRPDCAP_CCMP_TRAILER AIRPDCAP_RSNA_MICLEN +#define AIRPDCAP_CCMP_HEADER AIRPDCAP_RSNA_HEADER +#define AIRPDCAP_CCMP_TRAILER AIRPDCAP_RSNA_MICLEN -#define AIRPDCAP_TKIP_HEADER AIRPDCAP_RSNA_HEADER -#define AIRPDCAP_TKIP_TRAILER AIRPDCAP_RSNA_MICLEN + AIRPDCAP_WEP_ICV +#define AIRPDCAP_TKIP_HEADER AIRPDCAP_RSNA_HEADER +#define AIRPDCAP_TKIP_TRAILER AIRPDCAP_RSNA_MICLEN + AIRPDCAP_WEP_ICV -#define AIRPDCAP_CRC_LEN 4 +#define AIRPDCAP_CRC_LEN 4 /* */ /* */ /******************************************************************************/ @@ -138,193 +140,205 @@ typedef struct _AIRPDCAP_CONTEXT { extern "C" { #endif - /*! - /brief - it processes a packet and if necessary it tries to decrypt encrypted data. - The packet received in input should be an 802.11 frame (composed by the MAC header, the frame body and the FCS -if specified-). If the data will be decrypted the FCS will be recomputed. The packet received could start with a RadioTap header. - - /param ctx - [IN] pointer to the current context - - /param data - [IN] pointer to a buffer with packet data - - /param len - [IN] packet data length; this should be the capture packet length (to avoid errors in processing) - - /param decrypt_data - [OUT] pointer to a buffer that will contain decrypted data - - /param decrypt_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. - - /param fcsPresent - [IN] flag that specifies if the FCS is present in the packet or not (0 when the FCS is not present, 1 when it is). - - /param radioTapPresent - [IN] flag that specifies if a RadioTap header is present or not (0 when the header is no present, 1 when it is). - - /param mngHandshake - [IN] if TRUE this function will manage the 4-way handshake for WPA/WPA2 - - /param mngDecrypt - [IN] if TRUE this function will manage the WEP or WPA/WPA2 decryption - - /return - - AIRPDCAP_RET_SUCCESS: decryption has been done (decrypt_data and decrypt_length will contain the packet data decrypted and the lenght of the new packet) - - AIRPDCAP_RET_SUCCESS_HANDSHAKE: a step of the 4-way handshake for WPA key has been successfully done - - AIRPDCAP_RET_NO_DATA: the packet is not a data packet - - AIRPDCAP_RET_WRONG_DATA_SIZE: the size of the packet is below the accepted minimum - - AIRPDCAP_RET_REQ_DATA: required data is not available and the processing must be interrupted - - AIRPDCAP_RET_NO_VALID_HANDSHAKE: the authentication is not for WPA or RSNA - - AIRPDCAP_RET_NO_DATA_ENCRYPTED: no encrypted data - - AIRPDCAP_RET_UNSUCCESS: no decryption has been done (decrypt_data and decrypt_length will be not modified). - Some other errors could be: - data not correct - data not encrypted - key handshake, not encryption - decryption not successful - key handshake not correct - replay check not successful - - /note - The decrypted buffer should be allocated for a size equal or greater than the packet data buffer size. Before decryption process original data is copied in the buffer pointed by decrypt_data not to modify the original packet. - - /note - The length of decrypted data will consider the entire 802.11 frame (thus the MAC header, the frame body and the recalculated FCS -if initially present-) - - /note - This function is not thread-safe when used in parallel with context management functions on the same context. - */ - INT AirPDcapPacketProcess( +/** + * It processes a packet and if necessary it tries to decrypt + * encrypted data. + * The packet received in input should be an 802.11 frame (composed by the + * MAC header, the frame body and the FCS -if specified-). If the data will + * be decrypted the FCS will be recomputed. The packet received could start + * with a RadioTap header. + * @param ctx [IN] pointer to the current context + * @param data [IN] pointer to a buffer with packet data + * @param len [IN] packet data length; this should be the capture packet + * length (to avoid errors in processing) + * @param decrypt_data [OUT] pointer to a buffer that will contain + * decrypted data + * @param decrypt_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. + * @param fcsPresent [IN] flag that specifies if the FCS is present in + * the packet or not (0 when the FCS is not present, 1 when it is). + * @param radioTapPresent [IN] flag that specifies if a RadioTap header + * is present or not (0 when the header is no present, 1 when it is). + * @param mngHandshake [IN] if TRUE this function will manage the 4-way + * handshake for WPA/WPA2 + * @param mngDecrypt [IN] if TRUE this function will manage the WEP or + * WPA/WPA2 decryption + * @return + * - AIRPDCAP_RET_SUCCESS: decryption has been done (decrypt_data and + * decrypt_length will contain the packet data decrypted and the lenght of + * the new packet) + * - AIRPDCAP_RET_SUCCESS_HANDSHAKE: a step of the 4-way handshake for + * WPA key has been successfully done + * - AIRPDCAP_RET_NO_DATA: the packet is not a data packet + * - AIRPDCAP_RET_WRONG_DATA_SIZE: the size of the packet is below the + * accepted minimum + * - AIRPDCAP_RET_REQ_DATA: required data is not available and the + * processing must be interrupted + * - AIRPDCAP_RET_NO_VALID_HANDSHAKE: the authentication is not for WPA or RSNA + * - AIRPDCAP_RET_NO_DATA_ENCRYPTED: no encrypted data + * - AIRPDCAP_RET_UNSUCCESS: no decryption has been done (decrypt_data + * and decrypt_length will be not modified). + * Some other errors could be: + * data not correct + * data not encrypted + * key handshake, not encryption + * decryption not successful + * key handshake not correct + * replay check not successful + * @note + * The decrypted buffer should be allocated for a size equal or greater + * than the packet data buffer size. Before decryption process original + * data is copied in the buffer pointed by decrypt_data not to modify the + * original packet. + * @note + * The length of decrypted data will consider the entire 802.11 frame + * (thus the MAC header, the frame body and the recalculated FCS -if + * initially present-) + * @note + * This function is not thread-safe when used in parallel with context + * management functions on the same context. + */ +extern INT AirPDcapPacketProcess( PAIRPDCAP_CONTEXT ctx, - const UCHAR *data, - const size_t len, - UCHAR *decrypt_data, - size_t *decrypt_len, + const UCHAR *data, + const size_t len, + UCHAR *decrypt_data, + size_t *decrypt_len, PAIRPDCAP_KEY_ITEM key, - UINT8 fcsPresent, - UINT8 radioTapPresent, - UINT8 mngHandshake, - UINT8 mngDecrypt) - ; - - /*! - /brief - It sets a new keys collection to use during packet processing. - Any key should be well-formed, thus: it should have a defined key type and the specified length should be conforming WEP or WPA/WPA2 standards. A general WEP keys could be of any length (in the range defined in AIRPDCAP_KEY_ITEM), if a specific WEP key is used, the length of the key will be the one specified in 802.11i-2004 (40 bits or 104 bits). - For WPA/WPA2 the password (passphrase and SSID), the PSK and the PMK are in alternative, as explain in the AIRPDCAP_KEY_ITEM structure description. - - /param ctx - [IN] pointer to the current context - - /param keys - [IN] an array of keys to set. - - /param keys_nr - [IN] the size of the keys array - - /return - The number of keys correctly inserted in the current database. - - /note - Before inserting new keys, the current database will be cleaned. - - /note - This function is not thread-safe when used in parallel with context management functions and the packet process function on the same context. - */ - INT AirPDcapSetKeys( + UINT8 fcsPresent, + UINT8 radioTapPresent, + UINT8 mngHandshake, + UINT8 mngDecrypt) + ; + +/** + * It sets a new keys collection to use during packet processing. + * Any key should be well-formed, thus: it should have a defined key + * type and the specified length should be conforming WEP or WPA/WPA2 + * standards. A general WEP keys could be of any length (in the range + * defined in AIRPDCAP_KEY_ITEM), if a specific WEP key is used, the + * length of the key will be the one specified in 802.11i-2004 (40 bits or + * 104 bits). + * For WPA/WPA2 the password (passphrase and SSID), the PSK and the PMK + * are in alternative, as explain in the AIRPDCAP_KEY_ITEM structure + * description. + * @param ctx [IN] pointer to the current context + * @param keys [IN] an array of keys to set. + * @param keys_nr [IN] the size of the keys array + * @return The number of keys correctly inserted in the current database. + * @note Before inserting new keys, the current database will be cleaned. + * @note + * This function is not thread-safe when used in parallel with context + * management functions and the packet process function on the same + * context. + */ +extern INT AirPDcapSetKeys( PAIRPDCAP_CONTEXT ctx, AIRPDCAP_KEY_ITEM keys[], - const size_t keys_nr) - ; - - /*! - /brief - it removes all keys from the active database - - /param ctx - [IN] pointer to the current context - - /return - The number of keys correctly removed. - - /note - This function is not thread-safe when used in parallel with context management functions and the packet process function on the same context. - */ - INT AirPDcapCleanKeys( + const size_t keys_nr) + ; + +/** + * Remove all keys from the active database + * @param ctx [IN] pointer to the current context + * @return The number of keys correctly removed. + * + * @note + * This function is not thread-safe when used in parallel with context + * management functions and the packet process function on the same + * context. + */ +INT AirPDcapCleanKeys( PAIRPDCAP_CONTEXT ctx) - ; - - /*! - /brief - It gets the keys collection fom the specified context. - - /param ctx - [IN] pointer to the current context - - /param key - [IN] a preallocated array of keys to be returned - - /param keys_nr - [IN] the number of keys to return (the key array must be able to contain at least keys_nr keys) - - /return - The number of keys returned - - /note - Any key could be modified, as stated in the AIRPDCAP_KEY_ITEM description. - - /note - This function is not thread-safe when used in parallel with context management functions and the packet process function on the same context. - */ - INT AirPDcapGetKeys( - const PAIRPDCAP_CONTEXT ctx, + ; + +/** + * It gets the keys collection fom the specified context. + * @param ctx [IN] pointer to the current context + * @param key [IN] a preallocated array of keys to be returned + * @param keys_nr [IN] the number of keys to return (the key array must + * be able to contain at least keys_nr keys) + * @return The number of keys returned + * @note + * Any key could be modified, as stated in the AIRPDCAP_KEY_ITEM description. + * @note + * This function is not thread-safe when used in parallel with context + * management functions and the packet process function on the same + * context. + */ +INT AirPDcapGetKeys( + const PAIRPDCAP_CONTEXT ctx, AIRPDCAP_KEY_ITEM keys[], - const size_t keys_nr) - ; - /*! - /brief - it initializes a context used to manage decryption and keys collection. - - /param ctx - [IN|OUT] pointer to a preallocated context structure - - /return - AIRPDCAP_RET_SUCCESS: the context has been successfully initialized - AIRPDCAP_RET_UNSUCCESS: the context has not been initialized - - /note - Only a correctly initialized context can be used to manage decryption processes and keys. - - /note - This function is not thread-safe when used in parallel with context - management functions and the packet process function on the same context. - */ - INT AirPDcapInitContext( + const size_t keys_nr) + ; +/** + * Initialize a context used to manage decryption and keys collection. + * @param ctx [IN|OUT] pointer to a preallocated context structure + * @return + * AIRPDCAP_RET_SUCCESS: the context has been successfully initialized + * AIRPDCAP_RET_UNSUCCESS: the context has not been initialized + * @note + * Only a correctly initialized context can be used to manage decryption + * processes and keys. + * @note + * This function is not thread-safe when used in parallel with context + * management functions and the packet process function on the same context. + */ +INT AirPDcapInitContext( + PAIRPDCAP_CONTEXT ctx) + ; + +/** + * Clean up the specified context. After the cleanup the pointer should + * not be used anymore. + * @param ctx [IN|OUT] pointer to the current context structure + * @return + * AIRPDCAP_RET_SUCCESS: the context has been successfully initialized + * AIRPDCAP_RET_UNSUCCESS: the context has not been initialized + * @note + * This function is not thread-safe when used in parallel with context + * management functions and the packet process function on the same + * context. + */ +INT AirPDcapDestroyContext( PAIRPDCAP_CONTEXT ctx) - ; + ; + + +extern INT AirPDcapWepDecrypt( + const UCHAR *seed, + const size_t seed_len, /* max AIRPDCAP_KEYBUF_SIZE */ + UCHAR *cypher_text, + const size_t data_len) + ; +extern INT AirPDcapCcmpDecrypt( + UINT8 *m, + INT len, + UCHAR TK1[16]) + ; +extern INT AirPDcapTkipDecrypt( + UCHAR *tkip_mpdu, + size_t mpdu_len, + UCHAR TA[AIRPDCAP_MAC_LEN], + UCHAR TK[AIRPDCAP_TK_LEN]) + ; +extern void AirPDcapAlgHmacMd5( + UCHAR *key, /* pointer to authentication key */ + INT key_len, /* length of authentication key */ + const UCHAR *text, /* pointer to data stream */ + const INT text_len, /* length of data stream */ + UCHAR *digest) /* caller digest to be filled in */ + ; +extern void AirPDcapAlgHmacSha1( + const UCHAR *key_len, + const size_t keylen, + UCHAR *buffer, + const size_t digest_len, + UCHAR digest[20]) + ; - /*! - /brief - it cleanup the specified context. After the cleanup the pointer should not be used anymore. - - /param ctx - [IN|OUT] pointer to the current context structure - - /return - AIRPDCAP_RET_SUCCESS: the context has been successfully initialized - AIRPDCAP_RET_UNSUCCESS: the context has not been initialized - - /note - This function is not thread-safe when used in parallel with context management functions and the packet process function on the same context. - */ - INT AirPDcapDestroyContext( - PAIRPDCAP_CONTEXT ctx) - ; #ifdef __cplusplus } @@ -333,4 +347,4 @@ extern "C" { /* */ /******************************************************************************/ -#endif
\ No newline at end of file +#endif /* _AIRPDCAP_SYSTEM_H */ diff --git a/airpdcap/airpdcap_tkip.c b/airpdcap/airpdcap_tkip.c index d9fb2bdd9c..886540e6c9 100644 --- a/airpdcap/airpdcap_tkip.c +++ b/airpdcap/airpdcap_tkip.c @@ -4,10 +4,9 @@ #include "airpdcap_system.h" #include "airpdcap_int.h" -#include "airpdcap_tkip.h" #include "airpdcap_wep.h" -#include "airpdcap_debug.h" +#include "airpdcap_debug.h" /* */ /******************************************************************************/ @@ -24,18 +23,18 @@ /* Internal function prototypes declarations */ /* */ void AirPDcapTkipMixingPhase1( - UINT16 *TTAK, - const UINT8 *TK, - const UINT8 *TA, - UINT32 TSC) - ; + UINT16 *TTAK, + const UINT8 *TK, + const UINT8 *TA, + UINT32 TSC) + ; static void AirPDcapTkipMixingPhase2( - UINT8 *wep_seed, - const UINT8 *TK, - UINT16 *PPK, - UINT16 TSC16) - ; + UINT8 *wep_seed, + const UINT8 *TK, + UINT16 *PPK, + UINT16 TSC16) + ; /* */ /******************************************************************************/ @@ -90,38 +89,38 @@ static const UINT16 Sbox[256] = { /* Note: any functions were copied from FreeBSD source code, RELENG 6, */ /* sys/net80211/ieee80211_crypto_tkip.c */ static __inline UINT16 RotR1( - UINT16 val) + UINT16 val) { return (UINT16)((val >> 1) | (val << 15)); } static __inline UINT8 Lo8( - UINT16 val) + UINT16 val) { return (UINT8)(val & 0xff); } static __inline UINT8 Hi8( - UINT16 val) + UINT16 val) { return (UINT8)(val >> 8); } static __inline UINT16 Lo16( - UINT32 val) + UINT32 val) { return (UINT16)(val & 0xffff); } static __inline UINT16 Hi16( - UINT32 val) + UINT32 val) { return (UINT16)(val >> 16); } static __inline UINT16 Mk16( - UINT8 hi, - UINT8 lo) + UINT8 hi, + UINT8 lo) { return (UINT16)(lo | (((UINT16) hi) << 8)); } @@ -132,19 +131,19 @@ static __inline UINT16 Mk16_le(const UINT16 *v) } static __inline UINT16 _S_( - UINT16 v) + UINT16 v) { UINT16 t = Sbox[Hi8(v)]; return (UINT16)(Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8))); } static __inline UINT64 READ_6( - UINT8 b0, - UINT8 b1, - UINT8 b2, - UINT8 b3, - UINT8 b4, - UINT8 b5) + UINT8 b0, + UINT8 b1, + UINT8 b2, + UINT8 b3, + UINT8 b4, + UINT8 b5) { UINT32 iv32 = (b0 << 0) | (b1 << 8) | (b2 << 16) | (b3 << 24); UINT16 iv16 = (UINT16)((b4 << 0) | (b5 << 8)); @@ -152,10 +151,10 @@ static __inline UINT64 READ_6( } void AirPDcapTkipMixingPhase1( - UINT16 *TTAK, - const UINT8 *TK, - const UINT8 *TA, - UINT32 TSC) + UINT16 *TTAK, + const UINT8 *TK, + const UINT8 *TA, + UINT32 TSC) { UINT16 i, j; @@ -177,10 +176,10 @@ void AirPDcapTkipMixingPhase1( } static void AirPDcapTkipMixingPhase2( - UINT8 *wep_seed, - const UINT8 *TK, - UINT16 *TTAK, - UINT16 TSC16) + UINT8 *wep_seed, + const UINT8 *TK, + UINT16 *TTAK, + UINT16 TSC16) { INT i; TTAK[5] = (UINT16)(TTAK[4] + TSC16); @@ -217,10 +216,10 @@ static void AirPDcapTkipMixingPhase2( /* Note: taken from FreeBSD source code, RELENG 6, */ /* sys/net80211/ieee80211_crypto_tkip.c, 936 */ INT AirPDcapTkipDecrypt( - UCHAR *tkip_mpdu, - size_t mpdu_len, - UCHAR TA[AIRPDCAP_MAC_LEN], - UCHAR TK[AIRPDCAP_TK_LEN]) + UCHAR *tkip_mpdu, + size_t mpdu_len, + UCHAR TA[AIRPDCAP_MAC_LEN], + UCHAR TK[AIRPDCAP_TK_LEN]) { UINT32 TSC; UINT16 TSC16; diff --git a/airpdcap/airpdcap_tkip.h b/airpdcap/airpdcap_tkip.h index 4b7b2c49be..e69de29bb2 100644 --- a/airpdcap/airpdcap_tkip.h +++ b/airpdcap/airpdcap_tkip.h @@ -1,27 +0,0 @@ -#ifndef _AIRPDCAP_TKIP_H -#define _AIRPDCAP_TKIP_H - -/******************************************************************************/ -/* File includes */ -/* */ -#include "airpdcap_interop.h" -/* */ -/* */ -/******************************************************************************/ - -#define AIRPDCAP_TK_LEN 16 - -/******************************************************************************/ -/* External function prototypes declarations */ -/* */ -/* Note: copied and modified from net80211/ieee80211_airpdcap_tkip.c */ -INT AirPDcapTkipDecrypt( - UCHAR *tkip_mpdu, - size_t mpdu_len, - UCHAR TA[AIRPDCAP_MAC_LEN], - UCHAR TK[AIRPDCAP_TK_LEN]) - ; -/* */ -/******************************************************************************/ - -#endif
\ No newline at end of file diff --git a/airpdcap/airpdcap_user.h b/airpdcap/airpdcap_user.h index b872b931f5..b637ea90b8 100644 --- a/airpdcap/airpdcap_user.h +++ b/airpdcap/airpdcap_user.h @@ -32,8 +32,8 @@ #define AIRPDCAP_WPA_PASSPHRASE_MAX_LEN 63 /* null-terminated string, the actual length of the storage is 64 */ #define AIRPDCAP_WPA_SSID_MIN_LEN 0 #define AIRPDCAP_WPA_SSID_MAX_LEN 32 -#define AIRPDCAP_WPA_PSK_LEN 64 -#define AIRPDCAP_WPA_PMK_LEN 32 +#define AIRPDCAP_WPA_PSK_LEN 64 +#define AIRPDCAP_WPA_PMK_LEN 32 /* */ /* */ /******************************************************************************/ @@ -47,67 +47,89 @@ /******************************************************************************/ /* Type definitions */ /* */ -/*! -/brief -It represent a key item used during the decryption process. -*/ -typedef struct _AIRPDCAP_KEY_ITEM { - /*! - /brief - Type of key. The type will remain unchanged during the processing, even if some fields could be changed (e.g., WPA fields). +/** + * Struct to store info about a specific decryption key. + */ +typedef struct { + GString *key; + GString *ssid; + guint bits; + guint type; +} decryption_key_t; - /note - You can use constants AIRPDCAP_KEY_TYPE_xxx to indicate the key type. - */ +/** + * Key item used during the decryption process. + */ +typedef struct _AIRPDCAP_KEY_ITEM { + /** + * Type of key. The type will remain unchanged during the + * processing, even if some fields could be changed (e.g., WPA + * fields). + * @note + * You can use constants AIRPDCAP_KEY_TYPE_xxx to indicate the + * key type. + */ UINT8 KeyType; - /*! - /brief - Key data. - This field can be used for the following decryptographic algorithms: WEP-40, with a key of 40 bits (10 hex-digits); WEP-104, with a key of 104 bits (or 26 hex-digits); WPA or WPA2. - /note - For WPA/WPA2, the PMK is calculated from the PSK, and the PSK is calculated from the passphrase-SSID pair. You can enter one of these 3 values and subsequent fields will be automatically calculated. - /note - For WPA and WPA2 this implementation will use standards as defined in 802.11i (2004) and 802.1X (2004). - */ + /** + * Key data. + * This field can be used for the following decryptographic + * algorithms: WEP-40, with a key of 40 bits (10 hex-digits); + * WEP-104, with a key of 104 bits (or 26 hex-digits); WPA or + * WPA2. + * @note + * For WPA/WPA2, the PMK is calculated from the PSK, and the PSK + * is calculated from the passphrase-SSID pair. You can enter one + * of these 3 values and subsequent fields will be automatically + * calculated. + * @note + * For WPA and WPA2 this implementation will use standards as + * defined in 802.11i (2004) and 802.1X (2004). + */ union AIRPDCAP_KEY_ITEMDATA { struct AIRPDCAP_KEY_ITEMDATA_WEP { - /*! - /brief - The binary value of the WEP key. - /note - It is accepted a key of lenght between AIRPDCAP_WEP_KEY_MINLEN and AIRPDCAP_WEP_KEY_MAXLEN. A WEP key standard-compliante should be either 40 bits (10 hex-digits, 5 bytes) for WEP-40 or 104 bits (26 hex-digits, 13 bytes) for WEP-104. - */ + /** + * The binary value of the WEP key. + * @note + * It is accepted a key of lenght between + * AIRPDCAP_WEP_KEY_MINLEN and + * AIRPDCAP_WEP_KEY_MAXLEN. A WEP key + * standard-compliante should be either 40 bits + * (10 hex-digits, 5 bytes) for WEP-40 or 104 bits + * (26 hex-digits, 13 bytes) for WEP-104. + */ UCHAR WepKey[AIRPDCAP_WEP_KEY_MAXLEN]; - /*! - /brief - The length of the WEP key. Acceptable range is [AIRPDCAP_WEP_KEY_MINLEN;AIRPDCAP_WEP_KEY_MAXLEN]. - */ + /** + * The length of the WEP key. Acceptable range + * is [AIRPDCAP_WEP_KEY_MINLEN;AIRPDCAP_WEP_KEY_MAXLEN]. + */ size_t WepKeyLen; } Wep; - /*! - /brief - WPA/WPA2 key data. Note that the decryption process will use the PMK (equal to PSK), that is calculated from passphrase-SSID pair. You can define one of these three fields and necessary fields will be automatically calculated. - */ + /** + * WPA/WPA2 key data. Note that the decryption process + * will use the PMK (equal to PSK), that is calculated + * from passphrase-SSID pair. You can define one of these + * three fields and necessary fields will be automatically + * calculated. + */ union AIRPDCAP_KEY_ITEMDATA_WPA { struct AIRPDCAP_KEY_ITEMDATA_PWD { - /*! - /brief - The string (null-terminated) value of the passphrase. - */ + /** + * The string (null-terminated) value of + * the passphrase. + */ CHAR Passphrase[AIRPDCAP_WPA_PASSPHRASE_MAX_LEN+1]; - /*! - /brief - The value of the SSID (up to AIRPDCAP_WPA_SSID_MAX_LEN octets). - /note - A zero-length SSID indicates broadcast. - */ + /** + * The value of the SSID (up to + * AIRPDCAP_WPA_SSID_MAX_LEN octets). + * @note + * A zero-length SSID indicates broadcast. + */ CHAR Ssid[AIRPDCAP_WPA_SSID_MAX_LEN]; - /*! - /brief - The length of the SSID - */ + /** + *The length of the SSID + */ size_t SsidLen; } UserPwd; @@ -118,21 +140,18 @@ typedef struct _AIRPDCAP_KEY_ITEM { } KeyData; } AIRPDCAP_KEY_ITEM, *PAIRPDCAP_KEY_ITEM; -/*! -/brief -Collection of keys to use to decrypt packets -*/ +/** + * Collection of keys to use to decrypt packets + */ typedef struct _AIRPDCAP_KEYS_COLLECTION { - /*! - /brief - Number of stored keys - */ + /** + * Number of stored keys + */ size_t nKeys; - /*! - /brief - Array of nKeys keys - */ + /** + * Array of nKeys keys + */ AIRPDCAP_KEY_ITEM Keys[256]; } AIRPDCAP_KEYS_COLLECTION, *PAIRPDCAP_KEYS_COLLECTION; /* */ @@ -145,4 +164,4 @@ typedef struct _AIRPDCAP_KEYS_COLLECTION { /* */ /******************************************************************************/ -#endif
\ No newline at end of file +#endif /* _AIRPDCAP_USER_H */ diff --git a/airpdcap/airpdcap_wep.c b/airpdcap/airpdcap_wep.c index f4dc72cb30..1501d61155 100644 --- a/airpdcap/airpdcap_wep.c +++ b/airpdcap/airpdcap_wep.c @@ -6,7 +6,7 @@ #include "airpdcap_wep.h" -#include "airpdcap_debug.h" +#include "airpdcap_debug.h" /* */ /******************************************************************************/ @@ -15,10 +15,10 @@ extern const UINT32 crc32_table[256]; /* Note: copied from FreeBSD source code, RELENG 6, */ /* sys/net80211/ieee80211_crypto_wep.c, 391 */ INT AirPDcapWepDecrypt( - const UCHAR *seed, - const size_t seed_len, - UCHAR *cypher_text, - const size_t data_len) + const UCHAR *seed, + const size_t seed_len, + UCHAR *cypher_text, + const size_t data_len) { UINT32 i, j, k, crc; UINT8 S[256]; @@ -64,4 +64,4 @@ INT AirPDcapWepDecrypt( } return AIRPDCAP_RET_SUCCESS; -}
\ No newline at end of file +} diff --git a/airpdcap/airpdcap_wep.h b/airpdcap/airpdcap_wep.h index 1534e2d564..a7885c18f6 100644 --- a/airpdcap/airpdcap_wep.h +++ b/airpdcap/airpdcap_wep.h @@ -72,13 +72,7 @@ static const UINT32 crc32_table[256] = { /******************************************************************************/ /* External function prototypes declarations */ /* */ -INT AirPDcapWepDecrypt( - const UCHAR *seed, - const size_t seed_len, /* max AIRPDCAP_KEYBUF_SIZE */ - UCHAR *cypher_text, - const size_t data_len) - ; /* */ /******************************************************************************/ -#endif
\ No newline at end of file +#endif /* _AIRPDCAP_WEP */ diff --git a/airpdcap/airpdcap_ws.h b/airpdcap/airpdcap_ws.h index 1811bd1288..6eec4d0ff6 100644 --- a/airpdcap/airpdcap_ws.h +++ b/airpdcap/airpdcap_ws.h @@ -1,9 +1,7 @@ #ifndef _AIRPDCAP_WS_H #define _AIRPDCAP_WS_H -#define HAVE_WIRESHARK - #include "airpdcap_system.h" WS_VAR_IMPORT AIRPDCAP_CONTEXT airpdcap_ctx; -#endif
\ No newline at end of file +#endif /* _AIRPDCAP_WS_H */ diff --git a/configure.in b/configure.in index b03164a3ed..67f58cd9ef 100644 --- a/configure.in +++ b/configure.in @@ -1047,6 +1047,12 @@ AC_SUBST(ADNS_LIBS) # AC_DEFINE(WS_VAR_IMPORT, extern, [Define as the string to precede external variable declarations in dynamically-linked libraries]) +# +# Define HAVE_AIRPDCAP +# We'll want to remove this eventually. +# +AC_DEFINE(HAVE_AIRPDCAP, 1, [Enable AirPDcap (WPA/WPA2 decryption)]) + dnl Checks for typedefs, structures, and compiler characteristics. # AC_C_CONST @@ -1313,6 +1319,7 @@ AC_CONFIG_SUBDIRS(wiretap) AC_OUTPUT( Makefile doxygen.cfg + airpdcap/Makefile asn1/Makefile doc/Makefile epan/Makefile diff --git a/epan/Makefile.am b/epan/Makefile.am index 966a29a612..4443d77105 100644 --- a/epan/Makefile.am +++ b/epan/Makefile.am @@ -100,8 +100,8 @@ MAINTAINERCLEANFILES = \ # # Add the object files for missing routines, if any. # -libwireshark_la_LIBADD = @G_ASCII_STRTOULL_LO@ @INET_ATON_LO@ @INET_PTON_LO@ @INET_NTOP_LO@ dfilter/libdfilter.la ftypes/libftypes.la dissectors/libdissectors.la $(wslua_lib) @ADNS_LIBS@ @LIBGNUTLS_LIBS@ @LIBICONV@ @KRB5_LIBS@ @SNMP_LIBS@ @SSL_LIBS@ -lm -libwireshark_la_DEPENDENCIES = @G_ASCII_STRTOULL_LO@ @INET_ATON_LO@ @INET_PTON_LO@ @INET_NTOP_LO@ dfilter/libdfilter.la ftypes/libftypes.la dissectors/libdissectors.la $(wslua_lib) +libwireshark_la_LIBADD = @G_ASCII_STRTOULL_LO@ @INET_ATON_LO@ @INET_PTON_LO@ @INET_NTOP_LO@ dfilter/libdfilter.la ftypes/libftypes.la dissectors/libdissectors.la ../airpdcap/libairpdcap.a $(wslua_lib) @ADNS_LIBS@ @LIBGNUTLS_LIBS@ @LIBICONV@ @KRB5_LIBS@ @SNMP_LIBS@ @SSL_LIBS@ -lm +libwireshark_la_DEPENDENCIES = @G_ASCII_STRTOULL_LO@ @INET_ATON_LO@ @INET_PTON_LO@ @INET_NTOP_LO@ dfilter/libdfilter.la ftypes/libftypes.la dissectors/libdissectors.la ../airpdcap/libairpdcap.a $(wslua_lib) tvbtest: tvbtest.o tvbuff.o except.o strutil.o emem.o $(LINK) $^ $(GLIB_LIBS) -lz diff --git a/epan/dissectors/packet-ieee80211.c b/epan/dissectors/packet-ieee80211.c index b40b11b48c..9285be48a0 100644 --- a/epan/dissectors/packet-ieee80211.c +++ b/epan/dissectors/packet-ieee80211.c @@ -70,6 +70,7 @@ #include <epan/crc32.h> #include <epan/tap.h> #include <epan/emem.h> +#include <epan/crypt/wep-wpadefs.h> #include <ctype.h> #include "isprint.h" @@ -791,14 +792,15 @@ static dissector_handle_t data_handle; static int wlan_tap = -1; -/* Davide Schiera (2006-11-22): including AirPDcap project */ -#ifdef HAVE_AIRPDCAP -#include "..\..\airpdcap\airpdcap_ws.h" +/* Davide Schiera (2006-11-22): including AirPDcap project */ +#ifdef HAVE_AIRPDCAP +#include "airpdcap/airpdcap_ws.h" AIRPDCAP_CONTEXT airpdcap_ctx; #else int airpdcap_ctx; #endif -/* Davide Schiera (2006-11-22) ---------------------------------------------- */ +/* Davide Schiera (2006-11-22) ---------------------------------------------- */ + /* ************************************************************************* */ /* Return the length of the current header (in bytes) */ @@ -5454,7 +5456,7 @@ void set_airpdcap_keys() gboolean res; gchar* tmpk = NULL; - keys=(PAIRPDCAP_KEYS_COLLECTION)malloc(sizeof(AIRPDCAP_KEYS_COLLECTION)); + keys=(PAIRPDCAP_KEYS_COLLECTION)g_malloc(sizeof(AIRPDCAP_KEYS_COLLECTION)); keys->nKeys = 0; for(i = 0; i < MAX_ENCRYPTION_KEYS; i++) @@ -5526,12 +5528,13 @@ void set_airpdcap_keys() keys->nKeys++; } } + if(tmpk != NULL) g_free(tmpk); } /* Now set the keys */ AirPDcapSetKeys(&airpdcap_ctx,keys->Keys,keys->nKeys); + g_free(keys); - if(tmpk != NULL) g_free(tmpk); } #endif diff --git a/gtk/main.c b/gtk/main.c index 150f7eb5d4..3c139ea71f 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -174,7 +174,7 @@ #ifdef HAVE_AIRPDCAP /* Davide Schiera (2006-11-22): including AirPDcap project */ -#include "..\airpdcap\airpdcap_ws.h" +#include "../airpdcap/airpdcap_ws.h" /* Davide Schiera (2006-11-22) ---------------------------------------------- */ #endif |