cmm_wpa.c

来自「Linux下的RT系列无线网卡驱动,可以直接在x86平台上编译」· C语言 代码 · 共 1,330 行 · 第 1/3 页

C
1,330
字号
                break;            case Ndis802_11Encryption3Enabled:#ifdef CONFIG_STA_SUPPORT				if (pAd->StaCfg.bMixCipher)					NdisMoveMemory(pRsnie2->mcast, OUI_WPA2_TKIP, 4);				else					                	NdisMoveMemory(pRsnie2->mcast, OUI_WPA2_CCMP, 4);#endif // CONFIG_STA_SUPPORT //                pRsnie2->ucount = 1;                NdisMoveMemory(pRsnie2->ucast[0].oui, OUI_WPA2_CCMP, 4);                Rsnie_size = sizeof(RSNIE2);                break;        }        pRsnie_auth2 = (RSNIE_AUTH*)((PUCHAR)pRsnie2 + Rsnie_size);        switch (AuthMode)        {            case Ndis802_11AuthModeWPA2:            case Ndis802_11AuthModeWPA1WPA2:                pRsnie_auth2->acount = 1;                NdisMoveMemory(pRsnie_auth2->auth[0].oui, OUI_WPA2_WEP40, 4);                break;            case Ndis802_11AuthModeWPA2PSK:            case Ndis802_11AuthModeWPA1PSKWPA2PSK:                pRsnie_auth2->acount = 1;                NdisMoveMemory(pRsnie_auth2->auth[0].oui, OUI_WPA2_TKIP, 4);                break;        }        pRSN_Cap = (RSN_CAPABILITIES*)((PUCHAR)pRsnie_auth2 + sizeof(RSNIE_AUTH));#ifdef BIG_ENDIAN	    pRsnie2->version = SWAP16(pRsnie2->version);	    pRsnie2->ucount = SWAP16(pRsnie2->ucount);	    pRsnie_auth2->acount = SWAP16(pRsnie_auth2->acount);		pRSN_Cap->word = SWAP16(pRSN_Cap->word);#endif#ifdef CONFIG_STA_SUPPORT		pAd->StaCfg.RSNIE_Len = Rsnie_size + sizeof(RSNIE_AUTH) + sizeof(RSN_CAPABILITIES);#endif // CONFIG_STA_SUPPORT //		    }#ifdef CONFIG_STA_SUPPORT    DBGPRINT(RT_DEBUG_TRACE,("RTMPMakeRSNIE in STA mode: RSNIE_Len = %d\n", pAd->StaCfg.RSNIE_Len));#endif // CONFIG_STA_SUPPORT //}/*    ==========================================================================    Description:           Return:         TRUE if this is EAP frame         FALSE otherwise    ==========================================================================*/BOOLEAN RTMPCheckWPAframe(    IN PRTMP_ADAPTER    pAd,    IN PUCHAR           pData,    IN ULONG            DataByteCount){	ULONG	Body_len;    if(DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H))        return FALSE;    DBGPRINT(RT_DEBUG_INFO, ("RTMPCheckWPAframe ===> \n"));    	// Skip LLC header	    if (NdisEqualMemory(SNAP_802_1H, pData, 6))     {        pData += 6;    }    if (NdisEqualMemory(EAPOL, pData, 2))     {        pData += 2;             }    else            return FALSE;    switch (*(pData+1))         {           case EAPPacket:			Body_len = (*(pData+2)<<8) | (*(pData+3));            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len));            break;        case EAPOLStart:            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n"));            break;        case EAPOLLogoff:            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n"));            break;        case EAPOLKey:			Body_len = (*(pData+2)<<8) | (*(pData+3));            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len));            break;        case EAPOLASFAlert:            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));            break;        default:            return FALSE;        }       return TRUE;}/*    ==========================================================================    Description:        ENCRYPT AES GTK before sending in EAPOL frame.        AES GTK length = 128 bit,  so fix blocks for aes-key-wrap as 2 in this function.        This function references to RFC 3394 for aes key wrap algorithm.    Return:    ==========================================================================*/  VOID AES_GTK_KEY_WRAP(     IN UCHAR    *key,    IN UCHAR    *plaintext,    IN UCHAR    p_len,    OUT UCHAR   *ciphertext){    UCHAR       A[8], BIN[16], BOUT[16];    UCHAR       R[512];    INT         num_blocks = p_len/8;   // unit:64bits    INT         i, j;    aes_context aesctx;    UCHAR       xor;    aes_set_key(&aesctx, key, 128);    // Init IA    for (i = 0; i < 8; i++)        A[i] = 0xa6;    //Input plaintext    for (i = 0; i < num_blocks; i++)    {        for (j = 0 ; j < 8; j++)            R[8 * (i + 1) + j] = plaintext[8 * i + j];    }    // Key Mix    for (j = 0; j < 6; j++)    {        for(i = 1; i <= num_blocks; i++)        {            //phase 1            NdisMoveMemory(BIN, A, 8);            NdisMoveMemory(&BIN[8], &R[8 * i], 8);            aes_encrypt(&aesctx, BIN, BOUT);            NdisMoveMemory(A, &BOUT[0], 8);            xor = num_blocks * j + i;            A[7] = BOUT[7] ^ xor;            NdisMoveMemory(&R[8 * i], &BOUT[8], 8);        }    }    // Output ciphertext    NdisMoveMemory(ciphertext, A, 8);    for (i = 1; i <= num_blocks; i++)    {        for (j = 0 ; j < 8; j++)            ciphertext[8 * i + j] = R[8 * i + j];    }}/*	========================================================================		Routine Description:		Misc function to decrypt AES body		Arguments:				Return Value:		Note:		This function references to	RFC	3394 for aes key unwrap algorithm.				========================================================================*/VOID	AES_GTK_KEY_UNWRAP( 	IN	UCHAR	*key,	OUT	UCHAR	*plaintext,	IN	UCHAR    c_len,	IN	UCHAR	*ciphertext)	{	UCHAR       A[8], BIN[16], BOUT[16];	UCHAR       xor;	INT         i, j;	aes_context aesctx;	UCHAR       *R;	INT         num_blocks = c_len/8;	// unit:64bits		os_alloc_mem(NULL, (PUCHAR *)&R, 512);	if (R == NULL)    {        DBGPRINT(RT_DEBUG_ERROR, ("!!!AES_GTK_KEY_UNWRAP: no memory!!!\n"));        return;    } /* End of if */	// Initialize	NdisMoveMemory(A, ciphertext, 8);	//Input plaintext	for(i = 0; i < (c_len-8); i++)	{		R[ i] = ciphertext[i + 8];	}	aes_set_key(&aesctx, key, 128);	for(j = 5; j >= 0; j--)	{		for(i = (num_blocks-1); i > 0; i--)		{			xor = (num_blocks -1 )* j + i;			NdisMoveMemory(BIN, A, 8);			BIN[7] = A[7] ^ xor;			NdisMoveMemory(&BIN[8], &R[(i-1)*8], 8);			aes_decrypt(&aesctx, BIN, BOUT);			NdisMoveMemory(A, &BOUT[0], 8);			NdisMoveMemory(&R[(i-1)*8], &BOUT[8], 8);		}	}	// OUTPUT	for(i = 0; i < c_len; i++)	{		plaintext[i] = R[i];	}	DBGPRINT_RAW(RT_DEBUG_INFO, ("plaintext = \n"));	for(i = 0; i < (num_blocks *8); i++)	{		DBGPRINT_RAW(RT_DEBUG_INFO, ("%2x ", plaintext[i]));		if(i%16 == 15)			DBGPRINT_RAW(RT_DEBUG_INFO, ("\n "));	}	DBGPRINT_RAW(RT_DEBUG_INFO, ("\n  \n"));		os_free_mem(NULL, R);}CHAR *GetEapolMsgType(CHAR msg){    if(msg == EAPOL_PAIR_MSG_1)        return "Pairwise Message 1";    else if(msg == EAPOL_PAIR_MSG_2)        return "Pairwise Message 2";	else if(msg == EAPOL_PAIR_MSG_3)        return "Pairwise Message 3";	else if(msg == EAPOL_PAIR_MSG_4)        return "Pairwise Message 4";	else if(msg == EAPOL_GROUP_MSG_1)        return "Group Message 1";	else if(msg == EAPOL_GROUP_MSG_2)        return "Group Message 2";    else    	return "Invalid Message";}/*    ========================================================================        Routine Description:    Check Sanity RSN IE of EAPoL message    Arguments:            Return Value:		    ========================================================================*/BOOLEAN RTMPCheckRSNIE(	IN  PRTMP_ADAPTER   pAd,	IN  PUCHAR          pData,	IN  UCHAR           DataLen,	IN  MAC_TABLE_ENTRY *pEntry,	OUT	UCHAR			*Offset){	PUCHAR              pVIE;	UCHAR               len;	PEID_STRUCT         pEid;	BOOLEAN				result = FALSE;			pVIE = pData;	len	 = DataLen;	*Offset = 0;	while (len > sizeof(RSNIE2))	{		pEid = (PEID_STRUCT) pVIE;			// WPA RSN IE		if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)))		{						if ((pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) &&				(NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) &&				(pEntry->RSNIE_Len == (pEid->Len + 2)))			{									DBGPRINT(RT_DEBUG_INFO, ("RTMPCheckRSNIE ==> WPA/WPAPSK RSN IE matched, Length(%d) \n", (pEid->Len + 2)));					result = TRUE;							}								*Offset += (pEid->Len + 2);					}		// WPA2 RSN IE		else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)))		{			if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2 || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) &&				(NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) &&				(pEntry->RSNIE_Len == (pEid->Len + 2)))			{									DBGPRINT(RT_DEBUG_INFO, ("RTMPCheckRSNIE ==> WPA2/WPA2PSK RSN IE matched, Length(%d) \n", (pEid->Len + 2)));					result = TRUE;							}						*Offset += (pEid->Len + 2);		}				else		{						break;		}		pVIE += (pEid->Len + 2);		len  -= (pEid->Len + 2);	}		DBGPRINT(RT_DEBUG_INFO, ("RTMPCheckRSNIE ==> skip_offset(%d) \n", *Offset));			return result;	}/*    ========================================================================        Routine Description:    Parse KEYDATA field.  KEYDATA[] May contain 2 RSN IE and optionally GTK.      GTK  is encaptulated in KDE format at  p.83 802.11i D10    Arguments:            Return Value:    Note:        802.11i D10              ========================================================================*/BOOLEAN RTMPParseEapolKeyData(	IN  PRTMP_ADAPTER   pAd,	IN  PUCHAR          pKeyData,	IN  UCHAR           KeyDataLen,	IN	UCHAR			GroupKeyIndex,	IN	UCHAR			MsgType,	IN	BOOLEAN			bWPA2,	IN  MAC_TABLE_ENTRY *pEntry){    PKDE_ENCAP          pKDE = NULL;    PUCHAR              pMyKeyData = pKeyData;    UCHAR               KeyDataLength = KeyDataLen;    UCHAR               GTKLEN = 0;	UCHAR				DefaultIdx = 0;	UCHAR				skip_offset;			    	// Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it	if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3)    {		// Check RSN IE whether it is WPA2/WPA2PSK   				if (!RTMPCheckRSNIE(pAd, pKeyData, KeyDataLen, pEntry, &skip_offset))		{			// send wireless event - for RSN IE different			if (pAd->CommonCfg.bWirelessEvent)				RTMPSendWirelessEvent(pAd, IW_RSNIE_DIFF_EVENT_FLAG, pEntry);         	DBGPRINT(RT_DEBUG_ERROR, ("RSN_IE Different in msg %d of 4-way handshake!\n", MsgType));						hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen);			hex_dump("Desired RSN_IE ", pEntry->RSN_IE, pEntry->RSNIE_Len);									return FALSE;			    	}    	else		{			if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3)			{				// skip RSN IE				pMyKeyData += skip_offset;				KeyDataLength -= skip_offset;				DBGPRINT(RT_DEBUG_TRACE, ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset));			}			else				return TRUE;					}	}	DBGPRINT(RT_DEBUG_TRACE,("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength));	// Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2	if (bWPA2 && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1))	{						if (KeyDataLength >= 8)	// KDE format exclude GTK length    	{        	pKDE = (PKDE_ENCAP) pMyKeyData;				        DBGPRINT(RT_DEBUG_INFO, ("pKDE->Type %x \n", pKDE->Type));    	    DBGPRINT(RT_DEBUG_INFO, ("pKDE->Len 0x%x \n", pKDE->Len));        	DBGPRINT(RT_DEBUG_INFO, ("pKDE->OUI %x %x %x \n", pKDE->OUI[0],pKDE->OUI[1],pKDE->OUI[2]));	    	DBGPRINT(RT_DEBUG_INFO, ("pKDE->DataType %x \n", pKDE->DataType));						DefaultIdx = pKDE->GTKEncap.Kid;			// Sanity check - KED length			if (KeyDataLength < (pKDE->Len + 2))    		{        		DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n"));        		return FALSE;			    		}			// Get GTK length - refer to IEEE 802.11i-2004 p.82			GTKLEN = pKDE->Len -6;			if (GTKLEN < LEN_AES_KEY)			{				DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN));        		return FALSE;			}

⌨️ 快捷键说明

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