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