wpa.c

来自「台湾RALink公司的 rt2570无线 802.11g 网卡的 驱动的源代码 」· C语言 代码 · 共 1,350 行 · 第 1/4 页

C
1,350
字号
        
    ========================================================================
*/
VOID    WpaGroupMsg1Action(
    IN  PRT2570ADAPTER   pAdapter, 
    IN  MLME_QUEUE_ELEM *Elem) 
{
	UCHAR               *OutBuffer = NULL;
	HEADER_802_11       Header_802_11;
	NDIS_STATUS         NStatus;
	UCHAR               AckRate = RATE_2;
	USHORT              AckDuration = 0;
	ULONG               FrameLen = 0;
	UCHAR               EAPHEAD[8] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00,0x88,0x8e};
	EAPOL_PACKET        Packet;
	PEAPOL_PACKET       pGroup;
	UCHAR               Mic[16], OldMic[16];
	UCHAR               GTK[32], Key[32];
	NDIS_802_11_KEY     GroupKey;
	UCHAR MSG[MAX_LEN_OF_MLME_BUFFER];
    
	if(NdisEqualMemory(&Elem->Msg[LENGTH_802_11 + 8], EAPHEAD, LENGTH_802_1_H))
	{
	DBGPRINT(RT_DEBUG_ERROR, "WpaGroupMsg1Action ----->MsgLen=%d\n",Elem->MsgLen);
		NdisMoveMemory(MSG, Elem->Msg, LENGTH_802_11);
		NdisMoveMemory(&MSG[LENGTH_802_11], &Elem->Msg[LENGTH_802_11+8], (Elem->MsgLen ));
	}
	else
	{
	DBGPRINT(RT_DEBUG_ERROR, "WpaGroupMsg1Action ----->2\n");
		NdisMoveMemory(MSG, Elem->Msg, Elem->MsgLen);
	}
	// Process Group message 1 frame.
	pGroup = (PEAPOL_PACKET) &MSG[LENGTH_802_11 + LENGTH_802_1_H];
//	pGroup = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H + 8];//red

    // 1. Verify Replay counter
    //    Check Replay Counter, it has to be larger than last one. No need to be exact one larger
    if (RTMPCompareMemory(pGroup->KeyDesc.ReplayCounter, pAdapter->PortCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1)
	{
		DBGPRINT(RT_DEBUG_ERROR,"Different Replay Counter in Group 2 Handshake\n");
		return;
	}

	// Update new replay counter
	NdisMoveMemory(pAdapter->PortCfg.ReplayCounter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);        

    // 2. Verify MIC is valid
    // Save the MIC and replace with zero
		
    NdisZeroMemory(OldMic, LEN_KEY_DESC_MIC);
    NdisMoveMemory(OldMic, pGroup->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
    NdisZeroMemory(pGroup->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
    if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
    {
        // AES
        UCHAR digest[80];
            
        HMAC_SHA1((PUCHAR) pGroup, pGroup->Len[1] + 4, pAdapter->PortCfg.PTK, LEN_EAP_MICK, digest);
        NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
    }
	else
	{
		hmac_md5(pAdapter->PortCfg.PTK, LEN_EAP_MICK, (PUCHAR) pGroup, 131, Mic);
	}
   
    if (!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC))
    {
        DBGPRINT(RT_DEBUG_ERROR, " MIC Different in group msg 1 of 2-way handshake!!!!!!!!!! \n");
        return;
    }
    else
        DBGPRINT(RT_DEBUG_TEMP, " MIC VALID in group msg 1 of 2-way handshake!!!!!!!!!! \n");

    // 3. Decrypt GTK from Key Data
    if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
    {
        if (pGroup->KeyDesc.KeyInfo.KeyDescVer != 2)
            return;
        // Decrypt AES GTK
        AES_GTK_KEY_UNWRAP(&pAdapter->PortCfg.PTK[16], GTK, pGroup->KeyDesc.KeyData);       
    }
    else    // TKIP
    {
        INT i;
        
        if (pGroup->KeyDesc.KeyInfo.KeyDescVer != 1)
            return;
        // Decrypt TKIP GTK
        // Construct 32 bytes RC4 Key
        NdisMoveMemory(Key, pGroup->KeyDesc.KeyIv, 16);
        NdisMoveMemory(&Key[16], &pAdapter->PortCfg.PTK[16], 16);
        ARCFOUR_INIT(&pAdapter->PrivateInfo.WEPCONTEXT, Key, 32);
        //discard first 256 bytes
        for (i = 0; i < 256; i++)
            ARCFOUR_BYTE(&pAdapter->PrivateInfo.WEPCONTEXT);
        // Decrypt GTK. Becareful, there is no ICV to check the result is correct or not
        ARCFOUR_DECRYPT(&pAdapter->PrivateInfo.WEPCONTEXT, GTK, pGroup->KeyDesc.KeyData, 32);       
    }
    
    // 4. Construct Group Message 2
    pAdapter->Sequence = ((pAdapter->Sequence) + 1) & (MAX_SEQ_NUMBER);
    WpaMacHeaderInit(pAdapter, &Header_802_11, 1, &pAdapter->PortCfg.Bssid);

    // ACK size is 14 include CRC, and its rate is based on real time information
    AckRate = pAdapter->PortCfg.ExpectedACKRate[pAdapter->PortCfg.TxRate];
    AckDuration = RTUSBCalcDuration(pAdapter, AckRate, 14);
    Header_802_11.Controlhead.Duration = pAdapter->PortCfg.Dsifs + AckDuration;
    
    // Zero Group message 1 body
    NdisZeroMemory(&Packet, sizeof(Packet));
    Packet.Version = EAPOL_VER;
    Packet.Type    = EAPOLKey;
    Packet.Len[1]  = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE;     // No data field
    
    //
    // Group Message 2 as  EAPOL-Key(1,0,0,0,G,0,0,MIC,0)
    //
    Packet.KeyDesc.Type = RSN_KEY_DESC;
    
    // Key descriptor version and appropriate RSN IE
    Packet.KeyDesc.KeyInfo.KeyDescVer = pGroup->KeyDesc.KeyInfo.KeyDescVer;

    // Key Type Group key
    Packet.KeyDesc.KeyInfo.KeyType = 0;

    // KeyMic field presented
    Packet.KeyDesc.KeyInfo.KeyMic  = 1;

    // Secure bit is 1
    Packet.KeyDesc.KeyInfo.Secure  = 1;
    
    // Key Replay count 
    NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);       
    // Out buffer for transmitting group message 2      
    NStatus = MlmeAllocateMemory(pAdapter, (PVOID)&OutBuffer);  //Get an unused nonpaged memory
    if (NStatus != NDIS_STATUS_SUCCESS)
        return;                 

    // Prepare EAPOL frame for MIC calculation
    // Be careful, only EAPOL frame is counted for MIC calculation
    MakeOutgoingFrame(OutBuffer, &FrameLen,
        Packet.Len[1] + 4 , &Packet,
        END_OF_ARGS);

    // Prepare and Fill MIC value
    NdisZeroMemory(Mic, sizeof(Mic));
    if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
    {
        // AES
        UCHAR digest[80];
            
        HMAC_SHA1(OutBuffer, FrameLen, pAdapter->PortCfg.PTK, LEN_EAP_MICK, digest);
        NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
    }
    else
    {            
        hmac_md5(pAdapter->PortCfg.PTK, LEN_EAP_MICK, OutBuffer, FrameLen, Mic);
    }
    NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);

    FrameLen = 0;   

    MakeOutgoingFrame(OutBuffer, &FrameLen, sizeof(MACHDR), &Header_802_11,
//    	 8,pTempIvEiv,
        sizeof(EAPHEAD), EAPHEAD, 
        Packet.Len[1] + 4, &Packet,
        END_OF_ARGS);	

    // 5. Copy frame to Tx ring and prepare for encryption
     WpaHardEncrypt(pAdapter, OutBuffer, FrameLen);

    // 6 Free allocated memory
    MlmeFreeMemory(pAdapter, OutBuffer);
    
    // 6. Update GTK
    NdisZeroMemory(&GroupKey, sizeof(GroupKey));
    GroupKey.Length    = sizeof(GroupKey);
    GroupKey.KeyIndex  = 0x80000000 | pGroup->KeyDesc.KeyInfo.KeyIndex;           
    GroupKey.KeyLength = 16;
    NdisMoveMemory(GroupKey.BSSID, pAdapter->PortCfg.Bssid.Octet, 6);
    NdisMoveMemory(GroupKey.KeyMaterial, GTK, 32);
    // Call Add peer key function
    RTMPWPAAddKeyProc(pAdapter, &GroupKey);
    
    DBGPRINT(RT_DEBUG_TRACE, "WpaGroupMsg1Action <-----\n");
}
/*
    ========================================================================
    
    Routine Description:
        Init WPA MAC header

    Arguments:
        pAdapter    Pointer to our adapter
        
    Return Value:
        None
        
    Note:
        
    ========================================================================
*/
VOID    WpaMacHeaderInit(
    IN      PRT2570ADAPTER   pAd, 
    IN OUT  PHEADER_802_11  Hdr, 
    IN      UCHAR           wep, 
    IN      PMACADDR        pAddr1) 
{
    NdisZeroMemory(Hdr, sizeof(HEADER_802_11));
    Hdr->Controlhead.Frame.Type = BTYPE_DATA;   
    Hdr->Controlhead.Frame.ToDs = 1;
    if (wep == 1)
        Hdr->Controlhead.Frame.Wep = 1;
    
     // Addr1: DA, Addr2: BSSID, Addr3: SA
    COPY_MAC_ADDR(&Hdr->Controlhead.Addr1, pAddr1);
    COPY_MAC_ADDR(&Hdr->Controlhead.Addr2, &pAd->CurrentAddress);
    COPY_MAC_ADDR(&Hdr->Addr3, &pAd->PortCfg.Bssid);
    Hdr->Sequence = pAd->Sequence;      
}

/*
    ========================================================================

    Routine Description:
        Copy frame from waiting queue into relative ring buffer and set 
    appropriate ASIC register to kick hardware encryption before really
    sent out to air.
        
    Arguments:
        pAdapter        Pointer to our adapter
        PNDIS_PACKET    Pointer to outgoing Ndis frame
        NumberOfFrag    Number of fragment required
        
    Return Value:
        None

    Note:
    
    ========================================================================
*/
VOID    WpaHardEncrypt(
    IN  PRT2570ADAPTER   pAdapter,
    IN  PUCHAR          pPacket,
    IN  ULONG           Len)
{
	CHAR                 *OutBuffer = NULL;
	UCHAR           FrameGap;
	PUCHAR          pDest;
	PUCHAR          pSrc;
	ULONG           Iv16;
	ULONG           Iv32;
	PWPA_KEY        pWpaKey;
	NDIS_STATUS           NStatus;

	NStatus = MlmeAllocateMemory(pAdapter, (PVOID)&OutBuffer);  //Get an unused nonpaged memory
	if (NStatus != NDIS_STATUS_SUCCESS) 
	{
		DBGPRINT(RT_DEBUG_TRACE, "WPA - WpaHardEncrypt allocate memory failed\n");
		pAdapter->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
		MlmeCntlConfirm(pAdapter, MT2_DISASSOC_CONF, MLME_FAIL_NO_RESOURCE);
		return;
	}
	
	FrameGap = IFS_BACKOFF;     // Default frame gap mode
	pDest = (PUCHAR)OutBuffer;
	pSrc = pPacket; // Point to start of MSDU
    
	// outgoing frame always wakeup PHY to prevent frame lost and 
	// turn off PSM bit to improve performance
	if (pAdapter->PortCfg.Psm == PWR_SAVE)
	{
		MlmeSetPsmBit(pAdapter, PWR_ACTIVE);
	}
	AsicForceWakeup(pAdapter);
    
	pWpaKey = (PWPA_KEY) &pAdapter->PortCfg.PairwiseKey[0];
	pWpaKey->Type = PAIRWISE_KEY;
	if (pWpaKey->KeyLen == 0)
	{
		// No pairwise key, this should not happen
		//NdisReleaseSpinLock(&pAdapter->TxRingLock);
		DBGPRINT(RT_DEBUG_ERROR,"no pairwise key\n");
		return;
	}

	if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption2Enabled)
	{
		INT     i = 0;
		// Start CALCULATE MIC Value
		RTMPInitMICEngine(
		                pAdapter,
		                pWpaKey->Key,
				pSrc + 4,
				pSrc + 10,
				pWpaKey->TxMic);
		
		NdisMoveMemory(pDest, pSrc, LENGTH_802_11);
		pDest += LENGTH_802_11;
		pSrc += LENGTH_802_11;
		RTMPTkipAppend(&pAdapter->PrivateInfo.Tx, pSrc, (Len - LENGTH_802_11));
		RTMPTkipGetMIC(&pAdapter->PrivateInfo.Tx);
		//pAdapter->PrivateInfo.Tx.MIC[3]++;
		// Prepare IV, EIV, IV offset, Key for hardware encryption
		RTMPInitTkipEngine(
			pAdapter,
			pWpaKey->Key,
			0,
			pAdapter->CurrentAddress,
			pWpaKey->TxMic,
			pWpaKey->TxTsc,
			1,
			&Iv16,
			&Iv32,
			pDest);

		// Increase TxTsc value for next transmission
		while (++pWpaKey->TxTsc[i] == 0x0)
		{
			i++;
			if (i == 6)
			break;
		}

		if (i == 6)
		{
			// TODO: TSC has done one full cycle, do re-keying stuff follow specs
			// Should send a special event microsoft defined to request re-key
		}
            
		pDest += 8;
            
		RTMPTkipEncryptData(pAdapter, pSrc, pDest, (Len-LENGTH_802_11));
		pDest +=  (Len-LENGTH_802_11);
		//printk("-4\n");

		RTMPTkipEncryptData(pAdapter, pAdapter->PrivateInfo.Tx.MIC, pDest, 8);

⌨️ 快捷键说明

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