abf807d3119345e07efd2c5a0a105860766817e1
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / mt5931 / mgmt / wapi.c
1 /*
2 ** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/wapi.c#1 $
3 */
4
5 /*! \file   "wapi.c"
6     \brief  This file including the WAPI related function.
7
8     This file provided the macros and functions library support the wapi ie parsing,
9     cipher and AKM check to help the AP seleced deciding.
10 */
11
12
13
14 /*
15 ** $Log: wapi.c $
16  *
17  * 11 10 2011 wh.su
18  * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG
19  * change the debug module level.
20  *
21  * 10 20 2010 wh.su
22  * [WCXRP00000067] [MT6620 Wi-Fi][Driver] Support the android+ WAPI function
23  * fixed the network type
24  *
25  * 09 01 2010 wh.su
26  * NULL
27  * adding the wapi support for integration test.
28  *
29  * 07 20 2010 wh.su
30  *
31  * .
32  *
33  * 04 06 2010 wh.su
34  * [BORA00000680][MT6620] Support the statistic for Microsoft os query
35  * fixed the firmware return the broadcast frame at wrong tc.
36  *
37  * 03 03 2010 wh.su
38  * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize
39  * move the AIS specific variable for security to AIS specific structure.
40  *
41  * 12 18 2009 cm.chang
42  * [BORA00000018]Integrate WIFI part into BORA for the 1st time
43  * .
44  *
45  * Dec 8 2009 mtk01088
46  * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code
47  * adding the function to check and update the default wapi tx
48  *
49  * Dec 7 2009 mtk01088
50  * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code
51  * adding the generate wapi ie function, and replace the tabe by space
52  *
53  * Nov 23 2009 mtk01088
54  * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code
55  *
56 */
57
58 /*******************************************************************************
59 *                         C O M P I L E R   F L A G S
60 ********************************************************************************
61 */
62
63 /*******************************************************************************
64 *                    E X T E R N A L   R E F E R E N C E S
65 ********************************************************************************
66 */
67
68 #include "precomp.h"
69 #if CFG_SUPPORT_WAPI
70
71 /*******************************************************************************
72 *                              C O N S T A N T S
73 ********************************************************************************
74 */
75
76 /*******************************************************************************
77 *                             D A T A   T Y P E S
78 ********************************************************************************
79 */
80
81 /*******************************************************************************
82 *                            P U B L I C   D A T A
83 ********************************************************************************
84 */
85
86 /*******************************************************************************
87 *                           P R I V A T E   D A T A
88 ********************************************************************************
89 */
90
91 /*******************************************************************************
92 *                                 M A C R O S
93 ********************************************************************************
94 */
95
96 /*******************************************************************************
97 *                   F U N C T I O N   D E C L A R A T I O N S
98 ********************************************************************************
99 */
100
101 /*******************************************************************************
102 *                              F U N C T I O N S
103 ********************************************************************************
104 */
105
106 /*----------------------------------------------------------------------------*/
107 /*!
108 *
109 * \brief This routine is called to generate WPA IE for
110 *        associate request frame.
111 *
112 * \param[in]  prCurrentBss     The Selected BSS description
113 *
114 * \retval The append WPA IE length
115 *
116 * \note
117 *      Called by: AIS module, Associate request
118 */
119 /*----------------------------------------------------------------------------*/
120 VOID
121 wapiGenerateWAPIIE (
122     IN P_ADAPTER_T          prAdapter,
123     IN P_MSDU_INFO_T        prMsduInfo
124     )
125 {
126     PUINT_8                 pucBuffer;
127
128     ASSERT(prAdapter);
129     ASSERT(prMsduInfo);
130
131     if (prMsduInfo->ucNetworkType != NETWORK_TYPE_AIS_INDEX)
132         return;
133
134     pucBuffer = (PUINT_8)((UINT_32)prMsduInfo->prPacket +
135                           (UINT_32)prMsduInfo->u2FrameLength);
136
137     /* ASSOC INFO IE ID: 68 :0x44 */
138     if (/* prWlanInfo->fgWapiMode && */ prAdapter->prGlueInfo->u2WapiAssocInfoIESz) {
139         kalMemCopy(pucBuffer, &prAdapter->prGlueInfo->aucWapiAssocInfoIEs, prAdapter->prGlueInfo->u2WapiAssocInfoIESz);
140         prMsduInfo->u2FrameLength += prAdapter->prGlueInfo->u2WapiAssocInfoIESz;
141     }
142
143 }
144
145
146 /*----------------------------------------------------------------------------*/
147 /*!
148 * \brief This routine is called to parse WAPI IE.
149 *
150 * \param[in]  prInfoElem Pointer to the RSN IE
151 * \param[out] prRsnInfo Pointer to the BSSDescription structure to store the
152 **                  WAPI information from the given WAPI IE
153 *
154 * \retval TRUE - Succeeded
155 * \retval FALSE - Failed
156 */
157 /*----------------------------------------------------------------------------*/
158 BOOLEAN
159 wapiParseWapiIE (
160     IN  P_WAPI_INFO_ELEM_T prInfoElem,
161     OUT P_WAPI_INFO_T      prWapiInfo
162     )
163 {
164     UINT_32                i;
165     INT_32                 u4RemainWapiIeLen;
166     UINT_16                u2Version;
167     UINT_16                u2Cap = 0;
168     UINT_32                u4GroupSuite = WAPI_CIPHER_SUITE_WPI;
169     UINT_16                u2PairSuiteCount = 0;
170     UINT_16                u2AuthSuiteCount = 0;
171     PUCHAR                 pucPairSuite = NULL;
172     PUCHAR                 pucAuthSuite = NULL;
173     PUCHAR                 cp;
174
175     DEBUGFUNC("wapiParseWapiIE");
176
177     ASSERT(prInfoElem);
178     ASSERT(prWapiInfo);
179
180     /* Verify the length of the WAPI IE. */
181     if (prInfoElem->ucLength < 6) {
182         DBGLOG(SEC, TRACE, ("WAPI IE length too short (length=%d)\n", prInfoElem->ucLength));
183         return FALSE;
184     }
185
186     /* Check WAPI version: currently, we only support version 1. */
187     WLAN_GET_FIELD_16(&prInfoElem->u2Version, &u2Version);
188     if (u2Version != 1) {
189         DBGLOG(SEC, TRACE, ("Unsupported WAPI IE version: %d\n", u2Version));
190         return FALSE;
191     }
192
193     cp = (PUCHAR) &prInfoElem->u2AuthKeyMgtSuiteCount;
194     u4RemainWapiIeLen = (INT_32) prInfoElem->ucLength - 2;
195
196     do {
197         if (u4RemainWapiIeLen == 0) {
198             break;
199         }
200
201         /*
202            AuthCount    : 2
203            AuthSuite    : 4 * authSuiteCount
204            PairwiseCount: 2
205            PairwiseSuite: 4 * pairSuiteCount
206            GroupSuite   : 4
207            Cap          : 2 */
208
209         /* Parse the Authentication and Key Management Cipher Suite Count
210            field. */
211         if (u4RemainWapiIeLen < 2) {
212             DBGLOG(SEC, TRACE, ("Fail to parse WAPI IE in auth & key mgt suite count (IE len: %d)\n",
213                 prInfoElem->ucLength));
214             return FALSE;
215         }
216
217         WLAN_GET_FIELD_16(cp, &u2AuthSuiteCount);
218         cp += 2;
219         u4RemainWapiIeLen -= 2;
220
221         /* Parse the Authentication and Key Management Cipher Suite List
222            field. */
223         i = (UINT_32) u2AuthSuiteCount * 4;
224         if (u4RemainWapiIeLen < (INT_32) i) {
225             DBGLOG(SEC, TRACE, ("Fail to parse WAPI IE in auth & key mgt suite list (IE len: %d)\n",
226                 prInfoElem->ucLength));
227             return FALSE;
228         }
229
230         pucAuthSuite = cp;
231
232         cp += i;
233         u4RemainWapiIeLen -= (INT_32) i;
234
235         if (u4RemainWapiIeLen == 0) {
236             break;
237         }
238
239         /* Parse the Pairwise Key Cipher Suite Count field. */
240         if (u4RemainWapiIeLen < 2) {
241             DBGLOG(SEC, TRACE, ("Fail to parse WAPI IE in pairwise cipher suite count (IE len: %d)\n",
242                 prInfoElem->ucLength));
243             return FALSE;
244         }
245
246         WLAN_GET_FIELD_16(cp, &u2PairSuiteCount);
247         cp += 2;
248         u4RemainWapiIeLen -= 2;
249
250         /* Parse the Pairwise Key Cipher Suite List field. */
251         i = (UINT_32) u2PairSuiteCount * 4;
252         if (u4RemainWapiIeLen < (INT_32) i) {
253             DBGLOG(SEC, TRACE, ("Fail to parse WAPI IE in pairwise cipher suite list (IE len: %d)\n",
254                 prInfoElem->ucLength));
255             return FALSE;
256         }
257
258         pucPairSuite = cp;
259
260         cp += i;
261         u4RemainWapiIeLen -= (INT_32) i;
262
263         /* Parse the Group Key Cipher Suite field. */
264         if (u4RemainWapiIeLen < 4) {
265             DBGLOG(SEC, TRACE, ("Fail to parse WAPI IE in group cipher suite (IE len: %d)\n",
266                 prInfoElem->ucLength));
267             return FALSE;
268         }
269
270         WLAN_GET_FIELD_32(cp, &u4GroupSuite);
271         cp += 4;
272         u4RemainWapiIeLen -= 4;
273
274         /* Parse the WAPI u2Capabilities field. */
275         if (u4RemainWapiIeLen < 2) {
276             DBGLOG(SEC, TRACE, ("Fail to parse WAPI IE in WAPI capabilities (IE len: %d)\n",
277                 prInfoElem->ucLength));
278             return FALSE;
279         }
280
281         WLAN_GET_FIELD_16(cp, &u2Cap);
282         u4RemainWapiIeLen -= 2;
283
284         /* Todo:: BKID support */
285     } while (FALSE);
286
287     /* Save the WAPI information for the BSS. */
288
289     prWapiInfo->ucElemId = ELEM_ID_WAPI;
290
291     prWapiInfo->u2Version = u2Version;
292
293     prWapiInfo->u4GroupKeyCipherSuite = u4GroupSuite;
294
295     DBGLOG(SEC, LOUD, ("WAPI: version %d, group key cipher suite %02x-%02x-%02x-%02x\n",
296         u2Version, (UCHAR) (u4GroupSuite & 0x000000FF),
297         (UCHAR) ((u4GroupSuite >> 8) & 0x000000FF),
298         (UCHAR) ((u4GroupSuite >> 16) & 0x000000FF),
299         (UCHAR) ((u4GroupSuite >> 24) & 0x000000FF)));
300
301     if (pucPairSuite) {
302         /* The information about the pairwise key cipher suites is present. */
303         if (u2PairSuiteCount > MAX_NUM_SUPPORTED_CIPHER_SUITES) {
304             u2PairSuiteCount = MAX_NUM_SUPPORTED_CIPHER_SUITES;
305         }
306
307         prWapiInfo->u4PairwiseKeyCipherSuiteCount = (UINT_32) u2PairSuiteCount;
308
309         for (i = 0; i < (UINT_32) u2PairSuiteCount; i++) {
310             WLAN_GET_FIELD_32(pucPairSuite,
311                               &prWapiInfo->au4PairwiseKeyCipherSuite[i]);
312             pucPairSuite += 4;
313
314             DBGLOG(SEC, LOUD,("WAPI: pairwise key cipher suite [%d]: %02x-%02x-%02x-%02x\n",
315                 (UINT_8)i, (UCHAR) (prWapiInfo->au4PairwiseKeyCipherSuite[i] & 0x000000FF),
316                 (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[i] >> 8) & 0x000000FF),
317                 (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[i] >> 16) & 0x000000FF),
318                 (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[i] >> 24) & 0x000000FF)));
319         }
320     }
321     else {
322         /* The information about the pairwise key cipher suites is not present.
323            Use the default chipher suite for WAPI: WPI. */
324         prWapiInfo->u4PairwiseKeyCipherSuiteCount = 1;
325         prWapiInfo->au4PairwiseKeyCipherSuite[0] = WAPI_CIPHER_SUITE_WPI;
326
327         DBGLOG(SEC, LOUD, ("WAPI: pairwise key cipher suite: %02x-%02x-%02x-%02x (default)\n",
328             (UCHAR) (prWapiInfo->au4PairwiseKeyCipherSuite[0] & 0x000000FF),
329             (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> 8) & 0x000000FF),
330             (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> 16) & 0x000000FF),
331             (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> 24) & 0x000000FF)));
332     }
333
334     if (pucAuthSuite) {
335         /* The information about the authentication and key management suites
336            is present. */
337         if (u2AuthSuiteCount > MAX_NUM_SUPPORTED_AKM_SUITES) {
338             u2AuthSuiteCount = MAX_NUM_SUPPORTED_AKM_SUITES;
339         }
340
341         prWapiInfo->u4AuthKeyMgtSuiteCount = (UINT_32) u2AuthSuiteCount;
342
343         for (i = 0; i < (UINT_32) u2AuthSuiteCount; i++) {
344             WLAN_GET_FIELD_32(pucAuthSuite, &prWapiInfo->au4AuthKeyMgtSuite[i]);
345             pucAuthSuite += 4;
346
347             DBGLOG(SEC, LOUD, ("WAPI: AKM suite [%d]: %02x-%02x-%02x-%02x\n",
348                 (UINT_8)i, (UCHAR) (prWapiInfo->au4AuthKeyMgtSuite[i] & 0x000000FF),
349                 (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> 8) & 0x000000FF),
350                 (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> 16) & 0x000000FF),
351                 (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> 24) & 0x000000FF)));
352         }
353     }
354     else {
355         /* The information about the authentication and key management suites
356            is not present. Use the default AKM suite for WAPI. */
357         prWapiInfo->u4AuthKeyMgtSuiteCount = 1;
358         prWapiInfo->au4AuthKeyMgtSuite[0] = WAPI_AKM_SUITE_802_1X;
359
360         DBGLOG(SEC, LOUD, ("WAPI: AKM suite: %02x-%02x-%02x-%02x (default)\n",
361             (UCHAR) (prWapiInfo->au4AuthKeyMgtSuite[0] & 0x000000FF),
362             (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 8) & 0x000000FF),
363             (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 16) & 0x000000FF),
364             (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 24) & 0x000000FF)));
365     }
366
367     prWapiInfo->u2WapiCap = u2Cap;
368     DBGLOG(SEC, LOUD, ("WAPI: cap: 0x%04x\n", prWapiInfo->u2WapiCap));
369
370     return TRUE;
371 }   /* wapiParseWapiIE */
372
373
374 /*----------------------------------------------------------------------------*/
375 /*!
376 * \brief This routine is called to perform WAPI policy selection for a given BSS.
377 *
378 * \param[in]  prAdapter Pointer to the adapter object data area.
379 * \param[in]  prBss Pointer to the BSS description
380 *
381 * \retval TRUE - The WAPI policy selection for the given BSS is
382 *                successful. The selected pairwise and group cipher suites
383 *                are returned in the BSS description.
384 * \retval FALSE - The WAPI policy selection for the given BSS is failed.
385 *                 The driver shall not attempt to join the given BSS.
386 *
387 * \note The Encrypt status matched score will save to bss for final ap select.
388 */
389 /*----------------------------------------------------------------------------*/
390 BOOLEAN
391 wapiPerformPolicySelection (
392     IN  P_ADAPTER_T         prAdapter,
393     IN  P_BSS_DESC_T        prBss
394     )
395 {
396     UINT_32                 i;
397     UINT_32                 u4PairwiseCipher = 0;
398     UINT_32                 u4GroupCipher = 0;
399     UINT_32                 u4AkmSuite = 0;
400     P_WAPI_INFO_T           prBssWapiInfo;
401     P_WLAN_INFO_T           prWlanInfo;
402
403     DEBUGFUNC("wapiPerformPolicySelection");
404
405     ASSERT(prBss);
406
407     /* Notice!!!! WAPI AP not set the privacy bit for WAI and WAI-PSK at WZC configuration mode */
408     prWlanInfo = &prAdapter->rWlanInfo;
409
410     if (prBss->fgIEWAPI) {
411         prBssWapiInfo = &prBss->rIEWAPI;
412     }
413     else {
414         if (prAdapter->rWifiVar.rConnSettings.fgWapiMode == FALSE) {
415             DBGLOG(SEC, TRACE,("-- No Protected BSS\n"));
416             return TRUE;
417         }
418         else {
419             DBGLOG(SEC, TRACE, ("WAPI Information Element does not exist.\n"));
420             return FALSE;
421         }
422     }
423
424     /* Select pairwise/group ciphers */
425     for (i = 0; i < prBssWapiInfo->u4PairwiseKeyCipherSuiteCount; i++) {
426         if (prBssWapiInfo->au4PairwiseKeyCipherSuite[i] ==
427             prAdapter->rWifiVar.rConnSettings.u4WapiSelectedPairwiseCipher) {
428                 u4PairwiseCipher = prBssWapiInfo->au4PairwiseKeyCipherSuite[i];
429         }
430     }
431     if (prBssWapiInfo->u4GroupKeyCipherSuite ==
432         prAdapter->rWifiVar.rConnSettings.u4WapiSelectedGroupCipher)
433         u4GroupCipher = prBssWapiInfo->u4GroupKeyCipherSuite;
434
435     /* Exception handler */
436     /* If we cannot find proper pairwise and group cipher suites to join the
437        BSS, do not check the supported AKM suites. */
438     if (u4PairwiseCipher == 0 || u4GroupCipher == 0) {
439         DBGLOG(SEC, TRACE, ("Failed to select pairwise/group cipher (0x%08lx/0x%08lx)\n",
440             u4PairwiseCipher, u4GroupCipher));
441         return FALSE;
442     }
443
444     /* Select AKM */
445     /* If the driver cannot support any authentication suites advertised in
446        the given BSS, we fail to perform RSNA policy selection. */
447     /* Attempt to find any overlapping supported AKM suite. */
448     for (i = 0; i < prBssWapiInfo->u4AuthKeyMgtSuiteCount; i++) {
449         if (prBssWapiInfo->au4AuthKeyMgtSuite[i] == prAdapter->rWifiVar.rConnSettings.u4WapiSelectedAKMSuite) {
450             u4AkmSuite = prBssWapiInfo->au4AuthKeyMgtSuite[i];
451             break;
452         }
453     }
454
455     if (u4AkmSuite == 0) {
456         DBGLOG(SEC, TRACE, ("Cannot support any AKM suites\n"));
457         return FALSE;
458     }
459
460     DBGLOG(SEC, TRACE, ("Selected pairwise/group cipher: %02x-%02x-%02x-%02x/%02x-%02x-%02x-%02x\n",
461         (UINT_8) (u4PairwiseCipher & 0x000000FF),
462         (UINT_8) ((u4PairwiseCipher >> 8) & 0x000000FF),
463         (UINT_8) ((u4PairwiseCipher >> 16) & 0x000000FF),
464         (UINT_8) ((u4PairwiseCipher >> 24) & 0x000000FF),
465         (UINT_8) (u4GroupCipher & 0x000000FF),
466         (UINT_8) ((u4GroupCipher >> 8) & 0x000000FF),
467         (UINT_8) ((u4GroupCipher >> 16) & 0x000000FF),
468         (UINT_8) ((u4GroupCipher >> 24) & 0x000000FF)));
469
470     DBGLOG(SEC, TRACE, ("Selected AKM suite: %02x-%02x-%02x-%02x\n",
471         (UINT_8) (u4AkmSuite & 0x000000FF),
472         (UINT_8) ((u4AkmSuite >> 8) & 0x000000FF),
473         (UINT_8) ((u4AkmSuite >> 16) & 0x000000FF),
474         (UINT_8) ((u4AkmSuite >> 24) & 0x000000FF)));
475
476     return TRUE;
477 }  /* wapiPerformPolicySelection */
478
479 #if 0
480 /*----------------------------------------------------------------------------*/
481 /*!
482 * \brief This routine is use for wapi mode, to update the current wpi tx idx ? 0 :1 .
483 *
484 * \param[in]  prStaRec Pointer to the Sta record
485 * \param[out] ucWlanIdx The Rx status->wlanidx field
486 *
487 * \retval TRUE - Succeeded
488 * \retval FALSE - Failed
489 */
490 /*----------------------------------------------------------------------------*/
491 BOOLEAN
492 wapiUpdateTxKeyIdx (
493     IN  P_STA_RECORD_T     prStaRec,
494     IN  UINT_8             ucWlanIdx
495     )
496 {
497     UINT_8 ucKeyId;
498
499     if ((ucWlanIdx & BITS(0, 3)) == CIPHER_SUITE_WPI) {
500
501         ucKeyId = ((ucWlanIdx & BITS(4, 5)) >> 4);
502
503         if (ucKeyId != g_prWifiVar->rAisSpecificBssInfo.ucWpiActivedPWKey) {
504             DBGLOG(RSN, STATE, ("Change wapi key index from %d->%d\n", g_prWifiVar->rAisSpecificBssInfo.ucWpiActivedPWKey, ucKeyId));
505             g_prWifiVar->rAisSpecificBssInfo.ucWpiActivedPWKey = ucKeyId;
506
507             prStaRec->ucWTEntry =
508                 (ucKeyId == WTBL_AIS_BSSID_WAPI_IDX_0) ? WTBL_AIS_BSSID_WAPI_IDX_0 : WTBL_AIS_BSSID_WAPI_IDX_1;
509         }
510     }
511 }
512 #endif
513 #endif
514