xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/mvl88w8977/mlan/esa/keyMgmtAp_rom.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /** @file keyMgmtAp_rom.c
2  *
3  *  @brief This file defines api for key managment
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 UINT32
util_FindLowestBitSet(UINT32 val)44 util_FindLowestBitSet(UINT32 val)
45 {
46 	UINT32 bitmap = 1;
47 
48 	while (bitmap && (!(bitmap & val))) {
49 		bitmap <<= 1;
50 	}
51 
52 	return bitmap;
53 }
54 
55 UINT8
convertMrvlAuthToIEEEAuth(UINT32 mrvlauth)56 convertMrvlAuthToIEEEAuth(UINT32 mrvlauth)
57 {
58 	UINT8 auth;
59 
60 	switch (mrvlauth) {
61 	case UAP_HOSTCMD_KEYMGMT_EAP:
62 		auth = IEEEtypes_RSN_AUTH_KEY_SUITE_8021X;
63 		break;
64 	case UAP_HOSTCMD_KEYMGMT_PSK:
65 		auth = IEEEtypes_RSN_AUTH_KEY_SUITE_PSK;
66 		break;
67 	case UAP_HOSTCMD_KEYMGMT_NONE:
68 	default:
69 		auth = IEEEtypes_RSN_AUTH_KEY_SUITE_RSVD;
70 		break;
71 	}
72 	return auth;
73 }
74 
75 UINT32
convertIEEEAuthToMrvlAuth(UINT8 auth)76 convertIEEEAuthToMrvlAuth(UINT8 auth)
77 {
78 	UINT32 MrvlAuth = 0;
79 	switch (auth) {
80 	case IEEEtypes_RSN_AUTH_KEY_SUITE_8021X:
81 		MrvlAuth |= UAP_HOSTCMD_KEYMGMT_EAP;
82 		break;
83 	case IEEEtypes_RSN_AUTH_KEY_SUITE_PSK:
84 		MrvlAuth |= UAP_HOSTCMD_KEYMGMT_PSK;
85 		break;
86 	case IEEEtypes_RSN_AUTH_KEY_SUITE_RSVD:
87 	default:
88 		MrvlAuth = 0;
89 		break;
90 	}
91 	return MrvlAuth;
92 }
93 
94 UINT8
convertMrvlCipherToIEEECipher(UINT8 mrvlcipher)95 convertMrvlCipherToIEEECipher(UINT8 mrvlcipher)
96 {
97 	UINT8 Cipher;
98 	switch (mrvlcipher) {
99 	case UAP_HOSTCMD_CIPHER_WEP40:
100 		Cipher = IEEEtypes_RSN_CIPHER_SUITE_WEP40;
101 		break;
102 	case UAP_HOSTCMD_CIPHER_WEP104:
103 		Cipher = IEEEtypes_RSN_CIPHER_SUITE_WEP104;
104 		break;
105 	case UAP_HOSTCMD_CIPHER_TKIP:
106 		Cipher = IEEEtypes_RSN_CIPHER_SUITE_TKIP;
107 		break;
108 	case UAP_HOSTCMD_CIPHER_CCMP:
109 		Cipher = IEEEtypes_RSN_CIPHER_SUITE_CCMP;
110 		break;
111 	default:
112 		Cipher = IEEEtypes_RSN_CIPHER_SUITE_NONE;
113 		break;
114 	}
115 	return Cipher;
116 }
117 
118 UINT32
convertIEEECipherToMrvlCipher(UINT8 cipher)119 convertIEEECipherToMrvlCipher(UINT8 cipher)
120 {
121 	UINT32 MrvlCipher = 0;
122 	switch (cipher) {
123 	case IEEEtypes_RSN_CIPHER_SUITE_WEP40:
124 		MrvlCipher |= UAP_HOSTCMD_CIPHER_WEP40;
125 		break;
126 	case IEEEtypes_RSN_CIPHER_SUITE_TKIP:
127 		MrvlCipher |= UAP_HOSTCMD_CIPHER_TKIP;
128 		break;
129 	case IEEEtypes_RSN_CIPHER_SUITE_CCMP:
130 		MrvlCipher |= UAP_HOSTCMD_CIPHER_CCMP;
131 		break;
132 	case IEEEtypes_RSN_CIPHER_SUITE_WEP104:
133 		MrvlCipher |= UAP_HOSTCMD_CIPHER_WEP104;
134 		break;
135 	case IEEEtypes_RSN_CIPHER_SUITE_NONE:
136 	case IEEEtypes_RSN_CIPHER_SUITE_WRAP:
137 	default:
138 		MrvlCipher = 0;
139 		break;
140 	}
141 	return MrvlCipher;
142 }
143 
144 void
GenerateGTK_internal(hostsa_private * priv,KeyData_t * grpKeyData,UINT8 * nonce,UINT8 * StaMacAddr)145 GenerateGTK_internal(hostsa_private *priv, KeyData_t *grpKeyData,
146 		     UINT8 *nonce, UINT8 *StaMacAddr)
147 {
148 	hostsa_util_fns *util_fns = &priv->util_fns;
149 	UINT8 inp_data[NONCE_SIZE + sizeof(IEEEtypes_MacAddr_t)];
150 	UINT8 prefix[] = "Group key expansion";
151 	UINT8 GTK[32];		//group transient key
152 	UINT8 grpMasterKey[32];
153 
154 	if (!grpKeyData || !nonce) {
155 		return;
156 	}
157 
158 	memcpy(util_fns, inp_data, StaMacAddr, sizeof(IEEEtypes_MacAddr_t));
159 	supplicantGenerateRand(priv, nonce, NONCE_SIZE);
160 	memcpy(util_fns, inp_data + sizeof(IEEEtypes_MacAddr_t), nonce,
161 	       NONCE_SIZE);
162 	supplicantGenerateRand(priv, grpMasterKey, sizeof(grpMasterKey));
163 	Mrvl_PRF((void *)priv, grpMasterKey,
164 		 sizeof(grpMasterKey),
165 		 prefix,
166 		 wlan_strlen((char *)prefix),
167 		 inp_data, sizeof(inp_data), GTK, sizeof(GTK));
168 	memcpy(util_fns, grpKeyData->Key, GTK, TK_SIZE);
169 	memcpy(util_fns, grpKeyData->TxMICKey, GTK + TK_SIZE, MIC_KEY_SIZE);
170 	memcpy(util_fns, grpKeyData->RxMICKey, GTK + TK_SIZE + MIC_KEY_SIZE,
171 	       MIC_KEY_SIZE);
172 
173 }
174 
175 /*
176     Populates EAPOL frame based on Cipher, given Nonce, replay counters,
177     and type, which encodes whether this is secure, part of WPA2 or WPA
178     handshake.
179     This is currently used for EAPOL sent from AP, msg1, msg3 and group
180     key msg.
181 */
182 void
PopulateKeyMsg(hostsa_private * priv,EAPOL_KeyMsg_Tx_t * tx_eapol_ptr,Cipher_t * Cipher,UINT16 Type,UINT32 replay_cnt[2],UINT8 * Nonce)183 PopulateKeyMsg(hostsa_private *priv, EAPOL_KeyMsg_Tx_t *tx_eapol_ptr,
184 	       Cipher_t *Cipher,
185 	       UINT16 Type, UINT32 replay_cnt[2], UINT8 *Nonce)
186 {
187 	hostsa_util_fns *util_fns = &priv->util_fns;
188 	key_info_t *pKeyInfo;
189 
190 	if (!tx_eapol_ptr || !Cipher) {
191 		return;
192 	}
193 
194 	pKeyInfo = &tx_eapol_ptr->keyMsg.key_info;
195 
196 	if (Cipher->tkip) {
197 		//TKIP unicast
198 		tx_eapol_ptr->keyMsg.key_length =
199 			SHORT_SWAP((TK_SIZE + TK_SIZE));
200 	} else if (Cipher->ccmp) {
201 		//CCMP unicast
202 		tx_eapol_ptr->keyMsg.key_length = SHORT_SWAP(TK_SIZE);
203 	}
204 
205 	pKeyInfo->KeyAck = 1;
206 
207 	if (Type & PAIRWISE_KEY_MSG) {
208 		pKeyInfo->KeyType = 1;
209 		if (Type & SECURE_HANDSHAKE_FLAG) {
210 			pKeyInfo->KeyMIC = 1;
211 			pKeyInfo->Install = 1;
212 			pKeyInfo->EncryptedKeyData = pKeyInfo->Secure =
213 				(Type & WPA2_HANDSHAKE) ? 1 : 0;
214 		}
215 	} else {
216 		pKeyInfo->Secure = 1;
217 		pKeyInfo->KeyMIC = 1;
218 		pKeyInfo->EncryptedKeyData = (Type & WPA2_HANDSHAKE) ? 1 : 0;
219 	}
220 
221 	tx_eapol_ptr->keyMsg.replay_cnt[0] = WORD_SWAP(replay_cnt[0]);
222 	tx_eapol_ptr->keyMsg.replay_cnt[1] = WORD_SWAP(replay_cnt[1]);
223 	memcpy(util_fns, (void *)tx_eapol_ptr->keyMsg.key_nonce, Nonce,
224 	       NONCE_SIZE);
225 
226 	DBG_HEXDUMP(MCMD_D, " nonce ",
227 		    (t_u8 *)tx_eapol_ptr->keyMsg.key_nonce, NONCE_SIZE);
228 }
229 
230 /*
231     Function to prepare KDE in EAPOL frame .
232     Used by the AP to encapsulate GTK
233 */
234 
235 void
prepareKDE(hostsa_private * priv,EAPOL_KeyMsg_Tx_t * tx_eapol_ptr,KeyData_t * grKey,Cipher_t * cipher)236 prepareKDE(hostsa_private *priv, EAPOL_KeyMsg_Tx_t *tx_eapol_ptr,
237 	   KeyData_t *grKey, Cipher_t *cipher)
238 {
239 	hostsa_util_fns *util_fns = &priv->util_fns;
240 	KDE_t *pKeyDataWPA2;
241 	GTK_KDE_t *pGTK_IE;
242 	UINT8 RsnIE_len = 0, PadLen = 0;
243 	UINT8 *buf_p;
244 
245 	if (!tx_eapol_ptr || !grKey || !cipher) {
246 		return;
247 	}
248 
249 	RsnIE_len = tx_eapol_ptr->keyMsg.key_material_len;
250 	buf_p = (UINT8 *)(tx_eapol_ptr->keyMsg.key_data + RsnIE_len);
251 
252 	pKeyDataWPA2 = (KDE_t *)buf_p;
253 	pKeyDataWPA2->type = 0xdd;
254 	pKeyDataWPA2->length = KEYDATA_SIZE;
255 	pKeyDataWPA2->OUI[0] = kde_oui[0];
256 	pKeyDataWPA2->OUI[1] = kde_oui[1];
257 	pKeyDataWPA2->OUI[2] = kde_oui[2];
258 	pKeyDataWPA2->dataType = 1;
259 	buf_p = buf_p + KDE_SIZE;
260 
261 	pGTK_IE = (GTK_KDE_t *)buf_p;
262 	pGTK_IE->KeyID = 1;
263 	buf_p = buf_p + GTK_IE_SIZE;
264 
265 	// copy over GTK
266 	memcpy(util_fns, (void *)buf_p, (void *)grKey->Key, TK_SIZE);
267 	buf_p = buf_p + TK_SIZE;
268 
269 	if (cipher->tkip) {
270 		pKeyDataWPA2->length += (MIC_KEY_SIZE + MIC_KEY_SIZE);
271 		memcpy(util_fns, (void *)buf_p, (void *)grKey->TxMICKey,
272 		       MIC_KEY_SIZE);
273 		buf_p = buf_p + MIC_KEY_SIZE;
274 		memcpy(util_fns, (void *)buf_p, (void *)grKey->RxMICKey,
275 		       MIC_KEY_SIZE);
276 		buf_p = buf_p + MIC_KEY_SIZE;
277 	}
278 
279 	tx_eapol_ptr->keyMsg.key_material_len += (pKeyDataWPA2->length
280 						  + KDE_IE_SIZE);
281 
282 	PadLen = ((8 - ((tx_eapol_ptr->keyMsg.key_material_len) % 8)) % 8);
283 	if (PadLen) {
284 		*(buf_p) = 0xdd;
285 		memset(util_fns, (void *)(buf_p + 1), 0, PadLen - 1);
286 		tx_eapol_ptr->keyMsg.key_material_len += PadLen;
287 	}
288 
289 }
290 
291 BOOLEAN
Encrypt_keyData(hostsa_private * priv,EAPOL_KeyMsg_Tx_t * tx_eapol_ptr,UINT8 * EAPOL_Encr_Key,Cipher_t * cipher)292 Encrypt_keyData(hostsa_private *priv, EAPOL_KeyMsg_Tx_t *tx_eapol_ptr,
293 		UINT8 *EAPOL_Encr_Key, Cipher_t *cipher)
294 {
295 	hostsa_util_fns *util_fns = &priv->util_fns;
296 	UINT8 key[16];
297 	UINT8 cipherText[400] = { 0 };
298 
299 	if (!tx_eapol_ptr || !EAPOL_Encr_Key || !cipher) {
300 		return FALSE;
301 	}
302 
303 	if (cipher->ccmp) {
304 		// Pairwise is CCMP
305 		memcpy(util_fns, (void *)key, EAPOL_Encr_Key, 16);
306 
307 		// use AES-only mode from AEU HW to perform AES wrap
308 		MRVL_AesWrap(key, 2, tx_eapol_ptr->keyMsg.key_material_len / 8,
309 			     tx_eapol_ptr->keyMsg.key_data, NULL, cipherText);
310 
311 		tx_eapol_ptr->keyMsg.key_material_len += 8;
312 		memcpy(util_fns, (void *)tx_eapol_ptr->keyMsg.key_data,
313 		       cipherText, tx_eapol_ptr->keyMsg.key_material_len);
314 	} else if (cipher->tkip) {
315 		// Pairwise is TKIP
316 		supplicantGenerateRand(priv,
317 				       (UINT8 *)tx_eapol_ptr->keyMsg.
318 				       EAPOL_key_IV, 16);
319 		RC4_Encrypt((t_void *)priv, (unsigned char *)EAPOL_Encr_Key,
320 			    (unsigned char *)&tx_eapol_ptr->keyMsg.EAPOL_key_IV,
321 			    16, (unsigned char *)&tx_eapol_ptr->keyMsg.key_data,
322 			    (unsigned short)tx_eapol_ptr->keyMsg.
323 			    key_material_len, 256);
324 	} else {
325 		return FALSE;
326 	}
327 
328 	return TRUE;
329 }
330 
331 void
KeyMgmtAp_DerivePTK(hostsa_private * priv,UINT8 * pPMK,t_u8 * da,t_u8 * sa,UINT8 * ANonce,UINT8 * SNonce,UINT8 * EAPOL_MIC_Key,UINT8 * EAPOL_Encr_Key,KeyData_t * newPWKey,BOOLEAN use_kdf)332 KeyMgmtAp_DerivePTK(hostsa_private *priv,
333 		    UINT8 *pPMK,
334 		    t_u8 *da,
335 		    t_u8 *sa,
336 		    UINT8 *ANonce,
337 		    UINT8 *SNonce,
338 		    UINT8 *EAPOL_MIC_Key,
339 		    UINT8 *EAPOL_Encr_Key, KeyData_t *newPWKey, BOOLEAN use_kdf)
340 {
341 	hostsa_util_fns *util_fns = &priv->util_fns;
342 	UINT8 tmp[MIC_KEY_SIZE];
343 
344 	// call STA PTK generation funciton first
345 	KeyMgmtSta_DeriveKeys(priv, pPMK,
346 			      da,
347 			      sa,
348 			      ANonce,
349 			      SNonce,
350 			      EAPOL_MIC_Key, EAPOL_Encr_Key, newPWKey, use_kdf);
351 
352 	// We need to swap Rx/Tx Keys for AP
353 
354 	memcpy(util_fns, tmp, newPWKey->RxMICKey, MIC_KEY_SIZE);
355 	memcpy(util_fns, newPWKey->RxMICKey, newPWKey->TxMICKey, MIC_KEY_SIZE);
356 	memcpy(util_fns, newPWKey->TxMICKey, tmp, MIC_KEY_SIZE);
357 
358 }
359 
360 BOOLEAN
KeyData_CopyWPAWP2(hostsa_private * priv,EAPOL_KeyMsg_Tx_t * pTxEAPOL,void * pIe)361 KeyData_CopyWPAWP2(hostsa_private *priv, EAPOL_KeyMsg_Tx_t *pTxEAPOL, void *pIe)
362 {
363 	hostsa_util_fns *util_fns = &priv->util_fns;
364 	IEEEtypes_InfoElementHdr_t *pElement =
365 		(IEEEtypes_InfoElementHdr_t *)pIe;
366 
367 	if (!pIe) {
368 		return FALSE;
369 	}
370 
371 	pTxEAPOL->keyMsg.key_material_len =
372 		pElement->Len + sizeof(IEEEtypes_InfoElementHdr_t);
373 
374 	memcpy(util_fns, (void *)pTxEAPOL->keyMsg.key_data,
375 	       pIe, pTxEAPOL->keyMsg.key_material_len);
376 
377 	return TRUE;
378 }
379 
380 BOOLEAN
KeyData_UpdateKeyMaterial(hostsa_private * priv,EAPOL_KeyMsg_Tx_t * pTxEAPOL,SecurityMode_t * pSecType,void * pWPA,void * pWPA2)381 KeyData_UpdateKeyMaterial(hostsa_private *priv, EAPOL_KeyMsg_Tx_t *pTxEAPOL,
382 			  SecurityMode_t *pSecType, void *pWPA, void *pWPA2)
383 {
384 
385 	if (pSecType->wpa || pSecType->wpaNone) {
386 		if (KeyData_CopyWPAWP2(priv, pTxEAPOL, pWPA) == FALSE) {
387 			return FALSE;
388 		}
389 	} else if (pSecType->wpa2) {
390 		if (KeyData_CopyWPAWP2(priv, pTxEAPOL, pWPA2) == FALSE) {
391 			return FALSE;
392 		}
393 	}
394 
395 	return TRUE;
396 }
397 
398 void
KeyData_AddGTK(hostsa_private * priv,EAPOL_KeyMsg_Tx_t * pTxEAPOL,KeyData_t * grKey,Cipher_t * cipher)399 KeyData_AddGTK(hostsa_private *priv, EAPOL_KeyMsg_Tx_t *pTxEAPOL,
400 	       KeyData_t *grKey, Cipher_t *cipher)
401 {
402 	hostsa_util_fns *util_fns = &priv->util_fns;
403 	UINT8 *buf_p;
404 	buf_p = (UINT8 *)pTxEAPOL->keyMsg.key_data;
405 	memcpy(util_fns, (void *)buf_p, (void *)grKey, TK_SIZE);
406 
407 	buf_p = buf_p + TK_SIZE;
408 
409 	pTxEAPOL->keyMsg.key_material_len += TK_SIZE;
410 
411 	if (cipher->tkip) {
412 		memcpy(util_fns, (void *)buf_p, (void *)grKey->TxMICKey,
413 		       MIC_KEY_SIZE);
414 		buf_p = buf_p + MIC_KEY_SIZE;
415 		memcpy(util_fns, (void *)buf_p, (void *)grKey->RxMICKey,
416 		       MIC_KEY_SIZE);
417 		pTxEAPOL->keyMsg.key_material_len += (MIC_KEY_SIZE +
418 						      MIC_KEY_SIZE);
419 	}
420 }
421 
422 /* Returns FALSE if security type is other than WPA* */
423 BOOLEAN
KeyData_AddKey(hostsa_private * priv,EAPOL_KeyMsg_Tx_t * pTxEAPOL,SecurityMode_t * pSecType,KeyData_t * grKey,Cipher_t * cipher)424 KeyData_AddKey(hostsa_private *priv, EAPOL_KeyMsg_Tx_t *pTxEAPOL,
425 	       SecurityMode_t *pSecType, KeyData_t *grKey, Cipher_t *cipher)
426 {
427 	hostsa_util_fns *util_fns = &priv->util_fns;
428 	BOOLEAN status = FALSE;
429 
430 	pTxEAPOL->keyMsg.key_info.KeyIndex = grKey->KeyIndex;
431 
432 	pTxEAPOL->keyMsg.key_RSC[0] = grKey->TxIV16 & 0x00FF;
433 	pTxEAPOL->keyMsg.key_RSC[1] = (grKey->TxIV16 >> 8) & 0x00FF;
434 	memcpy(util_fns, (void *)(pTxEAPOL->keyMsg.key_RSC + 2),
435 	       &grKey->TxIV32, 4);
436 
437 	if (pSecType->wpa || pSecType->wpaNone) {
438 		KeyData_AddGTK(priv, pTxEAPOL, grKey, cipher);
439 		status = TRUE;
440 	} else if (pSecType->wpa2) {
441 		prepareKDE(priv, pTxEAPOL, grKey, cipher);
442 		status = TRUE;
443 	}
444 	return status;
445 }
446 
447 void
ROM_InitGTK(hostsa_private * priv,KeyData_t * grpKeyData,UINT8 * nonce,UINT8 * StaMacAddr)448 ROM_InitGTK(hostsa_private *priv, KeyData_t *grpKeyData, UINT8 *nonce,
449 	    UINT8 *StaMacAddr)
450 {
451 	grpKeyData->KeyIndex = 1;
452 	grpKeyData->TxIV16 = 1;
453 	grpKeyData->TxIV32 = 0;
454 
455 	GenerateGTK_internal(priv, grpKeyData, nonce, StaMacAddr);
456 }
457 
458 t_u16
keyMgmtAp_FormatWPARSN_IE_internal(phostsa_private priv,IEEEtypes_InfoElementHdr_t * pIe,UINT8 isRsn,Cipher_t * pCipher,UINT8 cipherCnt,Cipher_t * pMcastCipher,UINT16 authKey,UINT16 authKeyCnt)459 keyMgmtAp_FormatWPARSN_IE_internal(phostsa_private priv,
460 				   IEEEtypes_InfoElementHdr_t *pIe,
461 				   UINT8 isRsn,
462 				   Cipher_t *pCipher,
463 				   UINT8 cipherCnt,
464 				   Cipher_t *pMcastCipher,
465 				   UINT16 authKey, UINT16 authKeyCnt)
466 {
467 	phostsa_util_fns util_fns = &priv->util_fns;
468 	int i;
469 	UINT8 *pBuf = NULL;
470 	IEEEtypes_RSNElement_t *pRsn = (IEEEtypes_RSNElement_t *)pIe;
471 	IEEEtypes_WPAElement_t *pWpa = (IEEEtypes_WPAElement_t *)pIe;
472 
473 	UINT16 bitPos = 0;
474 	UINT16 authKeyBitmap = authKey;
475 	UINT8 ucastBitmap = *((UINT8 *)pCipher);
476 	UINT8 mcastBitmap = *((UINT8 *)pMcastCipher);
477 	UINT8 oui[3];
478 	UINT16 ieLength = 0;
479 
480 	pIe->ElementId = (isRsn == 1) ? ELEM_ID_RSN : ELEM_ID_VENDOR_SPECIFIC;
481 
482 	if (isRsn) {
483 		memcpy(util_fns, (void *)&oui, (void *)&kde_oui, sizeof(oui));
484 		pBuf = (UINT8 *)&pRsn->Ver;
485 	} else {
486 		memcpy(util_fns, (void *)&oui, (void *)&wpa_oui01, sizeof(oui));
487 		memcpy(util_fns, (void *)&pWpa->OuiType, (void *)&wpa_oui01,
488 		       sizeof(wpa_oui01));
489 		pBuf = (UINT8 *)&pWpa->Ver;
490 	}
491 
492 	pBuf[0] = 0x1;
493 	pBuf[1] = 0x0;
494 	pBuf += 2;
495 
496 	//filling group cipher
497 	memcpy(util_fns, (void *)pBuf, (void *)&oui, sizeof(oui));
498 
499 	if (mcastBitmap) {
500 		bitPos = util_FindLowestBitSet(mcastBitmap);
501 	}
502 
503 	pBuf[3] = convertMrvlCipherToIEEECipher(bitPos);
504 	pBuf += 4;
505 
506 	pBuf[0] = (cipherCnt >> 0) & 0xFF;
507 	pBuf[1] = (cipherCnt >> 16) & 0xFF;
508 	pBuf += 2;
509 
510 	for (i = 0; i < cipherCnt; i++) {
511 		pBuf[0] = oui[0];
512 		pBuf[1] = oui[1];
513 		pBuf[2] = oui[2];
514 
515 		bitPos = util_FindLowestBitSet(ucastBitmap);
516 
517 		pBuf[3] = convertMrvlCipherToIEEECipher(bitPos);
518 
519 		ucastBitmap &= ~bitPos;
520 
521 		pBuf += 4;
522 	}
523 
524 	pBuf[0] = (authKeyCnt >> 0) & 0xFF;
525 	pBuf[1] = (authKeyCnt >> 16) & 0xFF;
526 	pBuf += 2;
527 
528 	for (i = 0; i < authKeyCnt; i++) {
529 		pBuf[0] = oui[0];
530 		pBuf[1] = oui[1];
531 		pBuf[2] = oui[2];
532 
533 		bitPos = util_FindLowestBitSet(authKeyBitmap);
534 
535 		pBuf[3] = convertMrvlAuthToIEEEAuth(bitPos);
536 
537 		authKeyBitmap &= ~bitPos;
538 		pBuf += 4;
539 	}
540 
541 	if (isRsn) {
542 		pBuf[0] = 0x0;
543 		pBuf[1] = 0x0;
544 		pBuf += 2;
545 	}
546 
547 	ieLength = (unsigned long)pBuf - (unsigned long)pIe;
548 	pIe->Len = ieLength - sizeof(IEEEtypes_InfoElementHdr_t);
549 	DBG_HEXDUMP(MCMD_D, "RSN or WPA IE", (t_u8 *)pIe, ieLength);
550 	return ieLength;
551 }
552 
553 /* Ideally one day this function should re-use client code */
554 t_u16
keyMgmtAp_FormatWPARSN_IE(hostsa_private * priv,IEEEtypes_InfoElementHdr_t * pIe,UINT8 isRsn,Cipher_t * pCipher,UINT8 cipherCount,Cipher_t * pMcastCipher,UINT16 authKey,UINT16 authKeyCount)555 keyMgmtAp_FormatWPARSN_IE(hostsa_private *priv,
556 			  IEEEtypes_InfoElementHdr_t *pIe,
557 			  UINT8 isRsn,
558 			  Cipher_t *pCipher,
559 			  UINT8 cipherCount,
560 			  Cipher_t *pMcastCipher,
561 			  UINT16 authKey, UINT16 authKeyCount)
562 {
563 
564 	UINT16 ieLength;
565 
566 	ieLength = keyMgmtAp_FormatWPARSN_IE_internal(priv, pIe,
567 						      isRsn,
568 						      pCipher,
569 						      cipherCount,
570 						      pMcastCipher,
571 						      authKey, authKeyCount);
572 
573 	return ieLength;
574 }
575