]>
Commit | Line | Data |
---|---|---|
91980990 GKH |
1 | /* |
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" | |
ec278fa2 | 39 | /* WPA OUI */ |
51126deb BZ |
40 | u8 OUI_WPA_NONE_AKM[4] = { 0x00, 0x50, 0xF2, 0x00 }; |
41 | u8 OUI_WPA_VERSION[4] = { 0x00, 0x50, 0xF2, 0x01 }; | |
42 | u8 OUI_WPA_WEP40[4] = { 0x00, 0x50, 0xF2, 0x01 }; | |
43 | u8 OUI_WPA_TKIP[4] = { 0x00, 0x50, 0xF2, 0x02 }; | |
44 | u8 OUI_WPA_CCMP[4] = { 0x00, 0x50, 0xF2, 0x04 }; | |
45 | u8 OUI_WPA_WEP104[4] = { 0x00, 0x50, 0xF2, 0x05 }; | |
46 | u8 OUI_WPA_8021X_AKM[4] = { 0x00, 0x50, 0xF2, 0x01 }; | |
47 | u8 OUI_WPA_PSK_AKM[4] = { 0x00, 0x50, 0xF2, 0x02 }; | |
96b3c83d | 48 | |
ec278fa2 | 49 | /* WPA2 OUI */ |
51126deb BZ |
50 | u8 OUI_WPA2_WEP40[4] = { 0x00, 0x0F, 0xAC, 0x01 }; |
51 | u8 OUI_WPA2_TKIP[4] = { 0x00, 0x0F, 0xAC, 0x02 }; | |
52 | u8 OUI_WPA2_CCMP[4] = { 0x00, 0x0F, 0xAC, 0x04 }; | |
53 | u8 OUI_WPA2_8021X_AKM[4] = { 0x00, 0x0F, 0xAC, 0x01 }; | |
54 | u8 OUI_WPA2_PSK_AKM[4] = { 0x00, 0x0F, 0xAC, 0x02 }; | |
55 | u8 OUI_WPA2_WEP104[4] = { 0x00, 0x0F, 0xAC, 0x05 }; | |
56 | ||
62eb734b | 57 | static void ConstructEapolKeyData(struct rt_mac_table_entry *pEntry, |
51126deb BZ |
58 | u8 GroupKeyWepStatus, |
59 | u8 keyDescVer, | |
60 | u8 MsgType, | |
61 | u8 DefaultKeyIdx, | |
62 | u8 * GTK, | |
63 | u8 * RSNIE, | |
62eb734b | 64 | u8 RSNIE_LEN, struct rt_eapol_packet * pMsg); |
51126deb BZ |
65 | |
66 | static void CalculateMIC(u8 KeyDescVer, | |
62eb734b | 67 | u8 * PTK, struct rt_eapol_packet * pMsg); |
51126deb | 68 | |
62eb734b | 69 | static void WpaEAPPacketAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); |
51126deb | 70 | |
62eb734b BZ |
71 | static void WpaEAPOLASFAlertAction(struct rt_rtmp_adapter *pAd, |
72 | struct rt_mlme_queue_elem *Elem); | |
96b3c83d | 73 | |
62eb734b BZ |
74 | static void WpaEAPOLLogoffAction(struct rt_rtmp_adapter *pAd, |
75 | struct rt_mlme_queue_elem *Elem); | |
96b3c83d | 76 | |
62eb734b BZ |
77 | static void WpaEAPOLStartAction(struct rt_rtmp_adapter *pAd, |
78 | struct rt_mlme_queue_elem *Elem); | |
96b3c83d | 79 | |
62eb734b | 80 | static void WpaEAPOLKeyAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); |
91980990 GKH |
81 | |
82 | /* | |
ca97b838 BZ |
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 | */ | |
62eb734b BZ |
90 | void WpaStateMachineInit(struct rt_rtmp_adapter *pAd, |
91 | struct rt_state_machine *S, OUT STATE_MACHINE_FUNC Trans[]) | |
ca97b838 | 92 | { |
96b3c83d BZ |
93 | StateMachineInit(S, (STATE_MACHINE_FUNC *) Trans, MAX_WPA_PTK_STATE, |
94 | MAX_WPA_MSG, (STATE_MACHINE_FUNC) Drop, WPA_PTK, | |
95 | WPA_MACHINE_BASE); | |
96 | ||
97 | 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); | |
ca97b838 | 107 | } |
91980990 | 108 | |
ca97b838 BZ |
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 | */ | |
62eb734b | 118 | void WpaEAPPacketAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) |
ca97b838 BZ |
119 | { |
120 | } | |
121 | ||
62eb734b | 122 | void WpaEAPOLASFAlertAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) |
ca97b838 BZ |
123 | { |
124 | } | |
125 | ||
62eb734b | 126 | void WpaEAPOLLogoffAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) |
ca97b838 BZ |
127 | { |
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 | */ | |
62eb734b | 137 | void WpaEAPOLStartAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) |
ca97b838 | 138 | { |
62eb734b BZ |
139 | struct rt_mac_table_entry *pEntry; |
140 | struct rt_header_802_11 * pHeader; | |
96b3c83d BZ |
141 | |
142 | DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLStartAction ===> \n")); | |
143 | ||
62eb734b | 144 | pHeader = (struct rt_header_802_11 *) Elem->Msg; |
96b3c83d | 145 | |
ec278fa2 | 146 | /*For normaol PSK, we enqueue an EAPOL-Start command to trigger the process. */ |
96b3c83d BZ |
147 | if (Elem->MsgLen == 6) |
148 | pEntry = MacTableLookup(pAd, Elem->Msg); | |
149 | else { | |
150 | pEntry = MacTableLookup(pAd, pHeader->Addr2); | |
151 | } | |
152 | ||
153 | 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)); | |
158 | ||
159 | 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; | |
171 | ||
172 | WPAStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV); | |
173 | } | |
174 | } | |
ca97b838 BZ |
175 | } |
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 | */ | |
62eb734b | 190 | void WpaEAPOLKeyAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) |
ca97b838 | 191 | { |
62eb734b BZ |
192 | 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; | |
ca97b838 | 196 | |
96b3c83d | 197 | DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLKeyAction ===>\n")); |
ca97b838 | 198 | |
62eb734b | 199 | pHeader = (struct rt_header_802_11 *) Elem->Msg; |
96b3c83d | 200 | pEapol_packet = |
62eb734b | 201 | (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; |
ca97b838 | 202 | |
51126deb BZ |
203 | NdisZeroMemory((u8 *)& peerKeyInfo, sizeof(peerKeyInfo)); |
204 | NdisMoveMemory((u8 *)& peerKeyInfo, | |
205 | (u8 *)& pEapol_packet->KeyDesc.KeyInfo, | |
62eb734b | 206 | sizeof(struct rt_key_info)); |
ca97b838 | 207 | |
96b3c83d BZ |
208 | hex_dump("Received Eapol frame", (unsigned char *)pEapol_packet, |
209 | (Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H)); | |
ca97b838 | 210 | |
51126deb | 211 | *((u16 *) & peerKeyInfo) = cpu2le16(*((u16 *) & peerKeyInfo)); |
ca97b838 | 212 | |
96b3c83d BZ |
213 | do { |
214 | pEntry = MacTableLookup(pAd, pHeader->Addr2); | |
ca97b838 | 215 | |
96b3c83d BZ |
216 | if (!pEntry |
217 | || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli))) | |
218 | break; | |
ca97b838 BZ |
219 | |
220 | if (pEntry->AuthMode < Ndis802_11AuthModeWPA) | |
96b3c83d | 221 | break; |
ca97b838 | 222 | |
96b3c83d BZ |
223 | DBGPRINT(RT_DEBUG_TRACE, |
224 | ("Receive EAPoL-Key frame from STA %02X-%02X-%02X-%02X-%02X-%02X\n", | |
225 | PRINT_MAC(pEntry->Addr))); | |
ca97b838 | 226 | |
96b3c83d BZ |
227 | 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 | } | |
ec278fa2 BZ |
235 | /* 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. */ | |
96b3c83d BZ |
237 | 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 | } | |
ec278fa2 BZ |
243 | /* 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. */ | |
96b3c83d BZ |
245 | 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 | } | |
ec278fa2 | 251 | /* Check if this STA is in class 3 state and the WPA state is started */ |
96b3c83d BZ |
252 | if ((pEntry->Sst == SST_ASSOC) |
253 | && (pEntry->WpaState >= AS_INITPSK)) { | |
ec278fa2 BZ |
254 | /* 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. */ | |
96b3c83d | 258 | if (peerKeyInfo.KeyAck == 1) { |
ec278fa2 BZ |
259 | /* The frame is snet by Authenticator. */ |
260 | /* So the Supplicant side shall handle this. */ | |
ca97b838 | 261 | |
96b3c83d BZ |
262 | if ((peerKeyInfo.Secure == 0) |
263 | && (peerKeyInfo.Request == 0) | |
264 | && (peerKeyInfo.Error == 0) | |
265 | && (peerKeyInfo.KeyType == PAIRWISEKEY)) { | |
ec278fa2 BZ |
266 | /* 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) */ | |
ca97b838 | 270 | if (peerKeyInfo.KeyMic == 0) |
96b3c83d BZ |
271 | PeerPairMsg1Action(pAd, pEntry, |
272 | Elem); | |
273 | else | |
274 | PeerPairMsg3Action(pAd, pEntry, | |
275 | Elem); | |
276 | } else if ((peerKeyInfo.Secure == 1) | |
277 | && (peerKeyInfo.KeyMic == 1) | |
278 | && (peerKeyInfo.Request == 0) | |
279 | && (peerKeyInfo.Error == 0)) { | |
ec278fa2 BZ |
280 | /* 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]) */ | |
ca97b838 | 284 | if (peerKeyInfo.KeyType == PAIRWISEKEY) |
96b3c83d BZ |
285 | PeerPairMsg3Action(pAd, pEntry, |
286 | Elem); | |
ca97b838 | 287 | else |
96b3c83d BZ |
288 | PeerGroupMsg1Action(pAd, pEntry, |
289 | Elem); | |
ca97b838 | 290 | } |
96b3c83d | 291 | } else { |
ec278fa2 BZ |
292 | /* The frame is snet by Supplicant. */ |
293 | /* So the Authenticator side shall handle this. */ | |
ca97b838 | 294 | if ((peerKeyInfo.Request == 0) && |
96b3c83d BZ |
295 | (peerKeyInfo.Error == 0) && |
296 | (peerKeyInfo.KeyMic == 1)) { | |
297 | if (peerKeyInfo.Secure == 0 | |
298 | && peerKeyInfo.KeyType == | |
299 | PAIRWISEKEY) { | |
ec278fa2 BZ |
300 | /* 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 */ | |
51126deb | 303 | if (CONV_ARRARY_TO_u16 |
96b3c83d BZ |
304 | (pEapol_packet->KeyDesc. |
305 | KeyDataLen) == 0) { | |
306 | PeerPairMsg4Action(pAd, | |
307 | pEntry, | |
308 | Elem); | |
309 | } else { | |
310 | PeerPairMsg2Action(pAd, | |
311 | pEntry, | |
312 | Elem); | |
ca97b838 | 313 | } |
96b3c83d BZ |
314 | } else if (peerKeyInfo.Secure == 1 |
315 | && peerKeyInfo.KeyType == | |
316 | PAIRWISEKEY) { | |
ec278fa2 BZ |
317 | /* EAPOL-Key(1,1,0,0,P,0,0,0,MIC,0) */ |
318 | /* Process message 4 of 4-way HS in WPA2 */ | |
96b3c83d BZ |
319 | PeerPairMsg4Action(pAd, pEntry, |
320 | Elem); | |
321 | } else if (peerKeyInfo.Secure == 1 | |
322 | && peerKeyInfo.KeyType == | |
323 | GROUPKEY) { | |
ec278fa2 BZ |
324 | /* EAPOL-Key(1,1,0,0,G,0,0,0,MIC,0) */ |
325 | /* Process message 2 of Group key HS in WPA or WPA2 */ | |
96b3c83d BZ |
326 | PeerGroupMsg2Action(pAd, pEntry, |
327 | &Elem-> | |
328 | Msg | |
329 | [LENGTH_802_11], | |
330 | (Elem-> | |
331 | MsgLen - | |
332 | LENGTH_802_11)); | |
ca97b838 BZ |
333 | } |
334 | } | |
335 | } | |
96b3c83d BZ |
336 | } |
337 | } while (FALSE); | |
ca97b838 BZ |
338 | } |
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. | |
91980990 GKH |
347 | |
348 | Arguments: | |
ca97b838 | 349 | pAd Pointer to our adapter |
8a10a546 | 350 | void * Pointer to outgoing Ndis frame |
ca97b838 | 351 | NumberOfFrag Number of fragment required |
91980990 GKH |
352 | |
353 | Return Value: | |
ca97b838 | 354 | None |
91980990 GKH |
355 | |
356 | Note: | |
91980990 GKH |
357 | |
358 | ======================================================================== | |
359 | */ | |
62eb734b BZ |
360 | void RTMPToWirelessSta(struct rt_rtmp_adapter *pAd, |
361 | struct rt_mac_table_entry *pEntry, | |
51126deb BZ |
362 | u8 *pHeader802_3, |
363 | u32 HdrLen, | |
364 | u8 *pData, u32 DataLen, IN BOOLEAN bClearFrame) | |
91980990 | 365 | { |
8a10a546 | 366 | void *pPacket; |
51126deb | 367 | int Status; |
91980990 | 368 | |
ca97b838 BZ |
369 | if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli))) |
370 | return; | |
91980990 | 371 | |
96b3c83d | 372 | do { |
ec278fa2 | 373 | /* build a NDIS packet */ |
96b3c83d BZ |
374 | Status = |
375 | RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen, | |
376 | pData, DataLen); | |
ca97b838 | 377 | if (Status != NDIS_STATUS_SUCCESS) |
96b3c83d | 378 | break; |
ca97b838 | 379 | |
96b3c83d BZ |
380 | if (bClearFrame) |
381 | RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 1); | |
382 | else | |
383 | RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 0); | |
ca97b838 BZ |
384 | { |
385 | RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS); | |
386 | ||
ec278fa2 | 387 | RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, MAIN_MBSSID); /* set a default value */ |
96b3c83d BZ |
388 | if (pEntry->apidx != 0) |
389 | RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, | |
390 | pEntry-> | |
391 | apidx); | |
ca97b838 | 392 | |
51126deb | 393 | RTMP_SET_PACKET_WCID(pPacket, (u8)pEntry->Aid); |
ca97b838 BZ |
394 | RTMP_SET_PACKET_MOREDATA(pPacket, FALSE); |
395 | } | |
396 | ||
397 | { | |
ec278fa2 | 398 | /* send out the packet */ |
96b3c83d BZ |
399 | Status = STASendPacket(pAd, pPacket); |
400 | if (Status == NDIS_STATUS_SUCCESS) { | |
51126deb | 401 | u8 Index; |
ca97b838 | 402 | |
ec278fa2 BZ |
403 | /* 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 */ | |
96b3c83d BZ |
408 | 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); | |
ca97b838 BZ |
420 | } |
421 | } | |
422 | } | |
423 | ||
96b3c83d | 424 | } while (FALSE); |
ca97b838 BZ |
425 | } |
426 | ||
427 | /* | |
428 | ========================================================================== | |
429 | Description: | |
421f91d2 | 430 | This is a function to initialize 4-way handshake |
ca97b838 BZ |
431 | |
432 | Return: | |
433 | ||
434 | ========================================================================== | |
435 | */ | |
62eb734b BZ |
436 | void WPAStart4WayHS(struct rt_rtmp_adapter *pAd, |
437 | struct rt_mac_table_entry *pEntry, unsigned long TimeInterval) | |
ca97b838 | 438 | { |
51126deb | 439 | u8 Header802_3[14]; |
62eb734b | 440 | struct rt_eapol_packet EAPOLPKT; |
51126deb BZ |
441 | u8 *pBssid = NULL; |
442 | u8 group_cipher = Ndis802_11WEPDisabled; | |
ca97b838 | 443 | |
96b3c83d | 444 | DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart4WayHS\n")); |
ca97b838 | 445 | |
96b3c83d BZ |
446 | if (RTMP_TEST_FLAG |
447 | (pAd, | |
448 | fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS)) | |
ca97b838 | 449 | { |
96b3c83d BZ |
450 | DBGPRINT(RT_DEBUG_ERROR, |
451 | ("[ERROR]WPAStart4WayHS : The interface is closed...\n")); | |
ca97b838 BZ |
452 | return; |
453 | } | |
454 | ||
96b3c83d BZ |
455 | if (pBssid == NULL) { |
456 | DBGPRINT(RT_DEBUG_ERROR, | |
457 | ("[ERROR]WPAStart4WayHS : No corresponding Authenticator.\n")); | |
ca97b838 | 458 | return; |
96b3c83d | 459 | } |
ec278fa2 | 460 | /* Check the status */ |
96b3c83d BZ |
461 | if ((pEntry->WpaState > AS_PTKSTART) || (pEntry->WpaState < AS_INITPMK)) { |
462 | DBGPRINT(RT_DEBUG_ERROR, | |
463 | ("[ERROR]WPAStart4WayHS : Not expect calling\n")); | |
464 | return; | |
465 | } | |
91980990 | 466 | |
ec278fa2 | 467 | /* Increment replay counter by 1 */ |
ca97b838 | 468 | ADD_ONE_To_64BIT_VAR(pEntry->R_Counter); |
91980990 | 469 | |
ec278fa2 | 470 | /* Randomly generate ANonce */ |
51126deb | 471 | GenRandom(pAd, (u8 *) pBssid, pEntry->ANonce); |
91980990 | 472 | |
ec278fa2 BZ |
473 | /* Construct EAPoL message - Pairwise Msg 1 */ |
474 | /* EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) */ | |
62eb734b | 475 | NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet)); |
ec278fa2 BZ |
476 | 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 */ | |
96b3c83d | 481 | &EAPOLPKT); |
91980990 | 482 | |
ec278fa2 | 483 | /* Make outgoing frame */ |
96b3c83d BZ |
484 | MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); |
485 | RTMPToWirelessSta(pAd, pEntry, Header802_3, | |
51126deb BZ |
486 | LENGTH_802_3, (u8 *)& EAPOLPKT, |
487 | CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, | |
96b3c83d BZ |
488 | (pEntry->PortSecured == |
489 | WPA_802_1X_PORT_SECURED) ? FALSE : TRUE); | |
ca97b838 | 490 | |
ec278fa2 | 491 | /* Trigger Retry Timer */ |
96b3c83d | 492 | RTMPModTimer(&pEntry->RetryTimer, TimeInterval); |
ca97b838 | 493 | |
ec278fa2 | 494 | /* Update State */ |
96b3c83d | 495 | pEntry->WpaState = AS_PTKSTART; |
ca97b838 | 496 | |
96b3c83d BZ |
497 | DBGPRINT(RT_DEBUG_TRACE, |
498 | ("<=== WPAStart4WayHS: send Msg1 of 4-way \n")); | |
ca97b838 | 499 | |
91980990 GKH |
500 | } |
501 | ||
502 | /* | |
503 | ======================================================================== | |
504 | ||
505 | Routine Description: | |
ca97b838 | 506 | Process Pairwise key Msg-1 of 4-way handshaking and send Msg-2 |
91980990 GKH |
507 | |
508 | Arguments: | |
ca97b838 BZ |
509 | pAd Pointer to our adapter |
510 | Elem Message body | |
91980990 GKH |
511 | |
512 | Return Value: | |
ca97b838 | 513 | None |
91980990 GKH |
514 | |
515 | Note: | |
91980990 GKH |
516 | |
517 | ======================================================================== | |
518 | */ | |
62eb734b BZ |
519 | void PeerPairMsg1Action(struct rt_rtmp_adapter *pAd, |
520 | struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem) | |
91980990 | 521 | { |
51126deb BZ |
522 | u8 PTK[80]; |
523 | u8 Header802_3[14]; | |
62eb734b | 524 | struct rt_eapol_packet * pMsg1; |
51126deb | 525 | u32 MsgLen; |
62eb734b | 526 | struct rt_eapol_packet EAPOLPKT; |
51126deb BZ |
527 | u8 *pCurrentAddr = NULL; |
528 | u8 *pmk_ptr = NULL; | |
529 | u8 group_cipher = Ndis802_11WEPDisabled; | |
530 | u8 *rsnie_ptr = NULL; | |
531 | u8 rsnie_len = 0; | |
ca97b838 BZ |
532 | |
533 | DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg1Action \n")); | |
534 | ||
535 | if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli))) | |
536 | return; | |
91980990 | 537 | |
96b3c83d BZ |
538 | if (Elem->MsgLen < |
539 | (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + | |
62eb734b | 540 | sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2)) |
96b3c83d | 541 | return; |
91980990 | 542 | |
ca97b838 BZ |
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 | } | |
91980990 | 550 | |
ec278fa2 | 551 | /* Store the received frame */ |
62eb734b | 552 | pMsg1 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; |
ca97b838 | 553 | MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; |
91980990 | 554 | |
ec278fa2 | 555 | /* Sanity Check peer Pairwise message 1 - Replay Counter */ |
96b3c83d BZ |
556 | if (PeerWpaMessageSanity(pAd, pMsg1, MsgLen, EAPOL_PAIR_MSG_1, pEntry) |
557 | == FALSE) | |
ca97b838 | 558 | return; |
91980990 | 559 | |
ec278fa2 | 560 | /* Store Replay counter, it will use to verify message 3 and construct message 2 */ |
96b3c83d BZ |
561 | NdisMoveMemory(pEntry->R_Counter, pMsg1->KeyDesc.ReplayCounter, |
562 | LEN_KEY_DESC_REPLAY); | |
ca97b838 | 563 | |
ec278fa2 | 564 | /* Store ANonce */ |
96b3c83d BZ |
565 | NdisMoveMemory(pEntry->ANonce, pMsg1->KeyDesc.KeyNonce, |
566 | LEN_KEY_DESC_NONCE); | |
ca97b838 | 567 | |
ec278fa2 | 568 | /* Generate random SNonce */ |
51126deb | 569 | GenRandom(pAd, (u8 *) pCurrentAddr, pEntry->SNonce); |
ca97b838 BZ |
570 | |
571 | { | |
ec278fa2 | 572 | /* Calculate PTK(ANonce, SNonce) */ |
96b3c83d BZ |
573 | WpaDerivePTK(pAd, |
574 | pmk_ptr, | |
575 | pEntry->ANonce, | |
576 | pEntry->Addr, | |
577 | pEntry->SNonce, pCurrentAddr, PTK, LEN_PTK); | |
ca97b838 | 578 | |
ec278fa2 | 579 | /* Save key to PTK entry */ |
ca97b838 BZ |
580 | NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK); |
581 | } | |
582 | ||
ec278fa2 | 583 | /* Update WpaState */ |
ca97b838 BZ |
584 | pEntry->WpaState = AS_PTKINIT_NEGOTIATING; |
585 | ||
ec278fa2 BZ |
586 | /* Construct EAPoL message - Pairwise Msg 2 */ |
587 | /* EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,DataKD_M2) */ | |
62eb734b | 588 | NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet)); |
ec278fa2 BZ |
589 | ConstructEapolMsg(pEntry, group_cipher, EAPOL_PAIR_MSG_2, 0, /* DefaultKeyIdx */ |
590 | pEntry->SNonce, NULL, /* TxRsc */ | |
591 | NULL, /* GTK */ | |
51126deb | 592 | (u8 *) rsnie_ptr, rsnie_len, &EAPOLPKT); |
ca97b838 | 593 | |
ec278fa2 | 594 | /* Make outgoing frame */ |
ca97b838 BZ |
595 | MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL); |
596 | ||
597 | RTMPToWirelessSta(pAd, pEntry, | |
51126deb BZ |
598 | Header802_3, sizeof(Header802_3), (u8 *)& EAPOLPKT, |
599 | CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, TRUE); | |
ca97b838 | 600 | |
96b3c83d BZ |
601 | DBGPRINT(RT_DEBUG_TRACE, |
602 | ("<=== PeerPairMsg1Action: send Msg2 of 4-way \n")); | |
ca97b838 BZ |
603 | } |
604 | ||
ca97b838 BZ |
605 | /* |
606 | ========================================================================== | |
607 | Description: | |
608 | When receiving the second packet of 4-way pairwisekey handshake. | |
609 | Return: | |
610 | ========================================================================== | |
611 | */ | |
62eb734b BZ |
612 | void PeerPairMsg2Action(struct rt_rtmp_adapter *pAd, |
613 | struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem) | |
ca97b838 | 614 | { |
51126deb | 615 | u8 PTK[80]; |
96b3c83d | 616 | BOOLEAN Cancelled; |
62eb734b BZ |
617 | struct rt_header_802_11 * pHeader; |
618 | struct rt_eapol_packet EAPOLPKT; | |
619 | struct rt_eapol_packet * pMsg2; | |
51126deb BZ |
620 | 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; | |
96b3c83d BZ |
630 | |
631 | DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg2Action \n")); | |
632 | ||
633 | if ((!pEntry) || (!pEntry->ValidAsCLI)) | |
634 | return; | |
ca97b838 | 635 | |
96b3c83d BZ |
636 | if (Elem->MsgLen < |
637 | (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + | |
62eb734b | 638 | sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2)) |
96b3c83d | 639 | return; |
ca97b838 | 640 | |
ec278fa2 | 641 | /* check Entry in valid State */ |
96b3c83d BZ |
642 | if (pEntry->WpaState < AS_PTKSTART) |
643 | return; | |
ca97b838 | 644 | |
ec278fa2 | 645 | /* pointer to 802.11 header */ |
62eb734b | 646 | pHeader = (struct rt_header_802_11 *) Elem->Msg; |
ca97b838 | 647 | |
ec278fa2 | 648 | /* skip 802.11_header(24-byte) and LLC_header(8) */ |
62eb734b | 649 | pMsg2 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; |
ca97b838 BZ |
650 | MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; |
651 | ||
ec278fa2 | 652 | /* Store SNonce */ |
96b3c83d BZ |
653 | NdisMoveMemory(pEntry->SNonce, pMsg2->KeyDesc.KeyNonce, |
654 | LEN_KEY_DESC_NONCE); | |
ca97b838 BZ |
655 | |
656 | { | |
ec278fa2 | 657 | /* Derive PTK */ |
51126deb BZ |
658 | WpaDerivePTK(pAd, (u8 *) pmk_ptr, pEntry->ANonce, /* ANONCE */ |
659 | (u8 *) pBssid, pEntry->SNonce, /* SNONCE */ | |
96b3c83d BZ |
660 | pEntry->Addr, PTK, LEN_PTK); |
661 | ||
662 | NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK); | |
ca97b838 BZ |
663 | } |
664 | ||
ec278fa2 | 665 | /* Sanity Check peer Pairwise message 2 - Replay Counter, MIC, RSNIE */ |
96b3c83d BZ |
666 | if (PeerWpaMessageSanity(pAd, pMsg2, MsgLen, EAPOL_PAIR_MSG_2, pEntry) |
667 | == FALSE) | |
ca97b838 BZ |
668 | return; |
669 | ||
96b3c83d | 670 | do { |
ec278fa2 | 671 | /* delete retry timer */ |
ca97b838 BZ |
672 | RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); |
673 | ||
ec278fa2 | 674 | /* Change state */ |
96b3c83d | 675 | pEntry->WpaState = AS_PTKINIT_NEGOTIATING; |
ca97b838 | 676 | |
ec278fa2 | 677 | /* Increment replay counter by 1 */ |
ca97b838 BZ |
678 | ADD_ONE_To_64BIT_VAR(pEntry->R_Counter); |
679 | ||
ec278fa2 | 680 | /* Construct EAPoL message - Pairwise Msg 3 */ |
62eb734b | 681 | NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet)); |
ca97b838 | 682 | ConstructEapolMsg(pEntry, |
96b3c83d BZ |
683 | group_cipher, |
684 | EAPOL_PAIR_MSG_3, | |
685 | default_key, | |
686 | pEntry->ANonce, | |
687 | TxTsc, | |
51126deb BZ |
688 | (u8 *) gtk_ptr, |
689 | (u8 *) rsnie_ptr, rsnie_len, &EAPOLPKT); | |
96b3c83d | 690 | |
ec278fa2 | 691 | /* Make outgoing frame */ |
96b3c83d BZ |
692 | MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); |
693 | RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3, | |
51126deb BZ |
694 | (u8 *)& EAPOLPKT, |
695 | CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, | |
96b3c83d BZ |
696 | (pEntry->PortSecured == |
697 | WPA_802_1X_PORT_SECURED) ? FALSE : TRUE); | |
698 | ||
699 | pEntry->ReTryCounter = PEER_MSG3_RETRY_TIMER_CTR; | |
ca97b838 BZ |
700 | RTMPSetTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV); |
701 | ||
ec278fa2 | 702 | /* Update State */ |
96b3c83d BZ |
703 | pEntry->WpaState = AS_PTKINIT_NEGOTIATING; |
704 | } while (FALSE); | |
ca97b838 | 705 | |
96b3c83d BZ |
706 | DBGPRINT(RT_DEBUG_TRACE, |
707 | ("<=== PeerPairMsg2Action: send Msg3 of 4-way \n")); | |
ca97b838 BZ |
708 | } |
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 | */ | |
62eb734b BZ |
727 | void PeerPairMsg3Action(struct rt_rtmp_adapter *pAd, |
728 | struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem) | |
ca97b838 | 729 | { |
62eb734b | 730 | struct rt_header_802_11 * pHeader; |
51126deb | 731 | u8 Header802_3[14]; |
62eb734b BZ |
732 | struct rt_eapol_packet EAPOLPKT; |
733 | struct rt_eapol_packet * pMsg3; | |
51126deb BZ |
734 | u32 MsgLen; |
735 | u8 *pCurrentAddr = NULL; | |
736 | u8 group_cipher = Ndis802_11WEPDisabled; | |
ca97b838 BZ |
737 | |
738 | DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg3Action \n")); | |
739 | ||
740 | if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli))) | |
741 | return; | |
742 | ||
96b3c83d BZ |
743 | if (Elem->MsgLen < |
744 | (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + | |
62eb734b | 745 | sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2)) |
ca97b838 BZ |
746 | return; |
747 | ||
748 | { | |
749 | pCurrentAddr = pAd->CurrentAddress; | |
750 | group_cipher = pAd->StaCfg.GroupCipher; | |
751 | ||
752 | } | |
753 | ||
ec278fa2 | 754 | /* Record 802.11 header & the received EAPOL packet Msg3 */ |
62eb734b BZ |
755 | pHeader = (struct rt_header_802_11 *) Elem->Msg; |
756 | pMsg3 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; | |
ca97b838 BZ |
757 | MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; |
758 | ||
ec278fa2 | 759 | /* Sanity Check peer Pairwise message 3 - Replay Counter, MIC, RSNIE */ |
96b3c83d BZ |
760 | if (PeerWpaMessageSanity(pAd, pMsg3, MsgLen, EAPOL_PAIR_MSG_3, pEntry) |
761 | == FALSE) | |
ca97b838 BZ |
762 | return; |
763 | ||
ec278fa2 | 764 | /* Save Replay counter, it will use construct message 4 */ |
96b3c83d BZ |
765 | NdisMoveMemory(pEntry->R_Counter, pMsg3->KeyDesc.ReplayCounter, |
766 | LEN_KEY_DESC_REPLAY); | |
ca97b838 | 767 | |
ec278fa2 | 768 | /* Double check ANonce */ |
96b3c83d BZ |
769 | if (!NdisEqualMemory |
770 | (pEntry->ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE)) { | |
ca97b838 BZ |
771 | return; |
772 | } | |
ec278fa2 | 773 | /* Construct EAPoL message - Pairwise Msg 4 */ |
62eb734b | 774 | NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet)); |
ec278fa2 BZ |
775 | 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 */ | |
96b3c83d | 780 | 0, &EAPOLPKT); |
ca97b838 | 781 | |
ec278fa2 | 782 | /* Update WpaState */ |
ca97b838 BZ |
783 | pEntry->WpaState = AS_PTKINITDONE; |
784 | ||
ec278fa2 | 785 | /* Update pairwise key */ |
ca97b838 | 786 | { |
62eb734b | 787 | struct rt_cipher_key *pSharedKey; |
ca97b838 BZ |
788 | |
789 | pSharedKey = &pAd->SharedKey[BSS0][0]; | |
790 | ||
791 | NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK); | |
792 | ||
ec278fa2 | 793 | /* Prepare pair-wise key information into shared key table */ |
62eb734b | 794 | NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key)); |
ca97b838 | 795 | pSharedKey->KeyLen = LEN_TKIP_EK; |
96b3c83d BZ |
796 | 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); | |
ca97b838 | 803 | |
ec278fa2 | 804 | /* Decide its ChiperAlg */ |
ca97b838 BZ |
805 | 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 | ||
62eb734b | 812 | /* Update these related information to struct rt_mac_table_entry */ |
ca97b838 | 813 | pEntry = &pAd->MacTab.Content[BSSID_WCID]; |
96b3c83d BZ |
814 | 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); | |
ca97b838 BZ |
821 | pEntry->PairwiseKey.CipherAlg = pSharedKey->CipherAlg; |
822 | ||
ec278fa2 | 823 | /* Update pairwise key information to ASIC Shared Key Table */ |
ca97b838 | 824 | AsicAddSharedKeyEntry(pAd, |
96b3c83d BZ |
825 | BSS0, |
826 | 0, | |
827 | pSharedKey->CipherAlg, | |
828 | pSharedKey->Key, | |
829 | pSharedKey->TxMic, pSharedKey->RxMic); | |
ca97b838 | 830 | |
ec278fa2 | 831 | /* Update ASIC WCID attribute table and IVEIV table */ |
ca97b838 | 832 | RTMPAddWcidAttributeEntry(pAd, |
96b3c83d BZ |
833 | BSS0, |
834 | 0, pSharedKey->CipherAlg, pEntry); | |
ca97b838 BZ |
835 | |
836 | } | |
837 | ||
ec278fa2 | 838 | /* open 802.1x port control and privacy filter */ |
ca97b838 | 839 | if (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK || |
96b3c83d | 840 | pEntry->AuthMode == Ndis802_11AuthModeWPA2) { |
ca97b838 BZ |
841 | pEntry->PortSecured = WPA_802_1X_PORT_SECURED; |
842 | pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; | |
843 | ||
844 | STA_PORT_SECURED(pAd); | |
ec278fa2 | 845 | /* Indicate Connected for GUI */ |
96b3c83d BZ |
846 | 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 { | |
ca97b838 BZ |
853 | } |
854 | ||
ec278fa2 | 855 | /* Init 802.3 header and send out */ |
ca97b838 BZ |
856 | MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL); |
857 | RTMPToWirelessSta(pAd, pEntry, | |
96b3c83d | 858 | Header802_3, sizeof(Header802_3), |
51126deb BZ |
859 | (u8 *)& EAPOLPKT, |
860 | CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, TRUE); | |
ca97b838 | 861 | |
96b3c83d BZ |
862 | DBGPRINT(RT_DEBUG_TRACE, |
863 | ("<=== PeerPairMsg3Action: send Msg4 of 4-way \n")); | |
ca97b838 BZ |
864 | } |
865 | ||
866 | /* | |
867 | ========================================================================== | |
868 | Description: | |
869 | When receiving the last packet of 4-way pairwisekey handshake. | |
421f91d2 | 870 | Initialize 2-way groupkey handshake following. |
ca97b838 BZ |
871 | Return: |
872 | ========================================================================== | |
873 | */ | |
62eb734b BZ |
874 | void PeerPairMsg4Action(struct rt_rtmp_adapter *pAd, |
875 | struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem) | |
ca97b838 | 876 | { |
62eb734b BZ |
877 | struct rt_eapol_packet * pMsg4; |
878 | struct rt_header_802_11 * pHeader; | |
51126deb | 879 | u32 MsgLen; |
96b3c83d | 880 | BOOLEAN Cancelled; |
51126deb | 881 | u8 group_cipher = Ndis802_11WEPDisabled; |
ca97b838 | 882 | |
96b3c83d | 883 | DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg4Action\n")); |
ca97b838 | 884 | |
96b3c83d BZ |
885 | do { |
886 | if ((!pEntry) || (!pEntry->ValidAsCLI)) | |
887 | break; | |
ca97b838 | 888 | |
96b3c83d BZ |
889 | if (Elem->MsgLen < |
890 | (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + | |
62eb734b | 891 | sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2)) |
96b3c83d | 892 | break; |
ca97b838 | 893 | |
96b3c83d BZ |
894 | if (pEntry->WpaState < AS_PTKINIT_NEGOTIATING) |
895 | break; | |
ca97b838 | 896 | |
ec278fa2 | 897 | /* pointer to 802.11 header */ |
62eb734b | 898 | pHeader = (struct rt_header_802_11 *) Elem->Msg; |
ca97b838 | 899 | |
ec278fa2 | 900 | /* skip 802.11_header(24-byte) and LLC_header(8) */ |
96b3c83d | 901 | pMsg4 = |
62eb734b | 902 | (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; |
ca97b838 BZ |
903 | MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; |
904 | ||
ec278fa2 | 905 | /* Sanity Check peer Pairwise message 4 - Replay Counter, MIC */ |
96b3c83d BZ |
906 | if (PeerWpaMessageSanity |
907 | (pAd, pMsg4, MsgLen, EAPOL_PAIR_MSG_4, pEntry) == FALSE) | |
ca97b838 BZ |
908 | break; |
909 | ||
ec278fa2 | 910 | /* 3. uses the MLME.SETKEYS.request to configure PTK into MAC */ |
62eb734b | 911 | NdisZeroMemory(&pEntry->PairwiseKey, sizeof(struct rt_cipher_key)); |
ca97b838 | 912 | |
ec278fa2 | 913 | /* reset IVEIV in Asic */ |
ca97b838 BZ |
914 | AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, 1, 0); |
915 | ||
96b3c83d BZ |
916 | 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); | |
ca97b838 | 925 | |
ec278fa2 | 926 | /* Set pairwise key to Asic */ |
96b3c83d BZ |
927 | { |
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; | |
ca97b838 | 934 | |
ec278fa2 | 935 | /* Add Pair-wise key to Asic */ |
96b3c83d BZ |
936 | AsicAddPairwiseKeyEntry(pAd, |
937 | pEntry->Addr, | |
51126deb | 938 | (u8)pEntry->Aid, |
96b3c83d | 939 | &pEntry->PairwiseKey); |
ca97b838 | 940 | |
ec278fa2 | 941 | /* update WCID attribute table and IVEIV table for this entry */ |
96b3c83d BZ |
942 | RTMPAddWcidAttributeEntry(pAd, |
943 | pEntry->apidx, | |
944 | 0, | |
945 | pEntry->PairwiseKey.CipherAlg, | |
946 | pEntry); | |
947 | } | |
ca97b838 | 948 | |
ec278fa2 | 949 | /* 4. upgrade state */ |
96b3c83d BZ |
950 | pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; |
951 | pEntry->WpaState = AS_PTKINITDONE; | |
952 | pEntry->PortSecured = WPA_802_1X_PORT_SECURED; | |
ca97b838 BZ |
953 | |
954 | if (pEntry->AuthMode == Ndis802_11AuthModeWPA2 || | |
96b3c83d | 955 | pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) { |
ca97b838 BZ |
956 | pEntry->GTKState = REKEY_ESTABLISHED; |
957 | RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); | |
958 | ||
ec278fa2 | 959 | /* send wireless event - for set key done WPA2 */ |
ca97b838 | 960 | if (pAd->CommonCfg.bWirelessEvent) |
96b3c83d BZ |
961 | RTMPSendWirelessEvent(pAd, |
962 | IW_SET_KEY_DONE_WPA2_EVENT_FLAG, | |
963 | pEntry->Addr, | |
964 | pEntry->apidx, 0); | |
965 | ||
966 | 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 { | |
ec278fa2 | 974 | /* 5. init Group 2-way handshake if necessary. */ |
96b3c83d BZ |
975 | WPAStart2WayGroupHS(pAd, pEntry); |
976 | ||
977 | pEntry->ReTryCounter = GROUP_MSG1_RETRY_TIMER_CTR; | |
978 | RTMPModTimer(&pEntry->RetryTimer, | |
979 | PEER_MSG3_RETRY_EXEC_INTV); | |
ca97b838 | 980 | } |
96b3c83d | 981 | } while (FALSE); |
ca97b838 BZ |
982 | |
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 | */ | |
62eb734b | 993 | void WPAStart2WayGroupHS(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry) |
ca97b838 | 994 | { |
51126deb BZ |
995 | u8 Header802_3[14]; |
996 | u8 TxTsc[6]; | |
62eb734b | 997 | struct rt_eapol_packet EAPOLPKT; |
51126deb BZ |
998 | u8 group_cipher = Ndis802_11WEPDisabled; |
999 | u8 default_key = 0; | |
1000 | u8 *gnonce_ptr = NULL; | |
1001 | u8 *gtk_ptr = NULL; | |
1002 | u8 *pBssid = NULL; | |
ca97b838 BZ |
1003 | |
1004 | DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart2WayGroupHS\n")); | |
1005 | ||
96b3c83d BZ |
1006 | if ((!pEntry) || (!pEntry->ValidAsCLI)) |
1007 | return; | |
ca97b838 | 1008 | |
96b3c83d | 1009 | do { |
ec278fa2 | 1010 | /* Increment replay counter by 1 */ |
ca97b838 BZ |
1011 | ADD_ONE_To_64BIT_VAR(pEntry->R_Counter); |
1012 | ||
ec278fa2 | 1013 | /* Construct EAPoL message - Group Msg 1 */ |
62eb734b | 1014 | NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet)); |
ca97b838 | 1015 | ConstructEapolMsg(pEntry, |
96b3c83d BZ |
1016 | group_cipher, |
1017 | EAPOL_GROUP_MSG_1, | |
1018 | default_key, | |
51126deb BZ |
1019 | (u8 *) gnonce_ptr, |
1020 | TxTsc, (u8 *) gtk_ptr, NULL, 0, &EAPOLPKT); | |
ca97b838 | 1021 | |
ec278fa2 | 1022 | /* Make outgoing frame */ |
96b3c83d BZ |
1023 | MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); |
1024 | RTMPToWirelessSta(pAd, pEntry, | |
1025 | Header802_3, LENGTH_802_3, | |
51126deb BZ |
1026 | (u8 *)& EAPOLPKT, |
1027 | CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, | |
96b3c83d | 1028 | FALSE); |
ca97b838 | 1029 | |
96b3c83d | 1030 | } while (FALSE); |
ca97b838 | 1031 | |
96b3c83d BZ |
1032 | DBGPRINT(RT_DEBUG_TRACE, |
1033 | ("<=== WPAStart2WayGroupHS : send out Group Message 1 \n")); | |
ca97b838 | 1034 | |
96b3c83d | 1035 | return; |
ca97b838 BZ |
1036 | } |
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 | */ | |
62eb734b BZ |
1055 | void PeerGroupMsg1Action(struct rt_rtmp_adapter *pAd, |
1056 | struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem) | |
ca97b838 | 1057 | { |
51126deb | 1058 | u8 Header802_3[14]; |
62eb734b BZ |
1059 | struct rt_eapol_packet EAPOLPKT; |
1060 | struct rt_eapol_packet * pGroup; | |
51126deb | 1061 | u32 MsgLen; |
96b3c83d | 1062 | BOOLEAN Cancelled; |
51126deb BZ |
1063 | u8 default_key = 0; |
1064 | u8 group_cipher = Ndis802_11WEPDisabled; | |
1065 | u8 *pCurrentAddr = NULL; | |
ca97b838 BZ |
1066 | |
1067 | DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg1Action \n")); | |
1068 | ||
1069 | if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli))) | |
96b3c83d | 1070 | return; |
ca97b838 BZ |
1071 | |
1072 | { | |
1073 | pCurrentAddr = pAd->CurrentAddress; | |
1074 | group_cipher = pAd->StaCfg.GroupCipher; | |
1075 | default_key = pAd->StaCfg.DefaultKeyId; | |
1076 | } | |
1077 | ||
ec278fa2 | 1078 | /* Process Group Message 1 frame. skip 802.11 header(24) & LLC_SNAP header(8) */ |
62eb734b | 1079 | pGroup = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; |
ca97b838 BZ |
1080 | MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; |
1081 | ||
ec278fa2 | 1082 | /* Sanity Check peer group message 1 - Replay Counter, MIC, RSNIE */ |
96b3c83d BZ |
1083 | if (PeerWpaMessageSanity(pAd, pGroup, MsgLen, EAPOL_GROUP_MSG_1, pEntry) |
1084 | == FALSE) | |
ca97b838 BZ |
1085 | return; |
1086 | ||
ec278fa2 | 1087 | /* delete retry timer */ |
ca97b838 BZ |
1088 | RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); |
1089 | ||
ec278fa2 | 1090 | /* Save Replay counter, it will use to construct message 2 */ |
96b3c83d BZ |
1091 | NdisMoveMemory(pEntry->R_Counter, pGroup->KeyDesc.ReplayCounter, |
1092 | LEN_KEY_DESC_REPLAY); | |
ca97b838 | 1093 | |
ec278fa2 | 1094 | /* Construct EAPoL message - Group Msg 2 */ |
62eb734b | 1095 | NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet)); |
ec278fa2 BZ |
1096 | 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 */ | |
96b3c83d BZ |
1100 | 0, &EAPOLPKT); |
1101 | ||
ec278fa2 | 1102 | /* open 802.1x port control and privacy filter */ |
ca97b838 BZ |
1103 | pEntry->PortSecured = WPA_802_1X_PORT_SECURED; |
1104 | pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; | |
1105 | ||
1106 | STA_PORT_SECURED(pAd); | |
ec278fa2 | 1107 | /* Indicate Connected for GUI */ |
96b3c83d | 1108 | pAd->IndicateMediaState = NdisMediaStateConnected; |
ca97b838 | 1109 | |
96b3c83d BZ |
1110 | 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))); | |
ca97b838 | 1115 | |
ec278fa2 | 1116 | /* init header and Fill Packet and send Msg 2 to authenticator */ |
ca97b838 BZ |
1117 | MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL); |
1118 | RTMPToWirelessSta(pAd, pEntry, | |
96b3c83d | 1119 | Header802_3, sizeof(Header802_3), |
51126deb BZ |
1120 | (u8 *)& EAPOLPKT, |
1121 | CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, FALSE); | |
ca97b838 | 1122 | |
96b3c83d BZ |
1123 | DBGPRINT(RT_DEBUG_TRACE, |
1124 | ("<=== PeerGroupMsg1Action: sned group message 2\n")); | |
ca97b838 BZ |
1125 | } |
1126 | ||
1127 | /* | |
1128 | ========================================================================== | |
1129 | Description: | |
1130 | When receiving the last packet of 2-way groupkey handshake. | |
1131 | Return: | |
1132 | ========================================================================== | |
1133 | */ | |
62eb734b BZ |
1134 | void PeerGroupMsg2Action(struct rt_rtmp_adapter *pAd, |
1135 | struct rt_mac_table_entry *pEntry, | |
51126deb | 1136 | void * Msg, u32 MsgLen) |
ca97b838 | 1137 | { |
51126deb BZ |
1138 | u32 Len; |
1139 | u8 *pData; | |
96b3c83d | 1140 | BOOLEAN Cancelled; |
62eb734b | 1141 | struct rt_eapol_packet * pMsg2; |
51126deb | 1142 | u8 group_cipher = Ndis802_11WEPDisabled; |
ca97b838 BZ |
1143 | |
1144 | DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg2Action \n")); | |
1145 | ||
96b3c83d BZ |
1146 | do { |
1147 | if ((!pEntry) || (!pEntry->ValidAsCLI)) | |
1148 | break; | |
ca97b838 | 1149 | |
96b3c83d | 1150 | if (MsgLen < |
62eb734b | 1151 | (LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(struct rt_key_descripter) - |
96b3c83d BZ |
1152 | MAX_LEN_OF_RSNIE - 2)) |
1153 | break; | |
ca97b838 | 1154 | |
96b3c83d BZ |
1155 | if (pEntry->WpaState != AS_PTKINITDONE) |
1156 | break; | |
ca97b838 | 1157 | |
51126deb | 1158 | pData = (u8 *)Msg; |
62eb734b | 1159 | pMsg2 = (struct rt_eapol_packet *) (pData + LENGTH_802_1_H); |
96b3c83d | 1160 | Len = MsgLen - LENGTH_802_1_H; |
ca97b838 | 1161 | |
ec278fa2 | 1162 | /* Sanity Check peer group message 2 - Replay Counter, MIC */ |
96b3c83d BZ |
1163 | if (PeerWpaMessageSanity |
1164 | (pAd, pMsg2, Len, EAPOL_GROUP_MSG_2, pEntry) == FALSE) | |
1165 | break; | |
ca97b838 | 1166 | |
ec278fa2 | 1167 | /* 3. upgrade state */ |
ca97b838 BZ |
1168 | |
1169 | RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); | |
96b3c83d | 1170 | pEntry->GTKState = REKEY_ESTABLISHED; |
ca97b838 | 1171 | |
96b3c83d BZ |
1172 | if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) |
1173 | || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) { | |
ec278fa2 | 1174 | /* send wireless event - for set key done WPA2 */ |
ca97b838 | 1175 | if (pAd->CommonCfg.bWirelessEvent) |
96b3c83d BZ |
1176 | RTMPSendWirelessEvent(pAd, |
1177 | IW_SET_KEY_DONE_WPA2_EVENT_FLAG, | |
1178 | pEntry->Addr, | |
1179 | pEntry->apidx, 0); | |
1180 | ||
1181 | 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 { | |
ec278fa2 | 1189 | /* send wireless event - for set key done WPA */ |
ca97b838 | 1190 | if (pAd->CommonCfg.bWirelessEvent) |
96b3c83d BZ |
1191 | RTMPSendWirelessEvent(pAd, |
1192 | IW_SET_KEY_DONE_WPA1_EVENT_FLAG, | |
1193 | pEntry->Addr, | |
1194 | pEntry->apidx, 0); | |
1195 | ||
1196 | 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))); | |
ca97b838 | 1203 | } |
96b3c83d | 1204 | } while (FALSE); |
ca97b838 BZ |
1205 | } |
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 | */ | |
51126deb | 1229 | BOOLEAN WpaMsgTypeSubst(u8 EAPType, int * MsgType) |
ca97b838 | 1230 | { |
96b3c83d BZ |
1231 | 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; | |
ca97b838 BZ |
1249 | } |
1250 | return TRUE; | |
1251 | } | |
1252 | ||
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: | |
51126deb BZ |
1264 | 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 | |
ca97b838 BZ |
1271 | |
1272 | Return Value: | |
51126deb | 1273 | u8 *output - the calculated result |
ca97b838 BZ |
1274 | |
1275 | Note: | |
1276 | 802.11i-2004 Annex H.3 | |
1277 | ||
1278 | ======================================================================== | |
1279 | */ | |
51126deb BZ |
1280 | void PRF(u8 * key, |
1281 | int key_len, | |
1282 | u8 * prefix, | |
1283 | int prefix_len, | |
1284 | u8 * data, int data_len, u8 * output, int len) | |
ca97b838 | 1285 | { |
51126deb BZ |
1286 | int i; |
1287 | u8 *input; | |
1288 | int currentindex = 0; | |
1289 | int total_len; | |
ca97b838 | 1290 | |
ec278fa2 | 1291 | /* Allocate memory for input */ |
51126deb | 1292 | os_alloc_mem(NULL, (u8 **) & input, 1024); |
ca97b838 | 1293 | |
96b3c83d | 1294 | if (input == NULL) { |
06aea994 | 1295 | DBGPRINT(RT_DEBUG_ERROR, ("PRF: no memory!\n")); |
96b3c83d BZ |
1296 | return; |
1297 | } | |
ec278fa2 | 1298 | /* Generate concatenation input */ |
ca97b838 BZ |
1299 | NdisMoveMemory(input, prefix, prefix_len); |
1300 | ||
ec278fa2 | 1301 | /* Concatenate a single octet containing 0 */ |
96b3c83d | 1302 | input[prefix_len] = 0; |
ca97b838 | 1303 | |
ec278fa2 | 1304 | /* Concatenate specific data */ |
ca97b838 | 1305 | NdisMoveMemory(&input[prefix_len + 1], data, data_len); |
96b3c83d | 1306 | total_len = prefix_len + 1 + data_len; |
ca97b838 | 1307 | |
ec278fa2 BZ |
1308 | /* Concatenate a single octet containing 0 */ |
1309 | /* This octet shall be update later */ | |
ca97b838 BZ |
1310 | input[total_len] = 0; |
1311 | total_len++; | |
1312 | ||
ec278fa2 BZ |
1313 | /* Iterate to calculate the result by hmac-sha-1 */ |
1314 | /* Then concatenate to last result */ | |
96b3c83d BZ |
1315 | 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; | |
ca97b838 | 1319 | |
ec278fa2 | 1320 | /* update the last octet */ |
ca97b838 BZ |
1321 | input[total_len - 1]++; |
1322 | } | |
96b3c83d | 1323 | os_free_mem(NULL, input); |
ca97b838 BZ |
1324 | } |
1325 | ||
1326 | /* | |
1327 | * 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 | ||
96b3c83d BZ |
1333 | static void F(char *password, unsigned char *ssid, int ssidlength, |
1334 | int iterations, int count, unsigned char *output) | |
ca97b838 | 1335 | { |
96b3c83d BZ |
1336 | unsigned char digest[36], digest1[SHA1_DIGEST_SIZE]; |
1337 | int i, j; | |
1338 | ||
1339 | /* 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); | |
ec278fa2 | 1345 | HMAC_SHA1((unsigned char *)password, (int)strlen(password), digest, ssidlength + 4, digest1, SHA1_DIGEST_SIZE); /* for WPA update */ |
96b3c83d BZ |
1346 | |
1347 | /* output = U1 */ | |
1348 | memcpy(output, digest1, SHA1_DIGEST_SIZE); | |
1349 | ||
1350 | for (i = 1; i < iterations; i++) { | |
1351 | /* Un = PRF(P, Un-1) */ | |
ec278fa2 | 1352 | HMAC_SHA1((unsigned char *)password, (int)strlen(password), digest1, SHA1_DIGEST_SIZE, digest, SHA1_DIGEST_SIZE); /* for WPA update */ |
96b3c83d BZ |
1353 | memcpy(digest1, digest, SHA1_DIGEST_SIZE); |
1354 | ||
1355 | /* output = output xor Un */ | |
1356 | for (j = 0; j < SHA1_DIGEST_SIZE; j++) { | |
1357 | output[j] ^= digest[j]; | |
1358 | } | |
1359 | } | |
ca97b838 BZ |
1360 | } |
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 | */ | |
51126deb | 1368 | int PasswordHash(char *password, u8 *ssid, int ssidlength, u8 *output) |
ca97b838 | 1369 | { |
96b3c83d BZ |
1370 | if ((strlen(password) > 63) || (ssidlength > 32)) |
1371 | return 0; | |
ca97b838 | 1372 | |
96b3c83d BZ |
1373 | F(password, ssid, ssidlength, 4096, 1, output); |
1374 | F(password, ssid, ssidlength, 4096, 2, &output[SHA1_DIGEST_SIZE]); | |
1375 | return 1; | |
ca97b838 BZ |
1376 | } |
1377 | ||
ca97b838 BZ |
1378 | /* |
1379 | ======================================================================== | |
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: | |
1386 | pAd - pointer to our pAdapter context | |
1387 | 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 | */ | |
62eb734b | 1402 | void WpaDerivePTK(struct rt_rtmp_adapter *pAd, |
51126deb BZ |
1403 | u8 * PMK, |
1404 | u8 * ANonce, | |
1405 | u8 * AA, | |
1406 | u8 * SNonce, | |
1407 | u8 * SA, u8 * output, u32 len) | |
ca97b838 | 1408 | { |
51126deb BZ |
1409 | u8 concatenation[76]; |
1410 | u32 CurrPos = 0; | |
1411 | u8 temp[32]; | |
1412 | u8 Prefix[] = | |
96b3c83d BZ |
1413 | { 'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ', |
1414 | 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n' | |
1415 | }; | |
ca97b838 | 1416 | |
ec278fa2 | 1417 | /* initiate the concatenation input */ |
ca97b838 BZ |
1418 | NdisZeroMemory(temp, sizeof(temp)); |
1419 | NdisZeroMemory(concatenation, 76); | |
1420 | ||
ec278fa2 | 1421 | /* Get smaller address */ |
ca97b838 BZ |
1422 | if (RTMPCompareMemory(SA, AA, 6) == 1) |
1423 | NdisMoveMemory(concatenation, AA, 6); | |
1424 | else | |
1425 | NdisMoveMemory(concatenation, SA, 6); | |
1426 | CurrPos += 6; | |
1427 | ||
ec278fa2 | 1428 | /* Get larger address */ |
ca97b838 BZ |
1429 | if (RTMPCompareMemory(SA, AA, 6) == 1) |
1430 | NdisMoveMemory(&concatenation[CurrPos], SA, 6); | |
1431 | else | |
1432 | NdisMoveMemory(&concatenation[CurrPos], AA, 6); | |
1433 | ||
ec278fa2 BZ |
1434 | /* store the larger mac address for backward compatible of */ |
1435 | /* ralink proprietary STA-key issue */ | |
ca97b838 BZ |
1436 | NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN); |
1437 | CurrPos += 6; | |
1438 | ||
ec278fa2 | 1439 | /* Get smaller Nonce */ |
ca97b838 | 1440 | if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) |
ec278fa2 | 1441 | NdisMoveMemory(&concatenation[CurrPos], temp, 32); /* patch for ralink proprietary STA-key issue */ |
ca97b838 BZ |
1442 | 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 | ||
ec278fa2 | 1448 | /* Get larger Nonce */ |
ca97b838 | 1449 | if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) |
ec278fa2 | 1450 | NdisMoveMemory(&concatenation[CurrPos], temp, 32); /* patch for ralink proprietary STA-key issue */ |
ca97b838 BZ |
1451 | 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 | ||
ec278fa2 | 1459 | /* Use PRF to generate PTK */ |
ca97b838 BZ |
1460 | 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 | */ | |
62eb734b | 1481 | void GenRandom(struct rt_rtmp_adapter *pAd, u8 * macAddr, u8 * random) |
ca97b838 | 1482 | { |
51126deb BZ |
1483 | int i, curr; |
1484 | u8 local[80], KeyCounter[32]; | |
1485 | u8 result[80]; | |
1486 | unsigned long CurrentTime; | |
1487 | u8 prefix[] = | |
96b3c83d | 1488 | { 'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r' }; |
ca97b838 | 1489 | |
ec278fa2 | 1490 | /* Zero the related information */ |
ca97b838 BZ |
1491 | NdisZeroMemory(result, 80); |
1492 | NdisZeroMemory(local, 80); | |
1493 | NdisZeroMemory(KeyCounter, 32); | |
1494 | ||
96b3c83d | 1495 | for (i = 0; i < 32; i++) { |
ec278fa2 | 1496 | /* copy the local MAC address */ |
ca97b838 | 1497 | COPY_MAC_ADDR(local, macAddr); |
96b3c83d | 1498 | curr = MAC_ADDR_LEN; |
ca97b838 | 1499 | |
ec278fa2 | 1500 | /* concatenate the current time */ |
ca97b838 | 1501 | NdisGetSystemUpTime(&CurrentTime); |
96b3c83d BZ |
1502 | NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime)); |
1503 | curr += sizeof(CurrentTime); | |
ca97b838 | 1504 | |
ec278fa2 | 1505 | /* concatenate the last result */ |
96b3c83d BZ |
1506 | NdisMoveMemory(&local[curr], result, 32); |
1507 | curr += 32; | |
ca97b838 | 1508 | |
ec278fa2 | 1509 | /* concatenate a variable */ |
96b3c83d BZ |
1510 | NdisMoveMemory(&local[curr], &i, 2); |
1511 | curr += 2; | |
ca97b838 | 1512 | |
ec278fa2 | 1513 | /* calculate the result */ |
96b3c83d | 1514 | PRF(KeyCounter, 32, prefix, 12, local, curr, result, 32); |
ca97b838 BZ |
1515 | } |
1516 | ||
96b3c83d | 1517 | NdisMoveMemory(random, result, 32); |
ca97b838 BZ |
1518 | } |
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 | |
1529 | ElementID - indicate the WPA1 or WPA2 | |
1530 | WepStatus - indicate the encryption type | |
1531 | 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 | */ | |
62eb734b | 1540 | static void RTMPMakeRsnIeCipher(struct rt_rtmp_adapter *pAd, |
51126deb BZ |
1541 | u8 ElementID, |
1542 | u32 WepStatus, | |
96b3c83d | 1543 | IN BOOLEAN bMixCipher, |
51126deb BZ |
1544 | u8 FlexibleCipher, |
1545 | u8 *pRsnIe, u8 * rsn_len) | |
ca97b838 | 1546 | { |
51126deb | 1547 | u8 PairwiseCnt; |
ca97b838 BZ |
1548 | |
1549 | *rsn_len = 0; | |
1550 | ||
ec278fa2 | 1551 | /* decide WPA2 or WPA1 */ |
96b3c83d | 1552 | if (ElementID == Wpa2Ie) { |
62eb734b | 1553 | struct rt_rsnie2 *pRsnie_cipher = (struct rt_rsnie2 *)pRsnIe; |
ca97b838 | 1554 | |
ec278fa2 | 1555 | /* Assign the verson as 1 */ |
ca97b838 BZ |
1556 | pRsnie_cipher->version = 1; |
1557 | ||
96b3c83d | 1558 | switch (WepStatus) { |
ec278fa2 | 1559 | /* TKIP mode */ |
96b3c83d BZ |
1560 | 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); | |
62eb734b | 1565 | *rsn_len = sizeof(struct rt_rsnie2); |
96b3c83d | 1566 | break; |
ca97b838 | 1567 | |
ec278fa2 | 1568 | /* AES mode */ |
96b3c83d BZ |
1569 | 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); | |
62eb734b | 1579 | *rsn_len = sizeof(struct rt_rsnie2); |
96b3c83d | 1580 | break; |
ca97b838 | 1581 | |
ec278fa2 | 1582 | /* TKIP-AES mix mode */ |
96b3c83d BZ |
1583 | case Ndis802_11Encryption4Enabled: |
1584 | NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); | |
1585 | ||
1586 | PairwiseCnt = 1; | |
ec278fa2 | 1587 | /* Insert WPA2 TKIP as the first pairwise cipher */ |
96b3c83d BZ |
1588 | if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher)) { |
1589 | NdisMoveMemory(pRsnie_cipher->ucast[0].oui, | |
1590 | OUI_WPA2_TKIP, 4); | |
ec278fa2 | 1591 | /* Insert WPA2 AES as the secondary pairwise cipher */ |
96b3c83d BZ |
1592 | if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher)) { |
1593 | NdisMoveMemory(pRsnie_cipher->ucast[0]. | |
1594 | oui + 4, OUI_WPA2_CCMP, | |
1595 | 4); | |
1596 | PairwiseCnt = 2; | |
ca97b838 | 1597 | } |
96b3c83d | 1598 | } else { |
ec278fa2 | 1599 | /* Insert WPA2 AES as the first pairwise cipher */ |
96b3c83d BZ |
1600 | NdisMoveMemory(pRsnie_cipher->ucast[0].oui, |
1601 | OUI_WPA2_CCMP, 4); | |
1602 | } | |
ca97b838 | 1603 | |
96b3c83d | 1604 | pRsnie_cipher->ucount = PairwiseCnt; |
62eb734b | 1605 | *rsn_len = sizeof(struct rt_rsnie2) + (4 * (PairwiseCnt - 1)); |
96b3c83d BZ |
1606 | break; |
1607 | } | |
ca97b838 BZ |
1608 | |
1609 | if ((pAd->OpMode == OPMODE_STA) && | |
96b3c83d BZ |
1610 | (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) && |
1611 | (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) { | |
51126deb | 1612 | u32 GroupCipher = pAd->StaCfg.GroupCipher; |
96b3c83d BZ |
1613 | 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; | |
ca97b838 BZ |
1622 | } |
1623 | } | |
ec278fa2 | 1624 | /* swap for big-endian platform */ |
ca97b838 | 1625 | pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); |
96b3c83d BZ |
1626 | pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); |
1627 | } else { | |
62eb734b | 1628 | struct rt_rsnie *pRsnie_cipher = (struct rt_rsnie *)pRsnIe; |
ca97b838 | 1629 | |
ec278fa2 | 1630 | /* Assign OUI and version */ |
ca97b838 | 1631 | NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4); |
96b3c83d | 1632 | pRsnie_cipher->version = 1; |
ca97b838 | 1633 | |
96b3c83d | 1634 | switch (WepStatus) { |
ec278fa2 | 1635 | /* TKIP mode */ |
96b3c83d BZ |
1636 | 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); | |
62eb734b | 1641 | *rsn_len = sizeof(struct rt_rsnie); |
96b3c83d | 1642 | break; |
ca97b838 | 1643 | |
ec278fa2 | 1644 | /* AES mode */ |
96b3c83d BZ |
1645 | 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); | |
62eb734b | 1655 | *rsn_len = sizeof(struct rt_rsnie); |
96b3c83d | 1656 | break; |
ca97b838 | 1657 | |
ec278fa2 | 1658 | /* TKIP-AES mix mode */ |
96b3c83d BZ |
1659 | case Ndis802_11Encryption4Enabled: |
1660 | NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); | |
1661 | ||
1662 | PairwiseCnt = 1; | |
ec278fa2 | 1663 | /* Insert WPA TKIP as the first pairwise cipher */ |
96b3c83d BZ |
1664 | if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher)) { |
1665 | NdisMoveMemory(pRsnie_cipher->ucast[0].oui, | |
1666 | OUI_WPA_TKIP, 4); | |
ec278fa2 | 1667 | /* Insert WPA AES as the secondary pairwise cipher */ |
96b3c83d BZ |
1668 | if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher)) { |
1669 | NdisMoveMemory(pRsnie_cipher->ucast[0]. | |
1670 | oui + 4, OUI_WPA_CCMP, | |
1671 | 4); | |
1672 | PairwiseCnt = 2; | |
ca97b838 | 1673 | } |
96b3c83d | 1674 | } else { |
ec278fa2 | 1675 | /* Insert WPA AES as the first pairwise cipher */ |
96b3c83d BZ |
1676 | NdisMoveMemory(pRsnie_cipher->ucast[0].oui, |
1677 | OUI_WPA_CCMP, 4); | |
1678 | } | |
ca97b838 | 1679 | |
96b3c83d | 1680 | pRsnie_cipher->ucount = PairwiseCnt; |
62eb734b | 1681 | *rsn_len = sizeof(struct rt_rsnie) + (4 * (PairwiseCnt - 1)); |
96b3c83d BZ |
1682 | break; |
1683 | } | |
ca97b838 BZ |
1684 | |
1685 | if ((pAd->OpMode == OPMODE_STA) && | |
96b3c83d BZ |
1686 | (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) && |
1687 | (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) { | |
51126deb | 1688 | u32 GroupCipher = pAd->StaCfg.GroupCipher; |
96b3c83d BZ |
1689 | 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; | |
ca97b838 BZ |
1698 | } |
1699 | } | |
ec278fa2 | 1700 | /* swap for big-endian platform */ |
ca97b838 | 1701 | pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); |
96b3c83d | 1702 | pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); |
ca97b838 BZ |
1703 | } |
1704 | } | |
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 | |
1715 | ElementID - indicate the WPA1 or WPA2 | |
1716 | AuthMode - indicate the authentication mode | |
1717 | apidx - indicate the interface index | |
1718 | ||
1719 | Return Value: | |
1720 | ||
1721 | Note: | |
1722 | ||
1723 | ======================================================================== | |
1724 | */ | |
62eb734b | 1725 | static void RTMPMakeRsnIeAKM(struct rt_rtmp_adapter *pAd, |
51126deb BZ |
1726 | u8 ElementID, |
1727 | u32 AuthMode, | |
1728 | u8 apidx, | |
1729 | u8 *pRsnIe, u8 * rsn_len) | |
ca97b838 | 1730 | { |
62eb734b | 1731 | struct rt_rsnie_auth *pRsnie_auth; |
51126deb | 1732 | u8 AkmCnt = 1; /* default as 1 */ |
ca97b838 | 1733 | |
62eb734b | 1734 | pRsnie_auth = (struct rt_rsnie_auth *) (pRsnIe + (*rsn_len)); |
ca97b838 | 1735 | |
ec278fa2 | 1736 | /* decide WPA2 or WPA1 */ |
96b3c83d | 1737 | if (ElementID == Wpa2Ie) { |
ca97b838 | 1738 | |
96b3c83d BZ |
1739 | 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; | |
ca97b838 | 1745 | |
96b3c83d BZ |
1746 | 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; | |
1754 | ||
1755 | } | |
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; | |
1763 | ||
1764 | case Ndis802_11AuthModeWPAPSK: | |
1765 | case Ndis802_11AuthModeWPA1PSKWPA2PSK: | |
1766 | NdisMoveMemory(pRsnie_auth->auth[0].oui, | |
1767 | OUI_WPA_PSK_AKM, 4); | |
1768 | break; | |
1769 | ||
1770 | 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 | } | |
ca97b838 BZ |
1778 | } |
1779 | ||
1780 | pRsnie_auth->acount = AkmCnt; | |
1781 | pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount); | |
1782 | ||
ec278fa2 | 1783 | /* update current RSNIE length */ |
62eb734b | 1784 | (*rsn_len) += (sizeof(struct rt_rsnie_auth) + (4 * (AkmCnt - 1))); |
ca97b838 BZ |
1785 | |
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 | |
1797 | ElementID - indicate the WPA1 or WPA2 | |
1798 | apidx - indicate the interface index | |
1799 | ||
1800 | Return Value: | |
1801 | ||
1802 | Note: | |
1803 | ||
1804 | ======================================================================== | |
1805 | */ | |
62eb734b | 1806 | static void RTMPMakeRsnIeCap(struct rt_rtmp_adapter *pAd, |
51126deb BZ |
1807 | u8 ElementID, |
1808 | u8 apidx, | |
1809 | u8 *pRsnIe, u8 * rsn_len) | |
ca97b838 | 1810 | { |
96b3c83d | 1811 | RSN_CAPABILITIES *pRSN_Cap; |
ca97b838 | 1812 | |
ec278fa2 | 1813 | /* it could be ignored in WPA1 mode */ |
ca97b838 BZ |
1814 | if (ElementID == WpaIe) |
1815 | return; | |
1816 | ||
96b3c83d | 1817 | pRSN_Cap = (RSN_CAPABILITIES *) (pRsnIe + (*rsn_len)); |
ca97b838 BZ |
1818 | |
1819 | pRSN_Cap->word = cpu2le16(pRSN_Cap->word); | |
1820 | ||
ec278fa2 | 1821 | (*rsn_len) += sizeof(RSN_CAPABILITIES); /* update current RSNIE length */ |
ca97b838 BZ |
1822 | |
1823 | } | |
1824 | ||
ca97b838 BZ |
1825 | /* |
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 | |
1833 | AuthMode - indicate the authentication mode | |
1834 | WepStatus - indicate the encryption type | |
1835 | apidx - indicate the interface index | |
1836 | ||
1837 | Return Value: | |
1838 | ||
1839 | Note: | |
1840 | ||
1841 | ======================================================================== | |
1842 | */ | |
62eb734b | 1843 | void RTMPMakeRSNIE(struct rt_rtmp_adapter *pAd, |
51126deb | 1844 | u32 AuthMode, u32 WepStatus, u8 apidx) |
ca97b838 | 1845 | { |
51126deb BZ |
1846 | 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; | |
ec278fa2 | 1850 | BOOLEAN bMixCipher = FALSE; /* indicate the pairwise and group cipher are different */ |
51126deb | 1851 | u8 p_offset; |
ec278fa2 | 1852 | WPA_MIX_PAIR_CIPHER FlexibleCipher = WPA_TKIPAES_WPA2_TKIPAES; /* it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode */ |
ca97b838 BZ |
1853 | |
1854 | rsnielen_cur_p = NULL; | |
1855 | rsnielen_ex_cur_p = NULL; | |
1856 | ||
1857 | { | |
1858 | { | |
96b3c83d BZ |
1859 | if (pAd->StaCfg.WpaSupplicantUP != |
1860 | WPA_SUPPLICANT_DISABLE) { | |
ca97b838 BZ |
1861 | if (AuthMode < Ndis802_11AuthModeWPA) |
1862 | return; | |
96b3c83d | 1863 | } else { |
ec278fa2 BZ |
1864 | /* Support WPAPSK or WPA2PSK in STA-Infra mode */ |
1865 | /* Support WPANone in STA-Adhoc mode */ | |
ca97b838 | 1866 | if ((AuthMode != Ndis802_11AuthModeWPAPSK) && |
96b3c83d BZ |
1867 | (AuthMode != Ndis802_11AuthModeWPA2PSK) && |
1868 | (AuthMode != Ndis802_11AuthModeWPANone) | |
1869 | ) | |
ca97b838 BZ |
1870 | return; |
1871 | } | |
1872 | ||
96b3c83d | 1873 | DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPMakeRSNIE(STA)\n")); |
ca97b838 | 1874 | |
ec278fa2 | 1875 | /* Zero RSNIE context */ |
ca97b838 BZ |
1876 | pAd->StaCfg.RSNIE_Len = 0; |
1877 | NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE); | |
1878 | ||
ec278fa2 | 1879 | /* Pointer to RSNIE */ |
ca97b838 BZ |
1880 | rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len; |
1881 | pRsnIe = pAd->StaCfg.RSN_IE; | |
1882 | ||
1883 | bMixCipher = pAd->StaCfg.bMixCipher; | |
1884 | } | |
1885 | } | |
1886 | ||
ec278fa2 | 1887 | /* indicate primary RSNIE as WPA or WPA2 */ |
ca97b838 | 1888 | if ((AuthMode == Ndis802_11AuthModeWPA) || |
96b3c83d BZ |
1889 | (AuthMode == Ndis802_11AuthModeWPAPSK) || |
1890 | (AuthMode == Ndis802_11AuthModeWPANone) || | |
1891 | (AuthMode == Ndis802_11AuthModeWPA1WPA2) || | |
1892 | (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) | |
ca97b838 | 1893 | PrimaryRsnie = WpaIe; |
91980990 | 1894 | else |
ca97b838 | 1895 | PrimaryRsnie = Wpa2Ie; |
91980990 | 1896 | |
ca97b838 | 1897 | { |
ec278fa2 BZ |
1898 | /* Build the primary RSNIE */ |
1899 | /* 1. insert cipher suite */ | |
96b3c83d BZ |
1900 | RTMPMakeRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher, |
1901 | FlexibleCipher, pRsnIe, &p_offset); | |
ca97b838 | 1902 | |
ec278fa2 | 1903 | /* 2. insert AKM */ |
96b3c83d BZ |
1904 | RTMPMakeRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, |
1905 | &p_offset); | |
ca97b838 | 1906 | |
ec278fa2 | 1907 | /* 3. insert capability */ |
ca97b838 BZ |
1908 | RTMPMakeRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset); |
1909 | } | |
1910 | ||
ec278fa2 | 1911 | /* 4. update the RSNIE length */ |
ca97b838 BZ |
1912 | *rsnielen_cur_p = p_offset; |
1913 | ||
1914 | hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p)); | |
1915 | ||
ca97b838 BZ |
1916 | } |
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 | |
1927 | DataByteCount - the received frame's length | |
1928 | FromWhichBSSID - indicate the interface index | |
1929 | ||
1930 | Return: | |
1931 | TRUE - This frame is EAP frame | |
1932 | FALSE - otherwise | |
1933 | ========================================================================== | |
1934 | */ | |
62eb734b BZ |
1935 | BOOLEAN RTMPCheckWPAframe(struct rt_rtmp_adapter *pAd, |
1936 | struct rt_mac_table_entry *pEntry, | |
51126deb BZ |
1937 | u8 *pData, |
1938 | unsigned long DataByteCount, u8 FromWhichBSSID) | |
ca97b838 | 1939 | { |
51126deb | 1940 | unsigned long Body_len; |
ca97b838 BZ |
1941 | BOOLEAN Cancelled; |
1942 | ||
96b3c83d BZ |
1943 | if (DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H)) |
1944 | return FALSE; | |
ca97b838 | 1945 | |
ec278fa2 | 1946 | /* Skip LLC header */ |
96b3c83d | 1947 | if (NdisEqualMemory(SNAP_802_1H, pData, 6) || |
ec278fa2 | 1948 | /* Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL */ |
96b3c83d BZ |
1949 | NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6)) { |
1950 | pData += 6; | |
1951 | } | |
ec278fa2 | 1952 | /* Skip 2-bytes EAPoL type */ |
96b3c83d BZ |
1953 | if (NdisEqualMemory(EAPOL, pData, 2)) { |
1954 | pData += 2; | |
1955 | } else | |
1956 | return FALSE; | |
1957 | ||
1958 | 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; | |
1994 | ||
1995 | } | |
1996 | return TRUE; | |
ca97b838 BZ |
1997 | } |
1998 | ||
1999 | /* | |
2000 | ========================================================================== | |
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 | */ | |
51126deb | 2017 | char *GetEapolMsgType(char msg) |
ca97b838 | 2018 | { |
96b3c83d BZ |
2019 | 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"; | |
ca97b838 BZ |
2033 | } |
2034 | ||
ca97b838 BZ |
2035 | /* |
2036 | ======================================================================== | |
2037 | ||
2038 | Routine Description: | |
2039 | Check Sanity RSN IE of EAPoL message | |
2040 | ||
2041 | Arguments: | |
2042 | ||
2043 | Return Value: | |
2044 | ||
ca97b838 BZ |
2045 | ======================================================================== |
2046 | */ | |
62eb734b | 2047 | BOOLEAN RTMPCheckRSNIE(struct rt_rtmp_adapter *pAd, |
51126deb BZ |
2048 | u8 *pData, |
2049 | u8 DataLen, | |
62eb734b | 2050 | struct rt_mac_table_entry *pEntry, u8 * Offset) |
ca97b838 | 2051 | { |
51126deb BZ |
2052 | u8 *pVIE; |
2053 | u8 len; | |
62eb734b | 2054 | struct rt_eid * pEid; |
96b3c83d | 2055 | BOOLEAN result = FALSE; |
ca97b838 BZ |
2056 | |
2057 | pVIE = pData; | |
96b3c83d | 2058 | len = DataLen; |
ca97b838 BZ |
2059 | *Offset = 0; |
2060 | ||
62eb734b BZ |
2061 | while (len > sizeof(struct rt_rsnie2)) { |
2062 | pEid = (struct rt_eid *) pVIE; | |
ec278fa2 | 2063 | /* WPA RSN IE */ |
96b3c83d BZ |
2064 | 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; | |
ca97b838 BZ |
2073 | } |
2074 | ||
2075 | *Offset += (pEid->Len + 2); | |
2076 | } | |
ec278fa2 | 2077 | /* WPA2 RSN IE */ |
96b3c83d BZ |
2078 | 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))) { | |
2088 | ||
2089 | result = TRUE; | |
ca97b838 BZ |
2090 | } |
2091 | ||
2092 | *Offset += (pEid->Len + 2); | |
96b3c83d | 2093 | } else { |
ca97b838 BZ |
2094 | break; |
2095 | } | |
91980990 | 2096 | |
ca97b838 | 2097 | pVIE += (pEid->Len + 2); |
96b3c83d | 2098 | len -= (pEid->Len + 2); |
ca97b838 | 2099 | } |
91980990 | 2100 | |
ca97b838 BZ |
2101 | 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 | |
2111 | ||
2112 | Arguments: | |
2113 | ||
2114 | Return Value: | |
2115 | ||
2116 | Note: | |
2117 | 802.11i D10 | |
2118 | ||
2119 | ======================================================================== | |
2120 | */ | |
62eb734b | 2121 | BOOLEAN RTMPParseEapolKeyData(struct rt_rtmp_adapter *pAd, |
51126deb BZ |
2122 | u8 *pKeyData, |
2123 | u8 KeyDataLen, | |
2124 | u8 GroupKeyIndex, | |
2125 | u8 MsgType, | |
62eb734b | 2126 | IN BOOLEAN bWPA2, struct rt_mac_table_entry *pEntry) |
ca97b838 | 2127 | { |
62eb734b | 2128 | struct rt_kde_encap * pKDE = NULL; |
51126deb BZ |
2129 | u8 *pMyKeyData = pKeyData; |
2130 | u8 KeyDataLength = KeyDataLen; | |
2131 | u8 GTKLEN = 0; | |
2132 | u8 DefaultIdx = 0; | |
2133 | u8 skip_offset; | |
ca97b838 | 2134 | |
ec278fa2 | 2135 | /* Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it */ |
96b3c83d | 2136 | if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3) { |
ec278fa2 | 2137 | /* Check RSN IE whether it is WPA2/WPA2PSK */ |
96b3c83d BZ |
2138 | if (!RTMPCheckRSNIE |
2139 | (pAd, pKeyData, KeyDataLen, pEntry, &skip_offset)) { | |
ec278fa2 | 2140 | /* send wireless event - for RSN IE different */ |
ca97b838 | 2141 | if (pAd->CommonCfg.bWirelessEvent) |
96b3c83d BZ |
2142 | RTMPSendWirelessEvent(pAd, |
2143 | IW_RSNIE_DIFF_EVENT_FLAG, | |
2144 | pEntry->Addr, | |
2145 | pEntry->apidx, 0); | |
2146 | ||
2147 | DBGPRINT(RT_DEBUG_ERROR, | |
2148 | ("RSN_IE Different in msg %d of 4-way handshake!\n", | |
2149 | MsgType)); | |
ca97b838 | 2150 | hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen); |
96b3c83d BZ |
2151 | hex_dump("Desired RSN_IE ", pEntry->RSN_IE, |
2152 | pEntry->RSNIE_Len); | |
ca97b838 BZ |
2153 | |
2154 | return FALSE; | |
96b3c83d BZ |
2155 | } else { |
2156 | if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3) { | |
ca97b838 BZ |
2157 | WpaShowAllsuite(pMyKeyData, skip_offset); |
2158 | ||
ec278fa2 | 2159 | /* skip RSN IE */ |
ca97b838 BZ |
2160 | pMyKeyData += skip_offset; |
2161 | KeyDataLength -= skip_offset; | |
96b3c83d BZ |
2162 | DBGPRINT(RT_DEBUG_TRACE, |
2163 | ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", | |
2164 | skip_offset)); | |
2165 | } else | |
ca97b838 BZ |
2166 | return TRUE; |
2167 | } | |
2168 | } | |
91980990 | 2169 | |
96b3c83d BZ |
2170 | DBGPRINT(RT_DEBUG_TRACE, |
2171 | ("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", | |
2172 | KeyDataLength)); | |
ec278fa2 | 2173 | /*hex_dump("remain data", pMyKeyData, KeyDataLength); */ |
91980990 | 2174 | |
ec278fa2 | 2175 | /* Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2 */ |
96b3c83d BZ |
2176 | if (bWPA2 |
2177 | && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1)) { | |
ec278fa2 | 2178 | if (KeyDataLength >= 8) /* KDE format exclude GTK length */ |
96b3c83d | 2179 | { |
62eb734b | 2180 | pKDE = (struct rt_kde_encap *) pMyKeyData; |
91980990 | 2181 | |
ca97b838 | 2182 | DefaultIdx = pKDE->GTKEncap.Kid; |
91980990 | 2183 | |
ec278fa2 | 2184 | /* Sanity check - KED length */ |
96b3c83d BZ |
2185 | if (KeyDataLength < (pKDE->Len + 2)) { |
2186 | DBGPRINT(RT_DEBUG_ERROR, | |
2187 | ("ERROR: The len from KDE is too short \n")); | |
2188 | return FALSE; | |
2189 | } | |
ec278fa2 | 2190 | /* Get GTK length - refer to IEEE 802.11i-2004 p.82 */ |
96b3c83d BZ |
2191 | 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; | |
ca97b838 | 2197 | } |
91980990 | 2198 | |
96b3c83d BZ |
2199 | } else { |
2200 | DBGPRINT(RT_DEBUG_ERROR, | |
2201 | ("ERROR: KDE format length is too short \n")); | |
2202 | return FALSE; | |
2203 | } | |
91980990 | 2204 | |
96b3c83d BZ |
2205 | DBGPRINT(RT_DEBUG_TRACE, |
2206 | ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", | |
2207 | DefaultIdx, GTKLEN)); | |
ec278fa2 | 2208 | /* skip it */ |
ca97b838 BZ |
2209 | pMyKeyData += 8; |
2210 | KeyDataLength -= 8; | |
91980990 | 2211 | |
96b3c83d | 2212 | } else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1) { |
ca97b838 | 2213 | DefaultIdx = GroupKeyIndex; |
96b3c83d BZ |
2214 | DBGPRINT(RT_DEBUG_TRACE, |
2215 | ("GTK DefaultKeyID=%d \n", DefaultIdx)); | |
ca97b838 | 2216 | } |
ec278fa2 | 2217 | /* Sanity check - shared key index must be 1 ~ 3 */ |
96b3c83d BZ |
2218 | 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; | |
ca97b838 | 2224 | } |
91980990 | 2225 | |
ca97b838 | 2226 | { |
62eb734b | 2227 | struct rt_cipher_key *pSharedKey; |
ca97b838 | 2228 | |
ec278fa2 | 2229 | /* set key material, TxMic and RxMic */ |
ca97b838 BZ |
2230 | NdisMoveMemory(pAd->StaCfg.GTK, pMyKeyData, 32); |
2231 | pAd->StaCfg.DefaultKeyId = DefaultIdx; | |
2232 | ||
2233 | pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId]; | |
2234 | ||
ec278fa2 | 2235 | /* Prepare pair-wise key information into shared key table */ |
62eb734b | 2236 | NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key)); |
ca97b838 BZ |
2237 | pSharedKey->KeyLen = LEN_TKIP_EK; |
2238 | NdisMoveMemory(pSharedKey->Key, pAd->StaCfg.GTK, LEN_TKIP_EK); | |
96b3c83d BZ |
2239 | NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.GTK[16], |
2240 | LEN_TKIP_RXMICK); | |
2241 | NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.GTK[24], | |
2242 | LEN_TKIP_TXMICK); | |
ca97b838 | 2243 | |
ec278fa2 | 2244 | /* Update Shared Key CipherAlg */ |
ca97b838 BZ |
2245 | pSharedKey->CipherAlg = CIPHER_NONE; |
2246 | if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) | |
2247 | pSharedKey->CipherAlg = CIPHER_TKIP; | |
96b3c83d BZ |
2248 | else if (pAd->StaCfg.GroupCipher == |
2249 | Ndis802_11Encryption3Enabled) | |
ca97b838 BZ |
2250 | pSharedKey->CipherAlg = CIPHER_AES; |
2251 | else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled) | |
2252 | pSharedKey->CipherAlg = CIPHER_WEP64; | |
96b3c83d BZ |
2253 | else if (pAd->StaCfg.GroupCipher == |
2254 | Ndis802_11GroupWEP104Enabled) | |
ca97b838 BZ |
2255 | pSharedKey->CipherAlg = CIPHER_WEP128; |
2256 | ||
ec278fa2 | 2257 | /* Update group key information to ASIC Shared Key Table */ |
ca97b838 | 2258 | AsicAddSharedKeyEntry(pAd, |
96b3c83d BZ |
2259 | BSS0, |
2260 | pAd->StaCfg.DefaultKeyId, | |
2261 | pSharedKey->CipherAlg, | |
2262 | pSharedKey->Key, | |
2263 | pSharedKey->TxMic, pSharedKey->RxMic); | |
ca97b838 | 2264 | |
ec278fa2 | 2265 | /* Update ASIC WCID attribute table and IVEIV table */ |
ca97b838 | 2266 | RTMPAddWcidAttributeEntry(pAd, |
96b3c83d BZ |
2267 | BSS0, |
2268 | pAd->StaCfg.DefaultKeyId, | |
2269 | pSharedKey->CipherAlg, NULL); | |
91980990 GKH |
2270 | } |
2271 | ||
ca97b838 BZ |
2272 | return TRUE; |
2273 | ||
91980990 GKH |
2274 | } |
2275 | ||
2276 | /* | |
2277 | ======================================================================== | |
2278 | ||
2279 | Routine Description: | |
ca97b838 BZ |
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 | ||
91980990 | 2313 | Arguments: |
ca97b838 | 2314 | pAd Pointer to our adapter |
91980990 GKH |
2315 | |
2316 | Return Value: | |
ca97b838 | 2317 | None |
91980990 GKH |
2318 | |
2319 | Note: | |
2320 | ||
2321 | ======================================================================== | |
2322 | */ | |
62eb734b | 2323 | void ConstructEapolMsg(struct rt_mac_table_entry *pEntry, |
51126deb BZ |
2324 | u8 GroupKeyWepStatus, |
2325 | u8 MsgType, | |
2326 | u8 DefaultKeyIdx, | |
2327 | u8 * KeyNonce, | |
2328 | u8 * TxRSC, | |
2329 | u8 * GTK, | |
2330 | u8 * RSNIE, | |
62eb734b | 2331 | u8 RSNIE_Len, struct rt_eapol_packet * pMsg) |
91980990 | 2332 | { |
96b3c83d | 2333 | BOOLEAN bWPA2 = FALSE; |
51126deb | 2334 | u8 KeyDescVer; |
91980990 | 2335 | |
ec278fa2 | 2336 | /* Choose WPA2 or not */ |
ca97b838 | 2337 | if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || |
96b3c83d | 2338 | (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) |
ca97b838 | 2339 | bWPA2 = TRUE; |
91980990 | 2340 | |
ec278fa2 | 2341 | /* Init Packet and Fill header */ |
96b3c83d BZ |
2342 | pMsg->ProVer = EAPOL_VER; |
2343 | pMsg->ProType = EAPOLKey; | |
91980990 | 2344 | |
ec278fa2 | 2345 | /* Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field */ |
51126deb | 2346 | SET_u16_TO_ARRARY(pMsg->Body_Len, LEN_EAPOL_KEY_MSG); |
91980990 | 2347 | |
ec278fa2 | 2348 | /* Fill in EAPoL descriptor */ |
ca97b838 BZ |
2349 | if (bWPA2) |
2350 | pMsg->KeyDesc.Type = WPA2_KEY_DESC; | |
2351 | else | |
2352 | pMsg->KeyDesc.Type = WPA1_KEY_DESC; | |
91980990 | 2353 | |
ec278fa2 | 2354 | /* Key Descriptor Version (bits 0-2) specifies the key descriptor version type */ |
ca97b838 | 2355 | { |
ec278fa2 BZ |
2356 | /* 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. */ | |
96b3c83d BZ |
2358 | KeyDescVer = |
2359 | (((pEntry->WepStatus == Ndis802_11Encryption3Enabled) | |
2360 | || (GroupKeyWepStatus == | |
2361 | Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) | |
2362 | : (DESC_TYPE_TKIP)); | |
ca97b838 BZ |
2363 | } |
2364 | ||
2365 | pMsg->KeyDesc.KeyInfo.KeyDescVer = KeyDescVer; | |
2366 | ||
ec278fa2 | 2367 | /* Specify Key Type as Group(0) or Pairwise(1) */ |
ca97b838 BZ |
2368 | if (MsgType >= EAPOL_GROUP_MSG_1) |
2369 | pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY; | |
96b3c83d | 2370 | else |
ca97b838 | 2371 | pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; |
91980990 | 2372 | |
ec278fa2 | 2373 | /* Specify Key Index, only group_msg1_WPA1 */ |
ca97b838 BZ |
2374 | if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)) |
2375 | pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx; | |
91980990 | 2376 | |
ca97b838 BZ |
2377 | if (MsgType == EAPOL_PAIR_MSG_3) |
2378 | pMsg->KeyDesc.KeyInfo.Install = 1; | |
2379 | ||
96b3c83d BZ |
2380 | if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) |
2381 | || (MsgType == EAPOL_GROUP_MSG_1)) | |
ca97b838 BZ |
2382 | 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)) || | |
96b3c83d BZ |
2388 | (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))) { |
2389 | pMsg->KeyDesc.KeyInfo.Secure = 1; | |
2390 | } | |
ca97b838 BZ |
2391 | |
2392 | if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) || | |
96b3c83d BZ |
2393 | (MsgType == EAPOL_GROUP_MSG_1))) { |
2394 | pMsg->KeyDesc.KeyInfo.EKD_DL = 1; | |
2395 | } | |
ec278fa2 | 2396 | /* key Information element has done. */ |
51126deb BZ |
2397 | *(u16 *) (&pMsg->KeyDesc.KeyInfo) = |
2398 | cpu2le16(*(u16 *) (&pMsg->KeyDesc.KeyInfo)); | |
91980990 | 2399 | |
ec278fa2 | 2400 | /* Fill in Key Length */ |
91980990 | 2401 | { |
96b3c83d | 2402 | if (MsgType >= EAPOL_GROUP_MSG_1) { |
ec278fa2 | 2403 | /* the length of group key cipher */ |
96b3c83d BZ |
2404 | pMsg->KeyDesc.KeyLength[1] = |
2405 | ((GroupKeyWepStatus == | |
2406 | Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH : | |
2407 | LEN_AES_KEY); | |
2408 | } else { | |
ec278fa2 | 2409 | /* the length of pairwise key cipher */ |
96b3c83d BZ |
2410 | pMsg->KeyDesc.KeyLength[1] = |
2411 | ((pEntry->WepStatus == | |
2412 | Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : | |
2413 | LEN_AES_KEY); | |
ca97b838 BZ |
2414 | } |
2415 | } | |
91980990 | 2416 | |
ec278fa2 | 2417 | /* Fill in replay counter */ |
96b3c83d BZ |
2418 | NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, |
2419 | LEN_KEY_DESC_REPLAY); | |
91980990 | 2420 | |
ec278fa2 BZ |
2421 | /* Fill Key Nonce field */ |
2422 | /* ANonce : pairwise_msg1 & pairwise_msg3 */ | |
2423 | /* SNonce : pairwise_msg2 */ | |
2424 | /* GNonce : group_msg1_wpa1 */ | |
96b3c83d BZ |
2425 | if ((MsgType <= EAPOL_PAIR_MSG_3) |
2426 | || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)))) | |
2427 | NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, | |
2428 | LEN_KEY_DESC_NONCE); | |
91980990 | 2429 | |
ec278fa2 | 2430 | /* Fill key IV - WPA2 as 0, WPA1 as random */ |
96b3c83d | 2431 | if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) { |
ec278fa2 | 2432 | /* Suggest IV be random number plus some number, */ |
96b3c83d BZ |
2433 | NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], |
2434 | LEN_KEY_DESC_IV); | |
2435 | pMsg->KeyDesc.KeyIv[15] += 2; | |
2436 | } | |
ec278fa2 BZ |
2437 | /* Fill Key RSC field */ |
2438 | /* It contains the RSC for the GTK being installed. */ | |
96b3c83d BZ |
2439 | if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) |
2440 | || (MsgType == EAPOL_GROUP_MSG_1)) { | |
2441 | NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6); | |
2442 | } | |
ec278fa2 | 2443 | /* Clear Key MIC field for MIC calculation later */ |
96b3c83d | 2444 | NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); |
ca97b838 BZ |
2445 | |
2446 | ConstructEapolKeyData(pEntry, | |
96b3c83d BZ |
2447 | GroupKeyWepStatus, |
2448 | KeyDescVer, | |
2449 | MsgType, | |
2450 | DefaultKeyIdx, GTK, RSNIE, RSNIE_Len, pMsg); | |
ca97b838 | 2451 | |
ec278fa2 | 2452 | /* Calculate MIC and fill in KeyMic Field except Pairwise Msg 1. */ |
96b3c83d | 2453 | if (MsgType != EAPOL_PAIR_MSG_1) { |
ca97b838 | 2454 | CalculateMIC(KeyDescVer, pEntry->PTK, pMsg); |
96b3c83d | 2455 | } |
ca97b838 | 2456 | |
96b3c83d BZ |
2457 | 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", | |
51126deb | 2462 | CONV_ARRARY_TO_u16(pMsg->Body_Len))); |
96b3c83d BZ |
2463 | DBGPRINT(RT_DEBUG_TRACE, |
2464 | (" Key length = %d \n", | |
51126deb | 2465 | CONV_ARRARY_TO_u16(pMsg->KeyDesc.KeyLength))); |
ca97b838 | 2466 | |
91980990 GKH |
2467 | } |
2468 | ||
2469 | /* | |
2470 | ======================================================================== | |
2471 | ||
2472 | Routine Description: | |
ca97b838 | 2473 | Construct the Key Data field of EAPoL message |
91980990 GKH |
2474 | |
2475 | Arguments: | |
ca97b838 BZ |
2476 | pAd Pointer to our adapter |
2477 | Elem Message body | |
91980990 GKH |
2478 | |
2479 | Return Value: | |
ca97b838 | 2480 | None |
91980990 GKH |
2481 | |
2482 | Note: | |
2483 | ||
2484 | ======================================================================== | |
2485 | */ | |
62eb734b | 2486 | void ConstructEapolKeyData(struct rt_mac_table_entry *pEntry, |
51126deb BZ |
2487 | u8 GroupKeyWepStatus, |
2488 | u8 keyDescVer, | |
2489 | u8 MsgType, | |
2490 | u8 DefaultKeyIdx, | |
2491 | u8 * GTK, | |
2492 | u8 * RSNIE, | |
62eb734b | 2493 | u8 RSNIE_LEN, struct rt_eapol_packet * pMsg) |
91980990 | 2494 | { |
51126deb BZ |
2495 | u8 *mpool, *Key_Data, *Rc4GTK; |
2496 | u8 ekey[(LEN_KEY_DESC_IV + LEN_EAP_EK)]; | |
2497 | unsigned long data_offset; | |
96b3c83d | 2498 | BOOLEAN bWPA2Capable = FALSE; |
62eb734b | 2499 | struct rt_rtmp_adapter *pAd = pEntry->pAd; |
96b3c83d | 2500 | BOOLEAN GTK_Included = FALSE; |
ca97b838 | 2501 | |
ec278fa2 | 2502 | /* Choose WPA2 or not */ |
ca97b838 | 2503 | if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || |
96b3c83d | 2504 | (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) |
ca97b838 BZ |
2505 | bWPA2Capable = TRUE; |
2506 | ||
2507 | if (MsgType == EAPOL_PAIR_MSG_1 || | |
96b3c83d | 2508 | MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2) |
ca97b838 | 2509 | return; |
91980990 | 2510 | |
ec278fa2 | 2511 | /* allocate memory pool */ |
51126deb | 2512 | os_alloc_mem(NULL, (u8 **) & mpool, 1500); |
91980990 | 2513 | |
96b3c83d | 2514 | if (mpool == NULL) |
ca97b838 BZ |
2515 | return; |
2516 | ||
2517 | /* Rc4GTK Len = 512 */ | |
51126deb | 2518 | Rc4GTK = (u8 *) ROUND_UP(mpool, 4); |
ca97b838 | 2519 | /* Key_Data Len = 512 */ |
51126deb | 2520 | Key_Data = (u8 *) ROUND_UP(Rc4GTK + 512, 4); |
ca97b838 BZ |
2521 | |
2522 | NdisZeroMemory(Key_Data, 512); | |
51126deb | 2523 | SET_u16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, 0); |
ca97b838 BZ |
2524 | data_offset = 0; |
2525 | ||
ec278fa2 | 2526 | /* Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3 */ |
96b3c83d BZ |
2527 | if (RSNIE_LEN |
2528 | && ((MsgType == EAPOL_PAIR_MSG_2) | |
2529 | || (MsgType == EAPOL_PAIR_MSG_3))) { | |
51126deb BZ |
2530 | u8 *pmkid_ptr = NULL; |
2531 | u8 pmkid_len = 0; | |
ca97b838 BZ |
2532 | |
2533 | RTMPInsertRSNIE(&Key_Data[data_offset], | |
96b3c83d BZ |
2534 | &data_offset, |
2535 | RSNIE, RSNIE_LEN, pmkid_ptr, pmkid_len); | |
ca97b838 BZ |
2536 | } |
2537 | ||
ec278fa2 | 2538 | /* Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2 */ |
96b3c83d BZ |
2539 | if (bWPA2Capable |
2540 | && ((MsgType == EAPOL_PAIR_MSG_3) | |
2541 | || (MsgType == EAPOL_GROUP_MSG_1))) { | |
ec278fa2 | 2542 | /* Key Data Encapsulation (KDE) format - 802.11i-2004 Figure-43w and Table-20h */ |
96b3c83d | 2543 | Key_Data[data_offset + 0] = 0xDD; |
ca97b838 | 2544 | |
96b3c83d | 2545 | if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) { |
ec278fa2 | 2546 | Key_Data[data_offset + 1] = 0x16; /* 4+2+16(OUI+DataType+DataField) */ |
96b3c83d | 2547 | } else { |
ec278fa2 | 2548 | Key_Data[data_offset + 1] = 0x26; /* 4+2+32(OUI+DataType+DataField) */ |
ca97b838 BZ |
2549 | } |
2550 | ||
96b3c83d BZ |
2551 | 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; | |
ca97b838 | 2555 | |
ec278fa2 | 2556 | /* GTK KDE format - 802.11i-2004 Figure-43x */ |
96b3c83d | 2557 | Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03); |
ec278fa2 | 2558 | Key_Data[data_offset + 7] = 0x00; /* Reserved Byte */ |
ca97b838 BZ |
2559 | |
2560 | data_offset += 8; | |
2561 | } | |
2562 | ||
ec278fa2 BZ |
2563 | /* Encapsulate GTK */ |
2564 | /* Only for pairwise_msg3_WPA2 and group_msg1 */ | |
96b3c83d BZ |
2565 | if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) |
2566 | || (MsgType == EAPOL_GROUP_MSG_1)) { | |
ec278fa2 | 2567 | /* Fill in GTK */ |
96b3c83d BZ |
2568 | if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) { |
2569 | NdisMoveMemory(&Key_Data[data_offset], GTK, | |
2570 | LEN_AES_KEY); | |
ca97b838 | 2571 | data_offset += LEN_AES_KEY; |
96b3c83d BZ |
2572 | } else { |
2573 | NdisMoveMemory(&Key_Data[data_offset], GTK, | |
2574 | TKIP_GTK_LENGTH); | |
ca97b838 BZ |
2575 | data_offset += TKIP_GTK_LENGTH; |
2576 | } | |
2577 | ||
2578 | GTK_Included = TRUE; | |
2579 | } | |
2580 | ||
ec278fa2 BZ |
2581 | /* This whole key-data field shall be encrypted if a GTK is included. */ |
2582 | /* Encrypt the data material in key data field with KEK */ | |
96b3c83d | 2583 | if (GTK_Included) { |
ec278fa2 | 2584 | /*hex_dump("GTK_Included", Key_Data, data_offset); */ |
91980990 | 2585 | |
96b3c83d | 2586 | if ((keyDescVer == DESC_TYPE_AES)) { |
51126deb BZ |
2587 | u8 remainder = 0; |
2588 | u8 pad_len = 0; | |
ca97b838 | 2589 | |
ec278fa2 BZ |
2590 | /* 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. */ | |
ca97b838 | 2593 | |
ec278fa2 BZ |
2594 | /* 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. */ | |
96b3c83d | 2598 | if ((remainder = data_offset & 0x07) != 0) { |
51126deb | 2599 | int i; |
ca97b838 BZ |
2600 | |
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; | |
96b3c83d | 2607 | } |
ca97b838 | 2608 | |
96b3c83d BZ |
2609 | AES_GTK_KEY_WRAP(&pEntry->PTK[16], Key_Data, |
2610 | data_offset, Rc4GTK); | |
ec278fa2 | 2611 | /* AES wrap function will grow 8 bytes in length */ |
96b3c83d BZ |
2612 | 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. */ | |
ca97b838 | 2616 | |
ec278fa2 BZ |
2617 | /* 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. */ | |
ca97b838 | 2620 | |
ec278fa2 | 2621 | /* ekey is the contanetion of IV-field, and PTK[16]->PTK[31] */ |
96b3c83d BZ |
2622 | NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv, |
2623 | LEN_KEY_DESC_IV); | |
2624 | NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &pEntry->PTK[16], | |
2625 | LEN_EAP_EK); | |
ec278fa2 | 2626 | ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey)); /*INIT SBOX, KEYLEN+3(IV) */ |
96b3c83d BZ |
2627 | 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); | |
ca97b838 | 2632 | } |
91980990 | 2633 | |
ca97b838 | 2634 | NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset); |
96b3c83d | 2635 | } else { |
ca97b838 | 2636 | NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset); |
91980990 GKH |
2637 | } |
2638 | ||
ec278fa2 | 2639 | /* Update key data length field and total body length */ |
51126deb BZ |
2640 | SET_u16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, data_offset); |
2641 | INC_u16_TO_ARRARY(pMsg->Body_Len, data_offset); | |
91980990 | 2642 | |
ca97b838 | 2643 | os_free_mem(NULL, mpool); |
91980990 GKH |
2644 | |
2645 | } | |
2646 | ||
2647 | /* | |
2648 | ======================================================================== | |
2649 | ||
2650 | Routine Description: | |
ca97b838 | 2651 | Calcaulate MIC. It is used during 4-ways handsharking. |
91980990 GKH |
2652 | |
2653 | Arguments: | |
2654 | pAd - pointer to our pAdapter context | |
ca97b838 | 2655 | PeerWepStatus - indicate the encryption type |
91980990 GKH |
2656 | |
2657 | Return Value: | |
2658 | ||
2659 | Note: | |
2660 | ||
2661 | ======================================================================== | |
2662 | */ | |
51126deb | 2663 | static void CalculateMIC(u8 KeyDescVer, |
62eb734b | 2664 | u8 * PTK, struct rt_eapol_packet * pMsg) |
91980990 | 2665 | { |
51126deb BZ |
2666 | u8 *OutBuffer; |
2667 | unsigned long FrameLen = 0; | |
2668 | u8 mic[LEN_KEY_DESC_MIC]; | |
2669 | u8 digest[80]; | |
91980990 | 2670 | |
ec278fa2 | 2671 | /* allocate memory for MIC calculation */ |
51126deb | 2672 | os_alloc_mem(NULL, (u8 **) & OutBuffer, 512); |
ca97b838 | 2673 | |
96b3c83d | 2674 | if (OutBuffer == NULL) { |
06aea994 | 2675 | DBGPRINT(RT_DEBUG_ERROR, ("CalculateMIC: no memory!\n")); |
91980990 | 2676 | return; |
96b3c83d | 2677 | } |
ec278fa2 | 2678 | /* make a frame for calculating MIC. */ |
96b3c83d | 2679 | MakeOutgoingFrame(OutBuffer, &FrameLen, |
51126deb | 2680 | CONV_ARRARY_TO_u16(pMsg->Body_Len) + 4, pMsg, |
96b3c83d | 2681 | END_OF_ARGS); |
91980990 | 2682 | |
ca97b838 | 2683 | NdisZeroMemory(mic, sizeof(mic)); |
91980990 | 2684 | |
ec278fa2 | 2685 | /* Calculate MIC */ |
96b3c83d BZ |
2686 | if (KeyDescVer == DESC_TYPE_AES) { |
2687 | HMAC_SHA1(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, digest, | |
2688 | SHA1_DIGEST_SIZE); | |
ca97b838 | 2689 | NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC); |
96b3c83d BZ |
2690 | } else { |
2691 | HMAC_MD5(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, mic, | |
2692 | MD5_DIGEST_SIZE); | |
ca97b838 | 2693 | } |
91980990 | 2694 | |
ec278fa2 | 2695 | /* store the calculated MIC */ |
ca97b838 | 2696 | NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC); |
91980990 | 2697 | |
ca97b838 | 2698 | os_free_mem(NULL, OutBuffer); |
91980990 GKH |
2699 | } |
2700 | ||
91980990 GKH |
2701 | /* |
2702 | ======================================================================== | |
2703 | ||
2704 | Routine Description: | |
ca97b838 | 2705 | Some received frames can't decrypt by Asic, so decrypt them by software. |
91980990 GKH |
2706 | |
2707 | Arguments: | |
2708 | pAd - pointer to our pAdapter context | |
ca97b838 | 2709 | PeerWepStatus - indicate the encryption type |
91980990 GKH |
2710 | |
2711 | Return Value: | |
ca97b838 BZ |
2712 | NDIS_STATUS_SUCCESS - decryption successful |
2713 | NDIS_STATUS_FAILURE - decryption failure | |
91980990 GKH |
2714 | |
2715 | ======================================================================== | |
2716 | */ | |
62eb734b BZ |
2717 | int RTMPSoftDecryptBroadCastData(struct rt_rtmp_adapter *pAd, |
2718 | struct rt_rx_blk *pRxBlk, | |
96b3c83d | 2719 | IN NDIS_802_11_ENCRYPTION_STATUS |
62eb734b | 2720 | GroupCipher, struct rt_cipher_key *pShard_key) |
91980990 | 2721 | { |
62eb734b | 2722 | struct rt_rxwi * pRxWI = pRxBlk->pRxWI; |
91980990 | 2723 | |
ec278fa2 | 2724 | /* handle WEP decryption */ |
96b3c83d BZ |
2725 | if (GroupCipher == Ndis802_11Encryption1Enabled) { |
2726 | if (RTMPSoftDecryptWEP | |
2727 | (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, | |
2728 | pShard_key)) { | |
ca97b838 | 2729 | |
ec278fa2 | 2730 | /*Minus IV[4] & ICV[4] */ |
ca97b838 | 2731 | pRxWI->MPDUtotalByteCount -= 8; |
96b3c83d BZ |
2732 | } else { |
2733 | DBGPRINT(RT_DEBUG_ERROR, | |
2734 | ("ERROR : Software decrypt WEP data fails.\n")); | |
ec278fa2 | 2735 | /* give up this frame */ |
ca97b838 BZ |
2736 | return NDIS_STATUS_FAILURE; |
2737 | } | |
2738 | } | |
ec278fa2 | 2739 | /* handle TKIP decryption */ |
96b3c83d BZ |
2740 | else if (GroupCipher == Ndis802_11Encryption2Enabled) { |
2741 | if (RTMPSoftDecryptTKIP | |
2742 | (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0, | |
2743 | pShard_key)) { | |
ca97b838 | 2744 | |
ec278fa2 | 2745 | /*Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV */ |
ca97b838 | 2746 | pRxWI->MPDUtotalByteCount -= 20; |
96b3c83d BZ |
2747 | } else { |
2748 | DBGPRINT(RT_DEBUG_ERROR, | |
2749 | ("ERROR : RTMPSoftDecryptTKIP Failed\n")); | |
ec278fa2 | 2750 | /* give up this frame */ |
ca97b838 | 2751 | return NDIS_STATUS_FAILURE; |
96b3c83d | 2752 | } |
ca97b838 | 2753 | } |
ec278fa2 | 2754 | /* handle AES decryption */ |
96b3c83d BZ |
2755 | else if (GroupCipher == Ndis802_11Encryption3Enabled) { |
2756 | if (RTMPSoftDecryptAES | |
2757 | (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, | |
2758 | pShard_key)) { | |
91980990 | 2759 | |
ec278fa2 | 2760 | /*8 bytes MIC, 8 bytes IV/EIV (CCMP Header) */ |
ca97b838 | 2761 | pRxWI->MPDUtotalByteCount -= 16; |
96b3c83d BZ |
2762 | } else { |
2763 | DBGPRINT(RT_DEBUG_ERROR, | |
2764 | ("ERROR : RTMPSoftDecryptAES Failed\n")); | |
ec278fa2 | 2765 | /* give up this frame */ |
ca97b838 BZ |
2766 | return NDIS_STATUS_FAILURE; |
2767 | } | |
96b3c83d | 2768 | } else { |
ec278fa2 | 2769 | /* give up this frame */ |
ca97b838 BZ |
2770 | return NDIS_STATUS_FAILURE; |
2771 | } | |
91980990 | 2772 | |
ca97b838 | 2773 | return NDIS_STATUS_SUCCESS; |
91980990 | 2774 | |
ca97b838 | 2775 | } |
91980990 | 2776 | |
51126deb BZ |
2777 | u8 *GetSuiteFromRSNIE(u8 *rsnie, |
2778 | u32 rsnie_len, u8 type, u8 * count) | |
ca97b838 | 2779 | { |
62eb734b | 2780 | struct rt_eid * pEid; |
51126deb BZ |
2781 | int len; |
2782 | u8 *pBuf; | |
2783 | int offset = 0; | |
62eb734b | 2784 | struct rt_rsnie_auth *pAkm; |
51126deb | 2785 | u16 acount; |
96b3c83d BZ |
2786 | BOOLEAN isWPA2 = FALSE; |
2787 | ||
62eb734b | 2788 | pEid = (struct rt_eid *) rsnie; |
ec278fa2 | 2789 | len = rsnie_len - 2; /* exclude IE and length */ |
51126deb | 2790 | pBuf = (u8 *)& pEid->Octet[0]; |
ca97b838 | 2791 | |
ec278fa2 | 2792 | /* set default value */ |
ca97b838 BZ |
2793 | *count = 0; |
2794 | ||
ec278fa2 | 2795 | /* Check length */ |
96b3c83d | 2796 | if ((len <= 0) || (pEid->Len != len)) { |
ca97b838 BZ |
2797 | DBGPRINT_ERR(("%s : The length is invalid\n", __func__)); |
2798 | return NULL; | |
91980990 | 2799 | } |
ec278fa2 | 2800 | /* Check WPA or WPA2 */ |
96b3c83d | 2801 | if (pEid->Eid == IE_WPA) { |
62eb734b | 2802 | struct rt_rsnie *pRsnie = (struct rt_rsnie *)pBuf; |
51126deb | 2803 | u16 ucount; |
91980990 | 2804 | |
62eb734b | 2805 | if (len < sizeof(struct rt_rsnie)) { |
96b3c83d BZ |
2806 | DBGPRINT_ERR(("%s : The length is too short for WPA\n", |
2807 | __func__)); | |
ca97b838 BZ |
2808 | return NULL; |
2809 | } | |
ec278fa2 | 2810 | /* Get the count of pairwise cipher */ |
ca97b838 | 2811 | ucount = cpu2le16(pRsnie->ucount); |
96b3c83d BZ |
2812 | if (ucount > 2) { |
2813 | DBGPRINT_ERR(("%s : The count(%d) of pairwise cipher is invlaid\n", __func__, ucount)); | |
ca97b838 BZ |
2814 | return NULL; |
2815 | } | |
ec278fa2 | 2816 | /* Get the group cipher */ |
96b3c83d | 2817 | if (type == GROUP_SUITE) { |
ca97b838 BZ |
2818 | *count = 1; |
2819 | return pRsnie->mcast; | |
2820 | } | |
ec278fa2 | 2821 | /* Get the pairwise cipher suite */ |
96b3c83d BZ |
2822 | else if (type == PAIRWISE_SUITE) { |
2823 | DBGPRINT(RT_DEBUG_TRACE, | |
2824 | ("%s : The count of pairwise cipher is %d\n", | |
2825 | __func__, ucount)); | |
ca97b838 BZ |
2826 | *count = ucount; |
2827 | return pRsnie->ucast[0].oui; | |
96b3c83d | 2828 | } |
91980990 | 2829 | |
62eb734b | 2830 | offset = sizeof(struct rt_rsnie) + (4 * (ucount - 1)); |
91980990 | 2831 | |
96b3c83d | 2832 | } else if (pEid->Eid == IE_RSN) { |
62eb734b | 2833 | struct rt_rsnie2 *pRsnie = (struct rt_rsnie2 *)pBuf; |
51126deb | 2834 | u16 ucount; |
91980990 | 2835 | |
ca97b838 | 2836 | isWPA2 = TRUE; |
91980990 | 2837 | |
62eb734b | 2838 | if (len < sizeof(struct rt_rsnie2)) { |
96b3c83d BZ |
2839 | DBGPRINT_ERR(("%s : The length is too short for WPA2\n", |
2840 | __func__)); | |
ca97b838 BZ |
2841 | return NULL; |
2842 | } | |
ec278fa2 | 2843 | /* Get the count of pairwise cipher */ |
ca97b838 | 2844 | ucount = cpu2le16(pRsnie->ucount); |
96b3c83d BZ |
2845 | if (ucount > 2) { |
2846 | DBGPRINT_ERR(("%s : The count(%d) of pairwise cipher is invlaid\n", __func__, ucount)); | |
ca97b838 BZ |
2847 | return NULL; |
2848 | } | |
ec278fa2 | 2849 | /* Get the group cipher */ |
96b3c83d | 2850 | if (type == GROUP_SUITE) { |
ca97b838 BZ |
2851 | *count = 1; |
2852 | return pRsnie->mcast; | |
2853 | } | |
ec278fa2 | 2854 | /* Get the pairwise cipher suite */ |
96b3c83d BZ |
2855 | else if (type == PAIRWISE_SUITE) { |
2856 | DBGPRINT(RT_DEBUG_TRACE, | |
2857 | ("%s : The count of pairwise cipher is %d\n", | |
2858 | __func__, ucount)); | |
ca97b838 BZ |
2859 | *count = ucount; |
2860 | return pRsnie->ucast[0].oui; | |
2861 | } | |
91980990 | 2862 | |
62eb734b | 2863 | offset = sizeof(struct rt_rsnie2) + (4 * (ucount - 1)); |
ca97b838 | 2864 | |
96b3c83d | 2865 | } else { |
ca97b838 BZ |
2866 | DBGPRINT_ERR(("%s : Unknown IE (%d)\n", __func__, pEid->Eid)); |
2867 | return NULL; | |
2868 | } | |
91980990 | 2869 | |
ec278fa2 | 2870 | /* skip group cipher and pairwise cipher suite */ |
ca97b838 BZ |
2871 | pBuf += offset; |
2872 | len -= offset; | |
91980990 | 2873 | |
62eb734b | 2874 | if (len < sizeof(struct rt_rsnie_auth)) { |
96b3c83d BZ |
2875 | DBGPRINT_ERR(("%s : The length of RSNIE is too short\n", |
2876 | __func__)); | |
ca97b838 BZ |
2877 | return NULL; |
2878 | } | |
ec278fa2 | 2879 | /* pointer to AKM count */ |
62eb734b | 2880 | pAkm = (struct rt_rsnie_auth *)pBuf; |
91980990 | 2881 | |
ec278fa2 | 2882 | /* Get the count of pairwise cipher */ |
ca97b838 | 2883 | acount = cpu2le16(pAkm->acount); |
96b3c83d | 2884 | if (acount > 2) { |
ca97b838 | 2885 | DBGPRINT_ERR(("%s : The count(%d) of AKM is invlaid\n", |
96b3c83d | 2886 | __func__, acount)); |
ca97b838 | 2887 | return NULL; |
96b3c83d | 2888 | } |
ec278fa2 | 2889 | /* Get the AKM suite */ |
96b3c83d | 2890 | if (type == AKM_SUITE) { |
ca97b838 | 2891 | DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of AKM is %d\n", |
96b3c83d | 2892 | __func__, acount)); |
ca97b838 BZ |
2893 | *count = acount; |
2894 | return pAkm->auth[0].oui; | |
96b3c83d | 2895 | } |
62eb734b | 2896 | offset = sizeof(struct rt_rsnie_auth) + (4 * (acount - 1)); |
91980990 | 2897 | |
ca97b838 BZ |
2898 | pBuf += offset; |
2899 | len -= offset; | |
2900 | ||
ec278fa2 | 2901 | /* The remaining length must larger than (RSN-Capability(2) + PMKID-Count(2) + PMKID(16~)) */ |
96b3c83d | 2902 | if (len >= (sizeof(RSN_CAPABILITIES) + 2 + LEN_PMKID)) { |
ec278fa2 | 2903 | /* Skip RSN capability and PMKID-Count */ |
ca97b838 BZ |
2904 | pBuf += (sizeof(RSN_CAPABILITIES) + 2); |
2905 | len -= (sizeof(RSN_CAPABILITIES) + 2); | |
2906 | ||
ec278fa2 | 2907 | /* Get PMKID */ |
96b3c83d | 2908 | if (type == PMKID_LIST) { |
ca97b838 BZ |
2909 | *count = 1; |
2910 | return pBuf; | |
96b3c83d BZ |
2911 | } |
2912 | } else { | |
ca97b838 BZ |
2913 | DBGPRINT_ERR(("%s : it can't get any more information beyond AKM \n", __func__)); |
2914 | return NULL; | |
2915 | } | |
2916 | ||
2917 | *count = 0; | |
ec278fa2 | 2918 | /*DBGPRINT_ERR(("%s : The type(%d) doesn't support \n", __func__, type)); */ |
ca97b838 BZ |
2919 | return NULL; |
2920 | ||
91980990 GKH |
2921 | } |
2922 | ||
51126deb | 2923 | void WpaShowAllsuite(u8 *rsnie, u32 rsnie_len) |
ca97b838 | 2924 | { |
51126deb BZ |
2925 | u8 *pSuite = NULL; |
2926 | u8 count; | |
91980990 | 2927 | |
ca97b838 | 2928 | hex_dump("RSNIE", rsnie, rsnie_len); |
91980990 | 2929 | |
ec278fa2 | 2930 | /* group cipher */ |
96b3c83d BZ |
2931 | if ((pSuite = |
2932 | GetSuiteFromRSNIE(rsnie, rsnie_len, GROUP_SUITE, | |
2933 | &count)) != NULL) { | |
2934 | hex_dump("group cipher", pSuite, 4 * count); | |
ca97b838 | 2935 | } |
ec278fa2 | 2936 | /* pairwise cipher */ |
96b3c83d BZ |
2937 | if ((pSuite = |
2938 | GetSuiteFromRSNIE(rsnie, rsnie_len, PAIRWISE_SUITE, | |
2939 | &count)) != NULL) { | |
2940 | hex_dump("pairwise cipher", pSuite, 4 * count); | |
ca97b838 | 2941 | } |
ec278fa2 | 2942 | /* AKM */ |
96b3c83d BZ |
2943 | if ((pSuite = |
2944 | GetSuiteFromRSNIE(rsnie, rsnie_len, AKM_SUITE, &count)) != NULL) { | |
2945 | hex_dump("AKM suite", pSuite, 4 * count); | |
ca97b838 | 2946 | } |
ec278fa2 | 2947 | /* PMKID */ |
96b3c83d BZ |
2948 | if ((pSuite = |
2949 | GetSuiteFromRSNIE(rsnie, rsnie_len, PMKID_LIST, &count)) != NULL) { | |
ca97b838 BZ |
2950 | hex_dump("PMKID", pSuite, LEN_PMKID); |
2951 | } | |
91980990 | 2952 | |
ca97b838 | 2953 | } |
91980990 | 2954 | |
51126deb BZ |
2955 | void RTMPInsertRSNIE(u8 *pFrameBuf, |
2956 | unsigned long *pFrameLen, | |
2957 | u8 *rsnie_ptr, | |
2958 | u8 rsnie_len, | |
2959 | u8 *pmkid_ptr, u8 pmkid_len) | |
ca97b838 | 2960 | { |
51126deb BZ |
2961 | 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 }; | |
ca97b838 BZ |
2968 | |
2969 | pTmpBuf = pFrameBuf; | |
2970 | ||
2971 | /* PMKID-List Must larger than 0 and the multiple of 16. */ | |
96b3c83d | 2972 | if (pmkid_len > 0 && ((pmkid_len & 0x0f) == 0)) { |
51126deb | 2973 | extra_len = sizeof(u16)+ pmkid_len; |
91980990 | 2974 | |
ca97b838 BZ |
2975 | pmk_count = (pmkid_len >> 4); |
2976 | pmk_count = cpu2le16(pmk_count); | |
96b3c83d BZ |
2977 | } 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)); | |
ca97b838 | 2981 | } |
91980990 | 2982 | |
96b3c83d | 2983 | if (rsnie_len != 0) { |
ca97b838 BZ |
2984 | ie_num = IE_WPA; |
2985 | total_len = rsnie_len; | |
91980990 | 2986 | |
96b3c83d | 2987 | if (NdisEqualMemory(rsnie_ptr + 2, WPA2_OUI, sizeof(WPA2_OUI))) { |
ca97b838 BZ |
2988 | ie_num = IE_RSN; |
2989 | total_len += extra_len; | |
96b3c83d | 2990 | } |
91980990 | 2991 | |
ca97b838 | 2992 | /* construct RSNIE body */ |
96b3c83d BZ |
2993 | MakeOutgoingFrame(pTmpBuf, &TempLen, |
2994 | 1, &ie_num, | |
2995 | 1, &total_len, | |
2996 | rsnie_len, rsnie_ptr, END_OF_ARGS); | |
ca97b838 BZ |
2997 | |
2998 | pTmpBuf += TempLen; | |
2999 | *pFrameLen = *pFrameLen + TempLen; | |
91980990 | 3000 | |
96b3c83d | 3001 | if (ie_num == IE_RSN) { |
ca97b838 | 3002 | /* Insert PMKID-List field */ |
96b3c83d BZ |
3003 | if (extra_len > 0) { |
3004 | MakeOutgoingFrame(pTmpBuf, &TempLen, | |
3005 | 2, &pmk_count, | |
3006 | pmkid_len, pmkid_ptr, | |
3007 | END_OF_ARGS); | |
ca97b838 BZ |
3008 | |
3009 | pTmpBuf += TempLen; | |
3010 | *pFrameLen = *pFrameLen + TempLen; | |
96b3c83d | 3011 | } |
91980990 GKH |
3012 | } |
3013 | } | |
91980990 | 3014 | |
ca97b838 | 3015 | return; |
91980990 | 3016 | } |