1 /*
2  * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*
21  *
22  * This file lim_sme_req_utils.cc contains the utility functions
23  * for processing SME request messages.
24  * Author:        Chandra Modumudi
25  * Date:          02/11/02
26  * History:-
27  * Date           Modified by    Modification Information
28  * --------------------------------------------------------------------
29  * 05/26/10       js             WPA handling in (Re)Assoc frames
30  *
31  */
32 
33 #include "wni_api.h"
34 #include "wni_cfg.h"
35 #include "sir_api.h"
36 #include "sch_api.h"
37 #include "utils_api.h"
38 #include "lim_types.h"
39 #include "lim_utils.h"
40 #include "lim_assoc_utils.h"
41 #include "lim_security_utils.h"
42 #include "lim_ser_des_utils.h"
43 #include "lim_sme_req_utils.h"
44 
45 /**
46  * lim_is_rsn_ie_valid_in_sme_req_message()
47  *
48  * @mac_ctx   Pointer to Global MAC structure
49  * @rsn_ie    Pointer to received RSN IE
50  *
51  * This function is called to verify if the RSN IE received in various SME_REQ
52  * messages is valid or not
53  *
54  * Return: true when RSN IE is valid, false otherwise
55  *
56  */
57 static uint8_t
lim_is_rsn_ie_valid_in_sme_req_message(struct mac_context * mac_ctx,tpSirRSNie rsn_ie)58 lim_is_rsn_ie_valid_in_sme_req_message(struct mac_context *mac_ctx,
59 				       tpSirRSNie rsn_ie)
60 {
61 	uint8_t start = 0;
62 	uint32_t val;
63 	int len;
64 
65 	val = mac_ctx->mlme_cfg->feature_flags.enable_rsn;
66 	if (rsn_ie->length && !val) {
67 		/* Privacy & RSN not enabled in CFG.
68 		 * In order to allow mixed mode for Guest access
69 		 * allow BSS creation/join with no Privacy capability
70 		 * yet advertising WPA IE
71 		 */
72 		pe_debug("RSN ie len: %d RSN: %d",
73 			       rsn_ie->length, val);
74 	}
75 
76 	if (!rsn_ie->length) {
77 		pe_debug("RSN IE length is 0");
78 		return true;
79 	}
80 
81 	if ((rsn_ie->rsnIEdata[0] != DOT11F_EID_RSN)
82 #ifdef FEATURE_WLAN_WAPI
83 	    && (rsn_ie->rsnIEdata[0] != DOT11F_EID_WAPI)
84 #endif
85 	    && (rsn_ie->rsnIEdata[0] != DOT11F_EID_WPA)) {
86 		pe_err("RSN/WPA/WAPI EID: %d not [%d || %d]",
87 			rsn_ie->rsnIEdata[0], DOT11F_EID_RSN,
88 			DOT11F_EID_WPA);
89 		return false;
90 	}
91 
92 	len = rsn_ie->length;
93 	start = 0;
94 	while (len > 0) {
95 		switch (rsn_ie->rsnIEdata[start]) {
96 		case DOT11F_EID_RSN:
97 		/* Check validity of RSN IE */
98 			if ((rsn_ie->rsnIEdata[start + 1] >
99 			    DOT11F_IE_RSN_MAX_LEN)
100 			    || (rsn_ie->rsnIEdata[start + 1] <
101 				DOT11F_IE_RSN_MIN_LEN)) {
102 				pe_err("RSN IE len: %d not [%d,%d]",
103 					rsn_ie->rsnIEdata[start + 1],
104 					DOT11F_IE_RSN_MIN_LEN,
105 					DOT11F_IE_RSN_MAX_LEN);
106 				return false;
107 			}
108 			break;
109 		case DOT11F_EID_WPA:
110 			/* Check validity of WPA IE */
111 			if (WLAN_MAX_IE_LEN <= start)
112 				break;
113 
114 			if (start <= (WLAN_MAX_IE_LEN - sizeof(uint32_t)))
115 				val = sir_read_u32((uint8_t *) &
116 					rsn_ie->rsnIEdata[start + 2]);
117 
118 			if ((rsn_ie->rsnIEdata[start + 1] <
119 			     DOT11F_IE_WPA_MIN_LEN)
120 			    || (rsn_ie->rsnIEdata[start + 1] >
121 				DOT11F_IE_WPA_MAX_LEN)
122 			    || (SIR_MAC_WPA_OUI != val)) {
123 				pe_err("WPA IE len: %d not [%d,%d] OR data 0x%x not 0x%x",
124 					rsn_ie->rsnIEdata[start + 1],
125 					DOT11F_IE_WPA_MIN_LEN,
126 					DOT11F_IE_WPA_MAX_LEN,
127 					val, SIR_MAC_WPA_OUI);
128 				return false;
129 			}
130 			break;
131 #ifdef FEATURE_WLAN_WAPI
132 		case DOT11F_EID_WAPI:
133 			if ((rsn_ie->rsnIEdata[start + 1] >
134 			    DOT11F_IE_WAPI_MAX_LEN)
135 			    || (rsn_ie->rsnIEdata[start + 1] <
136 				DOT11F_IE_WAPI_MIN_LEN)) {
137 				pe_err("WAPI IE len: %d not [%d,%d]",
138 					rsn_ie->rsnIEdata[start + 1],
139 					DOT11F_IE_WAPI_MIN_LEN,
140 					DOT11F_IE_WAPI_MAX_LEN);
141 				return false;
142 			}
143 			break;
144 #endif
145 		default:
146 			/* we will never be here, simply for completeness */
147 			return false;
148 		} /* end of switch */
149 		/* EID + length field + length */
150 		start += 2 + rsn_ie->rsnIEdata[start + 1];
151 		len -= start;
152 	} /* end while loop */
153 	return true;
154 } /*** end lim_is_rs_nie_valid_in_sme_req_message() ***/
155 
156 /**
157  * lim_set_rs_nie_wp_aiefrom_sme_start_bss_req_message() - to set rsnie/wpaie
158  *
159  * @mac_ctx : Pointer to Global MAC structure
160  * @rsn_ie  : Pointer to received RSN IE
161  * @session : Pointer to pe session
162  *
163  * This function is called to verify if the RSN IE received in various
164  * SME_REQ messages is valid or not. RSN IE validity checks are performed in
165  * this function
166  *
167  * Return: true when RSN IE is valid, false otherwise
168  */
169 uint8_t
lim_set_rs_nie_wp_aiefrom_sme_start_bss_req_message(struct mac_context * mac_ctx,tpSirRSNie rsn_ie,struct pe_session * session)170 lim_set_rs_nie_wp_aiefrom_sme_start_bss_req_message(struct mac_context *mac_ctx,
171 						    tpSirRSNie rsn_ie,
172 						    struct pe_session *session)
173 {
174 	uint32_t ret;
175 	uint8_t wpa_idx = 0;
176 	uint32_t val;
177 	bool privacy;
178 
179 	privacy = mac_ctx->mlme_cfg->wep_params.is_privacy_enabled;
180 
181 	val = mac_ctx->mlme_cfg->feature_flags.enable_rsn;
182 	if (rsn_ie->length && (!privacy || !val)) {
183 		/*
184 		 * Privacy & RSN not enabled in CFG.
185 		 * In order to allow mixed mode for Guest access
186 		 * allow BSS creation/join with no Privacy capability
187 		 * yet advertising WPA IE
188 		 */
189 		pe_debug("RSN ie len: %d but PRIVACY: %d RSN: %d",
190 			rsn_ie->length, privacy, val);
191 	}
192 
193 	if (!rsn_ie->length)
194 		return true;
195 
196 	if ((rsn_ie->rsnIEdata[0] != WLAN_ELEMID_RSN) &&
197 	    (rsn_ie->rsnIEdata[0] != SIR_MAC_WPA_EID)) {
198 		pe_err("RSN/WPA EID: %d not [%d || %d]",
199 			rsn_ie->rsnIEdata[0], WLAN_ELEMID_RSN,
200 			SIR_MAC_WPA_EID);
201 		return false;
202 	}
203 	/* Check validity of RSN IE */
204 	if ((rsn_ie->rsnIEdata[0] == WLAN_ELEMID_RSN) &&
205 	    (rsn_ie->rsnIEdata[1] < SIR_MAC_RSN_IE_MIN_LENGTH)) {
206 		pe_err("RSN IE len: %d not [%d,%d]",
207 			rsn_ie->rsnIEdata[1], SIR_MAC_RSN_IE_MIN_LENGTH,
208 			WLAN_MAX_IE_LEN);
209 		return false;
210 	}
211 
212 	if (rsn_ie->length > rsn_ie->rsnIEdata[1] + 2) {
213 		if (rsn_ie->rsnIEdata[0] != WLAN_ELEMID_RSN) {
214 			pe_err("First byte: %d in rsnIEdata isn't RSN_EID",
215 				rsn_ie->rsnIEdata[1]);
216 			return false;
217 		}
218 		pe_debug("WPA IE is present along with WPA2 IE");
219 		wpa_idx = 2 + rsn_ie->rsnIEdata[1];
220 	} else if ((rsn_ie->length == rsn_ie->rsnIEdata[1] + 2) &&
221 		   (rsn_ie->rsnIEdata[0] == WLAN_ELEMID_RSN)) {
222 		pe_debug("Only RSN IE is present");
223 		ret = dot11f_unpack_ie_rsn(mac_ctx, &rsn_ie->rsnIEdata[2],
224 					   rsn_ie->rsnIEdata[1],
225 					   &session->gStartBssRSNIe, false);
226 		if (!DOT11F_SUCCEEDED(ret)) {
227 			pe_err("unpack failed, ret: %d", ret);
228 			return false;
229 		}
230 		return true;
231 	} else if ((rsn_ie->length == rsn_ie->rsnIEdata[1] + 2)
232 		   && (rsn_ie->rsnIEdata[0] == SIR_MAC_WPA_EID)) {
233 		pe_debug("Only WPA IE is present");
234 		ret = dot11f_unpack_ie_wpa(mac_ctx, &rsn_ie->rsnIEdata[6],
235 					   rsn_ie->rsnIEdata[1] - 4,
236 					   &session->gStartBssWPAIe, false);
237 		if (!DOT11F_SUCCEEDED(ret)) {
238 			pe_err("unpack failed, ret: %d", ret);
239 			return false;
240 		}
241 		return true;
242 	}
243 	/* Check validity of WPA IE */
244 	if (wpa_idx + 6 >= WLAN_MAX_IE_LEN)
245 		return false;
246 
247 	val = sir_read_u32((uint8_t *)&rsn_ie->rsnIEdata[wpa_idx + 2]);
248 	if ((rsn_ie->rsnIEdata[wpa_idx] == SIR_MAC_WPA_EID)
249 	    && ((rsn_ie->rsnIEdata[wpa_idx + 1] < SIR_MAC_WPA_IE_MIN_LENGTH)
250 	     || (SIR_MAC_WPA_OUI != val))) {
251 		pe_err("WPA IE len: %d not [%d,%d] OR data 0x%x not 0x%x",
252 			rsn_ie->rsnIEdata[1],
253 			SIR_MAC_RSN_IE_MIN_LENGTH,
254 			WLAN_MAX_IE_LEN, val,
255 			SIR_MAC_WPA_OUI);
256 		return false;
257 	} else {
258 		/* Both RSN and WPA IEs are present */
259 		ret = dot11f_unpack_ie_rsn(mac_ctx, &rsn_ie->rsnIEdata[2],
260 					   rsn_ie->rsnIEdata[1],
261 					   &session->gStartBssRSNIe, false);
262 		if (!DOT11F_SUCCEEDED(ret)) {
263 			pe_err("unpack failed, ret: %d", ret);
264 			return false;
265 		}
266 		ret = dot11f_unpack_ie_wpa(mac_ctx,
267 					   &rsn_ie->rsnIEdata[wpa_idx + 6],
268 					   rsn_ie->rsnIEdata[wpa_idx + 1] - 4,
269 					   &session->gStartBssWPAIe, false);
270 		if (!DOT11F_SUCCEEDED(ret)) {
271 			pe_err("unpack failed, ret: %d", ret);
272 			return false;
273 		}
274 	}
275 	return true;
276 }
277 
lim_is_sme_start_bss_req_valid(struct mac_context * mac_ctx,struct start_bss_config * start_bss_req,enum bss_type bss_type)278 bool lim_is_sme_start_bss_req_valid(struct mac_context *mac_ctx,
279 				    struct start_bss_config *start_bss_req,
280 				    enum bss_type bss_type)
281 {
282 	uint8_t i = 0;
283 	tSirMacRateSet *opr_rates = &start_bss_req->operationalRateSet;
284 
285 	switch (bss_type) {
286 	case eSIR_INFRASTRUCTURE_MODE:
287 		/**
288 		 * Should not have received start BSS req with bssType
289 		 * Infrastructure on STA.
290 		 */
291 		pe_warn("Invalid bss type: %d in eWNI_SME_START_BSS_REQ",
292 			bss_type);
293 		return false;
294 		break;
295 	case eSIR_INFRA_AP_MODE:
296 		break;
297 	case eSIR_NDI_MODE:
298 		break;
299 	default:
300 		/**
301 		 * Should not have received start BSS req with bssType
302 		 * other than Infrastructure/IBSS.
303 		 */
304 		pe_warn("Invalid bss type: %d in eWNI_SME_START_BSS_REQ",
305 			bss_type);
306 		return false;
307 	}
308 
309 	if (!lim_is_rsn_ie_valid_in_sme_req_message(mac_ctx,
310 						    &start_bss_req->rsnIE))
311 		return false;
312 
313 	if (start_bss_req->nwType != eSIR_11A_NW_TYPE
314 	    && start_bss_req->nwType != eSIR_11B_NW_TYPE
315 	    && start_bss_req->nwType != eSIR_11G_NW_TYPE)
316 		return false;
317 
318 	if (start_bss_req->nwType == eSIR_11A_NW_TYPE) {
319 		for (i = 0; i < opr_rates->numRates; i++) {
320 			if (sirIsArate(opr_rates->rate[i] & 0x7F))
321 				continue;
322 
323 			pe_warn("Invalid operational 11A rates");
324 			QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE,
325 					   QDF_TRACE_LEVEL_WARN,
326 					   opr_rates->rate,
327 					   opr_rates->numRates);
328 			return false;
329 		}
330 		return true;
331 	}
332 	/* check if all the rates in the opr rate set are legal 11G rates */
333 	if (start_bss_req->nwType == eSIR_11G_NW_TYPE) {
334 		for (i = 0; i < opr_rates->numRates; i++) {
335 			if (sirIsGrate(opr_rates->rate[i] & 0x7F))
336 				continue;
337 
338 			pe_warn("Invalid operational 11G rates");
339 			QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE,
340 					   QDF_TRACE_LEVEL_WARN,
341 					   opr_rates->rate,
342 					   opr_rates->numRates);
343 			return false;
344 		}
345 		return true;
346 	}
347 
348 	for (i = 0; i < opr_rates->numRates; i++) {
349 		if (sirIsBrate(opr_rates->rate[i] & 0x7F))
350 			continue;
351 
352 		pe_warn("Invalid operational 11B rates");
353 		QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE,
354 				   QDF_TRACE_LEVEL_WARN,
355 				   opr_rates->rate,
356 				   opr_rates->numRates);
357 		return false;
358 	}
359 	return true;
360 }
361 
lim_is_sme_disassoc_req_valid(struct mac_context * mac,struct disassoc_req * disassoc_req,struct pe_session * pe_session)362 bool lim_is_sme_disassoc_req_valid(struct mac_context *mac,
363 				   struct disassoc_req *disassoc_req,
364 				   struct pe_session *pe_session)
365 {
366 	if (qdf_is_macaddr_group(&disassoc_req->peer_macaddr) &&
367 	    !qdf_is_macaddr_broadcast(&disassoc_req->peer_macaddr))
368 		return false;
369 
370 	return true;
371 } /*** end lim_is_sme_disassoc_req_valid() ***/
372 
lim_is_sme_disassoc_cnf_valid(struct mac_context * mac,struct disassoc_cnf * disassoc_cnf,struct pe_session * pe_session)373 bool lim_is_sme_disassoc_cnf_valid(struct mac_context *mac,
374 				   struct disassoc_cnf *disassoc_cnf,
375 				   struct pe_session *pe_session)
376 {
377 	if (qdf_is_macaddr_group(&disassoc_cnf->peer_macaddr))
378 		return false;
379 
380 	return true;
381 } /*** end lim_is_sme_disassoc_cnf_valid() ***/
382 
lim_is_sme_deauth_req_valid(struct mac_context * mac,struct deauth_req * deauth_req,struct pe_session * pe_session)383 bool lim_is_sme_deauth_req_valid(struct mac_context *mac,
384 				 struct deauth_req *deauth_req,
385 				 struct pe_session *pe_session)
386 {
387 	if (qdf_is_macaddr_group(&deauth_req->peer_macaddr) &&
388 	    !qdf_is_macaddr_broadcast(&deauth_req->peer_macaddr))
389 		return false;
390 
391 	return true;
392 } /*** end lim_is_sme_deauth_req_valid() ***/
393