|
@@ -771,70 +771,6 @@ BOOLEAN RTMPCheckWPAframe(
|
|
|
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];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
/*
|
|
|
========================================================================
|
|
|
|
|
@@ -906,733 +842,3 @@ VOID AES_GTK_KEY_UNWRAP(
|
|
|
|
|
|
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;
|
|
|
- }
|
|
|
-
|
|
|
- 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;
|
|
|
-
|
|
|
-}
|
|
|
-
|