?? wpa.c
字號:
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2006, 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"
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));
extern UCHAR CipherWpa2Template[];
extern UCHAR CipherWpa2TemplateLen;
#define WPARSNIE 0xdd
#define WPA2RSNIE 0x30
/*
========================================================================
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
Note:
All these constants are defined in wpa.h
For supplicant, there is only EAPOL Key message avaliable
========================================================================
*/
BOOLEAN WpaMsgTypeSubst(
IN UCHAR EAPType,
OUT ULONG *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:
DBGPRINT(RT_DEBUG_INFO, "WpaMsgTypeSubst : return FALSE; \n");
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, (STATE_MACHINE_FUNC*)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)
{
#ifdef MAJI_DBG
printk("I am in %s \n",__FUNCTION__);
#endif
INT MsgType = EAPOL_MSG_INVALID;
PKEY_DESCRIPTER pKeyDesc;
PHEADER_802_11 pHeader; //red
UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY];
DBGPRINT(RT_DEBUG_TRACE, "-----> WpaEAPOLKeyAction\n");
pHeader = (PHEADER_802_11) Elem->Msg;
// Get 802.11 header first
pKeyDesc = (PKEY_DESCRIPTER) &Elem->Msg[(LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H)];
#ifdef BIG_ENDIAN
// pMsg->KeyDesc.KeyInfo and pKeyDesc->KeyInfo both point to the same addr.
// Thus, it only needs swap once.
{
USHORT tmpKeyinfo;
NdisMoveMemory(&tmpKeyinfo, &pKeyDesc->KeyInfo, sizeof(USHORT));
tmpKeyinfo = SWAP16(tmpKeyinfo);
NdisMoveMemory(&pKeyDesc->KeyInfo, &tmpKeyinfo, sizeof(USHORT));
}
// *(USHORT *)((UCHAR *)pKeyDesc+1) = SWAP16(*(USHORT *)((UCHAR *)pKeyDesc+1));
#endif
// Sanity check, this should only happen in WPA(2)-PSK mode
// 0. Debug print all bit information
DBGPRINT(RT_DEBUG_INFO, "KeyInfo Key Description Version %d\n", pKeyDesc->KeyInfo.KeyDescVer);
DBGPRINT(RT_DEBUG_INFO, "KeyInfo Key Type %d\n", pKeyDesc->KeyInfo.KeyType);
DBGPRINT(RT_DEBUG_INFO, "KeyInfo Key Index %d\n", pKeyDesc->KeyInfo.KeyIndex);
DBGPRINT(RT_DEBUG_INFO, "KeyInfo Install %d\n", pKeyDesc->KeyInfo.Install);
DBGPRINT(RT_DEBUG_INFO, "KeyInfo Key Ack %d\n", pKeyDesc->KeyInfo.KeyAck);
DBGPRINT(RT_DEBUG_INFO, "KeyInfo Key MIC %d\n", pKeyDesc->KeyInfo.KeyMic);
DBGPRINT(RT_DEBUG_INFO, "KeyInfo Secure %d\n", pKeyDesc->KeyInfo.Secure);
DBGPRINT(RT_DEBUG_INFO, "KeyInfo Error %d\n", pKeyDesc->KeyInfo.Error);
DBGPRINT(RT_DEBUG_INFO, "KeyInfo Request %d\n", pKeyDesc->KeyInfo.Request);
DBGPRINT(RT_DEBUG_INFO, "KeyInfo EKD_DL %d\n", pKeyDesc->KeyInfo.EKD_DL);
// 1. Check EAPOL frame version and type
if (pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPAPSK)
{
if ((Elem->Msg[LENGTH_802_11+LENGTH_802_1_H] != EAPOL_VER) || (pKeyDesc->Type != WPA1_KEY_DESC))
{
DBGPRINT(RT_DEBUG_ERROR, " Key descripter does not match with WPA1 rule \n");
return;
}
}
else if (pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
{
// pass (Version != EAPOL_VER)
if (pKeyDesc->Type != WPA2_KEY_DESC)
{
DBGPRINT(RT_DEBUG_ERROR, " Key descripter does not match with WPA2 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->PortCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) &&
(RTMPCompareMemory(pKeyDesc->ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0))
{
DBGPRINT(RT_DEBUG_ERROR, " ReplayCounter not match \n");
return;
}
/*
====================================================================
WPAPSK2 WPAPSK2 WPAPSK2 WPAPSK2
======================================================================
*/
if (pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
{
if ((pKeyDesc->KeyInfo.KeyType == 1) &&
(pKeyDesc->KeyInfo.EKD_DL == 0) &&
(pKeyDesc->KeyInfo.KeyAck == 1) &&
(pKeyDesc->KeyInfo.KeyMic == 0) &&
(pKeyDesc->KeyInfo.Secure == 0) &&
(pKeyDesc->KeyInfo.Error == 0) &&
(pKeyDesc->KeyInfo.Request == 0))
{
MsgType = EAPOL_PAIR_MSG_1;
DBGPRINT(RT_DEBUG_ERROR, "Receive EAPOL Key Pairwise Message 1\n");
}
else if ((pKeyDesc->KeyInfo.KeyType == 1) &&
(pKeyDesc->KeyInfo.EKD_DL == 1) &&
(pKeyDesc->KeyInfo.KeyAck == 1) &&
(pKeyDesc->KeyInfo.KeyMic == 1) &&
(pKeyDesc->KeyInfo.Secure == 1) &&
(pKeyDesc->KeyInfo.Error == 0) &&
(pKeyDesc->KeyInfo.Request == 0))
{
MsgType = EAPOL_PAIR_MSG_3;
DBGPRINT(RT_DEBUG_ERROR, "Receive EAPOL Key Pairwise Message 3\n");
}
else if ((pKeyDesc->KeyInfo.KeyType == 0) &&
(pKeyDesc->KeyInfo.EKD_DL == 1) &&
(pKeyDesc->KeyInfo.KeyAck == 1) &&
(pKeyDesc->KeyInfo.KeyMic == 1) &&
(pKeyDesc->KeyInfo.Secure == 1) &&
(pKeyDesc->KeyInfo.Error == 0) &&
(pKeyDesc->KeyInfo.Request == 0))
{
MsgType = EAPOL_GROUP_MSG_1;
DBGPRINT(RT_DEBUG_ERROR, "Receive EAPOL Key Group Message 1\n");
}
#ifdef BIG_ENDIAN
// recovery original byte order, before forward Elem to another routine
{
USHORT tmpKeyinfo;
NdisMoveMemory(&tmpKeyinfo, &pKeyDesc->KeyInfo, sizeof(USHORT));
tmpKeyinfo = SWAP16(tmpKeyinfo);
NdisMoveMemory(&pKeyDesc->KeyInfo, &tmpKeyinfo, sizeof(USHORT));
}
// *(USHORT *)((UCHAR *)pKeyDesc+1) = SWAP16(*(USHORT *)((UCHAR *)pKeyDesc+1));
#endif
// 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->PortCfg.WpaState)
{
case SS_START:
if (MsgType == EAPOL_PAIR_MSG_1)
{
Wpa2PairMsg1Action(pAd, Elem);
pAd->PortCfg.WpaState = SS_WAIT_MSG_3;
}
break;
case SS_WAIT_MSG_3:
if (MsgType == EAPOL_PAIR_MSG_1)
{
Wpa2PairMsg1Action(pAd, Elem);
pAd->PortCfg.WpaState = SS_WAIT_MSG_3;
}
else if (MsgType == EAPOL_PAIR_MSG_3)
{
Wpa2PairMsg3Action(pAd, Elem);
pAd->PortCfg.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)
{
Wpa2PairMsg1Action(pAd, Elem);
pAd->PortCfg.WpaState = SS_WAIT_MSG_3;
// Reset port secured variable
pAd->PortCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
}
else if (MsgType == EAPOL_PAIR_MSG_3)
{
Wpa2PairMsg3Action(pAd, Elem);
pAd->PortCfg.WpaState = SS_WAIT_GROUP;
// Reset port secured variable
pAd->PortCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
}
else if (MsgType == EAPOL_GROUP_MSG_1)
{
WpaGroupMsg1Action(pAd, Elem);
pAd->PortCfg.WpaState = SS_FINISH;
}
break;
default:
break;
}
}
///*
//====================================================================
// WPAPSK WPAPSK WPAPSK WPAPSK
//======================================================================
//*/
// Classify message Type, either pairwise message 1, 3, or group message 1 for supplicant
else if (pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPAPSK)
{
if ((pKeyDesc->KeyInfo.KeyType == 1) &&
(pKeyDesc->KeyInfo.KeyIndex == 0) &&
(pKeyDesc->KeyInfo.KeyAck == 1) &&
(pKeyDesc->KeyInfo.KeyMic == 0) &&
(pKeyDesc->KeyInfo.Secure == 0) &&
(pKeyDesc->KeyInfo.Error == 0) &&
(pKeyDesc->KeyInfo.Request == 0))
{
MsgType = EAPOL_PAIR_MSG_1;
DBGPRINT(RT_DEBUG_TRACE, "Receive EAPOL Key Pairwise Message 1\n");
}
else if ((pKeyDesc->KeyInfo.KeyType == 1) &&
(pKeyDesc->KeyInfo.KeyIndex == 0) &&
(pKeyDesc->KeyInfo.KeyAck == 1) &&
(pKeyDesc->KeyInfo.KeyMic == 1) &&
(pKeyDesc->KeyInfo.Secure == 0) &&
(pKeyDesc->KeyInfo.Error == 0) &&
(pKeyDesc->KeyInfo.Request == 0))
{
MsgType = EAPOL_PAIR_MSG_3;
DBGPRINT(RT_DEBUG_TRACE, "Receive EAPOL Key Pairwise Message 3\n");
}
else if ((pKeyDesc->KeyInfo.KeyType == 0) &&
(pKeyDesc->KeyInfo.KeyIndex != 0) &&
(pKeyDesc->KeyInfo.KeyAck == 1) &&
(pKeyDesc->KeyInfo.KeyMic == 1) &&
(pKeyDesc->KeyInfo.Secure == 1) &&
(pKeyDesc->KeyInfo.Error == 0) &&
(pKeyDesc->KeyInfo.Request == 0))
{
MsgType = EAPOL_GROUP_MSG_1;
DBGPRINT(RT_DEBUG_TRACE, "Receive EAPOL Key Group Message 1\n");
}
#ifdef BIG_ENDIAN
// recovery original byte order, before forward Elem to another routine
{
USHORT tmpKeyinfo;
NdisMoveMemory(&tmpKeyinfo, &pKeyDesc->KeyInfo, sizeof(USHORT));
tmpKeyinfo = SWAP16(tmpKeyinfo);
NdisMoveMemory(&pKeyDesc->KeyInfo, &tmpKeyinfo, sizeof(USHORT));
}
// *(USHORT *)((UCHAR *)pKeyDesc+1) = SWAP16(*(USHORT *)((UCHAR *)pKeyDesc+1));
#endif
// 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->PortCfg.WpaState)
{
case SS_START:
if (MsgType == EAPOL_PAIR_MSG_1)
{
WpaPairMsg1Action(pAd, Elem);
pAd->PortCfg.WpaState = SS_WAIT_MSG_3;
}
break;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -