* AIRPDCAP_SHA_DIGEST_LEN characters that will contain a part of the key
*/
static INT AirPDcapRsnaPwd2PskStep(
- CHAR *password,
- const CHAR *ssid,
- const size_t ssidLength,
- const INT iterations,
- const INT count,
- UCHAR *output)
- ;
+ 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
* Described in 802.11i-2004, page 165
*/
static INT AirPDcapRsnaPwd2Psk(
- CHAR *password,
- const CHAR *ssid,
- const size_t ssidLength,
- UCHAR *output)
- ;
+ CHAR *password,
+ const CHAR *ssid,
+ const size_t ssidLength,
+ UCHAR *output)
+ ;
static INT AirPDcapRsnaMng(
- UCHAR *decrypt_data,
- size_t *decrypt_len,
- PAIRPDCAP_KEY_ITEM key,
- AIRPDCAP_SEC_ASSOCIATION *sa,
- INT offset,
- UINT8 fcsPresent)
- ;
+ UCHAR *decrypt_data,
+ size_t *decrypt_len,
+ PAIRPDCAP_KEY_ITEM key,
+ AIRPDCAP_SEC_ASSOCIATION *sa,
+ INT offset,
+ UINT8 fcsPresent)
+ ;
static INT AirPDcapWepMng(
- PAIRPDCAP_CONTEXT ctx,
- UCHAR *decrypt_data,
- size_t *decrypt_len,
- PAIRPDCAP_KEY_ITEM key,
- AIRPDCAP_SEC_ASSOCIATION *sa,
- INT offset,
- UINT8 fcsPresent)
- ;
+ PAIRPDCAP_CONTEXT ctx,
+ UCHAR *decrypt_data,
+ size_t *decrypt_len,
+ PAIRPDCAP_KEY_ITEM key,
+ AIRPDCAP_SEC_ASSOCIATION *sa,
+ INT offset,
+ UINT8 fcsPresent)
+ ;
static INT AirPDcapRsna4WHandshake(
- PAIRPDCAP_CONTEXT ctx,
- const UCHAR *data,
- AIRPDCAP_SEC_ASSOCIATION *sa,
- PAIRPDCAP_KEY_ITEM key,
- INT offset)
- ;
+ 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
* - FALSE: the key has some invalid field or value
*/
static INT AirPDcapValidateKey(
- PAIRPDCAP_KEY_ITEM key)
- ;
+ PAIRPDCAP_KEY_ITEM key)
+ ;
static INT AirPDcapRsnaMicCheck(
- UCHAR *eapol,
- USHORT eapol_len,
- UCHAR KCK[AIRPDCAP_WPA_KCK_LEN],
- USHORT key_ver)
- ;
+ UCHAR *eapol,
+ USHORT eapol_len,
+ UCHAR KCK[AIRPDCAP_WPA_KCK_LEN],
+ USHORT key_ver)
+ ;
/**
* @param ctx [IN] pointer to the current context
* - -1, if the specified addresses pair BSSID-STA MAC has not been found
*/
static INT AirPDcapGetSa(
- PAIRPDCAP_CONTEXT ctx,
- AIRPDCAP_SEC_ASSOCIATION_ID *id)
- ;
+ PAIRPDCAP_CONTEXT ctx,
+ AIRPDCAP_SEC_ASSOCIATION_ID *id)
+ ;
static INT AirPDcapStoreSa(
- PAIRPDCAP_CONTEXT ctx,
- AIRPDCAP_SEC_ASSOCIATION_ID *id)
- ;
+ PAIRPDCAP_CONTEXT ctx,
+ AIRPDCAP_SEC_ASSOCIATION_ID *id)
+ ;
static const UCHAR * AirPDcapGetStaAddress(
- const AIRPDCAP_MAC_FRAME *frame)
- ;
+ const AIRPDCAP_MAC_FRAME_ADDR4 *frame)
+ ;
static const UCHAR * AirPDcapGetBssidAddress(
- const AIRPDCAP_MAC_FRAME *frame)
- ;
+ const AIRPDCAP_MAC_FRAME_ADDR4 *frame)
+ ;
static 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)
- ;
+ AIRPDCAP_SEC_ASSOCIATION *sa,
+ const UCHAR pmk[32],
+ const UCHAR snonce[32],
+ const INT x, /* for TKIP 512, for CCMP 384 */
+ UCHAR *ptk)
+ ;
#ifdef __cplusplus
}
#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)
+ 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;
- const UCHAR *address;
- AIRPDCAP_SEC_ASSOCIATION_ID id;
- INT index;
- PAIRPDCAP_SEC_ASSOCIATION sa;
- INT offset;
- UINT16 bodyLength;
+ size_t mac_header_len;
+ const UCHAR *address;
+ AIRPDCAP_SEC_ASSOCIATION_ID id;
+ INT index;
+ PAIRPDCAP_SEC_ASSOCIATION sa;
+ INT offset;
+ UINT16 bodyLength;
+ const UCHAR dot1x_header[] = {
+ 0xAA, /* DSAP=SNAP */
+ 0xAA, /* SSAP=SNAP */
+ 0x03, /* Control field=Unnumbered frame */
+ 0x00, 0x00, 0x00, /* Org. code=encaps. Ethernet */
+ 0x88, 0x8E /* Type: 802.1X authentication */
+ };
#ifdef _DEBUG
- CHAR msgbuf[255];
+ CHAR msgbuf[255];
#endif
- AIRPDCAP_DEBUG_TRACE_START("AirPDcapPacketProcess");
+ 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 (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;
+ 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 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;
- }
+ /* 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;
+ }
- /* 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 BSSID */
+ if ( (address=AirPDcapGetBssidAddress((const AIRPDCAP_MAC_FRAME_ADDR4 *)(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]);
+#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 the Security Association structure */
- sa=&ctx->sa[index];
-
- /* Do we have WEP, TKIP, or CCMP data? */
- if (AIRPDCAP_WEP(data[1]) && mngDecrypt && decrypt_data) {
- /* cache offset in the packet data (to scan encryption data) */
- offset+=AIRPDCAP_HEADER_LEN(data[offset+1]);
-
- /* 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);
- }
+ /* get STA address */
+ if ( (address=AirPDcapGetStaAddress((const AIRPDCAP_MAC_FRAME_ADDR4 *)(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]);
+#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;
}
+ }
- /* Build our keying material */
+ /* 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) {
- /* get BSSID */
- if ( (address=AirPDcapGetBssidAddress((const AIRPDCAP_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]);
-#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;
+ /* 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 (memcmp(data+offset, dot1x_header, 8) == 0) {
+ 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 STA address */
- if ( (address=AirPDcapGetStaAddress((const AIRPDCAP_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]);
-#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;
+ /* get and check the body length (IEEE 802.1X-2004, pg. 25) */
+ bodyLength=pntohs(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;
}
- /* cache offset in the packet data (to scan encryption data) */
- offset+=AIRPDCAP_HEADER_LEN(data[offset+1]);
-
- /* 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;
- }
+ /* skip EAPOL MPDU and go to the first byte of the body */
+ offset+=4;
- /* get and check the body length (IEEE 802.1X-2004, pg. 25) */
- bodyLength=pntohs(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;
- }
+ /* 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;
+ }
- /* skip EAPOL MPDU and go to the first byte of the body */
- offset+=4;
+ /* start with descriptor body */
+ offset+=1;
- /* 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;
- }
+ /* 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) {
- /* start with descriptor body */
- offset+=1;
+ if (decrypt_data==NULL)
+ return AIRPDCAP_RET_UNSUCCESS;
- /* 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;
- }
+ /* 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;
+ return AIRPDCAP_RET_UNSUCCESS;
}
INT AirPDcapSetKeys(
- PAIRPDCAP_CONTEXT ctx,
- AIRPDCAP_KEY_ITEM keys[],
- const size_t keys_nr)
+ 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;
- }
+ INT i;
+ INT success;
+ AIRPDCAP_DEBUG_TRACE_START("AirPDcapSetKeys");
- 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;
- }
+ 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);
+ /* 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].UserPwd.Passphrase, keys[i].UserPwd.Ssid, keys[i].UserPwd.SsidLen, keys[i].KeyData.Wpa.Psk);
- }
+ /* 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].UserPwd.Passphrase, keys[i].UserPwd.Ssid, keys[i].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
- memcpy(&ctx->keys[success], &keys[i], sizeof(keys[i]));
- success++;
- }
+ memcpy(&ctx->keys[success], &keys[i], sizeof(keys[i]));
+ success++;
}
+ }
- ctx->keys_nr=success;
+ ctx->keys_nr=success;
- AIRPDCAP_DEBUG_TRACE_END("AirPDcapSetKeys");
- return success;
+ AIRPDCAP_DEBUG_TRACE_END("AirPDcapSetKeys");
+ return success;
}
INT AirPDcapCleanKeys(
- PAIRPDCAP_CONTEXT ctx)
+ PAIRPDCAP_CONTEXT ctx)
{
- INT i;
- AIRPDCAP_DEBUG_TRACE_START("AirPDcapCleanKeys");
+ 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;
- }
+ 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));
- }
+ for (i=0; i<AIRPDCAP_MAX_KEYS_NR; i++) {
+ memset(&ctx->keys[i], 0, sizeof(AIRPDCAP_KEY_ITEM));
+ }
- ctx->keys_nr=0;
+ ctx->keys_nr=0;
- AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapCleanKeys", "Keys collection cleaned!", AIRPDCAP_DEBUG_LEVEL_5);
- AIRPDCAP_DEBUG_TRACE_END("AirPDcapCleanKeys");
+ AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapCleanKeys", "Keys collection cleaned!", AIRPDCAP_DEBUG_LEVEL_5);
+ AIRPDCAP_DEBUG_TRACE_END("AirPDcapCleanKeys");
- return i;
+ return i;
}
INT AirPDcapGetKeys(
- const PAIRPDCAP_CONTEXT ctx,
- AIRPDCAP_KEY_ITEM keys[],
- const size_t keys_nr)
+ 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++) {
- memcpy(&keys[j], &ctx->keys[i], sizeof(keys[j]));
- j++;
- AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapGetKeys", "Got a key", AIRPDCAP_DEBUG_LEVEL_5);
- }
+ UINT i;
+ UINT j;
+ AIRPDCAP_DEBUG_TRACE_START("AirPDcapGetKeys");
- AIRPDCAP_DEBUG_TRACE_END("AirPDcapGetKeys");
- return j;
+ 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++) {
+ memcpy(&keys[j], &ctx->keys[i], sizeof(keys[j]));
+ j++;
+ AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapGetKeys", "Got a key", AIRPDCAP_DEBUG_LEVEL_5);
}
+
+ AIRPDCAP_DEBUG_TRACE_END("AirPDcapGetKeys");
+ return j;
+ }
}
/*
* SSIDs.
*/
INT AirPDcapSetLastSSID(
- PAIRPDCAP_CONTEXT ctx,
- CHAR *pkt_ssid,
- size_t pkt_ssid_len)
+ PAIRPDCAP_CONTEXT ctx,
+ CHAR *pkt_ssid,
+ size_t pkt_ssid_len)
{
- if (!ctx || !pkt_ssid || pkt_ssid_len < 1 || pkt_ssid_len > WPA_SSID_MAX_SIZE)
- return AIRPDCAP_RET_UNSUCCESS;
+ if (!ctx || !pkt_ssid || pkt_ssid_len < 1 || pkt_ssid_len > WPA_SSID_MAX_SIZE)
+ return AIRPDCAP_RET_UNSUCCESS;
- memcpy(ctx->pkt_ssid, pkt_ssid, pkt_ssid_len);
- ctx->pkt_ssid_len = pkt_ssid_len;
+ memcpy(ctx->pkt_ssid, pkt_ssid, pkt_ssid_len);
+ ctx->pkt_ssid_len = pkt_ssid_len;
- return AIRPDCAP_RET_SUCCESS;
+ return AIRPDCAP_RET_SUCCESS;
}
INT AirPDcapInitContext(
- PAIRPDCAP_CONTEXT ctx)
+ PAIRPDCAP_CONTEXT ctx)
{
- AIRPDCAP_DEBUG_TRACE_START("AirPDcapInitContext");
+ 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;
- }
+ 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);
+ AirPDcapCleanKeys(ctx);
- ctx->first_free_index=0;
- ctx->index=-1;
- ctx->last_stored_index=-1;
- ctx->pkt_ssid_len = 0;
+ ctx->first_free_index=0;
+ ctx->index=-1;
+ ctx->last_stored_index=-1;
+ ctx->pkt_ssid_len = 0;
- AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapInitContext", "Context initialized!", AIRPDCAP_DEBUG_LEVEL_5);
- AIRPDCAP_DEBUG_TRACE_END("AirPDcapInitContext");
- return AIRPDCAP_RET_SUCCESS;
+ 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)
+ PAIRPDCAP_CONTEXT ctx)
{
- AIRPDCAP_DEBUG_TRACE_START("AirPDcapDestroyContext");
+ 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;
- }
+ 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);
+ AirPDcapCleanKeys(ctx);
- ctx->first_free_index=0;
- ctx->index=-1;
- ctx->last_stored_index=-1;
+ 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;
+ AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapDestroyContext", "Context destroyed!", AIRPDCAP_DEBUG_LEVEL_5);
+ AIRPDCAP_DEBUG_TRACE_END("AirPDcapDestroyContext");
+ return AIRPDCAP_RET_SUCCESS;
}
#ifdef __cplusplus
static INT
AirPDcapRsnaMng(
- UCHAR *decrypt_data,
- size_t *decrypt_len,
- PAIRPDCAP_KEY_ITEM key,
- AIRPDCAP_SEC_ASSOCIATION *sa,
- INT offset,
- UINT8 fcsPresent)
+ UCHAR *decrypt_data,
+ size_t *decrypt_len,
+ PAIRPDCAP_KEY_ITEM key,
+ AIRPDCAP_SEC_ASSOCIATION *sa,
+ INT offset,
+ UINT8 fcsPresent)
{
- INT ret_value;
- ULONG crc;
+ 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);
+ 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;
+ 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);
+ 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;
+ 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;
- }
+ 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 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);
+ /* 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 */
- crc = crc32_ccitt(decrypt_data, *decrypt_len);
- memcpy(decrypt_data+*decrypt_len, &crc, sizeof crc);
+ if (fcsPresent) {
+ /* calculate FCS */
+ crc = crc32_ccitt(decrypt_data, *decrypt_len);
+ memcpy(decrypt_data+*decrypt_len, &crc, sizeof crc);
- /* add FCS in packet */
- *decrypt_len+=4;
- }
+ /* add FCS in packet */
+ *decrypt_len+=4;
+ }
- if (key!=NULL) {
- memcpy(key, sa->key, sizeof(AIRPDCAP_KEY_ITEM));
+ 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;
- }
+ 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;
+ return AIRPDCAP_RET_SUCCESS;
}
static INT
AirPDcapWepMng(
- PAIRPDCAP_CONTEXT ctx,
- UCHAR *decrypt_data,
- size_t *decrypt_len,
- PAIRPDCAP_KEY_ITEM key,
- AIRPDCAP_SEC_ASSOCIATION *sa,
- INT offset,
- UINT8 fcsPresent)
+ 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;
- UCHAR *try_data = ep_alloc(*decrypt_len);
-
- 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];
- }
- }
+ 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;
+ UCHAR *try_data = ep_alloc(*decrypt_len);
+
+ 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);
+ /* 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));
- memcpy(try_data, decrypt_data, *decrypt_len);
+ memset(wep_key, 0, sizeof(wep_key));
+ memcpy(try_data, decrypt_data, *decrypt_len);
- /* 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, try_data+AIRPDCAP_HEADER_LEN(try_data[1]), AIRPDCAP_WEP_IVLEN);
- keylen=tmp_key->KeyData.Wep.WepKeyLen;
- memcpy(wep_key+AIRPDCAP_WEP_IVLEN, tmp_key->KeyData.Wep.WepKey, keylen);
+ /* 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, try_data+AIRPDCAP_HEADER_LEN(try_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,
- try_data + (AIRPDCAP_HEADER_LEN(try_data[1])+AIRPDCAP_WEP_IVLEN+AIRPDCAP_WEP_KIDLEN),
- *decrypt_len-(AIRPDCAP_HEADER_LEN(try_data[1])+AIRPDCAP_WEP_IVLEN+AIRPDCAP_WEP_KIDLEN+AIRPDCAP_CRC_LEN));
+ ret_value=AirPDcapWepDecrypt(wep_key,
+ keylen+AIRPDCAP_WEP_IVLEN,
+ try_data + (AIRPDCAP_HEADER_LEN(try_data[1])+AIRPDCAP_WEP_IVLEN+AIRPDCAP_WEP_KIDLEN),
+ *decrypt_len-(AIRPDCAP_HEADER_LEN(try_data[1])+AIRPDCAP_WEP_IVLEN+AIRPDCAP_WEP_KIDLEN+AIRPDCAP_CRC_LEN));
- if (ret_value == AIRPDCAP_RET_SUCCESS)
- memcpy(decrypt_data, try_data, *decrypt_len);
- }
+ if (ret_value == AIRPDCAP_RET_SUCCESS)
+ memcpy(decrypt_data, try_data, *decrypt_len);
+ }
- if (!ret_value && tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WEP) {
- /* the tried key is the correct one, cached in the Security Association */
+ 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;
+ sa->key=tmp_key;
- if (key!=NULL) {
- memcpy(key, &sa->key, sizeof(AIRPDCAP_KEY_ITEM));
- key->KeyType=AIRPDCAP_KEY_TYPE_WEP;
- }
+ 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 */
+ break;
+ } else {
+ /* the cached key was not valid, try other keys */
- if (useCache==TRUE) {
- useCache=FALSE;
- key_index--;
- }
- }
+ if (useCache==TRUE) {
+ useCache=FALSE;
+ key_index--;
+ }
}
+ }
- if (ret_value)
- return ret_value;
+ if (ret_value)
+ return ret_value;
- AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "WEP DECRYPTED!!!", AIRPDCAP_DEBUG_LEVEL_3);
+ AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "WEP DECRYPTED!!!", AIRPDCAP_DEBUG_LEVEL_3);
- /* remove ICV (4bytes) from the end of packet */
- *decrypt_len-=4;
+ /* remove ICV (4bytes) from the end of packet */
+ *decrypt_len-=4;
- /* remove protection bit */
- decrypt_data[1]&=0xBF;
+ /* 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);
+ /* 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 */
- crc = crc32_ccitt(decrypt_data, *decrypt_len);
- memcpy(decrypt_data+*decrypt_len, &crc, sizeof crc);
+ if (fcsPresent) {
+ /* calculate FCS and append it at the end of the decrypted packet */
+ crc = crc32_ccitt(decrypt_data, *decrypt_len);
+ memcpy(decrypt_data+*decrypt_len, &crc, sizeof crc);
- /* add FCS in packet */
- *decrypt_len += 4;
- }
+ /* add FCS in packet */
+ *decrypt_len += 4;
+ }
- return AIRPDCAP_RET_SUCCESS;
+ return AIRPDCAP_RET_SUCCESS;
}
/* Refer to IEEE 802.11i-2004, 8.5.3, pag. 85 */
static INT
AirPDcapRsna4WHandshake(
- PAIRPDCAP_CONTEXT ctx,
- const UCHAR *data,
- AIRPDCAP_SEC_ASSOCIATION *sa,
- PAIRPDCAP_KEY_ITEM key,
- INT offset)
+ PAIRPDCAP_CONTEXT ctx,
+ const UCHAR *data,
+ AIRPDCAP_SEC_ASSOCIATION *sa,
+ PAIRPDCAP_KEY_ITEM key,
+ INT offset)
{
- AIRPDCAP_KEY_ITEM *tmp_key, pkt_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;
- }
+ AIRPDCAP_KEY_ITEM *tmp_key, pkt_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 timeouts? reauthentication? */
- /* TODO consider key-index */
+ /* TODO consider key-index */
- /* TODO considera Deauthentications */
+ /* TODO considera Deauthentications */
- AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake...", AIRPDCAP_DEBUG_LEVEL_5);
+ 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) */
+ /* 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);
+ /* 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!) */
+ /* 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);
+ /* 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]);
+ /* 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;
+ sa->handshake=1;
- return AIRPDCAP_RET_SUCCESS_HANDSHAKE;
- }
+ 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 (data[offset+92]!=0 || data[offset+93]!=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 || useCache; 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)
- {
- if (tmp_key->KeyType == AIRPDCAP_KEY_TYPE_WPA_PWD && tmp_key->UserPwd.SsidLen == 0 && ctx->pkt_ssid_len > 0 && ctx->pkt_ssid_len <= AIRPDCAP_WPA_SSID_MAX_LEN) {
- /* We have a "wildcard" SSID. Use the one from the packet. */
- memcpy(&pkt_key, tmp_key, sizeof(pkt_key));
- memcpy(&pkt_key.UserPwd.Ssid, ctx->pkt_ssid, ctx->pkt_ssid_len);
- pkt_key.UserPwd.SsidLen = ctx->pkt_ssid_len;
- AirPDcapRsnaPwd2Psk(pkt_key.UserPwd.Passphrase, pkt_key.UserPwd.Ssid,
- pkt_key.UserPwd.SsidLen, pkt_key.KeyData.Wpa.Psk);
- tmp_key = &pkt_key;
- }
-
- /* 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=pntohs(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;
+ /* 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 (data[offset+92]!=0 || data[offset+93]!=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 || useCache; 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 {
- /* message 4 */
-
- /* TODO "Note that when the 4-Way Handshake is first used Message 4 is sent in the clear." */
+ 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)
+ {
+ if (tmp_key->KeyType == AIRPDCAP_KEY_TYPE_WPA_PWD && tmp_key->UserPwd.SsidLen == 0 && ctx->pkt_ssid_len > 0 && ctx->pkt_ssid_len <= AIRPDCAP_WPA_SSID_MAX_LEN) {
+ /* We have a "wildcard" SSID. Use the one from the packet. */
+ memcpy(&pkt_key, tmp_key, sizeof(pkt_key));
+ memcpy(&pkt_key.UserPwd.Ssid, ctx->pkt_ssid, ctx->pkt_ssid_len);
+ pkt_key.UserPwd.SsidLen = ctx->pkt_ssid_len;
+ AirPDcapRsnaPwd2Psk(pkt_key.UserPwd.Passphrase, pkt_key.UserPwd.Ssid,
+ pkt_key.UserPwd.SsidLen, pkt_key.KeyData.Wpa.Psk);
+ tmp_key = &pkt_key;
+ }
- /* 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. */
+ /* 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=pntohs(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 */
- AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 4 (patched)", AIRPDCAP_DEBUG_LEVEL_3);
+ sa->key=tmp_key;
- sa->handshake=4;
+ 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;
+ }
- sa->validKey=TRUE;
+ break;
+ } else {
+ /* the cached key was not valid, try other keys */
- return AIRPDCAP_RET_SUCCESS_HANDSHAKE;
+ if (useCache==TRUE) {
+ useCache=FALSE;
+ key_index--;
}
- /* 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. */
+ if (ret_value) {
+ AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "handshake step failed", AIRPDCAP_DEBUG_LEVEL_3);
+ return ret_value;
+ }
- AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 4", AIRPDCAP_DEBUG_LEVEL_3);
+ sa->handshake=2;
- sa->handshake=4;
+ return AIRPDCAP_RET_SUCCESS_HANDSHAKE;
+ } else {
+ /* message 4 */
- sa->validKey=TRUE;
+ /* TODO "Note that when the 4-Way Handshake is first used Message 4 is sent in the clear." */
- return AIRPDCAP_RET_SUCCESS_HANDSHAKE;
- }
- }
+ /* 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. */
- /* 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);
+ AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 4 (patched)", 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!) */
+ sa->handshake=4;
- /* TODO check page 88 (RNS) */
+ 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;
}
+ }
- return AIRPDCAP_RET_UNSUCCESS;
+ /* 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;
}
static INT
AirPDcapRsnaMicCheck(
- UCHAR *eapol,
- USHORT eapol_len,
- UCHAR KCK[AIRPDCAP_WPA_KCK_LEN],
- USHORT key_ver)
+ UCHAR *eapol,
+ USHORT eapol_len,
+ UCHAR KCK[AIRPDCAP_WPA_KCK_LEN],
+ 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 */
- md5_hmac(eapol, eapol_len, KCK, AIRPDCAP_WPA_KCK_LEN, c_mic);
- } else if (key_ver==AIRPDCAP_WPA_KEY_VER_AES_CCMP) {
- /* use HMAC-SHA1-128 for the EAPOL-Key MIC */
- sha1_hmac(KCK, AIRPDCAP_WPA_KCK_LEN, eapol, eapol_len, c_mic);
- } else
- /* key descriptor version not recognized */
- return AIRPDCAP_RET_UNSUCCESS;
+ 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 */
+ md5_hmac(eapol, eapol_len, KCK, AIRPDCAP_WPA_KCK_LEN, c_mic);
+ } else if (key_ver==AIRPDCAP_WPA_KEY_VER_AES_CCMP) {
+ /* use HMAC-SHA1-128 for the EAPOL-Key MIC */
+ sha1_hmac(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);
+ /* compare calculated MIC with the Key MIC and return result (0 means success) */
+ return memcmp(mic, c_mic, AIRPDCAP_WPA_MICKEY_LEN);
}
static INT
AirPDcapValidateKey(
- PAIRPDCAP_KEY_ITEM key)
+ PAIRPDCAP_KEY_ITEM key)
{
- size_t len;
- UCHAR ret=TRUE;
- AIRPDCAP_DEBUG_TRACE_START("AirPDcapValidateKey");
+ 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;
- }
+ 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->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->UserPwd.SsidLen;
- if (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;
- }
+ 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->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->UserPwd.SsidLen;
+ if (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;
+ AIRPDCAP_DEBUG_TRACE_END("AirPDcapValidateKey");
+ return ret;
}
static INT
AirPDcapGetSa(
- PAIRPDCAP_CONTEXT ctx,
- AIRPDCAP_SEC_ASSOCIATION_ID *id)
+ 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;
- }
- }
+ 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;
+ return -1;
}
static INT
AirPDcapStoreSa(
- PAIRPDCAP_CONTEXT ctx,
- AIRPDCAP_SEC_ASSOCIATION_ID *id)
+ 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;
+ 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;
}
- /* use this info */
- ctx->index=ctx->first_free_index;
+ /* 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));
+ /* reset the info structure */
+ memset(ctx->sa+ctx->index, 0, sizeof(AIRPDCAP_SEC_ASSOCIATION));
- ctx->sa[ctx->index].used=1;
+ ctx->sa[ctx->index].used=1;
- /* set the info structure */
- memcpy(&(ctx->sa[ctx->index].saId), id, sizeof(AIRPDCAP_SEC_ASSOCIATION_ID));
+ /* 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++;
+ /* 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;
+ /* 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;
+ return ctx->index;
}
+/*
+ * AirPDcapGetBssidAddress() and AirPDcapGetBssidAddress() are used for
+ * key caching. In each case, it's more important to return a value than
+ * to return a _correct_ value, so we fudge addresses in some cases, e.g.
+ * the BSSID in bridged connections.
+ * FromDS ToDS Sta BSSID
+ * 0 0 addr2 addr3
+ * 0 1 addr2 addr1
+ * 1 0 addr1 addr2
+ * 1 1 addr2 addr1
+ */
+
static const UCHAR *
AirPDcapGetStaAddress(
- const AIRPDCAP_MAC_FRAME *frame)
+ const AIRPDCAP_MAC_FRAME_ADDR4 *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;
- }
+ switch(AIRPDCAP_DS_BITS(frame->fc[1])) { /* Bit 1 = FromDS, bit 0 = ToDS */
+ case 0:
+ case 1:
+ case 3:
+ return frame->addr2;
+ case 2:
+ return frame->addr1;
+ default:
+ return NULL;
+ }
}
static const UCHAR *
AirPDcapGetBssidAddress(
- const AIRPDCAP_MAC_FRAME *frame)
+ const AIRPDCAP_MAC_FRAME_ADDR4 *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;
- }
+ switch(AIRPDCAP_DS_BITS(frame->fc[1])) { /* Bit 1 = FromDS, bit 0 = ToDS */
+ case 0:
+ return frame->addr3;
+ case 1:
+ case 3:
+ return frame->addr1;
+ case 2:
+ return frame->addr2;
+ default:
+ return NULL;
+ }
}
/* Function used to derive the PTK. Refer to IEEE 802.11I-2004, pag. 74 */
static 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)
+ 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");
+ UINT8 i;
+ UCHAR R[100];
+ INT offset=sizeof("Pairwise key expansion");
- memset(R, 0, 100);
+ memset(R, 0, 100);
- memcpy(R, "Pairwise key expansion", offset);
+ 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);
- }
+ /* 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;
+ 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);
- }
+ /* 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;
+ offset+=32*2;
- for(i = 0; i < (x+159)/160; i++)
- {
- R[offset] = i;
- sha1_hmac(pmk, 32, R, 100, ptk + i * 20);
- }
+ for(i = 0; i < (x+159)/160; i++)
+ {
+ R[offset] = i;
+ sha1_hmac(pmk, 32, R, 100, ptk + i * 20);
+ }
}
static INT
AirPDcapRsnaPwd2PskStep(
- CHAR *password,
- const CHAR *ssid,
- const size_t ssidLength,
- const INT iterations,
- const INT count,
- UCHAR *output)
+ 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);
- sha1_hmac((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) */
- sha1_hmac((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];
- }
+ 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);
+ sha1_hmac((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) */
+ sha1_hmac((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;
+ return AIRPDCAP_RET_SUCCESS;
}
static INT
AirPDcapRsnaPwd2Psk(
- CHAR *password,
- const CHAR *ssid,
- const size_t ssidLength,
- UCHAR *output)
+ CHAR *password,
+ const CHAR *ssid,
+ const size_t ssidLength,
+ UCHAR *output)
{
- UCHAR m_output[AIRPDCAP_WPA_PSK_LEN];
+ UCHAR m_output[AIRPDCAP_WPA_PSK_LEN];
- memset(m_output, 0, AIRPDCAP_WPA_PSK_LEN);
+ memset(m_output, 0, AIRPDCAP_WPA_PSK_LEN);
- memset(m_output, 0, 40);
+ 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]);
+ 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);
+ memcpy(output, m_output, AIRPDCAP_WPA_PSK_LEN);
- return 0;
+ return 0;
}
/*
decryption_key_t *dk;
if(input_string == NULL)
- return NULL;
+ return NULL;
/*
* Parse the input_string. It should be in the form
/* Tokens is a null termiated array of strings ... */
while(tokens[n] != NULL)
- n++;
+ n++;
if(n == 0)
{
- /* Free the array of strings */
- g_strfreev(tokens);
- return NULL;
+ /* Free the array of strings */
+ g_strfreev(tokens);
+ return NULL;
}
/*
*/
if(n == 1)
{
- /* Maybe it is an 'old style' WEP key */
- key = g_strdup(tokens[0]);
-
- /* Create a new string */
- key_string = g_string_new(key);
-
- /* Check if it is a correct WEP key */
- if( ((key_string->len) > WEP_KEY_MAX_CHAR_SIZE) || ((key_string->len) < WEP_KEY_MIN_CHAR_SIZE))
- {
- g_string_free(key_string, TRUE);
- g_free(key);
- /* Free the array of strings */
- g_strfreev(tokens);
- return NULL;
- }
-
- if((key_string->len % 2) != 0)
- {
- g_string_free(key_string, TRUE);
- g_free(key);
- /* Free the array of strings */
- g_strfreev(tokens);
- return NULL;
- }
-
- for(i = 0; i < key_string->len; i++)
- {
- if(!g_ascii_isxdigit(key_string->str[i]))
- {
- g_string_free(key_string, TRUE);
- g_free(key);
- /* Free the array of strings */
- g_strfreev(tokens);
- return NULL;
- }
- }
-
- /* Key is correct! It was probably an 'old style' WEP key */
- /* Create the decryption_key_t structure, fill it and return it*/
- dk = g_malloc(sizeof(decryption_key_t));
-
- dk->type = AIRPDCAP_KEY_TYPE_WEP;
- dk->key = g_string_new(key);
- dk->bits = dk->key->len * 4;
- dk->ssid = NULL;
-
- g_string_free(key_string, TRUE);
- g_free(key);
-
- /* Free the array of strings */
- g_strfreev(tokens);
-
- return dk;
+ /* Maybe it is an 'old style' WEP key */
+ key = g_strdup(tokens[0]);
+
+ /* Create a new string */
+ key_string = g_string_new(key);
+
+ /* Check if it is a correct WEP key */
+ if( ((key_string->len) > WEP_KEY_MAX_CHAR_SIZE) || ((key_string->len) < WEP_KEY_MIN_CHAR_SIZE))
+ {
+ g_string_free(key_string, TRUE);
+ g_free(key);
+ /* Free the array of strings */
+ g_strfreev(tokens);
+ return NULL;
+ }
+
+ if((key_string->len % 2) != 0)
+ {
+ g_string_free(key_string, TRUE);
+ g_free(key);
+ /* Free the array of strings */
+ g_strfreev(tokens);
+ return NULL;
+ }
+
+ for(i = 0; i < key_string->len; i++)
+ {
+ if(!g_ascii_isxdigit(key_string->str[i]))
+ {
+ g_string_free(key_string, TRUE);
+ g_free(key);
+ /* Free the array of strings */
+ g_strfreev(tokens);
+ return NULL;
+ }
+ }
+
+ /* Key is correct! It was probably an 'old style' WEP key */
+ /* Create the decryption_key_t structure, fill it and return it*/
+ dk = g_malloc(sizeof(decryption_key_t));
+
+ dk->type = AIRPDCAP_KEY_TYPE_WEP;
+ dk->key = g_string_new(key);
+ dk->bits = dk->key->len * 4;
+ dk->ssid = NULL;
+
+ g_string_free(key_string, TRUE);
+ g_free(key);
+
+ /* Free the array of strings */
+ g_strfreev(tokens);
+
+ return dk;
}
/* There were at least 2 tokens... copy the type value */
/* Maybe there is a third token (an ssid, if everything else is ok) */
if(n >= 3)
{
- ssid = g_strdup(tokens[2]);
+ ssid = g_strdup(tokens[2]);
}
else
{
- ssid = NULL;
+ ssid = NULL;
}
/*
*/
if(g_strcasecmp(type,STRING_KEY_TYPE_WEP) == 0) /* WEP key */
{
- /* Create a new string */
- key_string = g_string_new(key);
-
- /* Check if it is a correct WEP key */
- if( ((key_string->len) > WEP_KEY_MAX_CHAR_SIZE) || ((key_string->len) < WEP_KEY_MIN_CHAR_SIZE))
- {
- g_string_free(key_string, TRUE);
- g_free(key);
- /* Free the array of strings */
- g_strfreev(tokens);
- return NULL;
- }
-
- if((key_string->len % 2) != 0)
- {
- g_string_free(key_string, TRUE);
- g_free(key);
- /* Free the array of strings */
- g_strfreev(tokens);
- return NULL;
- }
-
- for(i = 0; i < key_string->len; i++)
- {
- if(!g_ascii_isxdigit(key_string->str[i]))
- {
- g_string_free(key_string, TRUE);
- g_free(key);
- /* Free the array of strings */
- g_strfreev(tokens);
- return NULL;
- }
- }
-
- dk = (decryption_key_t*)g_malloc(sizeof(decryption_key_t));
-
- dk->type = AIRPDCAP_KEY_TYPE_WEP;
- dk->key = g_string_new(key);
- dk->bits = dk->key->len * 4;
- dk->ssid = NULL;
-
- g_string_free(key_string, TRUE);
- g_free(key);
-
- /* Free the array of strings */
- g_strfreev(tokens);
- return dk;
+ /* Create a new string */
+ key_string = g_string_new(key);
+
+ /* Check if it is a correct WEP key */
+ if( ((key_string->len) > WEP_KEY_MAX_CHAR_SIZE) || ((key_string->len) < WEP_KEY_MIN_CHAR_SIZE))
+ {
+ g_string_free(key_string, TRUE);
+ g_free(key);
+ /* Free the array of strings */
+ g_strfreev(tokens);
+ return NULL;
+ }
+
+ if((key_string->len % 2) != 0)
+ {
+ g_string_free(key_string, TRUE);
+ g_free(key);
+ /* Free the array of strings */
+ g_strfreev(tokens);
+ return NULL;
+ }
+
+ for(i = 0; i < key_string->len; i++)
+ {
+ if(!g_ascii_isxdigit(key_string->str[i]))
+ {
+ g_string_free(key_string, TRUE);
+ g_free(key);
+ /* Free the array of strings */
+ g_strfreev(tokens);
+ return NULL;
+ }
+ }
+
+ dk = (decryption_key_t*)g_malloc(sizeof(decryption_key_t));
+
+ dk->type = AIRPDCAP_KEY_TYPE_WEP;
+ dk->key = g_string_new(key);
+ dk->bits = dk->key->len * 4;
+ dk->ssid = NULL;
+
+ g_string_free(key_string, TRUE);
+ g_free(key);
+
+ /* Free the array of strings */
+ g_strfreev(tokens);
+ return dk;
}
else if(g_strcasecmp(type,STRING_KEY_TYPE_WPA_PSK) == 0) /* WPA key */
{
- /* Create a new string */
- key_string = g_string_new(key);
-
- /* Two tokens means that the user should have entered a WPA-BIN key ... */
- if( ((key_string->len) != WPA_PSK_KEY_CHAR_SIZE))
- {
- g_string_free(key_string, TRUE);
-
- g_free(type);
- g_free(key);
- /* No ssid has been created ... */
- /* Free the array of strings */
- g_strfreev(tokens);
- return NULL;
- }
-
- for(i = 0; i < key_string->len; i++)
- {
- if(!g_ascii_isxdigit(key_string->str[i]))
- {
- g_string_free(key_string, TRUE);
- /* No ssid_string has been created ... */
-
- g_free(type);
- g_free(key);
- /* No ssid has been created ... */
- /* Free the array of strings */
- g_strfreev(tokens);
- return NULL;
- }
- }
-
- /* Key was correct!!! Create the new decryption_key_t ... */
- dk = (decryption_key_t*)g_malloc(sizeof(decryption_key_t));
-
- dk->type = AIRPDCAP_KEY_TYPE_WPA_PMK;
- dk->key = g_string_new(key);
- dk->bits = dk->key->len * 4;
- dk->ssid = NULL;
-
- g_string_free(key_string, TRUE);
- g_free(key);
- g_free(type);
-
- /* Free the array of strings */
- g_strfreev(tokens);
- return dk;
+ /* Create a new string */
+ key_string = g_string_new(key);
+
+ /* Two tokens means that the user should have entered a WPA-BIN key ... */
+ if( ((key_string->len) != WPA_PSK_KEY_CHAR_SIZE))
+ {
+ g_string_free(key_string, TRUE);
+
+ g_free(type);
+ g_free(key);
+ /* No ssid has been created ... */
+ /* Free the array of strings */
+ g_strfreev(tokens);
+ return NULL;
+ }
+
+ for(i = 0; i < key_string->len; i++)
+ {
+ if(!g_ascii_isxdigit(key_string->str[i]))
+ {
+ g_string_free(key_string, TRUE);
+ /* No ssid_string has been created ... */
+
+ g_free(type);
+ g_free(key);
+ /* No ssid has been created ... */
+ /* Free the array of strings */
+ g_strfreev(tokens);
+ return NULL;
+ }
+ }
+
+ /* Key was correct!!! Create the new decryption_key_t ... */
+ dk = (decryption_key_t*)g_malloc(sizeof(decryption_key_t));
+
+ dk->type = AIRPDCAP_KEY_TYPE_WPA_PMK;
+ dk->key = g_string_new(key);
+ dk->bits = dk->key->len * 4;
+ dk->ssid = NULL;
+
+ g_string_free(key_string, TRUE);
+ g_free(key);
+ g_free(type);
+
+ /* Free the array of strings */
+ g_strfreev(tokens);
+ return dk;
}
else if(g_strcasecmp(type,STRING_KEY_TYPE_WPA_PWD) == 0) /* WPA key *//* If the number of tokens is more than three, we accept the string... if the first three tokens are correct... */
{
- /* Create a new string */
- key_string = g_string_new(key);
- ssid_ba = NULL;
-
-
- /* Three (or more) tokens mean that the user entered a WPA-PWD key ... */
- if( ((key_string->len) > WPA_KEY_MAX_CHAR_SIZE) || ((key_string->len) < WPA_KEY_MIN_CHAR_SIZE))
- {
- g_string_free(key_string, TRUE);
-
- g_free(type);
- g_free(key);
- g_free(ssid);
-
- /* Free the array of strings */
- g_strfreev(tokens);
- return NULL;
- }
-
- if(ssid != NULL) /* more than three tokens found, means that the user specified the ssid */
- {
- ssid_ba = g_byte_array_new();
- if (! uri_str_to_bytes(ssid, ssid_ba)) {
- g_string_free(key_string, TRUE);
- g_byte_array_free(ssid_ba, TRUE);
- g_free(type);
- g_free(key);
- g_free(ssid);
- /* Free the array of strings */
- g_strfreev(tokens);
- return NULL;
- }
-
- if(ssid_ba->len > WPA_SSID_MAX_CHAR_SIZE)
- {
- g_string_free(key_string, TRUE);
- g_byte_array_free(ssid_ba, TRUE);
-
- g_free(type);
- g_free(key);
- g_free(ssid);
-
- /* Free the array of strings */
- g_strfreev(tokens);
- return NULL;
- }
- }
-
- /* Key was correct!!! Create the new decryption_key_t ... */
- dk = (decryption_key_t*)g_malloc(sizeof(decryption_key_t));
-
- dk->type = AIRPDCAP_KEY_TYPE_WPA_PWD;
- dk->key = g_string_new(key);
- dk->bits = 256; /* This is the length of the array pf bytes that will be generated using key+ssid ...*/
- dk->ssid = byte_array_dup(ssid_ba); /* NULL if ssid_ba is NULL */
-
- g_string_free(key_string, TRUE);
- if (ssid_ba != NULL)
- g_byte_array_free(ssid_ba, TRUE);
-
- g_free(type);
- g_free(key);
- if(ssid != NULL) g_free(ssid);
-
- /* Free the array of strings */
- g_strfreev(tokens);
- return dk;
+ /* Create a new string */
+ key_string = g_string_new(key);
+ ssid_ba = NULL;
+
+
+ /* Three (or more) tokens mean that the user entered a WPA-PWD key ... */
+ if( ((key_string->len) > WPA_KEY_MAX_CHAR_SIZE) || ((key_string->len) < WPA_KEY_MIN_CHAR_SIZE))
+ {
+ g_string_free(key_string, TRUE);
+
+ g_free(type);
+ g_free(key);
+ g_free(ssid);
+
+ /* Free the array of strings */
+ g_strfreev(tokens);
+ return NULL;
+ }
+
+ if(ssid != NULL) /* more than three tokens found, means that the user specified the ssid */
+ {
+ ssid_ba = g_byte_array_new();
+ if (! uri_str_to_bytes(ssid, ssid_ba)) {
+ g_string_free(key_string, TRUE);
+ g_byte_array_free(ssid_ba, TRUE);
+ g_free(type);
+ g_free(key);
+ g_free(ssid);
+ /* Free the array of strings */
+ g_strfreev(tokens);
+ return NULL;
+ }
+
+ if(ssid_ba->len > WPA_SSID_MAX_CHAR_SIZE)
+ {
+ g_string_free(key_string, TRUE);
+ g_byte_array_free(ssid_ba, TRUE);
+
+ g_free(type);
+ g_free(key);
+ g_free(ssid);
+
+ /* Free the array of strings */
+ g_strfreev(tokens);
+ return NULL;
+ }
+ }
+
+ /* Key was correct!!! Create the new decryption_key_t ... */
+ dk = (decryption_key_t*)g_malloc(sizeof(decryption_key_t));
+
+ dk->type = AIRPDCAP_KEY_TYPE_WPA_PWD;
+ dk->key = g_string_new(key);
+ dk->bits = 256; /* This is the length of the array pf bytes that will be generated using key+ssid ...*/
+ dk->ssid = byte_array_dup(ssid_ba); /* NULL if ssid_ba is NULL */
+
+ g_string_free(key_string, TRUE);
+ if (ssid_ba != NULL)
+ g_byte_array_free(ssid_ba, TRUE);
+
+ g_free(type);
+ g_free(key);
+ if(ssid != NULL) g_free(ssid);
+
+ /* Free the array of strings */
+ g_strfreev(tokens);
+ return dk;
}
/* Something was wrong ... free everything */
g_free(type);
g_free(key);
if(ssid != NULL)
- g_free(ssid); /* It is not always present */
+ g_free(ssid); /* It is not always present */
if (ssid_ba != NULL)
- g_byte_array_free(ssid_ba, TRUE);
+ g_byte_array_free(ssid_ba, TRUE);
/* Free the array of strings */
g_strfreev(tokens);
gchar*
get_key_string(decryption_key_t* dk)
{
- gchar* output_string = NULL;
-
- if(dk == NULL)
- return NULL;
-
- if(dk->type == AIRPDCAP_KEY_TYPE_WEP)
- {
- if(dk->key == NULL) /* Should NOT happen at all... */
- return NULL;
-
- output_string = g_strdup_printf("%s:%s",STRING_KEY_TYPE_WEP,dk->key->str);
- }
- else if(dk->type == AIRPDCAP_KEY_TYPE_WPA_PWD)
- {
- if(dk->key == NULL) /* Should NOT happen at all... */
- return NULL;
-
- if(dk->ssid == NULL)
- output_string = g_strdup_printf("%s:%s",STRING_KEY_TYPE_WPA_PWD,dk->key->str);
- else
- output_string = g_strdup_printf("%s:%s:%s",
- STRING_KEY_TYPE_WPA_PWD,dk->key->str,
- format_text((guchar *)dk->ssid->data, dk->ssid->len));
- }
- else if(dk->type == AIRPDCAP_KEY_TYPE_WPA_PMK)
- {
- if(dk->key == NULL) /* Should NOT happen at all... */
- return NULL;
-
- output_string = g_strdup_printf("%s:%s",STRING_KEY_TYPE_WPA_PSK,dk->key->str);
- }
- else
- {
- return NULL;
- }
-
- return output_string;
+ gchar* output_string = NULL;
+
+ if(dk == NULL)
+ return NULL;
+
+ if(dk->type == AIRPDCAP_KEY_TYPE_WEP)
+ {
+ if(dk->key == NULL) /* Should NOT happen at all... */
+ return NULL;
+
+ output_string = g_strdup_printf("%s:%s",STRING_KEY_TYPE_WEP,dk->key->str);
+ }
+ else if(dk->type == AIRPDCAP_KEY_TYPE_WPA_PWD)
+ {
+ if(dk->key == NULL) /* Should NOT happen at all... */
+ return NULL;
+
+ if(dk->ssid == NULL)
+ output_string = g_strdup_printf("%s:%s",STRING_KEY_TYPE_WPA_PWD,dk->key->str);
+ else
+ output_string = g_strdup_printf("%s:%s:%s",
+ STRING_KEY_TYPE_WPA_PWD,dk->key->str,
+ format_text((guchar *)dk->ssid->data, dk->ssid->len));
+ }
+ else if(dk->type == AIRPDCAP_KEY_TYPE_WPA_PMK)
+ {
+ if(dk->key == NULL) /* Should NOT happen at all... */
+ return NULL;
+
+ output_string = g_strdup_printf("%s:%s",STRING_KEY_TYPE_WPA_PSK,dk->key->str);
+ }
+ else
+ {
+ return NULL;
+ }
+
+ return output_string;
}
#ifdef __cplusplus
#endif
/****************************************************************************/
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * set-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */