mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 14:19:09 -04:00
qcacld-3.0: Enhance the RSNXE inter-op logic
Some third-party APs are not able to handle more than 1 octet in the RSNXE, even though RSNXE support is present. Therefore, to prevent this interop issue, send only 1 octet of RSNXE if the AP broadcasts only 1 octet. RSNXE handling logic summary: 1. Don't modify userspace RSNXE when caps other than SAE_H2E, SAE_PK, SECURE_LTF, SECURE_RTT, PROT_RANGE_NEGOTIOATION are set. 2. AP doesn't send RSNXE For WPA2 - Strip the RSNXE completely. For WPA3 - Retain only SAE capabilities such as H2E and PK. 3. AP supports RSNXE with length 1 For WPA2 & WPA3 - Retain only the first octet in RSNXE. 4. AP supports RSNXE with multiple octet For WPA2 & WPA3 - Use the userspace assoc ie RSNXE as it is. Change-Id: I56d1d5711b067fe5e0ff19117f6a600219cb86a0 CRs-Fixed: 3490369
This commit is contained in:
parent
18748980f7
commit
5d837c1b79
2 changed files with 146 additions and 2 deletions
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022,2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
|
|
@ -1872,4 +1872,6 @@ struct he_6ghz_capability_info {
|
|||
#define SIR_MAC_TXSTBC 1
|
||||
#define SIR_MAC_RXSTBC 1
|
||||
|
||||
#define SIR_MAC_RSNX_CAP_MIN_LEN 1
|
||||
#define SIR_MAC_RSNX_CAP_MAX_LEN 16
|
||||
#endif /* __MAC_PROT_DEFS_H */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
|
|
@ -61,6 +61,7 @@
|
|||
#include <wlan_reg_ucfg_api.h>
|
||||
#include "wlan_lmac_if_def.h"
|
||||
#include "wlan_reg_services_api.h"
|
||||
#include <wlan_crypto_global_def.h>
|
||||
|
||||
/* SME REQ processing function templates */
|
||||
static bool __lim_process_sme_sys_ready_ind(struct mac_context *, uint32_t *);
|
||||
|
|
@ -1198,6 +1199,140 @@ lim_get_vdev_rmf_capable(struct mac_context *mac, struct pe_session *session)
|
|||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* lim_rebuild_rsnxe_cap() - Rebuild the RSNXE CAP for STA
|
||||
*
|
||||
* @rsnx_ie: RSNX IE
|
||||
* @length: length of extended RSN cap field
|
||||
*
|
||||
* This API is used to truncate/rebuild the RSNXE based on the length
|
||||
* provided. This length marks the length of the extended RSN cap field.
|
||||
*
|
||||
* Return: Newly constructed RSNX IE
|
||||
*/
|
||||
static inline uint8_t *lim_rebuild_rsnxe_cap(uint8_t *rsnx_ie, uint8_t length)
|
||||
{
|
||||
const uint8_t *rsnxe_cap;
|
||||
uint8_t cap_len;
|
||||
uint8_t *new_rsnxe = NULL;
|
||||
|
||||
if (length < SIR_MAC_RSNX_CAP_MIN_LEN ||
|
||||
length > SIR_MAC_RSNX_CAP_MAX_LEN) {
|
||||
pe_err("Invalid length %d", length);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rsnxe_cap = wlan_crypto_parse_rsnxe_ie(rsnx_ie, &cap_len);
|
||||
if (!rsnxe_cap)
|
||||
return NULL;
|
||||
|
||||
new_rsnxe = qdf_mem_malloc(length + 2);
|
||||
if (!new_rsnxe)
|
||||
return NULL;
|
||||
|
||||
new_rsnxe[0] = WLAN_ELEMID_RSNXE;
|
||||
new_rsnxe[1] = length;
|
||||
qdf_mem_copy(&new_rsnxe[2], rsnxe_cap, length);
|
||||
|
||||
/* Now update the new field length in octet 0 for the new length*/
|
||||
new_rsnxe[2] = (new_rsnxe[2] & 0xF0) | (length - 1);
|
||||
|
||||
pe_debug("New RSNXE length %d", length);
|
||||
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
|
||||
new_rsnxe, length + 2);
|
||||
return new_rsnxe;
|
||||
}
|
||||
|
||||
static inline QDF_STATUS
|
||||
lim_strip_rsnx_ie(struct mac_context *mac_ctx,
|
||||
struct pe_session *session)
|
||||
{
|
||||
int32_t akm;
|
||||
uint8_t len = 0;
|
||||
uint8_t *rsnxe = NULL, *new_rsnxe = NULL;
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
uint8_t *add_ie = NULL;
|
||||
uint16_t add_ie_len;
|
||||
|
||||
akm = wlan_crypto_get_param(session->vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
|
||||
if (akm == -1 ||
|
||||
!(WLAN_CRYPTO_IS_WPA_WPA2(akm) || WLAN_CRYPTO_IS_WPA3(akm)))
|
||||
return status;
|
||||
|
||||
add_ie = session->lim_join_req->addIEAssoc.addIEdata;
|
||||
add_ie_len = session->lim_join_req->addIEAssoc.length;
|
||||
|
||||
if (!wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RSNXE, add_ie, add_ie_len))
|
||||
return status;
|
||||
|
||||
/*
|
||||
* Userspace may send RSNXE also in connect request irrespective
|
||||
* of the connecting AP capabilities. This allows the driver to chose
|
||||
* best candidate based on score. But the chosen candidate may
|
||||
* not support the RSNXE feature and may not advertise RSNXE
|
||||
* in beacon/probe response. Station is not supposed to include
|
||||
* the RSNX IE in assoc request in such cases as legacy APs
|
||||
* may misbahave due to the new IE. It's observed that few
|
||||
* legacy APs which don't support the RSNXE reject the
|
||||
* connection at EAPOL stage.
|
||||
*
|
||||
*/
|
||||
rsnxe = qdf_mem_malloc(WLAN_MAX_IE_LEN + 2);
|
||||
if (!rsnxe)
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
|
||||
lim_strip_ie(mac_ctx, add_ie, &add_ie_len, WLAN_ELEMID_RSNXE,
|
||||
ONE_BYTE, NULL, 0, rsnxe, WLAN_MAX_IE_LEN);
|
||||
|
||||
session->lim_join_req->addIEAssoc.length = add_ie_len;
|
||||
|
||||
if (!rsnxe[0])
|
||||
goto end;
|
||||
|
||||
if (WLAN_CRYPTO_IS_WPA_WPA2(akm)) {
|
||||
mlme_debug("Strip RSNXE as it is not supported by AP");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (WLAN_CRYPTO_IS_WPA3(akm)) {
|
||||
len = 1;
|
||||
goto rebuild_rsnxe;
|
||||
}
|
||||
|
||||
pe_err("Error in handling RSNXE. RSNXE length : %d", rsnxe[1]);
|
||||
status = QDF_STATUS_E_FAILURE;
|
||||
goto end;
|
||||
|
||||
rebuild_rsnxe:
|
||||
/* Build the new RSNXE */
|
||||
new_rsnxe = lim_rebuild_rsnxe_cap(rsnxe, len);
|
||||
if (!new_rsnxe) {
|
||||
status = QDF_STATUS_E_FAILURE;
|
||||
goto end;
|
||||
} else if (!new_rsnxe[1]) {
|
||||
qdf_mem_free(new_rsnxe);
|
||||
status = QDF_STATUS_E_FAILURE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Append the new RSNXE to the assoc ie */
|
||||
if (add_ie_len + new_rsnxe[1] >= SIR_MAC_MAX_ADD_IE_LENGTH) {
|
||||
pe_err("Cannot accomodate the new RSNX IE");
|
||||
status = QDF_STATUS_E_FAILURE;
|
||||
qdf_mem_free(new_rsnxe);
|
||||
goto end;
|
||||
}
|
||||
|
||||
qdf_mem_copy(&add_ie[add_ie_len], new_rsnxe, new_rsnxe[1] + 2);
|
||||
add_ie_len += new_rsnxe[1] + 2;
|
||||
session->lim_join_req->addIEAssoc.length = add_ie_len;
|
||||
qdf_mem_free(new_rsnxe);
|
||||
|
||||
end:
|
||||
qdf_mem_free(rsnxe);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* __lim_process_sme_join_req() - process SME_JOIN_REQ message
|
||||
* @mac_ctx: Pointer to Global MAC structure
|
||||
|
|
@ -1599,6 +1734,13 @@ __lim_process_sme_join_req(struct mac_context *mac_ctx, void *msg_buf)
|
|||
ret_code = eSIR_SME_INVALID_PARAMETERS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
status = lim_strip_rsnx_ie(mac_ctx, session);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
pe_err("Error in parsing RSNX IE");
|
||||
ret_code = eSIR_SME_INVALID_PARAMETERS;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
mlme_obj = wlan_vdev_mlme_get_cmpt_obj(session->vdev);
|
||||
|
|
|
|||
Loading…
Reference in a new issue