diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index c1a6d8913bc1..33496f75feb7 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -4961,6 +4961,12 @@ hdd_sme_roam_callback(void *context, struct csr_roam_info *roam_info, } break; + case eCSR_ROAM_FIPS_PMK_REQUEST: + /* notify the supplicant of a new candidate */ + qdf_ret_status = wlan_hdd_cfg80211_pmksa_candidate_notify( + adapter, roam_info, 1, false); + break; + default: break; } diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 7c1d9c6df5af..61d2207a23c0 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -391,6 +391,7 @@ struct sme_ready_req { uint8_t vdev_id, uint8_t *deauth_disassoc_frame, uint16_t deauth_disassoc_frame_len); + void *csr_roam_pmkid_req_cb; }; /** diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index e61d6cdb829c..87dda14a5ee9 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -1307,7 +1307,8 @@ void pe_register_callbacks_with_wma(struct mac_context *mac, ready_req->csr_roam_synch_cb, ready_req->csr_roam_auth_event_handle_cb, ready_req->pe_roam_synch_cb, - ready_req->pe_disconnect_cb); + ready_req->pe_disconnect_cb, + ready_req->csr_roam_pmkid_req_cb); if (status != QDF_STATUS_SUCCESS) pe_err("Registering roaming callbacks with WMA failed"); } diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index 90edf5239253..d74ec82272b5 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -391,6 +391,7 @@ typedef enum { eCSR_ROAM_SAE_COMPUTE, /* LFR3 Roam sync complete */ eCSR_ROAM_SYNCH_COMPLETE, + eCSR_ROAM_FIPS_PMK_REQUEST, } eRoamCmdStatus; /* comment inside indicates what roaming callback gets */ diff --git a/core/sme/inc/csr_neighbor_roam.h b/core/sme/inc/csr_neighbor_roam.h index 21df7cb4c8d9..922045cd6ad4 100644 --- a/core/sme/inc/csr_neighbor_roam.h +++ b/core/sme/inc/csr_neighbor_roam.h @@ -426,6 +426,40 @@ QDF_STATUS csr_fast_reassoc(mac_handle_t mac_handle, const tSirMacAddr bssid, uint32_t ch_freq, uint8_t vdev_id, const tSirMacAddr connected_bssid); +#ifdef WLAN_FEATURE_FIPS +/** + * csr_roam_pmkid_req_callback() - Registered CSR Callback function to handle + * roam event from firmware for pmkid generation fallback. + * @vdev_id: Vdev id + * @bss_list: candidate AP bssid list + */ +QDF_STATUS +csr_roam_pmkid_req_callback(uint8_t vdev_id, + struct roam_pmkid_req_event *bss_list); + +/** + * csr_process_roam_pmkid_req_callback() - API to trigger the pmkid + * generation fallback event for candidate AP received from firmware. + * @mac_ctx: Global mac context pointer + * @vdev_id: Vdev id + * @roam_bsslist: roam candidate AP bssid list + * + * This function calls the hdd_sme_roam_callback with reason + * eCSR_ROAM_FIPS_PMK_REQUEST to trigger pmkid generation in supplicant. + */ +QDF_STATUS +csr_process_roam_pmkid_req_callback(struct mac_context *mac_ctx, + uint8_t vdev_id, + struct roam_pmkid_req_event *roam_bsslist); +#else +static inline QDF_STATUS +csr_roam_pmkid_req_callback(uint8_t vdev_id, + struct roam_pmkid_req_event *bss_list) +{ + return QDF_STATUS_SUCCESS; +} +#endif /* WLAN_FEATURE_FIPS */ + #else static inline QDF_STATUS csr_roam_synch_callback(struct mac_context *mac, struct roam_offload_synch_ind *roam_synch_data, @@ -450,6 +484,13 @@ QDF_STATUS csr_fast_reassoc(mac_handle_t mac_handle, { return QDF_STATUS_SUCCESS; } + +static inline QDF_STATUS +csr_roam_pmkid_req_callback(uint8_t vdev_id, + struct roam_pmkid_req_event *bss_list) +{ + return QDF_STATUS_E_NOSUPPORT; +} #endif void csr_neighbor_roam_state_transition(struct mac_context *mac_ctx, uint8_t newstate, uint8_t session); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 986513b4718c..850999bd3777 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -1077,6 +1077,7 @@ QDF_STATUS sme_hdd_ready_ind(mac_handle_t mac_handle) msg->stop_roaming_cb = sme_stop_roaming; msg->csr_roam_auth_event_handle_cb = csr_roam_auth_offload_callback; + msg->csr_roam_pmkid_req_cb = csr_roam_pmkid_req_callback; status = u_mac_post_ctrl_msg(mac_handle, (tSirMbMsg *)msg); if (QDF_IS_STATUS_ERROR(status)) { diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 644ccb5ebeb4..823d6f345db2 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -17406,6 +17406,72 @@ csr_update_roam_scan_offload_request(struct mac_context *mac_ctx, req_buf->roaming_scan_policy = mac_ctx->mlme_cfg->lfr.roaming_scan_policy; } + +#ifdef WLAN_FEATURE_FIPS +QDF_STATUS +csr_process_roam_pmkid_req_callback(struct mac_context *mac_ctx, + uint8_t vdev_id, + struct roam_pmkid_req_event *src_lst) +{ + struct csr_roam_info *roam_info; + struct csr_roam_session *session = CSR_GET_SESSION(mac_ctx, vdev_id); + struct qdf_mac_addr *dst_list; + QDF_STATUS status; + uint32_t num_entries, i; + + if (!session) + return QDF_STATUS_E_NULL_VALUE; + + roam_info = qdf_mem_malloc(sizeof(*roam_info)); + if (!roam_info) + return QDF_STATUS_E_NOMEM; + + num_entries = src_lst->num_entries; + for (i = 0; i < num_entries; i++) { + dst_list = &src_lst->ap_bssid[i]; + qdf_copy_macaddr(&roam_info->bssid, dst_list); + + status = csr_roam_call_callback(mac_ctx, vdev_id, roam_info, + 0, eCSR_ROAM_FIPS_PMK_REQUEST, + eCSR_ROAM_RESULT_NONE); + if (QDF_IS_STATUS_ERROR(status)) { + sme_err("%s: Trigger pmkid fallback failed", __func__); + qdf_mem_free(roam_info); + return status; + } + } + qdf_mem_free(roam_info); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +csr_roam_pmkid_req_callback(uint8_t vdev_id, + struct roam_pmkid_req_event *src_lst) +{ + QDF_STATUS status; + struct mac_context *mac_ctx; + + mac_ctx = cds_get_context(QDF_MODULE_ID_PE); + if (!mac_ctx) { + sme_err("%s: NULL mac ptr", __func__); + QDF_ASSERT(0); + return -EINVAL; + } + + status = sme_acquire_global_lock(&mac_ctx->sme); + if (!QDF_IS_STATUS_SUCCESS(status)) { + sme_err("%s: Locking failed, bailing out", __func__); + return status; + } + + status = csr_process_roam_pmkid_req_callback(mac_ctx, vdev_id, + src_lst); + sme_release_global_lock(&mac_ctx->sme); + + return status; +} +#endif /* WLAN_FEATURE_FIPS */ #else static inline void csr_update_roam_scan_offload_request(struct mac_context *mac_ctx, diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index a4f49fcd5a15..97db4b1af71a 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -302,6 +302,7 @@ const char *get_e_roam_cmd_status_str(eRoamCmdStatus val) CASE_RETURN_STR(eCSR_ROAM_NAPI_OFF); CASE_RETURN_STR(eCSR_ROAM_CHANNEL_COMPLETE_IND); CASE_RETURN_STR(eCSR_ROAM_SAE_COMPUTE); + CASE_RETURN_STR(eCSR_ROAM_FIPS_PMK_REQUEST); default: return "unknown"; } diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 7a1f5ade99c0..1955dd659ad3 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -1088,6 +1088,8 @@ typedef struct { uint8_t vdev_id, uint8_t *deauth_disassoc_frame, uint16_t deauth_disassoc_frame_len); + QDF_STATUS (*csr_roam_pmkid_req_cb)(uint8_t vdev_id, + struct roam_pmkid_req_event *bss_list); qdf_wake_lock_t wmi_cmd_rsp_wake_lock; qdf_runtime_lock_t wmi_cmd_rsp_runtime_lock; qdf_runtime_lock_t sap_prevent_runtime_pm_lock; diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h index 7443a07cce7a..0ee02146abb7 100644 --- a/core/wma/inc/wma_if.h +++ b/core/wma/inc/wma_if.h @@ -790,4 +790,14 @@ struct roam_blacklist_event { struct roam_blacklist_timeout roam_blacklist[]; }; +/* + * struct roam_pmkid_req_event - Pmkid event with entries destination structure + * @num_entries: total entries sent over the event + * @ap_bssid: bssid list + */ +struct roam_pmkid_req_event { + uint32_t num_entries; + struct qdf_mac_addr ap_bssid[]; +}; + #endif /* _HALMSGAPI_H_ */ diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 80733b73c8d5..df5158d00710 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -186,6 +186,34 @@ void wma_process_roam_synch_fail(WMA_HANDLE handle, int wma_roam_synch_event_handler(void *handle, uint8_t *event, uint32_t len); +#ifdef WLAN_FEATURE_FIPS +/** + * wma_register_pmkid_req_event_handler() - Register pmkid request event handler + * @wma_handle: wma_handle + * + * This function register pmkid request event handler. + */ +void wma_register_pmkid_req_event_handler(tp_wma_handle wma_handle); + +/** + * wma_roam_pmkid_request_event_handler() - Handles roam pmkid request event + * @handle: wma_handle + * @event: pmkid request event data pointer + * @len: length of the data + * + * Handles pmkid request event from firmware which is triggered after roam + * candidate selection. + */ +int wma_roam_pmkid_request_event_handler(void *handle, + uint8_t *event, + uint32_t len); +#else +static inline void +wma_register_pmkid_req_event_handler(tp_wma_handle wma_handle) +{ +} +#endif /* WLAN_FEATURE_FIPS */ + /** * wma_roam_auth_offload_event_handler() - Handle LFR-3.0 Roam authentication * offload event. diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h index 820ca40c0df0..6695b868628e 100644 --- a/core/wma/inc/wma_types.h +++ b/core/wma/inc/wma_types.h @@ -733,7 +733,9 @@ QDF_STATUS wma_register_roaming_callbacks( QDF_STATUS (*pe_disconnect_cb) (struct mac_context *mac, uint8_t vdev_id, uint8_t *deauth_disassoc_frame, - uint16_t deauth_disassoc_frame_len)); + uint16_t deauth_disassoc_frame_len), + QDF_STATUS (*csr_roam_pmkid_req_cb)(uint8_t vdev_id, + struct roam_pmkid_req_event *bss_list)); #else static inline QDF_STATUS wma_register_roaming_callbacks( QDF_STATUS (*csr_roam_synch_cb)(struct mac_context *mac, @@ -751,7 +753,9 @@ static inline QDF_STATUS wma_register_roaming_callbacks( QDF_STATUS (*pe_disconnect_cb) (struct mac_context *mac, uint8_t vdev_id, uint8_t *deauth_disassoc_frame, - uint16_t deauth_disassoc_frame_len)) + uint16_t deauth_disassoc_frame_len), + QDF_STATUS (*csr_roam_pmkid_req_cb)(uint8_t vdev_id, + struct roam_pmkid_req_event *bss_list)) { return QDF_STATUS_E_NOSUPPORT; } diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 3d6d17c0432e..25c27fbbdcd2 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -3259,6 +3259,8 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, wmi_roam_stats_event_id, wma_roam_stats_event_handler, WMA_RX_SERIALIZER_CTX); + + wma_register_pmkid_req_event_handler(wma_handle); #endif /* WLAN_FEATURE_ROAM_OFFLOAD */ wmi_unified_register_event_handler(wma_handle->wmi_handle, wmi_rssi_breach_event_id, diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 9c7e74490afe..83bf6742c755 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -3815,6 +3815,7 @@ QDF_STATUS wma_de_register_mgmt_frm_client(void) * @csr_roam_synch_cb: CSR roam synch callback routine pointer * @pe_roam_synch_cb: PE roam synch callback routine pointer * @csr_roam_auth_event_handle_cb: CSR callback routine pointer + * @csr_roam_pmkid_req_cb: CSR roam pmkid callback routine pointer * * Register the SME and PE callback routines with WMA for * handling roaming @@ -3836,7 +3837,9 @@ QDF_STATUS wma_register_roaming_callbacks( QDF_STATUS (*pe_disconnect_cb) (struct mac_context *mac, uint8_t vdev_id, uint8_t *deauth_disassoc_frame, - uint16_t deauth_disassoc_frame_len)) + uint16_t deauth_disassoc_frame_len), + QDF_STATUS (*csr_roam_pmkid_req_cb)(uint8_t vdev_id, + struct roam_pmkid_req_event *bss_list)) { tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); @@ -3850,6 +3853,8 @@ QDF_STATUS wma_register_roaming_callbacks( wma->pe_roam_synch_cb = pe_roam_synch_cb; wma->pe_disconnect_cb = pe_disconnect_cb; WMA_LOGD("Registered roam synch callbacks with WMA successfully"); + + wma->csr_roam_pmkid_req_cb = csr_roam_pmkid_req_cb; return QDF_STATUS_SUCCESS; } #endif diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index 2c79de51ad07..bbea886fbee2 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -6389,6 +6389,104 @@ QDF_STATUS wma_set_roam_triggers(tp_wma_handle wma, return wmi_unified_set_roam_triggers(wma->wmi_handle, triggers); } +#ifdef WLAN_FEATURE_FIPS +void wma_register_pmkid_req_event_handler(tp_wma_handle wma_handle) +{ + if (!wma_handle) { + wma_err("%s: pmkid req wma_handle is NULL", __func__); + return; + } + + wmi_unified_register_event_handler(wma_handle->wmi_handle, + wmi_roam_pmkid_request_event_id, + wma_roam_pmkid_request_event_handler, + WMA_RX_SERIALIZER_CTX); +} + +int wma_roam_pmkid_request_event_handler(void *handle, uint8_t *event, + uint32_t len) +{ + WMI_ROAM_PMKID_REQUEST_EVENTID_param_tlvs *param_buf; + wmi_roam_pmkid_request_event_fixed_param *roam_pmkid_req_ev; + wmi_roam_pmkid_request_tlv_param *src_list; + tp_wma_handle wma = (tp_wma_handle)handle; + struct roam_pmkid_req_event *dst_list; + struct qdf_mac_addr *roam_bsslist; + uint32_t num_entries, i; + QDF_STATUS status; + + if (!event) { + wma_err("%s: received null event from target", __func__); + return -EINVAL; + } + + param_buf = (WMI_ROAM_PMKID_REQUEST_EVENTID_param_tlvs *)event; + if (!param_buf) { + wma_err("%s: received null buf from target", __func__); + return -EINVAL; + } + + roam_pmkid_req_ev = param_buf->fixed_param; + if (!roam_pmkid_req_ev) { + wma_err("%s: received null event data from target", __func__); + return -EINVAL; + } + + if (roam_pmkid_req_ev->vdev_id >= wma->max_bssid) { + wma_err("%s: received invalid vdev_id %d", + __func__, roam_pmkid_req_ev->vdev_id); + return -EINVAL; + } + + num_entries = param_buf->num_pmkid_request; + if (num_entries > MAX_RSSI_AVOID_BSSID_LIST) { + wma_err("%s: num bssid entries:%d exceeds maximum value", + __func__, num_entries); + return -EINVAL; + } + + src_list = param_buf->pmkid_request; + if (len < (sizeof(*roam_pmkid_req_ev) + + (num_entries * sizeof(*src_list)))) { + wma_err("%s: Invalid length:%d", __func__, len); + return -EINVAL; + } + + dst_list = qdf_mem_malloc(sizeof(struct roam_pmkid_req_event) + + (sizeof(struct qdf_mac_addr) * num_entries)); + if (!dst_list) + return -ENOMEM; + + for (i = 0; i < num_entries; i++) { + roam_bsslist = &dst_list->ap_bssid[i]; + WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_list->bssid, + roam_bsslist->bytes); + if (qdf_is_macaddr_zero(roam_bsslist) || + qdf_is_macaddr_broadcast(roam_bsslist) || + qdf_is_macaddr_group(roam_bsslist)) { + wma_err("%s: Invalid bssid", __func__); + qdf_mem_free(dst_list); + return -EINVAL; + } + WMA_LOGD("%s:Received pmkid fallback for bssid: %pM vdev_id:%d", + __func__, roam_bsslist->bytes, + roam_pmkid_req_ev->vdev_id); + src_list++; + } + dst_list->num_entries = num_entries; + + status = wma->csr_roam_pmkid_req_cb(roam_pmkid_req_ev->vdev_id, + dst_list); + if (QDF_IS_STATUS_ERROR(status)) { + wma_err("%s: Pmkid request failed", __func__); + qdf_mem_free(dst_list); + return -EINVAL; + } + + qdf_mem_free(dst_list); + return 0; +} +#endif /* WLAN_FEATURE_FIPS */ #else inline QDF_STATUS wma_set_roam_triggers(tp_wma_handle wma, struct roam_triggers *triggers)