📄 wpa.c
字号:
// Addr1: DA, Addr2: BSSID, Addr3: SA
COPY_MAC_ADDR(pHdr80211->Addr1, pAddr1);
COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
COPY_MAC_ADDR(pHdr80211->Addr3, pAd->PortCfg.Bssid);
pHdr80211->Sequence = pAd->Sequence;
}
/*
========================================================================
Routine Description:
SHA1 function
Arguments:
Return Value:
Note:
========================================================================
*/
VOID HMAC_SHA1(
IN UCHAR *text,
IN UINT text_len,
IN UCHAR *key,
IN UINT key_len,
IN UCHAR *digest)
{
SHA_CTX context;
UCHAR k_ipad[65]; /* inner padding - key XORd with ipad */
UCHAR k_opad[65]; /* outer padding - key XORd with opad */
INT i;
// if key is longer than 64 bytes reset it to key=SHA1(key)
if (key_len > 64)
{
SHA_CTX tctx;
SHAInit(&tctx);
SHAUpdate(&tctx, key, key_len);
SHAFinal(&tctx, key);
key_len = 20;
}
NdisZeroMemory(k_ipad, sizeof(k_ipad));
NdisZeroMemory(k_opad, sizeof(k_opad));
NdisMoveMemory(k_ipad, key, key_len);
NdisMoveMemory(k_opad, key, key_len);
// XOR key with ipad and opad values
for (i = 0; i < 64; i++)
{
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
// perform inner SHA1
SHAInit(&context); /* init context for 1st pass */
SHAUpdate(&context, k_ipad, 64); /* start with inner pad */
SHAUpdate(&context, text, text_len); /* then text of datagram */
SHAFinal(&context, digest); /* finish up 1st pass */
//perform outer SHA1
SHAInit(&context); /* init context for 2nd pass */
SHAUpdate(&context, k_opad, 64); /* start with outer pad */
SHAUpdate(&context, digest, 20); /* then results of 1st hash */
SHAFinal(&context, digest); /* finish up 2nd pass */
}
/*
========================================================================
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
========================================================================
*/
VOID ParseKeyData(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pKeyData,
IN UCHAR KeyDataLen,
IN UCHAR KeyIdx,
IN BOOLEAN IsGroupMsg)
{
PKDE_ENCAP pKDE = NULL;
PNDIS_802_11_KEY pGroupKey = NULL;
PUCHAR pMyKeyData=NULL;// = pKeyData;
UCHAR *KeyDataBuf, *mpool;
UCHAR KeyDataLength = KeyDataLen;
UCHAR GTKLEN;
INT i;
ULONG Idx;
PUCHAR pVIE=NULL;
UCHAR Len;
PEID_STRUCT pEid;
BOOLEAN bKDE_Key = FALSE; // Key Data Encapsulation format
mpool = kmalloc(256, MEM_ALLOC_FLAG); // allocate memory
if (mpool == NULL)
return;
// KeyDataBuf len = 256.
KeyDataBuf = (UCHAR *) ROUND_UP(mpool, 4);
// Init the buffer
NdisZeroMemory(KeyDataBuf, 256);
if((Idx = BssTableSearch(&pAd->ScanTab, pAd->PortCfg.Bssid, pAd->PortCfg.Channel)) == BSS_NOT_FOUND)
{
DBGPRINT(RT_DEBUG_ERROR, "%s, Can't find BSS\n", __FUNCTION__);
return;
}
pVIE = pAd->ScanTab.BssEntry[Idx].VarIEs;
Len = (UCHAR)pAd->ScanTab.BssEntry[Idx].VarIELen;
while(Len > 0)
{
pEid = (PEID_STRUCT) pVIE;
if (pEid->Eid != IE_RSN)
{
pVIE += (pEid->Len + 2);
Len -= (pEid->Len + 2);
continue;
}
if (!NdisEqualMemory(pKeyData, pEid->Octet, pEid->Len))
{
// DBGPRINT(RT_DEBUG_ERROR, " RSN IE mismatched !!!!!!!!!! \n");
}
else
{
// DBGPRINT(RT_DEBUG_TRACE, " RSN IE matched !!!!!!!!!! \n");
}
Len -= (pEid->Len + 2);
break;
}
/*
====================================================================
======================================================================
*/
NdisMoveMemory(KeyDataBuf, pKeyData, KeyDataLen);
pMyKeyData =(PUCHAR) KeyDataBuf;
if (!IsGroupMsg)
{
do{
if ((*pMyKeyData == WPARSNIE) && (*(pMyKeyData+1) != 0) && (KeyDataLength >= (2 + *(pMyKeyData+1))))
{
if ((*(pMyKeyData+2) == 0x00) && (*(pMyKeyData+3) == 0x0f) && (*(pMyKeyData+4) == 0xac))
break;
DBGPRINT_RAW(RT_DEBUG_TRACE,"WPA WPA_IE length %d contained in this message \n", (2 + *(pMyKeyData+1)));
KeyDataLength -= (2 + *(pMyKeyData+1));
pMyKeyData += *(pMyKeyData+1) + 2;
}
if ((*pMyKeyData == WPA2RSNIE) && (*(pMyKeyData+1) != 0) && (KeyDataLength >= (2 + *(pMyKeyData+1))))
{
DBGPRINT_RAW(RT_DEBUG_TRACE,"WPA2 RSN_IE length %d contained in this message \n", (2 + *(pMyKeyData+1)));
KeyDataLength -= (2 + *(pMyKeyData+1));
pMyKeyData += (*(pMyKeyData+1) + 2);
}
} while(KeyDataLength > 0);
}
DBGPRINT_RAW(RT_DEBUG_TRACE,"KeyDataLength %d \n", KeyDataLength);
// GTK key Data Encapsulation
pKDE = (PKDE_ENCAP) pMyKeyData;
if((KeyDataLength >= 8) && (pKDE->Type == WPARSNIE) && (pKDE->OUI[0] == 0x00) && (pKDE->OUI[1]== 0x0f) && (pKDE->OUI[2]== 0x0ac) && (pKDE->DataType== 0x01))
{
DBGPRINT_RAW(RT_DEBUG_TRACE,"pKDE = \n");
DBGPRINT_RAW(RT_DEBUG_TRACE,"pKDE->Type %x:", pKDE->Type);
DBGPRINT_RAW(RT_DEBUG_TRACE,"pKDE->Len 0x%x:", pKDE->Len);
DBGPRINT_RAW(RT_DEBUG_TRACE,"pKDE->OUI %x %x %x :", pKDE->OUI[0],pKDE->OUI[1],pKDE->OUI[2] );
DBGPRINT_RAW(RT_DEBUG_TRACE,"\n");
bKDE_Key = TRUE;
}
if ((bKDE_Key == TRUE) && (pKDE->GTKEncap.Kid == 0))
{
DBGPRINT_RAW(RT_DEBUG_ERROR,"GTK Key index zero , error\n");
return;
}
// Update GTK
pGroupKey = kmalloc(MAX_LEN_OF_MLME_BUFFER, MEM_ALLOC_FLAG); // allocate memory
if (pGroupKey == NULL)
return;
NdisZeroMemory(pGroupKey, sizeof(NDIS_802_11_KEY) + LEN_EAP_KEY);
pGroupKey->Length = sizeof(NDIS_802_11_KEY) + LEN_EAP_KEY;
COPY_MAC_ADDR(pGroupKey->BSSID, pAd->PortCfg.Bssid);
if (bKDE_Key) // GTK Key Data Encapsulation
{
GTKLEN = pKDE->Len -6;
DBGPRINT_RAW(RT_DEBUG_TRACE,"GTK Key[%d] len=%d ", pKDE->GTKEncap.Kid, GTKLEN);
for (i = 0; i < GTKLEN; i++)
{
DBGPRINT_RAW(RT_DEBUG_TRACE,"%02x:", pKDE->GTKEncap.GTK[i]);
}
DBGPRINT_RAW(RT_DEBUG_TRACE,"\n");
pGroupKey->KeyIndex = 0x20000000 | pKDE->GTKEncap.Kid;
pGroupKey->KeyLength = GTKLEN;
NdisMoveMemory(pGroupKey->KeyMaterial, pKDE->GTKEncap.GTK, 32);
// Call Add peer key function
RTMPWPAAddKeyProc(pAd, pGroupKey);
}
else if (KeyIdx != 0) // non-KDE Key
{
pGroupKey->KeyIndex = 0x20000000 | KeyIdx;
pGroupKey->KeyLength = 32; //KeyDataLen
NdisMoveMemory(pGroupKey->KeyMaterial, pMyKeyData, LEN_EAP_KEY);
// Call Add peer key function
RTMPWPAAddKeyProc(pAd, pGroupKey);
}
kfree(pGroupKey);
kfree(mpool);
}
VOID WPAMake8023Hdr(
IN PRTMP_ADAPTER pAd,
IN PCHAR pDAddr,
IN OUT PCHAR pHdr)
{
// Addr1: DA, Addr2: BSSID, Addr3: SA
NdisMoveMemory(pHdr, pDAddr, MAC_ADDR_LEN);
NdisMoveMemory(&pHdr[MAC_ADDR_LEN], pAd->CurrentAddress, MAC_ADDR_LEN);
pHdr[2*MAC_ADDR_LEN] = 0x88;
pHdr[2*MAC_ADDR_LEN+1] = 0x8e;
}
/*
========================================================================
Routine Description:
PRF function
Arguments:
Return Value:
Note:
802.1i Annex F.9
========================================================================
*/
VOID PRF(
IN UCHAR *key,
IN INT key_len,
IN UCHAR *prefix,
IN INT prefix_len,
IN UCHAR *data,
IN INT data_len,
OUT UCHAR *output,
IN INT len)
{
INT i;
UCHAR *input;
INT currentindex = 0;
INT total_len;
BOOLEAN bfree = TRUE;
input = kmalloc(1024, MEM_ALLOC_FLAG); // allocate memory
if (input == NULL)
{
input = prf_input;
bfree = FALSE;
}
NdisMoveMemory(input, prefix, prefix_len);
input[prefix_len] = 0;
NdisMoveMemory(&input[prefix_len + 1], data, data_len);
total_len = prefix_len + 1 + data_len;
input[total_len] = 0;
total_len++;
for (i = 0; i < (len + 19) / 20; i++)
{
HMAC_SHA1(input, total_len, key, key_len, &output[currentindex]);
currentindex += 20;
input[total_len - 1]++;
}
if (bfree==TRUE)
kfree(input);
}
/*
========================================================================
Routine Description:
Count TPTK from PMK
Arguments:
Return Value:
Output Store the TPTK
Note:
========================================================================
*/
VOID WpaCountPTK(
IN UCHAR *PMK,
IN UCHAR *ANonce,
IN UCHAR *AA,
IN UCHAR *SNonce,
IN UCHAR *SA,
OUT UCHAR *output,
IN UINT len)
{
UCHAR concatenation[76];
UINT CurrPos = 0;
UCHAR temp[32];
UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ',
'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'};
NdisZeroMemory(temp, sizeof(temp));
// Get smaller address
if (RTMPCompareMemory(SA, AA, 6) == 1)
NdisMoveMemory(concatenation, AA, 6);
else
NdisMoveMemory(concatenation, SA, 6);
CurrPos += 6;
// Get larger address
if (RTMPCompareMemory(SA, AA, 6) == 1)
NdisMoveMemory(&concatenation[CurrPos], SA, 6);
else
NdisMoveMemory(&concatenation[CurrPos], AA, 6);
CurrPos += 6;
// Get smaller address
if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
else
NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
CurrPos += 32;
// Get larger address
if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
else
NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
CurrPos += 32;
PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len);
}
/*
========================================================================
Routine Description:
Misc function to Generate random number
Arguments:
Return Value:
Note:
802.1i Annex F.9
========================================================================
*/
VOID GenRandom(
IN PRTMP_ADAPTER pAd,
OUT UCHAR *random)
{
INT i, curr;
UCHAR *local, *KeyCounter;
UCHAR *result;
unsigned long CurrentTime;
UCHAR prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'};
UCHAR *mpool;
mpool = kmalloc(256, MEM_ALLOC_FLAG); // allocate memory
if (mpool == NULL)
return;
// local Len = 80.
local = (UCHAR *) ROUND_UP(mpool, 4);
// KeyCounter Len = 32.
KeyCounter = (UCHAR *) ROUND_UP(local + 80, 4);
// result Len = 80.
result = (UCHAR *) ROUND_UP(KeyCounter + 32, 4);
NdisZeroMemory(result, 80);
Ndi
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -