📄 wpa.c
字号:
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 ParseKeyData( IN PRTMP_ADAPTER pAd, IN PUCHAR pKeyData, IN UCHAR KeyDataLen, IN UCHAR bPairewise){ PKDE_ENCAP pKDE = NULL; PUCHAR pMyKeyData = pKeyData; UCHAR KeyDataLength = KeyDataLen; UCHAR GTKLEN; UCHAR skip_offset; // Verify The RSN IE contained in Pairewise-Msg 3 and skip it if (bPairewise) { // Check RSN IE whether it is WPA2/WPA2PSK if (!CheckRSNIE(pAd, pKeyData, KeyDataLen, &skip_offset)) { DBGPRINT(RT_DEBUG_ERROR, ("ParseKeyData ==> WPA2/WPA2PSK RSN IE mismatched \n")); hex_dump("Get KEYDATA :", pKeyData, KeyDataLen); return FALSE; } else { // skip RSN IE pMyKeyData += skip_offset; KeyDataLength -= skip_offset; //DBGPRINT(RT_DEBUG_TRACE, ("ParseKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset)); } } DBGPRINT(RT_DEBUG_TRACE,("ParseKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength)); // Parse EKD format if (KeyDataLength >= 8) { pKDE = (PKDE_ENCAP) pMyKeyData; } else { DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KeyDataLength is too short \n")); return FALSE; } // Sanity check - shared key index should not be 0 if (pKDE->GTKEncap.Kid == 0) { DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index zero \n")); return FALSE; } // 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_TRACE, ("GTK Key with KDE formet got index=%d, len=%d \n", pKDE->GTKEncap.Kid, GTKLEN)); // Update GTK // set key material, TxMic and RxMic for WPAPSK NdisMoveMemory(pAd->StaCfg.GTK, pKDE->GTKEncap.GTK, 32); pAd->StaCfg.DefaultKeyId = pKDE->GTKEncap.Kid; // Update shared key table NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY)); pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TKIP_EK; NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, pKDE->GTKEncap.GTK, LEN_TKIP_EK); NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, &pKDE->GTKEncap.GTK[16], LEN_TKIP_RXMICK); NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, &pKDE->GTKEncap.GTK[24], LEN_TKIP_TXMICK); // Update Shared Key CipherAlg pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE; if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP; else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled) pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES; return TRUE; }/* ======================================================================== Routine Description: Cisco CCKM PRF function Arguments: key Cisco Base Transient Key (BTK) key_len The key length of the BTK data Ruquest Number(RN) + BSSID data_len The length of the data output Store for PTK(Pairwise transient keys) len The length of the output Return Value: None Note: 802.1i Annex F.9 ========================================================================*/VOID CCKMPRF( IN UCHAR *key, IN INT key_len, IN UCHAR *data, IN INT data_len, OUT UCHAR *output, IN INT len){ INT i; UCHAR input[1024]; INT currentindex = 0; INT total_len; NdisMoveMemory(input, data, data_len); total_len = data_len; input[total_len] = 0; total_len++; for (i = 0; i < (len + 19) / 20; i++) { HMAC_SHA1(input, total_len, key, key_len, &output[currentindex]); currentindex += 20; input[total_len - 1]++; } }/* ======================================================================== Routine Description: Process MIC error indication and record MIC error timer. Arguments: pAd Pointer to our adapter pWpaKey Pointer to the WPA key structure Return Value: None IRQL = DISPATCH_LEVEL Note: ========================================================================*/VOID RTMPReportMicError( IN PRTMP_ADAPTER pAd, IN PCIPHER_KEY pWpaKey){ ULONG Now; UCHAR unicastKey = (pWpaKey->Type == PAIRWISE_KEY ? 1:0); // Record Last MIC error time and count Now = jiffies; if (pAd->StaCfg.MicErrCnt == 0) { pAd->StaCfg.MicErrCnt++; pAd->StaCfg.LastMicErrorTime = Now; NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8); } else if (pAd->StaCfg.MicErrCnt == 1) { if ((pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ)) < Now) { // Update Last MIC error time, this did not violate two MIC errors within 60 seconds pAd->StaCfg.LastMicErrorTime = Now; } else { if (pAd->CommonCfg.bWirelessEvent) RTMPSendWirelessEvent(pAd, IW_COUNTER_MEASURES_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); pAd->StaCfg.LastMicErrorTime = Now; // Violate MIC error counts, MIC countermeasures kicks in pAd->StaCfg.MicErrCnt++; // We shall block all reception // We shall clean all Tx ring and disassoicate from AP after next EAPOL frame // // No necessary to clean all Tx ring, on RTMPHardTransmit will stop sending non-802.1X EAPOL packets // if pAd->StaCfg.MicErrCnt greater than 2. // // RTMPRingCleanUp(pAd, QID_AC_BK); // RTMPRingCleanUp(pAd, QID_AC_BE); // RTMPRingCleanUp(pAd, QID_AC_VI); // RTMPRingCleanUp(pAd, QID_AC_VO); // RTMPRingCleanUp(pAd, QID_HCCA); } } else { // MIC error count >= 2 // This should not happen ; } MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, OID_802_11_MIC_FAILURE_REPORT_FRAME, 1, &unicastKey); if (pAd->StaCfg.MicErrCnt == 2) { RTMPSetTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, 100); }}#ifdef WPA_SUPPLICANT_SUPPORT#define LENGTH_EAP_H 4// If the received frame is EAP-Packet ,find out its EAP-Code (Request(0x01), Response(0x02), Success(0x03), Failure(0x04)).INT WpaCheckEapCode( IN PRTMP_ADAPTER pAd, IN PUCHAR pFrame, IN USHORT FrameLen, IN USHORT OffSet){ PUCHAR pData; INT result = 0; if( FrameLen < OffSet + LENGTH_EAPOL_H + LENGTH_EAP_H ) return result; pData = pFrame + OffSet; // skip offset bytes if(*(pData+1) == EAPPacket) // 802.1x header - Packet Type { result = *(pData+4); // EAP header - Code } return result;}VOID WpaSendMicFailureToWpaSupplicant( IN PRTMP_ADAPTER pAd, IN BOOLEAN bUnicast){ union iwreq_data wrqu; char custom[IW_CUSTOM_MAX] = {0}; sprintf(custom, "MLME-MICHAELMICFAILURE.indication"); if (bUnicast) sprintf(custom, "%s unicast", custom); wrqu.data.length = strlen(custom); wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, custom); return;}#endif // WPA_SUPPLICANT_SUPPORT //VOID WpaMicFailureReportFrame( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem){ PUCHAR pOutBuffer = NULL; UCHAR Header802_3[14]; ULONG FrameLen = 0; EAPOL_PACKET Packet; UCHAR Mic[16]; BOOLEAN bUnicast; DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame ----->\n")); bUnicast = (Elem->Msg[0] == 1 ? TRUE:FALSE); pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER); // init 802.3 header and Fill Packet MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); NdisZeroMemory(&Packet, sizeof(Packet)); Packet.ProVer = EAPOL_VER; Packet.ProType = EAPOLKey; Packet.KeyDesc.Type = WPA1_KEY_DESC; // Request field presented Packet.KeyDesc.KeyInfo.Request = 1; if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) { Packet.KeyDesc.KeyInfo.KeyDescVer = 2; } else // TKIP { Packet.KeyDesc.KeyInfo.KeyDescVer = 1; } Packet.KeyDesc.KeyInfo.KeyType = (bUnicast ? PAIRWISEKEY : GROUPKEY); // KeyMic field presented Packet.KeyDesc.KeyInfo.KeyMic = 1; // Error field presented Packet.KeyDesc.KeyInfo.Error = 1; // Update packet length after decide Key data payload Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE; // Key Replay Count NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY); inc_byte_array(pAd->StaCfg.ReplayCounter, 8); // Convert to little-endian format. *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory if(pOutBuffer == NULL) { return; } // Prepare EAPOL frame for MIC calculation // Be careful, only EAPOL frame is counted for MIC calculation MakeOutgoingFrame(pOutBuffer, &FrameLen, Packet.Body_Len[1] + 4, &Packet, END_OF_ARGS); // Prepare and Fill MIC value NdisZeroMemory(Mic, sizeof(Mic)); if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) { // AES UCHAR digest[20] = {0}; HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); } else { // TKIP hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); } NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); MakeOutgoingFrame(pOutBuffer, &FrameLen, LENGTH_802_3, &Header802_3, Packet.Body_Len[1] + 4, &Packet, END_OF_ARGS); // opy frame to Tx ring and send MIC failure report frame to authenticator RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, FALSE); MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame <-----\n"));}/** from wpa_supplicant * inc_byte_array - Increment arbitrary length byte array by one * @counter: Pointer to byte array * @len: Length of the counter in bytes * * This function increments the last byte of the counter by one and continues * rolling over to more significant bytes if the byte was incremented from * 0xff to 0x00. */void inc_byte_array(UCHAR *counter, int len){ int pos = len - 1; while (pos >= 0) { counter[pos]++; if (counter[pos] != 0) break; pos--; }}VOID WpaDisassocApAndBlockAssoc( IN PVOID SystemSpecific1, IN PVOID FunctionContext, IN PVOID SystemSpecific2, IN PVOID SystemSpecific3) { RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)FunctionContext; MLME_DISASSOC_REQ_STRUCT DisassocReq; // disassoc from current AP first DBGPRINT(RT_DEBUG_TRACE, ("RTMPReportMicError - disassociate with current AP after sending second continuous EAPOL frame\n")); DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_MIC_FAILURE); MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; pAd->StaCfg.bBlockAssoc = TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -