1 /** @file AssocAp_src_rom.c
2 *
3 * @brief This file defines the function for checking security type and ie
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 #include "wltypes.h"
26 #include "hostsa_ext_def.h"
27 #include "IEEE_types.h"
28
29 #include "authenticator.h"
30 #include "AssocAp_srv_rom.h"
31 #include "parser.h"
32 #include "keyMgmtAp.h"
33
34 BOOLEAN
AssocSrvAp_checkCipherSupport(Cipher_t cipher,Cipher_t allowedCiphers)35 AssocSrvAp_checkCipherSupport(Cipher_t cipher, Cipher_t allowedCiphers)
36 {
37 BOOLEAN match = FALSE;
38
39 if (cipher.ccmp && (allowedCiphers.ccmp)) {
40 match = TRUE;
41 } else if (cipher.tkip && (allowedCiphers.tkip)) {
42 match = TRUE;
43 } else if (cipher.wep40 && (allowedCiphers.wep40)) {
44 match = TRUE;
45 } else if (cipher.wep104 && (allowedCiphers.wep104)) {
46 match = TRUE;
47 }
48
49 return match;
50 }
51
52 UINT16
AssocSrvAp_checkAkm(phostsa_private priv,AkmSuite_t * pAkm,UINT16 allowedAkms)53 AssocSrvAp_checkAkm(phostsa_private priv, AkmSuite_t *pAkm, UINT16 allowedAkms)
54 {
55 hostsa_util_fns *util_fns = &priv->util_fns;
56 UINT16 matchedAkms;
57
58 matchedAkms = 0;
59
60 if ((memcmp(util_fns, pAkm->akmOui, wpa_oui, sizeof(wpa_oui)) != 0) &&
61 ((memcmp(util_fns, pAkm->akmOui, kde_oui, sizeof(kde_oui)) != 0))) {
62 return matchedAkms;
63 }
64
65 switch (pAkm->akmType) {
66 case AKM_1X:
67 matchedAkms = (allowedAkms & UAP_HOSTCMD_KEYMGMT_EAP);
68 break;
69
70 case AKM_PSK:
71 matchedAkms = (allowedAkms & UAP_HOSTCMD_KEYMGMT_PSK);
72 break;
73 case AKM_SHA256_PSK:
74 matchedAkms = (allowedAkms & UAP_HOSTCMD_KEYMGMT_PSK_SHA256);
75 break;
76 default:
77 break;
78 }
79
80 return matchedAkms;
81 }
82
83 WL_STATUS
assocSrvAp_validate4WayHandshakeIe(phostsa_private priv,SecurityMode_t secType,Cipher_t pwCipher,Cipher_t grpCipher,apKeyMgmtInfoStaRom_t * pKeyMgmtInfo,UINT8 akmType,UINT16 rsnCap,Cipher_t config_mcstCipher)84 assocSrvAp_validate4WayHandshakeIe(phostsa_private priv,
85 SecurityMode_t secType,
86 Cipher_t pwCipher,
87 Cipher_t grpCipher,
88 apKeyMgmtInfoStaRom_t *pKeyMgmtInfo,
89 UINT8 akmType,
90 UINT16 rsnCap, Cipher_t config_mcstCipher)
91 {
92 hostsa_util_fns *util_fns = &priv->util_fns;
93
94 if (memcmp
95 (util_fns, (void *)&secType, (void *)&pKeyMgmtInfo->staSecType,
96 sizeof(secType)) != 0) {
97 return FAIL;
98 }
99
100 if (memcmp(util_fns, (void *)&grpCipher,
101 (void *)&config_mcstCipher, sizeof(grpCipher)) != 0) {
102 return FAIL;
103 }
104
105 if (memcmp
106 (util_fns, (void *)&pwCipher, (void *)&pKeyMgmtInfo->staUcstCipher,
107 sizeof(pwCipher)) != 0) {
108 return FAIL;
109 }
110
111 if (akmType != pKeyMgmtInfo->staAkmType) {
112
113 return FAIL;
114 }
115
116 return SUCCESS;
117 }
118
119 void
AssocSrvAp_InitKeyMgmtInfo(phostsa_private priv,apKeyMgmtInfoStaRom_t * pKeyMgmtInfo,SecurityMode_t * secType,Cipher_t * pwCipher,UINT16 staRsnCap,UINT8 akmType)120 AssocSrvAp_InitKeyMgmtInfo(phostsa_private priv,
121 apKeyMgmtInfoStaRom_t *pKeyMgmtInfo,
122 SecurityMode_t *secType, Cipher_t *pwCipher,
123 UINT16 staRsnCap, UINT8 akmType)
124 {
125 hostsa_util_fns *util_fns = &priv->util_fns;
126 pKeyMgmtInfo->keyMgmtState = HSK_NOT_STARTED;
127 memcpy(util_fns, (void *)&pKeyMgmtInfo->staSecType, (void *)secType,
128 sizeof(SecurityMode_t));
129 memcpy(util_fns, (void *)&pKeyMgmtInfo->staUcstCipher, (void *)pwCipher,
130 sizeof(Cipher_t));
131 pKeyMgmtInfo->staAkmType = akmType;
132 if (secType->wpa2) {
133 pKeyMgmtInfo->staRsnCap = staRsnCap;
134 }
135 }
136
137 void
AssocSrvAp_InitStaKeyInfo(cm_Connection * connPtr,SecurityMode_t * secType,Cipher_t * pwCipher,UINT16 staRsnCap,UINT8 akmType)138 AssocSrvAp_InitStaKeyInfo(cm_Connection *connPtr,
139 SecurityMode_t *secType,
140 Cipher_t *pwCipher, UINT16 staRsnCap, UINT8 akmType)
141 {
142 apKeyMgmtInfoSta_t *pKeyMgmtInfo;
143
144 phostsa_private priv = (phostsa_private)connPtr->priv;
145 hostsa_util_fns *util_fns = &priv->util_fns;
146
147 KeyMgmtStopHskTimer(connPtr);
148
149 pKeyMgmtInfo = &connPtr->staData.keyMgmtInfo;
150 memset(util_fns, (void *)pKeyMgmtInfo, 0x00,
151 sizeof(apKeyMgmtInfoSta_t));
152 AssocSrvAp_InitKeyMgmtInfo(priv, &pKeyMgmtInfo->rom, secType, pwCipher,
153 staRsnCap, akmType);
154 pKeyMgmtInfo->EAPOLProtoVersion = EAPOL_PROTOCOL_V1;
155 }
156
157 WL_STATUS
assocSrvAp_checkRsnWpa(cm_Connection * connPtr,apKeyMgmtInfoStaRom_t * pKeyMgmtInfo,Cipher_t apWpaCipher,Cipher_t apWpa2Cipher,Cipher_t apMcstCipher,UINT16 apAuthKey,SecurityMode_t * pSecType,IEEEtypes_RSNElement_t * pRsn,IEEEtypes_WPAElement_t * pWpa,BOOLEAN validate4WayHandshakeIE)158 assocSrvAp_checkRsnWpa(cm_Connection *connPtr,
159 apKeyMgmtInfoStaRom_t *pKeyMgmtInfo,
160 Cipher_t apWpaCipher,
161 Cipher_t apWpa2Cipher,
162 Cipher_t apMcstCipher,
163 UINT16 apAuthKey,
164 SecurityMode_t *pSecType,
165 IEEEtypes_RSNElement_t *pRsn,
166 IEEEtypes_WPAElement_t *pWpa,
167 BOOLEAN validate4WayHandshakeIE)
168 {
169 phostsa_private priv = (phostsa_private)connPtr->priv;
170 hostsa_util_fns *util_fns = &priv->util_fns;
171 WL_STATUS result = SUCCESS;
172 Cipher_t apCipher;
173 Cipher_t pwCipher;
174 Cipher_t grpCipher;
175 SecurityMode_t wpaType;
176 AkmSuite_t akm[AKM_SUITE_MAX];
177 UINT8 minimumRsnLen;
178
179 /* staRsnCap field is only used to compare RsnCap received in AssocRequest
180 with rsnCap received in 4 way handshake PWKMsg2.
181
182 we use 0xFFFF signature. If rsnCap is not present in pRsn,
183 signature 0xFFFF would be saved in pKeyMgmtInfo->staRsnCap.
184 */
185
186 union {
187 UINT16 shortInt;
188 IEEEtypes_RSNCapability_t cfg;
189 } staRsnCap;
190
191 memset(util_fns, &wpaType, 0x00, sizeof(wpaType));
192 memset(util_fns, &apCipher, 0x00, sizeof(apCipher));
193 memset(util_fns, &pwCipher, 0x00, sizeof(pwCipher));
194 memset(util_fns, &grpCipher, 0x00, sizeof(grpCipher));
195 staRsnCap.shortInt = 0xFFFF;
196
197 if (pRsn && (pSecType->wpa2 == 1)) {
198
199 /*
200 In pRsn , All elements after Ver field are optional per the spec.
201
202 we reject Assoc Request, if GrpKeyCipher, pwsKey and AuthKey
203 is not present.
204
205 we can rely on minimum length check as we are rejecting Assoc Request
206 having pwsKeyCnt > 1 and AuthKeyCnt > 1
207
208 */
209
210 minimumRsnLen = (unsigned long)&pRsn->RsnCap -
211 (unsigned long)&pRsn->Ver;
212
213 if (pRsn->Len < minimumRsnLen) {
214 PRINTM(MERROR, "pRsn->Len %x < minimumRsnLen %x\n",
215 pRsn->Len, minimumRsnLen);
216 return FAIL;
217 }
218
219 if (pRsn->PwsKeyCnt == 1 && pRsn->AuthKeyCnt == 1) {
220 apCipher = apWpa2Cipher;
221
222 supplicantParseRsnIe(priv, pRsn,
223 &wpaType,
224 &grpCipher,
225 &pwCipher,
226 akm,
227 NELEMENTS(akm),
228 &staRsnCap.cfg, NULL);
229 } else {
230 PRINTM(MERROR,
231 "pRsn->PwsKeyCnt %x pRsn->AuthKeyCnt %x\n",
232 pRsn->PwsKeyCnt, pRsn->AuthKeyCnt);
233 result = FAIL;
234 }
235 } else if (pWpa && (pSecType->wpa == 1)) {
236 if (pWpa->PwsKeyCnt == 1 && pWpa->AuthKeyCnt == 1) {
237 apCipher = apWpaCipher;
238 supplicantParseWpaIe(priv, pWpa,
239 &wpaType,
240 &grpCipher,
241 &pwCipher, akm, NELEMENTS(akm));
242 } else {
243 PRINTM(MERROR,
244 "pWpa->PwsKeyCnt %x pWpa->AuthKeyCnt %x\n",
245 pWpa->PwsKeyCnt, pWpa->AuthKeyCnt);
246 result = FAIL;
247 }
248 } else {
249 PRINTM(MERROR, "No wpa or rsn\n");
250 result = FAIL;
251 }
252
253 if ((pwCipher.ccmp == 0) && (pwCipher.tkip == 0)) {
254 PRINTM(MERROR,
255 "(pwCipher.ccmp(%x) == 0) && (pwCipher.tkip(%x) == 0)\n",
256 pwCipher.ccmp, pwCipher.tkip);
257 result = FAIL;
258 }
259
260 if ((grpCipher.ccmp == 0) && (grpCipher.tkip == 0)) {
261 PRINTM(MERROR,
262 "((grpCipher.ccmp(%x) == 0) && (grpCipher.tkip(%x) == 0))\n",
263 grpCipher.ccmp, grpCipher.tkip);
264 result = FAIL;
265 }
266 DBG_HEXDUMP(MCMD_D, " akm", (t_u8 *)&akm[0], sizeof(AkmSuite_t));
267 if (SUCCESS == result) {
268 #ifdef DOT11W
269 if (staRsnCap.shortInt != 0xFFFF) {
270 /* Save the peer STA PMF capability, which will later used to enable PMF */
271 connPtr->staData.peerPMFCapable = staRsnCap.cfg.MFPC;
272 }
273 #endif
274 if (validate4WayHandshakeIE == MFALSE) {
275 if ((AssocSrvAp_checkCipherSupport(pwCipher, apCipher)
276 == TRUE) &&
277 (AssocSrvAp_checkCipherSupport
278 (grpCipher, apMcstCipher)
279 == TRUE) &&
280 (AssocSrvAp_checkAkm(priv, akm, apAuthKey) != 0)) {
281 AssocSrvAp_InitStaKeyInfo(connPtr, &wpaType,
282 &pwCipher,
283 staRsnCap.shortInt,
284 akm[0].akmType);
285 } else {
286 result = FAIL;
287 }
288 } else {
289 result = assocSrvAp_validate4WayHandshakeIe(priv,
290 wpaType,
291 pwCipher,
292 grpCipher,
293 pKeyMgmtInfo,
294 akm[0].
295 akmType,
296 staRsnCap.
297 shortInt,
298 apMcstCipher);
299 }
300 }
301 return result;
302 }
303
304 SINT32
assocSrvAp_CheckSecurity(cm_Connection * connPtr,IEEEtypes_WPSElement_t * pWps,IEEEtypes_RSNElement_t * pRsn,IEEEtypes_WPAElement_t * pWpa,IEEEtypes_WAPIElement_t * pWapi,IEEEtypes_StatusCode_t * pResult)305 assocSrvAp_CheckSecurity(cm_Connection *connPtr,
306 IEEEtypes_WPSElement_t *pWps,
307 IEEEtypes_RSNElement_t *pRsn,
308 IEEEtypes_WPAElement_t *pWpa,
309 IEEEtypes_WAPIElement_t *pWapi,
310 IEEEtypes_StatusCode_t *pResult)
311 {
312 phostsa_private priv = (phostsa_private)connPtr->priv;
313 apInfo_t *pApInfo = &priv->apinfo;
314 BssConfig_t *pBssConfig = NULL;
315 SINT32 retval = MLME_FAILURE;
316
317 *pResult = IEEEtypes_STATUS_INVALID_RSN_CAPABILITIES;
318
319 pBssConfig = &pApInfo->bssConfig;
320
321 PRINTM(MMSG, "assocSrvAp_CheckSecurity Sectyep wpa %x wpa2 %x\n",
322 pBssConfig->SecType.wpa, pBssConfig->SecType.wpa2);
323 if ((pBssConfig->SecType.wpa == 1) || (pBssConfig->SecType.wpa2 == 1)) {
324 apKeyMgmtInfoSta_t *pKeyMgmtInfo =
325 &connPtr->staData.keyMgmtInfo;
326 Cipher_t wpaUcastCipher = pBssConfig->RsnConfig.wpaUcstCipher;
327 Cipher_t wpa2UcastCipher = pBssConfig->RsnConfig.wpa2UcstCipher;
328 DBG_HEXDUMP(MCMD_D, " wpa2UcstCipher",
329 (t_u8 *)&wpa2UcastCipher, sizeof(Cipher_t));
330 DBG_HEXDUMP(MCMD_D, " wpaUcastCipher",
331 (t_u8 *)&wpaUcastCipher, sizeof(Cipher_t));
332 connPtr->staData.RSNEnabled = 0;
333 if (assocSrvAp_checkRsnWpa(connPtr, &pKeyMgmtInfo->rom,
334 wpaUcastCipher,
335 wpa2UcastCipher,
336 pBssConfig->RsnConfig.mcstCipher,
337 pBssConfig->RsnConfig.AuthKey,
338 &pBssConfig->SecType, pRsn, pWpa,
339 MFALSE) == SUCCESS) {
340 retval = MLME_SUCCESS;
341 connPtr->staData.RSNEnabled = 1;
342 }
343 } else if (pBssConfig->SecType.wepStatic == 1) {
344 if (!pRsn || !pWpa) {
345 retval = MLME_SUCCESS;
346 }
347 } else if (pBssConfig->SecType.wapi) {
348 /* if (wapi_ie_check(pBssConfig, pWapi, pResult))
349 {
350 *pResult = 0;
351 retval = MLME_SUCCESS;
352 } */
353 }
354
355 return retval;
356 }
357