diff options
Diffstat (limited to 'drivers/staging/rt3070/common/cmm_wpa.c')
-rw-r--r-- | drivers/staging/rt3070/common/cmm_wpa.c | 1607 |
1 files changed, 1 insertions, 1606 deletions
diff --git a/drivers/staging/rt3070/common/cmm_wpa.c b/drivers/staging/rt3070/common/cmm_wpa.c index 81c332ac252..6483d329286 100644 --- a/drivers/staging/rt3070/common/cmm_wpa.c +++ b/drivers/staging/rt3070/common/cmm_wpa.c @@ -1,1606 +1 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, Inc. - * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - * * - ************************************************************************* - - Module Name: - wpa.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Jan Lee 03-07-22 Initial - Paul Lin 03-11-28 Modify for supplicant -*/ -#include "../rt_config.h" -// WPA OUI -UCHAR OUI_WPA_NONE_AKM[4] = {0x00, 0x50, 0xF2, 0x00}; -UCHAR OUI_WPA_VERSION[4] = {0x00, 0x50, 0xF2, 0x01}; -UCHAR OUI_WPA_TKIP[4] = {0x00, 0x50, 0xF2, 0x02}; -UCHAR OUI_WPA_CCMP[4] = {0x00, 0x50, 0xF2, 0x04}; -UCHAR OUI_WPA_8021X_AKM[4] = {0x00, 0x50, 0xF2, 0x01}; -UCHAR OUI_WPA_PSK_AKM[4] = {0x00, 0x50, 0xF2, 0x02}; -// WPA2 OUI -UCHAR OUI_WPA2_WEP40[4] = {0x00, 0x0F, 0xAC, 0x01}; -UCHAR OUI_WPA2_TKIP[4] = {0x00, 0x0F, 0xAC, 0x02}; -UCHAR OUI_WPA2_CCMP[4] = {0x00, 0x0F, 0xAC, 0x04}; -UCHAR OUI_WPA2_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x01}; -UCHAR OUI_WPA2_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x02}; -// MSA OUI -UCHAR OUI_MSA_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x05}; // Not yet final - IEEE 802.11s-D1.06 -UCHAR OUI_MSA_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x06}; // Not yet final - IEEE 802.11s-D1.06 - -/* - ======================================================================== - - Routine Description: - The pseudo-random function(PRF) that hashes various inputs to - derive a pseudo-random value. To add liveness to the pseudo-random - value, a nonce should be one of the inputs. - - It is used to generate PTK, GTK or some specific random value. - - Arguments: - UCHAR *key, - the key material for HMAC_SHA1 use - INT key_len - the length of key - UCHAR *prefix - a prefix label - INT prefix_len - the length of the label - UCHAR *data - a specific data with variable length - INT data_len - the length of a specific data - INT len - the output lenght - - Return Value: - UCHAR *output - the calculated result - - Note: - 802.11i-2004 Annex H.3 - - ======================================================================== -*/ -VOID PRF( - IN UCHAR *key, - IN INT key_len, - IN UCHAR *prefix, - IN INT prefix_len, - IN UCHAR *data, - IN INT data_len, - OUT UCHAR *output, - IN INT len) -{ - INT i; - UCHAR *input; - INT currentindex = 0; - INT total_len; - - // Allocate memory for input - os_alloc_mem(NULL, (PUCHAR *)&input, 1024); - - if (input == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("!!!PRF: no memory!!!\n")); - return; - } - - // Generate concatenation input - NdisMoveMemory(input, prefix, prefix_len); - - // Concatenate a single octet containing 0 - input[prefix_len] = 0; - - // Concatenate specific data - NdisMoveMemory(&input[prefix_len + 1], data, data_len); - total_len = prefix_len + 1 + data_len; - - // Concatenate a single octet containing 0 - // This octet shall be update later - input[total_len] = 0; - total_len++; - - // Iterate to calculate the result by hmac-sha-1 - // Then concatenate to last result - for (i = 0; i < (len + 19) / 20; i++) - { - HMAC_SHA1(input, total_len, key, key_len, &output[currentindex]); - currentindex += 20; - - // update the last octet - input[total_len - 1]++; - } - os_free_mem(NULL, input); -} - -/* - ======================================================================== - - Routine Description: - It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK. - It shall be called by 4-way handshake processing. - - Arguments: - pAd - pointer to our pAdapter context - PMK - pointer to PMK - ANonce - pointer to ANonce - AA - pointer to Authenticator Address - SNonce - pointer to SNonce - SA - pointer to Supplicant Address - len - indicate the length of PTK (octet) - - Return Value: - Output pointer to the PTK - - Note: - Refer to IEEE 802.11i-2004 8.5.1.2 - - ======================================================================== -*/ -VOID WpaCountPTK( - IN PRTMP_ADAPTER pAd, - IN UCHAR *PMK, - IN UCHAR *ANonce, - IN UCHAR *AA, - IN UCHAR *SNonce, - IN UCHAR *SA, - OUT UCHAR *output, - IN UINT len) -{ - UCHAR concatenation[76]; - UINT CurrPos = 0; - UCHAR temp[32]; - UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ', - 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'}; - - // initiate the concatenation input - NdisZeroMemory(temp, sizeof(temp)); - NdisZeroMemory(concatenation, 76); - - // Get smaller address - if (RTMPCompareMemory(SA, AA, 6) == 1) - NdisMoveMemory(concatenation, AA, 6); - else - NdisMoveMemory(concatenation, SA, 6); - CurrPos += 6; - - // Get larger address - if (RTMPCompareMemory(SA, AA, 6) == 1) - NdisMoveMemory(&concatenation[CurrPos], SA, 6); - else - NdisMoveMemory(&concatenation[CurrPos], AA, 6); - - // store the larger mac address for backward compatible of - // ralink proprietary STA-key issue - NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN); - CurrPos += 6; - - // Get smaller Nonce - if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) - NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue - else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) - NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); - else - NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); - CurrPos += 32; - - // Get larger Nonce - if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) - NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue - else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) - NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); - else - NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); - CurrPos += 32; - - hex_dump("concatenation=", concatenation, 76); - - // Use PRF to generate PTK - PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len); - -} - -/* - ======================================================================== - - Routine Description: - Generate random number by software. - - Arguments: - pAd - pointer to our pAdapter context - macAddr - pointer to local MAC address - - Return Value: - - Note: - 802.1ii-2004 Annex H.5 - - ======================================================================== -*/ -VOID GenRandom( - IN PRTMP_ADAPTER pAd, - IN UCHAR *macAddr, - OUT UCHAR *random) -{ - INT i, curr; - UCHAR local[80], KeyCounter[32]; - UCHAR result[80]; - ULONG CurrentTime; - UCHAR prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'}; - - // Zero the related information - NdisZeroMemory(result, 80); - NdisZeroMemory(local, 80); - NdisZeroMemory(KeyCounter, 32); - - for (i = 0; i < 32; i++) - { - // copy the local MAC address - COPY_MAC_ADDR(local, macAddr); - curr = MAC_ADDR_LEN; - - // concatenate the current time - NdisGetSystemUpTime(&CurrentTime); - NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime)); - curr += sizeof(CurrentTime); - - // concatenate the last result - NdisMoveMemory(&local[curr], result, 32); - curr += 32; - - // concatenate a variable - NdisMoveMemory(&local[curr], &i, 2); - curr += 2; - - // calculate the result - PRF(KeyCounter, 32, prefix,12, local, curr, result, 32); - } - - NdisMoveMemory(random, result, 32); -} - -/* - ======================================================================== - - Routine Description: - Build cipher suite in RSN-IE. - It only shall be called by RTMPMakeRSNIE. - - Arguments: - pAd - pointer to our pAdapter context - ElementID - indicate the WPA1 or WPA2 - WepStatus - indicate the encryption type - bMixCipher - a boolean to indicate the pairwise cipher and group - cipher are the same or not - - Return Value: - - Note: - - ======================================================================== -*/ -static VOID RTMPInsertRsnIeCipher( - IN PRTMP_ADAPTER pAd, - IN UCHAR ElementID, - IN UINT WepStatus, - IN BOOLEAN bMixCipher, - IN UCHAR FlexibleCipher, - OUT PUCHAR pRsnIe, - OUT UCHAR *rsn_len) -{ - UCHAR PairwiseCnt; - - *rsn_len = 0; - - // decide WPA2 or WPA1 - if (ElementID == Wpa2Ie) - { - RSNIE2 *pRsnie_cipher = (RSNIE2*)pRsnIe; - - // Assign the verson as 1 - pRsnie_cipher->version = 1; - - switch (WepStatus) - { - // TKIP mode - case Ndis802_11Encryption2Enabled: - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); - pRsnie_cipher->ucount = 1; - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4); - *rsn_len = sizeof(RSNIE2); - break; - - // AES mode - case Ndis802_11Encryption3Enabled: - if (bMixCipher) - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); - else - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CCMP, 4); - pRsnie_cipher->ucount = 1; - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4); - *rsn_len = sizeof(RSNIE2); - break; - - // TKIP-AES mix mode - case Ndis802_11Encryption4Enabled: - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); - - PairwiseCnt = 1; - // Insert WPA2 TKIP as the first pairwise cipher - if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher)) - { - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4); - // Insert WPA2 AES as the secondary pairwise cipher - if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher)) - { - NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA2_CCMP, 4); - PairwiseCnt = 2; - } - } - else - { - // Insert WPA2 AES as the first pairwise cipher - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4); - } - - pRsnie_cipher->ucount = PairwiseCnt; - *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1)); - break; - } - - // swap for big-endian platform - pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); - pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); - } - else - { - RSNIE *pRsnie_cipher = (RSNIE*)pRsnIe; - - // Assign OUI and version - NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4); - pRsnie_cipher->version = 1; - - switch (WepStatus) - { - // TKIP mode - case Ndis802_11Encryption2Enabled: - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); - pRsnie_cipher->ucount = 1; - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4); - *rsn_len = sizeof(RSNIE); - break; - - // AES mode - case Ndis802_11Encryption3Enabled: - if (bMixCipher) - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); - else - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4); - pRsnie_cipher->ucount = 1; - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4); - *rsn_len = sizeof(RSNIE); - break; - - // TKIP-AES mix mode - case Ndis802_11Encryption4Enabled: - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); - - PairwiseCnt = 1; - // Insert WPA TKIP as the first pairwise cipher - if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher)) - { - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4); - // Insert WPA AES as the secondary pairwise cipher - if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher)) - { - NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA_CCMP, 4); - PairwiseCnt = 2; - } - } - else - { - // Insert WPA AES as the first pairwise cipher - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4); - } - - pRsnie_cipher->ucount = PairwiseCnt; - *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1)); - break; - } - - // swap for big-endian platform - pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); - pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); - } - -} - -/* - ======================================================================== - - Routine Description: - Build AKM suite in RSN-IE. - It only shall be called by RTMPMakeRSNIE. - - Arguments: - pAd - pointer to our pAdapter context - ElementID - indicate the WPA1 or WPA2 - AuthMode - indicate the authentication mode - apidx - indicate the interface index - - Return Value: - - Note: - - ======================================================================== -*/ -static VOID RTMPInsertRsnIeAKM( - IN PRTMP_ADAPTER pAd, - IN UCHAR ElementID, - IN UINT AuthMode, - IN UCHAR apidx, - OUT PUCHAR pRsnIe, - OUT UCHAR *rsn_len) -{ - RSNIE_AUTH *pRsnie_auth; - - pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len)); - - // decide WPA2 or WPA1 - if (ElementID == Wpa2Ie) - { - switch (AuthMode) - { - case Ndis802_11AuthModeWPA2: - case Ndis802_11AuthModeWPA1WPA2: - pRsnie_auth->acount = 1; - NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4); - break; - - case Ndis802_11AuthModeWPA2PSK: - case Ndis802_11AuthModeWPA1PSKWPA2PSK: - pRsnie_auth->acount = 1; - NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4); - break; - } - } - else - { - switch (AuthMode) - { - case Ndis802_11AuthModeWPA: - case Ndis802_11AuthModeWPA1WPA2: - pRsnie_auth->acount = 1; - NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_8021X_AKM, 4); - break; - - case Ndis802_11AuthModeWPAPSK: - case Ndis802_11AuthModeWPA1PSKWPA2PSK: - pRsnie_auth->acount = 1; - NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_PSK_AKM, 4); - break; - - case Ndis802_11AuthModeWPANone: - pRsnie_auth->acount = 1; - NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_NONE_AKM, 4); - break; - } - } - - pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount); - - (*rsn_len) += sizeof(RSNIE_AUTH); // update current RSNIE length - -} - -/* - ======================================================================== - - Routine Description: - Build capability in RSN-IE. - It only shall be called by RTMPMakeRSNIE. - - Arguments: - pAd - pointer to our pAdapter context - ElementID - indicate the WPA1 or WPA2 - apidx - indicate the interface index - - Return Value: - - Note: - - ======================================================================== -*/ -static VOID RTMPInsertRsnIeCap( - IN PRTMP_ADAPTER pAd, - IN UCHAR ElementID, - IN UCHAR apidx, - OUT PUCHAR pRsnIe, - OUT UCHAR *rsn_len) -{ - RSN_CAPABILITIES *pRSN_Cap; - - // it could be ignored in WPA1 mode - if (ElementID == WpaIe) - return; - - pRSN_Cap = (RSN_CAPABILITIES*)(pRsnIe + (*rsn_len)); - - - pRSN_Cap->word = cpu2le16(pRSN_Cap->word); - - (*rsn_len) += sizeof(RSN_CAPABILITIES); // update current RSNIE length - -} - - -/* - ======================================================================== - - Routine Description: - Build RSN IE context. It is not included element-ID and length. - - Arguments: - pAd - pointer to our pAdapter context - AuthMode - indicate the authentication mode - WepStatus - indicate the encryption type - apidx - indicate the interface index - - Return Value: - - Note: - - ======================================================================== -*/ -VOID RTMPMakeRSNIE( - IN PRTMP_ADAPTER pAd, - IN UINT AuthMode, - IN UINT WepStatus, - IN UCHAR apidx) -{ - PUCHAR pRsnIe = NULL; // primary RSNIE - UCHAR *rsnielen_cur_p = 0; // the length of the primary RSNIE - UCHAR *rsnielen_ex_cur_p = 0; // the length of the secondary RSNIE - UCHAR PrimaryRsnie; - BOOLEAN bMixCipher = FALSE; // indicate the pairwise and group cipher are different - UCHAR p_offset; - WPA_MIX_PAIR_CIPHER FlexibleCipher = MIX_CIPHER_NOTUSE; // it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode - - rsnielen_cur_p = NULL; - rsnielen_ex_cur_p = NULL; - - { -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { -#ifdef WPA_SUPPLICANT_SUPPORT - if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) - { - if (AuthMode < Ndis802_11AuthModeWPA) - return; - } - else -#endif // WPA_SUPPLICANT_SUPPORT // - { - // Support WPAPSK or WPA2PSK in STA-Infra mode - // Support WPANone in STA-Adhoc mode - if ((AuthMode != Ndis802_11AuthModeWPAPSK) && - (AuthMode != Ndis802_11AuthModeWPA2PSK) && - (AuthMode != Ndis802_11AuthModeWPANone) - ) - return; - } - - DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(STA)\n")); - - // Zero RSNIE context - pAd->StaCfg.RSNIE_Len = 0; - NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE); - - // Pointer to RSNIE - rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len; - pRsnIe = pAd->StaCfg.RSN_IE; - - bMixCipher = pAd->StaCfg.bMixCipher; - } -#endif // CONFIG_STA_SUPPORT // - } - - // indicate primary RSNIE as WPA or WPA2 - if ((AuthMode == Ndis802_11AuthModeWPA) || - (AuthMode == Ndis802_11AuthModeWPAPSK) || - (AuthMode == Ndis802_11AuthModeWPANone) || - (AuthMode == Ndis802_11AuthModeWPA1WPA2) || - (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) - PrimaryRsnie = WpaIe; - else - PrimaryRsnie = Wpa2Ie; - - { - // Build the primary RSNIE - // 1. insert cipher suite - RTMPInsertRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher, FlexibleCipher, pRsnIe, &p_offset); - - // 2. insert AKM - RTMPInsertRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, &p_offset); - - // 3. insert capability - RTMPInsertRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset); - } - - // 4. update the RSNIE length - *rsnielen_cur_p = p_offset; - - hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p)); - - -} - -/* - ========================================================================== - Description: - Check whether the received frame is EAP frame. - - Arguments: - pAd - pointer to our pAdapter context - pEntry - pointer to active entry - pData - the received frame - DataByteCount - the received frame's length - FromWhichBSSID - indicate the interface index - - Return: - TRUE - This frame is EAP frame - FALSE - otherwise - ========================================================================== -*/ -BOOLEAN RTMPCheckWPAframe( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN PUCHAR pData, - IN ULONG DataByteCount, - IN UCHAR FromWhichBSSID) -{ - ULONG Body_len; - BOOLEAN Cancelled; - - - if(DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H)) - return FALSE; - - - // Skip LLC header - if (NdisEqualMemory(SNAP_802_1H, pData, 6) || - // Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL - NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6)) - { - pData += 6; - } - // Skip 2-bytes EAPoL type - if (NdisEqualMemory(EAPOL, pData, 2)) - { - pData += 2; - } - else - return FALSE; - - switch (*(pData+1)) - { - case EAPPacket: - Body_len = (*(pData+2)<<8) | (*(pData+3)); - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len)); - break; - case EAPOLStart: - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n")); - if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE) - { - DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n")); - RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); - pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; - } - break; - case EAPOLLogoff: - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n")); - break; - case EAPOLKey: - Body_len = (*(pData+2)<<8) | (*(pData+3)); - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len)); - break; - case EAPOLASFAlert: - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n")); - break; - default: - return FALSE; - - } - return TRUE; -} - - -/* - ========================================================================== - Description: - ENCRYPT AES GTK before sending in EAPOL frame. - AES GTK length = 128 bit, so fix blocks for aes-key-wrap as 2 in this function. - This function references to RFC 3394 for aes key wrap algorithm. - Return: - ========================================================================== -*/ -VOID AES_GTK_KEY_WRAP( - IN UCHAR *key, - IN UCHAR *plaintext, - IN UCHAR p_len, - OUT UCHAR *ciphertext) -{ - UCHAR A[8], BIN[16], BOUT[16]; - UCHAR R[512]; - INT num_blocks = p_len/8; // unit:64bits - INT i, j; - aes_context aesctx; - UCHAR xor; - - rtmp_aes_set_key(&aesctx, key, 128); - - // Init IA - for (i = 0; i < 8; i++) - A[i] = 0xa6; - - //Input plaintext - for (i = 0; i < num_blocks; i++) - { - for (j = 0 ; j < 8; j++) - R[8 * (i + 1) + j] = plaintext[8 * i + j]; - } - - // Key Mix - for (j = 0; j < 6; j++) - { - for(i = 1; i <= num_blocks; i++) - { - //phase 1 - NdisMoveMemory(BIN, A, 8); - NdisMoveMemory(&BIN[8], &R[8 * i], 8); - rtmp_aes_encrypt(&aesctx, BIN, BOUT); - - NdisMoveMemory(A, &BOUT[0], 8); - xor = num_blocks * j + i; - A[7] = BOUT[7] ^ xor; - NdisMoveMemory(&R[8 * i], &BOUT[8], 8); - } - } - - // Output ciphertext - NdisMoveMemory(ciphertext, A, 8); - - for (i = 1; i <= num_blocks; i++) - { - for (j = 0 ; j < 8; j++) - ciphertext[8 * i + j] = R[8 * i + j]; - } -} - - -/* - ======================================================================== - - Routine Description: - Misc function to decrypt AES body - - Arguments: - - Return Value: - - Note: - This function references to RFC 3394 for aes key unwrap algorithm. - - ======================================================================== -*/ -VOID AES_GTK_KEY_UNWRAP( - IN UCHAR *key, - OUT UCHAR *plaintext, - IN UCHAR c_len, - IN UCHAR *ciphertext) - -{ - UCHAR A[8], BIN[16], BOUT[16]; - UCHAR xor; - INT i, j; - aes_context aesctx; - UCHAR *R; - INT num_blocks = c_len/8; // unit:64bits - - - os_alloc_mem(NULL, (PUCHAR *)&R, 512); - - if (R == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("!!!AES_GTK_KEY_UNWRAP: no memory!!!\n")); - return; - } /* End of if */ - - // Initialize - NdisMoveMemory(A, ciphertext, 8); - //Input plaintext - for(i = 0; i < (c_len-8); i++) - { - R[ i] = ciphertext[i + 8]; - } - - rtmp_aes_set_key(&aesctx, key, 128); - - for(j = 5; j >= 0; j--) - { - for(i = (num_blocks-1); i > 0; i--) - { - xor = (num_blocks -1 )* j + i; - NdisMoveMemory(BIN, A, 8); - BIN[7] = A[7] ^ xor; - NdisMoveMemory(&BIN[8], &R[(i-1)*8], 8); - rtmp_aes_decrypt(&aesctx, BIN, BOUT); - NdisMoveMemory(A, &BOUT[0], 8); - NdisMoveMemory(&R[(i-1)*8], &BOUT[8], 8); - } - } - - // OUTPUT - for(i = 0; i < c_len; i++) - { - plaintext[i] = R[i]; - } - - - os_free_mem(NULL, R); -} - -/* - ========================================================================== - Description: - Report the EAP message type - - Arguments: - msg - EAPOL_PAIR_MSG_1 - EAPOL_PAIR_MSG_2 - EAPOL_PAIR_MSG_3 - EAPOL_PAIR_MSG_4 - EAPOL_GROUP_MSG_1 - EAPOL_GROUP_MSG_2 - - Return: - message type string - - ========================================================================== -*/ -CHAR *GetEapolMsgType(CHAR msg) -{ - if(msg == EAPOL_PAIR_MSG_1) - return "Pairwise Message 1"; - else if(msg == EAPOL_PAIR_MSG_2) - return "Pairwise Message 2"; - else if(msg == EAPOL_PAIR_MSG_3) - return "Pairwise Message 3"; - else if(msg == EAPOL_PAIR_MSG_4) - return "Pairwise Message 4"; - else if(msg == EAPOL_GROUP_MSG_1) - return "Group Message 1"; - else if(msg == EAPOL_GROUP_MSG_2) - return "Group Message 2"; - else - return "Invalid Message"; -} - - -/* - ======================================================================== - - Routine Description: - Check Sanity RSN IE of EAPoL message - - Arguments: - - Return Value: - - - ======================================================================== -*/ -BOOLEAN RTMPCheckRSNIE( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN UCHAR DataLen, - IN MAC_TABLE_ENTRY *pEntry, - OUT UCHAR *Offset) -{ - PUCHAR pVIE; - UCHAR len; - PEID_STRUCT pEid; - BOOLEAN result = FALSE; - - pVIE = pData; - len = DataLen; - *Offset = 0; - - while (len > sizeof(RSNIE2)) - { - pEid = (PEID_STRUCT) pVIE; - // WPA RSN IE - if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))) - { - if ((pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) && - (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) && - (pEntry->RSNIE_Len == (pEid->Len + 2))) - { - result = TRUE; - } - - *Offset += (pEid->Len + 2); - } - // WPA2 RSN IE - else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))) - { - if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2 || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) && - (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) && - (pEntry->RSNIE_Len == (pEid->Len + 2))/* ToDo-AlbertY for mesh*/) - { - result = TRUE; - } - - *Offset += (pEid->Len + 2); - } - else - { - break; - } - - pVIE += (pEid->Len + 2); - len -= (pEid->Len + 2); - } - - - return result; - -} - - -/* - ======================================================================== - - Routine Description: - Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK. - GTK is encaptulated in KDE format at p.83 802.11i D10 - - Arguments: - - Return Value: - - Note: - 802.11i D10 - - ======================================================================== -*/ -BOOLEAN RTMPParseEapolKeyData( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pKeyData, - IN UCHAR KeyDataLen, - IN UCHAR GroupKeyIndex, - IN UCHAR MsgType, - IN BOOLEAN bWPA2, - IN MAC_TABLE_ENTRY *pEntry) -{ - PKDE_ENCAP pKDE = NULL; - PUCHAR pMyKeyData = pKeyData; - UCHAR KeyDataLength = KeyDataLen; - UCHAR GTKLEN = 0; - UCHAR DefaultIdx = 0; - UCHAR skip_offset; - - // Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it - if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3) - { - // Check RSN IE whether it is WPA2/WPA2PSK - if (!RTMPCheckRSNIE(pAd, pKeyData, KeyDataLen, pEntry, &skip_offset)) - { - // send wireless event - for RSN IE different - if (pAd->CommonCfg.bWirelessEvent) - RTMPSendWirelessEvent(pAd, IW_RSNIE_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); - - DBGPRINT(RT_DEBUG_ERROR, ("RSN_IE Different in msg %d of 4-way handshake!\n", MsgType)); - hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen); - hex_dump("Desired RSN_IE ", pEntry->RSN_IE, pEntry->RSNIE_Len); - - return FALSE; - } - else - { - if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3) - { - // skip RSN IE - pMyKeyData += skip_offset; - KeyDataLength -= skip_offset; - DBGPRINT(RT_DEBUG_TRACE, ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset)); - } - else - return TRUE; - } - } - - DBGPRINT(RT_DEBUG_TRACE,("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength)); - - // Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2 - if (bWPA2 && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1)) - { - if (KeyDataLength >= 8) // KDE format exclude GTK length - { - pKDE = (PKDE_ENCAP) pMyKeyData; - - - DefaultIdx = pKDE->GTKEncap.Kid; - - // Sanity check - KED length - if (KeyDataLength < (pKDE->Len + 2)) - { - DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n")); - return FALSE; - } - - // Get GTK length - refer to IEEE 802.11i-2004 p.82 - GTKLEN = pKDE->Len -6; - if (GTKLEN < LEN_AES_KEY) - { - DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN)); - return FALSE; - } - - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KDE format length is too short \n")); - return FALSE; - } - - DBGPRINT(RT_DEBUG_TRACE, ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx, GTKLEN)); - // skip it - pMyKeyData += 8; - KeyDataLength -= 8; - - } - else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1) - { - DefaultIdx = GroupKeyIndex; - DBGPRINT(RT_DEBUG_TRACE, ("GTK DefaultKeyID=%d \n", DefaultIdx)); - } - - // Sanity check - shared key index must be 1 ~ 3 - if (DefaultIdx < 1 || DefaultIdx > 3) - { - DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index(%d) is invalid in %s %s \n", DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType))); - return FALSE; - } - - -#ifdef CONFIG_STA_SUPPORT - // Todo -#endif // CONFIG_STA_SUPPORT // - - return TRUE; - -} - - -/* - ======================================================================== - - Routine Description: - Construct EAPoL message for WPA handshaking - Its format is below, - - +--------------------+ - | Protocol Version | 1 octet - +--------------------+ - | Protocol Type | 1 octet - +--------------------+ - | Body Length | 2 octets - +--------------------+ - | Descriptor Type | 1 octet - +--------------------+ - | Key Information | 2 octets - +--------------------+ - | Key Length | 1 octet - +--------------------+ - | Key Repaly Counter | 8 octets - +--------------------+ - | Key Nonce | 32 octets - +--------------------+ - | Key IV | 16 octets - +--------------------+ - | Key RSC | 8 octets - +--------------------+ - | Key ID or Reserved | 8 octets - +--------------------+ - | Key MIC | 16 octets - +--------------------+ - | Key Data Length | 2 octets - +--------------------+ - | Key Data | n octets - +--------------------+ - - - Arguments: - pAd Pointer to our adapter - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID ConstructEapolMsg( - IN PRTMP_ADAPTER pAd, - IN UCHAR AuthMode, - IN UCHAR WepStatus, - IN UCHAR GroupKeyWepStatus, - IN UCHAR MsgType, - IN UCHAR DefaultKeyIdx, - IN UCHAR *ReplayCounter, - IN UCHAR *KeyNonce, - IN UCHAR *TxRSC, - IN UCHAR *PTK, - IN UCHAR *GTK, - IN UCHAR *RSNIE, - IN UCHAR RSNIE_Len, - OUT PEAPOL_PACKET pMsg) -{ - BOOLEAN bWPA2 = FALSE; - - // Choose WPA2 or not - if ((AuthMode == Ndis802_11AuthModeWPA2) || (AuthMode == Ndis802_11AuthModeWPA2PSK)) - bWPA2 = TRUE; - - // Init Packet and Fill header - pMsg->ProVer = EAPOL_VER; - pMsg->ProType = EAPOLKey; - - // Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field - pMsg->Body_Len[1] = LEN_EAPOL_KEY_MSG; - - // Fill in EAPoL descriptor - if (bWPA2) - pMsg->KeyDesc.Type = WPA2_KEY_DESC; - else - pMsg->KeyDesc.Type = WPA1_KEY_DESC; - - // Fill in Key information, refer to IEEE Std 802.11i-2004 page 78 - // When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used. - pMsg->KeyDesc.KeyInfo.KeyDescVer = - (((WepStatus == Ndis802_11Encryption3Enabled) || (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP)); - - // Specify Key Type as Group(0) or Pairwise(1) - if (MsgType >= EAPOL_GROUP_MSG_1) - pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY; - else - pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; - - // Specify Key Index, only group_msg1_WPA1 - if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)) - pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx; - - if (MsgType == EAPOL_PAIR_MSG_3) - pMsg->KeyDesc.KeyInfo.Install = 1; - - if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)) - pMsg->KeyDesc.KeyInfo.KeyAck = 1; - - if (MsgType != EAPOL_PAIR_MSG_1) - pMsg->KeyDesc.KeyInfo.KeyMic = 1; - - if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) || (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))) - { - pMsg->KeyDesc.KeyInfo.Secure = 1; - } - - if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))) - { - pMsg->KeyDesc.KeyInfo.EKD_DL = 1; - } - - // key Information element has done. - *(USHORT *)(&pMsg->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pMsg->KeyDesc.KeyInfo)); - - // Fill in Key Length - { - if (MsgType >= EAPOL_GROUP_MSG_1) - { - // the length of group key cipher - pMsg->KeyDesc.KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH : LEN_AES_KEY); - } - else - { - // the length of pairwise key cipher - pMsg->KeyDesc.KeyLength[1] = ((WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : LEN_AES_KEY); - } - } - - // Fill in replay counter - NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, ReplayCounter, LEN_KEY_DESC_REPLAY); - - // Fill Key Nonce field - // ANonce : pairwise_msg1 & pairwise_msg3 - // SNonce : pairwise_msg2 - // GNonce : group_msg1_wpa1 - if ((MsgType <= EAPOL_PAIR_MSG_3) || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)))) - NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, LEN_KEY_DESC_NONCE); - - // Fill key IV - WPA2 as 0, WPA1 as random - if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) - { - // Suggest IV be random number plus some number, - NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], LEN_KEY_DESC_IV); - pMsg->KeyDesc.KeyIv[15] += 2; - } - - // Fill Key RSC field - // It contains the RSC for the GTK being installed. - if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1)) - { - NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6); - } - - // Clear Key MIC field for MIC calculation later - NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); - - ConstructEapolKeyData(pAd, - AuthMode, - WepStatus, - GroupKeyWepStatus, - MsgType, - DefaultKeyIdx, - bWPA2, - PTK, - GTK, - RSNIE, - RSNIE_Len, - pMsg); - - // Calculate MIC and fill in KeyMic Field except Pairwise Msg 1. - if (MsgType != EAPOL_PAIR_MSG_1) - { - CalculateMIC(pAd, WepStatus, PTK, pMsg); - } - - DBGPRINT(RT_DEBUG_TRACE, ("===> ConstructEapolMsg for %s %s\n", ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType))); - DBGPRINT(RT_DEBUG_TRACE, (" Body length = %d \n", pMsg->Body_Len[1])); - DBGPRINT(RT_DEBUG_TRACE, (" Key length = %d \n", pMsg->KeyDesc.KeyLength[1])); - - -} - -/* - ======================================================================== - - Routine Description: - Construct the Key Data field of EAPoL message - - Arguments: - pAd Pointer to our adapter - Elem Message body - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID ConstructEapolKeyData( - IN PRTMP_ADAPTER pAd, - IN UCHAR AuthMode, - IN UCHAR WepStatus, - IN UCHAR GroupKeyWepStatus, - IN UCHAR MsgType, - IN UCHAR DefaultKeyIdx, - IN BOOLEAN bWPA2Capable, - IN UCHAR *PTK, - IN UCHAR *GTK, - IN UCHAR *RSNIE, - IN UCHAR RSNIE_LEN, - OUT PEAPOL_PACKET pMsg) -{ - UCHAR *mpool, *Key_Data, *Rc4GTK; - UCHAR ekey[(LEN_KEY_DESC_IV+LEN_EAP_EK)]; - UCHAR data_offset; - - - if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2) - return; - - // allocate memory pool - os_alloc_mem(pAd, (PUCHAR *)&mpool, 1500); - - if (mpool == NULL) - return; - - /* Rc4GTK Len = 512 */ - Rc4GTK = (UCHAR *) ROUND_UP(mpool, 4); - /* Key_Data Len = 512 */ - Key_Data = (UCHAR *) ROUND_UP(Rc4GTK + 512, 4); - - NdisZeroMemory(Key_Data, 512); - pMsg->KeyDesc.KeyDataLen[1] = 0; - data_offset = 0; - - // Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3 - if (RSNIE_LEN && ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3))) - { - if (bWPA2Capable) - Key_Data[data_offset + 0] = IE_WPA2; - else - Key_Data[data_offset + 0] = IE_WPA; - - Key_Data[data_offset + 1] = RSNIE_LEN; - NdisMoveMemory(&Key_Data[data_offset + 2], RSNIE, RSNIE_LEN); - data_offset += (2 + RSNIE_LEN); - } - - // Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2 - if (bWPA2Capable && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))) - { - // Key Data Encapsulation (KDE) format - 802.11i-2004 Figure-43w and Table-20h - Key_Data[data_offset + 0] = 0xDD; - - if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) - { - Key_Data[data_offset + 1] = 0x16;// 4+2+16(OUI+DataType+DataField) - } - else - { - Key_Data[data_offset + 1] = 0x26;// 4+2+32(OUI+DataType+DataField) - } - - Key_Data[data_offset + 2] = 0x00; - Key_Data[data_offset + 3] = 0x0F; - Key_Data[data_offset + 4] = 0xAC; - Key_Data[data_offset + 5] = 0x01; - - // GTK KDE format - 802.11i-2004 Figure-43x - Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03); - Key_Data[data_offset + 7] = 0x00; // Reserved Byte - - data_offset += 8; - } - - - // Encapsulate GTK and encrypt the key-data field with KEK. - // Only for pairwise_msg3_WPA2 and group_msg1 - if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) || (MsgType == EAPOL_GROUP_MSG_1)) - { - // Fill in GTK - if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) - { - NdisMoveMemory(&Key_Data[data_offset], GTK, LEN_AES_KEY); - data_offset += LEN_AES_KEY; - } - else - { - NdisMoveMemory(&Key_Data[data_offset], GTK, TKIP_GTK_LENGTH); - data_offset += TKIP_GTK_LENGTH; - } - - // Still dont know why, but if not append will occur "GTK not include in MSG3" - // Patch for compatibility between zero config and funk - if (MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) - { - if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) - { - Key_Data[data_offset + 0] = 0xDD; - Key_Data[data_offset + 1] = 0; - data_offset += 2; - } - else - { - Key_Data[data_offset + 0] = 0xDD; - Key_Data[data_offset + 1] = 0; - Key_Data[data_offset + 2] = 0; - Key_Data[data_offset + 3] = 0; - Key_Data[data_offset + 4] = 0; - Key_Data[data_offset + 5] = 0; - data_offset += 6; - } - } - - // Encrypt the data material in key data field - if (WepStatus == Ndis802_11Encryption3Enabled) - { - AES_GTK_KEY_WRAP(&PTK[16], Key_Data, data_offset, Rc4GTK); - // AES wrap function will grow 8 bytes in length - data_offset += 8; - } - else - { - // PREPARE Encrypted "Key DATA" field. (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV) - // put TxTsc in Key RSC field - pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; //Init crc32. - - // ekey is the contanetion of IV-field, and PTK[16]->PTK[31] - NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv, LEN_KEY_DESC_IV); - NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &PTK[16], LEN_EAP_EK); - ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey)); //INIT SBOX, KEYLEN+3(IV) - pAd->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, Key_Data, data_offset); - WPAARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, Rc4GTK, Key_Data, data_offset); - } - - NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset); - } - else - { - NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset); - } - - // set key data length field and total length - pMsg->KeyDesc.KeyDataLen[1] = data_offset; - pMsg->Body_Len[1] += data_offset; - - os_free_mem(pAd, mpool); - -} - -/* - ======================================================================== - - Routine Description: - Calcaulate MIC. It is used during 4-ways handsharking. - - Arguments: - pAd - pointer to our pAdapter context - PeerWepStatus - indicate the encryption type - - Return Value: - - Note: - - ======================================================================== -*/ -VOID CalculateMIC( - IN PRTMP_ADAPTER pAd, - IN UCHAR PeerWepStatus, - IN UCHAR *PTK, - OUT PEAPOL_PACKET pMsg) -{ - UCHAR *OutBuffer; - ULONG FrameLen = 0; - UCHAR mic[LEN_KEY_DESC_MIC]; - UCHAR digest[80]; - - // allocate memory for MIC calculation - os_alloc_mem(pAd, (PUCHAR *)&OutBuffer, 512); - - if (OutBuffer == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("!!!CalculateMIC: no memory!!!\n")); - return; - } - - // make a frame for calculating MIC. - MakeOutgoingFrame(OutBuffer, &FrameLen, - pMsg->Body_Len[1] + 4, pMsg, - END_OF_ARGS); - - NdisZeroMemory(mic, sizeof(mic)); - - // Calculate MIC - if (PeerWepStatus == Ndis802_11Encryption3Enabled) - { - HMAC_SHA1(OutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest); - NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC); - } - else - { - hmac_md5(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, mic); - } - - // store the calculated MIC - NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC); - - os_free_mem(pAd, OutBuffer); -} - -/* - ======================================================================== - - Routine Description: - Some received frames can't decrypt by Asic, so decrypt them by software. - - Arguments: - pAd - pointer to our pAdapter context - PeerWepStatus - indicate the encryption type - - Return Value: - NDIS_STATUS_SUCCESS - decryption successful - NDIS_STATUS_FAILURE - decryption failure - - ======================================================================== -*/ -NDIS_STATUS RTMPSoftDecryptBroadCastData( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN NDIS_802_11_ENCRYPTION_STATUS GroupCipher, - IN PCIPHER_KEY pShard_key) -{ - PRXWI_STRUC pRxWI = pRxBlk->pRxWI; - - - - // handle WEP decryption - if (GroupCipher == Ndis802_11Encryption1Enabled) - { - if (RTMPSoftDecryptWEP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, pShard_key)) - { - - //Minus IV[4] & ICV[4] - pRxWI->MPDUtotalByteCount -= 8; - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("ERROR : Software decrypt WEP data fails.\n")); - // give up this frame - return NDIS_STATUS_FAILURE; - } - } - // handle TKIP decryption - else if (GroupCipher == Ndis802_11Encryption2Enabled) - { - if (RTMPSoftDecryptTKIP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0, pShard_key)) - { - - //Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV - pRxWI->MPDUtotalByteCount -= 20; - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptTKIP Failed\n")); - // give up this frame - return NDIS_STATUS_FAILURE; - } - } - // handle AES decryption - else if (GroupCipher == Ndis802_11Encryption3Enabled) - { - if (RTMPSoftDecryptAES(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount , pShard_key)) - { - - //8 bytes MIC, 8 bytes IV/EIV (CCMP Header) - pRxWI->MPDUtotalByteCount -= 16; - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptAES Failed\n")); - // give up this frame - return NDIS_STATUS_FAILURE; - } - } - else - { - // give up this frame - return NDIS_STATUS_FAILURE; - } - - return NDIS_STATUS_SUCCESS; - -} - +#include "../../rt2870/common/cmm_wpa.c" |