1 /** @file keyMgmtApStaCommon.c
2 *
3 * @brief This file defines common api for authenticator and supplicant.
4 *
5 * Copyright (C) 2014-2017, Marvell International Ltd.
6 *
7 * This software file (the "File") is distributed by Marvell International
8 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
9 * (the "License"). You may use, redistribute and/or modify this File in
10 * accordance with the terms and conditions of the License, a copy of which
11 * is available by writing to the Free Software Foundation, Inc.,
12 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
13 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
14 *
15 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
17 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
18 * this warranty disclaimer.
19 */
20
21 /******************************************************
22 Change log:
23 03/07/2014: Initial version
24 ******************************************************/
25 //Authenticator related function definitions
26 #include "wltypes.h"
27 #include "IEEE_types.h"
28
29 #include "hostsa_ext_def.h"
30 #include "authenticator.h"
31
32 #include "keyMgmtAp_rom.h"
33 #include "crypt_new_rom.h"
34 #include "keyCommonDef.h"
35 #include "pmkCache_rom.h"
36 #include "crypt_new_rom.h"
37 #include "rc4_rom.h"
38 #include "aes_cmac_rom.h"
39 #include "sha1.h"
40 #include "md5.h"
41 #include "mrvl_sha256_crypto.h"
42
43 const UINT8 wpa_oui_none[4] = { 0x00, 0x50, 0xf2, 0x00 };
44 const UINT8 wpa_oui01[4] = { 0x00, 0x50, 0xf2, 0x01 };
45 const UINT8 wpa_oui02[4] = { 0x00, 0x50, 0xf2, 0x02 };
46 const UINT8 wpa_oui03[4] = { 0x00, 0x50, 0xf2, 0x03 };
47 const UINT8 wpa_oui04[4] = { 0x00, 0x50, 0xf2, 0x04 };
48 const UINT8 wpa_oui05[4] = { 0x00, 0x50, 0xf2, 0x05 };
49 const UINT8 wpa_oui06[4] = { 0x00, 0x50, 0xf2, 0x06 };
50
51 const UINT8 wpa2_oui01[4] = { 0x00, 0x0f, 0xac, 0x01 };
52 const UINT8 wpa2_oui02[4] = { 0x00, 0x0f, 0xac, 0x02 };
53 const UINT8 wpa2_oui03[4] = { 0x00, 0x0f, 0xac, 0x03 };
54 const UINT8 wpa2_oui04[4] = { 0x00, 0x0f, 0xac, 0x04 };
55 const UINT8 wpa2_oui05[4] = { 0x00, 0x0f, 0xac, 0x05 };
56 const UINT8 wpa2_oui06[4] = { 0x00, 0x0f, 0xac, 0x06 };
57
58 const UINT8 wpa_oui[3] = { 0x00, 0x50, 0xf2 };
59 const UINT8 kde_oui[3] = { 0x00, 0x0f, 0xac };
60
61 /**
62 * @brief strlen
63 *
64 * @param str A pointer to string
65 *
66 * @return Length of string
67 */
68 t_u32
wlan_strlen(const char * str)69 wlan_strlen(const char *str)
70 {
71 t_u32 i;
72
73 for (i = 0; str[i] != 0; i++) {
74 }
75 return i;
76 }
77
78 static t_u32
srand_new(void * priv)79 srand_new(void *priv)
80 {
81 phostsa_private psapriv = (phostsa_private)priv;
82 hostsa_util_fns *util_fns = &psapriv->util_fns;
83 t_u32 sec, usec;
84
85 ENTER();
86 get_system_time(util_fns, &sec, &usec);
87 sec = (sec & 0xFFFF) + (sec >> 16);
88 usec = (usec & 0xFFFF) + (usec >> 16);
89
90 LEAVE();
91 return (usec << 16) | sec;
92 }
93
94 static unsigned int
rand_new(unsigned int seed,UINT32 randvaule)95 rand_new(unsigned int seed, UINT32 randvaule)
96 {
97 unsigned int next = seed;
98 unsigned int result;
99
100 next *= (3515245 * randvaule + randvaule * next);
101 next += 12345 + randvaule * 7;
102 result = (unsigned int)(next / 65536) % 2048;
103
104 next *= (39018768 * randvaule + randvaule * next);
105 next += 56789 + randvaule * 4;
106 result <<= 10;
107 result ^= (unsigned int)(next / 65536) % 1024;
108
109 next *= (89042053 * randvaule + randvaule * next);
110 next += 43728 + randvaule * 9;
111 result <<= 10;
112 result ^= (unsigned int)(next / 65536) % 1024;
113
114 return result;
115 }
116
117 void
supplicantGenerateRand(hostsa_private * priv,UINT8 * dataOut,UINT32 length)118 supplicantGenerateRand(hostsa_private *priv, UINT8 *dataOut, UINT32 length)
119 {
120 UINT32 i;
121 //UINT32 valueHi, valueLo;
122
123 /* Read mac 0 timer.
124 ** Doesn't matter which one we read. We just need a good seed.
125 */
126 //msi_wl_GetMCUCoreTimerTxTSF(&valueHi, &valueLo);
127 //srand(valueLo);
128 for (i = 0; i < length; i++) {
129 //dataOut[i] = rand();
130 dataOut[i] = rand_new(srand_new(priv), i + 1);
131 }
132 }
133
134 void
SetEAPOLKeyDescTypeVersion(EAPOL_KeyMsg_Tx_t * pTxEapol,BOOLEAN isWPA2,BOOLEAN isKDF,BOOLEAN nonTKIP)135 SetEAPOLKeyDescTypeVersion(EAPOL_KeyMsg_Tx_t *pTxEapol,
136 BOOLEAN isWPA2, BOOLEAN isKDF, BOOLEAN nonTKIP)
137 {
138 if (isWPA2) {
139 /* WPA2 */
140 pTxEapol->keyMsg.desc_type = 2;
141 } else {
142 /* WPA */
143 pTxEapol->keyMsg.desc_type = 254;
144 }
145
146 if (isKDF) {
147 /* 802.11r and 802.11w use SHA256-KDF and a different KeyDescVer */
148 pTxEapol->keyMsg.key_info.KeyDescriptorVersion = 3;
149 } else if (nonTKIP) {
150 /* CCMP */
151 pTxEapol->keyMsg.key_info.KeyDescriptorVersion = 2;
152 } else {
153 /* TKIP OR WEP */
154 pTxEapol->keyMsg.key_info.KeyDescriptorVersion = 1;
155 }
156 }
157
158 void
ComputeEAPOL_MIC(phostsa_private priv,EAPOL_KeyMsg_t * pKeyMsg,UINT16 data_length,UINT8 * MIC_Key,UINT8 MIC_Key_length,UINT8 micKeyDescVersion)159 ComputeEAPOL_MIC(phostsa_private priv, EAPOL_KeyMsg_t *pKeyMsg,
160 UINT16 data_length,
161 UINT8 *MIC_Key, UINT8 MIC_Key_length, UINT8 micKeyDescVersion)
162 {
163 int len = data_length;
164 UINT8 *pMicData;
165
166 pMicData = (UINT8 *)pKeyMsg;
167
168 /* Allow the caller to override the algorithm used to get by some Cisco
169 ** CCX bugs where the wrong MIC algorithm is used
170 */
171 if (micKeyDescVersion == 0) {
172 /* Algorithm not specified, use proper one from key_info */
173 micKeyDescVersion = pKeyMsg->key_info.KeyDescriptorVersion;
174 }
175
176 switch (micKeyDescVersion) {
177 case 3:
178 /* AES-128-CMAC */
179 mrvl_aes_cmac(priv, MIC_Key, pMicData, len,
180 (UINT8 *)pKeyMsg->key_MIC);
181 break;
182
183 case 2:
184 /* CCMP */
185 Mrvl_hmac_sha1((t_void *)priv, &pMicData,
186 &len,
187 1,
188 MIC_Key,
189 (int)MIC_Key_length,
190 (UINT8 *)pKeyMsg->key_MIC, EAPOL_MIC_SIZE);
191 break;
192
193 default:
194 case 1:
195 /* TKIP or WEP */
196 Mrvl_hmac_md5((t_void *)priv, pMicData,
197 data_length,
198 MIC_Key,
199 (int)MIC_Key_length, (UINT8 *)pKeyMsg->key_MIC);
200 break;
201 }
202 }
203
204 /* Returns TRUE if EAPOL MIC check passes, FALSE otherwise. */
205 BOOLEAN
IsEAPOL_MICValid(phostsa_private priv,EAPOL_KeyMsg_t * pKeyMsg,UINT8 * pMICKey)206 IsEAPOL_MICValid(phostsa_private priv, EAPOL_KeyMsg_t *pKeyMsg, UINT8 *pMICKey)
207 {
208 hostsa_util_fns *util_fns = &priv->util_fns;
209 UINT8 msgMIC[EAPOL_MIC_SIZE];
210
211 /* pull the MIC */
212 memcpy(util_fns, (UINT8 *)msgMIC, (UINT8 *)pKeyMsg->key_MIC,
213 EAPOL_MIC_SIZE);
214
215 /* zero the MIC key field before calculating the data */
216 memset(util_fns, (UINT8 *)pKeyMsg->key_MIC, 0x00, EAPOL_MIC_SIZE);
217
218 ComputeEAPOL_MIC(priv, pKeyMsg, (ntohs(pKeyMsg->hdr_8021x.pckt_body_len)
219 + sizeof(pKeyMsg->hdr_8021x)),
220 pMICKey, EAPOL_MIC_KEY_SIZE, 0);
221
222 if (memcmp(util_fns, (UINT8 *)pKeyMsg->key_MIC, msgMIC, EAPOL_MIC_SIZE)) {
223 #ifdef KEYMSG_DEBUG
224 hostEventPrintf(assocAgent_getConnPtr(),
225 "EAPOL MIC Failure: cmac(%d), sha1(%d), md5(%d)",
226 (pKeyMsg->key_info.KeyDescriptorVersion == 3),
227 (pKeyMsg->key_info.KeyDescriptorVersion == 2),
228 (pKeyMsg->key_info.KeyDescriptorVersion == 1));
229 #endif
230 /* MIC Failure */
231 return FALSE;
232 }
233
234 return TRUE;
235 }
236
237 void
supplicantConstructContext(phostsa_private priv,UINT8 * pAddr1,UINT8 * pAddr2,UINT8 * pNonce1,UINT8 * pNonce2,UINT8 * pContext)238 supplicantConstructContext(phostsa_private priv, UINT8 *pAddr1,
239 UINT8 *pAddr2,
240 UINT8 *pNonce1, UINT8 *pNonce2, UINT8 *pContext)
241 {
242 hostsa_util_fns *util_fns = &priv->util_fns;
243 if (memcmp(util_fns, pAddr1, pAddr2, 6) < 0) {
244 memcpy(util_fns, pContext, pAddr1, sizeof(IEEEtypes_MacAddr_t));
245 memcpy(util_fns, (pContext + 6), pAddr2,
246 sizeof(IEEEtypes_MacAddr_t));
247 } else {
248 memcpy(util_fns, pContext, pAddr2, sizeof(IEEEtypes_MacAddr_t));
249 memcpy(util_fns, (pContext + 6), pAddr1,
250 sizeof(IEEEtypes_MacAddr_t));
251 }
252
253 if (memcmp(util_fns, pNonce1, pNonce2, NONCE_SIZE) < 0) {
254 memcpy(util_fns, pContext + 6 + 6, pNonce1, NONCE_SIZE);
255 memcpy(util_fns, pContext + 6 + 6 + NONCE_SIZE, pNonce2,
256 NONCE_SIZE);
257 } else {
258 memcpy(util_fns, pContext + 6 + 6, pNonce2, NONCE_SIZE);
259 memcpy(util_fns, pContext + 6 + 6 + NONCE_SIZE, pNonce1,
260 NONCE_SIZE);
261 }
262 }
263
264 UINT16
KeyMgmtSta_PopulateEAPOLLengthMic(phostsa_private priv,EAPOL_KeyMsg_Tx_t * pTxEapol,UINT8 * pEAPOLMICKey,UINT8 eapolProtocolVersion,UINT8 forceKeyDescVersion)265 KeyMgmtSta_PopulateEAPOLLengthMic(phostsa_private priv,
266 EAPOL_KeyMsg_Tx_t *pTxEapol,
267 UINT8 *pEAPOLMICKey,
268 UINT8 eapolProtocolVersion,
269 UINT8 forceKeyDescVersion)
270 {
271 UINT16 frameLen;
272
273 #if 0 //!defined(REMOVE_PATCH_HOOKS)
274 if (KeyMgmtSta_PopulateEAPOLLengthMic_hook(pTxEapol,
275 pEAPOLMICKey,
276 eapolProtocolVersion,
277 forceKeyDescVersion,
278 &frameLen)) {
279 return frameLen;
280 }
281 #endif
282
283 if (!pTxEapol) {
284 return 0;
285 }
286
287 frameLen = sizeof(pTxEapol->keyMsg);
288 frameLen -= sizeof(pTxEapol->keyMsg.hdr_8021x);
289 frameLen -= sizeof(pTxEapol->keyMsg.key_data);
290 frameLen += pTxEapol->keyMsg.key_material_len;
291
292 pTxEapol->keyMsg.hdr_8021x.protocol_ver = eapolProtocolVersion;
293 pTxEapol->keyMsg.hdr_8021x.pckt_type = IEEE_8021X_PACKET_TYPE_EAPOL_KEY;
294 pTxEapol->keyMsg.hdr_8021x.pckt_body_len = htons(frameLen);
295
296 pTxEapol->keyMsg.key_material_len
297 = htons(pTxEapol->keyMsg.key_material_len);
298
299 ComputeEAPOL_MIC(priv, &pTxEapol->keyMsg,
300 frameLen + sizeof(pTxEapol->keyMsg.hdr_8021x),
301 pEAPOLMICKey, EAPOL_MIC_KEY_SIZE, forceKeyDescVersion);
302
303 return frameLen;
304 }
305
306 /*
307 ** This function generates the Pairwise transient key
308 */
309 void
KeyMgmt_DerivePTK(phostsa_private priv,UINT8 * pAddr1,UINT8 * pAddr2,UINT8 * pNonce1,UINT8 * pNonce2,UINT8 * pPTK,UINT8 * pPMK,BOOLEAN use_kdf)310 KeyMgmt_DerivePTK(phostsa_private priv, UINT8 *pAddr1,
311 UINT8 *pAddr2,
312 UINT8 *pNonce1,
313 UINT8 *pNonce2, UINT8 *pPTK, UINT8 *pPMK, BOOLEAN use_kdf)
314 {
315 UINT8 *pContext;
316 char *prefix;
317
318 /* pPTK is expected to be an encryption pool buffer (at least 500 bytes).
319 **
320 ** Use the first portion for the ptk output. Use memory in the end of
321 ** the buffer for the context construction (76 bytes).
322 **
323 ** The sha256 routine assumes available memory after the context for its
324 ** own sha256 output. Space after the context (76 bytes) is required
325 ** for 2 digests (2 * 32). pContext must have at least 76 + 64 bytes
326 ** available.
327 */
328 pContext = pPTK + 200;
329
330 supplicantConstructContext(priv, pAddr1, pAddr2, pNonce1, pNonce2,
331 pContext);
332
333 prefix = "Pairwise key expansion";
334
335 if (use_kdf) {
336 mrvl_sha256_crypto_kdf((t_void *)priv, pPMK, PMK_LEN_MAX, prefix, 22, /* strlen(prefix) */
337 pContext, 76, /* sizeof constructed context */
338 pPTK, 384);
339 } else {
340 Mrvl_PRF((void *)priv, pPMK, PMK_LEN_MAX, (UINT8 *)prefix, 22, /* strlen(prefix) */
341 pContext, 76, /* sizeof constructed context */
342 pPTK, 64);
343 }
344 }
345
346 void
KeyMgmtSta_DeriveKeys(hostsa_private * priv,UINT8 * pPMK,UINT8 * da,UINT8 * sa,UINT8 * ANonce,UINT8 * SNonce,UINT8 * EAPOL_MIC_Key,UINT8 * EAPOL_Encr_Key,KeyData_t * newPWKey,BOOLEAN use_kdf)347 KeyMgmtSta_DeriveKeys(hostsa_private *priv, UINT8 *pPMK,
348 UINT8 *da,
349 UINT8 *sa,
350 UINT8 *ANonce,
351 UINT8 *SNonce,
352 UINT8 *EAPOL_MIC_Key,
353 UINT8 *EAPOL_Encr_Key,
354 KeyData_t *newPWKey, BOOLEAN use_kdf)
355 {
356 hostsa_util_fns *util_fns = &priv->util_fns;
357 // phostsa_private psapriv = (phostsa_private) priv;
358 // hostsa_util_fns *util_fns = &psapriv->util_fns;
359 //BufferDesc_t* pBufDesc = NULL;
360 UINT8 buf[500] = { 0 };
361 TkipPtk_t *pPtk;
362
363 #if 0
364 #if !defined(REMOVE_PATCH_HOOKS)
365 if (KeyMgmtSta_DeriveKeys_hook(pPMK,
366 da,
367 sa,
368 ANonce,
369 SNonce,
370 EAPOL_MIC_Key,
371 EAPOL_Encr_Key, newPWKey, use_kdf)) {
372 return;
373 }
374 #endif
375 #endif
376 if (!pPMK || !EAPOL_MIC_Key || !newPWKey) {
377 return;
378 }
379 #if 0
380 /* Wait forever ensures a buffer */
381 pBufDesc = (BufferDesc_t *) bml_AllocBuffer(ramHook_encrPoolConfig,
382 500, BML_WAIT_FOREVER);
383 pPtk = (TkipPtk_t *)BML_DATA_PTR(pBufDesc);
384 #endif
385 pPtk = (TkipPtk_t *)buf;
386
387 KeyMgmt_DerivePTK(priv, sa, da, ANonce, SNonce, (UINT8 *)pPtk, pPMK,
388 use_kdf);
389
390 memcpy(util_fns, EAPOL_MIC_Key, pPtk->kck, sizeof(pPtk->kck));
391 memcpy(util_fns, EAPOL_Encr_Key, pPtk->kek, sizeof(pPtk->kek));
392 memcpy(util_fns, newPWKey->Key, pPtk->tk, sizeof(pPtk->tk));
393
394 memcpy(util_fns, newPWKey->RxMICKey,
395 pPtk->rxMicKey, sizeof(pPtk->rxMicKey));
396
397 memcpy(util_fns, newPWKey->TxMICKey,
398 pPtk->txMicKey, sizeof(pPtk->txMicKey));
399
400 // bml_FreeBuffer((UINT32)pBufDesc);
401 }
402
403 void
UpdateEAPOLWcbLenAndTransmit(hostsa_private * priv,pmlan_buffer pmbuf,UINT16 frameLen)404 UpdateEAPOLWcbLenAndTransmit(hostsa_private *priv, pmlan_buffer pmbuf,
405 UINT16 frameLen)
406 {
407 hostsa_mlan_fns *pm_fns = &priv->mlan_fns;
408
409 pm_fns->hostsa_tx_packet(priv->pmlan_private, pmbuf, frameLen);
410 }
411
412 void
formEAPOLEthHdr(phostsa_private priv,EAPOL_KeyMsg_Tx_t * pTxEapol,t_u8 * da,t_u8 * sa)413 formEAPOLEthHdr(phostsa_private priv, EAPOL_KeyMsg_Tx_t *pTxEapol,
414 t_u8 *da, t_u8 *sa)
415 {
416 hostsa_util_fns *util_fns = &priv->util_fns;
417 memcpy(util_fns, (void *)pTxEapol->ethHdr.da, da,
418 IEEEtypes_ADDRESS_SIZE);
419 memcpy(util_fns, (void *)pTxEapol->ethHdr.sa, sa,
420 IEEEtypes_ADDRESS_SIZE);
421 pTxEapol->ethHdr.type = 0x8E88;
422 }
423
424 void
supplicantParseWpaIe(phostsa_private priv,IEEEtypes_WPAElement_t * pIe,SecurityMode_t * pWpaType,Cipher_t * pMcstCipher,Cipher_t * pUcstCipher,AkmSuite_t * pAkmList,UINT8 akmOutMax)425 supplicantParseWpaIe(phostsa_private priv, IEEEtypes_WPAElement_t *pIe,
426 SecurityMode_t *pWpaType,
427 Cipher_t *pMcstCipher,
428 Cipher_t *pUcstCipher,
429 AkmSuite_t *pAkmList, UINT8 akmOutMax)
430 {
431 hostsa_util_fns *util_fns = &priv->util_fns;
432 IEEEtypes_WPAElement_t *pTemp = pIe;
433 int count;
434 int akmCount = akmOutMax;
435 AkmSuite_t *pAkm = pAkmList;
436
437 memset(util_fns, pMcstCipher, 0x00, sizeof(Cipher_t));
438 memset(util_fns, pUcstCipher, 0x00, sizeof(Cipher_t));
439 memset(util_fns, pAkmList, 0x00, akmOutMax * sizeof(AkmSuite_t));
440 memset(util_fns, pWpaType, 0x00, sizeof(SecurityMode_t));
441
442 pWpaType->wpa = 1;
443
444 /* record the AP's multicast cipher */
445 if (!memcmp
446 (util_fns, (char *)pTemp->GrpKeyCipher, wpa_oui02,
447 sizeof(wpa_oui02))) {
448 /* WPA TKIP */
449 pMcstCipher->tkip = 1;
450 } else if (!memcmp
451 (util_fns, (char *)pTemp->GrpKeyCipher, wpa_oui04,
452 sizeof(wpa_oui04))) {
453 /* WPA AES */
454 pMcstCipher->ccmp = 1;
455 } else if (!memcmp
456 (util_fns, (char *)pTemp->GrpKeyCipher, wpa_oui01,
457 sizeof(wpa_oui01))) {
458 /* WPA WEP 40 */
459 pMcstCipher->wep40 = 1;
460 } else if (!memcmp
461 (util_fns, (char *)pTemp->GrpKeyCipher, wpa_oui05,
462 sizeof(wpa_oui05))) {
463 /* WPA WEP 104 */
464 pMcstCipher->wep104 = 1;
465 }
466
467 count = wlan_le16_to_cpu(pTemp->PwsKeyCnt);
468
469 while (count) {
470 /* record the AP's unicast cipher */
471 if (!memcmp(util_fns, (char *)pTemp->PwsKeyCipherList,
472 wpa_oui02, sizeof(wpa_oui02))) {
473 /* WPA TKIP */
474 pUcstCipher->tkip = 1;
475 } else if (!memcmp(util_fns, (char *)pTemp->PwsKeyCipherList,
476 wpa_oui04, sizeof(wpa_oui04))) {
477 /* WPA AES */
478 pUcstCipher->ccmp = 1;
479 }
480 count--;
481
482 if (count) {
483 pTemp = (IEEEtypes_WPAElement_t *)((UINT8 *)pTemp +
484 sizeof(pTemp->
485 PwsKeyCipherList));
486 }
487 }
488
489 count = wlan_le16_to_cpu(pTemp->AuthKeyCnt);
490
491 while (count) {
492 if (akmCount) {
493 /* Store the AKM */
494 memcpy(util_fns, pAkm,
495 (char *)pTemp->AuthKeyList,
496 sizeof(pTemp->AuthKeyList));
497 pAkm++;
498 akmCount--;
499 }
500
501 count--;
502
503 if (count) {
504 pTemp = (IEEEtypes_WPAElement_t *)((UINT8 *)pTemp
505 +
506 sizeof(pTemp->
507 AuthKeyList));
508 }
509 }
510
511 if (!memcmp(util_fns, pAkmList, wpa_oui_none, sizeof(wpa_oui_none))) {
512 pWpaType->wpaNone = 1;
513 }
514 }
515
516 void
supplicantParseMcstCipher(phostsa_private priv,Cipher_t * pMcstCipherOut,UINT8 * pGrpKeyCipher)517 supplicantParseMcstCipher(phostsa_private priv, Cipher_t *pMcstCipherOut,
518 UINT8 *pGrpKeyCipher)
519 {
520 hostsa_util_fns *util_fns = &priv->util_fns;
521 memset(util_fns, pMcstCipherOut, 0x00, sizeof(Cipher_t));
522
523 /* record the AP's multicast cipher */
524 if (!memcmp(util_fns, pGrpKeyCipher, wpa2_oui02, sizeof(wpa2_oui02))) {
525 /* WPA2 TKIP */
526 pMcstCipherOut->tkip = 1;
527 } else if (!memcmp
528 (util_fns, pGrpKeyCipher, wpa2_oui04, sizeof(wpa2_oui04))) {
529 /* WPA2 AES */
530 pMcstCipherOut->ccmp = 1;
531 } else if (!memcmp
532 (util_fns, pGrpKeyCipher, wpa2_oui01, sizeof(wpa2_oui01))) {
533 /* WPA2 WEP 40 */
534 pMcstCipherOut->wep40 = 1;
535 } else if (!memcmp
536 (util_fns, pGrpKeyCipher, wpa2_oui05, sizeof(wpa2_oui05))) {
537 /* WPA2 WEP 104 */
538 pMcstCipherOut->wep104 = 1;
539 }
540 }
541
542 void
supplicantParseUcstCipher(phostsa_private priv,Cipher_t * pUcstCipherOut,UINT8 pwsKeyCnt,UINT8 * pPwsKeyCipherList)543 supplicantParseUcstCipher(phostsa_private priv, Cipher_t *pUcstCipherOut,
544 UINT8 pwsKeyCnt, UINT8 *pPwsKeyCipherList)
545 {
546 hostsa_util_fns *util_fns = &priv->util_fns;
547 UINT8 count;
548
549 memset(util_fns, pUcstCipherOut, 0x00, sizeof(Cipher_t));
550
551 /* Cycle through the PwsKeyCipherList and record each unicast cipher */
552 for (count = 0; count < pwsKeyCnt; count++) {
553 /* record the AP's unicast cipher */
554 if (!memcmp(util_fns, pPwsKeyCipherList + (count * 4),
555 wpa2_oui02, sizeof(wpa2_oui02))) {
556 /* WPA2 TKIP */
557 pUcstCipherOut->tkip = 1;
558 } else if (!memcmp(util_fns, pPwsKeyCipherList + (count * 4),
559 wpa2_oui04, sizeof(wpa2_oui04))) {
560 /* WPA2 AES */
561 pUcstCipherOut->ccmp = 1;
562 }
563 }
564 }
565
566 void
supplicantParseRsnIe(phostsa_private priv,IEEEtypes_RSNElement_t * pRsnIe,SecurityMode_t * pWpaTypeOut,Cipher_t * pMcstCipherOut,Cipher_t * pUcstCipherOut,AkmSuite_t * pAkmListOut,UINT8 akmOutMax,IEEEtypes_RSNCapability_t * pRsnCapOut,Cipher_t * pGrpMgmtCipherOut)567 supplicantParseRsnIe(phostsa_private priv, IEEEtypes_RSNElement_t *pRsnIe,
568 SecurityMode_t *pWpaTypeOut,
569 Cipher_t *pMcstCipherOut,
570 Cipher_t *pUcstCipherOut,
571 AkmSuite_t *pAkmListOut,
572 UINT8 akmOutMax,
573 IEEEtypes_RSNCapability_t *pRsnCapOut,
574 Cipher_t *pGrpMgmtCipherOut)
575 {
576 hostsa_util_fns *util_fns = &priv->util_fns;
577 UINT8 *pIeData;
578 UINT8 *pIeEnd;
579 UINT8 *pGrpKeyCipher;
580 UINT16 pwsKeyCnt;
581 UINT8 *pPwsKeyCipherList;
582 UINT16 authKeyCnt;
583 UINT8 *pAuthKeyList;
584
585 IEEEtypes_RSNCapability_t *pRsnCap;
586
587 UINT16 *pPMKIDCnt;
588 UINT16 PMKIDCnt;
589
590 UINT8 *pGrpMgmtCipher;
591 #if 0
592 #if !defined(REMOVE_PATCH_HOOKS)
593 if (supplicantParseRsnIe_hook(pRsnIe,
594 pWpaTypeOut,
595 pMcstCipherOut,
596 pUcstCipherOut,
597 pAkmListOut,
598 akmOutMax,
599 pRsnCapOut, pGrpMgmtCipherOut)) {
600 return;
601 }
602 #endif
603 #endif
604 memset(util_fns, pWpaTypeOut, 0x00, sizeof(SecurityMode_t));
605
606 pWpaTypeOut->wpa2 = 1;
607
608 /* Set the start and end of the IE data */
609 pIeData = (UINT8 *)&pRsnIe->Ver;
610 pIeEnd = pIeData + pRsnIe->Len;
611
612 /* Skip past the version field */
613 pIeData += sizeof(pRsnIe->Ver);
614
615 /* Parse the group key cipher list */
616 pGrpKeyCipher = pIeData;
617 pIeData += sizeof(pRsnIe->GrpKeyCipher);
618 supplicantParseMcstCipher(priv, pMcstCipherOut, pGrpKeyCipher);
619
620 /* Parse the pairwise key cipher list */
621 pwsKeyCnt = wlan_le16_to_cpu(*(UINT16 *)pIeData);
622 pIeData += sizeof(pRsnIe->PwsKeyCnt);
623
624 pPwsKeyCipherList = pIeData;
625 pIeData += pwsKeyCnt * sizeof(pRsnIe->PwsKeyCipherList);
626 supplicantParseUcstCipher(priv, pUcstCipherOut, pwsKeyCnt,
627 pPwsKeyCipherList);
628
629 /* Parse and return the AKM list */
630 authKeyCnt = wlan_le16_to_cpu(*(UINT16 *)pIeData);
631 pIeData += sizeof(pRsnIe->AuthKeyCnt);
632
633 pAuthKeyList = pIeData;
634 pIeData += authKeyCnt * sizeof(pRsnIe->AuthKeyList);
635 memset(util_fns, pAkmListOut, 0x00, akmOutMax * sizeof(AkmSuite_t));
636 memcpy(util_fns, pAkmListOut,
637 pAuthKeyList,
638 MIN(authKeyCnt, akmOutMax) * sizeof(pRsnIe->AuthKeyList));
639
640 DBG_HEXDUMP(MCMD_D, " pAuthKeyList",
641 (t_u8 *)pAuthKeyList, MIN(authKeyCnt,
642 akmOutMax) *
643 sizeof(pRsnIe->AuthKeyList));
644 DBG_HEXDUMP(MCMD_D, " pAuthKeyList", (t_u8 *)pAkmListOut,
645 MIN(authKeyCnt, akmOutMax) * sizeof(pRsnIe->AuthKeyList));
646 /* Check if the RSN Capability is included */
647 if (pIeData < pIeEnd) {
648 pRsnCap = (IEEEtypes_RSNCapability_t *)pIeData;
649 pIeData += sizeof(pRsnIe->RsnCap);
650
651 if (pRsnCapOut) {
652 memcpy(util_fns, pRsnCapOut, pRsnCap,
653 sizeof(IEEEtypes_RSNCapability_t));
654 }
655 }
656
657 /* Check if the PMKID count is included */
658 if (pIeData < pIeEnd) {
659 pPMKIDCnt = (UINT16 *)pIeData;
660 PMKIDCnt = wlan_le16_to_cpu(*pPMKIDCnt);
661 pIeData += sizeof(pRsnIe->PMKIDCnt);
662
663 /* Check if the PMKID List is included */
664 if (pIeData < pIeEnd) {
665 /* pPMKIDList = pIeData; <-- Currently not used in parsing */
666 pIeData += PMKIDCnt * sizeof(pRsnIe->PMKIDList);
667 }
668 }
669
670 /* Check if the Group Mgmt Cipher is included */
671 if (pIeData < pIeEnd) {
672 pGrpMgmtCipher = pIeData;
673
674 if (pGrpMgmtCipherOut) {
675 memcpy(util_fns, pGrpMgmtCipherOut,
676 pGrpMgmtCipher, sizeof(pRsnIe->GrpMgmtCipher));
677 }
678 }
679 }
680