wpa.c

来自「Ralink RT61 SoftAP Driver source code. 」· C语言 代码 · 共 1,629 行 · 第 1/5 页

C
1,629
字号
/*
 ***************************************************************************
 * Ralink Tech Inc.
 * 4F, No. 2 Technology 5th Rd.
 * Science-based Industrial Park
 * Hsin-chu, Taiwan, R.O.C.
 *
 * (c) Copyright 2005, Ralink Technology, Inc.
 *
 * All rights reserved. Ralink's source code is an unpublished work and the
 * use of a copyright notice does not imply otherwise. This source code
 * contains confidential trade secret material of Ralink Tech. Any attemp
 * or participation in deciphering, decoding, reverse engineering or in any
 * way altering the source code is stricitly prohibited, unless the prior
 * written consent of Ralink Technology, Inc. is obtained.
 ***************************************************************************

    Module Name:
    wpa.c

    Abstract:

    Revision History:
    Who         When            What
    --------    ----------      ----------------------------------------------
    Jan Lee     03-07-22        Initial
*/
#include "rt_config.h"

static UCHAR       OUI_WPA_WEP40[4]		= {0x00, 0x50, 0xF2, 0x01};
static UCHAR       OUI_WPA_TKIP[4]		= {0x00, 0x50, 0xF2, 0x02};
static UCHAR       OUI_WPA_CCMP[4]		= {0x00, 0x50, 0xF2, 0x04};
static UCHAR       OUI_WPA2_WEP40[4]		= {0x00, 0x0F, 0xAC, 0x01};
static UCHAR       OUI_WPA2_TKIP[4]		= {0x00, 0x0F, 0xAC, 0x02};
static UCHAR       OUI_WPA2_CCMP[4]		= {0x00, 0x0F, 0xAC, 0x04};
static UCHAR	   prf_input[1024];

#ifdef RTL865X_SOC
static inline VOID	ApCliWpaMacHeaderInit(
	IN		PRTMP_ADAPTER	pAd, 
	IN OUT	PHEADER_802_11	pHdr80211, 
	IN		UCHAR			wep, 
	IN		PUCHAR		    pAddr1,
	IN		PUCHAR		    pAddr2);

static inline VOID    Wpa2PairMsg3Action(
    IN  PRTMP_ADAPTER   pAd, 
    IN  MLME_QUEUE_ELEM *Elem,
	IN	INT				IfIndex);

static inline BOOLEAN ParseKeyData(
    IN  PRTMP_ADAPTER   pAd,
    IN  PUCHAR          pKeyData,
    IN  UCHAR           KeyDataLen,
	IN	INT				IfIndex,
	IN	UCHAR			bPairewise);	
#endif	/* endif ifdef RTL865X_SOC */

#define ROUND_UP(__x, __y) \
	(((ULONG)((__x)+((__y)-1))) & ((ULONG)~((__y)-1)))\

BOOLEAN WPAMsgTypeSubst(
    IN UCHAR    EAPType,
    OUT ULONG   *MsgType) 
{
	DBGPRINT(RT_DEBUG_TRACE, "WPAMsgTypeSubst (EAPType=%d)\n", EAPType);
	
    switch(EAPType)
    {
        case EAPPacket:
            *MsgType = MACHINE_TYPE_EAPPacket;
            break;

        case EAPOLStart:
            *MsgType = MACHINE_TYPE_EAPOLStart;
            break;

        case EAPOLLogoff:
            *MsgType = MACHINE_TYPE_EAPOLLogoff;
            break;

        case EAPOLKey:
            *MsgType = MACHINE_TYPE_EAPOLKey;
            break;

        case EAPOLASFAlert:
            *MsgType = MACHINE_TYPE_EAPOLASFAlert;
            break;

        default:
            DBGPRINT(RT_DEBUG_TRACE, "Unknown WPA MsgType\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 WpaStateMachineInit(
    IN  PRTMP_ADAPTER       pAd,
    IN  STATE_MACHINE       *S,
    OUT STATE_MACHINE_FUNC  Trans[])
{
    StateMachineInit(S, (STATE_MACHINE_FUNC*)Trans, MAX_WPA_PTK_STATE, MAX_WPA_MSG, (STATE_MACHINE_FUNC)Drop, WPA_PTK, WPA_MACHINE_BASE);

    StateMachineSetAction(S, WPA_PTK, MACHINE_TYPE_EAPPacket, (STATE_MACHINE_FUNC)WpaEAPPacketAction);
    StateMachineSetAction(S, WPA_PTK, MACHINE_TYPE_EAPOLStart, (STATE_MACHINE_FUNC)WpaEAPOLStartAction);
    StateMachineSetAction(S, WPA_PTK, MACHINE_TYPE_EAPOLLogoff, (STATE_MACHINE_FUNC)WpaEAPOLLogoffAction);
    StateMachineSetAction(S, WPA_PTK, MACHINE_TYPE_EAPOLKey, (STATE_MACHINE_FUNC)WpaEAPOLKeyAction);
    StateMachineSetAction(S, WPA_PTK, MACHINE_TYPE_EAPOLASFAlert, (STATE_MACHINE_FUNC)WpaEAPOLASFAlertAction);
}

/*
    ==========================================================================
    Description:
        Port Access Control Inquiry function. Return entry's Privacy and Wpastate.
        Also check if AP needs to initilize 4-way handshake. 
    Return:
        pEntry 
    ==========================================================================
*/
MAC_TABLE_ENTRY *PACInquiry(
    IN PRTMP_ADAPTER                pAd,
    IN PUCHAR                       pAddr,
    OUT NDIS_802_11_PRIVACY_FILTER  *Privacy,
    OUT WPA_STATE                   *WpaState)
{
    MAC_TABLE_ENTRY *pEntry = (MAC_TABLE_ENTRY*)NULL;
    
    *Privacy = Ndis802_11PrivFilterAcceptAll;
    *WpaState = AS_NOTUSE;

    if (MAC_ADDR_IS_GROUP(pAddr))
    {// mcast & broadcast address
    } 
    else
    {// unicast address
        pEntry = MacTableLookup(pAd, pAddr);
        if (pEntry) 
        {
            *Privacy = pEntry->PrivacyFilter;
            *WpaState = pEntry->WpaState;
        } 
    }
    return pEntry;
}

/*
    ==========================================================================
    Description:
       
    Return:
         TRUE if this is EAP frame
         FALSE otherwise
    ==========================================================================
*/
BOOLEAN RTMPCheckWPAframe(
    IN PRTMP_ADAPTER    pAdapter,
    IN PUCHAR           pHeader,
    IN ULONG            DataByteCount,
    IN UCHAR            Offset)
{
    PUCHAR  pData;
    
    DBGPRINT(RT_DEBUG_INFO, "RTMPCheckWPAframe ===>\n");
    
    if (DataByteCount < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + Offset))
        return FALSE;

    pData = pHeader + LENGTH_802_11 + Offset;
    DataByteCount -= (LENGTH_802_11 + Offset);
    if (RTMPEqualMemory(SNAP_802_1H, pData, 6)) 
    {
        pData += 6;
    }
    if (RTMPEqualMemory(EAPOL, pData, 2)) 
    {
        pData += 2;
    }
    else
        return FALSE;

    switch (*(pData+1))
    {   
        case EAPPacket:
            DBGPRINT(RT_DEBUG_INFO, "Receive EAP-Packet frame, TYPE = 0 \n");
            break;

        case EAPOLStart:
            DBGPRINT(RT_DEBUG_INFO, "Receive EAPOL-Start frame, TYPE = 1 \n");
            break;

        case EAPOLLogoff:
            DBGPRINT(RT_DEBUG_INFO, "Receive EAPOLLogoff frame, TYPE = 2 \n");
            break;

        case EAPOLKey:
            DBGPRINT(RT_DEBUG_INFO, "Receive EAPOL-Key frame, TYPE = 3, Length =%x\n", *(pData+2));
            break;

        case EAPOLASFAlert:
            DBGPRINT(RT_DEBUG_INFO, "Receive EAPOLASFAlert frame, TYPE = 4 \n");
            break;

        default:
            return FALSE;
    }   
    return TRUE;
}

/*
    ==========================================================================
    Description:
       Check invalidity of multicast cipher selection in RSN IE.
    Return:
         TRUE if match
         FALSE otherwise
    ==========================================================================
*/
BOOLEAN RTMPCheckMcast(
    IN PRTMP_ADAPTER    pAdapter,
    IN PEID_STRUCT      eid_ptr,
    IN MAC_TABLE_ENTRY	*pEntry)
{
	pEntry->AuthMode = pAdapter->PortCfg.MBSSID[pEntry->ApIdx].AuthMode;

    if (eid_ptr->Len >= 6)
    {
    	// WPA and WPA2 format not the same in RSN_IE
    	if (eid_ptr->Eid == IE_WPA)
    	{
    		if (pAdapter->PortCfg.MBSSID[pEntry->ApIdx].AuthMode == Ndis802_11AuthModeWPA1WPA2)
    			pEntry->AuthMode = Ndis802_11AuthModeWPA;
    		else if (pAdapter->PortCfg.MBSSID[pEntry->ApIdx].AuthMode == Ndis802_11AuthModeWPAPSKWPA2PSK)
    			pEntry->AuthMode = Ndis802_11AuthModeWPAPSK;

	        if (RTMPEqualMemory(&eid_ptr->Octet[6], &pAdapter->PortCfg.MBSSID[pEntry->ApIdx].RSN_IE[0][6], 4))
	            return TRUE;
    	}
    	else if (eid_ptr->Eid == IE_WPA2)
    	{
    		UCHAR	IE_Idx = 0;

			// When WPA1/WPA2 mix mode, the RSN_IE is stored in different structure
			if ((pAdapter->PortCfg.MBSSID[pEntry->ApIdx].AuthMode == Ndis802_11AuthModeWPA1WPA2) || (pAdapter->PortCfg.MBSSID[pEntry->ApIdx].AuthMode == Ndis802_11AuthModeWPAPSKWPA2PSK))
				IE_Idx = 1;
	
    		if (pAdapter->PortCfg.MBSSID[pEntry->ApIdx].AuthMode == Ndis802_11AuthModeWPA1WPA2)
    			pEntry->AuthMode = Ndis802_11AuthModeWPA2;
    		else if (pAdapter->PortCfg.MBSSID[pEntry->ApIdx].AuthMode == Ndis802_11AuthModeWPAPSKWPA2PSK)
    			pEntry->AuthMode = Ndis802_11AuthModeWPA2PSK;

    		if (RTMPEqualMemory(&eid_ptr->Octet[2], &pAdapter->PortCfg.MBSSID[pEntry->ApIdx].RSN_IE[IE_Idx][2], 4))
	            return TRUE;
    	}
    }

    DBGPRINT(RT_DEBUG_ERROR, "RTMPCheckMcast ==> WPAIE parsing error, WPAIE=%d\n", eid_ptr->Eid);

    return FALSE;
}

/*
    ==========================================================================
    Description:
       Check invalidity of unicast cipher selection in RSN IE.
    Return:
         TRUE if match
         FALSE otherwise
    ==========================================================================
*/
BOOLEAN RTMPCheckUcast(
    IN PRTMP_ADAPTER    pAdapter,
    IN PEID_STRUCT      eid_ptr,
    IN MAC_TABLE_ENTRY	*pEntry)
{
	pEntry->WepStatus = pAdapter->PortCfg.MBSSID[pEntry->ApIdx].WepStatus;
    
    if (eid_ptr->Len >= 16)
    {
    	if (eid_ptr->Eid == IE_WPA)
    	{
    		if (pAdapter->PortCfg.MBSSID[pEntry->ApIdx].WepStatus == Ndis802_11Encryption4Enabled)
			{// multiple cipher (TKIP/CCMP)
				if (RTMPEqualMemory(&eid_ptr->Octet[12], &pAdapter->PortCfg.MBSSID[pEntry->ApIdx].RSN_IE[0][12], 4))
				{
					pEntry->WepStatus = Ndis802_11Encryption2Enabled;
					return TRUE;
				}
				else if (RTMPEqualMemory(&eid_ptr->Octet[12], &pAdapter->PortCfg.MBSSID[pEntry->ApIdx].RSN_IE[0][16], 4))
				{
					pEntry->WepStatus = Ndis802_11Encryption3Enabled;
					return TRUE;
				}
    		}
    		else
    		{// single cipher
    			if (RTMPEqualMemory(&eid_ptr->Octet[12], &pAdapter->PortCfg.MBSSID[pEntry->ApIdx].RSN_IE[0][12], 4))
		            return TRUE;
    		}
    	}
    	else if (eid_ptr->Eid == IE_WPA2)
    	{
    		UCHAR	IE_Idx = 0;

			// When WPA1/WPA2 mix mode, the RSN_IE is stored in different structure
			if ((pAdapter->PortCfg.MBSSID[pEntry->ApIdx].AuthMode == Ndis802_11AuthModeWPA1WPA2) || (pAdapter->PortCfg.MBSSID[pEntry->ApIdx].AuthMode == Ndis802_11AuthModeWPAPSKWPA2PSK))
				IE_Idx = 1;
	
			if (pAdapter->PortCfg.MBSSID[pEntry->ApIdx].WepStatus == Ndis802_11Encryption4Enabled)
			{// multiple cipher (TKIP/CCMP)
				if (RTMPEqualMemory(&eid_ptr->Octet[8], &pAdapter->PortCfg.MBSSID[pEntry->ApIdx].RSN_IE[IE_Idx][8], 4))
				{
					pEntry->WepStatus = Ndis802_11Encryption2Enabled;
					return TRUE;
				}
				else if (RTMPEqualMemory(&eid_ptr->Octet[8], &pAdapter->PortCfg.MBSSID[pEntry->ApIdx].RSN_IE[IE_Idx][12], 4))
				{
					pEntry->WepStatus = Ndis802_11Encryption3Enabled;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?