/* ======================================================================== 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); } }
/* ========================================================================== Description: Check sanity of unicast cipher selector in RSN IE. Return: true if match false otherwise ========================================================================== */ bool RTMPCheckUcast( IN struct rtmp_adapter * pAd, IN PEID_STRUCT eid_ptr, IN MAC_TABLE_ENTRY *pEntry) { u8 * pStaTmp; unsigned short Count; u8 apidx; struct rtmp_wifi_dev *wdev; ASSERT(pEntry); ASSERT(pEntry->apidx < pAd->ApCfg.BssidNum); apidx = pEntry->apidx; wdev = &pAd->ApCfg.MBSSID[apidx].wdev; pEntry->WepStatus = wdev->WepStatus; if (eid_ptr->Len < 16) { DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]RTMPCheckUcast : the length is too short(%d) \n", eid_ptr->Len)); return false; } /* Store STA RSN_IE capability */ pStaTmp = (u8 *)&eid_ptr->Octet[0]; if(eid_ptr->Eid == IE_WPA2) { /* skip Version(2),Multicast cipter(4) 2+4==6 */ /* point to number of unicast */ pStaTmp +=6; } else if (eid_ptr->Eid == IE_WPA) { /* skip OUI(4),Vesrion(2),Multicast cipher(4) 4+2+4==10 */ /* point to number of unicast */ pStaTmp += 10; } else { DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]RTMPCheckUcast : invalid IE=%d\n", eid_ptr->Eid)); return false; } /* Store unicast cipher count */ memmove(&Count, pStaTmp, sizeof(unsigned short)); Count = cpu2le16(Count); /* pointer to unicast cipher */ pStaTmp += sizeof(unsigned short); if (eid_ptr->Len >= 16) { if (eid_ptr->Eid == IE_WPA) { if (wdev->WepStatus == Ndis802_11TKIPAESMix) {/* multiple cipher (TKIP/CCMP) */ while (Count > 0) { /* TKIP */ if (MIX_CIPHER_WPA_TKIP_ON(wdev->WpaMixPairCipher)) { /* Compare if peer STA uses the TKIP as its unicast cipher */ if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][12], 4)) { pEntry->WepStatus = Ndis802_11TKIPEnable; return true; } /* Our AP uses the AES as the secondary cipher */ /* Compare if the peer STA use AES as its unicast cipher */ if (MIX_CIPHER_WPA_AES_ON(wdev->WpaMixPairCipher)) { if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][16], 4)) { pEntry->WepStatus = Ndis802_11AESEnable; return true; } } } else { /* AES */ if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][12], 4)) { pEntry->WepStatus = Ndis802_11AESEnable; return true; } } pStaTmp += 4; Count--; } } else {/* single cipher */ while (Count > 0) { if (RTMPEqualMemory(pStaTmp , &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][12], 4)) return true; pStaTmp += 4; Count--; } } } else if (eid_ptr->Eid == IE_WPA2) { u8 IE_Idx = 0; /* When WPA1/WPA2 mix mode, the RSN_IE is stored in different structure */ if ((wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) IE_Idx = 1; if (wdev->WepStatus == Ndis802_11TKIPAESMix) {/* multiple cipher (TKIP/CCMP) */ while (Count > 0) { /* WPA2 TKIP */ if (MIX_CIPHER_WPA2_TKIP_ON(wdev->WpaMixPairCipher)) { /* Compare if peer STA uses the TKIP as its unicast cipher */ if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][8], 4)) { pEntry->WepStatus = Ndis802_11TKIPEnable; return true; } /* Our AP uses the AES as the secondary cipher */ /* Compare if the peer STA use AES as its unicast cipher */ if (MIX_CIPHER_WPA2_AES_ON(wdev->WpaMixPairCipher)) { if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][12], 4)) { pEntry->WepStatus = Ndis802_11AESEnable; return true; } } } else { /* AES */ if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][8], 4)) { pEntry->WepStatus = Ndis802_11AESEnable; return true; } } pStaTmp += 4; Count--; } } else {/* single cipher */ while (Count > 0) { if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][8], 4)) return true; pStaTmp += 4; Count--; } } } } return false; }
/* ========================================================================== Description: Check sanity of unicast cipher selector in RSN IE. Return: TRUE if match FALSE otherwise ========================================================================== */ BOOLEAN RTMPCheckUcast( IN PRTMP_ADAPTER pAd, IN PEID_STRUCT eid_ptr, IN MAC_TABLE_ENTRY *pEntry) { PUCHAR pStaTmp; USHORT Count; UCHAR apidx; ASSERT(pEntry); ASSERT(pEntry->apidx < pAd->ApCfg.BssidNum); apidx = pEntry->apidx; pEntry->WepStatus = pAd->ApCfg.MBSSID[apidx].WepStatus; if (eid_ptr->Len < 16) { DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]RTMPCheckUcast : the length is too short(%d) \n", eid_ptr->Len)); return FALSE; } /* Store STA RSN_IE capability */ pStaTmp = (PUCHAR)&eid_ptr->Octet[0]; if(eid_ptr->Eid == IE_WPA2) { /* skip Version(2),Multicast cipter(4) 2+4==6 */ /* point to number of unicast */ pStaTmp +=6; } else if (eid_ptr->Eid == IE_WPA) { /* skip OUI(4),Vesrion(2),Multicast cipher(4) 4+2+4==10 */ /* point to number of unicast */ pStaTmp += 10; } else { DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]RTMPCheckUcast : invalid IE=%d\n", eid_ptr->Eid)); return FALSE; } /* Store unicast cipher count */ NdisMoveMemory(&Count, pStaTmp, sizeof(USHORT)); Count = cpu2le16(Count); /* pointer to unicast cipher */ pStaTmp += sizeof(USHORT); if (eid_ptr->Len >= 16) { if (eid_ptr->Eid == IE_WPA) { if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption4Enabled) {/* multiple cipher (TKIP/CCMP) */ while (Count > 0) { /* TKIP */ if (MIX_CIPHER_WPA_TKIP_ON(pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher)) { /* Compare if peer STA uses the TKIP as its unicast cipher */ if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][12], 4)) { pEntry->WepStatus = Ndis802_11Encryption2Enabled; return TRUE; } /* Our AP uses the AES as the secondary cipher */ /* Compare if the peer STA use AES as its unicast cipher */ if (MIX_CIPHER_WPA_AES_ON(pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher)) { if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][16], 4)) { pEntry->WepStatus = Ndis802_11Encryption3Enabled; return TRUE; } } } else { /* AES */ if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][12], 4)) { pEntry->WepStatus = Ndis802_11Encryption3Enabled; return TRUE; } } pStaTmp += 4; Count--; } } else {/* single cipher */ while (Count > 0) { if (RTMPEqualMemory(pStaTmp , &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][12], 4)) return TRUE; pStaTmp += 4; Count--; } } } else if (eid_ptr->Eid == IE_WPA2) { UCHAR IE_Idx = 0; /* When WPA1/WPA2 mix mode, the RSN_IE is stored in different structure */ if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1WPA2) || (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) IE_Idx = 1; if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption4Enabled) {/* multiple cipher (TKIP/CCMP) */ while (Count > 0) { /* WPA2 TKIP */ if (MIX_CIPHER_WPA2_TKIP_ON(pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher)) { /* Compare if peer STA uses the TKIP as its unicast cipher */ if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][8], 4)) { pEntry->WepStatus = Ndis802_11Encryption2Enabled; return TRUE; } /* Our AP uses the AES as the secondary cipher */ /* Compare if the peer STA use AES as its unicast cipher */ if (MIX_CIPHER_WPA2_AES_ON(pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher)) { if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][12], 4)) { pEntry->WepStatus = Ndis802_11Encryption3Enabled; return TRUE; } } } else { /* AES */ if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][8], 4)) { pEntry->WepStatus = Ndis802_11Encryption3Enabled; return TRUE; } } pStaTmp += 4; Count--; } } else {/* single cipher */ while (Count > 0) { if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][8], 4)) return TRUE; pStaTmp += 4; Count--; } } } } return FALSE; }