⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wpa.c

📁 经过修改的在uClinux2.6上正常运行的ralink rt2571芯片组的设备驱动程序.
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 ***************************************************************************
 * 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 + -