From 75bfed4d77afbba345d7dfdfeb156d45502ef1a1 Mon Sep 17 00:00:00 2001 From: Surya Prakash Sivaraj Date: Mon, 16 Oct 2023 18:34:01 +0530 Subject: [PATCH] qcacld-3.0: Move invalid pmkid check to LIM In current design, host validates the PMKID in the assoc request of an SAE STA after the Peer creation in CSR. For cases with invalid PMKID, the assoc response with status INVALID_PMKID and the peer delete are queued back-to-back to the firmware. In some cases, this assoc response gets flushed out due to the peer delete cmd and leads to discard of the assoc response frame in SAP. To fix this, validate the PMKID before the peer creation as part of the assoc request sanity checks. Change-Id: I5aa71188e4482063c5a5173b9aebd54ac9891c17 CRs-Fixed: 3631253 --- core/mac/src/pe/lim/lim_api.c | 2 + .../src/pe/lim/lim_process_assoc_req_frame.c | 115 ++++++++++++++++++ core/sme/src/csr/csr_api_roam.c | 75 ------------ 3 files changed, 117 insertions(+), 75 deletions(-) diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index ce9b2b9e97..18a97900f3 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -3496,6 +3496,8 @@ static const struct rsn_oui_akm_type_map rsn_oui_akm_type_mapping_table[] = { {ANI_AKM_TYPE_DPP_RSN, {0x50, 0x6F, 0x9A, 0x02} }, {ANI_AKM_TYPE_WPA, {0x00, 0x50, 0xF2, 0x01} }, {ANI_AKM_TYPE_WPA_PSK, {0x00, 0x50, 0xF2, 0x02} }, + {ANI_AKM_TYPE_SAE_EXT_KEY, {0x00, 0x0F, 0xAC, 0x18} }, + {ANI_AKM_TYPE_FT_SAE_EXT_KEY, {0x00, 0x0F, 0xAC, 0x19} }, /* Add akm type above here */ {ANI_AKM_TYPE_UNKNOWN, {0} }, }; diff --git a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c index e00c70a621..e7ab254db8 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c @@ -2109,6 +2109,117 @@ static void lim_defer_sme_indication(struct mac_context *mac_ctx, sta_pre_auth_ctx->assoc_req.partner_peer_idx = partner_peer_idx; } +static bool lim_is_sae_akm_present(tDot11fIERSN * const rsn_ie) +{ + uint16_t i; + + if (rsn_ie->akm_suite_cnt > 6) + return false; + + for (i = 0; i < rsn_ie->akm_suite_cnt; i++) { + if ((LE_READ_4(rsn_ie->akm_suite[i]) == RSN_AUTH_KEY_MGMT_SAE) || + (LE_READ_4(rsn_ie->akm_suite[i]) == + RSN_AUTH_KEY_MGMT_SAE_EXT_KEY)) { + pe_debug("SAE AKM present"); + return true; + } + } + return false; +} + +static bool lim_is_pmkid_found_for_peer(struct mac_context *mac_ctx, + tSirMacAddr peer_mac_addr, + struct pe_session *session, + uint8_t *pmkid, + uint16_t pmkid_count) +{ + uint32_t i; + uint8_t *session_pmkid; + struct wlan_crypto_pmksa *pmkid_cache; + + pmkid_cache = qdf_mem_malloc(sizeof(*pmkid_cache)); + + if (!pmkid_cache) + return false; + + qdf_mem_copy(pmkid_cache->bssid.bytes, peer_mac_addr, + QDF_MAC_ADDR_SIZE); + + if (!cm_lookup_pmkid_using_bssid(mac_ctx->psoc, session->vdev_id, + pmkid_cache)) { + qdf_mem_free(pmkid_cache); + return false; + } + + session_pmkid = pmkid_cache->pmkid; + for (i = 0; i < pmkid_count; i++) { + if (!qdf_mem_cmp(pmkid + (i * PMKID_LEN), + session_pmkid, PMKID_LEN)) { + qdf_mem_free(pmkid_cache); + return true; + } + } + + pe_debug("PMKID in cache doesn't match with PMKIDs from the peer"); + qdf_mem_free(pmkid_cache); + + return false; +} + +static bool lim_is_sae_peer_allowed(struct mac_context *mac_ctx, + struct pe_session *session, + tDot11fIERSN *rsn_ie, tSirMacAddr sa, + enum wlan_status_code *mac_status_code) +{ + bool is_allowed = false; + uint8_t *peer_mac_addr = sa; + + /* Allow the peer with valid PMKID */ + if (!rsn_ie->pmkid_count) { + *mac_status_code = STATUS_NOT_SUPPORTED_AUTH_ALG; + pe_debug("No PMKID present in RSNIE; Tried to use SAE AKM after non-SAE authentication"); + } else if (lim_is_pmkid_found_for_peer(mac_ctx, peer_mac_addr, session, + &rsn_ie->pmkid[0][0], + rsn_ie->pmkid_count)) { + pe_debug("Valid PMKID found for SAE peer"); + is_allowed = true; + } else { + *mac_status_code = STATUS_INVALID_PMKID; + pe_debug("No valid PMKID found for SAE peer"); + } + + return is_allowed; +} + +static bool lim_validate_pmkid_for_sae(struct mac_context *mac_ctx, + struct pe_session *session, + tpSirAssocReq assoc_req, tSirMacAddr sa, + uint8_t sub_type) +{ + tDot11fIERSN rsn_ie = {0}; + enum wlan_status_code code = STATUS_INVALID_IE; + + if (!assoc_req->rsnPresent) + return true; + + if (dot11f_unpack_ie_rsn(mac_ctx, &assoc_req->rsn.info[0], + assoc_req->rsn.length, + &rsn_ie, false) != DOT11F_PARSE_SUCCESS) + goto reject_assoc; + + if (lim_is_sae_akm_present(&rsn_ie) && + !assoc_req->is_sae_authenticated && + !lim_is_sae_peer_allowed(mac_ctx, session, &rsn_ie, sa, &code)) + goto reject_assoc; + + return true; + +reject_assoc: + lim_send_assoc_rsp_mgmt_frame(mac_ctx, code, 1, sa, sub_type, 0, + session, false); + return false; +} + bool lim_send_assoc_ind_to_sme(struct mac_context *mac_ctx, struct pe_session *session, uint8_t sub_type, tSirMacAddr sa, @@ -2169,6 +2280,10 @@ bool lim_send_assoc_ind_to_sme(struct mac_context *mac_ctx, if (!lim_chk_wmm(mac_ctx, sa, session, assoc_req, sub_type, qos_mode)) return false; + if (!lim_validate_pmkid_for_sae(mac_ctx, session, assoc_req, + sa, sub_type)) + return false; + /* STA is Associated ! */ pe_debug("Received: %s Req successful from " QDF_MAC_ADDR_FMT, (sub_type == LIM_ASSOC) ? "Assoc" : "ReAssoc", diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index cc9ed90cea..65558c8a1a 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -3772,61 +3772,6 @@ static enum csr_akm_type csr_translate_akm_type(enum ani_akm_type akm_type) return csr_akm_type; } -static bool csr_is_sae_akm_present(tDot11fIERSN * const rsn_ie) -{ - uint16_t i; - - if (rsn_ie->akm_suite_cnt > 6) { - sme_debug("Invalid akm_suite_cnt in Rx RSN IE"); - return false; - } - - for (i = 0; i < rsn_ie->akm_suite_cnt; i++) { - if (LE_READ_4(rsn_ie->akm_suite[i]) == RSN_AUTH_KEY_MGMT_SAE) { - sme_debug("SAE AKM present"); - return true; - } - } - return false; -} - -static bool csr_is_sae_peer_allowed(struct mac_context *mac_ctx, - struct assoc_ind *assoc_ind, - struct csr_roam_session *session, - tDot11fIERSN *rsn_ie, - enum wlan_status_code *mac_status_code) -{ - bool is_allowed = false; - uint8_t *peer_mac_addr; - - /* Allow the peer if it's SAE authenticated */ - if (assoc_ind->is_sae_authenticated) - return true; - - /* Use peer MLD address to find PMKID - * if MLD address is valid - */ - peer_mac_addr = assoc_ind->peer_mld_addr; - if (qdf_is_macaddr_zero((struct qdf_mac_addr *)peer_mac_addr)) - peer_mac_addr = assoc_ind->peerMacAddr; - - /* Allow the peer with valid PMKID */ - if (!rsn_ie->pmkid_count) { - *mac_status_code = STATUS_NOT_SUPPORTED_AUTH_ALG; - sme_debug("No PMKID present in RSNIE; Tried to use SAE AKM after non-SAE authentication"); - } else if (csr_is_pmkid_found_for_peer(mac_ctx, session, peer_mac_addr, - &rsn_ie->pmkid[0][0], - rsn_ie->pmkid_count)) { - sme_debug("Valid PMKID found for SAE peer"); - is_allowed = true; - } else { - *mac_status_code = STATUS_INVALID_PMKID; - sme_debug("No valid PMKID found for SAE peer"); - } - - return is_allowed; -} - #ifdef WLAN_FEATURE_11BE_MLO static void csr_send_assoc_ind_to_upper_layer_mac_copy(tSirSmeAssocIndToUpperLayerCnf *cnf, @@ -4061,26 +4006,6 @@ csr_roam_chk_lnk_assoc_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr) roam_info->ft_pending_assoc_ind = NULL; } roam_info->status_code = eSIR_SME_ASSOC_REFUSED; - } else if (pAssocInd->rsnIE.length && WLAN_ELEMID_RSN == - pAssocInd->rsnIE.rsnIEdata[0]) { - tDot11fIERSN rsn_ie = {0}; - - if (dot11f_unpack_ie_rsn(mac_ctx, - pAssocInd->rsnIE.rsnIEdata + 2, - pAssocInd->rsnIE.length - 2, - &rsn_ie, false) - != DOT11F_PARSE_SUCCESS || - (csr_is_sae_akm_present(&rsn_ie) && - !csr_is_sae_peer_allowed(mac_ctx, pAssocInd, - session, - &rsn_ie, - &mac_status_code))) { - status = QDF_STATUS_E_INVAL; - roam_info->status_code = - eSIR_SME_ASSOC_REFUSED; - sme_debug("SAE peer not allowed: Status: %d", - mac_status_code); - } } } sme_debug("csr_akm_type: %d", csr_akm_type);