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