xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/mvl88w8977/mlan/esa/keyMgmtApStaCommon.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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