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);