|
@@ -2773,15 +2773,121 @@ static inline void fils_convert_assoc_rsp_frame2_struct(tDot11fAssocResponse
|
|
|
{ }
|
|
|
#endif
|
|
|
|
|
|
+QDF_STATUS wlan_parse_ftie_sha384(uint8_t *frame, uint32_t frame_len,
|
|
|
+ struct sSirAssocRsp *assoc_rsp)
|
|
|
+{
|
|
|
+ const uint8_t *ie, *ie_end, *pos;
|
|
|
+ uint8_t ie_len;
|
|
|
+ struct wlan_sha384_ftinfo_subelem *ft_subelem;
|
|
|
+
|
|
|
+ ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_FTINFO, frame, frame_len);
|
|
|
+ if (!ie) {
|
|
|
+ pe_err("FT IE not present");
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!ie[1]) {
|
|
|
+ pe_err("FT IE length is zero");
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
+ }
|
|
|
+
|
|
|
+ ie_len = ie[1];
|
|
|
+ if (ie_len < sizeof(struct wlan_sha384_ftinfo)) {
|
|
|
+ pe_err("Invalid FTIE len:%d", ie_len);
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
+ }
|
|
|
+ pos = ie + 2;
|
|
|
+ qdf_mem_copy(&assoc_rsp->sha384_ft_info, pos,
|
|
|
+ sizeof(struct wlan_sha384_ftinfo));
|
|
|
+ ie_end = ie + ie_len;
|
|
|
+ pos += sizeof(struct wlan_sha384_ftinfo);
|
|
|
+ ft_subelem = &assoc_rsp->sha384_ft_subelem;
|
|
|
+ qdf_mem_zero(ft_subelem, sizeof(*ft_subelem));
|
|
|
+ while (ie_end - pos >= 2) {
|
|
|
+ uint8_t id, len;
|
|
|
+
|
|
|
+ id = *pos++;
|
|
|
+ len = *pos++;
|
|
|
+ if (len < 1 ||
|
|
|
+ (len > (ie_end - pos))) {
|
|
|
+ pe_err("Invalid FT subelem length %d", len);
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (id) {
|
|
|
+ case FTIE_SUBELEM_R1KH_ID:
|
|
|
+ if (len != FTIE_R1KH_LEN) {
|
|
|
+ pe_err("Invalid R1KH-ID length: %d",
|
|
|
+ len);
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
+ }
|
|
|
+ ft_subelem->r1kh_id.present = 1;
|
|
|
+ qdf_mem_copy(ft_subelem->r1kh_id.PMK_R1_ID,
|
|
|
+ pos, FTIE_R1KH_LEN);
|
|
|
+ break;
|
|
|
+ case FTIE_SUBELEM_GTK:
|
|
|
+ if (ft_subelem->gtk) {
|
|
|
+ qdf_mem_zero(ft_subelem->gtk,
|
|
|
+ ft_subelem->gtk_len);
|
|
|
+ ft_subelem->gtk_len = 0;
|
|
|
+ qdf_mem_free(ft_subelem->gtk);
|
|
|
+ }
|
|
|
+ ft_subelem->gtk = qdf_mem_malloc(len);
|
|
|
+ if (!ft_subelem->gtk)
|
|
|
+ return QDF_STATUS_E_NOMEM;
|
|
|
+
|
|
|
+ qdf_mem_copy(ft_subelem->gtk, pos, len);
|
|
|
+ ft_subelem->gtk_len = len;
|
|
|
+ break;
|
|
|
+ case FTIE_SUBELEM_R0KH_ID:
|
|
|
+ if (len < 1 || len > FTIE_R0KH_MAX_LEN) {
|
|
|
+ pe_err("Invalid R0KH-ID length: %d",
|
|
|
+ len);
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
+ }
|
|
|
+ ft_subelem->r0kh_id.present = 1;
|
|
|
+ ft_subelem->r0kh_id.num_PMK_R0_ID = len;
|
|
|
+ qdf_mem_copy(ft_subelem->r0kh_id.PMK_R0_ID,
|
|
|
+ pos, len);
|
|
|
+ break;
|
|
|
+ case FTIE_SUBELEM_IGTK:
|
|
|
+ if (ft_subelem->igtk) {
|
|
|
+ qdf_mem_zero(ft_subelem->igtk,
|
|
|
+ ft_subelem->igtk_len);
|
|
|
+ ft_subelem->igtk_len = 0;
|
|
|
+ qdf_mem_free(ft_subelem->igtk);
|
|
|
+ }
|
|
|
+ ft_subelem->igtk = qdf_mem_malloc(len);
|
|
|
+ if (!ft_subelem->igtk)
|
|
|
+ return QDF_STATUS_E_NOMEM;
|
|
|
+
|
|
|
+ qdf_mem_copy(ft_subelem->igtk, pos, len);
|
|
|
+ ft_subelem->igtk_len = len;
|
|
|
+
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ pe_debug("Unknown subelem id %d len:%d",
|
|
|
+ id, len);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ pos += len;
|
|
|
+ }
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
QDF_STATUS
|
|
|
sir_convert_assoc_resp_frame2_struct(struct mac_context *mac,
|
|
|
- struct pe_session *session_entry,
|
|
|
- uint8_t *pFrame, uint32_t nFrame,
|
|
|
- tpSirAssocRsp pAssocRsp)
|
|
|
+ struct pe_session *session_entry,
|
|
|
+ uint8_t *frame, uint32_t frame_len,
|
|
|
+ tpSirAssocRsp pAssocRsp)
|
|
|
{
|
|
|
tDot11fAssocResponse *ar;
|
|
|
- uint32_t status;
|
|
|
+ enum ani_akm_type auth_type;
|
|
|
+ uint32_t status, ie_len;
|
|
|
+ QDF_STATUS qdf_status;
|
|
|
uint8_t cnt = 0;
|
|
|
+ bool sha384_akm;
|
|
|
+ uint8_t *ie_ptr;
|
|
|
|
|
|
ar = qdf_mem_malloc(sizeof(*ar));
|
|
|
if (!ar)
|
|
@@ -2790,7 +2896,7 @@ sir_convert_assoc_resp_frame2_struct(struct mac_context *mac,
|
|
|
/* decrypt the cipher text using AEAD decryption */
|
|
|
if (lim_is_fils_connection(session_entry)) {
|
|
|
status = aead_decrypt_assoc_rsp(mac, session_entry,
|
|
|
- ar, pFrame, &nFrame);
|
|
|
+ ar, frame, &frame_len);
|
|
|
if (!QDF_IS_STATUS_SUCCESS(status)) {
|
|
|
pe_err("FILS assoc rsp AEAD decrypt fails");
|
|
|
qdf_mem_free(ar);
|
|
@@ -2798,13 +2904,12 @@ sir_convert_assoc_resp_frame2_struct(struct mac_context *mac,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- status = dot11f_parse_assoc_response(mac, pFrame, nFrame, ar, false);
|
|
|
+ status = dot11f_parse_assoc_response(mac, frame, frame_len, ar, false);
|
|
|
if (QDF_STATUS_SUCCESS != status) {
|
|
|
qdf_mem_free(ar);
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/* Capabilities */
|
|
|
pAssocRsp->capabilityInfo.ess = ar->Capabilities.ess;
|
|
|
pAssocRsp->capabilityInfo.ibss = ar->Capabilities.ibss;
|
|
@@ -2889,13 +2994,39 @@ sir_convert_assoc_resp_frame2_struct(struct mac_context *mac,
|
|
|
(unsigned int)pAssocRsp->mdie[2]);
|
|
|
}
|
|
|
|
|
|
- if (ar->FTInfo.present) {
|
|
|
- pe_debug("FT Info present %d %d %d",
|
|
|
- ar->FTInfo.R0KH_ID.num_PMK_R0_ID,
|
|
|
- ar->FTInfo.R0KH_ID.present, ar->FTInfo.R1KH_ID.present);
|
|
|
+ /*
|
|
|
+ * If the connection is based on SHA384 AKM suite,
|
|
|
+ * then the length of MIC is 24 bytes, but frame parser
|
|
|
+ * has FTIE MIC of 16 bytes only. This results in parsing FTIE
|
|
|
+ * failure and R0KH and R1KH are not sent to firmware over RSO
|
|
|
+ * command. Frame parser doesn't have
|
|
|
+ * info on the connected AKM. So parse the FTIE again if
|
|
|
+ * AKM is sha384 based and extract the R0KH and R1KH using the new
|
|
|
+ * parsing logic.
|
|
|
+ */
|
|
|
+ auth_type = session_entry->connected_akm;
|
|
|
+ sha384_akm = lim_is_sha384_akm(auth_type);
|
|
|
+ if (sha384_akm) {
|
|
|
+ ie_ptr = frame + FIXED_PARAM_OFFSET_ASSOC_RSP;
|
|
|
+ ie_len = frame_len - FIXED_PARAM_OFFSET_ASSOC_RSP;
|
|
|
+ qdf_status = wlan_parse_ftie_sha384(ie_ptr, ie_len, pAssocRsp);
|
|
|
+ if (QDF_IS_STATUS_ERROR(qdf_status)) {
|
|
|
+ pe_err("FT IE parsing failed status:%d", status);
|
|
|
+ } else {
|
|
|
+ pe_debug("FT: R0KH present:%d len:%d R1KH present%d",
|
|
|
+ pAssocRsp->sha384_ft_subelem.r0kh_id.present,
|
|
|
+ pAssocRsp->sha384_ft_subelem.r0kh_id.num_PMK_R0_ID,
|
|
|
+ pAssocRsp->sha384_ft_subelem.r1kh_id.present);
|
|
|
+ ar->FTInfo.present = false;
|
|
|
+ }
|
|
|
+ } else if (ar->FTInfo.present) {
|
|
|
+ pe_debug("FT: R0KH present:%d, len:%d R1KH present:%d",
|
|
|
+ ar->FTInfo.R0KH_ID.present,
|
|
|
+ ar->FTInfo.R0KH_ID.num_PMK_R0_ID,
|
|
|
+ ar->FTInfo.R1KH_ID.present);
|
|
|
pAssocRsp->ftinfoPresent = 1;
|
|
|
qdf_mem_copy(&pAssocRsp->FTInfo, &ar->FTInfo,
|
|
|
- sizeof(tDot11fIEFTInfo));
|
|
|
+ sizeof(tDot11fIEFTInfo));
|
|
|
}
|
|
|
|
|
|
if (ar->num_RICDataDesc && ar->num_RICDataDesc <= 2) {
|