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")); }
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)); }