blob: 7b51be0e8dd335fbf8d78727fd998e583c342e9f [file] [log] [blame]
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001/*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
24 * *
25 *************************************************************************
26
27 Module Name:
28 wpa.c
29
30 Abstract:
31
32 Revision History:
33 Who When What
34 -------- ---------- ----------------------------------------------
35 Jan Lee 03-07-22 Initial
36 Paul Lin 03-11-28 Modify for supplicant
37*/
38#include "../rt_config.h"
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -080039/* WPA OUI */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080040u8 OUI_WPA_NONE_AKM[4] = { 0x00, 0x50, 0xF2, 0x00 };
41u8 OUI_WPA_VERSION[4] = { 0x00, 0x50, 0xF2, 0x01 };
42u8 OUI_WPA_WEP40[4] = { 0x00, 0x50, 0xF2, 0x01 };
43u8 OUI_WPA_TKIP[4] = { 0x00, 0x50, 0xF2, 0x02 };
44u8 OUI_WPA_CCMP[4] = { 0x00, 0x50, 0xF2, 0x04 };
45u8 OUI_WPA_WEP104[4] = { 0x00, 0x50, 0xF2, 0x05 };
46u8 OUI_WPA_8021X_AKM[4] = { 0x00, 0x50, 0xF2, 0x01 };
47u8 OUI_WPA_PSK_AKM[4] = { 0x00, 0x50, 0xF2, 0x02 };
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -080048
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -080049/* WPA2 OUI */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080050u8 OUI_WPA2_WEP40[4] = { 0x00, 0x0F, 0xAC, 0x01 };
51u8 OUI_WPA2_TKIP[4] = { 0x00, 0x0F, 0xAC, 0x02 };
52u8 OUI_WPA2_CCMP[4] = { 0x00, 0x0F, 0xAC, 0x04 };
53u8 OUI_WPA2_8021X_AKM[4] = { 0x00, 0x0F, 0xAC, 0x01 };
54u8 OUI_WPA2_PSK_AKM[4] = { 0x00, 0x0F, 0xAC, 0x02 };
55u8 OUI_WPA2_WEP104[4] = { 0x00, 0x0F, 0xAC, 0x05 };
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020056
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -080057static void ConstructEapolKeyData(struct rt_mac_table_entry *pEntry,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080058 u8 GroupKeyWepStatus,
59 u8 keyDescVer,
60 u8 MsgType,
61 u8 DefaultKeyIdx,
62 u8 * GTK,
63 u8 * RSNIE,
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -080064 u8 RSNIE_LEN, struct rt_eapol_packet * pMsg);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020065
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080066static void CalculateMIC(u8 KeyDescVer,
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -080067 u8 * PTK, struct rt_eapol_packet * pMsg);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020068
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -080069static void WpaEAPPacketAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020070
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -080071static void WpaEAPOLASFAlertAction(struct rt_rtmp_adapter *pAd,
72 struct rt_mlme_queue_elem *Elem);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020073
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -080074static void WpaEAPOLLogoffAction(struct rt_rtmp_adapter *pAd,
75 struct rt_mlme_queue_elem *Elem);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020076
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -080077static void WpaEAPOLStartAction(struct rt_rtmp_adapter *pAd,
78 struct rt_mlme_queue_elem *Elem);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020079
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -080080static void WpaEAPOLKeyAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020081
82/*
83 ==========================================================================
84 Description:
85 association state machine init, including state transition and timer init
86 Parameters:
87 S - pointer to the association state machine
88 ==========================================================================
89 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -080090void WpaStateMachineInit(struct rt_rtmp_adapter *pAd,
91 struct rt_state_machine *S, OUT STATE_MACHINE_FUNC Trans[])
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020092{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -080093 StateMachineInit(S, (STATE_MACHINE_FUNC *) Trans, MAX_WPA_PTK_STATE,
94 MAX_WPA_MSG, (STATE_MACHINE_FUNC) Drop, WPA_PTK,
95 WPA_MACHINE_BASE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020096
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -080097 StateMachineSetAction(S, WPA_PTK, MT2_EAPPacket,
98 (STATE_MACHINE_FUNC) WpaEAPPacketAction);
99 StateMachineSetAction(S, WPA_PTK, MT2_EAPOLStart,
100 (STATE_MACHINE_FUNC) WpaEAPOLStartAction);
101 StateMachineSetAction(S, WPA_PTK, MT2_EAPOLLogoff,
102 (STATE_MACHINE_FUNC) WpaEAPOLLogoffAction);
103 StateMachineSetAction(S, WPA_PTK, MT2_EAPOLKey,
104 (STATE_MACHINE_FUNC) WpaEAPOLKeyAction);
105 StateMachineSetAction(S, WPA_PTK, MT2_EAPOLASFAlert,
106 (STATE_MACHINE_FUNC) WpaEAPOLASFAlertAction);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200107}
108
109/*
110 ==========================================================================
111 Description:
112 this is state machine function.
113 When receiving EAP packets which is for 802.1x authentication use.
114 Not use in PSK case
115 Return:
116 ==========================================================================
117*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800118void WpaEAPPacketAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200119{
120}
121
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800122void WpaEAPOLASFAlertAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200123{
124}
125
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800126void WpaEAPOLLogoffAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200127{
128}
129
130/*
131 ==========================================================================
132 Description:
133 Start 4-way HS when rcv EAPOL_START which may create by our driver in assoc.c
134 Return:
135 ==========================================================================
136*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800137void WpaEAPOLStartAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200138{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800139 struct rt_mac_table_entry *pEntry;
140 struct rt_header_802_11 * pHeader;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200141
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800142 DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLStartAction ===> \n"));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200143
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800144 pHeader = (struct rt_header_802_11 *) Elem->Msg;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200145
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800146 /*For normaol PSK, we enqueue an EAPOL-Start command to trigger the process. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800147 if (Elem->MsgLen == 6)
148 pEntry = MacTableLookup(pAd, Elem->Msg);
149 else {
150 pEntry = MacTableLookup(pAd, pHeader->Addr2);
151 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200152
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800153 if (pEntry) {
154 DBGPRINT(RT_DEBUG_TRACE,
155 (" PortSecured(%d), WpaState(%d), AuthMode(%d), PMKID_CacheIdx(%d) \n",
156 pEntry->PortSecured, pEntry->WpaState,
157 pEntry->AuthMode, pEntry->PMKID_CacheIdx));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200158
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800159 if ((pEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED)
160 && (pEntry->WpaState < AS_PTKSTART)
161 && ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK)
162 || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)
163 || ((pEntry->AuthMode == Ndis802_11AuthModeWPA2)
164 && (pEntry->PMKID_CacheIdx != ENTRY_NOT_FOUND)))) {
165 pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
166 pEntry->WpaState = AS_INITPSK;
167 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
168 NdisZeroMemory(pEntry->R_Counter,
169 sizeof(pEntry->R_Counter));
170 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200171
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800172 WPAStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV);
173 }
174 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200175}
176
177/*
178 ==========================================================================
179 Description:
180 This is state machine function.
181 When receiving EAPOL packets which is for 802.1x key management.
182 Use both in WPA, and WPAPSK case.
183 In this function, further dispatch to different functions according to the received packet. 3 categories are :
184 1. normal 4-way pairwisekey and 2-way groupkey handshake
185 2. MIC error (Countermeasures attack) report packet from STA.
186 3. Request for pairwise/group key update from STA
187 Return:
188 ==========================================================================
189*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800190void WpaEAPOLKeyAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200191{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800192 struct rt_mac_table_entry *pEntry;
193 struct rt_header_802_11 * pHeader;
194 struct rt_eapol_packet * pEapol_packet;
195 struct rt_key_info peerKeyInfo;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200196
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800197 DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLKeyAction ===>\n"));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200198
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800199 pHeader = (struct rt_header_802_11 *) Elem->Msg;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800200 pEapol_packet =
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800201 (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200202
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800203 NdisZeroMemory((u8 *)& peerKeyInfo, sizeof(peerKeyInfo));
204 NdisMoveMemory((u8 *)& peerKeyInfo,
205 (u8 *)& pEapol_packet->KeyDesc.KeyInfo,
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800206 sizeof(struct rt_key_info));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200207
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800208 hex_dump("Received Eapol frame", (unsigned char *)pEapol_packet,
209 (Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200210
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800211 *((u16 *) & peerKeyInfo) = cpu2le16(*((u16 *) & peerKeyInfo));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200212
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800213 do {
214 pEntry = MacTableLookup(pAd, pHeader->Addr2);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200215
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800216 if (!pEntry
217 || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
218 break;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200219
220 if (pEntry->AuthMode < Ndis802_11AuthModeWPA)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800221 break;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200222
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800223 DBGPRINT(RT_DEBUG_TRACE,
224 ("Receive EAPoL-Key frame from STA %02X-%02X-%02X-%02X-%02X-%02X\n",
225 PRINT_MAC(pEntry->Addr)));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200226
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800227 if (((pEapol_packet->ProVer != EAPOL_VER)
228 && (pEapol_packet->ProVer != EAPOL_VER2))
229 || ((pEapol_packet->KeyDesc.Type != WPA1_KEY_DESC)
230 && (pEapol_packet->KeyDesc.Type != WPA2_KEY_DESC))) {
231 DBGPRINT(RT_DEBUG_ERROR,
232 ("Key descripter does not match with WPA rule\n"));
233 break;
234 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800235 /* The value 1 shall be used for all EAPOL-Key frames to and from a STA when */
236 /* neither the group nor pairwise ciphers are CCMP for Key Descriptor 1. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800237 if ((pEntry->WepStatus == Ndis802_11Encryption2Enabled)
238 && (peerKeyInfo.KeyDescVer != DESC_TYPE_TKIP)) {
239 DBGPRINT(RT_DEBUG_ERROR,
240 ("Key descripter version not match(TKIP) \n"));
241 break;
242 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800243 /* The value 2 shall be used for all EAPOL-Key frames to and from a STA when */
244 /* either the pairwise or the group cipher is AES-CCMP for Key Descriptor 2. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800245 else if ((pEntry->WepStatus == Ndis802_11Encryption3Enabled)
246 && (peerKeyInfo.KeyDescVer != DESC_TYPE_AES)) {
247 DBGPRINT(RT_DEBUG_ERROR,
248 ("Key descripter version not match(AES) \n"));
249 break;
250 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800251 /* Check if this STA is in class 3 state and the WPA state is started */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800252 if ((pEntry->Sst == SST_ASSOC)
253 && (pEntry->WpaState >= AS_INITPSK)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800254 /* Check the Key Ack (bit 7) of the Key Information to determine the Authenticator */
255 /* or not. */
256 /* An EAPOL-Key frame that is sent by the Supplicant in response to an EAPOL- */
257 /* Key frame from the Authenticator must not have the Ack bit set. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800258 if (peerKeyInfo.KeyAck == 1) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800259 /* The frame is snet by Authenticator. */
260 /* So the Supplicant side shall handle this. */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200261
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800262 if ((peerKeyInfo.Secure == 0)
263 && (peerKeyInfo.Request == 0)
264 && (peerKeyInfo.Error == 0)
265 && (peerKeyInfo.KeyType == PAIRWISEKEY)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800266 /* Process 1. the message 1 of 4-way HS in WPA or WPA2 */
267 /* EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) */
268 /* 2. the message 3 of 4-way HS in WPA */
269 /* EAPOL-Key(0,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3) */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200270 if (peerKeyInfo.KeyMic == 0)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800271 PeerPairMsg1Action(pAd, pEntry,
272 Elem);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200273 else
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800274 PeerPairMsg3Action(pAd, pEntry,
275 Elem);
276 } else if ((peerKeyInfo.Secure == 1)
277 && (peerKeyInfo.KeyMic == 1)
278 && (peerKeyInfo.Request == 0)
279 && (peerKeyInfo.Error == 0)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800280 /* Process 1. the message 3 of 4-way HS in WPA2 */
281 /* EAPOL-Key(1,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3) */
282 /* 2. the message 1 of group KS in WPA or WPA2 */
283 /* EAPOL-Key(1,1,1,0,G,0,Key RSC,0, MIC,GTK[N]) */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800284 if (peerKeyInfo.KeyType == PAIRWISEKEY)
285 PeerPairMsg3Action(pAd, pEntry,
286 Elem);
287 else
288 PeerGroupMsg1Action(pAd, pEntry,
289 Elem);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200290 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800291 } else {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800292 /* The frame is snet by Supplicant. */
293 /* So the Authenticator side shall handle this. */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200294 if ((peerKeyInfo.Request == 0) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800295 (peerKeyInfo.Error == 0) &&
296 (peerKeyInfo.KeyMic == 1)) {
297 if (peerKeyInfo.Secure == 0
298 && peerKeyInfo.KeyType ==
299 PAIRWISEKEY) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800300 /* EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,Data) */
301 /* Process 1. message 2 of 4-way HS in WPA or WPA2 */
302 /* 2. message 4 of 4-way HS in WPA */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800303 if (CONV_ARRARY_TO_u16
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800304 (pEapol_packet->KeyDesc.
305 KeyDataLen) == 0) {
306 PeerPairMsg4Action(pAd,
307 pEntry,
308 Elem);
309 } else {
310 PeerPairMsg2Action(pAd,
311 pEntry,
312 Elem);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200313 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800314 } else if (peerKeyInfo.Secure == 1
315 && peerKeyInfo.KeyType ==
316 PAIRWISEKEY) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800317 /* EAPOL-Key(1,1,0,0,P,0,0,0,MIC,0) */
318 /* Process message 4 of 4-way HS in WPA2 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800319 PeerPairMsg4Action(pAd, pEntry,
320 Elem);
321 } else if (peerKeyInfo.Secure == 1
322 && peerKeyInfo.KeyType ==
323 GROUPKEY) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800324 /* EAPOL-Key(1,1,0,0,G,0,0,0,MIC,0) */
325 /* Process message 2 of Group key HS in WPA or WPA2 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800326 PeerGroupMsg2Action(pAd, pEntry,
327 &Elem->
328 Msg
329 [LENGTH_802_11],
330 (Elem->
331 MsgLen -
332 LENGTH_802_11));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200333 }
334 }
335 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800336 }
337 } while (FALSE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200338}
339
340/*
341 ========================================================================
342
343 Routine Description:
344 Copy frame from waiting queue into relative ring buffer and set
345 appropriate ASIC register to kick hardware encryption before really
346 sent out to air.
347
348 Arguments:
349 pAd Pointer to our adapter
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -0800350 void * Pointer to outgoing Ndis frame
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200351 NumberOfFrag Number of fragment required
352
353 Return Value:
354 None
355
356 Note:
357
358 ========================================================================
359*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800360void RTMPToWirelessSta(struct rt_rtmp_adapter *pAd,
361 struct rt_mac_table_entry *pEntry,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800362 u8 *pHeader802_3,
363 u32 HdrLen,
364 u8 *pData, u32 DataLen, IN BOOLEAN bClearFrame)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200365{
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -0800366 void *pPacket;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800367 int Status;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200368
369 if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
370 return;
371
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800372 do {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800373 /* build a NDIS packet */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800374 Status =
375 RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen,
376 pData, DataLen);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200377 if (Status != NDIS_STATUS_SUCCESS)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800378 break;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200379
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800380 if (bClearFrame)
381 RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 1);
382 else
383 RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 0);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200384 {
385 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
386
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800387 RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, MAIN_MBSSID); /* set a default value */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800388 if (pEntry->apidx != 0)
389 RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket,
390 pEntry->
391 apidx);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200392
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800393 RTMP_SET_PACKET_WCID(pPacket, (u8)pEntry->Aid);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200394 RTMP_SET_PACKET_MOREDATA(pPacket, FALSE);
395 }
396
397 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800398 /* send out the packet */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800399 Status = STASendPacket(pAd, pPacket);
400 if (Status == NDIS_STATUS_SUCCESS) {
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800401 u8 Index;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200402
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800403 /* Dequeue one frame from TxSwQueue0..3 queue and process it */
404 /* There are three place calling dequeue for TX ring. */
405 /* 1. Here, right after queueing the frame. */
406 /* 2. At the end of TxRingTxDone service routine. */
407 /* 3. Upon NDIS call RTMPSendPackets */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800408 if ((!RTMP_TEST_FLAG
409 (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
410 &&
411 (!RTMP_TEST_FLAG
412 (pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))) {
413 for (Index = 0; Index < 5; Index++)
414 if (pAd->TxSwQueue[Index].
415 Number > 0)
416 RTMPDeQueuePacket(pAd,
417 FALSE,
418 Index,
419 MAX_TX_PROCESS);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200420 }
421 }
422 }
423
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800424 } while (FALSE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200425}
426
427/*
428 ==========================================================================
429 Description:
430 This is a function to initilize 4-way handshake
431
432 Return:
433
434 ==========================================================================
435*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800436void WPAStart4WayHS(struct rt_rtmp_adapter *pAd,
437 struct rt_mac_table_entry *pEntry, unsigned long TimeInterval)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200438{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800439 u8 Header802_3[14];
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800440 struct rt_eapol_packet EAPOLPKT;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800441 u8 *pBssid = NULL;
442 u8 group_cipher = Ndis802_11WEPDisabled;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200443
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800444 DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart4WayHS\n"));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200445
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800446 if (RTMP_TEST_FLAG
447 (pAd,
448 fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS))
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200449 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800450 DBGPRINT(RT_DEBUG_ERROR,
451 ("[ERROR]WPAStart4WayHS : The interface is closed...\n"));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200452 return;
453 }
454
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800455 if (pBssid == NULL) {
456 DBGPRINT(RT_DEBUG_ERROR,
457 ("[ERROR]WPAStart4WayHS : No corresponding Authenticator.\n"));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200458 return;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800459 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800460 /* Check the status */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800461 if ((pEntry->WpaState > AS_PTKSTART) || (pEntry->WpaState < AS_INITPMK)) {
462 DBGPRINT(RT_DEBUG_ERROR,
463 ("[ERROR]WPAStart4WayHS : Not expect calling\n"));
464 return;
465 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200466
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800467 /* Increment replay counter by 1 */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200468 ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
469
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800470 /* Randomly generate ANonce */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800471 GenRandom(pAd, (u8 *) pBssid, pEntry->ANonce);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200472
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800473 /* Construct EAPoL message - Pairwise Msg 1 */
474 /* EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800475 NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800476 ConstructEapolMsg(pEntry, group_cipher, EAPOL_PAIR_MSG_1, 0, /* Default key index */
477 pEntry->ANonce, NULL, /* TxRSC */
478 NULL, /* GTK */
479 NULL, /* RSNIE */
480 0, /* RSNIE length */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800481 &EAPOLPKT);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200482
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800483 /* Make outgoing frame */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800484 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
485 RTMPToWirelessSta(pAd, pEntry, Header802_3,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800486 LENGTH_802_3, (u8 *)& EAPOLPKT,
487 CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800488 (pEntry->PortSecured ==
489 WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200490
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800491 /* Trigger Retry Timer */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800492 RTMPModTimer(&pEntry->RetryTimer, TimeInterval);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200493
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800494 /* Update State */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800495 pEntry->WpaState = AS_PTKSTART;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200496
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800497 DBGPRINT(RT_DEBUG_TRACE,
498 ("<=== WPAStart4WayHS: send Msg1 of 4-way \n"));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200499
500}
501
502/*
503 ========================================================================
504
505 Routine Description:
506 Process Pairwise key Msg-1 of 4-way handshaking and send Msg-2
507
508 Arguments:
509 pAd Pointer to our adapter
510 Elem Message body
511
512 Return Value:
513 None
514
515 Note:
516
517 ========================================================================
518*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800519void PeerPairMsg1Action(struct rt_rtmp_adapter *pAd,
520 struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200521{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800522 u8 PTK[80];
523 u8 Header802_3[14];
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800524 struct rt_eapol_packet * pMsg1;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800525 u32 MsgLen;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800526 struct rt_eapol_packet EAPOLPKT;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800527 u8 *pCurrentAddr = NULL;
528 u8 *pmk_ptr = NULL;
529 u8 group_cipher = Ndis802_11WEPDisabled;
530 u8 *rsnie_ptr = NULL;
531 u8 rsnie_len = 0;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200532
533 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg1Action \n"));
534
535 if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
536 return;
537
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800538 if (Elem->MsgLen <
539 (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H +
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800540 sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2))
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800541 return;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200542
543 {
544 pCurrentAddr = pAd->CurrentAddress;
545 pmk_ptr = pAd->StaCfg.PMK;
546 group_cipher = pAd->StaCfg.GroupCipher;
547 rsnie_ptr = pAd->StaCfg.RSN_IE;
548 rsnie_len = pAd->StaCfg.RSNIE_Len;
549 }
550
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800551 /* Store the received frame */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800552 pMsg1 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200553 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
554
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800555 /* Sanity Check peer Pairwise message 1 - Replay Counter */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800556 if (PeerWpaMessageSanity(pAd, pMsg1, MsgLen, EAPOL_PAIR_MSG_1, pEntry)
557 == FALSE)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200558 return;
559
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800560 /* Store Replay counter, it will use to verify message 3 and construct message 2 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800561 NdisMoveMemory(pEntry->R_Counter, pMsg1->KeyDesc.ReplayCounter,
562 LEN_KEY_DESC_REPLAY);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200563
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800564 /* Store ANonce */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800565 NdisMoveMemory(pEntry->ANonce, pMsg1->KeyDesc.KeyNonce,
566 LEN_KEY_DESC_NONCE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200567
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800568 /* Generate random SNonce */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800569 GenRandom(pAd, (u8 *) pCurrentAddr, pEntry->SNonce);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200570
571 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800572 /* Calculate PTK(ANonce, SNonce) */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800573 WpaDerivePTK(pAd,
574 pmk_ptr,
575 pEntry->ANonce,
576 pEntry->Addr,
577 pEntry->SNonce, pCurrentAddr, PTK, LEN_PTK);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200578
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800579 /* Save key to PTK entry */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200580 NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK);
581 }
582
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800583 /* Update WpaState */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200584 pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
585
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800586 /* Construct EAPoL message - Pairwise Msg 2 */
587 /* EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,DataKD_M2) */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800588 NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800589 ConstructEapolMsg(pEntry, group_cipher, EAPOL_PAIR_MSG_2, 0, /* DefaultKeyIdx */
590 pEntry->SNonce, NULL, /* TxRsc */
591 NULL, /* GTK */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800592 (u8 *) rsnie_ptr, rsnie_len, &EAPOLPKT);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200593
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800594 /* Make outgoing frame */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200595 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
596
597 RTMPToWirelessSta(pAd, pEntry,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800598 Header802_3, sizeof(Header802_3), (u8 *)& EAPOLPKT,
599 CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, TRUE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200600
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800601 DBGPRINT(RT_DEBUG_TRACE,
602 ("<=== PeerPairMsg1Action: send Msg2 of 4-way \n"));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200603}
604
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200605/*
606 ==========================================================================
607 Description:
608 When receiving the second packet of 4-way pairwisekey handshake.
609 Return:
610 ==========================================================================
611*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800612void PeerPairMsg2Action(struct rt_rtmp_adapter *pAd,
613 struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200614{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800615 u8 PTK[80];
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800616 BOOLEAN Cancelled;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800617 struct rt_header_802_11 * pHeader;
618 struct rt_eapol_packet EAPOLPKT;
619 struct rt_eapol_packet * pMsg2;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800620 u32 MsgLen;
621 u8 Header802_3[LENGTH_802_3];
622 u8 TxTsc[6];
623 u8 *pBssid = NULL;
624 u8 *pmk_ptr = NULL;
625 u8 *gtk_ptr = NULL;
626 u8 default_key = 0;
627 u8 group_cipher = Ndis802_11WEPDisabled;
628 u8 *rsnie_ptr = NULL;
629 u8 rsnie_len = 0;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200630
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800631 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg2Action \n"));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200632
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800633 if ((!pEntry) || (!pEntry->ValidAsCLI))
634 return;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200635
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800636 if (Elem->MsgLen <
637 (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H +
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800638 sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2))
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800639 return;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200640
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800641 /* check Entry in valid State */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800642 if (pEntry->WpaState < AS_PTKSTART)
643 return;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200644
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800645 /* pointer to 802.11 header */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800646 pHeader = (struct rt_header_802_11 *) Elem->Msg;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200647
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800648 /* skip 802.11_header(24-byte) and LLC_header(8) */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800649 pMsg2 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200650 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
651
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800652 /* Store SNonce */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800653 NdisMoveMemory(pEntry->SNonce, pMsg2->KeyDesc.KeyNonce,
654 LEN_KEY_DESC_NONCE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200655
656 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800657 /* Derive PTK */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800658 WpaDerivePTK(pAd, (u8 *) pmk_ptr, pEntry->ANonce, /* ANONCE */
659 (u8 *) pBssid, pEntry->SNonce, /* SNONCE */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800660 pEntry->Addr, PTK, LEN_PTK);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200661
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800662 NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200663 }
664
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800665 /* Sanity Check peer Pairwise message 2 - Replay Counter, MIC, RSNIE */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800666 if (PeerWpaMessageSanity(pAd, pMsg2, MsgLen, EAPOL_PAIR_MSG_2, pEntry)
667 == FALSE)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200668 return;
669
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800670 do {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800671 /* delete retry timer */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200672 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
673
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800674 /* Change state */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800675 pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200676
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800677 /* Increment replay counter by 1 */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200678 ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
679
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800680 /* Construct EAPoL message - Pairwise Msg 3 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800681 NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200682 ConstructEapolMsg(pEntry,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800683 group_cipher,
684 EAPOL_PAIR_MSG_3,
685 default_key,
686 pEntry->ANonce,
687 TxTsc,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800688 (u8 *) gtk_ptr,
689 (u8 *) rsnie_ptr, rsnie_len, &EAPOLPKT);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200690
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800691 /* Make outgoing frame */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800692 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
693 RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800694 (u8 *)& EAPOLPKT,
695 CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800696 (pEntry->PortSecured ==
697 WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200698
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800699 pEntry->ReTryCounter = PEER_MSG3_RETRY_TIMER_CTR;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200700 RTMPSetTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV);
701
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800702 /* Update State */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800703 pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
704 } while (FALSE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200705
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800706 DBGPRINT(RT_DEBUG_TRACE,
707 ("<=== PeerPairMsg2Action: send Msg3 of 4-way \n"));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200708}
709
710/*
711 ========================================================================
712
713 Routine Description:
714 Process Pairwise key Msg 3 of 4-way handshaking and send Msg 4
715
716 Arguments:
717 pAd Pointer to our adapter
718 Elem Message body
719
720 Return Value:
721 None
722
723 Note:
724
725 ========================================================================
726*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800727void PeerPairMsg3Action(struct rt_rtmp_adapter *pAd,
728 struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200729{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800730 struct rt_header_802_11 * pHeader;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800731 u8 Header802_3[14];
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800732 struct rt_eapol_packet EAPOLPKT;
733 struct rt_eapol_packet * pMsg3;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800734 u32 MsgLen;
735 u8 *pCurrentAddr = NULL;
736 u8 group_cipher = Ndis802_11WEPDisabled;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200737
738 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg3Action \n"));
739
740 if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
741 return;
742
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800743 if (Elem->MsgLen <
744 (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H +
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800745 sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2))
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200746 return;
747
748 {
749 pCurrentAddr = pAd->CurrentAddress;
750 group_cipher = pAd->StaCfg.GroupCipher;
751
752 }
753
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800754 /* Record 802.11 header & the received EAPOL packet Msg3 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800755 pHeader = (struct rt_header_802_11 *) Elem->Msg;
756 pMsg3 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200757 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
758
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800759 /* Sanity Check peer Pairwise message 3 - Replay Counter, MIC, RSNIE */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800760 if (PeerWpaMessageSanity(pAd, pMsg3, MsgLen, EAPOL_PAIR_MSG_3, pEntry)
761 == FALSE)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200762 return;
763
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800764 /* Save Replay counter, it will use construct message 4 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800765 NdisMoveMemory(pEntry->R_Counter, pMsg3->KeyDesc.ReplayCounter,
766 LEN_KEY_DESC_REPLAY);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200767
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800768 /* Double check ANonce */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800769 if (!NdisEqualMemory
770 (pEntry->ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE)) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200771 return;
772 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800773 /* Construct EAPoL message - Pairwise Msg 4 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800774 NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800775 ConstructEapolMsg(pEntry, group_cipher, EAPOL_PAIR_MSG_4, 0, /* group key index not used in message 4 */
776 NULL, /* Nonce not used in message 4 */
777 NULL, /* TxRSC not used in message 4 */
778 NULL, /* GTK not used in message 4 */
779 NULL, /* RSN IE not used in message 4 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800780 0, &EAPOLPKT);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200781
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800782 /* Update WpaState */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200783 pEntry->WpaState = AS_PTKINITDONE;
784
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800785 /* Update pairwise key */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200786 {
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800787 struct rt_cipher_key *pSharedKey;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200788
789 pSharedKey = &pAd->SharedKey[BSS0][0];
790
791 NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK);
792
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800793 /* Prepare pair-wise key information into shared key table */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800794 NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200795 pSharedKey->KeyLen = LEN_TKIP_EK;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800796 NdisMoveMemory(pSharedKey->Key, &pAd->StaCfg.PTK[32],
797 LEN_TKIP_EK);
798 NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.PTK[48],
799 LEN_TKIP_RXMICK);
800 NdisMoveMemory(pSharedKey->TxMic,
801 &pAd->StaCfg.PTK[48 + LEN_TKIP_RXMICK],
802 LEN_TKIP_TXMICK);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200803
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800804 /* Decide its ChiperAlg */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200805 if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
806 pSharedKey->CipherAlg = CIPHER_TKIP;
807 else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
808 pSharedKey->CipherAlg = CIPHER_AES;
809 else
810 pSharedKey->CipherAlg = CIPHER_NONE;
811
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800812 /* Update these related information to struct rt_mac_table_entry */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200813 pEntry = &pAd->MacTab.Content[BSSID_WCID];
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800814 NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32],
815 LEN_TKIP_EK);
816 NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48],
817 LEN_TKIP_RXMICK);
818 NdisMoveMemory(pEntry->PairwiseKey.TxMic,
819 &pAd->StaCfg.PTK[48 + LEN_TKIP_RXMICK],
820 LEN_TKIP_TXMICK);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200821 pEntry->PairwiseKey.CipherAlg = pSharedKey->CipherAlg;
822
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800823 /* Update pairwise key information to ASIC Shared Key Table */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200824 AsicAddSharedKeyEntry(pAd,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800825 BSS0,
826 0,
827 pSharedKey->CipherAlg,
828 pSharedKey->Key,
829 pSharedKey->TxMic, pSharedKey->RxMic);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200830
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800831 /* Update ASIC WCID attribute table and IVEIV table */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200832 RTMPAddWcidAttributeEntry(pAd,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800833 BSS0,
834 0, pSharedKey->CipherAlg, pEntry);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200835
836 }
837
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800838 /* open 802.1x port control and privacy filter */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200839 if (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK ||
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800840 pEntry->AuthMode == Ndis802_11AuthModeWPA2) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200841 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
842 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
843
844 STA_PORT_SECURED(pAd);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800845 /* Indicate Connected for GUI */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800846 pAd->IndicateMediaState = NdisMediaStateConnected;
847 DBGPRINT(RT_DEBUG_TRACE,
848 ("PeerPairMsg3Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n",
849 GetAuthMode(pEntry->AuthMode),
850 GetEncryptType(pEntry->WepStatus),
851 GetEncryptType(group_cipher)));
852 } else {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200853 }
854
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800855 /* Init 802.3 header and send out */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200856 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
857 RTMPToWirelessSta(pAd, pEntry,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800858 Header802_3, sizeof(Header802_3),
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800859 (u8 *)& EAPOLPKT,
860 CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, TRUE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200861
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800862 DBGPRINT(RT_DEBUG_TRACE,
863 ("<=== PeerPairMsg3Action: send Msg4 of 4-way \n"));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200864}
865
866/*
867 ==========================================================================
868 Description:
869 When receiving the last packet of 4-way pairwisekey handshake.
870 Initilize 2-way groupkey handshake following.
871 Return:
872 ==========================================================================
873*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800874void PeerPairMsg4Action(struct rt_rtmp_adapter *pAd,
875 struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200876{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800877 struct rt_eapol_packet * pMsg4;
878 struct rt_header_802_11 * pHeader;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800879 u32 MsgLen;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800880 BOOLEAN Cancelled;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800881 u8 group_cipher = Ndis802_11WEPDisabled;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200882
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800883 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg4Action\n"));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200884
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800885 do {
886 if ((!pEntry) || (!pEntry->ValidAsCLI))
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200887 break;
888
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800889 if (Elem->MsgLen <
890 (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H +
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800891 sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2))
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800892 break;
893
894 if (pEntry->WpaState < AS_PTKINIT_NEGOTIATING)
895 break;
896
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800897 /* pointer to 802.11 header */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800898 pHeader = (struct rt_header_802_11 *) Elem->Msg;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800899
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800900 /* skip 802.11_header(24-byte) and LLC_header(8) */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800901 pMsg4 =
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800902 (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800903 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
904
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800905 /* Sanity Check peer Pairwise message 4 - Replay Counter, MIC */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800906 if (PeerWpaMessageSanity
907 (pAd, pMsg4, MsgLen, EAPOL_PAIR_MSG_4, pEntry) == FALSE)
908 break;
909
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800910 /* 3. uses the MLME.SETKEYS.request to configure PTK into MAC */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800911 NdisZeroMemory(&pEntry->PairwiseKey, sizeof(struct rt_cipher_key));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200912
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800913 /* reset IVEIV in Asic */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200914 AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, 1, 0);
915
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800916 pEntry->PairwiseKey.KeyLen = LEN_TKIP_EK;
917 NdisMoveMemory(pEntry->PairwiseKey.Key, &pEntry->PTK[32],
918 LEN_TKIP_EK);
919 NdisMoveMemory(pEntry->PairwiseKey.RxMic,
920 &pEntry->PTK[TKIP_AP_RXMICK_OFFSET],
921 LEN_TKIP_RXMICK);
922 NdisMoveMemory(pEntry->PairwiseKey.TxMic,
923 &pEntry->PTK[TKIP_AP_TXMICK_OFFSET],
924 LEN_TKIP_TXMICK);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200925
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800926 /* Set pairwise key to Asic */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800927 {
928 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
929 if (pEntry->WepStatus == Ndis802_11Encryption2Enabled)
930 pEntry->PairwiseKey.CipherAlg = CIPHER_TKIP;
931 else if (pEntry->WepStatus ==
932 Ndis802_11Encryption3Enabled)
933 pEntry->PairwiseKey.CipherAlg = CIPHER_AES;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200934
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800935 /* Add Pair-wise key to Asic */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800936 AsicAddPairwiseKeyEntry(pAd,
937 pEntry->Addr,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800938 (u8)pEntry->Aid,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800939 &pEntry->PairwiseKey);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200940
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800941 /* update WCID attribute table and IVEIV table for this entry */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800942 RTMPAddWcidAttributeEntry(pAd,
943 pEntry->apidx,
944 0,
945 pEntry->PairwiseKey.CipherAlg,
946 pEntry);
947 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200948
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800949 /* 4. upgrade state */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800950 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
951 pEntry->WpaState = AS_PTKINITDONE;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200952 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
953
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200954 if (pEntry->AuthMode == Ndis802_11AuthModeWPA2 ||
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800955 pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200956 pEntry->GTKState = REKEY_ESTABLISHED;
957 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
958
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800959 /* send wireless event - for set key done WPA2 */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200960 if (pAd->CommonCfg.bWirelessEvent)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800961 RTMPSendWirelessEvent(pAd,
962 IW_SET_KEY_DONE_WPA2_EVENT_FLAG,
963 pEntry->Addr,
964 pEntry->apidx, 0);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200965
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800966 DBGPRINT(RT_DEBUG_OFF,
967 ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
968 pEntry->AuthMode,
969 GetAuthMode(pEntry->AuthMode),
970 pEntry->WepStatus,
971 GetEncryptType(pEntry->WepStatus),
972 group_cipher, GetEncryptType(group_cipher)));
973 } else {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800974 /* 5. init Group 2-way handshake if necessary. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800975 WPAStart2WayGroupHS(pAd, pEntry);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200976
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800977 pEntry->ReTryCounter = GROUP_MSG1_RETRY_TIMER_CTR;
978 RTMPModTimer(&pEntry->RetryTimer,
979 PEER_MSG3_RETRY_EXEC_INTV);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200980 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800981 } while (FALSE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200982
983}
984
985/*
986 ==========================================================================
987 Description:
988 This is a function to send the first packet of 2-way groupkey handshake
989 Return:
990
991 ==========================================================================
992*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800993void WPAStart2WayGroupHS(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200994{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800995 u8 Header802_3[14];
996 u8 TxTsc[6];
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800997 struct rt_eapol_packet EAPOLPKT;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800998 u8 group_cipher = Ndis802_11WEPDisabled;
999 u8 default_key = 0;
1000 u8 *gnonce_ptr = NULL;
1001 u8 *gtk_ptr = NULL;
1002 u8 *pBssid = NULL;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001003
1004 DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart2WayGroupHS\n"));
1005
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001006 if ((!pEntry) || (!pEntry->ValidAsCLI))
1007 return;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001008
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001009 do {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001010 /* Increment replay counter by 1 */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001011 ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
1012
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001013 /* Construct EAPoL message - Group Msg 1 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001014 NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001015 ConstructEapolMsg(pEntry,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001016 group_cipher,
1017 EAPOL_GROUP_MSG_1,
1018 default_key,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001019 (u8 *) gnonce_ptr,
1020 TxTsc, (u8 *) gtk_ptr, NULL, 0, &EAPOLPKT);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001021
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001022 /* Make outgoing frame */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001023 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
1024 RTMPToWirelessSta(pAd, pEntry,
1025 Header802_3, LENGTH_802_3,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001026 (u8 *)& EAPOLPKT,
1027 CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001028 FALSE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001029
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001030 } while (FALSE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001031
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001032 DBGPRINT(RT_DEBUG_TRACE,
1033 ("<=== WPAStart2WayGroupHS : send out Group Message 1 \n"));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001034
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001035 return;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001036}
1037
1038/*
1039 ========================================================================
1040
1041 Routine Description:
1042 Process Group key 2-way handshaking
1043
1044 Arguments:
1045 pAd Pointer to our adapter
1046 Elem Message body
1047
1048 Return Value:
1049 None
1050
1051 Note:
1052
1053 ========================================================================
1054*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001055void PeerGroupMsg1Action(struct rt_rtmp_adapter *pAd,
1056 struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001057{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001058 u8 Header802_3[14];
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001059 struct rt_eapol_packet EAPOLPKT;
1060 struct rt_eapol_packet * pGroup;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001061 u32 MsgLen;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001062 BOOLEAN Cancelled;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001063 u8 default_key = 0;
1064 u8 group_cipher = Ndis802_11WEPDisabled;
1065 u8 *pCurrentAddr = NULL;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001066
1067 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg1Action \n"));
1068
1069 if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001070 return;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001071
1072 {
1073 pCurrentAddr = pAd->CurrentAddress;
1074 group_cipher = pAd->StaCfg.GroupCipher;
1075 default_key = pAd->StaCfg.DefaultKeyId;
1076 }
1077
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001078 /* Process Group Message 1 frame. skip 802.11 header(24) & LLC_SNAP header(8) */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001079 pGroup = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001080 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
1081
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001082 /* Sanity Check peer group message 1 - Replay Counter, MIC, RSNIE */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001083 if (PeerWpaMessageSanity(pAd, pGroup, MsgLen, EAPOL_GROUP_MSG_1, pEntry)
1084 == FALSE)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001085 return;
1086
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001087 /* delete retry timer */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001088 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
1089
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001090 /* Save Replay counter, it will use to construct message 2 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001091 NdisMoveMemory(pEntry->R_Counter, pGroup->KeyDesc.ReplayCounter,
1092 LEN_KEY_DESC_REPLAY);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001093
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001094 /* Construct EAPoL message - Group Msg 2 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001095 NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001096 ConstructEapolMsg(pEntry, group_cipher, EAPOL_GROUP_MSG_2, default_key, NULL, /* Nonce not used */
1097 NULL, /* TxRSC not used */
1098 NULL, /* GTK not used */
1099 NULL, /* RSN IE not used */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001100 0, &EAPOLPKT);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001101
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001102 /* open 802.1x port control and privacy filter */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001103 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
1104 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1105
1106 STA_PORT_SECURED(pAd);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001107 /* Indicate Connected for GUI */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001108 pAd->IndicateMediaState = NdisMediaStateConnected;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001109
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001110 DBGPRINT(RT_DEBUG_TRACE,
1111 ("PeerGroupMsg1Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n",
1112 GetAuthMode(pEntry->AuthMode),
1113 GetEncryptType(pEntry->WepStatus),
1114 GetEncryptType(group_cipher)));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001115
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001116 /* init header and Fill Packet and send Msg 2 to authenticator */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001117 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
1118 RTMPToWirelessSta(pAd, pEntry,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001119 Header802_3, sizeof(Header802_3),
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001120 (u8 *)& EAPOLPKT,
1121 CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, FALSE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001122
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001123 DBGPRINT(RT_DEBUG_TRACE,
1124 ("<=== PeerGroupMsg1Action: sned group message 2\n"));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001125}
1126
1127/*
1128 ==========================================================================
1129 Description:
1130 When receiving the last packet of 2-way groupkey handshake.
1131 Return:
1132 ==========================================================================
1133*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001134void PeerGroupMsg2Action(struct rt_rtmp_adapter *pAd,
1135 struct rt_mac_table_entry *pEntry,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001136 void * Msg, u32 MsgLen)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001137{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001138 u32 Len;
1139 u8 *pData;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001140 BOOLEAN Cancelled;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001141 struct rt_eapol_packet * pMsg2;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001142 u8 group_cipher = Ndis802_11WEPDisabled;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001143
1144 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg2Action \n"));
1145
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001146 do {
1147 if ((!pEntry) || (!pEntry->ValidAsCLI))
1148 break;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001149
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001150 if (MsgLen <
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001151 (LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(struct rt_key_descripter) -
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001152 MAX_LEN_OF_RSNIE - 2))
1153 break;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001154
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001155 if (pEntry->WpaState != AS_PTKINITDONE)
1156 break;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001157
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001158 pData = (u8 *)Msg;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001159 pMsg2 = (struct rt_eapol_packet *) (pData + LENGTH_802_1_H);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001160 Len = MsgLen - LENGTH_802_1_H;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001161
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001162 /* Sanity Check peer group message 2 - Replay Counter, MIC */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001163 if (PeerWpaMessageSanity
1164 (pAd, pMsg2, Len, EAPOL_GROUP_MSG_2, pEntry) == FALSE)
1165 break;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001166
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001167 /* 3. upgrade state */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001168
1169 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001170 pEntry->GTKState = REKEY_ESTABLISHED;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001171
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001172 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2)
1173 || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001174 /* send wireless event - for set key done WPA2 */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001175 if (pAd->CommonCfg.bWirelessEvent)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001176 RTMPSendWirelessEvent(pAd,
1177 IW_SET_KEY_DONE_WPA2_EVENT_FLAG,
1178 pEntry->Addr,
1179 pEntry->apidx, 0);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001180
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001181 DBGPRINT(RT_DEBUG_OFF,
1182 ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
1183 pEntry->AuthMode,
1184 GetAuthMode(pEntry->AuthMode),
1185 pEntry->WepStatus,
1186 GetEncryptType(pEntry->WepStatus),
1187 group_cipher, GetEncryptType(group_cipher)));
1188 } else {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001189 /* send wireless event - for set key done WPA */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001190 if (pAd->CommonCfg.bWirelessEvent)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001191 RTMPSendWirelessEvent(pAd,
1192 IW_SET_KEY_DONE_WPA1_EVENT_FLAG,
1193 pEntry->Addr,
1194 pEntry->apidx, 0);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001195
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001196 DBGPRINT(RT_DEBUG_OFF,
1197 ("AP SETKEYS DONE - WPA1, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
1198 pEntry->AuthMode,
1199 GetAuthMode(pEntry->AuthMode),
1200 pEntry->WepStatus,
1201 GetEncryptType(pEntry->WepStatus),
1202 group_cipher, GetEncryptType(group_cipher)));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001203 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001204 } while (FALSE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001205}
1206
1207/*
1208 ========================================================================
1209
1210 Routine Description:
1211 Classify WPA EAP message type
1212
1213 Arguments:
1214 EAPType Value of EAP message type
1215 MsgType Internal Message definition for MLME state machine
1216
1217 Return Value:
1218 TRUE Found appropriate message type
1219 FALSE No appropriate message type
1220
1221 IRQL = DISPATCH_LEVEL
1222
1223 Note:
1224 All these constants are defined in wpa.h
1225 For supplicant, there is only EAPOL Key message avaliable
1226
1227 ========================================================================
1228*/
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001229BOOLEAN WpaMsgTypeSubst(u8 EAPType, int * MsgType)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001230{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001231 switch (EAPType) {
1232 case EAPPacket:
1233 *MsgType = MT2_EAPPacket;
1234 break;
1235 case EAPOLStart:
1236 *MsgType = MT2_EAPOLStart;
1237 break;
1238 case EAPOLLogoff:
1239 *MsgType = MT2_EAPOLLogoff;
1240 break;
1241 case EAPOLKey:
1242 *MsgType = MT2_EAPOLKey;
1243 break;
1244 case EAPOLASFAlert:
1245 *MsgType = MT2_EAPOLASFAlert;
1246 break;
1247 default:
1248 return FALSE;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001249 }
1250 return TRUE;
1251}
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001252
1253/*
1254 ========================================================================
1255
1256 Routine Description:
1257 The pseudo-random function(PRF) that hashes various inputs to
1258 derive a pseudo-random value. To add liveness to the pseudo-random
1259 value, a nonce should be one of the inputs.
1260
1261 It is used to generate PTK, GTK or some specific random value.
1262
1263 Arguments:
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001264 u8 *key, - the key material for HMAC_SHA1 use
1265 int key_len - the length of key
1266 u8 *prefix - a prefix label
1267 int prefix_len - the length of the label
1268 u8 *data - a specific data with variable length
1269 int data_len - the length of a specific data
1270 int len - the output lenght
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001271
1272 Return Value:
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001273 u8 *output - the calculated result
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001274
1275 Note:
1276 802.11i-2004 Annex H.3
1277
1278 ========================================================================
1279*/
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001280void PRF(u8 * key,
1281 int key_len,
1282 u8 * prefix,
1283 int prefix_len,
1284 u8 * data, int data_len, u8 * output, int len)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001285{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001286 int i;
1287 u8 *input;
1288 int currentindex = 0;
1289 int total_len;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001290
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001291 /* Allocate memory for input */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001292 os_alloc_mem(NULL, (u8 **) & input, 1024);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001293
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001294 if (input == NULL) {
1295 DBGPRINT(RT_DEBUG_ERROR, ("!!!PRF: no memory!!!\n"));
1296 return;
1297 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001298 /* Generate concatenation input */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001299 NdisMoveMemory(input, prefix, prefix_len);
1300
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001301 /* Concatenate a single octet containing 0 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001302 input[prefix_len] = 0;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001303
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001304 /* Concatenate specific data */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001305 NdisMoveMemory(&input[prefix_len + 1], data, data_len);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001306 total_len = prefix_len + 1 + data_len;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001307
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001308 /* Concatenate a single octet containing 0 */
1309 /* This octet shall be update later */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001310 input[total_len] = 0;
1311 total_len++;
1312
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001313 /* Iterate to calculate the result by hmac-sha-1 */
1314 /* Then concatenate to last result */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001315 for (i = 0; i < (len + 19) / 20; i++) {
1316 HMAC_SHA1(key, key_len, input, total_len, &output[currentindex],
1317 SHA1_DIGEST_SIZE);
1318 currentindex += 20;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001319
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001320 /* update the last octet */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001321 input[total_len - 1]++;
1322 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001323 os_free_mem(NULL, input);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001324}
1325
1326/*
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001327* F(P, S, c, i) = U1 xor U2 xor ... Uc
1328* U1 = PRF(P, S || Int(i))
1329* U2 = PRF(P, U1)
1330* Uc = PRF(P, Uc-1)
1331*/
1332
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001333static void F(char *password, unsigned char *ssid, int ssidlength,
1334 int iterations, int count, unsigned char *output)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001335{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001336 unsigned char digest[36], digest1[SHA1_DIGEST_SIZE];
1337 int i, j;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001338
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001339 /* U1 = PRF(P, S || int(i)) */
1340 memcpy(digest, ssid, ssidlength);
1341 digest[ssidlength] = (unsigned char)((count >> 24) & 0xff);
1342 digest[ssidlength + 1] = (unsigned char)((count >> 16) & 0xff);
1343 digest[ssidlength + 2] = (unsigned char)((count >> 8) & 0xff);
1344 digest[ssidlength + 3] = (unsigned char)(count & 0xff);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001345 HMAC_SHA1((unsigned char *)password, (int)strlen(password), digest, ssidlength + 4, digest1, SHA1_DIGEST_SIZE); /* for WPA update */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001346
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001347 /* output = U1 */
1348 memcpy(output, digest1, SHA1_DIGEST_SIZE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001349
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001350 for (i = 1; i < iterations; i++) {
1351 /* Un = PRF(P, Un-1) */
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001352 HMAC_SHA1((unsigned char *)password, (int)strlen(password), digest1, SHA1_DIGEST_SIZE, digest, SHA1_DIGEST_SIZE); /* for WPA update */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001353 memcpy(digest1, digest, SHA1_DIGEST_SIZE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001354
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001355 /* output = output xor Un */
1356 for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
1357 output[j] ^= digest[j];
1358 }
1359 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001360}
1361
1362/*
1363* password - ascii string up to 63 characters in length
1364* ssid - octet string up to 32 octets
1365* ssidlength - length of ssid in octets
1366* output must be 40 octets in length and outputs 256 bits of key
1367*/
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001368int PasswordHash(char *password, u8 *ssid, int ssidlength, u8 *output)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001369{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001370 if ((strlen(password) > 63) || (ssidlength > 32))
1371 return 0;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001372
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001373 F(password, ssid, ssidlength, 4096, 1, output);
1374 F(password, ssid, ssidlength, 4096, 2, &output[SHA1_DIGEST_SIZE]);
1375 return 1;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001376}
1377
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001378/*
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001379 ========================================================================
1380
1381 Routine Description:
1382 It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK.
1383 It shall be called by 4-way handshake processing.
1384
1385 Arguments:
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001386 pAd - pointer to our pAdapter context
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001387 PMK - pointer to PMK
1388 ANonce - pointer to ANonce
1389 AA - pointer to Authenticator Address
1390 SNonce - pointer to SNonce
1391 SA - pointer to Supplicant Address
1392 len - indicate the length of PTK (octet)
1393
1394 Return Value:
1395 Output pointer to the PTK
1396
1397 Note:
1398 Refer to IEEE 802.11i-2004 8.5.1.2
1399
1400 ========================================================================
1401*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001402void WpaDerivePTK(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001403 u8 * PMK,
1404 u8 * ANonce,
1405 u8 * AA,
1406 u8 * SNonce,
1407 u8 * SA, u8 * output, u32 len)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001408{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001409 u8 concatenation[76];
1410 u32 CurrPos = 0;
1411 u8 temp[32];
1412 u8 Prefix[] =
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001413 { 'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ',
1414 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'
1415 };
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001416
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001417 /* initiate the concatenation input */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001418 NdisZeroMemory(temp, sizeof(temp));
1419 NdisZeroMemory(concatenation, 76);
1420
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001421 /* Get smaller address */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001422 if (RTMPCompareMemory(SA, AA, 6) == 1)
1423 NdisMoveMemory(concatenation, AA, 6);
1424 else
1425 NdisMoveMemory(concatenation, SA, 6);
1426 CurrPos += 6;
1427
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001428 /* Get larger address */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001429 if (RTMPCompareMemory(SA, AA, 6) == 1)
1430 NdisMoveMemory(&concatenation[CurrPos], SA, 6);
1431 else
1432 NdisMoveMemory(&concatenation[CurrPos], AA, 6);
1433
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001434 /* store the larger mac address for backward compatible of */
1435 /* ralink proprietary STA-key issue */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001436 NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN);
1437 CurrPos += 6;
1438
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001439 /* Get smaller Nonce */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001440 if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001441 NdisMoveMemory(&concatenation[CurrPos], temp, 32); /* patch for ralink proprietary STA-key issue */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001442 else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
1443 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
1444 else
1445 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
1446 CurrPos += 32;
1447
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001448 /* Get larger Nonce */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001449 if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001450 NdisMoveMemory(&concatenation[CurrPos], temp, 32); /* patch for ralink proprietary STA-key issue */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001451 else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
1452 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
1453 else
1454 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
1455 CurrPos += 32;
1456
1457 hex_dump("concatenation=", concatenation, 76);
1458
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001459 /* Use PRF to generate PTK */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001460 PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len);
1461
1462}
1463
1464/*
1465 ========================================================================
1466
1467 Routine Description:
1468 Generate random number by software.
1469
1470 Arguments:
1471 pAd - pointer to our pAdapter context
1472 macAddr - pointer to local MAC address
1473
1474 Return Value:
1475
1476 Note:
1477 802.1ii-2004 Annex H.5
1478
1479 ========================================================================
1480*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001481void GenRandom(struct rt_rtmp_adapter *pAd, u8 * macAddr, u8 * random)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001482{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001483 int i, curr;
1484 u8 local[80], KeyCounter[32];
1485 u8 result[80];
1486 unsigned long CurrentTime;
1487 u8 prefix[] =
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001488 { 'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r' };
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001489
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001490 /* Zero the related information */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001491 NdisZeroMemory(result, 80);
1492 NdisZeroMemory(local, 80);
1493 NdisZeroMemory(KeyCounter, 32);
1494
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001495 for (i = 0; i < 32; i++) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001496 /* copy the local MAC address */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001497 COPY_MAC_ADDR(local, macAddr);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001498 curr = MAC_ADDR_LEN;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001499
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001500 /* concatenate the current time */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001501 NdisGetSystemUpTime(&CurrentTime);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001502 NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime));
1503 curr += sizeof(CurrentTime);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001504
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001505 /* concatenate the last result */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001506 NdisMoveMemory(&local[curr], result, 32);
1507 curr += 32;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001508
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001509 /* concatenate a variable */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001510 NdisMoveMemory(&local[curr], &i, 2);
1511 curr += 2;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001512
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001513 /* calculate the result */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001514 PRF(KeyCounter, 32, prefix, 12, local, curr, result, 32);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001515 }
1516
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001517 NdisMoveMemory(random, result, 32);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001518}
1519
1520/*
1521 ========================================================================
1522
1523 Routine Description:
1524 Build cipher suite in RSN-IE.
1525 It only shall be called by RTMPMakeRSNIE.
1526
1527 Arguments:
1528 pAd - pointer to our pAdapter context
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001529 ElementID - indicate the WPA1 or WPA2
1530 WepStatus - indicate the encryption type
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001531 bMixCipher - a boolean to indicate the pairwise cipher and group
1532 cipher are the same or not
1533
1534 Return Value:
1535
1536 Note:
1537
1538 ========================================================================
1539*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001540static void RTMPMakeRsnIeCipher(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001541 u8 ElementID,
1542 u32 WepStatus,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001543 IN BOOLEAN bMixCipher,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001544 u8 FlexibleCipher,
1545 u8 *pRsnIe, u8 * rsn_len)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001546{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001547 u8 PairwiseCnt;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001548
1549 *rsn_len = 0;
1550
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001551 /* decide WPA2 or WPA1 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001552 if (ElementID == Wpa2Ie) {
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001553 struct rt_rsnie2 *pRsnie_cipher = (struct rt_rsnie2 *)pRsnIe;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001554
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001555 /* Assign the verson as 1 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001556 pRsnie_cipher->version = 1;
1557
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001558 switch (WepStatus) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001559 /* TKIP mode */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001560 case Ndis802_11Encryption2Enabled:
1561 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
1562 pRsnie_cipher->ucount = 1;
1563 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1564 OUI_WPA2_TKIP, 4);
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001565 *rsn_len = sizeof(struct rt_rsnie2);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001566 break;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001567
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001568 /* AES mode */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001569 case Ndis802_11Encryption3Enabled:
1570 if (bMixCipher)
1571 NdisMoveMemory(pRsnie_cipher->mcast,
1572 OUI_WPA2_TKIP, 4);
1573 else
1574 NdisMoveMemory(pRsnie_cipher->mcast,
1575 OUI_WPA2_CCMP, 4);
1576 pRsnie_cipher->ucount = 1;
1577 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1578 OUI_WPA2_CCMP, 4);
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001579 *rsn_len = sizeof(struct rt_rsnie2);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001580 break;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001581
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001582 /* TKIP-AES mix mode */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001583 case Ndis802_11Encryption4Enabled:
1584 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001585
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001586 PairwiseCnt = 1;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001587 /* Insert WPA2 TKIP as the first pairwise cipher */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001588 if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher)) {
1589 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1590 OUI_WPA2_TKIP, 4);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001591 /* Insert WPA2 AES as the secondary pairwise cipher */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001592 if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher)) {
1593 NdisMoveMemory(pRsnie_cipher->ucast[0].
1594 oui + 4, OUI_WPA2_CCMP,
1595 4);
1596 PairwiseCnt = 2;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001597 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001598 } else {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001599 /* Insert WPA2 AES as the first pairwise cipher */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001600 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1601 OUI_WPA2_CCMP, 4);
Adam McDanieled291e82009-02-23 08:01:07 -07001602 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001603
1604 pRsnie_cipher->ucount = PairwiseCnt;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001605 *rsn_len = sizeof(struct rt_rsnie2) + (4 * (PairwiseCnt - 1));
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001606 break;
Adam McDanieled291e82009-02-23 08:01:07 -07001607 }
Bartlomiej Zolnierkiewicz3cf830a2009-08-23 15:29:32 +02001608
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001609 if ((pAd->OpMode == OPMODE_STA) &&
1610 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
1611 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) {
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001612 u32 GroupCipher = pAd->StaCfg.GroupCipher;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001613 switch (GroupCipher) {
1614 case Ndis802_11GroupWEP40Enabled:
1615 NdisMoveMemory(pRsnie_cipher->mcast,
1616 OUI_WPA2_WEP40, 4);
1617 break;
1618 case Ndis802_11GroupWEP104Enabled:
1619 NdisMoveMemory(pRsnie_cipher->mcast,
1620 OUI_WPA2_WEP104, 4);
1621 break;
1622 }
1623 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001624 /* swap for big-endian platform */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001625 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001626 pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
1627 } else {
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001628 struct rt_rsnie *pRsnie_cipher = (struct rt_rsnie *)pRsnIe;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001629
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001630 /* Assign OUI and version */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001631 NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001632 pRsnie_cipher->version = 1;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001633
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001634 switch (WepStatus) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001635 /* TKIP mode */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001636 case Ndis802_11Encryption2Enabled:
1637 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
1638 pRsnie_cipher->ucount = 1;
1639 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1640 OUI_WPA_TKIP, 4);
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001641 *rsn_len = sizeof(struct rt_rsnie);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001642 break;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001643
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001644 /* AES mode */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001645 case Ndis802_11Encryption3Enabled:
1646 if (bMixCipher)
1647 NdisMoveMemory(pRsnie_cipher->mcast,
1648 OUI_WPA_TKIP, 4);
1649 else
1650 NdisMoveMemory(pRsnie_cipher->mcast,
1651 OUI_WPA_CCMP, 4);
1652 pRsnie_cipher->ucount = 1;
1653 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1654 OUI_WPA_CCMP, 4);
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001655 *rsn_len = sizeof(struct rt_rsnie);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001656 break;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001657
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001658 /* TKIP-AES mix mode */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001659 case Ndis802_11Encryption4Enabled:
1660 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001661
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001662 PairwiseCnt = 1;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001663 /* Insert WPA TKIP as the first pairwise cipher */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001664 if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher)) {
1665 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1666 OUI_WPA_TKIP, 4);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001667 /* Insert WPA AES as the secondary pairwise cipher */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001668 if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher)) {
1669 NdisMoveMemory(pRsnie_cipher->ucast[0].
1670 oui + 4, OUI_WPA_CCMP,
1671 4);
1672 PairwiseCnt = 2;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001673 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001674 } else {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001675 /* Insert WPA AES as the first pairwise cipher */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001676 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1677 OUI_WPA_CCMP, 4);
Adam McDanieled291e82009-02-23 08:01:07 -07001678 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001679
1680 pRsnie_cipher->ucount = PairwiseCnt;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001681 *rsn_len = sizeof(struct rt_rsnie) + (4 * (PairwiseCnt - 1));
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001682 break;
Adam McDanieled291e82009-02-23 08:01:07 -07001683 }
Bartlomiej Zolnierkiewicz3cf830a2009-08-23 15:29:32 +02001684
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001685 if ((pAd->OpMode == OPMODE_STA) &&
1686 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
1687 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) {
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001688 u32 GroupCipher = pAd->StaCfg.GroupCipher;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001689 switch (GroupCipher) {
1690 case Ndis802_11GroupWEP40Enabled:
1691 NdisMoveMemory(pRsnie_cipher->mcast,
1692 OUI_WPA_WEP40, 4);
1693 break;
1694 case Ndis802_11GroupWEP104Enabled:
1695 NdisMoveMemory(pRsnie_cipher->mcast,
1696 OUI_WPA_WEP104, 4);
1697 break;
1698 }
1699 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001700 /* swap for big-endian platform */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001701 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001702 pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001703 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001704}
1705
1706/*
1707 ========================================================================
1708
1709 Routine Description:
1710 Build AKM suite in RSN-IE.
1711 It only shall be called by RTMPMakeRSNIE.
1712
1713 Arguments:
1714 pAd - pointer to our pAdapter context
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001715 ElementID - indicate the WPA1 or WPA2
1716 AuthMode - indicate the authentication mode
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001717 apidx - indicate the interface index
1718
1719 Return Value:
1720
1721 Note:
1722
1723 ========================================================================
1724*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001725static void RTMPMakeRsnIeAKM(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001726 u8 ElementID,
1727 u32 AuthMode,
1728 u8 apidx,
1729 u8 *pRsnIe, u8 * rsn_len)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001730{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001731 struct rt_rsnie_auth *pRsnie_auth;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001732 u8 AkmCnt = 1; /* default as 1 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001733
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001734 pRsnie_auth = (struct rt_rsnie_auth *) (pRsnIe + (*rsn_len));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001735
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001736 /* decide WPA2 or WPA1 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001737 if (ElementID == Wpa2Ie) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001738
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001739 switch (AuthMode) {
1740 case Ndis802_11AuthModeWPA2:
1741 case Ndis802_11AuthModeWPA1WPA2:
1742 NdisMoveMemory(pRsnie_auth->auth[0].oui,
1743 OUI_WPA2_8021X_AKM, 4);
1744 break;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001745
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001746 case Ndis802_11AuthModeWPA2PSK:
1747 case Ndis802_11AuthModeWPA1PSKWPA2PSK:
1748 NdisMoveMemory(pRsnie_auth->auth[0].oui,
1749 OUI_WPA2_PSK_AKM, 4);
1750 break;
1751 default:
1752 AkmCnt = 0;
1753 break;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001754
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001755 }
1756 } else {
1757 switch (AuthMode) {
1758 case Ndis802_11AuthModeWPA:
1759 case Ndis802_11AuthModeWPA1WPA2:
1760 NdisMoveMemory(pRsnie_auth->auth[0].oui,
1761 OUI_WPA_8021X_AKM, 4);
1762 break;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001763
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001764 case Ndis802_11AuthModeWPAPSK:
1765 case Ndis802_11AuthModeWPA1PSKWPA2PSK:
1766 NdisMoveMemory(pRsnie_auth->auth[0].oui,
1767 OUI_WPA_PSK_AKM, 4);
1768 break;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001769
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001770 case Ndis802_11AuthModeWPANone:
1771 NdisMoveMemory(pRsnie_auth->auth[0].oui,
1772 OUI_WPA_NONE_AKM, 4);
1773 break;
1774 default:
1775 AkmCnt = 0;
1776 break;
1777 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001778 }
1779
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001780 pRsnie_auth->acount = AkmCnt;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001781 pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount);
1782
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001783 /* update current RSNIE length */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001784 (*rsn_len) += (sizeof(struct rt_rsnie_auth) + (4 * (AkmCnt - 1)));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001785
1786}
1787
1788/*
1789 ========================================================================
1790
1791 Routine Description:
1792 Build capability in RSN-IE.
1793 It only shall be called by RTMPMakeRSNIE.
1794
1795 Arguments:
1796 pAd - pointer to our pAdapter context
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001797 ElementID - indicate the WPA1 or WPA2
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001798 apidx - indicate the interface index
1799
1800 Return Value:
1801
1802 Note:
1803
1804 ========================================================================
1805*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001806static void RTMPMakeRsnIeCap(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001807 u8 ElementID,
1808 u8 apidx,
1809 u8 *pRsnIe, u8 * rsn_len)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001810{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001811 RSN_CAPABILITIES *pRSN_Cap;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001812
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001813 /* it could be ignored in WPA1 mode */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001814 if (ElementID == WpaIe)
1815 return;
1816
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001817 pRSN_Cap = (RSN_CAPABILITIES *) (pRsnIe + (*rsn_len));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001818
1819 pRSN_Cap->word = cpu2le16(pRSN_Cap->word);
1820
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001821 (*rsn_len) += sizeof(RSN_CAPABILITIES); /* update current RSNIE length */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001822
1823}
1824
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001825/*
1826 ========================================================================
1827
1828 Routine Description:
1829 Build RSN IE context. It is not included element-ID and length.
1830
1831 Arguments:
1832 pAd - pointer to our pAdapter context
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001833 AuthMode - indicate the authentication mode
1834 WepStatus - indicate the encryption type
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001835 apidx - indicate the interface index
1836
1837 Return Value:
1838
1839 Note:
1840
1841 ========================================================================
1842*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001843void RTMPMakeRSNIE(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001844 u32 AuthMode, u32 WepStatus, u8 apidx)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001845{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001846 u8 *pRsnIe = NULL; /* primary RSNIE */
1847 u8 *rsnielen_cur_p = 0; /* the length of the primary RSNIE */
1848 u8 *rsnielen_ex_cur_p = 0; /* the length of the secondary RSNIE */
1849 u8 PrimaryRsnie;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001850 BOOLEAN bMixCipher = FALSE; /* indicate the pairwise and group cipher are different */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001851 u8 p_offset;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001852 WPA_MIX_PAIR_CIPHER FlexibleCipher = WPA_TKIPAES_WPA2_TKIPAES; /* it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001853
1854 rsnielen_cur_p = NULL;
1855 rsnielen_ex_cur_p = NULL;
1856
1857 {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001858 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001859 if (pAd->StaCfg.WpaSupplicantUP !=
1860 WPA_SUPPLICANT_DISABLE) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001861 if (AuthMode < Ndis802_11AuthModeWPA)
1862 return;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001863 } else {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001864 /* Support WPAPSK or WPA2PSK in STA-Infra mode */
1865 /* Support WPANone in STA-Adhoc mode */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001866 if ((AuthMode != Ndis802_11AuthModeWPAPSK) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001867 (AuthMode != Ndis802_11AuthModeWPA2PSK) &&
1868 (AuthMode != Ndis802_11AuthModeWPANone)
1869 )
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001870 return;
1871 }
1872
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001873 DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPMakeRSNIE(STA)\n"));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001874
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001875 /* Zero RSNIE context */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001876 pAd->StaCfg.RSNIE_Len = 0;
1877 NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE);
1878
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001879 /* Pointer to RSNIE */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001880 rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len;
1881 pRsnIe = pAd->StaCfg.RSN_IE;
1882
1883 bMixCipher = pAd->StaCfg.bMixCipher;
1884 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001885 }
1886
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001887 /* indicate primary RSNIE as WPA or WPA2 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001888 if ((AuthMode == Ndis802_11AuthModeWPA) ||
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001889 (AuthMode == Ndis802_11AuthModeWPAPSK) ||
1890 (AuthMode == Ndis802_11AuthModeWPANone) ||
1891 (AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
1892 (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001893 PrimaryRsnie = WpaIe;
1894 else
1895 PrimaryRsnie = Wpa2Ie;
1896
1897 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001898 /* Build the primary RSNIE */
1899 /* 1. insert cipher suite */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001900 RTMPMakeRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher,
1901 FlexibleCipher, pRsnIe, &p_offset);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001902
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001903 /* 2. insert AKM */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001904 RTMPMakeRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe,
1905 &p_offset);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001906
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001907 /* 3. insert capability */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001908 RTMPMakeRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001909 }
1910
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001911 /* 4. update the RSNIE length */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001912 *rsnielen_cur_p = p_offset;
1913
1914 hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p));
1915
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001916}
1917
1918/*
1919 ==========================================================================
1920 Description:
1921 Check whether the received frame is EAP frame.
1922
1923 Arguments:
1924 pAd - pointer to our pAdapter context
1925 pEntry - pointer to active entry
1926 pData - the received frame
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001927 DataByteCount - the received frame's length
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001928 FromWhichBSSID - indicate the interface index
1929
1930 Return:
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001931 TRUE - This frame is EAP frame
1932 FALSE - otherwise
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001933 ==========================================================================
1934*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001935BOOLEAN RTMPCheckWPAframe(struct rt_rtmp_adapter *pAd,
1936 struct rt_mac_table_entry *pEntry,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001937 u8 *pData,
1938 unsigned long DataByteCount, u8 FromWhichBSSID)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001939{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001940 unsigned long Body_len;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001941 BOOLEAN Cancelled;
1942
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001943 if (DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H))
1944 return FALSE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001945
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001946 /* Skip LLC header */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001947 if (NdisEqualMemory(SNAP_802_1H, pData, 6) ||
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001948 /* Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001949 NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6)) {
1950 pData += 6;
1951 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001952 /* Skip 2-bytes EAPoL type */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001953 if (NdisEqualMemory(EAPOL, pData, 2)) {
1954 pData += 2;
1955 } else
1956 return FALSE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001957
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001958 switch (*(pData + 1)) {
1959 case EAPPacket:
1960 Body_len = (*(pData + 2) << 8) | (*(pData + 3));
1961 DBGPRINT(RT_DEBUG_TRACE,
1962 ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n",
1963 Body_len));
1964 break;
1965 case EAPOLStart:
1966 DBGPRINT(RT_DEBUG_TRACE,
1967 ("Receive EAPOL-Start frame, TYPE = 1 \n"));
1968 if (pEntry->EnqueueEapolStartTimerRunning !=
1969 EAPOL_START_DISABLE) {
1970 DBGPRINT(RT_DEBUG_TRACE,
1971 ("Cancel the EnqueueEapolStartTimerRunning \n"));
1972 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer,
1973 &Cancelled);
1974 pEntry->EnqueueEapolStartTimerRunning =
1975 EAPOL_START_DISABLE;
1976 }
1977 break;
1978 case EAPOLLogoff:
1979 DBGPRINT(RT_DEBUG_TRACE,
1980 ("Receive EAPOLLogoff frame, TYPE = 2 \n"));
1981 break;
1982 case EAPOLKey:
1983 Body_len = (*(pData + 2) << 8) | (*(pData + 3));
1984 DBGPRINT(RT_DEBUG_TRACE,
1985 ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n",
1986 Body_len));
1987 break;
1988 case EAPOLASFAlert:
1989 DBGPRINT(RT_DEBUG_TRACE,
1990 ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));
1991 break;
1992 default:
1993 return FALSE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001994
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001995 }
1996 return TRUE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001997}
1998
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001999/*
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002000 ==========================================================================
2001 Description:
2002 Report the EAP message type
2003
2004 Arguments:
2005 msg - EAPOL_PAIR_MSG_1
2006 EAPOL_PAIR_MSG_2
2007 EAPOL_PAIR_MSG_3
2008 EAPOL_PAIR_MSG_4
2009 EAPOL_GROUP_MSG_1
2010 EAPOL_GROUP_MSG_2
2011
2012 Return:
2013 message type string
2014
2015 ==========================================================================
2016*/
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002017char *GetEapolMsgType(char msg)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002018{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002019 if (msg == EAPOL_PAIR_MSG_1)
2020 return "Pairwise Message 1";
2021 else if (msg == EAPOL_PAIR_MSG_2)
2022 return "Pairwise Message 2";
2023 else if (msg == EAPOL_PAIR_MSG_3)
2024 return "Pairwise Message 3";
2025 else if (msg == EAPOL_PAIR_MSG_4)
2026 return "Pairwise Message 4";
2027 else if (msg == EAPOL_GROUP_MSG_1)
2028 return "Group Message 1";
2029 else if (msg == EAPOL_GROUP_MSG_2)
2030 return "Group Message 2";
2031 else
2032 return "Invalid Message";
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002033}
2034
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002035/*
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002036 ========================================================================
2037
2038 Routine Description:
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002039 Check Sanity RSN IE of EAPoL message
2040
2041 Arguments:
2042
2043 Return Value:
2044
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002045 ========================================================================
2046*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002047BOOLEAN RTMPCheckRSNIE(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002048 u8 *pData,
2049 u8 DataLen,
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002050 struct rt_mac_table_entry *pEntry, u8 * Offset)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002051{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002052 u8 *pVIE;
2053 u8 len;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002054 struct rt_eid * pEid;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002055 BOOLEAN result = FALSE;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002056
2057 pVIE = pData;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002058 len = DataLen;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002059 *Offset = 0;
2060
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002061 while (len > sizeof(struct rt_rsnie2)) {
2062 pEid = (struct rt_eid *) pVIE;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002063 /* WPA RSN IE */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002064 if ((pEid->Eid == IE_WPA)
2065 && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))) {
2066 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA
2067 || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK)
2068 &&
2069 (NdisEqualMemory
2070 (pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len))
2071 && (pEntry->RSNIE_Len == (pEid->Len + 2))) {
2072 result = TRUE;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002073 }
2074
2075 *Offset += (pEid->Len + 2);
2076 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002077 /* WPA2 RSN IE */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002078 else if ((pEid->Eid == IE_RSN)
2079 && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))) {
2080 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2
2081 || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)
2082 && (pEid->Eid == pEntry->RSN_IE[0])
2083 && ((pEid->Len + 2) >= pEntry->RSNIE_Len)
2084 &&
2085 (NdisEqualMemory
2086 (pEid->Octet, &pEntry->RSN_IE[2],
2087 pEntry->RSNIE_Len - 2))) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002088
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002089 result = TRUE;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002090 }
2091
2092 *Offset += (pEid->Len + 2);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002093 } else {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002094 break;
2095 }
2096
2097 pVIE += (pEid->Len + 2);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002098 len -= (pEid->Len + 2);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002099 }
2100
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002101 return result;
2102
2103}
2104
2105/*
2106 ========================================================================
2107
2108 Routine Description:
2109 Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK.
2110 GTK is encaptulated in KDE format at p.83 802.11i D10
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002111
2112 Arguments:
2113
2114 Return Value:
2115
2116 Note:
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002117 802.11i D10
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002118
2119 ========================================================================
2120*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002121BOOLEAN RTMPParseEapolKeyData(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002122 u8 *pKeyData,
2123 u8 KeyDataLen,
2124 u8 GroupKeyIndex,
2125 u8 MsgType,
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002126 IN BOOLEAN bWPA2, struct rt_mac_table_entry *pEntry)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002127{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002128 struct rt_kde_encap * pKDE = NULL;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002129 u8 *pMyKeyData = pKeyData;
2130 u8 KeyDataLength = KeyDataLen;
2131 u8 GTKLEN = 0;
2132 u8 DefaultIdx = 0;
2133 u8 skip_offset;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002134
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002135 /* Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002136 if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002137 /* Check RSN IE whether it is WPA2/WPA2PSK */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002138 if (!RTMPCheckRSNIE
2139 (pAd, pKeyData, KeyDataLen, pEntry, &skip_offset)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002140 /* send wireless event - for RSN IE different */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002141 if (pAd->CommonCfg.bWirelessEvent)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002142 RTMPSendWirelessEvent(pAd,
2143 IW_RSNIE_DIFF_EVENT_FLAG,
2144 pEntry->Addr,
2145 pEntry->apidx, 0);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002146
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002147 DBGPRINT(RT_DEBUG_ERROR,
2148 ("RSN_IE Different in msg %d of 4-way handshake!\n",
2149 MsgType));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002150 hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002151 hex_dump("Desired RSN_IE ", pEntry->RSN_IE,
2152 pEntry->RSNIE_Len);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002153
2154 return FALSE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002155 } else {
2156 if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002157 WpaShowAllsuite(pMyKeyData, skip_offset);
2158
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002159 /* skip RSN IE */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002160 pMyKeyData += skip_offset;
2161 KeyDataLength -= skip_offset;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002162 DBGPRINT(RT_DEBUG_TRACE,
2163 ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n",
2164 skip_offset));
2165 } else
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002166 return TRUE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002167 }
2168 }
2169
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002170 DBGPRINT(RT_DEBUG_TRACE,
2171 ("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n",
2172 KeyDataLength));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002173 /*hex_dump("remain data", pMyKeyData, KeyDataLength); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002174
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002175 /* Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002176 if (bWPA2
2177 && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002178 if (KeyDataLength >= 8) /* KDE format exclude GTK length */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002179 {
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002180 pKDE = (struct rt_kde_encap *) pMyKeyData;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002181
2182 DefaultIdx = pKDE->GTKEncap.Kid;
2183
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002184 /* Sanity check - KED length */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002185 if (KeyDataLength < (pKDE->Len + 2)) {
2186 DBGPRINT(RT_DEBUG_ERROR,
2187 ("ERROR: The len from KDE is too short \n"));
2188 return FALSE;
2189 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002190 /* Get GTK length - refer to IEEE 802.11i-2004 p.82 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002191 GTKLEN = pKDE->Len - 6;
2192 if (GTKLEN < LEN_AES_KEY) {
2193 DBGPRINT(RT_DEBUG_ERROR,
2194 ("ERROR: GTK Key length is too short (%d) \n",
2195 GTKLEN));
2196 return FALSE;
2197 }
2198
2199 } else {
2200 DBGPRINT(RT_DEBUG_ERROR,
2201 ("ERROR: KDE format length is too short \n"));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002202 return FALSE;
2203 }
2204
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002205 DBGPRINT(RT_DEBUG_TRACE,
2206 ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n",
2207 DefaultIdx, GTKLEN));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002208 /* skip it */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002209 pMyKeyData += 8;
2210 KeyDataLength -= 8;
2211
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002212 } else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002213 DefaultIdx = GroupKeyIndex;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002214 DBGPRINT(RT_DEBUG_TRACE,
2215 ("GTK DefaultKeyID=%d \n", DefaultIdx));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002216 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002217 /* Sanity check - shared key index must be 1 ~ 3 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002218 if (DefaultIdx < 1 || DefaultIdx > 3) {
2219 DBGPRINT(RT_DEBUG_ERROR,
2220 ("ERROR: GTK Key index(%d) is invalid in %s %s \n",
2221 DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"),
2222 GetEapolMsgType(MsgType)));
2223 return FALSE;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002224 }
2225
2226 {
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002227 struct rt_cipher_key *pSharedKey;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002228
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002229 /* set key material, TxMic and RxMic */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002230 NdisMoveMemory(pAd->StaCfg.GTK, pMyKeyData, 32);
2231 pAd->StaCfg.DefaultKeyId = DefaultIdx;
2232
2233 pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId];
2234
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002235 /* Prepare pair-wise key information into shared key table */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002236 NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002237 pSharedKey->KeyLen = LEN_TKIP_EK;
2238 NdisMoveMemory(pSharedKey->Key, pAd->StaCfg.GTK, LEN_TKIP_EK);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002239 NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.GTK[16],
2240 LEN_TKIP_RXMICK);
2241 NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.GTK[24],
2242 LEN_TKIP_TXMICK);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002243
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002244 /* Update Shared Key CipherAlg */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002245 pSharedKey->CipherAlg = CIPHER_NONE;
2246 if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
2247 pSharedKey->CipherAlg = CIPHER_TKIP;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002248 else if (pAd->StaCfg.GroupCipher ==
2249 Ndis802_11Encryption3Enabled)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002250 pSharedKey->CipherAlg = CIPHER_AES;
2251 else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled)
2252 pSharedKey->CipherAlg = CIPHER_WEP64;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002253 else if (pAd->StaCfg.GroupCipher ==
2254 Ndis802_11GroupWEP104Enabled)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002255 pSharedKey->CipherAlg = CIPHER_WEP128;
2256
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002257 /* Update group key information to ASIC Shared Key Table */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002258 AsicAddSharedKeyEntry(pAd,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002259 BSS0,
2260 pAd->StaCfg.DefaultKeyId,
2261 pSharedKey->CipherAlg,
2262 pSharedKey->Key,
2263 pSharedKey->TxMic, pSharedKey->RxMic);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002264
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002265 /* Update ASIC WCID attribute table and IVEIV table */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002266 RTMPAddWcidAttributeEntry(pAd,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002267 BSS0,
2268 pAd->StaCfg.DefaultKeyId,
2269 pSharedKey->CipherAlg, NULL);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002270 }
2271
2272 return TRUE;
2273
2274}
2275
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002276/*
2277 ========================================================================
2278
2279 Routine Description:
2280 Construct EAPoL message for WPA handshaking
2281 Its format is below,
2282
2283 +--------------------+
2284 | Protocol Version | 1 octet
2285 +--------------------+
2286 | Protocol Type | 1 octet
2287 +--------------------+
2288 | Body Length | 2 octets
2289 +--------------------+
2290 | Descriptor Type | 1 octet
2291 +--------------------+
2292 | Key Information | 2 octets
2293 +--------------------+
2294 | Key Length | 1 octet
2295 +--------------------+
2296 | Key Repaly Counter | 8 octets
2297 +--------------------+
2298 | Key Nonce | 32 octets
2299 +--------------------+
2300 | Key IV | 16 octets
2301 +--------------------+
2302 | Key RSC | 8 octets
2303 +--------------------+
2304 | Key ID or Reserved | 8 octets
2305 +--------------------+
2306 | Key MIC | 16 octets
2307 +--------------------+
2308 | Key Data Length | 2 octets
2309 +--------------------+
2310 | Key Data | n octets
2311 +--------------------+
2312
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002313 Arguments:
2314 pAd Pointer to our adapter
2315
2316 Return Value:
2317 None
2318
2319 Note:
2320
2321 ========================================================================
2322*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002323void ConstructEapolMsg(struct rt_mac_table_entry *pEntry,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002324 u8 GroupKeyWepStatus,
2325 u8 MsgType,
2326 u8 DefaultKeyIdx,
2327 u8 * KeyNonce,
2328 u8 * TxRSC,
2329 u8 * GTK,
2330 u8 * RSNIE,
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002331 u8 RSNIE_Len, struct rt_eapol_packet * pMsg)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002332{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002333 BOOLEAN bWPA2 = FALSE;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002334 u8 KeyDescVer;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002335
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002336 /* Choose WPA2 or not */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002337 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) ||
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002338 (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002339 bWPA2 = TRUE;
2340
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002341 /* Init Packet and Fill header */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002342 pMsg->ProVer = EAPOL_VER;
2343 pMsg->ProType = EAPOLKey;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002344
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002345 /* Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002346 SET_u16_TO_ARRARY(pMsg->Body_Len, LEN_EAPOL_KEY_MSG);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002347
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002348 /* Fill in EAPoL descriptor */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002349 if (bWPA2)
2350 pMsg->KeyDesc.Type = WPA2_KEY_DESC;
2351 else
2352 pMsg->KeyDesc.Type = WPA1_KEY_DESC;
2353
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002354 /* Key Descriptor Version (bits 0-2) specifies the key descriptor version type */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002355 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002356 /* Fill in Key information, refer to IEEE Std 802.11i-2004 page 78 */
2357 /* When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002358 KeyDescVer =
2359 (((pEntry->WepStatus == Ndis802_11Encryption3Enabled)
2360 || (GroupKeyWepStatus ==
2361 Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES)
2362 : (DESC_TYPE_TKIP));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002363 }
2364
2365 pMsg->KeyDesc.KeyInfo.KeyDescVer = KeyDescVer;
2366
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002367 /* Specify Key Type as Group(0) or Pairwise(1) */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002368 if (MsgType >= EAPOL_GROUP_MSG_1)
2369 pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002370 else
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002371 pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
2372
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002373 /* Specify Key Index, only group_msg1_WPA1 */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002374 if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))
2375 pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx;
2376
2377 if (MsgType == EAPOL_PAIR_MSG_3)
2378 pMsg->KeyDesc.KeyInfo.Install = 1;
2379
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002380 if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3)
2381 || (MsgType == EAPOL_GROUP_MSG_1))
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002382 pMsg->KeyDesc.KeyInfo.KeyAck = 1;
2383
2384 if (MsgType != EAPOL_PAIR_MSG_1)
2385 pMsg->KeyDesc.KeyInfo.KeyMic = 1;
2386
2387 if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) ||
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002388 (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))) {
2389 pMsg->KeyDesc.KeyInfo.Secure = 1;
2390 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002391
2392 if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) ||
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002393 (MsgType == EAPOL_GROUP_MSG_1))) {
2394 pMsg->KeyDesc.KeyInfo.EKD_DL = 1;
2395 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002396 /* key Information element has done. */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002397 *(u16 *) (&pMsg->KeyDesc.KeyInfo) =
2398 cpu2le16(*(u16 *) (&pMsg->KeyDesc.KeyInfo));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002399
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002400 /* Fill in Key Length */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002401 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002402 if (MsgType >= EAPOL_GROUP_MSG_1) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002403 /* the length of group key cipher */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002404 pMsg->KeyDesc.KeyLength[1] =
2405 ((GroupKeyWepStatus ==
2406 Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH :
2407 LEN_AES_KEY);
2408 } else {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002409 /* the length of pairwise key cipher */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002410 pMsg->KeyDesc.KeyLength[1] =
2411 ((pEntry->WepStatus ==
2412 Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY :
2413 LEN_AES_KEY);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002414 }
2415 }
2416
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002417 /* Fill in replay counter */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002418 NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter,
2419 LEN_KEY_DESC_REPLAY);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002420
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002421 /* Fill Key Nonce field */
2422 /* ANonce : pairwise_msg1 & pairwise_msg3 */
2423 /* SNonce : pairwise_msg2 */
2424 /* GNonce : group_msg1_wpa1 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002425 if ((MsgType <= EAPOL_PAIR_MSG_3)
2426 || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))))
2427 NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce,
2428 LEN_KEY_DESC_NONCE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002429
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002430 /* Fill key IV - WPA2 as 0, WPA1 as random */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002431 if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002432 /* Suggest IV be random number plus some number, */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002433 NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16],
2434 LEN_KEY_DESC_IV);
2435 pMsg->KeyDesc.KeyIv[15] += 2;
2436 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002437 /* Fill Key RSC field */
2438 /* It contains the RSC for the GTK being installed. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002439 if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2)
2440 || (MsgType == EAPOL_GROUP_MSG_1)) {
2441 NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6);
2442 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002443 /* Clear Key MIC field for MIC calculation later */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002444 NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002445
2446 ConstructEapolKeyData(pEntry,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002447 GroupKeyWepStatus,
2448 KeyDescVer,
2449 MsgType,
2450 DefaultKeyIdx, GTK, RSNIE, RSNIE_Len, pMsg);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002451
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002452 /* Calculate MIC and fill in KeyMic Field except Pairwise Msg 1. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002453 if (MsgType != EAPOL_PAIR_MSG_1) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002454 CalculateMIC(KeyDescVer, pEntry->PTK, pMsg);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002455 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002456
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002457 DBGPRINT(RT_DEBUG_TRACE,
2458 ("===> ConstructEapolMsg for %s %s\n",
2459 ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
2460 DBGPRINT(RT_DEBUG_TRACE,
2461 (" Body length = %d \n",
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002462 CONV_ARRARY_TO_u16(pMsg->Body_Len)));
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002463 DBGPRINT(RT_DEBUG_TRACE,
2464 (" Key length = %d \n",
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002465 CONV_ARRARY_TO_u16(pMsg->KeyDesc.KeyLength)));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002466
2467}
2468
2469/*
2470 ========================================================================
2471
2472 Routine Description:
2473 Construct the Key Data field of EAPoL message
2474
2475 Arguments:
2476 pAd Pointer to our adapter
2477 Elem Message body
2478
2479 Return Value:
2480 None
2481
2482 Note:
2483
2484 ========================================================================
2485*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002486void ConstructEapolKeyData(struct rt_mac_table_entry *pEntry,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002487 u8 GroupKeyWepStatus,
2488 u8 keyDescVer,
2489 u8 MsgType,
2490 u8 DefaultKeyIdx,
2491 u8 * GTK,
2492 u8 * RSNIE,
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002493 u8 RSNIE_LEN, struct rt_eapol_packet * pMsg)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002494{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002495 u8 *mpool, *Key_Data, *Rc4GTK;
2496 u8 ekey[(LEN_KEY_DESC_IV + LEN_EAP_EK)];
2497 unsigned long data_offset;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002498 BOOLEAN bWPA2Capable = FALSE;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002499 struct rt_rtmp_adapter *pAd = pEntry->pAd;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002500 BOOLEAN GTK_Included = FALSE;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002501
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002502 /* Choose WPA2 or not */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002503 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) ||
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002504 (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002505 bWPA2Capable = TRUE;
2506
2507 if (MsgType == EAPOL_PAIR_MSG_1 ||
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002508 MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002509 return;
2510
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002511 /* allocate memory pool */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002512 os_alloc_mem(NULL, (u8 **) & mpool, 1500);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002513
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002514 if (mpool == NULL)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002515 return;
2516
2517 /* Rc4GTK Len = 512 */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002518 Rc4GTK = (u8 *) ROUND_UP(mpool, 4);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002519 /* Key_Data Len = 512 */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002520 Key_Data = (u8 *) ROUND_UP(Rc4GTK + 512, 4);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002521
2522 NdisZeroMemory(Key_Data, 512);
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002523 SET_u16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, 0);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002524 data_offset = 0;
2525
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002526 /* Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002527 if (RSNIE_LEN
2528 && ((MsgType == EAPOL_PAIR_MSG_2)
2529 || (MsgType == EAPOL_PAIR_MSG_3))) {
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002530 u8 *pmkid_ptr = NULL;
2531 u8 pmkid_len = 0;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002532
2533 RTMPInsertRSNIE(&Key_Data[data_offset],
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002534 &data_offset,
2535 RSNIE, RSNIE_LEN, pmkid_ptr, pmkid_len);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002536 }
2537
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002538 /* Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002539 if (bWPA2Capable
2540 && ((MsgType == EAPOL_PAIR_MSG_3)
2541 || (MsgType == EAPOL_GROUP_MSG_1))) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002542 /* Key Data Encapsulation (KDE) format - 802.11i-2004 Figure-43w and Table-20h */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002543 Key_Data[data_offset + 0] = 0xDD;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002544
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002545 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002546 Key_Data[data_offset + 1] = 0x16; /* 4+2+16(OUI+DataType+DataField) */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002547 } else {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002548 Key_Data[data_offset + 1] = 0x26; /* 4+2+32(OUI+DataType+DataField) */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002549 }
2550
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002551 Key_Data[data_offset + 2] = 0x00;
2552 Key_Data[data_offset + 3] = 0x0F;
2553 Key_Data[data_offset + 4] = 0xAC;
2554 Key_Data[data_offset + 5] = 0x01;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002555
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002556 /* GTK KDE format - 802.11i-2004 Figure-43x */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002557 Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002558 Key_Data[data_offset + 7] = 0x00; /* Reserved Byte */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002559
2560 data_offset += 8;
2561 }
2562
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002563 /* Encapsulate GTK */
2564 /* Only for pairwise_msg3_WPA2 and group_msg1 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002565 if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable)
2566 || (MsgType == EAPOL_GROUP_MSG_1)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002567 /* Fill in GTK */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002568 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) {
2569 NdisMoveMemory(&Key_Data[data_offset], GTK,
2570 LEN_AES_KEY);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002571 data_offset += LEN_AES_KEY;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002572 } else {
2573 NdisMoveMemory(&Key_Data[data_offset], GTK,
2574 TKIP_GTK_LENGTH);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002575 data_offset += TKIP_GTK_LENGTH;
2576 }
2577
2578 GTK_Included = TRUE;
2579 }
2580
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002581 /* This whole key-data field shall be encrypted if a GTK is included. */
2582 /* Encrypt the data material in key data field with KEK */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002583 if (GTK_Included) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002584 /*hex_dump("GTK_Included", Key_Data, data_offset); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002585
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002586 if ((keyDescVer == DESC_TYPE_AES)) {
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002587 u8 remainder = 0;
2588 u8 pad_len = 0;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002589
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002590 /* Key Descriptor Version 2 or 3: AES key wrap, defined in IETF RFC 3394, */
2591 /* shall be used to encrypt the Key Data field using the KEK field from */
2592 /* the derived PTK. */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002593
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002594 /* If the Key Data field uses the NIST AES key wrap, then the Key Data field */
2595 /* shall be padded before encrypting if the key data length is less than 16 */
2596 /* octets or if it is not a multiple of 8. The padding consists of appending */
2597 /* a single octet 0xdd followed by zero or more 0x00 octets. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002598 if ((remainder = data_offset & 0x07) != 0) {
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002599 int i;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002600
2601 pad_len = (8 - remainder);
2602 Key_Data[data_offset] = 0xDD;
2603 for (i = 1; i < pad_len; i++)
2604 Key_Data[data_offset + i] = 0;
2605
2606 data_offset += pad_len;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002607 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002608
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002609 AES_GTK_KEY_WRAP(&pEntry->PTK[16], Key_Data,
2610 data_offset, Rc4GTK);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002611 /* AES wrap function will grow 8 bytes in length */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002612 data_offset += 8;
2613 } else {
2614 /* Key Descriptor Version 1: ARC4 is used to encrypt the Key Data field
2615 using the KEK field from the derived PTK. */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002616
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002617 /* PREPARE Encrypted "Key DATA" field. (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV) */
2618 /* put TxTsc in Key RSC field */
2619 pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; /*Init crc32. */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002620
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002621 /* ekey is the contanetion of IV-field, and PTK[16]->PTK[31] */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002622 NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv,
2623 LEN_KEY_DESC_IV);
2624 NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &pEntry->PTK[16],
2625 LEN_EAP_EK);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002626 ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey)); /*INIT SBOX, KEYLEN+3(IV) */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002627 pAd->PrivateInfo.FCSCRC32 =
2628 RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, Key_Data,
2629 data_offset);
2630 WPAARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, Rc4GTK,
2631 Key_Data, data_offset);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002632 }
2633
2634 NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002635 } else {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002636 NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset);
2637 }
2638
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002639 /* Update key data length field and total body length */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002640 SET_u16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, data_offset);
2641 INC_u16_TO_ARRARY(pMsg->Body_Len, data_offset);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002642
2643 os_free_mem(NULL, mpool);
2644
2645}
2646
2647/*
2648 ========================================================================
2649
2650 Routine Description:
2651 Calcaulate MIC. It is used during 4-ways handsharking.
2652
2653 Arguments:
2654 pAd - pointer to our pAdapter context
2655 PeerWepStatus - indicate the encryption type
2656
2657 Return Value:
2658
2659 Note:
2660
2661 ========================================================================
2662*/
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002663static void CalculateMIC(u8 KeyDescVer,
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002664 u8 * PTK, struct rt_eapol_packet * pMsg)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002665{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002666 u8 *OutBuffer;
2667 unsigned long FrameLen = 0;
2668 u8 mic[LEN_KEY_DESC_MIC];
2669 u8 digest[80];
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002670
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002671 /* allocate memory for MIC calculation */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002672 os_alloc_mem(NULL, (u8 **) & OutBuffer, 512);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002673
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002674 if (OutBuffer == NULL) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002675 DBGPRINT(RT_DEBUG_ERROR, ("!!!CalculateMIC: no memory!!!\n"));
2676 return;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002677 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002678 /* make a frame for calculating MIC. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002679 MakeOutgoingFrame(OutBuffer, &FrameLen,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002680 CONV_ARRARY_TO_u16(pMsg->Body_Len) + 4, pMsg,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002681 END_OF_ARGS);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002682
2683 NdisZeroMemory(mic, sizeof(mic));
2684
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002685 /* Calculate MIC */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002686 if (KeyDescVer == DESC_TYPE_AES) {
2687 HMAC_SHA1(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, digest,
2688 SHA1_DIGEST_SIZE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002689 NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002690 } else {
2691 HMAC_MD5(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, mic,
2692 MD5_DIGEST_SIZE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002693 }
2694
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002695 /* store the calculated MIC */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002696 NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC);
2697
2698 os_free_mem(NULL, OutBuffer);
2699}
2700
2701/*
2702 ========================================================================
2703
2704 Routine Description:
2705 Some received frames can't decrypt by Asic, so decrypt them by software.
2706
2707 Arguments:
2708 pAd - pointer to our pAdapter context
2709 PeerWepStatus - indicate the encryption type
2710
2711 Return Value:
2712 NDIS_STATUS_SUCCESS - decryption successful
2713 NDIS_STATUS_FAILURE - decryption failure
2714
2715 ========================================================================
2716*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002717int RTMPSoftDecryptBroadCastData(struct rt_rtmp_adapter *pAd,
2718 struct rt_rx_blk *pRxBlk,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002719 IN NDIS_802_11_ENCRYPTION_STATUS
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002720 GroupCipher, struct rt_cipher_key *pShard_key)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002721{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002722 struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002723
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002724 /* handle WEP decryption */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002725 if (GroupCipher == Ndis802_11Encryption1Enabled) {
2726 if (RTMPSoftDecryptWEP
2727 (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount,
2728 pShard_key)) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002729
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002730 /*Minus IV[4] & ICV[4] */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002731 pRxWI->MPDUtotalByteCount -= 8;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002732 } else {
2733 DBGPRINT(RT_DEBUG_ERROR,
2734 ("ERROR : Software decrypt WEP data fails.\n"));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002735 /* give up this frame */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002736 return NDIS_STATUS_FAILURE;
2737 }
2738 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002739 /* handle TKIP decryption */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002740 else if (GroupCipher == Ndis802_11Encryption2Enabled) {
2741 if (RTMPSoftDecryptTKIP
2742 (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0,
2743 pShard_key)) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002744
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002745 /*Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002746 pRxWI->MPDUtotalByteCount -= 20;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002747 } else {
2748 DBGPRINT(RT_DEBUG_ERROR,
2749 ("ERROR : RTMPSoftDecryptTKIP Failed\n"));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002750 /* give up this frame */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002751 return NDIS_STATUS_FAILURE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002752 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002753 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002754 /* handle AES decryption */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002755 else if (GroupCipher == Ndis802_11Encryption3Enabled) {
2756 if (RTMPSoftDecryptAES
2757 (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount,
2758 pShard_key)) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002759
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002760 /*8 bytes MIC, 8 bytes IV/EIV (CCMP Header) */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002761 pRxWI->MPDUtotalByteCount -= 16;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002762 } else {
2763 DBGPRINT(RT_DEBUG_ERROR,
2764 ("ERROR : RTMPSoftDecryptAES Failed\n"));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002765 /* give up this frame */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002766 return NDIS_STATUS_FAILURE;
2767 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002768 } else {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002769 /* give up this frame */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002770 return NDIS_STATUS_FAILURE;
2771 }
2772
2773 return NDIS_STATUS_SUCCESS;
2774
2775}
2776
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002777u8 *GetSuiteFromRSNIE(u8 *rsnie,
2778 u32 rsnie_len, u8 type, u8 * count)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002779{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002780 struct rt_eid * pEid;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002781 int len;
2782 u8 *pBuf;
2783 int offset = 0;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002784 struct rt_rsnie_auth *pAkm;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002785 u16 acount;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002786 BOOLEAN isWPA2 = FALSE;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002787
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002788 pEid = (struct rt_eid *) rsnie;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002789 len = rsnie_len - 2; /* exclude IE and length */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002790 pBuf = (u8 *)& pEid->Octet[0];
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002791
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002792 /* set default value */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002793 *count = 0;
2794
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002795 /* Check length */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002796 if ((len <= 0) || (pEid->Len != len)) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002797 DBGPRINT_ERR(("%s : The length is invalid\n", __func__));
2798 return NULL;
2799 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002800 /* Check WPA or WPA2 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002801 if (pEid->Eid == IE_WPA) {
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002802 struct rt_rsnie *pRsnie = (struct rt_rsnie *)pBuf;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002803 u16 ucount;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002804
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002805 if (len < sizeof(struct rt_rsnie)) {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002806 DBGPRINT_ERR(("%s : The length is too short for WPA\n",
2807 __func__));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002808 return NULL;
2809 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002810 /* Get the count of pairwise cipher */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002811 ucount = cpu2le16(pRsnie->ucount);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002812 if (ucount > 2) {
2813 DBGPRINT_ERR(("%s : The count(%d) of pairwise cipher is invlaid\n", __func__, ucount));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002814 return NULL;
2815 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002816 /* Get the group cipher */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002817 if (type == GROUP_SUITE) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002818 *count = 1;
2819 return pRsnie->mcast;
2820 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002821 /* Get the pairwise cipher suite */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002822 else if (type == PAIRWISE_SUITE) {
2823 DBGPRINT(RT_DEBUG_TRACE,
2824 ("%s : The count of pairwise cipher is %d\n",
2825 __func__, ucount));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002826 *count = ucount;
2827 return pRsnie->ucast[0].oui;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002828 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002829
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002830 offset = sizeof(struct rt_rsnie) + (4 * (ucount - 1));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002831
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002832 } else if (pEid->Eid == IE_RSN) {
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002833 struct rt_rsnie2 *pRsnie = (struct rt_rsnie2 *)pBuf;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002834 u16 ucount;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002835
2836 isWPA2 = TRUE;
2837
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002838 if (len < sizeof(struct rt_rsnie2)) {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002839 DBGPRINT_ERR(("%s : The length is too short for WPA2\n",
2840 __func__));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002841 return NULL;
2842 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002843 /* Get the count of pairwise cipher */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002844 ucount = cpu2le16(pRsnie->ucount);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002845 if (ucount > 2) {
2846 DBGPRINT_ERR(("%s : The count(%d) of pairwise cipher is invlaid\n", __func__, ucount));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002847 return NULL;
2848 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002849 /* Get the group cipher */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002850 if (type == GROUP_SUITE) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002851 *count = 1;
2852 return pRsnie->mcast;
2853 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002854 /* Get the pairwise cipher suite */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002855 else if (type == PAIRWISE_SUITE) {
2856 DBGPRINT(RT_DEBUG_TRACE,
2857 ("%s : The count of pairwise cipher is %d\n",
2858 __func__, ucount));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002859 *count = ucount;
2860 return pRsnie->ucast[0].oui;
2861 }
2862
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002863 offset = sizeof(struct rt_rsnie2) + (4 * (ucount - 1));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002864
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002865 } else {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002866 DBGPRINT_ERR(("%s : Unknown IE (%d)\n", __func__, pEid->Eid));
2867 return NULL;
2868 }
2869
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002870 /* skip group cipher and pairwise cipher suite */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002871 pBuf += offset;
2872 len -= offset;
2873
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002874 if (len < sizeof(struct rt_rsnie_auth)) {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002875 DBGPRINT_ERR(("%s : The length of RSNIE is too short\n",
2876 __func__));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002877 return NULL;
2878 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002879 /* pointer to AKM count */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002880 pAkm = (struct rt_rsnie_auth *)pBuf;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002881
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002882 /* Get the count of pairwise cipher */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002883 acount = cpu2le16(pAkm->acount);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002884 if (acount > 2) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002885 DBGPRINT_ERR(("%s : The count(%d) of AKM is invlaid\n",
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002886 __func__, acount));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002887 return NULL;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002888 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002889 /* Get the AKM suite */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002890 if (type == AKM_SUITE) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002891 DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of AKM is %d\n",
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002892 __func__, acount));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002893 *count = acount;
2894 return pAkm->auth[0].oui;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002895 }
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002896 offset = sizeof(struct rt_rsnie_auth) + (4 * (acount - 1));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002897
2898 pBuf += offset;
2899 len -= offset;
2900
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002901 /* The remaining length must larger than (RSN-Capability(2) + PMKID-Count(2) + PMKID(16~)) */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002902 if (len >= (sizeof(RSN_CAPABILITIES) + 2 + LEN_PMKID)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002903 /* Skip RSN capability and PMKID-Count */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002904 pBuf += (sizeof(RSN_CAPABILITIES) + 2);
2905 len -= (sizeof(RSN_CAPABILITIES) + 2);
2906
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002907 /* Get PMKID */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002908 if (type == PMKID_LIST) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002909 *count = 1;
2910 return pBuf;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002911 }
2912 } else {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002913 DBGPRINT_ERR(("%s : it can't get any more information beyond AKM \n", __func__));
2914 return NULL;
2915 }
2916
2917 *count = 0;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002918 /*DBGPRINT_ERR(("%s : The type(%d) doesn't support \n", __func__, type)); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002919 return NULL;
2920
2921}
2922
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002923void WpaShowAllsuite(u8 *rsnie, u32 rsnie_len)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002924{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002925 u8 *pSuite = NULL;
2926 u8 count;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002927
2928 hex_dump("RSNIE", rsnie, rsnie_len);
2929
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002930 /* group cipher */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002931 if ((pSuite =
2932 GetSuiteFromRSNIE(rsnie, rsnie_len, GROUP_SUITE,
2933 &count)) != NULL) {
2934 hex_dump("group cipher", pSuite, 4 * count);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002935 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002936 /* pairwise cipher */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002937 if ((pSuite =
2938 GetSuiteFromRSNIE(rsnie, rsnie_len, PAIRWISE_SUITE,
2939 &count)) != NULL) {
2940 hex_dump("pairwise cipher", pSuite, 4 * count);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002941 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002942 /* AKM */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002943 if ((pSuite =
2944 GetSuiteFromRSNIE(rsnie, rsnie_len, AKM_SUITE, &count)) != NULL) {
2945 hex_dump("AKM suite", pSuite, 4 * count);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002946 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002947 /* PMKID */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002948 if ((pSuite =
2949 GetSuiteFromRSNIE(rsnie, rsnie_len, PMKID_LIST, &count)) != NULL) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002950 hex_dump("PMKID", pSuite, LEN_PMKID);
2951 }
2952
2953}
2954
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002955void RTMPInsertRSNIE(u8 *pFrameBuf,
2956 unsigned long *pFrameLen,
2957 u8 *rsnie_ptr,
2958 u8 rsnie_len,
2959 u8 *pmkid_ptr, u8 pmkid_len)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002960{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002961 u8 *pTmpBuf;
2962 unsigned long TempLen = 0;
2963 u8 extra_len = 0;
2964 u16 pmk_count = 0;
2965 u8 ie_num;
2966 u8 total_len = 0;
2967 u8 WPA2_OUI[3] = { 0x00, 0x0F, 0xAC };
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002968
2969 pTmpBuf = pFrameBuf;
2970
2971 /* PMKID-List Must larger than 0 and the multiple of 16. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002972 if (pmkid_len > 0 && ((pmkid_len & 0x0f) == 0)) {
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002973 extra_len = sizeof(u16)+ pmkid_len;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002974
2975 pmk_count = (pmkid_len >> 4);
2976 pmk_count = cpu2le16(pmk_count);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002977 } else {
2978 DBGPRINT(RT_DEBUG_WARN,
2979 ("%s : The length is PMKID-List is invalid (%d), so don't insert it.\n",
2980 __func__, pmkid_len));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002981 }
2982
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002983 if (rsnie_len != 0) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002984 ie_num = IE_WPA;
2985 total_len = rsnie_len;
2986
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002987 if (NdisEqualMemory(rsnie_ptr + 2, WPA2_OUI, sizeof(WPA2_OUI))) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002988 ie_num = IE_RSN;
2989 total_len += extra_len;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002990 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002991
2992 /* construct RSNIE body */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002993 MakeOutgoingFrame(pTmpBuf, &TempLen,
2994 1, &ie_num,
2995 1, &total_len,
2996 rsnie_len, rsnie_ptr, END_OF_ARGS);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002997
2998 pTmpBuf += TempLen;
2999 *pFrameLen = *pFrameLen + TempLen;
3000
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003001 if (ie_num == IE_RSN) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003002 /* Insert PMKID-List field */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003003 if (extra_len > 0) {
3004 MakeOutgoingFrame(pTmpBuf, &TempLen,
3005 2, &pmk_count,
3006 pmkid_len, pmkid_ptr,
3007 END_OF_ARGS);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003008
3009 pTmpBuf += TempLen;
3010 *pFrameLen = *pFrameLen + TempLen;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003011 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003012 }
3013 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003014
3015 return;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003016}