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