📄 wpa.c
字号:
/* ************************************************************************* * 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"#define WPARSNIE 0xdd#define WPA2RSNIE 0x30//extern UCHAR BIT8[];UCHAR CipherWpaPskTkip[] = { 0xDD, 0x16, // RSN IE 0x00, 0x50, 0xf2, 0x01, // oui 0x01, 0x00, // Version 0x00, 0x50, 0xf2, 0x02, // Multicast 0x01, 0x00, // Number of unicast 0x00, 0x50, 0xf2, 0x02, // unicast 0x01, 0x00, // number of authentication method 0x00, 0x50, 0xf2, 0x02 // authentication };UCHAR CipherWpaPskTkipLen = (sizeof(CipherWpaPskTkip) / sizeof(UCHAR));UCHAR CipherWpaPskAes[] = { 0xDD, 0x16, // RSN IE 0x00, 0x50, 0xf2, 0x01, // oui 0x01, 0x00, // Version 0x00, 0x50, 0xf2, 0x04, // Multicast 0x01, 0x00, // Number of unicast 0x00, 0x50, 0xf2, 0x04, // unicast 0x01, 0x00, // number of authentication method 0x00, 0x50, 0xf2, 0x02 // authentication };UCHAR CipherWpaPskAesLen = (sizeof(CipherWpaPskAes) / sizeof(UCHAR));UCHAR CipherSuiteCiscoCCKM[] = { 0xDD, 0x16, // RSN IE 0x00, 0x50, 0xf2, 0x01, // oui 0x01, 0x00, // Version 0x00, 0x40, 0x96, 0x01, // Multicast 0x01, 0x00, // Number of uicast 0x00, 0x40, 0x96, 0x01, // unicast 0x01, 0x00, // number of authentication method 0x00, 0x40, 0x96, 0x00 // Authentication };UCHAR CipherSuiteCiscoCCKMLen = (sizeof(CipherSuiteCiscoCCKM) / sizeof(UCHAR));UCHAR CipherSuiteCiscoCCKM24[] = { 0xDD, 0x18, // RSN IE 0x00, 0x50, 0xf2, 0x01, // oui 0x01, 0x00, // Version 0x00, 0x40, 0x96, 0x01, // Multicast 0x01, 0x00, // Number of uicast 0x00, 0x40, 0x96, 0x01, // unicast 0x01, 0x00, // number of authentication method 0x00, 0x40, 0x96, 0x00, 0x28, 0x00// Authentication };UCHAR CipherSuiteCiscoCCKM24Len = (sizeof(CipherSuiteCiscoCCKM24) / sizeof(UCHAR));UCHAR CipherSuiteCCXTkip[] = { 0xDD, 0x16, // RSN IE 0x00, 0x50, 0xf2, 0x01, // oui 0x01, 0x00, // Version 0x00, 0x50, 0xf2, 0x02, // Multicast 0x01, 0x00, // Number of unicast 0x00, 0x50, 0xf2, 0x02, // unicast 0x01, 0x00, // number of authentication method 0x00, 0x50, 0xf2, 0x01 // authentication };UCHAR CipherSuiteCCXTkipLen = (sizeof(CipherSuiteCCXTkip) / sizeof(UCHAR));UCHAR CCX_LLC_HDR[] = {0xAA, 0xAA, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02};UCHAR LLC_NORMAL[] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00};UCHAR EAPOL_FRAME[] = {0x88, 0x8E};BOOLEAN CheckRSNIE( IN PRTMP_ADAPTER pAd, IN PUCHAR pData, IN UCHAR DataLen, OUT UCHAR *Offset);void inc_byte_array(UCHAR *counter, int len);/* ======================================================================== Routine Description: Classify WPA EAP message type Arguments: EAPType Value of EAP message type MsgType Internal Message definition for MLME state machine Return Value: TRUE Found appropriate message type FALSE No appropriate message type IRQL = DISPATCH_LEVEL Note: All these constants are defined in wpa.h For supplicant, there is only EAPOL Key message avaliable ========================================================================*/BOOLEAN WpaMsgTypeSubst( IN UCHAR EAPType, OUT INT *MsgType) { switch (EAPType) { case EAPPacket: *MsgType = MT2_EAPPacket; break; case EAPOLStart: *MsgType = MT2_EAPOLStart; break; case EAPOLLogoff: *MsgType = MT2_EAPOLLogoff; break; case EAPOLKey: *MsgType = MT2_EAPOLKey; break; case EAPOLASFAlert: *MsgType = MT2_EAPOLASFAlert; break; default: return FALSE; } return TRUE;}/* ========================================================================== Description: association state machine init, including state transition and timer init Parameters: S - pointer to the association state machine ========================================================================== */VOID WpaPskStateMachineInit( IN PRTMP_ADAPTER pAd, IN STATE_MACHINE *S, OUT STATE_MACHINE_FUNC Trans[]) { StateMachineInit(S, Trans, MAX_WPA_PSK_STATE, MAX_WPA_PSK_MSG, (STATE_MACHINE_FUNC)Drop, WPA_PSK_IDLE, WPA_MACHINE_BASE); StateMachineSetAction(S, WPA_PSK_IDLE, MT2_EAPOLKey, (STATE_MACHINE_FUNC)WpaEAPOLKeyAction);}/* ========================================================================== Description: This is state machine function. When receiving EAPOL packets which is for 802.1x key management. Use both in WPA, and WPAPSK case. In this function, further dispatch to different functions according to the received packet. 3 categories are : 1. normal 4-way pairwisekey and 2-way groupkey handshake 2. MIC error (Countermeasures attack) report packet from STA. 3. Request for pairwise/group key update from STA Return: ==========================================================================*/VOID WpaEAPOLKeyAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { INT MsgType = EAPOL_MSG_INVALID; PKEY_DESCRIPTER pKeyDesc; PHEADER_802_11 pHeader; //red UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY]; UCHAR EapolVr; KEY_INFO peerKeyInfo; DBGPRINT(RT_DEBUG_TRACE, ("-----> WpaEAPOLKeyAction\n")); // Get 802.11 header first pHeader = (PHEADER_802_11) Elem->Msg; // Get EAPoL-Key Descriptor pKeyDesc = (PKEY_DESCRIPTER) &Elem->Msg[(LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H)]; NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo)); NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pKeyDesc->KeyInfo, sizeof(KEY_INFO)); *((USHORT *)&peerKeyInfo) = cpu2le16(*((USHORT *)&peerKeyInfo)); // 1. Check EAPOL frame version and type EapolVr = (UCHAR) Elem->Msg[LENGTH_802_11+LENGTH_802_1_H]; if (((EapolVr != EAPOL_VER) && (EapolVr != EAPOL_VER2)) || ((pKeyDesc->Type != WPA1_KEY_DESC) && (pKeyDesc->Type != WPA2_KEY_DESC))) { DBGPRINT(RT_DEBUG_ERROR, ("Key descripter does not match with WPA rule\n")); return; } // First validate replay counter, only accept message with larger replay counter // Let equal pass, some AP start with all zero replay counter NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY); if((RTMPCompareMemory(pKeyDesc->ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) && (RTMPCompareMemory(pKeyDesc->ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0)) { DBGPRINT(RT_DEBUG_ERROR, (" ReplayCounter not match \n")); return; } // Process WPA2PSK frame if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) { if((peerKeyInfo.KeyType == PAIRWISEKEY) && (peerKeyInfo.EKD_DL == 0) && (peerKeyInfo.KeyAck == 1) && (peerKeyInfo.KeyMic == 0) && (peerKeyInfo.Secure == 0) && (peerKeyInfo.Error == 0) && (peerKeyInfo.Request == 0)) { MsgType = EAPOL_PAIR_MSG_1; DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 1\n")); } else if((peerKeyInfo.KeyType == PAIRWISEKEY) && (peerKeyInfo.EKD_DL == 1) && (peerKeyInfo.KeyAck == 1) && (peerKeyInfo.KeyMic == 1) && (peerKeyInfo.Secure == 1) && (peerKeyInfo.Error == 0) && (peerKeyInfo.Request == 0)) { MsgType = EAPOL_PAIR_MSG_3; DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 3\n")); } else if((peerKeyInfo.KeyType == GROUPKEY) && (peerKeyInfo.EKD_DL == 1) && (peerKeyInfo.KeyAck == 1) && (peerKeyInfo.KeyMic == 1) && (peerKeyInfo.Secure == 1) && (peerKeyInfo.Error == 0) && (peerKeyInfo.Request == 0)) { MsgType = EAPOL_GROUP_MSG_1; DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Group Message 1\n")); } // We will assume link is up (assoc suceess and port not secured). // All state has to be able to process message from previous state switch(pAd->StaCfg.WpaState) { case SS_START: if(MsgType == EAPOL_PAIR_MSG_1) { Wpa2PairMsg1Action(pAd, Elem); pAd->StaCfg.WpaState = SS_WAIT_MSG_3; } break; case SS_WAIT_MSG_3: if(MsgType == EAPOL_PAIR_MSG_1) { Wpa2PairMsg1Action(pAd, Elem); pAd->StaCfg.WpaState = SS_WAIT_MSG_3; } else if(MsgType == EAPOL_PAIR_MSG_3) { Wpa2PairMsg3Action(pAd, Elem); pAd->StaCfg.WpaState = SS_WAIT_GROUP; } break; case SS_WAIT_GROUP: // When doing group key exchange case SS_FINISH: // This happened when update group key if(MsgType == EAPOL_PAIR_MSG_1) { // Reset port secured variable pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; Wpa2PairMsg1Action(pAd, Elem); pAd->StaCfg.WpaState = SS_WAIT_MSG_3; } else if(MsgType == EAPOL_PAIR_MSG_3) { // Reset port secured variable pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; Wpa2PairMsg3Action(pAd, Elem); pAd->StaCfg.WpaState = SS_WAIT_GROUP; } else if(MsgType == EAPOL_GROUP_MSG_1) { WpaGroupMsg1Action(pAd, Elem); pAd->StaCfg.WpaState = SS_FINISH; } break; default: break; } } // Process WPAPSK Frame // Classify message Type, either pairwise message 1, 3, or group message 1 for supplicant else if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) { if((peerKeyInfo.KeyType == PAIRWISEKEY) && (peerKeyInfo.KeyIndex == 0) && (peerKeyInfo.KeyAck == 1) && (peerKeyInfo.KeyMic == 0) && (peerKeyInfo.Secure == 0) && (peerKeyInfo.Error == 0) && (peerKeyInfo.Request == 0)) { MsgType = EAPOL_PAIR_MSG_1; DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 1\n")); } else if((peerKeyInfo.KeyType == PAIRWISEKEY) && (peerKeyInfo.KeyIndex == 0) && (peerKeyInfo.KeyAck == 1) && (peerKeyInfo.KeyMic == 1) && (peerKeyInfo.Secure == 0) && (peerKeyInfo.Error == 0) && (peerKeyInfo.Request == 0)) { MsgType = EAPOL_PAIR_MSG_3; DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 3\n")); } else if((peerKeyInfo.KeyType == GROUPKEY) && (peerKeyInfo.KeyIndex != 0) && (peerKeyInfo.KeyAck == 1) && (peerKeyInfo.KeyMic == 1) && (peerKeyInfo.Secure == 1) && (peerKeyInfo.Error == 0) && (peerKeyInfo.Request == 0)) { MsgType = EAPOL_GROUP_MSG_1; DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Group Message 1\n")); } // We will assume link is up (assoc suceess and port not secured). // All state has to be able to process message from previous state switch(pAd->StaCfg.WpaState) { case SS_START: if(MsgType == EAPOL_PAIR_MSG_1) { WpaPairMsg1Action(pAd, Elem); pAd->StaCfg.WpaState = SS_WAIT_MSG_3; } break; case SS_WAIT_MSG_3: if(MsgType == EAPOL_PAIR_MSG_1) { WpaPairMsg1Action(pAd, Elem); pAd->StaCfg.WpaState = SS_WAIT_MSG_3; } else if(MsgType == EAPOL_PAIR_MSG_3) { WpaPairMsg3Action(pAd, Elem); pAd->StaCfg.WpaState = SS_WAIT_GROUP; } break; case SS_WAIT_GROUP: // When doing group key exchange case SS_FINISH: // This happened when update group key if(MsgType == EAPOL_PAIR_MSG_1) { WpaPairMsg1Action(pAd, Elem); pAd->StaCfg.WpaState = SS_WAIT_MSG_3; // Reset port secured variable pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; } else if(MsgType == EAPOL_PAIR_MSG_3) { WpaPairMsg3Action(pAd, Elem); pAd->StaCfg.WpaState = SS_WAIT_GROUP; // Reset port secured variable pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; } else if(MsgType == EAPOL_GROUP_MSG_1) { WpaGroupMsg1Action(pAd, Elem); pAd->StaCfg.WpaState = SS_FINISH; } break; default: break; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -