From 6a87278fe74ff68ea2ed81255bdd0c535978b8eb Mon Sep 17 00:00:00 2001 From: Srikanth Marepalli Date: Fri, 24 Jan 2020 18:12:05 +0530 Subject: [PATCH] qcacld-3.0: Add support for pmkid generation for FIPS Add support to fallback the PMKID generation from firmware to wpa_supplicant. In FIPS Enabled case, for roaming Firmware sends PMKID request to host as firmware is not supposed to do crypto functionality with FIPS enabled. Once the roam candidate selection is done in the firmware, it sends the WMI_ROAM_PMKID_REQUEST_EVENTID. After receiving this event the host driver triggers an event to wpa_supplicant using NL80211_CMD_PMKSA_CANDIDATE for PMKID generation. Then wpa_supplicant responds with PMKID to host using NL80211_CMD_SET_PMKSA. And host updates the wmi pmk cache and indicates the firmware via WMI_PDEV_UPDATE_PMK_CACHE_CMDID wmi command. Change-Id: I7d33a2b92f97260fa5a7e742b6f877adc7eced55 CRs-Fixed: 2512955 --- core/hdd/src/wlan_hdd_assoc.c | 6 ++ core/mac/inc/sir_api.h | 1 + core/mac/src/pe/lim/lim_api.c | 3 +- core/sme/inc/csr_api.h | 1 + core/sme/inc/csr_neighbor_roam.h | 41 +++++++++++++ core/sme/src/common/sme_api.c | 1 + core/sme/src/csr/csr_api_roam.c | 66 +++++++++++++++++++++ core/sme/src/csr/csr_util.c | 1 + core/wma/inc/wma.h | 2 + core/wma/inc/wma_if.h | 10 ++++ core/wma/inc/wma_internal.h | 28 +++++++++ core/wma/inc/wma_types.h | 8 ++- core/wma/src/wma_main.c | 2 + core/wma/src/wma_mgmt.c | 7 ++- core/wma/src/wma_scan_roam.c | 98 ++++++++++++++++++++++++++++++++ 15 files changed, 271 insertions(+), 4 deletions(-) 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)