wpa.c

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

C
1,629
字号
/*
    ==========================================================================
    Description:
        This is a function to initilize 4way handshake
    Return:
         
    ==========================================================================
*/
VOID WPAStart4WayHS(
    IN PRTMP_ADAPTER    pAdapter,
    IN MAC_TABLE_ENTRY  *pEntry)
{
    ULONG           FrameLen = 0;
    UCHAR           *OutBuffer = NULL;
    UCHAR           Header802_3[14];
    EAPOL_PACKET    Packet;

    DBGPRINT(RT_DEBUG_TRACE, "==>WPAStart4WayHS\n");

    do
    {
    	if (!pEntry)
    		break;
    	if ((pEntry->WpaState > AS_PTKSTART) || (pEntry->WpaState < AS_INITPMK))
	    {
	        DBGPRINT(RT_DEBUG_ERROR, "Not expect calling WPAStart4WayHS here ");
	        break;
	    }
    	
        OutBuffer = kmalloc(MAX_LEN_OF_EAP_HS, MEM_ALLOC_FLAG);
        if(OutBuffer == NULL)
            break;

        WPAMake8023Hdr(pAdapter, pEntry, Header802_3);

        // Increment replay counter by 1  
        ADD_ONE_To_64BIT_VAR(pAdapter->PortCfg.R_Counter);
        
        // 0. init Packet and Fill header
        NdisZeroMemory(&Packet, sizeof(Packet));
        Packet.ProVer = EAPOL_VER;
        Packet.ProType = EAPOLKey;
        Packet.Body_Len[1] = 0x5f;
        
        // 1. Fill replay counter
        NdisMoveMemory(pEntry->R_Counter, pAdapter->PortCfg.R_Counter, sizeof(pEntry->R_Counter));
        NdisMoveMemory(Packet.KeyDesc.RCounter, pEntry->R_Counter, sizeof(pEntry->R_Counter));
        
        // 2. Fill key version, keyinfo, key len
        Packet.KeyDesc.Keyinfo.KeyType = PAIRWISEKEY;
        Packet.KeyDesc.Keyinfo.KeyAck = 1;
		DBGPRINT(RT_DEBUG_TRACE, "STA from %02x:%02x:%02x:%02x:%02x:%02x\n", 
				pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], pEntry->Addr[3],
				pEntry->Addr[4], pEntry->Addr[5]);
        DBGPRINT(RT_DEBUG_TRACE, "PMK = %02x:%02x:%02x:%02x-%02x:%02x:%02x:%02x\n",
        	pAdapter->PortCfg.MBSSID[pEntry->ApIdx].PMK[0],pAdapter->PortCfg.MBSSID[pEntry->ApIdx].PMK[1],pAdapter->PortCfg.MBSSID[pEntry->ApIdx].PMK[2],pAdapter->PortCfg.MBSSID[pEntry->ApIdx].PMK[3],
        	pAdapter->PortCfg.MBSSID[pEntry->ApIdx].PMK[4],pAdapter->PortCfg.MBSSID[pEntry->ApIdx].PMK[5],pAdapter->PortCfg.MBSSID[pEntry->ApIdx].PMK[6],pAdapter->PortCfg.MBSSID[pEntry->ApIdx].PMK[7]);
        
        if ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || (pEntry->AuthMode == Ndis802_11AuthModeWPAPSK))
        {
        	Packet.KeyDesc.Type = WPA1_KEY_DESC;
        	Packet.KeyDesc.DataLen[1] = 0;

        	DBGPRINT(RT_DEBUG_TRACE, "pEntry->AuthMode == Ndis802_11AuthModeWPA/WPAPSK\n");
        }
        else if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
        {
        	Packet.KeyDesc.Type = WPA2_KEY_DESC;
        	Packet.KeyDesc.DataLen[1] = 0;

			// PMKID match, then start 4-way HS directly
        	if (pEntry->PMKID_CacheIdx != ENTRY_NOT_FOUND)
        	{
        		Packet.KeyDesc.Data[0] = 0xDD;
	        	Packet.KeyDesc.Data[2] = 0x00;
	        	Packet.KeyDesc.Data[3] = 0x0F;
	        	Packet.KeyDesc.Data[4] = 0xAC;
	        	Packet.KeyDesc.Data[5] = 0x04;

        		NdisMoveMemory(&Packet.KeyDesc.Data[6], &pAdapter->PortCfg.MBSSID[pEntry->ApIdx].PMKIDCache.BSSIDInfo[pEntry->PMKID_CacheIdx].PMKID, LEN_PMKID);
        		NdisMoveMemory(&pAdapter->PortCfg.MBSSID[pEntry->ApIdx].PMK, &pAdapter->PortCfg.MBSSID[pEntry->ApIdx].PMKIDCache.BSSIDInfo[pEntry->PMKID_CacheIdx].PMK, PMK_LEN);
        		
        		Packet.KeyDesc.Data[1] = 0x14;// 4+2+LEN_PMKID
        		Packet.KeyDesc.DataLen[1] += 6 + LEN_PMKID;
        		Packet.Body_Len[1] += 6 + LEN_PMKID;
        	}
        	
        	DBGPRINT(RT_DEBUG_TRACE, "pEntry->AuthMode == Ndis802_11AuthModeWPA2/WPA2PSK\n");
        }

        if (pEntry->WepStatus == Ndis802_11Encryption2Enabled)
        {
            Packet.KeyDesc.KeyLength[1] = LEN_TKIP_KEY;
            Packet.KeyDesc.Keyinfo.KeyDescVer = DESC_TYPE_TKIP;
        }
        else if (pEntry->WepStatus == Ndis802_11Encryption3Enabled)
        {
            Packet.KeyDesc.KeyLength[1] = LEN_AES_KEY;
            Packet.KeyDesc.Keyinfo.KeyDescVer = DESC_TYPE_AES;
        }

#ifdef BIG_ENDIAN
{
		USHORT	tmpKeyinfo;

		NdisMoveMemory(&tmpKeyinfo, &Packet.KeyDesc.Keyinfo, sizeof(USHORT)); 
		tmpKeyinfo = SWAP16(tmpKeyinfo);
		NdisMoveMemory(&Packet.KeyDesc.Keyinfo, &tmpKeyinfo, sizeof(USHORT)); 
}

//        *(USHORT *)&Packet.KeyDesc.Keyinfo = SWAP16(*(USHORT *)&Packet.KeyDesc.Keyinfo);
#endif
        
        // 3. Fill Anonce
        GenRandom(pAdapter, pEntry->ANonce, pEntry->ApIdx);
        NdisMoveMemory(Packet.KeyDesc.Nonce, pEntry->ANonce, sizeof(pEntry->ANonce));
        MakeOutgoingFrame(OutBuffer,            &FrameLen,
                            sizeof(Header802_3),    Header802_3,
                            Packet.Body_Len[1] + 4,  &Packet,
                            END_OF_ARGS);

        RTMPToWirelessSta(pAdapter, OutBuffer, FrameLen);

        mod_timer(&pEntry->RetryTimer, pEntry->RetryTimer.expires);
		// Should start from 1, init is 0
		pEntry->ReTryCounter++;
		pEntry->RetryTimerRunning = TRUE;

        pEntry->WpaState = AS_PTKSTART;

        kfree(OutBuffer);
    }while(FALSE);
    
    DBGPRINT(RT_DEBUG_TRACE, "<== WPAStart4WayHS:pEntry->WpaState=%d, FrameLen=%d\n",pEntry->WpaState,FrameLen);
}

/*
    ==========================================================================
    Description:
        When receiving the second packet of 4-way pairwisekey handshake.
    Return:
    ==========================================================================
*/
VOID PeerPairMsg2Action(
    IN PRTMP_ADAPTER    pAdapter, 
    IN MAC_TABLE_ENTRY  *pEntry,
    IN MLME_QUEUE_ELEM  *Elem) 
{
    UCHAR                   *mpool, *PTK, *digest, *Key_Data, *pRc4GTK; 
    UCHAR					mic[LEN_KEY_DESC_MIC], SNonce[LEN_KEY_DESC_NONCE];
    ULONG                   FrameLen = 0;
    UCHAR                   *OutBuffer = NULL;
    USHORT                  MICMsgLen, MICOffset;
    PUCHAR                  pSA;
    UCHAR                   Header802_3[LENGTH_802_3];
    EAPOL_PACKET            Packet;
    PEAPOL_PACKET           pMsg2;
    PHEADER_802_11          pHeader;

    DBGPRINT(RT_DEBUG_TRACE, "PeerPairMsg2Action ===>\n");

    if (!pEntry)
    	return;

    // check Entry in valid State
    if (pEntry->WpaState < AS_PTKSTART)
        return;

	mpool = kmalloc(4096, MEM_ALLOC_FLAG);  // allocate memory
    if (mpool == NULL)
            return;
            
	/* OutBuffer Len = MAX_LEN_OF_EAP_HS */
	OutBuffer = (UCHAR *) ROUND_UP(mpool, 4);
	/* PTK  Len = 80 */
	PTK = (UCHAR *) ROUND_UP(OutBuffer+MAX_LEN_OF_EAP_HS, 4);
	/* digest Len = 80 */
	digest =(UCHAR *) ROUND_UP(PTK+80, 4);
	/* pRc4GTK Len = 512 */
	pRc4GTK = (UCHAR *) ROUND_UP(digest+80, 4);
	/* Key_Data Len = 512 */
	Key_Data = (UCHAR *) ROUND_UP(pRc4GTK+512, 4);

    do
    {            
        // Save Data Length to pDesc for receiving packet,   then put in outgoing frame Data Len fields.
        pHeader =  (PHEADER_802_11) Elem->Msg;
        if (pHeader->FC.SubType & 0x08)
        {
            pMsg2 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H + 2];
        }
        else
        {
            pMsg2 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
	    }
            
        // 1. check Replay Counter coresponds to MSG1.,  otherwise discard
        if (!RTMPEqualMemory(pMsg2->KeyDesc.RCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY))
        {
            DBGPRINT(RT_DEBUG_ERROR, "Replay Counter Different in Msg 2 of 4-way handshake !! \n");
            DBGPRINT(RT_DEBUG_ERROR, "Receive : %d  %d  %d  %d  %d  %d  %d  %d \n", pMsg2->KeyDesc.RCounter[0],pMsg2->KeyDesc.RCounter[1],\
                pMsg2->KeyDesc.RCounter[2],pMsg2->KeyDesc.RCounter[3],pMsg2->KeyDesc.RCounter[4],pMsg2->KeyDesc.RCounter[5],pMsg2->KeyDesc.RCounter[6],pMsg2->KeyDesc.RCounter[7]);
            DBGPRINT(RT_DEBUG_ERROR, "Current : %d  %d  %d  %d  %d  %d  %d  %d \n",pEntry->R_Counter[0],pEntry->R_Counter[1],pEntry->R_Counter[2],pEntry->R_Counter[3],\
                pEntry->R_Counter[4],pEntry->R_Counter[5],pEntry->R_Counter[6],pEntry->R_Counter[7]);
            break;
        }

        // 2. Derive necessary info for counting PTK and thus count PTK
        MICMsgLen = pMsg2->Body_Len[1] | ((pMsg2->Body_Len[0]<<8) && 0xff00);
        MICMsgLen += LENGTH_EAPOL_H;
        if (MICMsgLen > (Elem->MsgLen -LENGTH_802_11 - LENGTH_802_1_H))
        {
            DBGPRINT(RT_DEBUG_ERROR, "Receive wrong format EAPOL packets \n");
            break;        
        }
        NdisMoveMemory(SNonce, pMsg2->KeyDesc.Nonce, LEN_KEY_DESC_NONCE);
        pSA = pEntry->Addr;

        CountPTK(pAdapter->PortCfg.MBSSID[pEntry->ApIdx].PMK,  pEntry->ANonce, pAdapter->PortCfg.MBSSID[pEntry->ApIdx].Bssid, SNonce, pSA, PTK, LEN_PTK); 
        NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK);

		DBGPRINT(RT_DEBUG_TRACE, "PTK-%x %x %x %x %x %x %x %x \n",PTK[0],PTK[1],PTK[2],PTK[3],PTK[4],PTK[5],PTK[6],PTK[7]);
	    DBGPRINT(RT_DEBUG_TRACE, "ANonce1-%x %x %x %x %x %x %x %x \n",pEntry->ANonce[0],pEntry->ANonce[1],pEntry->ANonce[2],pEntry->ANonce[3],pEntry->ANonce[4],pEntry->ANonce[5],pEntry->ANonce[6],pEntry->ANonce[7]);
	    DBGPRINT(RT_DEBUG_TRACE, "ANonce2-%x %x %x %x %x %x %x %x \n",pEntry->ANonce[8],pEntry->ANonce[9],pEntry->ANonce[10],pEntry->ANonce[11],pEntry->ANonce[12],pEntry->ANonce[13],pEntry->ANonce[14],pEntry->ANonce[15]);

        // 3. verify MSG2 MIC, If not valid, discard.
        MICOffset = sizeof(EAPOL_PACKET)-MAX_LEN_OF_RSNIE-2-LEN_KEY_DESC_MIC;
        NdisMoveMemory(OutBuffer, pMsg2, MICMsgLen);  
        NdisZeroMemory((OutBuffer+MICOffset), LEN_KEY_DESC_MIC);
        if (pEntry->WepStatus == Ndis802_11Encryption2Enabled)
        {
            hmac_md5(PTK, LEN_EAP_MICK, OutBuffer, MICMsgLen, mic);
        }
        else
        {
            HMAC_SHA1(OutBuffer,  MICMsgLen, PTK, LEN_EAP_MICK, digest);
            NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
        }
        if (!RTMPEqualMemory((PUCHAR)pMsg2+MICOffset, mic, LEN_KEY_DESC_MIC))
        {
            DBGPRINT(RT_DEBUG_ERROR, "MIC Different in Msg 2 of 4-way handshake!! \n");
            break;
        }
        else
            DBGPRINT(RT_DEBUG_TRACE, "MIC VALID in Msg 2 of 4-way handshake!! \n");
            
        // 4. check RSN IE, if not match, send MLME-DEAUTHENTICATE.
        if (!RTMPEqualMemory(&pMsg2->KeyDesc.Data[2], pEntry->RSN_IE, pEntry->RSNIE_Len))
        {       
            DBGPRINT(RT_DEBUG_ERROR, "RSN_IE Different in Msg 2 of 4-way handshake!! \n");
            DBGPRINT(RT_DEBUG_ERROR, "Receive : %x %x %x %x ...\n",pMsg2->KeyDesc.Data[2], pMsg2->KeyDesc.Data[3],pMsg2->KeyDesc.Data[4],pMsg2->KeyDesc.Data[5] );
            DBGPRINT(RT_DEBUG_ERROR, "Current : %x %x %x %x ...\n",pEntry->RSN_IE[0], pEntry->RSN_IE[1],pEntry->RSN_IE[2],pEntry->RSN_IE[3] );
            break;  
        }
        else
            DBGPRINT(RT_DEBUG_TRACE, "RSN_IE VALID in Msg 2 of 4-way handshake!! \n");
            
        pEntry->WpaState = AS_PTKINIT_NEGOTIATING;

        // Increment replay counter by 1       
        ADD_ONE_To_64BIT_VAR(pAdapter->PortCfg.R_Counter);
        NdisMoveMemory(pEntry->R_Counter, pAdapter->PortCfg.R_Counter, sizeof(pEntry->R_Counter));
            
        // 5. CONSTRUCT msg3
        // 5-0. Init Packet and Fill header
        NdisZeroMemory(&Packet, sizeof(Packet));
        Packet.ProVer = EAPOL_VER;
        Packet.ProType = EAPOLKey;
            
        // Fill replay counter
        NdisMoveMemory(Packet.KeyDesc.RCounter, pEntry->R_Counter, sizeof(pEntry->R_Counter));
          
        // Fill key version, keyinfo, key len
        Packet.KeyDesc.Keyinfo.KeyMic = 1;
        Packet.KeyDesc.Keyinfo.KeyType = PAIRWISEKEY;
        Packet.KeyDesc.Keyinfo.Install = 1;
        Packet.KeyDesc.Keyinfo.KeyAck = 1;
        if ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || (pEntry->AuthMode == Ndis802_11AuthModeWPAPSK))
        {
        	Packet.KeyDesc.Type = WPA1_KEY_DESC;
        	Packet.KeyDesc.DataLen[1] = 0;
        }
        else if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
        {
        	Packet.KeyDesc.Type = WPA2_KEY_DESC;
        	Packet.KeyDesc.DataLen[1] = 0;
        	Packet.KeyDesc.Keyinfo.EKD = 1;
        	Packet.KeyDesc.Keyinfo.Secure = 1;
        }

        if (pEntry->WepStatus == Ndis802_11Encryption2Enabled)
        {
            Packet.KeyDesc.KeyLength[1] = LEN_TKIP_KEY;
        }
        else if (pEntry->WepStatus == Ndis802_11Encryption3Enabled)
        {
            Packet.KeyDesc.KeyLength[1] = LEN_AES_KEY;
        }
        Packet.KeyDesc.Keyinfo.KeyDescVer =
        	(((pEntry->WepStatus == Ndis802_11Encryption3Enabled) || (pAdapter->PortCfg.MBSSID[pEntry->ApIdx].GroupKeyWepStatus == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP));

#ifdef BIG_ENDIAN
{
		USHORT	tmpKeyinfo;

		NdisMoveMemory(&tmpKeyinfo, &Packet.KeyDesc.Keyinfo, sizeof(USHORT)); 
		tmpKeyinfo = SWAP16(tmpKeyinfo);
		NdisMoveMemory(&Packet.KeyDesc.Keyinfo, &tmpKeyinfo, sizeof(USHORT)); 
}

//        *(USHORT *)&Packet.KeyDesc.Keyinfo = SWAP16(*(USHORT *)&Packet.KeyDesc.Keyinfo);
#endif

        // 5-3, Fill in Data, Data Len
        NdisMoveMemory(Packet.KeyDesc.Nonce, pEntry->ANonce, sizeof(pEntry->ANonce));
		NdisZeroMemory(Packet.KeyDesc.MIC, sizeof(Packet.KeyDesc.MIC));
        
        if ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || (pEntry->AuthMode == Ndis802_11AuthModeWPAPSK))
        {
			Packet.KeyDesc.Data[0] = IE_WPA;
			Packet.KeyDesc.Data[1] = pAdapter->PortCfg.MBSSID[pEntry->ApIdx].RSNIE_Len[0];
			Packet.KeyDesc.DataLen[1] = pAdapter->PortCfg.MBSSID[pEntry->ApIdx].RSNIE_Len[0] + 2;
			Packet.Body_Len[1] = 93 + 2 + 2 + pAdapter->PortCfg.MBSSID[pEntry->ApIdx].RSNIE_Len[0];

			NdisMoveMemory(&Packet.KeyDesc.Data[2], pAdapter->PortCfg.MBSSID[pEntry->ApIdx].RSN_IE[0], pAdapter->PortCfg.MBSSID[pEntry->ApIdx].RSNIE_Len[0]);

⌨️ 快捷键说明

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