예제 #1
0
VOID	WpaMicFailureReportFrame(
	IN  PRTMP_ADAPTER   pAd,
	IN MLME_QUEUE_ELEM *Elem)
{
	PUCHAR              pOutBuffer = NULL;
	UCHAR               Header802_3[14];
	ULONG               FrameLen = 0;
	UCHAR				*mpool;
	PEAPOL_PACKET       pPacket;
	UCHAR               Mic[16];
    BOOLEAN             bUnicast;
        
	DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame ----->\n"));

    bUnicast = (Elem->Msg[0] == 1 ? TRUE:FALSE);
	pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER);

	/* init 802.3 header and Fill Packet */
	MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);	

	/* Allocate memory for output */
	os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER);
	if (mpool == NULL)
    {
        DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__));
        return;
    }

	pPacket = (PEAPOL_PACKET)mpool;
	NdisZeroMemory(pPacket, TX_EAPOL_BUFFER);
	
	pPacket->ProVer	= EAPOL_VER;
	pPacket->ProType	= EAPOLKey;
	
	pPacket->KeyDesc.Type = WPA1_KEY_DESC;

    /* Request field presented */
    pPacket->KeyDesc.KeyInfo.Request = 1;
    
	if(pAd->StaCfg.WepStatus  == Ndis802_11Encryption3Enabled)
	{
		pPacket->KeyDesc.KeyInfo.KeyDescVer = 2;
	} 
	else	  /* TKIP */
	{
		pPacket->KeyDesc.KeyInfo.KeyDescVer = 1;
	}

    pPacket->KeyDesc.KeyInfo.KeyType = (bUnicast ? PAIRWISEKEY : GROUPKEY);

	/* KeyMic field presented */
	pPacket->KeyDesc.KeyInfo.KeyMic  = 1;

    /* Error field presented */
	pPacket->KeyDesc.KeyInfo.Error  = 1;
    
	/* Update packet length after decide Key data payload */
	SET_UINT16_TO_ARRARY(pPacket->Body_Len, MIN_LEN_OF_EAPOL_KEY_MSG)

	/* Key Replay Count */
	NdisMoveMemory(pPacket->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY);
    inc_byte_array(pAd->StaCfg.ReplayCounter, 8);

	/* Convert to little-endian format. */
	*((USHORT *)&pPacket->KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&pPacket->KeyDesc.KeyInfo));


	MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer);  /* allocate memory */
	if(pOutBuffer == NULL)
	{
		os_free_mem(NULL, mpool);
		return;
	}
    
	/*
	   Prepare EAPOL frame for MIC calculation
	   Be careful, only EAPOL frame is counted for MIC calculation
	*/
	MakeOutgoingFrame(pOutBuffer,               &FrameLen,
		              CONV_ARRARY_TO_UINT16(pPacket->Body_Len) + 4,   pPacket,
		              END_OF_ARGS);

	/* Prepare and Fill MIC value */
	NdisZeroMemory(Mic, sizeof(Mic));
	if(pAd->StaCfg.WepStatus  == Ndis802_11Encryption3Enabled)
	{	/* AES */
        UCHAR digest[20] = {0};
		RT_HMAC_SHA1(pAd->StaCfg.PTK, LEN_PTK_KCK, pOutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE);
		NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
	} 
	else
	{	/* TKIP */
		RT_HMAC_MD5(pAd->StaCfg.PTK, LEN_PTK_KCK, pOutBuffer, FrameLen, Mic, MD5_DIGEST_SIZE);
	}
	NdisMoveMemory(pPacket->KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);

	/* copy frame to Tx ring and send MIC failure report frame to authenticator */
	RTMPToWirelessSta(pAd, &pAd->MacTab.Content[BSSID_WCID],
					  Header802_3, LENGTH_802_3, 
					  (PUCHAR)pPacket, 
					  CONV_ARRARY_TO_UINT16(pPacket->Body_Len) + 4, FALSE);

	MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);

	os_free_mem(NULL, mpool);

	DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame <-----\n"));
}
예제 #2
0
파일: ap_wpa.c 프로젝트: 23171580/ralink
VOID RTMPHandleSTAKey(
    IN PRTMP_ADAPTER    pAd, 
    IN PMAC_TABLE_ENTRY	pEntry,
    IN MLME_QUEUE_ELEM  *Elem) 
{
	extern UCHAR		OUI_WPA2_WEP40[];
	ULONG				FrameLen = 0;
	PUCHAR				pOutBuffer = NULL;
	UCHAR				Header802_3[14];
	UCHAR				*mpool;
	PEAPOL_PACKET		pOutPacket;
	PEAPOL_PACKET		pSTAKey;
	PHEADER_802_11		pHeader;
	UCHAR				Offset = 0;
	ULONG				MICMsgLen;
	UCHAR				DA[MAC_ADDR_LEN];
	UCHAR				Key_Data[512];
	UCHAR				key_length;
	UCHAR				mic[LEN_KEY_DESC_MIC];
	UCHAR				rcv_mic[LEN_KEY_DESC_MIC];
	UCHAR				digest[80];
	UCHAR				temp[64];
	PMAC_TABLE_ENTRY	pDaEntry;

	/*Benson add for big-endian 20081016--> */
	KEY_INFO			peerKeyInfo;
	/*Benson add 20081016 <-- */
	
	DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleSTAKey\n"));

	if (!pEntry)
		return;
	
	if ((pEntry->WpaState != AS_PTKINITDONE))
	{
		DBGPRINT(RT_DEBUG_ERROR, ("Not expect calling STAKey hand shaking here"));
		return;
	}

    pHeader = (PHEADER_802_11) Elem->Msg;

	/* QoS control field (2B) is took off */
/*    if (pHeader->FC.SubType & 0x08) */
/*        Offset += 2; */
    
	pSTAKey = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H + Offset];	
	/*Benson add for big-endian 20081016--> */
	NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo));
	NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pSTAKey->KeyDesc.KeyInfo, sizeof(KEY_INFO));
	*((USHORT *)&peerKeyInfo) = cpu2le16(*((USHORT *)&peerKeyInfo));
	/*Benson add 20081016 <-- */
	
    /* Check Replay Counter */
    if (!RTMPEqualMemory(pSTAKey->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY))
    {
        DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in STAKey handshake!! \n"));
        DBGPRINT(RT_DEBUG_ERROR, ("Receive : %d %d %d %d  \n",
				pSTAKey->KeyDesc.ReplayCounter[0],
				pSTAKey->KeyDesc.ReplayCounter[1],
				pSTAKey->KeyDesc.ReplayCounter[2],
				pSTAKey->KeyDesc.ReplayCounter[3]));
        DBGPRINT(RT_DEBUG_ERROR, ("Current : %d %d %d %d  \n",
				pEntry->R_Counter[4],pEntry->R_Counter[5],
				pEntry->R_Counter[6],pEntry->R_Counter[7]));
        return;
    }

    /* Check MIC, if not valid, discard silently */
    NdisMoveMemory(DA, &pSTAKey->KeyDesc.KeyData[6], MAC_ADDR_LEN);

	if (peerKeyInfo.KeyMic && peerKeyInfo.Secure && peerKeyInfo.Request)/*Benson add for big-endian 20081016 --> */
	{
		pEntry->bDlsInit = TRUE;
		DBGPRINT(RT_DEBUG_TRACE, ("STAKey Initiator: %02x:%02x:%02x:%02x:%02x:%02x\n",
					PRINT_MAC(pEntry->Addr)));
	}


    MICMsgLen = pSTAKey->Body_Len[1] | ((pSTAKey->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"));
        return;        
    }

	/* This is proprietary DLS protocol, it will be adhered when spec. is finished. */
	NdisZeroMemory(temp, 64);
	NdisZeroMemory(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, sizeof(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK));
	NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32);

	WpaDerivePTK(pAd, temp, temp, pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, temp,
				pEntry->Addr, pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK);
	DBGPRINT(RT_DEBUG_TRACE, ("PTK-%x %x %x %x %x %x %x %x \n",
			pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[0],
			pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[1],
			pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[2],
			pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[3],
			pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[4],
			pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[5],
			pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[6],
			pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[7]));


	/* Record the received MIC for check later */
	NdisMoveMemory(rcv_mic, pSTAKey->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
	NdisZeroMemory(pSTAKey->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
    if (pEntry->WepStatus == Ndis802_11TKIPEnable)
    {
        RT_HMAC_MD5(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK_KCK, (PUCHAR)pSTAKey, MICMsgLen, mic, MD5_DIGEST_SIZE);
    }
    else
    {
        RT_HMAC_SHA1(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK_KCK, (PUCHAR)pSTAKey,  MICMsgLen, digest, SHA1_DIGEST_SIZE);
        NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
    }

    if (!RTMPEqualMemory(rcv_mic, mic, LEN_KEY_DESC_MIC))
    {
        DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in STAKey handshake!! \n"));
        return;
    }
    else
        DBGPRINT(RT_DEBUG_TRACE, ("MIC VALID in STAKey handshake!! \n"));

	/* Receive init STA's STAKey Message-2, and terminate the handshake */
	/*if (pEntry->bDlsInit && !pSTAKey->KeyDesc.KeyInfo.Request) */
	if (pEntry->bDlsInit && !peerKeyInfo.Request) /*Benson add for big-endian 20081016 --> */
	{
		pEntry->bDlsInit = FALSE;
		DBGPRINT(RT_DEBUG_TRACE, ("Receive init STA's STAKey Message-2, STAKey handshake finished \n"));
		return;
	}

	/* Receive init STA's STAKey Message-2, and terminate the handshake */
	if (RTMPEqualMemory(&pSTAKey->KeyDesc.KeyData[2], OUI_WPA2_WEP40, 3))
	{
		DBGPRINT(RT_DEBUG_WARN, ("Receive a STAKey message which not support currently, just drop it \n"));
		return;
	}
	
    do
    {
    	pDaEntry = MacTableLookup(pAd, DA);
    	if (!pDaEntry)
    		break;

    	if ((pDaEntry->WpaState != AS_PTKINITDONE))
	    {
	        DBGPRINT(RT_DEBUG_ERROR, ("Not expect calling STAKey hand shaking here \n"));
	        break;
	    }
    	
		MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer);  /* allocate memory */
        if(pOutBuffer == NULL)
            break;

        MAKE_802_3_HEADER(Header802_3, pDaEntry->Addr, pAd->ApCfg.MBSSID[pDaEntry->apidx].wdev.bssid, EAPOL);

        /* Increment replay counter by 1 */
        ADD_ONE_To_64BIT_VAR(pDaEntry->R_Counter);

		/* Allocate memory for output */
		os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER);
		if (mpool == NULL)
	    {
			MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);
	        DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__));
	        return;
	    }

		pOutPacket = (PEAPOL_PACKET)mpool;
		NdisZeroMemory(pOutPacket, TX_EAPOL_BUFFER);

        /* 0. init Packet and Fill header */
        pOutPacket->ProVer = EAPOL_VER;
        pOutPacket->ProType = EAPOLKey;
        pOutPacket->Body_Len[1] = 0x5f;
        
        /* 1. Fill replay counter */
/*        NdisMoveMemory(pDaEntry->R_Counter, pAd->ApCfg.R_Counter, sizeof(pDaEntry->R_Counter)); */
        NdisMoveMemory(pOutPacket->KeyDesc.ReplayCounter, pDaEntry->R_Counter, LEN_KEY_DESC_REPLAY);
        
        /* 2. Fill key version, keyinfo, key len */
        pOutPacket->KeyDesc.KeyInfo.KeyDescVer= GROUP_KEY;
        pOutPacket->KeyDesc.KeyInfo.KeyType	= GROUPKEY;
        pOutPacket->KeyDesc.KeyInfo.Install	= 1;
        pOutPacket->KeyDesc.KeyInfo.KeyAck	= 1;
        pOutPacket->KeyDesc.KeyInfo.KeyMic	= 1;
        pOutPacket->KeyDesc.KeyInfo.Secure	= 1;
        pOutPacket->KeyDesc.KeyInfo.EKD_DL	= 1;
		DBGPRINT(RT_DEBUG_TRACE, ("STAKey handshake for peer STA %02x:%02x:%02x:%02x:%02x:%02x\n",
			PRINT_MAC(DA)));
        
        if ((pDaEntry->AuthMode == Ndis802_11AuthModeWPA) || (pDaEntry->AuthMode == Ndis802_11AuthModeWPAPSK))
        {
        	pOutPacket->KeyDesc.Type = WPA1_KEY_DESC;

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

        	DBGPRINT(RT_DEBUG_TRACE, ("pDaEntry->AuthMode == Ndis802_11AuthModeWPA2/WPA2PSK\n"));
        }

        pOutPacket->KeyDesc.KeyLength[1] = LEN_TKIP_TK;
        pOutPacket->KeyDesc.KeyDataLen[1] = LEN_TKIP_TK;
        pOutPacket->KeyDesc.KeyInfo.KeyDescVer = KEY_DESC_TKIP;
        if (pDaEntry->WepStatus == Ndis802_11AESEnable)
        {
            pOutPacket->KeyDesc.KeyLength[1] = LEN_AES_TK;
            pOutPacket->KeyDesc.KeyDataLen[1] = LEN_AES_TK;
            pOutPacket->KeyDesc.KeyInfo.KeyDescVer = KEY_DESC_AES;
        }

		/* Key Data Encapsulation format, use Ralink OUI to distinguish proprietary and standard. */
    	Key_Data[0] = 0xDD;
		Key_Data[1] = 0x00;		/* Length (This field will be filled later) */
    	Key_Data[2] = 0x00;		/* OUI */
    	Key_Data[3] = 0x0C;		/* OUI */
    	Key_Data[4] = 0x43;		/* OUI */
    	Key_Data[5] = 0x02;		/* Data Type (STAKey Key Data Encryption) */

		/* STAKey Data Encapsulation format */
    	Key_Data[6] = 0x00;		/*Reserved */
		Key_Data[7] = 0x00;		/*Reserved */

		/* STAKey MAC address */
		NdisMoveMemory(&Key_Data[8], pEntry->Addr, MAC_ADDR_LEN);		/* initiator MAC address */

		/* STAKey (Handle the difference between TKIP and AES-CCMP) */
		if (pDaEntry->WepStatus == Ndis802_11AESEnable)
        {
        	Key_Data[1] = 0x1E;	/* 4+2+6+16(OUI+Reserved+STAKey_MAC_Addr+STAKey) */
        	NdisMoveMemory(&Key_Data[14], pEntry->PairwiseKey.Key, LEN_AES_TK);
		}
		else
		{
			Key_Data[1] = 0x2E;	/* 4+2+6+32(OUI+Reserved+STAKey_MAC_Addr+STAKey) */
			NdisMoveMemory(&Key_Data[14], pEntry->PairwiseKey.Key, LEN_TK);
			NdisMoveMemory(&Key_Data[14+LEN_TK], pEntry->PairwiseKey.TxMic, LEN_TKIP_MIC);
			NdisMoveMemory(&Key_Data[14+LEN_TK+LEN_TKIP_MIC], pEntry->PairwiseKey.RxMic, LEN_TKIP_MIC);
		}

		key_length = Key_Data[1];
		pOutPacket->Body_Len[1] = key_length + 0x5f;

		/* This is proprietary DLS protocol, it will be adhered when spec. is finished. */
		NdisZeroMemory(temp, 64);
		NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32);
		WpaDerivePTK(pAd, temp, temp, pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, temp, DA, pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK);
		
		DBGPRINT(RT_DEBUG_TRACE, ("PTK-0-%x %x %x %x %x %x %x %x \n",
				pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[0],
				pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[1],
				pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[2],
				pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[3],
				pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[4],
				pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[5],
				pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[6],
				pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[7]));

       	NdisMoveMemory(pOutPacket->KeyDesc.KeyData, Key_Data, key_length);
		NdisZeroMemory(mic, sizeof(mic));

		*(USHORT *)(&pOutPacket->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pOutPacket->KeyDesc.KeyInfo));

		MakeOutgoingFrame(pOutBuffer,			&FrameLen,
                        pOutPacket->Body_Len[1] + 4,	pOutPacket,
                        END_OF_ARGS);
	    
		/* Calculate MIC */
        if (pDaEntry->WepStatus == Ndis802_11AESEnable)
        {
            RT_HMAC_SHA1(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK_KCK, pOutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE);
            NdisMoveMemory(pOutPacket->KeyDesc.KeyMic, digest, LEN_KEY_DESC_MIC);
	    }
        else
        {
            RT_HMAC_MD5(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK_KCK, pOutBuffer, FrameLen, mic, MD5_DIGEST_SIZE);
            NdisMoveMemory(pOutPacket->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC);
        }

        RTMPToWirelessSta(pAd, pDaEntry, Header802_3, LENGTH_802_3, (PUCHAR)pOutPacket, pOutPacket->Body_Len[1] + 4, FALSE);

        MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);
		os_free_mem(NULL, mpool);
    }while(FALSE);
    
    DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleSTAKey: FrameLen=%ld\n", FrameLen));
}