wpa.c

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

C
1,629
字号
			// 5-4, First make a frame for Counting MIC.
			MakeOutgoingFrame(OutBuffer,            &FrameLen,
			    Packet.Body_Len[1] + 4,  &Packet,
			    END_OF_ARGS);
			NdisZeroMemory(mic, sizeof(mic));

			// 5-5, count MIC
			if (pEntry->WepStatus == Ndis802_11Encryption3Enabled)
			{
				UCHAR digest[80];
				HMAC_SHA1(OutBuffer,  FrameLen, PTK, LEN_EAP_MICK, digest);
				NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
			}
			else
			{
				hmac_md5(PTK,  LEN_EAP_MICK, OutBuffer, FrameLen, mic);
			}
			NdisMoveMemory(&Packet.KeyDesc.MIC, mic, LEN_KEY_DESC_MIC);
        }
        else if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
        {
        	UCHAR       GTK[TKIP_GTK_LENGTH],/*pRc4GTK[512],*/ mic[LEN_KEY_DESC_MIC];
			UCHAR       ekey[(LEN_KEY_DESC_IV+LEN_EAP_EK)], /*Key_Data[512],*/ key_length, RSNIE_Len;

			NdisMoveMemory(Packet.KeyDesc.RSC, pAdapter->PortCfg.MBSSID[pEntry->ApIdx].SharedKey[pAdapter->PortCfg.MBSSID[pEntry->ApIdx].DefaultKeyId].TxTsc, 6);

			CountGTK(pAdapter->PortCfg.MBSSID[pEntry->ApIdx].GMK, (UCHAR*)pAdapter->PortCfg.MBSSID[pEntry->ApIdx].GNonce, pAdapter->PortCfg.MBSSID[pEntry->ApIdx].Bssid, GTK, TKIP_GTK_LENGTH);

	        NdisMoveMemory(pAdapter->PortCfg.MBSSID[pEntry->ApIdx].SharedKey[pAdapter->PortCfg.MBSSID[pEntry->ApIdx].DefaultKeyId].Key, GTK, LEN_TKIP_EK);
	        NdisMoveMemory(pAdapter->PortCfg.MBSSID[pEntry->ApIdx].SharedKey[pAdapter->PortCfg.MBSSID[pEntry->ApIdx].DefaultKeyId].TxMic, &GTK[16], LEN_TKIP_TXMICK);
	        NdisMoveMemory(pAdapter->PortCfg.MBSSID[pEntry->ApIdx].SharedKey[pAdapter->PortCfg.MBSSID[pEntry->ApIdx].DefaultKeyId].RxMic, &GTK[24], LEN_TKIP_RXMICK);
	        DBGPRINT(RT_DEBUG_INFO, "WPA2 Group Key ID  = %d\n", pAdapter->PortCfg.MBSSID[pEntry->ApIdx].DefaultKeyId);
	        DBGPRINT(RT_DEBUG_INFO, "G_Key :%x %x %x %x %x %x %x %x \n",GTK[0],GTK[1],GTK[2],GTK[3],GTK[4],GTK[5],GTK[6],GTK[7]);
	        DBGPRINT(RT_DEBUG_INFO, "       %x %x %x %x %x %x %x %x \n",GTK[8],GTK[9],GTK[10],GTK[11],GTK[12],GTK[13],GTK[14],GTK[15]);
	        DBGPRINT(RT_DEBUG_INFO, "TX Mic:%x %x %x %x %x %x %x %x \n",GTK[16],GTK[17],GTK[18],GTK[19],GTK[20],GTK[21],GTK[22],GTK[23]);
	        DBGPRINT(RT_DEBUG_INFO, "RX Mic:%x %x %x %x %x %x %x %x \n",GTK[24],GTK[25],GTK[26],GTK[27],GTK[28],GTK[29],GTK[30],GTK[31]);

	        if (pAdapter->PortCfg.MBSSID[pEntry->ApIdx].GroupKeyWepStatus == Ndis802_11Encryption2Enabled)
                pAdapter->PortCfg.MBSSID[pEntry->ApIdx].SharedKey[pAdapter->PortCfg.MBSSID[pEntry->ApIdx].DefaultKeyId].CipherAlg = CIPHER_TKIP;
            else if (pAdapter->PortCfg.MBSSID[pEntry->ApIdx].GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
                pAdapter->PortCfg.MBSSID[pEntry->ApIdx].SharedKey[pAdapter->PortCfg.MBSSID[pEntry->ApIdx].DefaultKeyId].CipherAlg = CIPHER_AES;
            else
                pAdapter->PortCfg.MBSSID[pEntry->ApIdx].SharedKey[pAdapter->PortCfg.MBSSID[pEntry->ApIdx].DefaultKeyId].CipherAlg = CIPHER_NONE;
              
            // install Group Key to MAC ASIC
            AsicAddSharedKeyEntry(
                pAdapter, 
                pEntry->ApIdx, 
                pAdapter->PortCfg.MBSSID[pEntry->ApIdx].DefaultKeyId, 
                pAdapter->PortCfg.MBSSID[pEntry->ApIdx].SharedKey[pAdapter->PortCfg.MBSSID[pEntry->ApIdx].DefaultKeyId].CipherAlg, 
                pAdapter->PortCfg.MBSSID[pEntry->ApIdx].SharedKey[pAdapter->PortCfg.MBSSID[pEntry->ApIdx].DefaultKeyId].Key, 
                pAdapter->PortCfg.MBSSID[pEntry->ApIdx].SharedKey[pAdapter->PortCfg.MBSSID[pEntry->ApIdx].DefaultKeyId].TxMic, 
                pAdapter->PortCfg.MBSSID[pEntry->ApIdx].SharedKey[pAdapter->PortCfg.MBSSID[pEntry->ApIdx].DefaultKeyId].RxMic);

	        NdisZeroMemory(Key_Data, 512); //sizeof(Key_Data));

			if ((pAdapter->PortCfg.MBSSID[pEntry->ApIdx].AuthMode == Ndis802_11AuthModeWPAPSKWPA2PSK) ||
				(pAdapter->PortCfg.MBSSID[pEntry->ApIdx].AuthMode == Ndis802_11AuthModeWPA1WPA2))
			{
				RSNIE_Len = pAdapter->PortCfg.MBSSID[pEntry->ApIdx].RSNIE_Len[1];
	        	NdisMoveMemory(&Key_Data[2], pAdapter->PortCfg.MBSSID[pEntry->ApIdx].RSN_IE[1], RSNIE_Len);
			}
			else
			{
				RSNIE_Len = pAdapter->PortCfg.MBSSID[pEntry->ApIdx].RSNIE_Len[0];
		        NdisMoveMemory(&Key_Data[2], &pAdapter->PortCfg.MBSSID[pEntry->ApIdx].RSN_IE[0], RSNIE_Len);
			}

			Packet.Body_Len[1] = 2+RSNIE_Len;

			Key_Data[0] = IE_WPA2;
        	Key_Data[1] = RSNIE_Len;

			// Key Data Encapsulation format
        	Key_Data[2+RSNIE_Len+0] = 0xDD;
        	Key_Data[2+RSNIE_Len+2] = 0x00;
        	Key_Data[2+RSNIE_Len+3] = 0x0F;
        	Key_Data[2+RSNIE_Len+4] = 0xAC;
        	Key_Data[2+RSNIE_Len+5] = 0x01;

			// GTK Key Data Encapsulation format
        	Key_Data[2+RSNIE_Len+6] = (pAdapter->PortCfg.MBSSID[pEntry->ApIdx].DefaultKeyId & 0x03);
			Key_Data[2+RSNIE_Len+7] = 0x00;

			// handle the difference between TKIP and AES-CCMP
			if (pAdapter->PortCfg.MBSSID[pEntry->ApIdx].GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
	        {
	        	Key_Data[2+RSNIE_Len+1] = 0x16;// 4+2+16(OUI+GTK+GTKKEY)
	        	NdisMoveMemory(&Key_Data[2+RSNIE_Len+8], GTK, LEN_AES_KEY);
	        	Packet.Body_Len[1] += 8+LEN_AES_KEY;
			}
			else
			{
				Key_Data[2+RSNIE_Len+1] = 0x26;// 4+2+32(OUI+GTK+GTKKEY)
				NdisMoveMemory(&Key_Data[2+RSNIE_Len+8], GTK, TKIP_GTK_LENGTH);
	        	Packet.Body_Len[1] += 8+TKIP_GTK_LENGTH;
			}

			// Still dont know why, but if not append will occur "GTK not include in MSG3"
			// Patch for compatibility between zero config and funk
			if (pAdapter->PortCfg.MBSSID[pEntry->ApIdx].GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
			{
				Key_Data[2+RSNIE_Len+8+TKIP_GTK_LENGTH] = 0xDD;
				Key_Data[2+RSNIE_Len+8+TKIP_GTK_LENGTH+1] = 0;
				Packet.Body_Len[1] += 2;
			}
			else
			{
				Key_Data[2+RSNIE_Len+8+TKIP_GTK_LENGTH] = 0xDD;
				Key_Data[2+RSNIE_Len+8+TKIP_GTK_LENGTH+1] = 0;
				Key_Data[2+RSNIE_Len+8+TKIP_GTK_LENGTH+2] = 0;
				Key_Data[2+RSNIE_Len+8+TKIP_GTK_LENGTH+3] = 0;
				Key_Data[2+RSNIE_Len+8+TKIP_GTK_LENGTH+4] = 0;
				Key_Data[2+RSNIE_Len+8+TKIP_GTK_LENGTH+5] = 0;
				Packet.Body_Len[1] += 6;
			}

        	key_length = Packet.Body_Len[1];
        	Packet.KeyDesc.DataLen[1] = key_length;
        	Packet.Body_Len[1] += 93 + 2; 

	        NdisZeroMemory(mic, sizeof(mic));

	        // count MIC
	        if (pEntry->WepStatus == Ndis802_11Encryption3Enabled)
	        {
	            AES_GTK_KEY_WRAP(&pEntry->PTK[16], Key_Data, key_length, pRc4GTK);
	            // AES wrap function will grow 8 bytes in length
	            NdisMoveMemory(Packet.KeyDesc.Data, pRc4GTK, (key_length + 8));
	            Packet.Body_Len[1] += 8;
	            Packet.KeyDesc.DataLen[1] += 8;
	            MakeOutgoingFrame(OutBuffer,            &FrameLen,
	                            Packet.Body_Len[1] + 4, &Packet,
	                            END_OF_ARGS);

	            HMAC_SHA1(OutBuffer, FrameLen, pEntry->PTK, LEN_EAP_MICK, digest);
	            NdisMoveMemory(Packet.KeyDesc.MIC, digest, LEN_KEY_DESC_MIC);
 	        }
	        else
	        {
	            // PREPARE Encrypted  "Key DATA" field.  (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV)
	            // put TxTsc in Key RSC field
	            pAdapter->PrivateInfo.FCSCRC32 = PPPINITFCS32;   //Init crc32.

	            // ekey is the contanetion of IV-field, and PTK[16]->PTK[31]
	            NdisMoveMemory(ekey, Packet.KeyDesc.IV, LEN_KEY_DESC_IV);
	            NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &pEntry->PTK[16], LEN_EAP_EK);
	            ARCFOUR_INIT(&pAdapter->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey));  //INIT SBOX, KEYLEN+3(IV)
	            pAdapter->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAdapter->PrivateInfo.FCSCRC32, Key_Data, key_length);
	            WPAARCFOUR_ENCRYPT(&pAdapter->PrivateInfo.WEPCONTEXT, pRc4GTK,Key_Data, key_length);
	            NdisMoveMemory(Packet.KeyDesc.Data, pRc4GTK, key_length);

	            // make a frame for Countint MIC,
	            MakeOutgoingFrame(OutBuffer,            &FrameLen,
	                            Packet.Body_Len[1] + 4, &Packet,
	                            END_OF_ARGS);

	            hmac_md5(pEntry->PTK, LEN_EAP_MICK, OutBuffer, FrameLen, mic);
	            NdisMoveMemory(Packet.KeyDesc.MIC, mic, LEN_KEY_DESC_MIC);
	        }
        }
            
        // 5-6, Make outgoing frame
        WPAMake8023Hdr(pAdapter, pEntry, Header802_3);
        MakeOutgoingFrame(OutBuffer,            &FrameLen,
                            LENGTH_802_3,            Header802_3,
                            Packet.Body_Len[1] + 4,  &Packet,
                            END_OF_ARGS);
            
        DBGPRINT(RT_DEBUG_TRACE, "RTMPToWirelessSta : ETHTYPE = %x %x FrameLen = %d! \n",Header802_3[12],Header802_3[13],FrameLen);

        RTMPToWirelessSta(pAdapter, OutBuffer, FrameLen);

        // Should start from 1, init is 0
		pEntry->ReTryCounter = PEER_MSG3_RETRY_TIMER_CTR;
		pEntry->RetryTimer.expires = jiffies + PEER_MSG3_RETRY_EXEC_INTV;
		pEntry->RetryTimerRunning = TRUE;
        mod_timer(&pEntry->RetryTimer, pEntry->RetryTimer.expires);
		DBGPRINT(RT_DEBUG_TRACE, "Send Msg3 and setup timeout timer\n");

        pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
    }while(FALSE);

	kfree(mpool);
}

/*
    ==========================================================================
    Description:
        countermeasures active attack timer execution
    Return:
    ==========================================================================
*/
VOID CMTimerExec(
    IN  unsigned long data) 
{
    UINT            i, j=0, apidx;
    RTMP_ADAPTER    *pAdapter = (RTMP_ADAPTER *)data;
        
    for (apidx = 0; apidx < pAdapter->PortCfg.BssidNum; apidx++)
    {
        pAdapter->PortCfg.MBSSID[apidx].BANClass3Data = FALSE;
    }

    for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++)
    {
        if ((pAdapter->MacTab.Content[i].Valid == TRUE) && (pAdapter->MacTab.Content[i].CMTimerRunning == TRUE))
        {
            pAdapter->MacTab.Content[i].CMTimerRunning = FALSE;
            j++;
        }
    }

    if (j > 1)
        DBGPRINT(RT_DEBUG_ERROR, "Find more than one entry which generated MIC Fail ..  \n");

    pAdapter->PortCfg.CMTimerRunning = FALSE;
}
    
VOID WPARetryExec(
    IN  unsigned long data) 
{
    MAC_TABLE_ENTRY     *pEntry = (PMAC_TABLE_ENTRY) data;
    
    if ((pEntry) && (pEntry->RetryTimerRunning == TRUE))
    {
    	RTMP_ADAPTER		*pAdapter = (PRTMP_ADAPTER)pEntry->pAd;
    	
        // Turn off the retry flag first
        pEntry->RetryTimerRunning = FALSE;  
        DBGPRINT(RT_DEBUG_TRACE, "WPARetryExec - ReTryCounter=%d, WpaState=%d \n", pEntry->ReTryCounter, pEntry->WpaState);

        switch (pEntry->AuthMode)
        {
            case Ndis802_11AuthModeWPA:
            case Ndis802_11AuthModeWPAPSK:
            case Ndis802_11AuthModeWPA2:
            case Ndis802_11AuthModeWPA2PSK:
                //  1.   GTK already retried, give up and disconnect client.
                if (pEntry->ReTryCounter > (GRP_HS_RETRY_TIMER_CTR + 1))
                {    
					// Deauthenticate and delete timer and entry
					DisAssocAction(pAdapter, pEntry, SUBTYPE_DISASSOC, REASON_GROUP_KEY_UPDATE_TIMEOUT);
                    DBGPRINT(RT_DEBUG_TRACE, "Delete client after GTK retry failed\n");
                }
				// 2. Retry GTK.
                else if (pEntry->ReTryCounter >= GRP_HS_RETRY_TIMER_CTR)
                {
                    DBGPRINT(RT_DEBUG_TRACE, "ReInitilize 2-way group-key Handshake ===> \n");
                    WPAHardTransmit( pAdapter,  pEntry);
	                pEntry->RetryTimer.expires = jiffies + WPA_RETRY_EXEC_INTV;
    				mod_timer(&pEntry->RetryTimer, pEntry->RetryTimer.expires);
					pEntry->ReTryCounter++;
                    pEntry->RetryTimerRunning = TRUE;  
                }
				// 3. 4-way message 1 retried more than three times. Disconnect client
                else if (pEntry->ReTryCounter > (PEER_MSG1_RETRY_TIMER_CTR + 3))                
                {   
					// Deauthenticate and delete timer and entry
					DisAssocAction(pAdapter, pEntry, SUBTYPE_DEAUTH, REASON_UNSPECIFY);
                    DBGPRINT(RT_DEBUG_TRACE, "Delete client after 3 retries of message_1 \n");
                }
				// 4. Retry 4 way message 1, the last try, the timeout is 5 sec for EAPOL-Start
                else if (pEntry->ReTryCounter == (PEER_MSG1_RETRY_TIMER_CTR + 3))                
                {
                    DBGPRINT(RT_DEBUG_TRACE, "Message 1 time out, the last retry\n");
	              pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
	                pEntry->WpaState = AS_INITPSK;
	                pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
	                pEntry->RetryTimer.expires = jiffies + (5 * HZ);
                    WPAStart4WayHS(pAdapter, pEntry);
                }
				// 4. Retry 4 way message 1
                else if (pEntry->ReTryCounter < (PEER_MSG1_RETRY_TIMER_CTR + 3))                
                {
                    DBGPRINT(RT_DEBUG_TRACE, "Message 1 time out, retry it\n");
	                pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
	                pEntry->WpaState = AS_INITPSK;
	                pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
	                pEntry->RetryTimer.expires = jiffies + WPA_RETRY_EXEC_INTV;
                    WPAStart4WayHS(pAdapter, pEntry);
                }
                break;

            default:
                break;
        }        
    }
}

/*
    ==========================================================================
    Description:
        When receiving the last packet of 4-way pairwisekey handshake.
        Initilize 2-way groupkey handshake following.
    Return:
    ==========================================================================
*/
VOID Wpa1PeerPairMsg4Action(
    IN PRTMP_ADAPTER    pAdapter, 
    IN MAC_TABLE_ENTRY  *pEntry,
    IN MLME_QUEUE_ELEM  *Elem) 
{
    UCHAR               mic[LEN_KEY_DESC_MIC], digest[80];
    ULONG               MICMsgLen;
    EAPOL_PACKET        EAPOLPKT;
    PEAPOL_PACKET       pMsg4;
    NDIS_STATUS         Status;
    PHEADER_802_11      pHeader;
    UCHAR               Offset = 0;

    DBGPRINT(RT_DEBUG_TRACE, "WpaEAPOL Peer Pair Msg4 Action ===>\n");

    if (!pEntry)
    	return;

    if (pEntry->WpaState < AS_PTKINIT_NEGOTIATING)
        return;

    pHeader = (PHEADER_802_11) Elem->Msg;

    if (pHeader->FC.SubType & 0x08)
        Offset += 2;
    
    pMsg4 = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H + Offset

⌨️ 快捷键说明

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