qcacld-3.0: Add Support for FILS Association
Adds the following support: 1) Add FILS IE's to assoc request. 2) AEAD encrypt/decrypt the assoc request/response frames for FILS 3) Process/Verify the Assoc response for the FILS params 4) Plumb the Auth keys to firmware after successful FILS assoc 5) Update the user space with Auth key details Change-Id: I57f6319cecdf10e08047b510321b885c3cd711b5 CRs-Fixed: 2030038
This commit is contained in:
parent
7a412e492b
commit
0d5d2c745c
@ -3139,7 +3139,7 @@ static QDF_STATUS hdd_association_completion_handler(hdd_adapter_t *pAdapter,
|
||||
if (pRoamInfo)
|
||||
hdd_connect_result(dev,
|
||||
pRoamInfo->bssid.bytes,
|
||||
NULL, NULL, 0, NULL, 0,
|
||||
pRoamInfo, NULL, 0, NULL, 0,
|
||||
WLAN_STATUS_ASSOC_DENIED_UNSPEC,
|
||||
GFP_KERNEL,
|
||||
connect_timeout,
|
||||
@ -3156,7 +3156,7 @@ static QDF_STATUS hdd_association_completion_handler(hdd_adapter_t *pAdapter,
|
||||
if (pRoamInfo)
|
||||
hdd_connect_result(dev,
|
||||
pRoamInfo->bssid.bytes,
|
||||
NULL, NULL, 0, NULL, 0,
|
||||
pRoamInfo, NULL, 0, NULL, 0,
|
||||
pRoamInfo->reasonCode ?
|
||||
pRoamInfo->reasonCode :
|
||||
WLAN_STATUS_UNSPECIFIED_FAILURE,
|
||||
|
@ -4749,6 +4749,175 @@ static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WLAN_FEATURE_FILS_SK
|
||||
#ifdef CFG80211_CONNECT_DONE
|
||||
#ifdef CFG80211_FILS_SK_OFFLOAD_SUPPORT
|
||||
/**
|
||||
* hdd_populate_fils_params() - Populate FILS keys to connect response
|
||||
* @fils_params: connect response to supplicant
|
||||
* @fils_kek: FILS kek
|
||||
* @fils_kek_len: FILS kek length
|
||||
* @pmk: FILS PMK
|
||||
* @pmk_len: FILS PMK length
|
||||
* @pmkid: PMKID
|
||||
* @fils_seq_num: FILS Seq number
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void hdd_populate_fils_params(struct cfg80211_connect_resp_params
|
||||
*fils_params, const uint8_t *fils_kek,
|
||||
size_t fils_kek_len, const uint8_t *pmk,
|
||||
size_t pmk_len, const uint8_t *pmkid,
|
||||
uint16_t fils_seq_num)
|
||||
{
|
||||
/* Increament seq number to be used for next FILS */
|
||||
fils_params->fils_erp_next_seq_num = fils_seq_num + 1;
|
||||
fils_params->update_erp_next_seq_num = true;
|
||||
fils_params->fils_kek = fils_kek;
|
||||
fils_params->fils_kek_len = fils_kek_len;
|
||||
fils_params->pmk = pmk;
|
||||
fils_params->pmk_len = pmk_len;
|
||||
fils_params->pmkid = pmkid;
|
||||
}
|
||||
#else
|
||||
static inline void hdd_populate_fils_params(struct cfg80211_connect_resp_params
|
||||
*fils_params, const uint8_t
|
||||
*fils_kek, size_t fils_kek_len,
|
||||
const uint8_t *pmk, size_t pmk_len,
|
||||
const uint8_t *pmkid,
|
||||
uint16_t fils_seq_num)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hdd_connect_done() - Wrapper API to call cfg80211_connect_done
|
||||
* @dev: network device
|
||||
* @bssid: bssid to which we want to associate
|
||||
* @bss: cfg80211 bss info
|
||||
* @roam_info: information about connected bss
|
||||
* @req_ie: Request Information Element
|
||||
* @req_ie_len: len of the req IE
|
||||
* @resp_ie: Response IE
|
||||
* @resp_ie_len: len of ht response IE
|
||||
* @status: status
|
||||
* @gfp: allocation flags
|
||||
* @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
|
||||
* @timeout_reason: reason for connect timeout
|
||||
* @roam_fils_params: FILS join response params
|
||||
*
|
||||
* This API is used as wrapper to send FILS key/sequence number
|
||||
* params etc. to supplicant in case of FILS connection
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void hdd_connect_done(struct net_device *dev, const u8 *bssid,
|
||||
struct cfg80211_bss *bss, tCsrRoamInfo *roam_info,
|
||||
const u8 *req_ie, size_t req_ie_len,
|
||||
const u8 *resp_ie, size_t resp_ie_len, u16 status,
|
||||
gfp_t gfp, bool connect_timeout, tSirResultCodes
|
||||
timeout_reason, struct fils_join_rsp_params
|
||||
*roam_fils_params)
|
||||
{
|
||||
struct cfg80211_connect_resp_params fils_params;
|
||||
qdf_mem_zero(&fils_params, sizeof(fils_params));
|
||||
|
||||
if (!roam_fils_params) {
|
||||
fils_params.status = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
} else {
|
||||
fils_params.status = status;
|
||||
fils_params.bssid = bssid;
|
||||
fils_params.timeout_reason = timeout_reason;
|
||||
fils_params.req_ie = req_ie;
|
||||
fils_params.req_ie_len = req_ie_len;
|
||||
fils_params.resp_ie = resp_ie;
|
||||
fils_params.resp_ie_len = resp_ie_len;
|
||||
fils_params.bss = bss;
|
||||
hdd_populate_fils_params(&fils_params, roam_fils_params->kek,
|
||||
roam_fils_params->kek_len,
|
||||
roam_fils_params->fils_pmk,
|
||||
roam_fils_params->fils_pmk_len,
|
||||
roam_fils_params->fils_pmkid,
|
||||
roam_info->fils_seq_num);
|
||||
}
|
||||
hdd_debug("FILS indicate connect status %d seq no %d",
|
||||
fils_params.status,
|
||||
fils_params.fils_erp_next_seq_num);
|
||||
|
||||
cfg80211_connect_done(dev, &fils_params, gfp);
|
||||
|
||||
/* Clear all the FILS key info */
|
||||
if (roam_fils_params && roam_fils_params->fils_pmk)
|
||||
qdf_mem_free(roam_fils_params->fils_pmk);
|
||||
if (roam_fils_params)
|
||||
qdf_mem_free(roam_fils_params);
|
||||
roam_info->fils_join_rsp = NULL;
|
||||
}
|
||||
#else
|
||||
static inline void hdd_connect_done(struct net_device *dev, const u8 *bssid,
|
||||
struct cfg80211_bss *bss, tCsrRoamInfo
|
||||
*roam_info, const u8 *req_ie,
|
||||
size_t req_ie_len, const u8 *resp_ie,
|
||||
size_t resp_ie_len, u16 status, gfp_t gfp,
|
||||
bool connect_timeout, tSirResultCodes
|
||||
timeout_reason, struct fils_join_rsp_params
|
||||
*roam_fils_params)
|
||||
{ }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(CFG80211_CONNECT_DONE) && defined(WLAN_FEATURE_FILS_SK)
|
||||
/**
|
||||
* hdd_fils_update_connect_results() - API to send fils connection status to
|
||||
* supplicant.
|
||||
* @dev: network device
|
||||
* @bssid: bssid to which we want to associate
|
||||
* @bss: cfg80211 bss info
|
||||
* @roam_info: information about connected bss
|
||||
* @req_ie: Request Information Element
|
||||
* @req_ie_len: len of the req IE
|
||||
* @resp_ie: Response IE
|
||||
* @resp_ie_len: len of ht response IE
|
||||
* @status: status
|
||||
* @gfp: allocation flags
|
||||
* @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
|
||||
* @timeout_reason: reason for connect timeout
|
||||
*
|
||||
* The API is a wrapper to send connection status to supplicant
|
||||
*
|
||||
* Return: 0 if success else failure
|
||||
*/
|
||||
static int hdd_fils_update_connect_results(struct net_device *dev,
|
||||
const u8 *bssid,
|
||||
struct cfg80211_bss *bss,
|
||||
tCsrRoamInfo *roam_info, const u8 *req_ie,
|
||||
size_t req_ie_len, const u8 *resp_ie,
|
||||
size_t resp_ie_len, u16 status, gfp_t gfp,
|
||||
bool connect_timeout,
|
||||
tSirResultCodes timeout_reason)
|
||||
{
|
||||
ENTER();
|
||||
if (!roam_info || !roam_info->is_fils_connection)
|
||||
return -EINVAL;
|
||||
|
||||
hdd_connect_done(dev, bssid, bss, roam_info, req_ie, req_ie_len,
|
||||
resp_ie, resp_ie_len, status, gfp, connect_timeout,
|
||||
timeout_reason, roam_info->fils_join_rsp);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline int hdd_fils_update_connect_results(struct net_device *dev,
|
||||
const u8 *bssid,
|
||||
struct cfg80211_bss *bss,
|
||||
tCsrRoamInfo *roam_info, const u8 *req_ie,
|
||||
size_t req_ie_len, const u8 *resp_ie,
|
||||
size_t resp_ie_len, u16 status, gfp_t gfp,
|
||||
bool connect_timeout,
|
||||
tSirResultCodes timeout_reason)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hdd_connect_result() - API to send connection status to supplicant
|
||||
* @dev: network device
|
||||
@ -4796,9 +4965,14 @@ void hdd_connect_result(struct net_device *dev, const u8 *bssid,
|
||||
roam_info->u.pConnectedProfile->SSID.length);
|
||||
}
|
||||
|
||||
hdd_connect_bss(dev, bssid, bss, req_ie,
|
||||
req_ie_len, resp_ie, resp_ie_len,
|
||||
status, gfp, connect_timeout, timeout_reason);
|
||||
if (hdd_fils_update_connect_results(dev, bssid, bss,
|
||||
roam_info, req_ie, req_ie_len, resp_ie,
|
||||
resp_ie_len, status, gfp, connect_timeout,
|
||||
timeout_reason) != 0) {
|
||||
hdd_connect_bss(dev, bssid, bss, req_ie,
|
||||
req_ie_len, resp_ie, resp_ie_len,
|
||||
status, gfp, connect_timeout, timeout_reason);
|
||||
}
|
||||
|
||||
qdf_runtime_pm_allow_suspend(&padapter->connect_rpm_ctx.connect);
|
||||
hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_CONNECT);
|
||||
|
@ -329,6 +329,20 @@ typedef enum eSirResultCodes {
|
||||
eSIR_DONOT_USE_RESULT_CODE = SIR_MAX_ENUM_SIZE
|
||||
} tSirResultCodes;
|
||||
|
||||
#ifdef WLAN_FEATURE_FILS_SK
|
||||
struct fils_join_rsp_params {
|
||||
uint8_t *fils_pmk;
|
||||
uint8_t fils_pmk_len;
|
||||
uint8_t fils_pmkid[PMKID_LEN];
|
||||
uint8_t kek[MAX_KEK_LEN];
|
||||
uint8_t kek_len;
|
||||
uint8_t tk[MAX_TK_LEN];
|
||||
uint8_t tk_len;
|
||||
uint8_t gtk_len;
|
||||
uint8_t gtk[MAX_GTK_LEN];
|
||||
};
|
||||
#endif
|
||||
|
||||
#define RMENABLEDCAP_MAX_LEN 5
|
||||
|
||||
struct rrm_config_param {
|
||||
@ -1295,6 +1309,11 @@ typedef struct sSirSmeJoinRsp {
|
||||
tDot11fIEHTInfo ht_operation;
|
||||
tDot11fIEVHTOperation vht_operation;
|
||||
tDot11fIEhs20vendor_ie hs20vendor_ie;
|
||||
bool is_fils_connection;
|
||||
#ifdef WLAN_FEATURE_FILS_SK
|
||||
uint16_t fils_seq_num;
|
||||
struct fils_join_rsp_params *fils_join_rsp;
|
||||
#endif
|
||||
uint8_t frames[1];
|
||||
} tSirSmeJoinRsp, *tpSirSmeJoinRsp;
|
||||
|
||||
|
@ -414,6 +414,11 @@ typedef struct sSirAssocRsp {
|
||||
tSirQCNIE QCN_IE;
|
||||
tDot11fIEvendor_he_cap vendor_he_cap;
|
||||
tDot11fIEvendor_he_op vendor_he_op;
|
||||
#ifdef WLAN_FEATURE_FILS_SK
|
||||
tDot11fIEfils_session fils_session;
|
||||
tDot11fIEfils_key_confirmation fils_key_auth;
|
||||
tDot11fIEfils_kde fils_kde;
|
||||
#endif
|
||||
} tSirAssocRsp, *tpSirAssocRsp;
|
||||
|
||||
#ifdef FEATURE_WLAN_ESE
|
||||
@ -579,6 +584,7 @@ sir_convert_assoc_req_frame2_struct(struct sAniSirGlobal *pMac,
|
||||
|
||||
tSirRetStatus
|
||||
sir_convert_assoc_resp_frame2_struct(struct sAniSirGlobal *pMac,
|
||||
tpPESession session_entry,
|
||||
uint8_t *frame, uint32_t len,
|
||||
tpSirAssocRsp assoc);
|
||||
|
||||
@ -1065,6 +1071,27 @@ populate_dot11f_ext_cap(tpAniSirGlobal pMac, bool isVHTEnabled,
|
||||
|
||||
void populate_dot11f_qcn_ie(tDot11fIEQCN_IE *pDot11f);
|
||||
|
||||
#ifdef WLAN_FEATURE_FILS_SK
|
||||
/**
|
||||
* populate_dot11f_fils_params() - Populate FILS IE to frame
|
||||
* @mac_ctx: global mac context
|
||||
* @frm: Assoc request frame
|
||||
* @pe_session: PE session
|
||||
*
|
||||
* This API is used to populate FILS IE to Association request
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void populate_dot11f_fils_params(tpAniSirGlobal mac_ctx,
|
||||
tDot11fAssocRequest * frm,
|
||||
tpPESession pe_session);
|
||||
#else
|
||||
static inline void populate_dot11f_fils_params(tpAniSirGlobal mac_ctx,
|
||||
tDot11fAssocRequest *frm,
|
||||
tpPESession pe_session)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
tSirRetStatus
|
||||
populate_dot11f_operating_mode(tpAniSirGlobal pMac,
|
||||
tDot11fIEOperatingMode *pDot11f,
|
||||
|
@ -34,6 +34,9 @@
|
||||
#define MAX_KEY_AUTH_DATA_LEN 48
|
||||
#define MAX_GTK_LEN 255
|
||||
#define MAX_IGTK_LEN 255
|
||||
#define SIR_FILS_SESSION_IE_LEN 11
|
||||
#define FILS_KEY_RSC_LEN 8
|
||||
#define FILS_MAX_KEY_AUTH_LEN (MAX_ICK_LEN + MAX_KEK_LEN + MAX_TK_LEN)
|
||||
|
||||
#define IPN_LEN 6
|
||||
#define FILS_SESSION_LENGTH 8
|
||||
@ -90,6 +93,18 @@
|
||||
#define SIR_FILS_EAP_TLV_CRYPTO_LIST 5
|
||||
#define SIR_FILS_EAP_TLV_AUTH_INDICATION 6
|
||||
|
||||
#define DATA_TYPE_GTK 1
|
||||
#define DATA_TYPE_IGTK 9
|
||||
#define KEY_RSC_LEN 8
|
||||
#define KDE_IE_DATA_OFFSET 4
|
||||
#define KDE_DATA_TYPE_OFFSET 3
|
||||
#define GTK_OFFSET 2
|
||||
#define IPN_OFFSET 2
|
||||
#define IGTK_OFFSET 8
|
||||
|
||||
#define KDE_OUI_TYPE "\x00\x0F\xAC"
|
||||
#define KDE_OUI_TYPE_SIZE 3
|
||||
|
||||
/*
|
||||
* struct eap_auth_reserved: this structure defines flags format in eap packets
|
||||
* as defined in RFC 6696 5.3.1
|
||||
|
@ -99,6 +99,84 @@ static inline void lim_increase_fils_sequence_number(tpPESession session_entry)
|
||||
session_entry->fils_info->sequence_number++;
|
||||
}
|
||||
|
||||
/**
|
||||
* populate_fils_connect_params() - Populate FILS connect params to join rsp
|
||||
* @mac_ctx: Mac context
|
||||
* @session: PE session
|
||||
* @sme_join_rsp: SME join rsp
|
||||
*
|
||||
* This API copies the FILS connect params from PE session to SME join rsp
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void populate_fils_connect_params(tpAniSirGlobal mac_ctx,
|
||||
tpPESession session,
|
||||
tpSirSmeJoinRsp sme_join_rsp);
|
||||
|
||||
/**
|
||||
* aead_encrypt_assoc_req() - Encrypt FILS IE's in assoc request
|
||||
* @mac_ctx: mac context
|
||||
* @pe_session: PE session
|
||||
* @frame: packed frame buffer
|
||||
* @payload: length of @frame
|
||||
*
|
||||
* This API is used to encrypt the all the IE present after FILS session IE
|
||||
* in Association request frame
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS aead_encrypt_assoc_req(tpAniSirGlobal mac_ctx,
|
||||
tpPESession pe_session,
|
||||
uint8_t *frame, uint32_t *payload);
|
||||
|
||||
/**
|
||||
* aead_decrypt_assoc_rsp() - API for AEAD decryption in FILS connection
|
||||
* @mac_ctx: MAC context
|
||||
* @session: PE session
|
||||
* @ar: Assoc response frame structure
|
||||
* @p_frame: frame buffer received
|
||||
* @n_frame: length of @p_frame
|
||||
*
|
||||
* This API is used to decrypt the AEAD encrypted part of FILS assoc response
|
||||
* and populate the decrypted FILS IE's to Assoc response frame structure(ar)
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS aead_decrypt_assoc_rsp(tpAniSirGlobal mac_ctx,
|
||||
tpPESession session,
|
||||
tDot11fAssocResponse *ar,
|
||||
uint8_t *p_frame, uint32_t *n_frame);
|
||||
/**
|
||||
* lim_is_fils_connection() - Check if it is FILS connection
|
||||
* @pe_session: PE session
|
||||
*
|
||||
* This API is used to check if current PE session is FILS connection
|
||||
*
|
||||
* Return: True if FILS connection, false if not
|
||||
*/
|
||||
static inline bool lim_is_fils_connection(tpPESession pe_session)
|
||||
{
|
||||
if (pe_session->fils_info->is_fils_connection)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* lim_verify_fils_params_assoc_rsp() - Verify FILS params in assoc rsp
|
||||
* @mac_ctx: Mac context
|
||||
* @session_entry: PE session
|
||||
* @assoc_rsp: Assoc response received
|
||||
* @assoc_cnf: Assoc cnf msg to be sent to MLME
|
||||
*
|
||||
* This API is used to match FILS params received in Assoc response
|
||||
* with Assoc params received/derived at the Authentication stage
|
||||
*
|
||||
* Return: True, if successfully matches. False, otherwise
|
||||
*/
|
||||
bool lim_verify_fils_params_assoc_rsp(tpAniSirGlobal mac_ctx,
|
||||
tpPESession session_entry,
|
||||
tpSirAssocRsp assoc_rsp,
|
||||
tLimMlmAssocCnf * assoc_cnf);
|
||||
#else
|
||||
static inline bool lim_process_fils_auth_frame2(tpAniSirGlobal mac_ctx,
|
||||
tpPESession pe_session, tSirMacAuthFrameBody *rx_auth_frm_body)
|
||||
@ -130,4 +208,39 @@ static inline uint32_t lim_create_fils_auth_data(tpAniSirGlobal mac_ctx,
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool lim_is_fils_connection(tpPESession pe_session)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void populate_fils_connect_params(tpAniSirGlobal mac_ctx,
|
||||
tpPESession session,
|
||||
tpSirSmeJoinRsp sme_join_rsp)
|
||||
{ }
|
||||
|
||||
static inline QDF_STATUS aead_encrypt_assoc_req(tpAniSirGlobal mac_ctx,
|
||||
tpPESession pe_session,
|
||||
uint8_t *frame,
|
||||
uint32_t *payload)
|
||||
{
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static inline QDF_STATUS aead_decrypt_assoc_rsp(tpAniSirGlobal mac_ctx,
|
||||
tpPESession session,
|
||||
tDot11fAssocResponse *ar,
|
||||
uint8_t *p_frame, uint32_t *n_frame)
|
||||
{
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static inline bool lim_verify_fils_params_assoc_rsp(tpAniSirGlobal mac_ctx,
|
||||
tpPESession session_entry,
|
||||
tpSirAssocRsp assoc_rsp,
|
||||
tLimMlmAssocCnf *assoc_cnf)
|
||||
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
@ -646,4 +646,13 @@ void pe_delete_session(tpAniSirGlobal pMac, tpPESession psessionEntry);
|
||||
tpPESession pe_find_session_by_sme_session_id(tpAniSirGlobal mac_ctx,
|
||||
uint8_t sme_session_id);
|
||||
uint8_t pe_get_active_session_count(tpAniSirGlobal mac_ctx);
|
||||
#ifdef WLAN_FEATURE_FILS_SK
|
||||
/**
|
||||
* pe_delete_fils_info: API to delete fils session info
|
||||
* @session: pe session
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
void pe_delete_fils_info(tpPESession session);
|
||||
#endif
|
||||
#endif /* #if !defined( __LIM_SESSION_H ) */
|
||||
|
@ -767,16 +767,15 @@ lim_send_del_sta_cnf(tpAniSirGlobal pMac, struct qdf_mac_addr sta_dsaddr,
|
||||
mlmStaContext.protStatusCode,
|
||||
psessionEntry->peSessionId);
|
||||
|
||||
if (mlmStaContext.resultCode != eSIR_SME_SUCCESS) {
|
||||
pe_delete_session(pMac, psessionEntry);
|
||||
psessionEntry = NULL;
|
||||
}
|
||||
|
||||
lim_send_sme_join_reassoc_rsp(pMac, eWNI_SME_REASSOC_RSP,
|
||||
mlmStaContext.resultCode,
|
||||
mlmStaContext.protStatusCode,
|
||||
psessionEntry, smesessionId,
|
||||
smetransactionId);
|
||||
if (mlmStaContext.resultCode != eSIR_SME_SUCCESS) {
|
||||
pe_delete_session(pMac, psessionEntry);
|
||||
psessionEntry = NULL;
|
||||
}
|
||||
} else {
|
||||
qdf_mem_free(psessionEntry->pLimJoinReq);
|
||||
psessionEntry->pLimJoinReq = NULL;
|
||||
@ -788,16 +787,16 @@ lim_send_del_sta_cnf(tpAniSirGlobal pMac, struct qdf_mac_addr sta_dsaddr,
|
||||
mlmStaContext.protStatusCode,
|
||||
psessionEntry->peSessionId);
|
||||
|
||||
if (mlmStaContext.resultCode != eSIR_SME_SUCCESS) {
|
||||
pe_delete_session(pMac, psessionEntry);
|
||||
psessionEntry = NULL;
|
||||
}
|
||||
|
||||
lim_send_sme_join_reassoc_rsp(pMac, eWNI_SME_JOIN_RSP,
|
||||
mlmStaContext.resultCode,
|
||||
mlmStaContext.protStatusCode,
|
||||
psessionEntry, smesessionId,
|
||||
smetransactionId);
|
||||
|
||||
if (mlmStaContext.resultCode != eSIR_SME_SUCCESS) {
|
||||
pe_delete_session(pMac, psessionEntry);
|
||||
psessionEntry = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (mlmStaContext.cleanupTrigger == eLIM_DUPLICATE_ENTRY) {
|
||||
|
@ -51,7 +51,7 @@
|
||||
#include "lim_ser_des_utils.h"
|
||||
#include "lim_sta_hash_api.h"
|
||||
#include "lim_send_messages.h"
|
||||
|
||||
#include "lim_process_fils.h"
|
||||
|
||||
extern tSirRetStatus sch_beacon_edca_process(tpAniSirGlobal pMac,
|
||||
tSirMacEdcaParamSetIE *edca, tpPESession psessionEntry);
|
||||
@ -626,7 +626,7 @@ lim_process_assoc_rsp_frame(tpAniSirGlobal mac_ctx,
|
||||
else
|
||||
body = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
|
||||
/* parse Re/Association Response frame. */
|
||||
if (sir_convert_assoc_resp_frame2_struct(mac_ctx, body,
|
||||
if (sir_convert_assoc_resp_frame2_struct(mac_ctx, session_entry, body,
|
||||
frame_len, assoc_rsp) == eSIR_FAILURE) {
|
||||
qdf_mem_free(assoc_rsp);
|
||||
pe_err("Parse error Assoc resp subtype: %d" "length: %d",
|
||||
@ -759,6 +759,23 @@ lim_process_assoc_rsp_frame(tpAniSirGlobal mac_ctx,
|
||||
hdr->sa, session_entry, false);
|
||||
goto assocReject;
|
||||
}
|
||||
|
||||
/*
|
||||
* If it is FILS connection, check is FILS params are matching
|
||||
* with Authentication stage.
|
||||
*/
|
||||
if (!lim_verify_fils_params_assoc_rsp(mac_ctx, session_entry,
|
||||
assoc_rsp, &assoc_cnf)) {
|
||||
pe_err("FILS params doesnot match");
|
||||
assoc_cnf.resultCode = eSIR_SME_INVALID_ASSOC_RSP_RXED;
|
||||
assoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
|
||||
/* Send advisory Disassociation frame to AP */
|
||||
lim_send_disassoc_mgmt_frame(mac_ctx,
|
||||
eSIR_MAC_UNSPEC_FAILURE_REASON,
|
||||
hdr->sa, session_entry, false);
|
||||
goto assocReject;
|
||||
}
|
||||
|
||||
/*
|
||||
* Association Response received with success code
|
||||
* Set the link state to POSTASSOC now that we have received
|
||||
|
@ -1235,4 +1235,555 @@ uint32_t lim_create_fils_auth_data(tpAniSirGlobal mac_ctx,
|
||||
}
|
||||
return frame_len;
|
||||
}
|
||||
|
||||
void populate_fils_connect_params(tpAniSirGlobal mac_ctx,
|
||||
tpPESession session,
|
||||
tpSirSmeJoinRsp sme_join_rsp)
|
||||
{
|
||||
struct fils_join_rsp_params *fils_join_rsp;
|
||||
struct pe_fils_session *fils_info = session->fils_info;
|
||||
|
||||
if (!lim_is_fils_connection(session))
|
||||
return;
|
||||
|
||||
if (!fils_info->fils_pmk_len ||
|
||||
!fils_info->tk_len || !fils_info->gtk_len ||
|
||||
!fils_info->fils_pmk || !fils_info->kek_len) {
|
||||
pe_err("Invalid FILS info pmk len %d kek len %d tk len %d gtk len %d",
|
||||
fils_info->fils_pmk_len,
|
||||
fils_info->kek_len,
|
||||
fils_info->tk_len,
|
||||
fils_info->gtk_len);
|
||||
return;
|
||||
}
|
||||
|
||||
sme_join_rsp->fils_join_rsp = qdf_mem_malloc(sizeof(*fils_join_rsp));
|
||||
if (!sme_join_rsp->fils_join_rsp) {
|
||||
pe_err("fils_join_rsp malloc fails!");
|
||||
pe_delete_fils_info(session);
|
||||
return;
|
||||
}
|
||||
|
||||
fils_join_rsp = sme_join_rsp->fils_join_rsp;
|
||||
fils_join_rsp->fils_pmk = qdf_mem_malloc(fils_info->fils_pmk_len);
|
||||
if (!fils_join_rsp->fils_pmk) {
|
||||
pe_err("fils_pmk malloc fails!");
|
||||
qdf_mem_free(fils_join_rsp);
|
||||
pe_delete_fils_info(session);
|
||||
return;
|
||||
}
|
||||
|
||||
fils_join_rsp->fils_pmk_len = fils_info->fils_pmk_len;
|
||||
qdf_mem_copy(fils_join_rsp->fils_pmk, fils_info->fils_pmk,
|
||||
fils_info->fils_pmk_len);
|
||||
|
||||
qdf_mem_copy(fils_join_rsp->fils_pmkid, fils_info->fils_pmkid,
|
||||
IEEE80211_PMKID_LEN);
|
||||
|
||||
fils_join_rsp->kek_len = fils_info->kek_len;
|
||||
qdf_mem_copy(fils_join_rsp->kek, fils_info->kek, fils_info->kek_len);
|
||||
|
||||
fils_join_rsp->tk_len = fils_info->tk_len;
|
||||
qdf_mem_copy(fils_join_rsp->tk, fils_info->tk, fils_info->tk_len);
|
||||
|
||||
fils_join_rsp->gtk_len = fils_info->gtk_len;
|
||||
qdf_mem_copy(fils_join_rsp->gtk, fils_info->gtk, fils_info->gtk_len);
|
||||
|
||||
pe_debug("FILS connect params copied lim");
|
||||
pe_delete_fils_info(session);
|
||||
}
|
||||
|
||||
/**
|
||||
* lim_parse_kde_elements() - Parse Key Delivery Elements
|
||||
* @mac_ctx: mac context
|
||||
* @fils_info: FILS info
|
||||
* @kde_list: KDE list buffer
|
||||
* @kde_list_len: Length of @kde_list
|
||||
*
|
||||
* This API is used to parse the Key Delivery Elements from buffer
|
||||
* and populate them in PE FILS session struct i.e @fils_info
|
||||
*
|
||||
* Key Delivery Element[KDE] format
|
||||
* +----------+--------+-----------+------------+----------+
|
||||
* | ID(0xDD) | length | KDE OUI | data type | IE data |
|
||||
* |----------|--------|-----------|------------|----------|
|
||||
* | 1 byte | 1 byte | 3 bytes | 1 byte | variable |
|
||||
* +----------+--------+-----------+------------+----------+
|
||||
*
|
||||
* there can be multiple KDE present inside KDE list.
|
||||
* the IE data could be GTK, IGTK etc based on the data type
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS if we parse GTK successfully,
|
||||
* QDF_STATUS_E_FAILURE otherwise
|
||||
*/
|
||||
static QDF_STATUS lim_parse_kde_elements(tpAniSirGlobal mac_ctx,
|
||||
struct pe_fils_session *fils_info,
|
||||
uint8_t *kde_list,
|
||||
uint8_t kde_list_len)
|
||||
{
|
||||
uint8_t rem_len = kde_list_len;
|
||||
uint8_t *temp_ie = kde_list;
|
||||
uint8_t elem_id, data_type, data_len, *ie_data = NULL, *current_ie;
|
||||
uint16_t elem_len;
|
||||
|
||||
if (!kde_list_len || !kde_list) {
|
||||
pe_err("kde_list NULL or kde_list_len %d", kde_list_len);
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
while (rem_len >= 2) {
|
||||
current_ie = temp_ie;
|
||||
elem_id = *temp_ie++;
|
||||
elem_len = *temp_ie++;
|
||||
rem_len -= 2;
|
||||
|
||||
if (lim_check_if_vendor_oui_match(mac_ctx, KDE_OUI_TYPE,
|
||||
KDE_OUI_TYPE_SIZE, current_ie, elem_len)) {
|
||||
|
||||
data_type = *(temp_ie + KDE_DATA_TYPE_OFFSET);
|
||||
ie_data = (temp_ie + KDE_IE_DATA_OFFSET);
|
||||
data_len = (elem_len - KDE_IE_DATA_OFFSET);
|
||||
|
||||
switch (data_type) {
|
||||
case DATA_TYPE_GTK:
|
||||
qdf_mem_copy(fils_info->gtk, (ie_data +
|
||||
GTK_OFFSET), (data_len -
|
||||
GTK_OFFSET));
|
||||
fils_info->gtk_len = (data_len - GTK_OFFSET);
|
||||
lim_fils_data_dump("GTK: ", fils_info->gtk,
|
||||
fils_info->gtk_len);
|
||||
break;
|
||||
|
||||
case DATA_TYPE_IGTK:
|
||||
fils_info->igtk_len = (data_len - IGTK_OFFSET);
|
||||
qdf_mem_copy(fils_info->igtk, (ie_data +
|
||||
IGTK_OFFSET), (data_len -
|
||||
IGTK_OFFSET));
|
||||
qdf_mem_copy(fils_info->ipn, (ie_data +
|
||||
IPN_OFFSET), IPN_LEN);
|
||||
lim_fils_data_dump("IGTK: ", fils_info->igtk,
|
||||
fils_info->igtk_len);
|
||||
break;
|
||||
default:
|
||||
pe_err("Unknown KDE data type %x", data_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
temp_ie += elem_len;
|
||||
rem_len -= elem_len;
|
||||
ie_data = NULL;
|
||||
}
|
||||
|
||||
/* Expecting GTK in KDE */
|
||||
if (!fils_info->gtk_len) {
|
||||
pe_err("GTK not found in KDE");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
bool lim_verify_fils_params_assoc_rsp(tpAniSirGlobal mac_ctx,
|
||||
tpPESession session_entry,
|
||||
tpSirAssocRsp assoc_rsp,
|
||||
tLimMlmAssocCnf *assoc_cnf)
|
||||
{
|
||||
struct pe_fils_session *fils_info = session_entry->fils_info;
|
||||
tDot11fIEfils_session fils_session = assoc_rsp->fils_session;
|
||||
tDot11fIEfils_key_confirmation fils_key_auth = assoc_rsp->fils_key_auth;
|
||||
tDot11fIEfils_kde fils_kde = assoc_rsp->fils_kde;
|
||||
QDF_STATUS status;
|
||||
|
||||
if (!lim_is_fils_connection(session_entry))
|
||||
return true;
|
||||
|
||||
if (!assoc_rsp->fils_session.present) {
|
||||
pe_err("FILS IE not present");
|
||||
goto verify_fils_params_fails;
|
||||
}
|
||||
|
||||
/* Compare FILS session */
|
||||
if (qdf_mem_cmp(fils_info->fils_session,
|
||||
fils_session.session, DOT11F_IE_FILS_SESSION_MAX_LEN)) {
|
||||
pe_err("FILS session mismatch");
|
||||
goto verify_fils_params_fails;
|
||||
}
|
||||
|
||||
/* Compare FILS key auth */
|
||||
if ((fils_key_auth.num_key_auth != fils_info->key_auth_len) ||
|
||||
qdf_mem_cmp(fils_info->ap_key_auth_data, fils_key_auth.key_auth,
|
||||
fils_info->ap_key_auth_len)) {
|
||||
lim_fils_data_dump("session keyauth",
|
||||
fils_info->ap_key_auth_data,
|
||||
fils_info->ap_key_auth_len);
|
||||
lim_fils_data_dump("Pkt keyauth",
|
||||
fils_key_auth.key_auth,
|
||||
fils_key_auth.num_key_auth);
|
||||
goto verify_fils_params_fails;
|
||||
}
|
||||
|
||||
/* Verify the Key Delivery Element presence */
|
||||
if (!fils_kde.num_kde_list) {
|
||||
pe_err("FILS KDE list absent");
|
||||
goto verify_fils_params_fails;
|
||||
}
|
||||
|
||||
/* Derive KDE elements */
|
||||
status = lim_parse_kde_elements(mac_ctx, fils_info, fils_kde.kde_list,
|
||||
fils_kde.num_kde_list);
|
||||
if (!QDF_IS_STATUS_SUCCESS(status)) {
|
||||
pe_err("KDE parsing fails");
|
||||
goto verify_fils_params_fails;
|
||||
}
|
||||
return true;
|
||||
|
||||
verify_fils_params_fails:
|
||||
assoc_cnf->resultCode = eSIR_SME_ASSOC_REFUSED;
|
||||
assoc_cnf->protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* find_ie_data_after_fils_session_ie() - Find IE pointer after FILS Session IE
|
||||
* @mac_ctx: MAC context
|
||||
* @buf: IE buffer
|
||||
* @buf_len: Length of @buf
|
||||
* @ie: Pointer to update the found IE pointer after FILS session IE
|
||||
* @ie_len: length of the IE data after FILS session IE
|
||||
*
|
||||
* This API is used to find the IE data ptr and length after FILS session IE
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS if found, else QDF_STATUS_E_FAILURE
|
||||
*/
|
||||
static QDF_STATUS find_ie_data_after_fils_session_ie(tpAniSirGlobal mac_ctx,
|
||||
uint8_t *buf,
|
||||
uint32_t buf_len,
|
||||
uint8_t **ie,
|
||||
uint32_t *ie_len)
|
||||
{
|
||||
uint32_t left = buf_len;
|
||||
uint8_t *ptr = buf;
|
||||
uint8_t elem_id, elem_len;
|
||||
|
||||
if (NULL == buf || 0 == buf_len)
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
|
||||
while (left >= 2) {
|
||||
elem_id = ptr[0];
|
||||
elem_len = ptr[1];
|
||||
left -= 2;
|
||||
if (elem_len > left)
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
|
||||
if (elem_id == SIR_MAC_REQUEST_EID_MAX &&
|
||||
ptr[2] == SIR_FILS_SESSION_EXT_EID) {
|
||||
(*ie) = ((&ptr[1]) + ptr[1] + 1);
|
||||
(*ie_len) = (left - elem_len);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
left -= elem_len;
|
||||
ptr += (elem_len + 2);
|
||||
}
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* fils_aead_encrypt() - API to do FILS AEAD encryption
|
||||
*
|
||||
* @kek: Pointer to KEK
|
||||
* @kek_len: KEK length
|
||||
* @own_mac: Pointer to own MAC address
|
||||
* @bssid: Bssid
|
||||
* @snonce: Supplicant Nonce
|
||||
* @anonce: Authenticator Nonce
|
||||
* @data: Pointer to data after MAC header
|
||||
* @data_len: length of @data
|
||||
* @plain_text: Pointer to data after FILS Session IE
|
||||
* @plain_text_len: length of @plain_text
|
||||
* @out: Pointer to the encrypted data
|
||||
*
|
||||
* length of AEAD encryption @out is @plain_text_len + AES_BLOCK_SIZE[16 bytes]
|
||||
*
|
||||
* Return: zero on success, error otherwise
|
||||
*/
|
||||
static int fils_aead_encrypt(const u8 *kek, unsigned int kek_len,
|
||||
const u8 *own_mac, const u8 *bssid,
|
||||
const u8 *snonce, const u8 *anonce,
|
||||
const u8 *data, size_t data_len, u8 *plain_text,
|
||||
size_t plain_text_len, u8 *out)
|
||||
{
|
||||
u8 v[AES_BLOCK_SIZE];
|
||||
const u8 *aad[6];
|
||||
size_t aad_len[6];
|
||||
u8 *buf;
|
||||
int ret;
|
||||
|
||||
/* SIV Encrypt/Decrypt takes input key of length 256, 384 or 512 bits */
|
||||
if (kek_len != 32 && kek_len != 48 && kek_len != 64) {
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
|
||||
FL("Invalid key length: %u"), kek_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (own_mac == NULL || bssid == NULL || snonce == NULL ||
|
||||
anonce == NULL || data_len == 0 || plain_text_len == 0 ||
|
||||
out == NULL) {
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
|
||||
FL("Error missing params mac:%p bssid:%p snonce:%p anonce:%p data_len:%lu plain_text_len:%lu out:%p"),
|
||||
own_mac, bssid, snonce, anonce, data_len,
|
||||
plain_text_len, out);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (plain_text == out) {
|
||||
buf = qdf_mem_malloc(plain_text_len);
|
||||
if (buf == NULL) {
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
|
||||
FL("Failed to allocate memory"));
|
||||
return -ENOMEM;
|
||||
}
|
||||
qdf_mem_copy(buf, plain_text, plain_text_len);
|
||||
} else {
|
||||
buf = plain_text;
|
||||
}
|
||||
|
||||
aad[0] = own_mac;
|
||||
aad_len[0] = QDF_MAC_ADDR_SIZE;
|
||||
aad[1] = bssid;
|
||||
aad_len[1] = QDF_MAC_ADDR_SIZE;
|
||||
aad[2] = snonce;
|
||||
aad_len[2] = SIR_FILS_NONCE_LENGTH;
|
||||
aad[3] = anonce;
|
||||
aad_len[3] = SIR_FILS_NONCE_LENGTH;
|
||||
aad[4] = data;
|
||||
aad_len[4] = data_len;
|
||||
/* Plain text, P, is Sn in AES-SIV */
|
||||
aad[5] = buf;
|
||||
aad_len[5] = plain_text_len;
|
||||
|
||||
/* AES-SIV S2V */
|
||||
/* K1 = leftmost(K, len(K)/2) */
|
||||
ret = qdf_aes_s2v(kek, kek_len/2, aad, aad_len, 6, v);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* out = SIV || C (Synthetic Initialization Vector || Ciphered text) */
|
||||
qdf_mem_copy(out, v, AES_BLOCK_SIZE);
|
||||
|
||||
/* AES-SIV CTR */
|
||||
/* K2 = rightmost(K, len(K)/2) */
|
||||
/* Clear 31st and 63rd bits in counter synthetic iv */
|
||||
v[12] &= 0x7F;
|
||||
v[8] &= 0x7F;
|
||||
|
||||
ret = qdf_aes_ctr(kek + kek_len/2, kek_len/2, v, buf, plain_text_len,
|
||||
out + AES_BLOCK_SIZE, true);
|
||||
|
||||
error:
|
||||
if (plain_text == out)
|
||||
qdf_mem_free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
QDF_STATUS aead_encrypt_assoc_req(tpAniSirGlobal mac_ctx,
|
||||
tpPESession pe_session,
|
||||
uint8_t *frm, uint32_t *frm_len)
|
||||
{
|
||||
uint8_t *plain_text = NULL, *data;
|
||||
uint32_t plain_text_len = 0, data_len;
|
||||
QDF_STATUS status;
|
||||
struct pe_fils_session *fils_info = pe_session->fils_info;
|
||||
|
||||
/*
|
||||
* data is the packet data after MAC header till
|
||||
* FILS session IE(inclusive)
|
||||
*/
|
||||
data = frm + sizeof(tSirMacMgmtHdr);
|
||||
|
||||
/*
|
||||
* plain_text is the packet data after FILS session IE
|
||||
* which needs to be encrypted. Get plain_text ptr and
|
||||
* plain_text_len values using find_ptr_aft_fils_session_ie()
|
||||
*/
|
||||
status = find_ie_data_after_fils_session_ie(mac_ctx, data +
|
||||
FIXED_PARAM_OFFSET_ASSOC_REQ,
|
||||
(*frm_len -
|
||||
FIXED_PARAM_OFFSET_ASSOC_REQ),
|
||||
&plain_text, &plain_text_len);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
pe_err("Could not find FILS session IE");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
data_len = ((*frm_len) - plain_text_len);
|
||||
|
||||
lim_fils_data_dump("Plain text: ", plain_text, plain_text_len);
|
||||
|
||||
/* Overwrite the AEAD encrypted output @ plain_text */
|
||||
if (fils_aead_encrypt(fils_info->kek, fils_info->kek_len,
|
||||
pe_session->selfMacAddr, pe_session->bssId,
|
||||
fils_info->fils_nonce,
|
||||
fils_info->auth_info.fils_nonce,
|
||||
data, data_len, plain_text, plain_text_len,
|
||||
plain_text)) {
|
||||
pe_err("AEAD Encryption fails!");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* AEAD encrypted output(cipher_text) will have length equals to
|
||||
* plain_text_len + AES_BLOCK_SIZE(AEAD encryption header info).
|
||||
* Add this to frm_len
|
||||
*/
|
||||
(*frm_len) += (AES_BLOCK_SIZE);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* fils_aead_decrypt() - API to do AEAD decryption
|
||||
*
|
||||
* @kek: Pointer to KEK
|
||||
* @kek_len: KEK length
|
||||
* @own_mac: Pointer to own MAC address
|
||||
* @bssid: Bssid
|
||||
* @snonce: Supplicant Nonce
|
||||
* @anonce: Authenticator Nonce
|
||||
* @data: Pointer to data after MAC header
|
||||
* @data_len: length of @data
|
||||
* @plain_text: Pointer to data after FILS Session IE
|
||||
* @plain_text_len: length of @plain_text
|
||||
* @out: Pointer to the encrypted data
|
||||
*
|
||||
* Return: zero on success, error otherwise
|
||||
*/
|
||||
static int fils_aead_decrypt(const u8 *kek, unsigned int kek_len,
|
||||
const u8 *own_mac, const u8 *bssid,
|
||||
const u8 *snonce, const u8 *anonce,
|
||||
const u8 *data, size_t data_len, u8 *ciphered_text,
|
||||
size_t ciphered_text_len, u8 *plain_text)
|
||||
{
|
||||
const u8 *aad[6];
|
||||
size_t aad_len[6];
|
||||
u8 *buf;
|
||||
size_t buf_len;
|
||||
u8 v[AES_BLOCK_SIZE];
|
||||
u8 siv[AES_BLOCK_SIZE];
|
||||
int ret;
|
||||
|
||||
/* SIV Encrypt/Decrypt takes input key of length 256, 384 or 512 bits */
|
||||
if (kek_len != 32 && kek_len != 48 && kek_len != 64) {
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
|
||||
FL("Invalid key length: %u"), kek_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (own_mac == NULL || bssid == NULL || snonce == NULL ||
|
||||
anonce == NULL || data_len == 0 || ciphered_text_len == 0 ||
|
||||
plain_text == NULL) {
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
|
||||
FL("Error missing params mac:%p bssid:%p snonce:%p anonce:%p data_len:%lu ciphered_text_len:%lu plain_text:%p"),
|
||||
own_mac, bssid, snonce, anonce, data_len,
|
||||
ciphered_text_len, plain_text);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qdf_mem_copy(v, ciphered_text, AES_BLOCK_SIZE);
|
||||
qdf_mem_copy(siv, ciphered_text, AES_BLOCK_SIZE);
|
||||
v[12] &= 0x7F;
|
||||
v[8] &= 0x7F;
|
||||
|
||||
buf_len = ciphered_text_len - AES_BLOCK_SIZE;
|
||||
if (ciphered_text == plain_text) {
|
||||
/* in place decryption */
|
||||
buf = qdf_mem_malloc(buf_len);
|
||||
if (buf == NULL) {
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
|
||||
FL("Failed to allocate memory"));
|
||||
return -ENOMEM;
|
||||
}
|
||||
qdf_mem_copy(buf, ciphered_text + AES_BLOCK_SIZE, buf_len);
|
||||
} else {
|
||||
buf = ciphered_text + AES_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
/* AES-SIV CTR */
|
||||
/* K2 = rightmost(K, len(K)/2) */
|
||||
ret = qdf_aes_ctr(kek + kek_len/2, kek_len/2, v, buf, buf_len,
|
||||
plain_text, false);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
aad[0] = bssid;
|
||||
aad_len[0] = QDF_MAC_ADDR_SIZE;
|
||||
aad[1] = own_mac;
|
||||
aad_len[1] = QDF_MAC_ADDR_SIZE;
|
||||
aad[2] = anonce;
|
||||
aad_len[2] = SIR_FILS_NONCE_LENGTH;
|
||||
aad[3] = snonce;
|
||||
aad_len[3] = SIR_FILS_NONCE_LENGTH;
|
||||
aad[4] = data;
|
||||
aad_len[4] = data_len;
|
||||
aad[5] = plain_text;
|
||||
aad_len[5] = buf_len;
|
||||
|
||||
/* AES-SIV S2V */
|
||||
/* K1 = leftmost(K, len(K)/2) */
|
||||
ret = qdf_aes_s2v(kek, kek_len/2, aad, aad_len, 6, v);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* compare the iv generated against the one sent by AP */
|
||||
if (memcmp(v, siv, AES_BLOCK_SIZE) != 0) {
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
|
||||
FL("siv not same as frame siv"));
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
error:
|
||||
if (ciphered_text == plain_text)
|
||||
qdf_mem_free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
QDF_STATUS aead_decrypt_assoc_rsp(tpAniSirGlobal mac_ctx,
|
||||
tpPESession session,
|
||||
tDot11fAssocResponse *ar,
|
||||
uint8_t *p_frame, uint32_t *n_frame)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
uint32_t data_len, fils_ies_len;
|
||||
uint8_t *fils_ies;
|
||||
struct pe_fils_session *fils_info = session->fils_info;
|
||||
|
||||
lim_fils_data_dump("Assoc Rsp :", p_frame, *n_frame);
|
||||
status = find_ie_data_after_fils_session_ie(mac_ctx, p_frame +
|
||||
FIXED_PARAM_OFFSET_ASSOC_RSP,
|
||||
((*n_frame) -
|
||||
FIXED_PARAM_OFFSET_ASSOC_RSP),
|
||||
&fils_ies, &fils_ies_len);
|
||||
if (!QDF_IS_STATUS_SUCCESS(status)) {
|
||||
pe_err("FILS session IE not present");
|
||||
return status;
|
||||
}
|
||||
|
||||
data_len = (*n_frame) - fils_ies_len;
|
||||
|
||||
if (fils_aead_decrypt(fils_info->kek, fils_info->kek_len,
|
||||
session->selfMacAddr, session->bssId,
|
||||
fils_info->fils_nonce,
|
||||
fils_info->auth_info.fils_nonce,
|
||||
p_frame, data_len,
|
||||
fils_ies, fils_ies_len, fils_ies)){
|
||||
pe_err("AEAD decryption fails");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
/* Dump the output of AEAD decrypt */
|
||||
lim_fils_data_dump("Plain text: ", fils_ies,
|
||||
fils_ies_len - AES_BLOCK_SIZE);
|
||||
|
||||
(*n_frame) -= AES_BLOCK_SIZE;
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
@ -1289,7 +1289,7 @@ static void lim_join_result_callback(tpAniSirGlobal mac, void *param,
|
||||
lim_send_sme_join_reassoc_rsp(mac, eWNI_SME_JOIN_RSP,
|
||||
link_state_params->result_code,
|
||||
link_state_params->prot_status_code,
|
||||
NULL, sme_session_id, sme_trans_id);
|
||||
session, sme_session_id, sme_trans_id);
|
||||
pe_delete_session(mac, session);
|
||||
qdf_mem_free(link_state_params);
|
||||
}
|
||||
|
@ -59,6 +59,7 @@
|
||||
#include "cds_utils.h"
|
||||
#include "sme_trace.h"
|
||||
#include "rrm_api.h"
|
||||
#include "qdf_crypto.h"
|
||||
|
||||
#include "wma_types.h"
|
||||
#include <cdp_txrx_cmn.h>
|
||||
@ -1637,6 +1638,7 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx,
|
||||
tDot11fIEExtCap bcn_ext_cap;
|
||||
uint8_t *bcn_ie = NULL;
|
||||
uint32_t bcn_ie_len = 0;
|
||||
uint32_t aes_block_size_len = 0;
|
||||
|
||||
if (NULL == pe_session) {
|
||||
pe_err("pe_session is NULL");
|
||||
@ -1921,6 +1923,20 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx,
|
||||
add_ie, &add_ie_len, &frm->SuppOperatingClasses))
|
||||
pe_debug("Unable to Stripoff supp op classes IE from Assoc Req");
|
||||
|
||||
if (lim_is_fils_connection(pe_session)) {
|
||||
populate_dot11f_fils_params(mac_ctx, frm, pe_session);
|
||||
aes_block_size_len = AES_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do unpack to populate the add_ie buffer to frm structure
|
||||
* before packing the frm structure. In this way, the IE ordering
|
||||
* which the latest 802.11 spec mandates is maintained.
|
||||
*/
|
||||
if (add_ie_len)
|
||||
dot11f_unpack_assoc_request(mac_ctx, add_ie,
|
||||
add_ie_len, frm, true);
|
||||
|
||||
status = dot11f_get_packed_assoc_request_size(mac_ctx, frm, &payload);
|
||||
if (DOT11F_FAILED(status)) {
|
||||
pe_err("Association Request packet size failure(0x%08x)",
|
||||
@ -1932,7 +1948,8 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx,
|
||||
status);
|
||||
}
|
||||
|
||||
bytes = payload + sizeof(tSirMacMgmtHdr) + add_ie_len;
|
||||
bytes = payload + sizeof(tSirMacMgmtHdr) +
|
||||
aes_block_size_len;
|
||||
|
||||
qdf_status = cds_packet_alloc((uint16_t) bytes, (void **)&frame,
|
||||
(void **)&packet);
|
||||
@ -1974,17 +1991,20 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx,
|
||||
pe_warn("Assoc request pack warning (0x%08x)", status);
|
||||
}
|
||||
|
||||
pe_debug("Sending Association Request length %d to ", bytes);
|
||||
if (pe_session->assocReq != NULL) {
|
||||
qdf_mem_free(pe_session->assocReq);
|
||||
pe_session->assocReq = NULL;
|
||||
pe_session->assocReqLen = 0;
|
||||
}
|
||||
|
||||
if (add_ie_len) {
|
||||
qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
|
||||
add_ie, add_ie_len);
|
||||
payload += add_ie_len;
|
||||
if (lim_is_fils_connection(pe_session)) {
|
||||
qdf_status = aead_encrypt_assoc_req(mac_ctx, pe_session,
|
||||
frame, &payload);
|
||||
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
|
||||
cds_packet_free((void *)packet);
|
||||
qdf_mem_free(frm);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pe_session->assocReq = qdf_mem_malloc(payload);
|
||||
@ -2017,6 +2037,8 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx,
|
||||
mac_hdr = (tpSirMacMgmtHdr) frame;
|
||||
MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
|
||||
pe_session->peSessionId, mac_hdr->fc.subType));
|
||||
|
||||
pe_debug("Sending Association Request length %d to ", bytes);
|
||||
qdf_status =
|
||||
wma_tx_frame(mac_ctx, packet,
|
||||
(uint16_t) (sizeof(tSirMacMgmtHdr) + payload),
|
||||
|
@ -64,6 +64,7 @@
|
||||
#ifdef CONVERGED_TDLS_ENABLE
|
||||
#include "wlan_tdls_tgt_api.h"
|
||||
#endif
|
||||
#include "lim_process_fils.h"
|
||||
|
||||
static void lim_handle_join_rsp_status(tpAniSirGlobal mac_ctx,
|
||||
tpPESession session_entry, tSirResultCodes result_code,
|
||||
@ -453,6 +454,18 @@ static void lim_add_bss_info(tpDphHashNode sta_ds, tpSirSmeJoinRsp sme_join_rsp)
|
||||
sme_join_rsp->vht_operation = parsed_ies->vht_operation;
|
||||
}
|
||||
|
||||
#ifdef WLAN_FEATURE_FILS_SK
|
||||
static void lim_update_fils_seq_num(tpSirSmeJoinRsp sme_join_rsp,
|
||||
tpPESession session_entry)
|
||||
{
|
||||
sme_join_rsp->fils_seq_num =
|
||||
session_entry->fils_info->sequence_number;
|
||||
}
|
||||
#else
|
||||
static inline void lim_update_fils_seq_num(tpSirSmeJoinRsp sme_join_rsp,
|
||||
tpPESession session_entry)
|
||||
{}
|
||||
#endif
|
||||
/**
|
||||
* lim_send_sme_join_reassoc_rsp() - Send Response to Upper Layers
|
||||
* @mac_ctx: Pointer to Global MAC structure
|
||||
@ -516,6 +529,13 @@ lim_send_sme_join_reassoc_rsp(tpAniSirGlobal mac_ctx, uint16_t msg_type,
|
||||
pe_err("MemAlloc fail - JOIN/REASSOC_RSP");
|
||||
return;
|
||||
}
|
||||
|
||||
if (lim_is_fils_connection(session_entry)) {
|
||||
sme_join_rsp->is_fils_connection = true;
|
||||
lim_update_fils_seq_num(sme_join_rsp,
|
||||
session_entry);
|
||||
}
|
||||
|
||||
if (result_code == eSIR_SME_SUCCESS) {
|
||||
sta_ds = dph_get_hash_entry(mac_ctx,
|
||||
DPH_STA_HASH_INDEX_PEER,
|
||||
@ -541,8 +561,13 @@ lim_send_sme_join_reassoc_rsp(tpAniSirGlobal mac_ctx, uint16_t msg_type,
|
||||
sme_join_rsp->max_rate_flags =
|
||||
lim_get_max_rate_flags(mac_ctx, sta_ds);
|
||||
lim_add_bss_info(sta_ds, sme_join_rsp);
|
||||
|
||||
/* Copy FILS params only for Successful join */
|
||||
populate_fils_connect_params(mac_ctx,
|
||||
session_entry, sme_join_rsp);
|
||||
}
|
||||
}
|
||||
|
||||
sme_join_rsp->beaconLength = 0;
|
||||
sme_join_rsp->assocReqLength = 0;
|
||||
sme_join_rsp->assocRspLength = 0;
|
||||
|
@ -274,7 +274,7 @@ pe_init_pmf_comeback_timer(tpAniSirGlobal mac_ctx,
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static void pe_delete_fils_info(tpPESession session)
|
||||
void pe_delete_fils_info(tpPESession session)
|
||||
{
|
||||
struct pe_fils_session *fils_info;
|
||||
|
||||
|
@ -7988,3 +7988,22 @@ tCsrRoamSession *lim_get_session_by_macaddr(tpAniSirGlobal mac_ctx,
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool lim_check_if_vendor_oui_match(tpAniSirGlobal mac_ctx,
|
||||
uint8_t *oui, uint8_t oui_len,
|
||||
uint8_t *ie, uint8_t ie_len)
|
||||
{
|
||||
uint8_t *ptr = ie;
|
||||
uint8_t elem_id = *ie;
|
||||
|
||||
if (NULL == ie || 0 == ie_len) {
|
||||
pe_err("IE Null or ie len zero %d", ie_len);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (elem_id == IE_EID_VENDOR &&
|
||||
!qdf_mem_cmp(&ptr[2], oui, oui_len))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
@ -1127,4 +1127,19 @@ void lim_assoc_rej_add_to_rssi_based_reject_list(tpAniSirGlobal mac_ctx,
|
||||
* Return: None
|
||||
*/
|
||||
void lim_decrement_pending_mgmt_count(tpAniSirGlobal mac_ctx);
|
||||
|
||||
/**
|
||||
* lim_check_if_vendor_oui_match() - Check if the given OUI match in IE buffer
|
||||
* @mac_ctx: MAC context
|
||||
* @ie: IE buffer
|
||||
* @ie_len: length of @ie
|
||||
*
|
||||
* This API is used to check if given vendor OUI
|
||||
* matches in given IE buffer
|
||||
*
|
||||
* Return: True, if mataches. False otherwise
|
||||
*/
|
||||
bool lim_check_if_vendor_oui_match(tpAniSirGlobal mac_ctx,
|
||||
uint8_t *oui, uint8_t oui_len,
|
||||
uint8_t *ie, uint8_t ie_len);
|
||||
#endif /* __LIM_UTILS_H */
|
||||
|
@ -48,6 +48,8 @@
|
||||
#include "rrm_api.h"
|
||||
|
||||
#include "cds_regdomain.h"
|
||||
#include "qdf_crypto.h"
|
||||
#include "lim_process_fils.h"
|
||||
|
||||
/* ////////////////////////////////////////////////////////////////////// */
|
||||
void swap_bit_field16(uint16_t in, uint16_t *out)
|
||||
@ -2269,8 +2271,53 @@ void sir_copy_caps_info(tpAniSirGlobal mac_ctx, tDot11fFfCapabilities caps,
|
||||
}
|
||||
|
||||
#ifdef WLAN_FEATURE_FILS_SK
|
||||
static void populate_dot11f_fils_rsn(tpAniSirGlobal mac_ctx,
|
||||
tDot11fIERSNOpaque *p_dot11f,
|
||||
uint8_t *rsn_ie)
|
||||
{
|
||||
pe_debug("FILS RSN IE length %d", rsn_ie[1]);
|
||||
if (rsn_ie[1]) {
|
||||
p_dot11f->present = 1;
|
||||
p_dot11f->num_data = rsn_ie[1];
|
||||
qdf_mem_copy(p_dot11f->data, &rsn_ie[2], rsn_ie[1]);
|
||||
}
|
||||
}
|
||||
|
||||
void populate_dot11f_fils_params(tpAniSirGlobal mac_ctx,
|
||||
tDot11fAssocRequest *frm,
|
||||
tpPESession pe_session)
|
||||
{
|
||||
struct pe_fils_session *fils_info = pe_session->fils_info;
|
||||
|
||||
/* Populate RSN IE with FILS AKM */
|
||||
populate_dot11f_fils_rsn(mac_ctx, &frm->RSNOpaque,
|
||||
fils_info->rsn_ie);
|
||||
|
||||
/* Populate FILS session IE */
|
||||
frm->fils_session.present = true;
|
||||
qdf_mem_copy(frm->fils_session.session,
|
||||
fils_info->fils_session, FILS_SESSION_LENGTH);
|
||||
|
||||
/* Populate FILS Key confirmation IE */
|
||||
if (fils_info->key_auth_len) {
|
||||
frm->fils_key_confirmation.present = true;
|
||||
frm->fils_key_confirmation.num_key_auth =
|
||||
fils_info->key_auth_len;
|
||||
|
||||
qdf_mem_copy(frm->fils_key_confirmation.key_auth,
|
||||
fils_info->key_auth, fils_info->key_auth_len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* update_fils_data: update fils params from beacon/probe response
|
||||
* @fils_ind: pointer to sir_fils_indication
|
||||
* @fils_indication: pointer to tDot11fIEfils_indication
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void update_fils_data(struct sir_fils_indication *fils_ind,
|
||||
tDot11fIEfils_indication *fils_indication)
|
||||
tDot11fIEfils_indication *fils_indication)
|
||||
{
|
||||
uint8_t *data;
|
||||
|
||||
@ -2787,231 +2834,321 @@ sir_convert_assoc_req_frame2_struct(tpAniSirGlobal pMac,
|
||||
|
||||
} /* End sir_convert_assoc_req_frame2_struct. */
|
||||
|
||||
/**
|
||||
* dot11f_parse_assoc_response() - API to parse Assoc IE buffer to struct
|
||||
* @mac_ctx: MAC context
|
||||
* @p_buf: Pointer to the assoc IE buffer
|
||||
* @n_buf: length of the @p_buf
|
||||
* @p_frm: Struct to populate the IE buffer after parsing
|
||||
* @append_ie: Boolean to indicate whether to reset @p_frm or not. If @append_ie
|
||||
* is true, @p_frm struct is not reset to zeros.
|
||||
*
|
||||
* Return: tSirRetStatus
|
||||
*/
|
||||
static tSirRetStatus dot11f_parse_assoc_response(tpAniSirGlobal mac_ctx,
|
||||
uint8_t *p_buf, uint32_t n_buf,
|
||||
tDot11fAssocResponse *p_frm,
|
||||
bool append_ie)
|
||||
{
|
||||
uint32_t status;
|
||||
|
||||
status = dot11f_unpack_assoc_response(mac_ctx, p_buf,
|
||||
n_buf, p_frm, append_ie);
|
||||
if (DOT11F_FAILED(status)) {
|
||||
pe_err("Failed to parse an Association Response (0x%08x, %d bytes):",
|
||||
status, n_buf);
|
||||
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR,
|
||||
p_buf, n_buf);
|
||||
return eSIR_FAILURE;
|
||||
}
|
||||
|
||||
return eSIR_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef WLAN_FEATURE_FILS_SK
|
||||
/**
|
||||
* fils_convert_assoc_rsp_frame2_struct() - Copy FILS IE's to Assoc rsp struct
|
||||
* @ar: frame parser Assoc response struct
|
||||
* @pAssocRsp: LIM Assoc response
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void fils_convert_assoc_rsp_frame2_struct(tDot11fAssocResponse *ar,
|
||||
tpSirAssocRsp pAssocRsp)
|
||||
{
|
||||
if (ar->fils_session.present) {
|
||||
pe_debug("fils session IE present");
|
||||
pAssocRsp->fils_session.present = true;
|
||||
qdf_mem_copy(pAssocRsp->fils_session.session,
|
||||
ar->fils_session.session,
|
||||
DOT11F_IE_FILS_SESSION_MAX_LEN);
|
||||
}
|
||||
|
||||
if (ar->fils_key_confirmation.present) {
|
||||
pe_debug("fils key conf IE present");
|
||||
pAssocRsp->fils_key_auth.num_key_auth =
|
||||
ar->fils_key_confirmation.num_key_auth;
|
||||
qdf_mem_copy(pAssocRsp->fils_key_auth.key_auth,
|
||||
ar->fils_key_confirmation.key_auth,
|
||||
pAssocRsp->fils_key_auth.num_key_auth);
|
||||
}
|
||||
|
||||
if (ar->fils_kde.present) {
|
||||
pe_debug("fils kde IE present %d",
|
||||
ar->fils_kde.num_kde_list);
|
||||
pAssocRsp->fils_kde.num_kde_list =
|
||||
ar->fils_kde.num_kde_list;
|
||||
qdf_mem_copy(pAssocRsp->fils_kde.key_rsc,
|
||||
ar->fils_kde.key_rsc, KEY_RSC_LEN);
|
||||
qdf_mem_copy(&pAssocRsp->fils_kde.kde_list,
|
||||
&ar->fils_kde.kde_list,
|
||||
pAssocRsp->fils_kde.num_kde_list);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static inline void fils_convert_assoc_rsp_frame2_struct(tDot11fAssocResponse
|
||||
*ar, tpSirAssocRsp
|
||||
pAssocRsp)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
tSirRetStatus
|
||||
sir_convert_assoc_resp_frame2_struct(tpAniSirGlobal pMac,
|
||||
uint8_t *pFrame,
|
||||
uint32_t nFrame, tpSirAssocRsp pAssocRsp)
|
||||
tpPESession session_entry,
|
||||
uint8_t *pFrame, uint32_t nFrame,
|
||||
tpSirAssocRsp pAssocRsp)
|
||||
{
|
||||
static tDot11fAssocResponse ar;
|
||||
tDot11fAssocResponse *ar;
|
||||
uint32_t status;
|
||||
uint8_t cnt = 0;
|
||||
|
||||
/* Zero-init our [out] parameter, */
|
||||
qdf_mem_set((uint8_t *) pAssocRsp, sizeof(tSirAssocRsp), 0);
|
||||
|
||||
/* delegate to the framesc-generated code, */
|
||||
status = dot11f_unpack_assoc_response(pMac, pFrame, nFrame, &ar, false);
|
||||
if (DOT11F_FAILED(status)) {
|
||||
pe_err("Failed to parse an Association Response (0x%08x, %d bytes):",
|
||||
status, nFrame);
|
||||
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR,
|
||||
pFrame, nFrame);
|
||||
ar = qdf_mem_malloc(sizeof(*ar));
|
||||
if (!ar) {
|
||||
pe_err("Assoc rsp mem alloc fails");
|
||||
return eSIR_FAILURE;
|
||||
} else if (DOT11F_WARNED(status)) {
|
||||
pe_debug("There were warnings while unpacking an Association Response (0x%08x, %d bytes):",
|
||||
status, nFrame);
|
||||
}
|
||||
/* & "transliterate" from a 'tDot11fAssocResponse' a 'tSirAssocRsp'... */
|
||||
|
||||
/* decrypt the cipher text using AEAD decryption */
|
||||
if (lim_is_fils_connection(session_entry)) {
|
||||
status = aead_decrypt_assoc_rsp(pMac, session_entry,
|
||||
ar, pFrame, &nFrame);
|
||||
if (!QDF_IS_STATUS_SUCCESS(status)) {
|
||||
pe_err("FILS assoc rsp AEAD decrypt fails");
|
||||
qdf_mem_free(ar);
|
||||
return eSIR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
status = dot11f_parse_assoc_response(pMac, pFrame, nFrame, ar, false);
|
||||
if (eSIR_SUCCESS != status) {
|
||||
qdf_mem_free(ar);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Capabilities */
|
||||
pAssocRsp->capabilityInfo.ess = ar.Capabilities.ess;
|
||||
pAssocRsp->capabilityInfo.ibss = ar.Capabilities.ibss;
|
||||
pAssocRsp->capabilityInfo.cfPollable = ar.Capabilities.cfPollable;
|
||||
pAssocRsp->capabilityInfo.cfPollReq = ar.Capabilities.cfPollReq;
|
||||
pAssocRsp->capabilityInfo.privacy = ar.Capabilities.privacy;
|
||||
pAssocRsp->capabilityInfo.shortPreamble = ar.Capabilities.shortPreamble;
|
||||
pAssocRsp->capabilityInfo.pbcc = ar.Capabilities.pbcc;
|
||||
pAssocRsp->capabilityInfo.ess = ar->Capabilities.ess;
|
||||
pAssocRsp->capabilityInfo.ibss = ar->Capabilities.ibss;
|
||||
pAssocRsp->capabilityInfo.cfPollable = ar->Capabilities.cfPollable;
|
||||
pAssocRsp->capabilityInfo.cfPollReq = ar->Capabilities.cfPollReq;
|
||||
pAssocRsp->capabilityInfo.privacy = ar->Capabilities.privacy;
|
||||
pAssocRsp->capabilityInfo.shortPreamble =
|
||||
ar->Capabilities.shortPreamble;
|
||||
pAssocRsp->capabilityInfo.pbcc = ar->Capabilities.pbcc;
|
||||
pAssocRsp->capabilityInfo.channelAgility =
|
||||
ar.Capabilities.channelAgility;
|
||||
pAssocRsp->capabilityInfo.spectrumMgt = ar.Capabilities.spectrumMgt;
|
||||
pAssocRsp->capabilityInfo.qos = ar.Capabilities.qos;
|
||||
pAssocRsp->capabilityInfo.shortSlotTime = ar.Capabilities.shortSlotTime;
|
||||
pAssocRsp->capabilityInfo.apsd = ar.Capabilities.apsd;
|
||||
pAssocRsp->capabilityInfo.rrm = ar.Capabilities.rrm;
|
||||
pAssocRsp->capabilityInfo.dsssOfdm = ar.Capabilities.dsssOfdm;
|
||||
pAssocRsp->capabilityInfo.delayedBA = ar.Capabilities.delayedBA;
|
||||
pAssocRsp->capabilityInfo.immediateBA = ar.Capabilities.immediateBA;
|
||||
ar->Capabilities.channelAgility;
|
||||
pAssocRsp->capabilityInfo.spectrumMgt = ar->Capabilities.spectrumMgt;
|
||||
pAssocRsp->capabilityInfo.qos = ar->Capabilities.qos;
|
||||
pAssocRsp->capabilityInfo.shortSlotTime =
|
||||
ar->Capabilities.shortSlotTime;
|
||||
pAssocRsp->capabilityInfo.apsd = ar->Capabilities.apsd;
|
||||
pAssocRsp->capabilityInfo.rrm = ar->Capabilities.rrm;
|
||||
pAssocRsp->capabilityInfo.dsssOfdm = ar->Capabilities.dsssOfdm;
|
||||
pAssocRsp->capabilityInfo.delayedBA = ar->Capabilities.delayedBA;
|
||||
pAssocRsp->capabilityInfo.immediateBA = ar->Capabilities.immediateBA;
|
||||
|
||||
pAssocRsp->statusCode = ar.Status.status;
|
||||
pAssocRsp->aid = ar.AID.associd;
|
||||
pAssocRsp->statusCode = ar->Status.status;
|
||||
pAssocRsp->aid = ar->AID.associd;
|
||||
#ifdef WLAN_FEATURE_11W
|
||||
if (ar.TimeoutInterval.present) {
|
||||
if (ar->TimeoutInterval.present) {
|
||||
pAssocRsp->TimeoutInterval.present = 1;
|
||||
pAssocRsp->TimeoutInterval.timeoutType =
|
||||
ar.TimeoutInterval.timeoutType;
|
||||
ar->TimeoutInterval.timeoutType;
|
||||
pAssocRsp->TimeoutInterval.timeoutValue =
|
||||
ar.TimeoutInterval.timeoutValue;
|
||||
ar->TimeoutInterval.timeoutValue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!ar.SuppRates.present) {
|
||||
if (!ar->SuppRates.present) {
|
||||
pAssocRsp->suppRatesPresent = 0;
|
||||
pe_warn("Mandatory IE Supported Rates not present!");
|
||||
} else {
|
||||
pAssocRsp->suppRatesPresent = 1;
|
||||
convert_supp_rates(pMac, &pAssocRsp->supportedRates,
|
||||
&ar.SuppRates);
|
||||
&ar->SuppRates);
|
||||
}
|
||||
|
||||
if (ar.ExtSuppRates.present) {
|
||||
if (ar->ExtSuppRates.present) {
|
||||
pAssocRsp->extendedRatesPresent = 1;
|
||||
convert_ext_supp_rates(pMac, &pAssocRsp->extendedRates,
|
||||
&ar.ExtSuppRates);
|
||||
&ar->ExtSuppRates);
|
||||
}
|
||||
|
||||
if (ar.EDCAParamSet.present) {
|
||||
if (ar->EDCAParamSet.present) {
|
||||
pAssocRsp->edcaPresent = 1;
|
||||
convert_edca_param(pMac, &pAssocRsp->edca, &ar.EDCAParamSet);
|
||||
convert_edca_param(pMac, &pAssocRsp->edca, &ar->EDCAParamSet);
|
||||
}
|
||||
|
||||
if (ar.WMMParams.present) {
|
||||
if (ar->WMMParams.present) {
|
||||
pAssocRsp->wmeEdcaPresent = 1;
|
||||
convert_wmm_params(pMac, &pAssocRsp->edca, &ar.WMMParams);
|
||||
convert_wmm_params(pMac, &pAssocRsp->edca, &ar->WMMParams);
|
||||
pe_debug("Received Assoc Resp with WMM Param");
|
||||
__print_wmm_params(pMac, &ar.WMMParams);
|
||||
__print_wmm_params(pMac, &ar->WMMParams);
|
||||
}
|
||||
|
||||
if (ar.HTCaps.present) {
|
||||
if (ar->HTCaps.present) {
|
||||
pe_debug("Received Assoc Resp with HT Cap");
|
||||
qdf_mem_copy(&pAssocRsp->HTCaps, &ar.HTCaps,
|
||||
qdf_mem_copy(&pAssocRsp->HTCaps, &ar->HTCaps,
|
||||
sizeof(tDot11fIEHTCaps));
|
||||
}
|
||||
|
||||
if (ar.HTInfo.present) {
|
||||
if (ar->HTInfo.present) {
|
||||
pe_debug("Received Assoc Resp with HT Info");
|
||||
qdf_mem_copy(&pAssocRsp->HTInfo, &ar.HTInfo,
|
||||
qdf_mem_copy(&pAssocRsp->HTInfo, &ar->HTInfo,
|
||||
sizeof(tDot11fIEHTInfo));
|
||||
}
|
||||
if (ar.MobilityDomain.present) {
|
||||
if (ar->MobilityDomain.present) {
|
||||
/* MobilityDomain */
|
||||
pAssocRsp->mdiePresent = 1;
|
||||
qdf_mem_copy((uint8_t *) &(pAssocRsp->mdie[0]),
|
||||
(uint8_t *) &(ar.MobilityDomain.MDID),
|
||||
sizeof(uint16_t));
|
||||
pAssocRsp->mdie[2] =
|
||||
((ar.MobilityDomain.overDSCap << 0) | (ar.MobilityDomain.
|
||||
resourceReqCap <<
|
||||
1));
|
||||
(uint8_t *) &(ar->MobilityDomain.MDID),
|
||||
sizeof(uint16_t));
|
||||
pAssocRsp->mdie[2] = ((ar->MobilityDomain.overDSCap << 0) |
|
||||
(ar->MobilityDomain.resourceReqCap << 1));
|
||||
pe_debug("new mdie=%02x%02x%02x",
|
||||
(unsigned int)pAssocRsp->mdie[0],
|
||||
(unsigned int)pAssocRsp->mdie[1],
|
||||
(unsigned int)pAssocRsp->mdie[2]);
|
||||
}
|
||||
|
||||
if (ar.FTInfo.present) {
|
||||
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);
|
||||
ar->FTInfo.R0KH_ID.num_PMK_R0_ID,
|
||||
ar->FTInfo.R0KH_ID.present, ar->FTInfo.R1KH_ID.present);
|
||||
pAssocRsp->ftinfoPresent = 1;
|
||||
qdf_mem_copy(&pAssocRsp->FTInfo, &ar.FTInfo,
|
||||
sizeof(tDot11fIEFTInfo));
|
||||
qdf_mem_copy(&pAssocRsp->FTInfo, &ar->FTInfo,
|
||||
sizeof(tDot11fIEFTInfo));
|
||||
}
|
||||
|
||||
if (ar.num_RICDataDesc && ar.num_RICDataDesc <= 2) {
|
||||
for (cnt = 0; cnt < ar.num_RICDataDesc; cnt++) {
|
||||
if (ar.RICDataDesc[cnt].present) {
|
||||
if (ar->num_RICDataDesc && ar->num_RICDataDesc <= 2) {
|
||||
for (cnt = 0; cnt < ar->num_RICDataDesc; cnt++) {
|
||||
if (ar->RICDataDesc[cnt].present) {
|
||||
qdf_mem_copy(&pAssocRsp->RICData[cnt],
|
||||
&ar.RICDataDesc[cnt],
|
||||
sizeof(tDot11fIERICDataDesc));
|
||||
&ar->RICDataDesc[cnt],
|
||||
sizeof(tDot11fIERICDataDesc));
|
||||
}
|
||||
}
|
||||
pAssocRsp->num_RICData = ar.num_RICDataDesc;
|
||||
pAssocRsp->num_RICData = ar->num_RICDataDesc;
|
||||
pAssocRsp->ricPresent = true;
|
||||
}
|
||||
|
||||
#ifdef FEATURE_WLAN_ESE
|
||||
if (ar.num_WMMTSPEC) {
|
||||
pAssocRsp->num_tspecs = ar.num_WMMTSPEC;
|
||||
for (cnt = 0; cnt < ar.num_WMMTSPEC; cnt++) {
|
||||
if (ar->num_WMMTSPEC) {
|
||||
pAssocRsp->num_tspecs = ar->num_WMMTSPEC;
|
||||
for (cnt = 0; cnt < ar->num_WMMTSPEC; cnt++) {
|
||||
qdf_mem_copy(&pAssocRsp->TSPECInfo[cnt],
|
||||
&ar.WMMTSPEC[cnt],
|
||||
(sizeof(tDot11fIEWMMTSPEC) *
|
||||
ar.num_WMMTSPEC));
|
||||
&ar->WMMTSPEC[cnt],
|
||||
(sizeof(tDot11fIEWMMTSPEC) *
|
||||
ar->num_WMMTSPEC));
|
||||
}
|
||||
pAssocRsp->tspecPresent = true;
|
||||
}
|
||||
|
||||
if (ar.ESETrafStrmMet.present) {
|
||||
if (ar->ESETrafStrmMet.present) {
|
||||
pAssocRsp->tsmPresent = 1;
|
||||
qdf_mem_copy(&pAssocRsp->tsmIE.tsid,
|
||||
&ar.ESETrafStrmMet.tsid, sizeof(tSirMacESETSMIE));
|
||||
&ar->ESETrafStrmMet.tsid,
|
||||
sizeof(tSirMacESETSMIE));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ar.VHTCaps.present) {
|
||||
qdf_mem_copy(&pAssocRsp->VHTCaps, &ar.VHTCaps,
|
||||
if (ar->VHTCaps.present) {
|
||||
qdf_mem_copy(&pAssocRsp->VHTCaps, &ar->VHTCaps,
|
||||
sizeof(tDot11fIEVHTCaps));
|
||||
pe_debug("Received Assoc Response with VHT Cap");
|
||||
lim_log_vht_cap(pMac, &pAssocRsp->VHTCaps);
|
||||
}
|
||||
if (ar.VHTOperation.present) {
|
||||
qdf_mem_copy(&pAssocRsp->VHTOperation, &ar.VHTOperation,
|
||||
if (ar->VHTOperation.present) {
|
||||
qdf_mem_copy(&pAssocRsp->VHTOperation, &ar->VHTOperation,
|
||||
sizeof(tDot11fIEVHTOperation));
|
||||
pe_debug("Received Assoc Response with VHT Operation");
|
||||
lim_log_vht_operation(pMac, &pAssocRsp->VHTOperation);
|
||||
}
|
||||
|
||||
if (ar.ExtCap.present) {
|
||||
if (ar->ExtCap.present) {
|
||||
struct s_ext_cap *ext_cap;
|
||||
qdf_mem_copy(&pAssocRsp->ExtCap, &ar.ExtCap,
|
||||
sizeof(tDot11fIEExtCap));
|
||||
qdf_mem_copy(&pAssocRsp->ExtCap, &ar->ExtCap,
|
||||
sizeof(tDot11fIEExtCap));
|
||||
ext_cap = (struct s_ext_cap *)&pAssocRsp->ExtCap.bytes;
|
||||
pe_debug("timingMeas: %d, finetimingMeas Init: %d, Resp: %d",
|
||||
ext_cap->timing_meas, ext_cap->fine_time_meas_initiator,
|
||||
ext_cap->fine_time_meas_responder);
|
||||
}
|
||||
|
||||
if (ar.QosMapSet.present) {
|
||||
if (ar->QosMapSet.present) {
|
||||
pAssocRsp->QosMapSet.present = 1;
|
||||
convert_qos_mapset_frame(pMac, &pAssocRsp->QosMapSet,
|
||||
&ar.QosMapSet);
|
||||
&ar->QosMapSet);
|
||||
pe_debug("Received Assoc Response with Qos Map Set");
|
||||
lim_log_qos_map_set(pMac, &pAssocRsp->QosMapSet);
|
||||
}
|
||||
|
||||
pAssocRsp->vendor_vht_ie.present = ar.vendor_vht_ie.present;
|
||||
if (ar.vendor_vht_ie.present) {
|
||||
pAssocRsp->vendor_vht_ie.type = ar.vendor_vht_ie.type;
|
||||
pAssocRsp->vendor_vht_ie.sub_type = ar.vendor_vht_ie.sub_type;
|
||||
pAssocRsp->vendor_vht_ie.present = ar->vendor_vht_ie.present;
|
||||
if (ar->vendor_vht_ie.present) {
|
||||
pAssocRsp->vendor_vht_ie.type = ar->vendor_vht_ie.type;
|
||||
pAssocRsp->vendor_vht_ie.sub_type = ar->vendor_vht_ie.sub_type;
|
||||
}
|
||||
if (ar.OBSSScanParameters.present) {
|
||||
if (ar->OBSSScanParameters.present) {
|
||||
qdf_mem_copy(&pAssocRsp->obss_scanparams,
|
||||
&ar.OBSSScanParameters,
|
||||
sizeof(struct sDot11fIEOBSSScanParameters));
|
||||
&ar->OBSSScanParameters,
|
||||
sizeof(struct sDot11fIEOBSSScanParameters));
|
||||
}
|
||||
if (ar.vendor_vht_ie.VHTCaps.present) {
|
||||
if (ar->vendor_vht_ie.VHTCaps.present) {
|
||||
qdf_mem_copy(&pAssocRsp->vendor_vht_ie.VHTCaps,
|
||||
&ar.vendor_vht_ie.VHTCaps,
|
||||
&ar->vendor_vht_ie.VHTCaps,
|
||||
sizeof(tDot11fIEVHTCaps));
|
||||
pe_debug("Received Assoc Response with Vendor specific VHT Cap");
|
||||
lim_log_vht_cap(pMac, &pAssocRsp->VHTCaps);
|
||||
}
|
||||
if (ar.vendor_vht_ie.VHTOperation.present) {
|
||||
if (ar->vendor_vht_ie.VHTOperation.present) {
|
||||
qdf_mem_copy(&pAssocRsp->vendor_vht_ie.VHTOperation,
|
||||
&ar.vendor_vht_ie.VHTOperation,
|
||||
&ar->vendor_vht_ie.VHTOperation,
|
||||
sizeof(tDot11fIEVHTOperation));
|
||||
pe_debug("Received Assoc Response with Vendor specific VHT Oper");
|
||||
lim_log_vht_operation(pMac, &pAssocRsp->VHTOperation);
|
||||
}
|
||||
|
||||
if (ar.vendor_he_cap.present) {
|
||||
if (ar->vendor_he_cap.present) {
|
||||
pe_debug("11AX: HE cap IE present");
|
||||
qdf_mem_copy(&pAssocRsp->vendor_he_cap, &ar.vendor_he_cap,
|
||||
qdf_mem_copy(&pAssocRsp->vendor_he_cap, &ar->vendor_he_cap,
|
||||
sizeof(tDot11fIEvendor_he_cap));
|
||||
}
|
||||
if (ar.vendor_he_op.present) {
|
||||
if (ar->vendor_he_op.present) {
|
||||
pe_debug("11AX: HE Operation IE present");
|
||||
qdf_mem_copy(&pAssocRsp->vendor_he_op, &ar.vendor_he_op,
|
||||
qdf_mem_copy(&pAssocRsp->vendor_he_op, &ar->vendor_he_op,
|
||||
sizeof(tDot11fIEvendor_he_op));
|
||||
}
|
||||
|
||||
if (ar.MBO_IE.present && ar.MBO_IE.rssi_assoc_rej.present) {
|
||||
if (ar->MBO_IE.present && ar->MBO_IE.rssi_assoc_rej.present) {
|
||||
qdf_mem_copy(&pAssocRsp->rssi_assoc_rej,
|
||||
&ar.MBO_IE.rssi_assoc_rej,
|
||||
&ar->MBO_IE.rssi_assoc_rej,
|
||||
sizeof(tDot11fTLVrssi_assoc_rej));
|
||||
pe_debug("Received Assoc Response with rssi based assoc rej");
|
||||
}
|
||||
|
||||
fils_convert_assoc_rsp_frame2_struct(ar, pAssocRsp);
|
||||
|
||||
qdf_mem_free(ar);
|
||||
return eSIR_SUCCESS;
|
||||
|
||||
} /* End sir_convert_assoc_resp_frame2_struct. */
|
||||
|
@ -1487,6 +1487,11 @@ typedef struct tagCsrRoamInfo {
|
||||
uint8_t tx_mcs_map;
|
||||
/* Extended capabilities of STA */
|
||||
uint8_t ecsa_capable;
|
||||
bool is_fils_connection;
|
||||
#ifdef WLAN_FEATURE_FILS_SK
|
||||
uint16_t fils_seq_num;
|
||||
struct fils_join_rsp_params *fils_join_rsp;
|
||||
#endif
|
||||
} tCsrRoamInfo;
|
||||
|
||||
typedef struct tagCsrFreqScanInfo {
|
||||
|
@ -6504,6 +6504,27 @@ static void csr_roam_copy_ht_profile(tCsrRoamHTProfile *dst_profile,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(WLAN_FEATURE_FILS_SK)
|
||||
/**
|
||||
* csr_update_fils_seq_number() - Copy FILS sequence number to roam info
|
||||
* @session: CSR Roam Session
|
||||
* @roam_info: Roam info
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void csr_update_fils_seq_number(tCsrRoamSession *session,
|
||||
tCsrRoamInfo *roam_info)
|
||||
{
|
||||
roam_info->is_fils_connection = true;
|
||||
roam_info->fils_seq_num = session->fils_seq_num;
|
||||
pe_debug("FILS sequence number %x", session->fils_seq_num);
|
||||
}
|
||||
#else
|
||||
static inline void csr_update_fils_seq_number(tCsrRoamSession *session,
|
||||
tCsrRoamInfo *roam_info)
|
||||
{}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* csr_roam_process_results_default() - Process the result for start bss
|
||||
* @mac_ctx: Global MAC Context
|
||||
@ -6526,7 +6547,8 @@ static void csr_roam_process_results_default(tpAniSirGlobal mac_ctx,
|
||||
}
|
||||
session = CSR_GET_SESSION(mac_ctx, session_id);
|
||||
|
||||
sme_debug("receives no association indication");
|
||||
sme_debug("receives no association indication; FILS %d",
|
||||
session->is_fils_connection);
|
||||
sme_debug("Assoc ref count: %d", session->bRefAssocStartCnt);
|
||||
if (CSR_IS_INFRASTRUCTURE(&session->connectedProfile)
|
||||
|| CSR_IS_ROAM_SUBSTATE_STOP_BSS_REQ(mac_ctx, session_id)) {
|
||||
@ -6540,6 +6562,11 @@ static void csr_roam_process_results_default(tpAniSirGlobal mac_ctx,
|
||||
csr_set_default_dot11_mode(mac_ctx);
|
||||
}
|
||||
|
||||
qdf_mem_set(&roam_info, sizeof(tCsrRoamInfo), 0);
|
||||
/* Copy FILS sequence number used to be updated to userspace */
|
||||
if (session->is_fils_connection)
|
||||
csr_update_fils_seq_number(session, &roam_info);
|
||||
|
||||
switch (cmd->u.roamCmd.roamReason) {
|
||||
/*
|
||||
* If this transition is because of an 802.11 OID, then we
|
||||
@ -6552,7 +6579,6 @@ static void csr_roam_process_results_default(tpAniSirGlobal mac_ctx,
|
||||
case eCsrSmeIssuedDisassocForHandoff:
|
||||
csr_roam_state_change(mac_ctx, eCSR_ROAMING_STATE_IDLE,
|
||||
session_id);
|
||||
qdf_mem_set(&roam_info, sizeof(tCsrRoamInfo), 0);
|
||||
roam_info.pBssDesc = cmd->u.roamCmd.pLastRoamBss;
|
||||
roam_info.pProfile = &cmd->u.roamCmd.roamProfile;
|
||||
roam_info.statusCode = session->joinFailStatusCode.statusCode;
|
||||
@ -6922,6 +6948,154 @@ static void csr_roam_process_start_bss_success(tpAniSirGlobal mac_ctx,
|
||||
|
||||
}
|
||||
|
||||
#ifdef WLAN_FEATURE_FILS_SK
|
||||
/**
|
||||
* populate_fils_params_join_rsp() - Copy FILS params from JOIN rsp
|
||||
* @mac_ctx: Global MAC Context
|
||||
* @roam_info: CSR Roam Info
|
||||
* @join_rsp: SME Join response
|
||||
*
|
||||
* Copy the FILS params from the join results
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
static QDF_STATUS populate_fils_params_join_rsp(tpAniSirGlobal mac_ctx,
|
||||
tCsrRoamInfo *roam_info,
|
||||
tSirSmeJoinRsp *join_rsp)
|
||||
{
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
struct fils_join_rsp_params *roam_fils_info,
|
||||
*fils_join_rsp = join_rsp->fils_join_rsp;
|
||||
|
||||
if (!fils_join_rsp->fils_pmk_len ||
|
||||
!fils_join_rsp->fils_pmk || !fils_join_rsp->tk_len ||
|
||||
!fils_join_rsp->kek_len || !fils_join_rsp->gtk_len) {
|
||||
sme_err("fils join rsp err: pmk len %d tk len %d kek len %d gtk len %d",
|
||||
fils_join_rsp->fils_pmk_len,
|
||||
fils_join_rsp->tk_len,
|
||||
fils_join_rsp->kek_len,
|
||||
fils_join_rsp->gtk_len);
|
||||
status = QDF_STATUS_E_FAILURE;
|
||||
goto free_fils_join_rsp;
|
||||
}
|
||||
|
||||
roam_info->fils_join_rsp = qdf_mem_malloc(sizeof(*fils_join_rsp));
|
||||
if (!roam_info->fils_join_rsp) {
|
||||
sme_err("fils_join_rsp malloc fails!");
|
||||
status = QDF_STATUS_E_FAILURE;
|
||||
goto free_fils_join_rsp;
|
||||
}
|
||||
|
||||
roam_fils_info = roam_info->fils_join_rsp;
|
||||
roam_fils_info->fils_pmk = qdf_mem_malloc(fils_join_rsp->fils_pmk_len);
|
||||
if (!roam_fils_info->fils_pmk) {
|
||||
qdf_mem_free(roam_info->fils_join_rsp);
|
||||
roam_info->fils_join_rsp = NULL;
|
||||
sme_err("fils_pmk malloc fails!");
|
||||
status = QDF_STATUS_E_FAILURE;
|
||||
goto free_fils_join_rsp;
|
||||
}
|
||||
|
||||
roam_info->fils_seq_num = join_rsp->fils_seq_num;
|
||||
roam_fils_info->fils_pmk_len = fils_join_rsp->fils_pmk_len;
|
||||
qdf_mem_copy(roam_fils_info->fils_pmk,
|
||||
fils_join_rsp->fils_pmk, roam_fils_info->fils_pmk_len);
|
||||
|
||||
qdf_mem_copy(roam_fils_info->fils_pmkid,
|
||||
fils_join_rsp->fils_pmkid, PMKID_LEN);
|
||||
|
||||
roam_fils_info->kek_len = fils_join_rsp->kek_len;
|
||||
qdf_mem_copy(roam_fils_info->kek,
|
||||
fils_join_rsp->kek, roam_fils_info->kek_len);
|
||||
|
||||
roam_fils_info->tk_len = fils_join_rsp->tk_len;
|
||||
qdf_mem_copy(roam_fils_info->tk,
|
||||
fils_join_rsp->tk, fils_join_rsp->tk_len);
|
||||
|
||||
roam_fils_info->gtk_len = fils_join_rsp->gtk_len;
|
||||
qdf_mem_copy(roam_fils_info->gtk,
|
||||
fils_join_rsp->gtk, roam_fils_info->gtk_len);
|
||||
|
||||
sme_debug("FILS connect params copied to CSR!");
|
||||
|
||||
free_fils_join_rsp:
|
||||
qdf_mem_free(fils_join_rsp->fils_pmk);
|
||||
qdf_mem_free(fils_join_rsp);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_process_fils_join_rsp() - Process join rsp for FILS connection
|
||||
* @mac_ctx: Global MAC Context
|
||||
* @profile: CSR Roam Profile
|
||||
* @session_id: Session ID
|
||||
* @roam_info: CSR Roam Info
|
||||
* @bss_desc: BSS description
|
||||
* @join_rsp: SME Join rsp
|
||||
*
|
||||
* Process SME join response for FILS connection
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void csr_process_fils_join_rsp(tpAniSirGlobal mac_ctx,
|
||||
tCsrRoamProfile *profile,
|
||||
uint32_t session_id,
|
||||
tCsrRoamInfo *roam_info,
|
||||
tSirBssDescription *bss_desc,
|
||||
tSirSmeJoinRsp *join_rsp)
|
||||
{
|
||||
tSirMacAddr bcast_mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
QDF_STATUS status;
|
||||
|
||||
if (!join_rsp || !join_rsp->fils_join_rsp) {
|
||||
sme_err("Join rsp doesn't have FILS info");
|
||||
goto process_fils_join_rsp_fail;
|
||||
}
|
||||
|
||||
/* Copy FILS params */
|
||||
status = populate_fils_params_join_rsp(mac_ctx, roam_info, join_rsp);
|
||||
if (!QDF_IS_STATUS_SUCCESS(status)) {
|
||||
sme_err("Copy FILS params join rsp fails");
|
||||
goto process_fils_join_rsp_fail;
|
||||
}
|
||||
|
||||
status = csr_roam_issue_set_context_req(mac_ctx, session_id,
|
||||
profile->negotiatedMCEncryptionType,
|
||||
bss_desc, &bcast_mac, true, false,
|
||||
eSIR_RX_ONLY, 2,
|
||||
roam_info->fils_join_rsp->gtk_len,
|
||||
roam_info->fils_join_rsp->gtk, 0);
|
||||
if (!QDF_IS_STATUS_SUCCESS(status)) {
|
||||
sme_err("Set context for bcast fail");
|
||||
goto process_fils_join_rsp_fail;
|
||||
}
|
||||
|
||||
status = csr_roam_issue_set_context_req(mac_ctx, session_id,
|
||||
profile->negotiatedUCEncryptionType,
|
||||
bss_desc, &(bss_desc->bssId), true,
|
||||
true, eSIR_TX_RX, 0,
|
||||
roam_info->fils_join_rsp->tk_len,
|
||||
roam_info->fils_join_rsp->tk, 0);
|
||||
if (!QDF_IS_STATUS_SUCCESS(status)) {
|
||||
sme_err("Set context for unicast fail");
|
||||
goto process_fils_join_rsp_fail;
|
||||
}
|
||||
return;
|
||||
|
||||
process_fils_join_rsp_fail:
|
||||
csr_roam_substate_change(mac_ctx, eCSR_ROAM_SUBSTATE_NONE, session_id);
|
||||
}
|
||||
#else
|
||||
|
||||
static inline void csr_process_fils_join_rsp(tpAniSirGlobal mac_ctx,
|
||||
tCsrRoamProfile *profile,
|
||||
uint32_t session_id,
|
||||
tCsrRoamInfo *roam_info,
|
||||
tSirBssDescription *bss_desc,
|
||||
tSirSmeJoinRsp *join_rsp)
|
||||
{}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* csr_roam_process_join_res() - Process the Join results
|
||||
* @mac_ctx: Global MAC Context
|
||||
@ -7097,6 +7271,11 @@ static void csr_roam_process_join_res(tpAniSirGlobal mac_ctx,
|
||||
profile->negotiatedMCEncryptionType,
|
||||
bss_desc, &bcast_mac, false, false,
|
||||
eSIR_TX_RX, 0, 0, NULL, 0);
|
||||
} else if (CSR_IS_AUTH_TYPE_FILS(profile->negotiatedAuthType)
|
||||
&& join_rsp->is_fils_connection) {
|
||||
roam_info.is_fils_connection = true;
|
||||
csr_process_fils_join_rsp(mac_ctx, profile, session_id,
|
||||
&roam_info, bss_desc, join_rsp);
|
||||
} else {
|
||||
/* Need to wait for supplicant authtication */
|
||||
roam_info.fAuthRequired = true;
|
||||
@ -7468,6 +7647,7 @@ static bool csr_roam_process_results(tpAniSirGlobal mac_ctx, tSmeCmd *cmd,
|
||||
break;
|
||||
case eCsrStopBssSuccess:
|
||||
if (CSR_IS_NDI(profile)) {
|
||||
qdf_mem_set(&roam_info, sizeof(roam_info), 0);
|
||||
csr_roam_update_ndp_return_params(mac_ctx, res,
|
||||
&roam_status, &roam_result, &roam_info);
|
||||
csr_roam_call_callback(mac_ctx, session_id, &roam_info,
|
||||
@ -7477,6 +7657,7 @@ static bool csr_roam_process_results(tpAniSirGlobal mac_ctx, tSmeCmd *cmd,
|
||||
break;
|
||||
case eCsrStopBssFailure:
|
||||
if (CSR_IS_NDI(profile)) {
|
||||
qdf_mem_set(&roam_info, sizeof(roam_info), 0);
|
||||
csr_roam_update_ndp_return_params(mac_ctx, res,
|
||||
&roam_status, &roam_result, &roam_info);
|
||||
csr_roam_call_callback(mac_ctx, session_id, &roam_info,
|
||||
@ -8873,6 +9054,11 @@ static void csr_roam_join_rsp_processor(tpAniSirGlobal pMac,
|
||||
if (pEntry)
|
||||
pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
|
||||
|
||||
sme_debug("is_fils_connection %d", pSmeJoinRsp->is_fils_connection);
|
||||
/* Copy Sequence Number last used for FILS assoc failure case */
|
||||
if (session_ptr->is_fils_connection)
|
||||
session_ptr->fils_seq_num = pSmeJoinRsp->fils_seq_num;
|
||||
|
||||
if (eSIR_SME_SUCCESS == pSmeJoinRsp->statusCode) {
|
||||
if (pCommand
|
||||
&& eCsrSmeIssuedAssocToSimilarAP ==
|
||||
|
@ -181,6 +181,12 @@ typedef struct {
|
||||
#define CSR_IS_ENC_TYPE_STATIC(encType) ((eCSR_ENCRYPT_TYPE_NONE == (encType)) || \
|
||||
(eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == (encType)) || \
|
||||
(eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == (encType)))
|
||||
|
||||
#define CSR_IS_AUTH_TYPE_FILS(auth_type) \
|
||||
((eCSR_AUTH_TYPE_FILS_SHA256 == auth_type) || \
|
||||
(eCSR_AUTH_TYPE_FILS_SHA384 == auth_type) || \
|
||||
(eCSR_AUTH_TYPE_FT_FILS_SHA256 == auth_type) || \
|
||||
(eCSR_AUTH_TYPE_FT_FILS_SHA384 == auth_type))
|
||||
#define CSR_IS_WAIT_FOR_KEY(pMac, sessionId) \
|
||||
(CSR_IS_ROAM_JOINED(pMac, sessionId) && \
|
||||
CSR_IS_ROAM_SUBSTATE_WAITFORKEY(pMac, sessionId))
|
||||
|
Loading…
Reference in New Issue
Block a user