From 7a7163bac75034fdff703d2cecd93ba90f0c1ddb Mon Sep 17 00:00:00 2001 From: Pragaspathi Thilagaraj Date: Sun, 14 Jul 2019 22:47:09 +0530 Subject: [PATCH] qcacld-3.0: Add support for wpa3 roaming authentication offload Firmware offloads WPA3 SAE authentication to host due to the crypto library availability limitation. Once the roam candidate selection is done in the firmware, firmware sends the WMI_ROAM_PREAUTH_START_EVENTID. Once this event is received, the host driver triggers the SAE. Add support to offload the SAE authentication from firmware to wpa_supplicant. Change-Id: Ie3a9e731194e1edfcd9f33ef0d601767b9485d46 CRs-Fixed: 2490201 --- core/mac/inc/sir_api.h | 3 ++ core/mac/src/pe/lim/lim_api.c | 1 + core/sme/inc/csr_neighbor_roam.h | 42 +++++++++++++++++++++ core/sme/src/common/sme_api.c | 2 + core/sme/src/csr/csr_api_roam.c | 57 +++++++++++++++++++++++++++++ core/wma/inc/wma.h | 5 +++ core/wma/inc/wma_internal.h | 13 +++++++ core/wma/inc/wma_types.h | 8 ++++ core/wma/src/wma_main.c | 5 +++ core/wma/src/wma_mgmt.c | 5 +++ core/wma/src/wma_scan_roam.c | 63 ++++++++++++++++++++++++++++++++ 11 files changed, 204 insertions(+) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 129d1bd3002c..66d0e40a6459 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -372,6 +372,9 @@ struct sme_ready_req { uint16_t messageType; /* eWNI_SME_SYS_READY_IND */ uint16_t length; void *csr_roam_synch_cb; + QDF_STATUS (*csr_roam_auth_event_handle_cb)(struct mac_context *mac, + uint8_t vdev_id, + struct qdf_mac_addr bssid); void *pe_roam_synch_cb; void *stop_roaming_cb; QDF_STATUS (*sme_msg_cb)(struct mac_context *mac, diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index d1a15ade0f9d..f4fd99a2a7d3 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -1316,6 +1316,7 @@ void pe_register_callbacks_with_wma(struct mac_context *mac, status = wma_register_roaming_callbacks( 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); if (status != QDF_STATUS_SUCCESS) diff --git a/core/sme/inc/csr_neighbor_roam.h b/core/sme/inc/csr_neighbor_roam.h index 0130688ce258..5f5032f30c7c 100644 --- a/core/sme/inc/csr_neighbor_roam.h +++ b/core/sme/inc/csr_neighbor_roam.h @@ -308,6 +308,32 @@ QDF_STATUS csr_roam_read_tsf(struct mac_context *mac, uint8_t *pTimestamp, QDF_STATUS csr_roam_synch_callback(struct mac_context *mac, struct roam_offload_synch_ind *roam_synch_data, struct bss_description *bss_desc_ptr, enum sir_roam_op_code reason); + +/** + * csr_roam_auth_offload_callback() - Registered CSR Callback function to handle + * WPA3 roam pre-auth event from firmware. + * @mac_ctx: Global mac context pointer + * @vdev_id: Vdev id + * @bssid: candidate AP bssid + */ +QDF_STATUS +csr_roam_auth_offload_callback(struct mac_context *mac_ctx, + uint8_t vdev_id, + struct qdf_mac_addr bssid); + +/** + * csr_process_roam_auth_offload_callback() - API to trigger the + * WPA3 pre-auth event for candidate AP received from firmware. + * @vdev_id: vdev id + * @roam_bssid: Candidate BSSID to roam + * + * This function calls the hdd_sme_roam_callback with reason + * eCSR_ROAM_SAE_COMPUTE to trigger SAE auth to supplicant. + */ +QDF_STATUS +csr_process_roam_auth_offload_callback(struct mac_context *mac_ctx, + uint8_t vdev_id, + struct qdf_mac_addr roam_bssid); #else static inline QDF_STATUS csr_roam_synch_callback(struct mac_context *mac, struct roam_offload_synch_ind *roam_synch_data, @@ -315,6 +341,22 @@ static inline QDF_STATUS csr_roam_synch_callback(struct mac_context *mac, { return QDF_STATUS_E_NOSUPPORT; } + +static inline QDF_STATUS +csr_roam_auth_offload_callback(struct mac_context *mac_ctx, + uint8_t vdev_id, + struct qdf_mac_addr bssid) +{ + return QDF_STATUS_E_NOSUPPORT; +} + +static inline QDF_STATUS +csr_process_roam_auth_offload_callback(struct mac_context *mac_ctx, + uint8_t vdev_id, + struct qdf_mac_addr roam_bssid) +{ + 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 affe4ed530fd..a2408ca64e3c 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -1085,6 +1085,8 @@ QDF_STATUS sme_hdd_ready_ind(mac_handle_t mac_handle) msg->csr_roam_synch_cb = csr_roam_synch_callback; msg->sme_msg_cb = sme_process_msg_callback; msg->stop_roaming_cb = sme_stop_roaming; + msg->csr_roam_auth_event_handle_cb = + csr_roam_auth_offload_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 cd3916036ed8..26b4db714009 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -21474,6 +21474,63 @@ csr_roam_synch_callback(struct mac_context *mac_ctx, return status; } + +QDF_STATUS +csr_process_roam_auth_offload_callback(struct mac_context *mac_ctx, + uint8_t vdev_id, + struct qdf_mac_addr roam_bssid) +{ + struct csr_roam_info *roam_info; + struct sir_sae_info sae_info; + struct csr_roam_session *session = CSR_GET_SESSION(mac_ctx, vdev_id); + + if (!session) { + sme_err("WPA3 Preauth event with invalid session id:%d", + vdev_id); + return QDF_STATUS_E_FAILURE; + } + + roam_info = qdf_mem_malloc(sizeof(*roam_info)); + if (!roam_info) + return QDF_STATUS_E_FAILURE; + + sae_info.msg_len = sizeof(sae_info); + sae_info.vdev_id = vdev_id; + + sae_info.ssid.length = session->connectedProfile.SSID.length; + qdf_mem_copy(sae_info.ssid.ssId, session->connectedProfile.SSID.ssId, + sae_info.ssid.length); + + qdf_mem_copy(sae_info.peer_mac_addr.bytes, + roam_bssid.bytes, QDF_MAC_ADDR_SIZE); + + roam_info->sae_info = &sae_info; + + csr_roam_call_callback(mac_ctx, vdev_id, roam_info, 0, + eCSR_ROAM_SAE_COMPUTE, eCSR_ROAM_RESULT_NONE); + + qdf_mem_free(roam_info); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +csr_roam_auth_offload_callback(struct mac_context *mac_ctx, + uint8_t vdev_id, struct qdf_mac_addr bssid) +{ + QDF_STATUS status; + + status = sme_acquire_global_lock(&mac_ctx->sme); + if (!QDF_IS_STATUS_SUCCESS(status)) + return status; + + status = csr_process_roam_auth_offload_callback(mac_ctx, vdev_id, bssid); + + sme_release_global_lock(&mac_ctx->sme); + + return status; + +} #endif QDF_STATUS csr_update_owe_info(struct mac_context *mac, diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index a11072f3553f..10b0731d328d 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -998,6 +998,8 @@ struct wma_wlm_stats_data { * event in the serialized MC thread context with a timer. * @csr_roam_synch_cb: CSR callback for firmware Roam Sync events * @pe_roam_synch_cb: pe callback for firmware Roam Sync events + * @csr_roam_auth_event_handle_cb: CSR callback for target authentication + * offload event. * @wmi_cmd_rsp_wake_lock: wmi command response wake lock * @wmi_cmd_rsp_runtime_lock: wmi command response bus lock * @active_uc_apf_mode: Setting that determines how APF is applied in @@ -1123,6 +1125,9 @@ typedef struct { struct roam_offload_synch_ind *roam_synch_data, struct bss_description *bss_desc_ptr, enum sir_roam_op_code reason); + QDF_STATUS (*csr_roam_auth_event_handle_cb)(struct mac_context *mac, + uint8_t vdev_id, + struct qdf_mac_addr bssid); QDF_STATUS (*pe_roam_synch_cb)(struct mac_context *mac, struct roam_offload_synch_ind *roam_synch_data, struct bss_description *bss_desc_ptr, diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 5d2be51828f0..5e77e61653fa 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -158,6 +158,19 @@ void wma_process_roam_synch_fail(WMA_HANDLE handle, int wma_roam_synch_event_handler(void *handle, uint8_t *event, uint32_t len); +/** + * wma_roam_auth_offload_event_handler() - Handle LFR-3.0 Roam authentication + * offload event. + * @handle: wma_handle + * @event: rso auth offload event data pointer + * @len: length of the data + * + * Handles roam authentication offload event from firmware which is triggered + * after roam candidate selection. + */ +int wma_roam_auth_offload_event_handler(WMA_HANDLE handle, uint8_t *event, + uint32_t len); + /** * wma_mlme_roam_synch_event_handler_cb() - roam synch event handler * @handle: wma handle diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h index 84b9adefa226..9e35557d7bf9 100644 --- a/core/wma/inc/wma_types.h +++ b/core/wma/inc/wma_types.h @@ -718,6 +718,10 @@ QDF_STATUS wma_register_roaming_callbacks( struct roam_offload_synch_ind *roam_synch_data, struct bss_description *bss_desc_ptr, enum sir_roam_op_code reason), + QDF_STATUS (*csr_roam_auth_event_handle_cb)( + struct mac_context *mac, + uint8_t vdev_id, + struct qdf_mac_addr bssid), QDF_STATUS (*pe_roam_synch_cb)(struct mac_context *mac, struct roam_offload_synch_ind *roam_synch_data, struct bss_description *bss_desc_ptr, @@ -732,6 +736,10 @@ static inline QDF_STATUS wma_register_roaming_callbacks( struct roam_offload_synch_ind *roam_synch_data, struct bss_description *bss_desc_ptr, enum sir_roam_op_code reason), + QDF_STATUS (*csr_roam_auth_event_handle_cb)( + struct mac_context *mac, + uint8_t vdev_id, + struct qdf_mac_addr bssid), QDF_STATUS (*pe_roam_synch_cb)(struct mac_context *mac, struct roam_offload_synch_ind *roam_synch_data, struct bss_description *bss_desc_ptr, diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 80935581d92c..86d205a8d52b 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -3540,6 +3540,11 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, wmi_roam_synch_frame_event_id, wma_roam_synch_frame_event_handler, WMA_RX_SERIALIZER_CTX); + + wmi_unified_register_event_handler(wma_handle->wmi_handle, + wmi_roam_auth_offload_event_id, + wma_roam_auth_offload_event_handler, + WMA_RX_SERIALIZER_CTX); #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 65a0b1d02fa8..3e9df0060be6 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -4432,6 +4432,7 @@ QDF_STATUS wma_de_register_mgmt_frm_client(void) * wma_register_roaming_callbacks() - Register roaming callbacks * @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 * * Register the SME and PE callback routines with WMA for * handling roaming @@ -4443,6 +4444,9 @@ QDF_STATUS wma_register_roaming_callbacks( struct roam_offload_synch_ind *roam_synch_data, struct bss_description *bss_desc_ptr, enum sir_roam_op_code reason), + QDF_STATUS (*csr_roam_auth_event_handle_cb)(struct mac_context *mac, + uint8_t vdev_id, + struct qdf_mac_addr bssid), QDF_STATUS (*pe_roam_synch_cb)(struct mac_context *mac, struct roam_offload_synch_ind *roam_synch_data, struct bss_description *bss_desc_ptr, @@ -4460,6 +4464,7 @@ QDF_STATUS wma_register_roaming_callbacks( return QDF_STATUS_E_FAILURE; } wma->csr_roam_synch_cb = csr_roam_synch_cb; + wma->csr_roam_auth_event_handle_cb = csr_roam_auth_event_handle_cb; 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"); diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index ed92a443865b..c5fd386688f7 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -3126,6 +3126,69 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event, return 0; } +int wma_roam_auth_offload_event_handler(WMA_HANDLE handle, uint8_t *event, + uint32_t len) +{ + QDF_STATUS status; + tp_wma_handle wma = (tp_wma_handle) handle; + struct mac_context *mac_ctx; + wmi_roam_preauth_start_event_fixed_param *rso_auth_start_ev; + WMI_ROAM_PREAUTH_START_EVENTID_param_tlvs *param_buf; + struct qdf_mac_addr ap_bssid; + uint8_t vdev_id; + + if (!event) { + wma_err_rl("received null event from target"); + return -EINVAL; + } + + param_buf = (WMI_ROAM_PREAUTH_START_EVENTID_param_tlvs *) event; + if (!param_buf) { + wma_err_rl("received null buf from target"); + return -EINVAL; + } + + rso_auth_start_ev = param_buf->fixed_param; + if (!rso_auth_start_ev) { + wma_err_rl("received null event data from target"); + return -EINVAL; + } + + if (rso_auth_start_ev->vdev_id > wma->max_bssid) { + wma_err_rl("received invalid vdev_id %d", + rso_auth_start_ev->vdev_id); + return -EINVAL; + } + + mac_ctx = cds_get_context(QDF_MODULE_ID_PE); + if (!mac_ctx) { + wma_err("NULL mac ptr"); + QDF_ASSERT(0); + return -EINVAL; + } + + WMI_MAC_ADDR_TO_CHAR_ARRAY(&rso_auth_start_ev->candidate_ap_bssid, + ap_bssid.bytes); + if (qdf_is_macaddr_zero(&ap_bssid) || + qdf_is_macaddr_broadcast(&ap_bssid) || + qdf_is_macaddr_group(&ap_bssid)) { + wma_err_rl("Invalid bssid"); + return -EINVAL; + } + + vdev_id = rso_auth_start_ev->vdev_id; + wma_debug("Received Roam auth offload event for bss:%pM vdev_id:%d", + ap_bssid.bytes, vdev_id); + + status = wma->csr_roam_auth_event_handle_cb(mac_ctx, vdev_id, ap_bssid); + if (QDF_IS_STATUS_ERROR(status)) { + wma_err_rl("Trigger pre-auth failed"); + return -EINVAL; + } + + return 0; +} + #define RSN_CAPS_SHIFT 16 /** * wma_roam_scan_fill_self_caps() - fill capabilities